diff --git a/AGENTS.md b/AGENTS.md index e2a83e6..8d3453d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -264,6 +264,7 @@ Build process injects: - `import.meta.VERSION` - Package version from package.json - `import.meta.ownerSizeTotalWorker` - 'Owner size total' worker path - `import.meta.creditsWorker` - 'Credits' worker path +- `import.meta.initDbOnce` - Allow the DB to only be set up once ### 6. No Network After Key Loading diff --git a/build/main.js b/build/main.js index a5d65b0..64fb1b0 100644 --- a/build/main.js +++ b/build/main.js @@ -5,14 +5,7 @@ var __require = __deno_internal_createRequire(import.meta.url); // build/main.js-tmp import { Buffer as Buffer22 } from "node:buffer"; -import { Buffer as Buffer3 } from "node:buffer"; -import { Buffer as Buffer4 } from "node:buffer"; import { Buffer as Buffer5 } from "node:buffer"; -import { Buffer as Buffer6 } from "node:buffer"; -import { Buffer as Buffer7 } from "node:buffer"; -import { Buffer as Buffer8 } from "node:buffer"; -import { Buffer as Buffer9 } from "node:buffer"; -import { randomBytes as randomBytes2, timingSafeEqual } from "node:crypto"; import { mkdir, readdir, readFile, rm, unlink, writeFile } from "node:fs/promises"; import { basename as basename9, dirname as dirname9, join as join9, normalize as normalize8, resolve as resolve9 } from "node:path"; import { Buffer as Buffer10 } from "node:buffer"; @@ -850,9 +843,9 @@ var EOL = globalThis.Deno?.build.os === "windows" ? CRLF : LF; var { Deno: Deno2 } = globalThis; var noColor = typeof Deno2?.noColor === "boolean" ? Deno2.noColor : false; var enabled = !noColor; -function code(open, close) { +function code(open2, close) { return { - open: `\x1B[${open.join(";")}m`, + open: `\x1B[${open2.join(";")}m`, close: `\x1B[${close}m`, regexp: new RegExp(`\\x1b\\[${close}m`, "g") }; @@ -3078,24 +3071,6 @@ var wrapTransaction = (fn, db2, { begin, commit, rollback, savepoint, release, r import { Buffer as Buffer11 } from "node:buffer"; import { mkdir as mkdir2 } from "node:fs/promises"; import { basename as basename22, dirname as dirname22, join as join22, resolve as resolve22 } from "node:path"; -import process2 from "node:process"; -import { Readable } from "node:stream"; -import path5 from "node:path"; -import process5 from "node:process"; -import process6 from "node:process"; -import { Buffer as Buffer13 } from "node:buffer"; -import { basename as basename52 } from "node:path"; -import process7 from "node:process"; -import { Buffer as Buffer14 } from "node:buffer"; -import process8 from "node:process"; -import { Buffer as Buffer15 } from "node:buffer"; -import { isIP } from "node:net"; -import path6 from "node:path"; -import process9 from "node:process"; -import { join as join72 } from "node:path"; -import process10 from "node:process"; -import { pathToFileURL } from "node:url"; -import process11 from "node:process"; import process13 from "node:process"; // deno:https://jsr.io/@std/path/1.1.1/_common/assert_path.ts @@ -4023,6 +3998,15 @@ function resolve8(...pathSegments) { // build/main.js-tmp import { Buffer as Buffer12 } from "node:buffer"; +import process2 from "node:process"; +import { Readable } from "node:stream"; +import { Buffer as Buffer6 } from "node:buffer"; +import { Buffer as Buffer4 } from "node:buffer"; +import { Buffer as Buffer3 } from "node:buffer"; +import { Buffer as Buffer7 } from "node:buffer"; +import { Buffer as Buffer9 } from "node:buffer"; +import { randomBytes as randomBytes2, timingSafeEqual } from "node:crypto"; +import { Buffer as Buffer8 } from "node:buffer"; import { join as join32 } from "node:path"; // deno:https://jsr.io/@std/encoding/1.0.10/_common64.ts @@ -4115,8 +4099,31 @@ import { copyFile, mkdir as mkdir3, readFile as readFile3, writeFile as writeFil import { basename as basename42, dirname as dirname42, join as join62 } from "node:path"; import process4 from "node:process"; import process12 from "node:process"; +import process10 from "node:process"; +import { createServer as createServerHTTP } from "node:http"; +import { Http2ServerRequest as Http2ServerRequest2, constants as h2constants } from "node:http2"; +import { Http2ServerRequest } from "node:http2"; +import { Readable as Readable2 } from "node:stream"; +import crypto2 from "node:crypto"; +import { Buffer as Buffer13 } from "node:buffer"; +import { basename as basename52 } from "node:path"; +import process5 from "node:process"; +import { join as join72 } from "node:path"; +import process9 from "node:process"; +import { Buffer as Buffer14 } from "node:buffer"; +import { isIP } from "node:net"; +import path5 from "node:path"; +import process7 from "node:process"; +import { Readable as Readable3 } from "node:stream"; +import process6 from "node:process"; +import process8 from "node:process"; +import { Buffer as Buffer15 } from "node:buffer"; +import { pathToFileURL } from "node:url"; +import path6 from "node:path"; +import process11 from "node:process"; +import { join as join82 } from "node:path"; import { notStrictEqual, strictEqual } from "node:assert"; -import { dirname as dirname52, resolve as resolve42 } from "node:path"; +import { dirname as dirname62, resolve as resolve42 } from "node:path"; import { readdirSync, statSync } from "node:fs"; import { format as format42, inspect } from "node:util"; import { readFileSync as readFileSync3 } from "node:fs"; @@ -4124,7 +4131,7 @@ import { fileURLToPath } from "node:url"; import { format as format22 } from "node:util"; import { readFileSync } from "node:fs"; import { normalize as normalize22, resolve as resolve52 } from "node:path"; -import { basename as basename62, dirname as dirname62, extname as extname8, relative as relative22, resolve as resolve72 } from "node:path"; +import { basename as basename62, dirname as dirname72, extname as extname8, relative as relative22, resolve as resolve72 } from "node:path"; import { readFileSync as readFileSync2, statSync as statSync2, writeFile as writeFile3 } from "node:fs"; import { format as format32 } from "node:util"; import { resolve as resolve62 } from "node:path"; @@ -4171,143 +4178,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); -function sbp(selector, ...data) { - const domain = domainFromSelector(selector); - const starSelector = `${domain}/*`; - const selExists = !!selectors[selector]; - let sel = selector; - if (!selExists) { - if (selectors[starSelector]) { - sel = starSelector; - } else { - throw new Error(`SBP: selector not registered: ${selector}`); - } - } - for (const filters of [selectorFilters[selector], domainFilters[domain], globalFilters]) { - if (filters) { - for (const filter of filters) { - if (filter(domain, selector, data) === false) - return; - } - } - } - if (!selExists) { - data.unshift(selector); - } - return selectors[sel].apply(domains[domain].state, data); -} -function domainFromSelector(selector) { - const domainLookup = DOMAIN_REGEX.exec(selector); - if (domainLookup === null) { - throw new Error(`SBP: selector missing domain: ${selector}`); - } - return domainLookup[0]; -} -var selectors; -var domains; -var globalFilters; -var domainFilters; -var selectorFilters; -var unsafeSelectors; -var DOMAIN_REGEX; -var SBP_BASE_SELECTORS; -var esm_default; -var init_esm = __esm({ - "node_modules/.deno/@sbp+sbp@2.4.1/node_modules/@sbp/sbp/dist/esm/index.js"() { - selectors = /* @__PURE__ */ Object.create(null); - domains = /* @__PURE__ */ Object.create(null); - globalFilters = []; - domainFilters = /* @__PURE__ */ Object.create(null); - selectorFilters = /* @__PURE__ */ Object.create(null); - unsafeSelectors = /* @__PURE__ */ Object.create(null); - DOMAIN_REGEX = /^[^/]+/; - SBP_BASE_SELECTORS = { - "sbp/selectors/register": (sels) => { - const registered = []; - for (const selector in sels) { - const domainName = domainFromSelector(selector); - const domain = domainName in domains ? domains[domainName] : domains[domainName] = { state: /* @__PURE__ */ Object.create(null), locked: false }; - if (domain.locked) { - (console.warn || console.log)(`[SBP WARN]: not registering selector on locked domain: '${selector}'`); - } else if (selectors[selector]) { - (console.warn || console.log)(`[SBP WARN]: not registering already registered selector: '${selector}'`); - } else if (typeof sels[selector] === "function") { - if (unsafeSelectors[selector]) { - (console.warn || console.log)(`[SBP WARN]: registering unsafe selector: '${selector}' (remember to lock after overwriting)`); - } - const fn = selectors[selector] = sels[selector]; - registered.push(selector); - if (selector === `${domainName}/_init`) { - fn.call(domain.state); - } - } - } - return registered; - }, - "sbp/selectors/unregister": (sels) => { - var _a2; - for (const selector of sels) { - if (!unsafeSelectors[selector]) { - throw new Error(`SBP: can't unregister locked selector: ${selector}`); - } - if ((_a2 = domains[domainFromSelector(selector)]) === null || _a2 === void 0 ? void 0 : _a2.locked) { - throw new Error(`SBP: can't unregister selector on a locked domain: '${selector}'`); - } - delete selectors[selector]; - } - }, - "sbp/selectors/overwrite": (sels) => { - sbp("sbp/selectors/unregister", Object.keys(sels)); - return sbp("sbp/selectors/register", sels); - }, - "sbp/selectors/unsafe": (sels) => { - for (const selector of sels) { - if (selectors[selector]) { - throw new Error("unsafe must be called before registering selector"); - } - unsafeSelectors[selector] = true; - } - }, - "sbp/selectors/lock": (sels) => { - for (const selector of sels) { - delete unsafeSelectors[selector]; - } - }, - "sbp/selectors/fn": (sel) => { - return selectors[sel]; - }, - "sbp/filters/global/add": (filter) => { - globalFilters.push(filter); - }, - "sbp/filters/domain/add": (domain, filter) => { - if (!domainFilters[domain]) - domainFilters[domain] = []; - domainFilters[domain].push(filter); - }, - "sbp/filters/selector/add": (selector, filter) => { - if (!selectorFilters[selector]) - selectorFilters[selector] = []; - selectorFilters[selector].push(filter); - }, - "sbp/domains/lock": (domainNames) => { - if (!domainNames) { - for (const name in domains) { - domains[name].locked = true; - } - } else { - for (const name of domainNames) { - if (!domains[name]) { - throw new Error(`SBP: cannot lock non-existent domain: ${name}`); - } - domains[name].locked = true; - } - } - } - }; - SBP_BASE_SELECTORS["sbp/selectors/register"](SBP_BASE_SELECTORS); - esm_default = sbp; - } -}); var require_async = __commonJS({ "node_modules/.deno/async@3.2.6/node_modules/async/dist/async.js"(exports2, module14) { (function(global2, factory) { @@ -4829,12 +4699,12 @@ var require_async = __commonJS({ } function parseParams(func) { const src2 = stripComments(func.toString()); - let match = src2.match(FN_ARGS); - if (!match) { - match = src2.match(ARROW_FN_ARGS); + let match2 = src2.match(FN_ARGS); + if (!match2) { + match2 = src2.match(ARROW_FN_ARGS); } - if (!match) throw new Error("could not parse args in autoInject\nSource:\n" + src2); - let [, args] = match; + if (!match2) throw new Error("could not parse args in autoInject\nSource:\n" + src2); + let [, args] = match2; return args.replace(/\s/g, "").split(FN_ARG_SPLIT).map((arg) => arg.replace(FN_ARG, "").trim()); } function autoInject(tasks, callback) { @@ -5219,7 +5089,7 @@ var require_async = __commonJS({ return cb[PROMISE_SYMBOL]; }; } - function compose(...args) { + function compose2(...args) { return seq(...args.reverse()); } function mapLimit(coll, limit, iteratee, callback) { @@ -5961,7 +5831,7 @@ var require_async = __commonJS({ autoInject, cargo: cargo$1, cargoQueue: cargo, - compose, + compose: compose2, concat: concat$1, concatLimit: concatLimit$1, concatSeries: concatSeries$1, @@ -6072,7 +5942,7 @@ var require_async = __commonJS({ exports3.autoInject = autoInject; exports3.cargo = cargo$1; exports3.cargoQueue = cargo; - exports3.compose = compose; + exports3.compose = compose2; exports3.concat = concat$1; exports3.concatLimit = concatLimit$1; exports3.concatSeries = concatSeries$1; @@ -6219,11 +6089,11 @@ var require_ini = __commonJS({ for (const line of lines) { if (!line || line.match(/^\s*[;#]/)) continue; - const match = line.match(re); - if (!match) + const match2 = line.match(re); + if (!match2) continue; - if (match[1] !== void 0) { - section = unsafe(match[1]); + if (match2[1] !== void 0) { + section = unsafe(match2[1]); if (section === "__proto__") { p = /* @__PURE__ */ Object.create(null); continue; @@ -6231,12 +6101,12 @@ var require_ini = __commonJS({ p = out[section] = out[section] || /* @__PURE__ */ Object.create(null); continue; } - const keyRaw = unsafe(match[2]); + const keyRaw = unsafe(match2[2]); const isArray = keyRaw.length > 2 && keyRaw.slice(-2) === "[]"; const key = isArray ? keyRaw.slice(0, -2) : keyRaw; if (key === "__proto__") continue; - const valueRaw = match[3] ? unsafe(match[4]) : true; + const valueRaw = match2[3] ? unsafe(match2[4]) : true; const value = valueRaw === "true" || valueRaw === "false" || valueRaw === "null" ? JSON.parse(valueRaw) : valueRaw; if (isArray) { if (!hasOwnProperty.call(p, key)) @@ -6446,7 +6316,7 @@ var require_memory = __commonJS({ }); var require_common = __commonJS({ "node_modules/.deno/nconf@0.13.0/node_modules/nconf/lib/nconf/common.js"(exports2) { - var fs = __require2("fs"); + var fs = __require2("node:fs"); var async = require_async(); var formats = require_formats(); var Memory = require_memory().Memory; @@ -6927,9 +6797,9 @@ var require_package = __commonJS({ var require_build = __commonJS({ "node_modules/.deno/y18n@5.0.8/node_modules/y18n/build/index.cjs"(exports2, module14) { "use strict"; - var fs = __require2("fs"); - var util = __require2("util"); - var path8 = __require2("path"); + var fs = __require2("node:fs"); + var util = __require2("node:util"); + var path8 = __require2("node:path"); var shim4; var Y18N2 = class { constructor(opts) { @@ -7113,9 +6983,9 @@ var require_build = __commonJS({ var require_build2 = __commonJS({ "node_modules/.deno/yargs-parser@20.2.9/node_modules/yargs-parser/build/index.cjs"(exports2, module14) { "use strict"; - var util = __require2("util"); - var fs = __require2("fs"); - var path8 = __require2("path"); + var util = __require2("node:util"); + var fs = __require2("node:fs"); + var path8 = __require2("node:path"); function camelCase2(str) { const isCamelCase = str !== str.toLowerCase() && str !== str.toUpperCase(); if (!isCamelCase) { @@ -7900,8 +7770,8 @@ var require_build2 = __commonJS({ function hasFlagsMatching(arg, ...patterns) { const toCheck = [].concat(...patterns); return toCheck.some(function(pattern) { - const match = arg.match(pattern); - return match && hasAnyFlag(match[1]); + const match2 = arg.match(pattern); + return match2 && hasAnyFlag(match2[1]); }); } function hasAllShortFlags(arg) { @@ -8442,9 +8312,9 @@ var require_conversions = __commonJS({ const g2 = rgb[1]; let b = rgb[2]; const h2 = convert.rgb.hsl(rgb)[0]; - const w4 = 1 / 255 * Math.min(r, Math.min(g2, b)); + const w3 = 1 / 255 * Math.min(r, Math.min(g2, b)); b = 1 - 1 / 255 * Math.max(r, Math.max(g2, b)); - return [h2, w4 * 100, b * 100]; + return [h2, w3 * 100, b * 100]; }; convert.rgb.cmyk = function(rgb) { const r = rgb[0] / 255; @@ -8806,12 +8676,12 @@ var require_conversions = __commonJS({ return "000000".substring(string3.length) + string3; }; convert.hex.rgb = function(args) { - const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); - if (!match) { + const match2 = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); + if (!match2) { return [0, 0, 0]; } - let colorString = match[0]; - if (match[0].length === 3) { + let colorString = match2[0]; + if (match2[0].length === 3) { colorString = colorString.split("").map((char) => { return char + char; }).join(""); @@ -8879,7 +8749,7 @@ var require_conversions = __commonJS({ const pure = [0, 0, 0]; const hi = h2 % 1 * 6; const v2 = hi % 1; - const w4 = 1 - v2; + const w3 = 1 - v2; let mg = 0; switch (Math.floor(hi)) { case 0: @@ -8888,7 +8758,7 @@ var require_conversions = __commonJS({ pure[2] = 0; break; case 1: - pure[0] = w4; + pure[0] = w3; pure[1] = 1; pure[2] = 0; break; @@ -8899,7 +8769,7 @@ var require_conversions = __commonJS({ break; case 3: pure[0] = 0; - pure[1] = w4; + pure[1] = w3; pure[2] = 1; break; case 4: @@ -8910,7 +8780,7 @@ var require_conversions = __commonJS({ default: pure[0] = 1; pure[1] = 0; - pure[2] = w4; + pure[2] = w3; } mg = (1 - c) * g2; return [ @@ -8948,10 +8818,10 @@ var require_conversions = __commonJS({ return [hcg[0], (v2 - c) * 100, (1 - v2) * 100]; }; convert.hwb.hcg = function(hwb) { - const w4 = hwb[1] / 100; + const w3 = hwb[1] / 100; const b = hwb[2] / 100; const v2 = 1 - b; - const c = v2 - w4; + const c = v2 - w3; let g2 = 0; if (c < 1) { g2 = (v2 - c) / (1 - c); @@ -9063,7 +8933,7 @@ var require_route = __commonJS({ var require_color_convert = __commonJS({ "node_modules/.deno/color-convert@2.0.1/node_modules/color-convert/index.js"(exports2, module14) { var conversions = require_conversions(); - var route2 = require_route(); + var route = require_route(); var convert = {}; var models = Object.keys(conversions); function wrapRaw(fn) { @@ -9108,7 +8978,7 @@ var require_color_convert = __commonJS({ convert[fromModel] = {}; Object.defineProperty(convert[fromModel], "channels", { value: conversions[fromModel].channels }); Object.defineProperty(convert[fromModel], "labels", { value: conversions[fromModel].labels }); - const routes = route2(fromModel); + const routes = route(fromModel); const routeModels = Object.keys(routes); routeModels.forEach((toModel) => { const fn = routes[toModel]; @@ -9537,8 +9407,8 @@ var require_build3 = __commonJS({ // if the full 'source' can render in // the target line, do so. renderInline(source, previousLine) { - const match = source.match(/^ */); - const leadingWhitespace = match ? match[0].length : 0; + const match2 = source.match(/^ */); + const leadingWhitespace = match2 ? match2[0].length : 0; const target = previousLine.text; const targetTextWidth = mixin3.stringWidth(target.trimRight()); if (!previousLine.span) { @@ -9615,11 +9485,11 @@ var require_build3 = __commonJS({ return void 0; }); const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0; - return widths.map((w4, i2) => { - if (w4 === void 0) { + return widths.map((w3, i2) => { + if (w3 === void 0) { return Math.max(unsetWidth, _minWidth2(row[i2])); } - return w4; + return w3; }); } }; @@ -9688,18 +9558,18 @@ var require_build3 = __commonJS({ }); var require_sync = __commonJS({ "node_modules/.deno/escalade@3.2.0/node_modules/escalade/sync/index.js"(exports2, module14) { - var { dirname: dirname72, resolve: resolve82 } = __require2("path"); - var { readdirSync: readdirSync2, statSync: statSync3 } = __require2("fs"); + var { dirname: dirname82, resolve: resolve82 } = __require2("node:path"); + var { readdirSync: readdirSync2, statSync: statSync3 } = __require2("node:fs"); module14.exports = function(start, callback) { let dir = resolve82(".", start); let tmp, stats = statSync3(dir); if (!stats.isDirectory()) { - dir = dirname72(dir); + dir = dirname82(dir); } while (true) { tmp = callback(dir, readdirSync2(dir)); if (tmp) return resolve82(dir, tmp); - dir = dirname72(tmp = dir); + dir = dirname82(tmp = dir); if (tmp === dir) break; } }; @@ -9730,10 +9600,10 @@ var require_get_caller_file = __commonJS({ var require_require_directory = __commonJS({ "node_modules/.deno/require-directory@2.1.1/node_modules/require-directory/index.js"(exports2, module14) { "use strict"; - var fs = __require2("fs"); - var join92 = __require2("path").join; - var resolve82 = __require2("path").resolve; - var dirname72 = __require2("path").dirname; + var fs = __require2("node:fs"); + var join10 = __require2("node:path").join; + var resolve82 = __require2("node:path").resolve; + var dirname82 = __require2("node:path").dirname; var defaultOptions4 = { extensions: ["js", "json", "coffee"], recurse: true, @@ -9766,9 +9636,9 @@ var require_require_directory = __commonJS({ options2[prop] = defaultOptions4[prop]; } } - path8 = !path8 ? dirname72(m3.filename) : resolve82(dirname72(m3.filename), path8); + path8 = !path8 ? dirname82(m3.filename) : resolve82(dirname82(m3.filename), path8); fs.readdirSync(path8).forEach(function(filename) { - var joined = join92(path8, filename), files, key, obj; + var joined = join10(path8, filename), files, key, obj; if (fs.statSync(joined).isDirectory() && options2.recurse) { files = requireDirectory(m3, joined, options2); if (Object.keys(files).length) { @@ -9791,7 +9661,7 @@ var require_require_directory = __commonJS({ var require_build4 = __commonJS({ "node_modules/.deno/yargs@16.2.0/node_modules/yargs/build/index.cjs"(exports2, module14) { "use strict"; - var assert2 = __require2("assert"); + var assert2 = __require2("node:assert"); var YError2 = class _YError2 extends Error { constructor(msg) { super(msg || "yargs error"); @@ -9937,7 +9807,7 @@ var require_build4 = __commonJS({ function argumentTypeError2(observedType, allowedTypes, position) { throw new YError2(`Invalid ${positionName2[position] || "manyith"} argument. Expected ${allowedTypes.join(" or ")} but received ${observedType}.`); } - function isPromise2(maybePromise) { + function isPromise3(maybePromise) { return !!maybePromise && !!maybePromise.then && typeof maybePromise.then === "function"; } function assertNotStrictEqual2(actual, expected, shim5, message) { @@ -9990,16 +9860,16 @@ var require_build4 = __commonJS({ if (middleware.applyBeforeValidation !== beforeValidation) { return acc; } - if (isPromise2(acc)) { + if (isPromise3(acc)) { return acc.then((initialObj) => Promise.all([ initialObj, middleware(initialObj, yargs) ])).then(([initialObj, middlewareObj]) => Object.assign(initialObj, middlewareObj)); } else { const result = middleware(acc, yargs); - if (beforeValidation && isPromise2(result)) + if (beforeValidation && isPromise3(result)) throw beforeValidationError; - return isPromise2(result) ? result.then((middlewareObj) => Object.assign(acc, middlewareObj)) : Object.assign(acc, result); + return isPromise3(result) ? result.then((middlewareObj) => Object.assign(acc, middlewareObj)) : Object.assign(acc, result); } }, argv); } @@ -10187,13 +10057,13 @@ var require_build4 = __commonJS({ yargs2._postProcess(innerArgv, populateDoubleDash); innerArgv = applyMiddleware2(innerArgv, yargs2, middlewares, false); let handlerResult; - if (isPromise2(innerArgv)) { + if (isPromise3(innerArgv)) { handlerResult = innerArgv.then((argv) => commandHandler.handler(argv)); } else { handlerResult = commandHandler.handler(innerArgv); } const handlerFinishCommand = yargs2.getHandlerFinishCommand(); - if (isPromise2(handlerResult)) { + if (isPromise3(handlerResult)) { yargs2.getUsageInstance().cacheHelpMessage(); handlerResult.then((value) => { if (handlerFinishCommand) { @@ -10950,7 +10820,7 @@ compdef _{{app_name}}_yargs_completions {{app_name}} assertNotStrictEqual2(completionFunction, null, shim5); if (isSyncCompletionFunction2(completionFunction)) { const result = completionFunction(current, argv2); - if (isPromise2(result)) { + if (isPromise3(result)) { return result.then((list) => { shim5.process.nextTick(() => { done(list); @@ -10969,7 +10839,7 @@ compdef _{{app_name}}_yargs_completions {{app_name}} } } if (completionFunction) { - return isPromise2(argv) ? argv.then(runCompletionFunction) : runCompletionFunction(argv); + return isPromise3(argv) ? argv.then(runCompletionFunction) : runCompletionFunction(argv); } const handlers = command3.getCommandHandlers(); for (let i2 = 0, ii = args.length; i2 < ii; ++i2) { @@ -11856,7 +11726,7 @@ ${customMsgs.join("\n")}` : ""; } let parseFn = null; let parseContext = null; - self2.parse = function parse52(args, shortCircuit, _parseFn) { + self2.parse = function parse62(args, shortCircuit, _parseFn) { argsert2("[string|array] [function|boolean|object] [function]", [args, shortCircuit, _parseFn], arguments.length); freeze(); if (typeof args === "undefined") { @@ -12362,7 +12232,7 @@ ${customMsgs.join("\n")}` : ""; return self2._postProcess(argv, populateDoubleDash, _calledFromCommand); }; self2._postProcess = function(argv, populateDoubleDash, calledFromCommand = false) { - if (isPromise2(argv)) + if (isPromise3(argv)) return argv; if (calledFromCommand) return argv; @@ -12429,9 +12299,9 @@ ${customMsgs.join("\n")}` : ""; } var _a2; var _b; - var { readFileSync: readFileSync4 } = __require2("fs"); - var { inspect: inspect2 } = __require2("util"); - var { resolve: resolve82 } = __require2("path"); + var { readFileSync: readFileSync4 } = __require2("node:fs"); + var { inspect: inspect2 } = __require2("node:util"); + var { resolve: resolve82 } = __require2("node:path"); var y18n3 = require_build(); var Parser2 = require_build2(); var cjsPlatformShim = { @@ -12449,7 +12319,7 @@ ${customMsgs.join("\n")}` : ""; inspect: inspect2, mainFilename: (_b = (_a2 = __require2 === null || __require2 === void 0 ? void 0 : __require2.main) === null || _a2 === void 0 ? void 0 : _a2.filename) !== null && _b !== void 0 ? _b : process.cwd(), Parser: Parser2, - path: __require2("path"), + path: __require2("node:path"), process: { argv: () => process.argv, cwd: process.cwd, @@ -12484,7 +12354,7 @@ ${customMsgs.join("\n")}` : ""; Yargs: Yargs$1, argsert: argsert2, globalMiddlewareFactory: globalMiddlewareFactory2, - isPromise: isPromise2, + isPromise: isPromise3, objFilter: objFilter2, parseCommand: parseCommand2, Parser: Parser$1, @@ -12526,7 +12396,7 @@ var require_yargs = __commonJS({ }); var require_argv = __commonJS({ "node_modules/.deno/nconf@0.13.0/node_modules/nconf/lib/nconf/stores/argv.js"(exports2) { - var util = __require2("util"); + var util = __require2("node:util"); var common4 = require_common(); var Memory = require_memory().Memory; var Argv = exports2.Argv = function(options2, usage2) { @@ -12599,7 +12469,7 @@ var require_argv = __commonJS({ }); var require_env = __commonJS({ "node_modules/.deno/nconf@0.13.0/node_modules/nconf/lib/nconf/stores/env.js"(exports2) { - var util = __require2("util"); + var util = __require2("node:util"); var common4 = require_common(); var Memory = require_memory().Memory; var Env = exports2.Env = function(options2) { @@ -12675,7 +12545,7 @@ var require_env = __commonJS({ var require_secure_keys = __commonJS({ "node_modules/.deno/secure-keys@1.0.0/node_modules/secure-keys/index.js"(exports2, module14) { "use strict"; - var crypto2 = __require2("crypto"); + var crypto3 = __require2("node:crypto"); var json = { stringify: function(obj, replacer, spacing) { return JSON.stringify(obj, replacer || null, spacing || 2); @@ -12719,16 +12589,16 @@ var require_secure_keys = __commonJS({ }; function cipherConvert(contents, opts) { var encs = opts.encs; - var cipher = crypto2.createCipher(opts.alg, opts.secret); + var cipher = crypto3.createCipher(opts.alg, opts.secret); return cipher.update(contents, encs.input, encs.output) + cipher.final(encs.output); } } }); var require_file = __commonJS({ "node_modules/.deno/nconf@0.13.0/node_modules/nconf/lib/nconf/stores/file.js"(exports2) { - var fs = __require2("fs"); - var path8 = __require2("path"); - var util = __require2("util"); + var fs = __require2("node:fs"); + var path8 = __require2("node:path"); + var util = __require2("node:util"); var Secure = require_secure_keys(); var formats = require_formats(); var Memory = require_memory().Memory; @@ -12882,7 +12752,7 @@ var require_file = __commonJS({ }); var require_literal = __commonJS({ "node_modules/.deno/nconf@0.13.0/node_modules/nconf/lib/nconf/stores/literal.js"(exports2) { - var util = __require2("util"); + var util = __require2("node:util"); var Memory = require_memory().Memory; var Literal = exports2.Literal = function Literal2(options2) { Memory.call(this, options2); @@ -16008,9 +15878,64 @@ function _refine(Class2, fn, _params) { }); return schema; } +function _stringbool(Classes, _params) { + const params = normalizeParams(_params); + let truthyArray = params.truthy ?? ["true", "1", "yes", "on", "y", "enabled"]; + let falsyArray = params.falsy ?? ["false", "0", "no", "off", "n", "disabled"]; + if (params.case !== "sensitive") { + truthyArray = truthyArray.map((v2) => typeof v2 === "string" ? v2.toLowerCase() : v2); + falsyArray = falsyArray.map((v2) => typeof v2 === "string" ? v2.toLowerCase() : v2); + } + const truthySet = new Set(truthyArray); + const falsySet = new Set(falsyArray); + const _Pipe = Classes.Pipe ?? $ZodPipe; + const _Boolean = Classes.Boolean ?? $ZodBoolean; + const _String = Classes.String ?? $ZodString; + const _Transform = Classes.Transform ?? $ZodTransform; + const tx = new _Transform({ + type: "transform", + transform: (input, payload) => { + let data = input; + if (params.case !== "sensitive") + data = data.toLowerCase(); + if (truthySet.has(data)) { + return true; + } else if (falsySet.has(data)) { + return false; + } else { + payload.issues.push({ + code: "invalid_value", + expected: "stringbool", + values: [...truthySet, ...falsySet], + input: payload.value, + inst: tx + }); + return {}; + } + }, + error: params.error + }); + const innerPipe = new _Pipe({ + type: "pipe", + in: new _String({ type: "string", error: params.error }), + out: tx, + error: params.error + }); + const outerPipe = new _Pipe({ + type: "pipe", + in: innerPipe, + out: new _Boolean({ + type: "boolean", + error: params.error + }), + error: params.error + }); + return outerPipe; +} var init_api = __esm({ "node_modules/.deno/zod@4.0.5/node_modules/zod/v4/core/api.js"() { init_checks(); + init_schemas(); init_util(); } }); @@ -16358,6 +16283,7 @@ var ZodCatch; var ZodPipe; var ZodReadonly; var ZodCustom; +var stringbool; var init_schemas2 = __esm({ "node_modules/.deno/zod@4.0.5/node_modules/zod/v4/classic/schemas.js"() { init_core2(); @@ -16761,6 +16687,12 @@ var init_schemas2 = __esm({ $ZodCustom.init(inst, def); ZodType.init(inst, def); }); + stringbool = (...args) => _stringbool({ + Pipe: ZodPipe, + Boolean: ZodBoolean, + String: ZodString, + Transform: ZodTransform + }, ...args); } }); var ZodFirstPartyTypeKind; @@ -17189,10 +17121,10 @@ var require_util = __commonJS({ } console.log(msg); } - function testSpeed(hashFn, N11, M2) { + function testSpeed(hashFn, N10, M2) { let startMs = (/* @__PURE__ */ new Date()).getTime(); - const input = new Uint8Array(N11); - for (let i2 = 0; i2 < N11; i2++) { + const input = new Uint8Array(N10); + for (let i2 = 0; i2 < N10; i2++) { input[i2] = i2 % 256; } const genMs = (/* @__PURE__ */ new Date()).getTime(); @@ -17205,7 +17137,7 @@ var require_util = __commonJS({ startMs = hashMs; console.log("Hashed in " + ms + "ms: " + hashHex.substring(0, 20) + "..."); console.log( - Math.round(N11 / (1 << 20) / (ms / 1e3) * 100) / 100 + " MB PER SECOND" + Math.round(N10 / (1 << 20) / (ms / 1e3) * 100) / 100 + " MB PER SECOND" ); } } @@ -19122,6 +19054,143 @@ var init_functions = __esm({ }; } }); +function sbp(selector, ...data) { + const domain = domainFromSelector(selector); + const starSelector = `${domain}/*`; + const selExists = !!selectors[selector]; + let sel = selector; + if (!selExists) { + if (selectors[starSelector]) { + sel = starSelector; + } else { + throw new Error(`SBP: selector not registered: ${selector}`); + } + } + for (const filters of [selectorFilters[selector], domainFilters[domain], globalFilters]) { + if (filters) { + for (const filter of filters) { + if (filter(domain, selector, data) === false) + return; + } + } + } + if (!selExists) { + data.unshift(selector); + } + return selectors[sel].apply(domains[domain].state, data); +} +function domainFromSelector(selector) { + const domainLookup = DOMAIN_REGEX.exec(selector); + if (domainLookup === null) { + throw new Error(`SBP: selector missing domain: ${selector}`); + } + return domainLookup[0]; +} +var selectors; +var domains; +var globalFilters; +var domainFilters; +var selectorFilters; +var unsafeSelectors; +var DOMAIN_REGEX; +var SBP_BASE_SELECTORS; +var esm_default; +var init_esm = __esm({ + "node_modules/.deno/@sbp+sbp@2.4.1/node_modules/@sbp/sbp/dist/esm/index.js"() { + selectors = /* @__PURE__ */ Object.create(null); + domains = /* @__PURE__ */ Object.create(null); + globalFilters = []; + domainFilters = /* @__PURE__ */ Object.create(null); + selectorFilters = /* @__PURE__ */ Object.create(null); + unsafeSelectors = /* @__PURE__ */ Object.create(null); + DOMAIN_REGEX = /^[^/]+/; + SBP_BASE_SELECTORS = { + "sbp/selectors/register": (sels) => { + const registered = []; + for (const selector in sels) { + const domainName = domainFromSelector(selector); + const domain = domainName in domains ? domains[domainName] : domains[domainName] = { state: /* @__PURE__ */ Object.create(null), locked: false }; + if (domain.locked) { + (console.warn || console.log)(`[SBP WARN]: not registering selector on locked domain: '${selector}'`); + } else if (selectors[selector]) { + (console.warn || console.log)(`[SBP WARN]: not registering already registered selector: '${selector}'`); + } else if (typeof sels[selector] === "function") { + if (unsafeSelectors[selector]) { + (console.warn || console.log)(`[SBP WARN]: registering unsafe selector: '${selector}' (remember to lock after overwriting)`); + } + const fn = selectors[selector] = sels[selector]; + registered.push(selector); + if (selector === `${domainName}/_init`) { + fn.call(domain.state); + } + } + } + return registered; + }, + "sbp/selectors/unregister": (sels) => { + var _a2; + for (const selector of sels) { + if (!unsafeSelectors[selector]) { + throw new Error(`SBP: can't unregister locked selector: ${selector}`); + } + if ((_a2 = domains[domainFromSelector(selector)]) === null || _a2 === void 0 ? void 0 : _a2.locked) { + throw new Error(`SBP: can't unregister selector on a locked domain: '${selector}'`); + } + delete selectors[selector]; + } + }, + "sbp/selectors/overwrite": (sels) => { + sbp("sbp/selectors/unregister", Object.keys(sels)); + return sbp("sbp/selectors/register", sels); + }, + "sbp/selectors/unsafe": (sels) => { + for (const selector of sels) { + if (selectors[selector]) { + throw new Error("unsafe must be called before registering selector"); + } + unsafeSelectors[selector] = true; + } + }, + "sbp/selectors/lock": (sels) => { + for (const selector of sels) { + delete unsafeSelectors[selector]; + } + }, + "sbp/selectors/fn": (sel) => { + return selectors[sel]; + }, + "sbp/filters/global/add": (filter) => { + globalFilters.push(filter); + }, + "sbp/filters/domain/add": (domain, filter) => { + if (!domainFilters[domain]) + domainFilters[domain] = []; + domainFilters[domain].push(filter); + }, + "sbp/filters/selector/add": (selector, filter) => { + if (!selectorFilters[selector]) + selectorFilters[selector] = []; + selectorFilters[selector].push(filter); + }, + "sbp/domains/lock": (domainNames) => { + if (!domainNames) { + for (const name in domains) { + domains[name].locked = true; + } + } else { + for (const name of domainNames) { + if (!domains[name]) { + throw new Error(`SBP: cannot lock non-existent domain: ${name}`); + } + domains[name].locked = true; + } + } + } + }; + SBP_BASE_SELECTORS["sbp/selectors/register"](SBP_BASE_SELECTORS); + esm_default = sbp; + } +}); var isEventQueueSbpEvent; var esm_default2; var init_esm2 = __esm({ @@ -19241,54 +19310,6 @@ var init_esm3 = __esm({ }); } }); -var listenKey; -var esm_default4; -var init_esm4 = __esm({ - "node_modules/.deno/@sbp+okturtles.events@1.0.1/node_modules/@sbp/okturtles.events/dist/esm/index.mjs"() { - init_esm(); - init_esm3(); - listenKey = (evt) => `events/${evt}/listeners`; - esm_default4 = esm_default("sbp/selectors/register", { - "okTurtles.events/_init": function() { - this.errorHandler = (event, e2) => { - console.error(`[okTurtles.events] Error at handler for ${event}`, e2); - }; - }, - "okTurtles.events/on": function(event, handler) { - esm_default("okTurtles.data/add", listenKey(event), handler); - return () => esm_default("okTurtles.events/off", event, handler); - }, - "okTurtles.events/once": function(event, handler) { - const cbWithOff = (...args) => { - handler(...args); - esm_default("okTurtles.events/off", event, cbWithOff); - }; - return esm_default("okTurtles.events/on", event, cbWithOff); - }, - "okTurtles.events/emit": function(event, ...data) { - var _a2; - for (const listener of esm_default("okTurtles.data/get", listenKey(event)) || []) { - try { - listener(...data); - } catch (e2) { - (_a2 = this.errorHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, event, e2); - } - } - }, - // almost identical to Vue.prototype.$off, except we require `event` argument - "okTurtles.events/off": function(event, handler) { - if (handler) { - esm_default("okTurtles.data/remove", listenKey(event), handler); - } else { - esm_default("okTurtles.data/delete", listenKey(event)); - } - }, - "okTurtles.events/setErrorHandler": function(errorHandler) { - this.errorHandler = errorHandler; - } - }); - } -}); function pick2(o2, props) { const x3 = /* @__PURE__ */ Object.create(null); for (const k of props) { @@ -19405,666 +19426,12 @@ function debounce(func, wait, immediate) { return debounced; } var has; -var init_esm5 = __esm({ +var init_esm4 = __esm({ "node_modules/.deno/turtledash@1.0.3/node_modules/turtledash/dist/esm/index.js"() { has = Function.prototype.call.bind(Object.prototype.hasOwnProperty); } }); -function runWithRetry(client, channelID, type, getPayload) { - let attemptNo = 0; - const { socket, options: options2 } = client; - const instance = {}; - client.pendingOperations.tSet(type, channelID, instance); - const send = () => { - if (client.socket !== socket || socket?.readyState !== WebSocket.OPEN) - return; - const currentInstance = client.pendingOperations.tGet(type, channelID); - if (currentInstance !== instance) - return; - if (attemptNo++ > options2.maxOpRetries) { - console.warn(`[pubsub] Giving up ${type} for channel`, channelID); - client.pendingOperations.tDelete(type, channelID); - return; - } - const payload = getPayload(); - socket.send(createRequest(type, payload)); - const minDelay = (attemptNo - 1) * options2.opRetryInterval; - const jitter = randomIntFromRange(0, options2.opRetryInterval); - const delay2 = Math.min(200, minDelay) + jitter; - setTimeout(send, delay2); - }; - send(); -} -function createClient(url2, options2 = {}) { - const client = { - customEventHandlers: options2.handlers || {}, - // The current number of connection attempts that failed. - // Reset to 0 upon successful connection. - // Used to compute how long to wait before the next reconnection attempt. - failedConnectionAttempts: 0, - isLocal: /\/\/(localhost|127\.0\.0\.1)([:?/]|$)/.test(url2), - // True if this client has never been connected yet. - isNew: true, - listeners: /* @__PURE__ */ Object.create(null), - messageHandlers: { ...defaultMessageHandlers, ...options2.messageHandlers }, - nextConnectionAttemptDelayID: void 0, - options: { ...defaultOptions, ...options2 }, - pendingOperations: new TieredMap(), - pingTimeoutID: void 0, - shouldReconnect: true, - // The underlying WebSocket object. - // A new one is necessary for every connection or reconnection attempt. - socket: null, - subscriptionSet: /* @__PURE__ */ new Set(), - kvFilter: /* @__PURE__ */ new Map(), - connectionTimeoutID: void 0, - url: url2.replace(/^http/, "ws"), - ...publicMethods - }; - for (const name of Object.keys(defaultClientEventHandlers)) { - client.listeners[name] = (event) => { - try { - defaultClientEventHandlers[name].call(client, event); - client.customEventHandlers[name]?.call(client, event); - } catch (error2) { - esm_default("okTurtles.events/emit", PUBSUB_ERROR, client, error2?.message); - } - }; - } - if (typeof self === "object" && self instanceof EventTarget) { - for (const name of globalEventNames) { - globalEventMap.set(name, client.listeners[name]); - } - } - if (!client.options.manual) { - client.connect(); - } - return client; -} -function createMessage(type, data, meta) { - const message = { ...meta, type, data }; - let string3; - const stringify2 = function() { - if (!string3) - string3 = JSON.stringify(this); - return string3; - }; - Object.defineProperties(message, { - [Symbol.toPrimitive]: { - value: stringify2 - } - }); - return message; -} -function createKvMessage(channelID, key, data) { - return JSON.stringify({ type: NOTIFICATION_TYPE.KV, channelID, key, data }); -} -function createPubMessage(channelID, data) { - return JSON.stringify({ type: NOTIFICATION_TYPE.PUB, channelID, data }); -} -function createRequest(type, data) { - return JSON.stringify(Object.assign({ type }, data)); -} -var NOTIFICATION_TYPE; -var REQUEST_TYPE; -var RESPONSE_TYPE; -var PUSH_SERVER_ACTION_TYPE; -var defaultOptions; -var PUBSUB_ERROR; -var PUBSUB_RECONNECTION_ATTEMPT; -var PUBSUB_RECONNECTION_FAILED; -var PUBSUB_RECONNECTION_SCHEDULED; -var PUBSUB_RECONNECTION_SUCCEEDED; -var PUBSUB_SUBSCRIPTION_SUCCEEDED; -var TieredMap; -var isKvFilterFresh; -var pubPayloadFactory; -var defaultClientEventHandlers; -var defaultMessageHandlers; -var globalEventNames; -var socketEventNames; -var globalEventMap; -var isDefinetelyOffline; -var messageParser; -var publicMethods; -var init_pubsub = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/pubsub/index.mjs"() { - init_esm4(); - init_esm(); - init_esm5(); - NOTIFICATION_TYPE = Object.freeze({ - ENTRY: "entry", - DELETION: "deletion", - KV: "kv", - KV_FILTER: "kv_filter", - PING: "ping", - PONG: "pong", - PUB: "pub", - SUB: "sub", - UNSUB: "unsub", - VERSION_INFO: "version_info" - }); - REQUEST_TYPE = Object.freeze({ - PUB: "pub", - SUB: "sub", - UNSUB: "unsub", - PUSH_ACTION: "push_action", - KV_FILTER: "kv_filter" - }); - RESPONSE_TYPE = Object.freeze({ - ERROR: "error", - OK: "ok" - }); - PUSH_SERVER_ACTION_TYPE = Object.freeze({ - SEND_PUBLIC_KEY: "send-public-key", - STORE_SUBSCRIPTION: "store-subscription", - DELETE_SUBSCRIPTION: "delete-subscription", - SEND_PUSH_NOTIFICATION: "send-push-notification" - }); - defaultOptions = { - logPingMessages: !process.env.CI, - pingTimeout: 45e3, - maxReconnectionDelay: 6e4, - maxRetries: 10, - minReconnectionDelay: 500, - reconnectOnDisconnection: true, - reconnectOnOnline: true, - // Defaults to false to avoid reconnection attempts in case the server doesn't - // respond because of a failed authentication. - reconnectOnTimeout: false, - reconnectionDelayGrowFactor: 2, - timeout: 6e4, - maxOpRetries: 4, - opRetryInterval: 2e3 - }; - PUBSUB_ERROR = "pubsub-error"; - PUBSUB_RECONNECTION_ATTEMPT = "pubsub-reconnection-attempt"; - PUBSUB_RECONNECTION_FAILED = "pubsub-reconnection-failed"; - PUBSUB_RECONNECTION_SCHEDULED = "pubsub-reconnection-scheduled"; - PUBSUB_RECONNECTION_SUCCEEDED = "pubsub-reconnection-succeeded"; - PUBSUB_SUBSCRIPTION_SUCCEEDED = "pubsub-subscription-succeeded"; - TieredMap = class extends Map { - tGet(k1, k2) { - return this.get(k1)?.get(k2); - } - tHas(k1, k2) { - return !!this.get(k1)?.has(k2); - } - tSet(k1, k2, v2) { - let submap = this.get(k1); - if (!submap) { - submap = /* @__PURE__ */ new Map(); - this.set(k1, submap); - } - return submap.set(k2, v2); - } - tDelete(k1, k2) { - const submap = this.get(k1); - if (submap) { - const result = submap.delete(k2); - if (submap.size === 0) { - this.delete(k1); - } - return result; - } - return false; - } - tClear(k1) { - this.delete(k1); - } - }; - isKvFilterFresh = (ourKvFilter, theirKvFilter) => { - if (!ourKvFilter !== !theirKvFilter) { - return false; - } else if (ourKvFilter && theirKvFilter) { - if (ourKvFilter.length !== theirKvFilter.length) { - return false; - } else { - const sortedA = [...ourKvFilter].sort(); - const sortedB = [...theirKvFilter].sort(); - for (let i2 = 0; i2 < sortedA.length; i2++) { - if (sortedA[i2] !== sortedB[i2]) { - return false; - } - } - } - } - return true; - }; - pubPayloadFactory = (client, channelID) => () => { - const kvFilter = client.kvFilter.get(channelID); - return kvFilter ? { kvFilter, channelID } : { channelID }; - }; - defaultClientEventHandlers = { - // Emitted when the connection is closed. - close(event) { - const client = this; - console.debug("[pubsub] Event: close", event.code, event.reason); - client.failedConnectionAttempts++; - if (client.socket) { - for (const name of socketEventNames) { - client.socket.removeEventListener(name, client.listeners[name]); - } - } - client.socket = null; - client.clearAllTimers(); - if (client.shouldReconnect) { - const pendingSubscriptionMap = client.pendingOperations.get(REQUEST_TYPE.SUB); - if (pendingSubscriptionMap) { - for (const [channelID] of pendingSubscriptionMap) { - pendingSubscriptionMap.set(channelID, {}); - } - } - client.subscriptionSet.forEach((channelID) => { - if (!client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID)) { - client.pendingOperations.tSet(REQUEST_TYPE.SUB, channelID, {}); - } - }); - } - client.subscriptionSet.clear(); - client.pendingOperations.tClear(REQUEST_TYPE.UNSUB); - client.pendingOperations.tClear(REQUEST_TYPE.KV_FILTER); - if (client.shouldReconnect && client.options.reconnectOnDisconnection) { - if (client.failedConnectionAttempts > client.options.maxRetries) { - esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_FAILED, client); - } else { - if (!isDefinetelyOffline() || client.isLocal) { - client.scheduleConnectionAttempt(); - } - } - } - }, - // Emitted when an error has occured. - // The socket will be closed automatically by the engine if necessary. - error(event) { - const client = this; - console.warn("[pubsub] Event: error", event); - clearTimeout(client.pingTimeoutID); - }, - // Emitted when a message is received. - // The connection will be terminated if the message is malformed or has an - // unexpected data type (e.g. binary instead of text). - message(event) { - const client = this; - const { data } = event; - if (typeof data !== "string") { - esm_default("okTurtles.events/emit", PUBSUB_ERROR, client, { - message: `Wrong data type: ${typeof data}` - }); - return client.destroy(); - } - let msg = { type: "" }; - try { - msg = messageParser(data); - } catch (error2) { - esm_default("okTurtles.events/emit", PUBSUB_ERROR, client, { - message: `Malformed message: ${error2?.message}` - }); - return client.destroy(); - } - const handler = client.messageHandlers[msg.type]; - if (handler) { - handler.call(client, msg); - } else { - throw new Error(`Unhandled message type: ${msg.type}`); - } - }, - offline() { - console.info("[pubsub] Event: offline"); - const client = this; - client.clearAllTimers(); - client.failedConnectionAttempts = 0; - client.socket?.close(); - }, - online() { - console.info("[pubsub] Event: online"); - const client = this; - if (client.options.reconnectOnOnline && client.shouldReconnect) { - if (!client.socket) { - client.failedConnectionAttempts = 0; - client.scheduleConnectionAttempt(); - } - } - }, - // Emitted when the connection is established. - open() { - console.debug("[pubsub] Event: open"); - const client = this; - const { options: options2 } = this; - client.connectionTimeUsed = void 0; - client.clearAllTimers(); - esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_SUCCEEDED, client); - client.failedConnectionAttempts = -1; - client.isNew = false; - if (options2.pingTimeout > 0 && options2.pingTimeout < Infinity) { - client.pingTimeoutID = setTimeout(() => { - client.socket?.close(); - }, options2.pingTimeout); - } - for (const [channelID] of client.pendingOperations.get(REQUEST_TYPE.SUB) || []) { - runWithRetry(client, channelID, REQUEST_TYPE.SUB, pubPayloadFactory(client, channelID)); - } - }, - "reconnection-attempt"() { - console.info("[pubsub] Trying to reconnect..."); - }, - "reconnection-succeeded"() { - console.info("[pubsub] Connection re-established"); - }, - "reconnection-failed"() { - console.warn("[pubsub] Reconnection failed"); - const client = this; - client.destroy(); - }, - "reconnection-scheduled"(event) { - const { delay: delay2, nth } = event.detail; - console.info(`[pubsub] Scheduled connection attempt ${nth} in ~${delay2} ms`); - }, - "subscription-succeeded"(event) { - const { channelID } = event.detail; - console.debug(`[pubsub] Subscribed to channel ${channelID}`); - } - }; - defaultMessageHandlers = { - [NOTIFICATION_TYPE.ENTRY](msg) { - console.debug("[pubsub] Received ENTRY:", msg); - }, - [NOTIFICATION_TYPE.PING]({ data }) { - const client = this; - if (client.options.logPingMessages) { - console.debug(`[pubsub] Ping received in ${Date.now() - Number(data)} ms`); - } - client.socket?.send(createMessage(NOTIFICATION_TYPE.PONG, data)); - clearTimeout(client.pingTimeoutID); - client.pingTimeoutID = setTimeout(() => { - client.socket?.close(); - }, client.options.pingTimeout); - }, - [NOTIFICATION_TYPE.PUB]({ channelID, data }) { - console.log(`[pubsub] Received data from channel ${channelID}:`, data); - }, - [NOTIFICATION_TYPE.KV]({ channelID, key, data }) { - console.log(`[pubsub] Received KV update from channel ${channelID} ${key}:`, data); - }, - [NOTIFICATION_TYPE.SUB](msg) { - console.debug(`[pubsub] Ignoring ${msg.type} message:`, msg.data); - }, - [NOTIFICATION_TYPE.UNSUB](msg) { - console.debug(`[pubsub] Ignoring ${msg.type} message:`, msg.data); - }, - [RESPONSE_TYPE.ERROR]({ data }) { - const { type, channelID, reason } = data; - console.warn(`[pubsub] Received ERROR response for ${type} request to ${channelID}`); - const client = this; - switch (type) { - case REQUEST_TYPE.SUB: { - console.warn(`[pubsub] Could not subscribe to ${channelID}: ${reason}`); - client.pendingOperations.tDelete(REQUEST_TYPE.SUB, channelID); - break; - } - case REQUEST_TYPE.UNSUB: { - console.warn(`[pubsub] Could not unsubscribe from ${channelID}: ${reason}`); - client.pendingOperations.tDelete(REQUEST_TYPE.UNSUB, channelID); - break; - } - case REQUEST_TYPE.PUSH_ACTION: { - const { actionType, message } = data; - console.warn(`[pubsub] Received ERROR for PUSH_ACTION request with the action type '${actionType}' and the following message: ${message}`); - break; - } - case REQUEST_TYPE.KV_FILTER: { - console.warn(`[pubsub] Could not set KV filter for ${channelID}: ${reason}`); - client.pendingOperations.tDelete(REQUEST_TYPE.KV_FILTER, channelID); - break; - } - default: { - console.error(`[pubsub] Malformed response: invalid request type ${type}`); - } - } - }, - [RESPONSE_TYPE.OK]({ data: { type, channelID, kvFilter } }) { - const client = this; - switch (type) { - case REQUEST_TYPE.SUB: { - if (client.pendingOperations.tHas(REQUEST_TYPE.SUB, channelID)) { - client.pendingOperations.tDelete(REQUEST_TYPE.SUB, channelID); - client.subscriptionSet.add(channelID); - esm_default("okTurtles.events/emit", PUBSUB_SUBSCRIPTION_SUCCEEDED, client, { channelID }); - const ourKvFilter = client.kvFilter.get(channelID); - if (!isKvFilterFresh(ourKvFilter, kvFilter)) { - console.debug(`[pubsub] Subscribed to ${channelID}, need to set new KV filter`); - this.setKvFilter(channelID, ourKvFilter); - } - } else { - console.debug(`[pubsub] Received unexpected sub for ${channelID}`); - } - break; - } - case REQUEST_TYPE.UNSUB: { - if (client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID)) { - console.debug(`[pubsub] Unsubscribed from ${channelID}`); - client.pendingOperations.tDelete(REQUEST_TYPE.UNSUB, channelID); - client.subscriptionSet.delete(channelID); - } else { - console.debug(`[pubsub] Received unexpected unsub for ${channelID}`); - } - break; - } - case REQUEST_TYPE.KV_FILTER: { - if (client.pendingOperations.tHas(REQUEST_TYPE.KV_FILTER, channelID)) { - const ourKvFilter = client.kvFilter.get(channelID); - if (isKvFilterFresh(ourKvFilter, kvFilter)) { - console.debug(`[pubsub] Set KV filter for ${channelID}`, kvFilter); - client.pendingOperations.tDelete(REQUEST_TYPE.KV_FILTER, channelID); - } else { - console.debug(`[pubsub] Received stale KV filter ack for ${channelID}`, kvFilter, ourKvFilter); - } - } else { - console.debug(`[pubsub] Received unexpected kv-filter for ${channelID}`); - } - break; - } - default: { - console.error(`[pubsub] Malformed response: invalid request type ${type}`); - } - } - } - }; - globalEventNames = ["offline", "online"]; - socketEventNames = ["close", "error", "message", "open"]; - globalEventMap = /* @__PURE__ */ new Map(); - if (typeof self === "object" && self instanceof EventTarget) { - for (const name of globalEventNames) { - const handler = (ev) => { - const h2 = globalEventMap.get(name); - return h2?.(ev); - }; - self.addEventListener(name, handler, false); - } - } - isDefinetelyOffline = () => typeof navigator === "object" && navigator.onLine === false; - messageParser = (data) => { - const msg = JSON.parse(data); - if (typeof msg !== "object" || msg === null) { - throw new TypeError("Message is null or not an object"); - } - const { type } = msg; - if (typeof type !== "string" || type === "") { - throw new TypeError("Message type must be a non-empty string"); - } - return msg; - }; - publicMethods = { - clearAllTimers() { - const client = this; - clearTimeout(client.connectionTimeoutID); - clearTimeout(client.nextConnectionAttemptDelayID); - clearTimeout(client.pingTimeoutID); - client.connectionTimeoutID = void 0; - client.nextConnectionAttemptDelayID = void 0; - client.pingTimeoutID = void 0; - }, - // Performs a connection or reconnection attempt. - connect() { - const client = this; - if (client.socket !== null) { - throw new Error("connect() can only be called if there is no current socket."); - } - if (client.nextConnectionAttemptDelayID) { - throw new Error("connect() must not be called during a reconnection delay."); - } - if (!client.shouldReconnect) { - throw new Error("connect() should no longer be called on this instance."); - } - client.socket = new WebSocket(client.url); - client.socket.send = function(data) { - const send = WebSocket.prototype.send.bind(this); - if (typeof data === "object" && typeof data[Symbol.toPrimitive] === "function") { - return send(data[Symbol.toPrimitive]()); - } - return send(data); - }; - if (client.options.timeout) { - const start = performance.now(); - client.connectionTimeoutID = setTimeout(() => { - client.connectionTimeoutID = void 0; - if (client.options.reconnectOnTimeout) { - client.connectionTimeUsed = performance.now() - start; - } - client.socket?.close(4e3, "timeout"); - }, client.options.timeout); - } - for (const name of socketEventNames) { - client.socket.addEventListener(name, client.listeners[name]); - } - }, - /** - * Immediately close the socket, stop listening for events and clear any cache. - * - * This method is used in unit tests. - * - In particular, no 'close' event handler will be called. - * - Any incoming or outgoing buffered data will be discarded. - * - Any pending messages will be discarded. - */ - destroy() { - const client = this; - client.clearAllTimers(); - client.pendingOperations.clear(); - client.subscriptionSet.clear(); - if (typeof self === "object" && self instanceof EventTarget) { - for (const name of globalEventNames) { - globalEventMap.delete(name); - } - } - if (client.socket) { - for (const name of socketEventNames) { - client.socket.removeEventListener(name, client.listeners[name]); - } - client.socket.close(); - } - client.listeners = /* @__PURE__ */ Object.create(null); - client.socket = null; - client.shouldReconnect = false; - }, - getNextRandomDelay() { - const client = this; - const { maxReconnectionDelay, minReconnectionDelay, reconnectionDelayGrowFactor } = client.options; - const minDelay = minReconnectionDelay * reconnectionDelayGrowFactor ** client.failedConnectionAttempts; - const maxDelay = minDelay * reconnectionDelayGrowFactor; - const connectionTimeUsed = client.connectionTimeUsed; - client.connectionTimeUsed = void 0; - return Math.min( - // See issue #1943: Have the connection time used 'eat into' the - // reconnection time used - Math.max(minReconnectionDelay, connectionTimeUsed ? maxReconnectionDelay - connectionTimeUsed : maxReconnectionDelay), - Math.round(minDelay + (0, Math.random)() * (maxDelay - minDelay)) - ); - }, - // Schedules a connection attempt to happen after a delay computed according to - // a randomized exponential backoff algorithm variant. - scheduleConnectionAttempt() { - const client = this; - if (!client.shouldReconnect) { - throw new Error("Cannot call `scheduleConnectionAttempt()` when `shouldReconnect` is false."); - } - if (client.nextConnectionAttemptDelayID) { - return console.warn("[pubsub] A reconnection attempt is already scheduled."); - } - const delay2 = client.getNextRandomDelay(); - const nth = client.failedConnectionAttempts + 1; - client.nextConnectionAttemptDelayID = setTimeout(() => { - esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_ATTEMPT, client); - client.nextConnectionAttemptDelayID = void 0; - client.connect(); - }, delay2); - esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_SCHEDULED, client, { delay: delay2, nth }); - }, - // Can be used to send ephemeral messages outside of any contract log. - // Does nothing if the socket is not in the OPEN state. - pub(channelID, data) { - if (this.socket?.readyState === WebSocket.OPEN) { - this.socket.send(createPubMessage(channelID, data)); - } - }, - /** - * Sends a SUB request to the server as soon as possible. - * - * - The given channel ID will be cached until we get a relevant server - * response, allowing us to resend the same request if necessary. - * - Any identical UNSUB request that has not been sent yet will be cancelled. - * - Calling this method again before the server has responded has no effect. - * @param channelID - The ID of the channel whose updates we want to subscribe to. - */ - sub(channelID) { - const client = this; - if (!client.pendingOperations.tHas(REQUEST_TYPE.SUB, channelID) && !client.subscriptionSet.has(channelID)) { - client.pendingOperations.tDelete(REQUEST_TYPE.UNSUB, channelID); - runWithRetry(client, channelID, REQUEST_TYPE.SUB, pubPayloadFactory(client, channelID)); - } - }, - /** - * Sends a KV_FILTER request to the server as soon as possible. - */ - setKvFilter(channelID, kvFilter) { - const client = this; - if (kvFilter) { - client.kvFilter.set(channelID, kvFilter); - } else { - client.kvFilter.delete(channelID); - } - if (client.subscriptionSet.has(channelID) && !client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID)) { - runWithRetry(client, channelID, REQUEST_TYPE.KV_FILTER, pubPayloadFactory(client, channelID)); - } - }, - /** - * Sends an UNSUB request to the server as soon as possible. - * - * - The given channel ID will be cached until we get a relevant server - * response, allowing us to resend the same request if necessary. - * - Any identical SUB request that has not been sent yet will be cancelled. - * - Calling this method again before the server has responded has no effect. - * @param channelID - The ID of the channel whose updates we want to unsubscribe from. - */ - unsub(channelID) { - const client = this; - if (!client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID) && (client.subscriptionSet.has(channelID) || client.pendingOperations.tHas(REQUEST_TYPE.SUB, channelID))) { - client.pendingOperations.tDelete(REQUEST_TYPE.SUB, channelID); - client.kvFilter.delete(channelID); - runWithRetry(client, channelID, REQUEST_TYPE.UNSUB, () => ({ channelID })); - } - } - }; - for (const name of Object.keys(defaultClientEventHandlers)) { - if (name === "error" || !socketEventNames.includes(name)) { - esm_default("okTurtles.events/on", `pubsub-${name}`, (target, detail) => { - const ev = new CustomEvent(name, { detail }); - target.listeners[name].call(target, ev); - }); - } - } - } -}); -var init_esm6 = __esm({ +var init_esm5 = __esm({ "node_modules/.deno/@chelonia+multiformats@1.0.0/node_modules/@chelonia/multiformats/dist/esm/index.mjs"() { init_base(); init_base32(); @@ -20081,7 +19448,7 @@ var require_scrypt_async = __commonJS({ function scrypt3(password, salt, logN, r, dkLen, interruptStep, callback, encoding) { "use strict"; function SHA256(m3) { - var K3 = [ + var K2 = [ 1116352408, 1899447441, 3049323471, @@ -20147,24 +19514,24 @@ var require_scrypt_async = __commonJS({ 3204031479, 3329325298 ]; - var h0 = 1779033703, h1 = 3144134277, h2 = 1013904242, h3 = 2773480762, h4 = 1359893119, h5 = 2600822924, h6 = 528734635, h7 = 1541459225, w4 = new Array(64); + var h0 = 1779033703, h1 = 3144134277, h2 = 1013904242, h3 = 2773480762, h4 = 1359893119, h5 = 2600822924, h6 = 528734635, h7 = 1541459225, w3 = new Array(64); function blocks(p3) { var off = 0, len = p3.length; while (len >= 64) { var a = h0, b = h1, c = h2, d = h3, e2 = h4, f = h5, g2 = h6, h8 = h7, u2, i3, j, t1, t2; for (i3 = 0; i3 < 16; i3++) { j = off + i3 * 4; - w4[i3] = (p3[j] & 255) << 24 | (p3[j + 1] & 255) << 16 | (p3[j + 2] & 255) << 8 | p3[j + 3] & 255; + w3[i3] = (p3[j] & 255) << 24 | (p3[j + 1] & 255) << 16 | (p3[j + 2] & 255) << 8 | p3[j + 3] & 255; } for (i3 = 16; i3 < 64; i3++) { - u2 = w4[i3 - 2]; + u2 = w3[i3 - 2]; t1 = (u2 >>> 17 | u2 << 32 - 17) ^ (u2 >>> 19 | u2 << 32 - 19) ^ u2 >>> 10; - u2 = w4[i3 - 15]; + u2 = w3[i3 - 15]; t2 = (u2 >>> 7 | u2 << 32 - 7) ^ (u2 >>> 18 | u2 << 32 - 18) ^ u2 >>> 3; - w4[i3] = (t1 + w4[i3 - 7] | 0) + (t2 + w4[i3 - 16] | 0) | 0; + w3[i3] = (t1 + w3[i3 - 7] | 0) + (t2 + w3[i3 - 16] | 0) | 0; } for (i3 = 0; i3 < 64; i3++) { - t1 = (((e2 >>> 6 | e2 << 32 - 6) ^ (e2 >>> 11 | e2 << 32 - 11) ^ (e2 >>> 25 | e2 << 32 - 25)) + (e2 & f ^ ~e2 & g2) | 0) + (h8 + (K3[i3] + w4[i3] | 0) | 0) | 0; + t1 = (((e2 >>> 6 | e2 << 32 - 6) ^ (e2 >>> 11 | e2 << 32 - 11) ^ (e2 >>> 25 | e2 << 32 - 25)) + (e2 & f ^ ~e2 & g2) | 0) + (h8 + (K2[i3] + w3[i3] | 0) | 0) | 0; t2 = ((a >>> 2 | a << 32 - 2) ^ (a >>> 13 | a << 32 - 13) ^ (a >>> 22 | a << 32 - 22)) + (a & b ^ a & c ^ b & c) | 0; h8 = g2; g2 = f; @@ -20264,8 +19631,8 @@ var require_scrypt_async = __commonJS({ } return dk; } - function salsaXOR(tmp2, B5, bin, bout) { - var j0 = tmp2[0] ^ B5[bin++], j1 = tmp2[1] ^ B5[bin++], j2 = tmp2[2] ^ B5[bin++], j3 = tmp2[3] ^ B5[bin++], j4 = tmp2[4] ^ B5[bin++], j5 = tmp2[5] ^ B5[bin++], j6 = tmp2[6] ^ B5[bin++], j7 = tmp2[7] ^ B5[bin++], j8 = tmp2[8] ^ B5[bin++], j9 = tmp2[9] ^ B5[bin++], j10 = tmp2[10] ^ B5[bin++], j11 = tmp2[11] ^ B5[bin++], j12 = tmp2[12] ^ B5[bin++], j13 = tmp2[13] ^ B5[bin++], j14 = tmp2[14] ^ B5[bin++], j15 = tmp2[15] ^ B5[bin++], u2, i2; + function salsaXOR(tmp2, B4, bin, bout) { + var j0 = tmp2[0] ^ B4[bin++], j1 = tmp2[1] ^ B4[bin++], j2 = tmp2[2] ^ B4[bin++], j3 = tmp2[3] ^ B4[bin++], j4 = tmp2[4] ^ B4[bin++], j5 = tmp2[5] ^ B4[bin++], j6 = tmp2[6] ^ B4[bin++], j7 = tmp2[7] ^ B4[bin++], j8 = tmp2[8] ^ B4[bin++], j9 = tmp2[9] ^ B4[bin++], j10 = tmp2[10] ^ B4[bin++], j11 = tmp2[11] ^ B4[bin++], j12 = tmp2[12] ^ B4[bin++], j13 = tmp2[13] ^ B4[bin++], j14 = tmp2[14] ^ B4[bin++], j15 = tmp2[15] ^ B4[bin++], u2, i2; var x0 = j0, x1 = j1, x22 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, x15 = j15; for (i2 = 0; i2 < 8; i2 += 2) { u2 = x0 + x12; @@ -20333,22 +19700,22 @@ var require_scrypt_async = __commonJS({ u2 = x14 + x13; x15 ^= u2 << 18 | u2 >>> 32 - 18; } - B5[bout++] = tmp2[0] = x0 + j0 | 0; - B5[bout++] = tmp2[1] = x1 + j1 | 0; - B5[bout++] = tmp2[2] = x22 + j2 | 0; - B5[bout++] = tmp2[3] = x3 + j3 | 0; - B5[bout++] = tmp2[4] = x4 + j4 | 0; - B5[bout++] = tmp2[5] = x5 + j5 | 0; - B5[bout++] = tmp2[6] = x6 + j6 | 0; - B5[bout++] = tmp2[7] = x7 + j7 | 0; - B5[bout++] = tmp2[8] = x8 + j8 | 0; - B5[bout++] = tmp2[9] = x9 + j9 | 0; - B5[bout++] = tmp2[10] = x10 + j10 | 0; - B5[bout++] = tmp2[11] = x11 + j11 | 0; - B5[bout++] = tmp2[12] = x12 + j12 | 0; - B5[bout++] = tmp2[13] = x13 + j13 | 0; - B5[bout++] = tmp2[14] = x14 + j14 | 0; - B5[bout++] = tmp2[15] = x15 + j15 | 0; + B4[bout++] = tmp2[0] = x0 + j0 | 0; + B4[bout++] = tmp2[1] = x1 + j1 | 0; + B4[bout++] = tmp2[2] = x22 + j2 | 0; + B4[bout++] = tmp2[3] = x3 + j3 | 0; + B4[bout++] = tmp2[4] = x4 + j4 | 0; + B4[bout++] = tmp2[5] = x5 + j5 | 0; + B4[bout++] = tmp2[6] = x6 + j6 | 0; + B4[bout++] = tmp2[7] = x7 + j7 | 0; + B4[bout++] = tmp2[8] = x8 + j8 | 0; + B4[bout++] = tmp2[9] = x9 + j9 | 0; + B4[bout++] = tmp2[10] = x10 + j10 | 0; + B4[bout++] = tmp2[11] = x11 + j11 | 0; + B4[bout++] = tmp2[12] = x12 + j12 | 0; + B4[bout++] = tmp2[13] = x13 + j13 | 0; + B4[bout++] = tmp2[14] = x14 + j14 | 0; + B4[bout++] = tmp2[15] = x15 + j15 | 0; } function blockCopy(dst, di, src2, si, len) { while (len--) dst[di++] = src2[si++]; @@ -20356,15 +19723,15 @@ var require_scrypt_async = __commonJS({ function blockXOR(dst, di, src2, si, len) { while (len--) dst[di++] ^= src2[si++]; } - function blockMix(tmp2, B5, bin, bout, r2) { - blockCopy(tmp2, 0, B5, bin + (2 * r2 - 1) * 16, 16); + function blockMix(tmp2, B4, bin, bout, r2) { + blockCopy(tmp2, 0, B4, bin + (2 * r2 - 1) * 16, 16); for (var i2 = 0; i2 < 2 * r2; i2 += 2) { - salsaXOR(tmp2, B5, bin + i2 * 16, bout + i2 * 8); - salsaXOR(tmp2, B5, bin + i2 * 16 + 16, bout + i2 * 8 + r2 * 16); + salsaXOR(tmp2, B4, bin + i2 * 16, bout + i2 * 8); + salsaXOR(tmp2, B4, bin + i2 * 16 + 16, bout + i2 * 8 + r2 * 16); } } - function integerify(B5, bi, r2) { - return B5[bi + (2 * r2 - 1) * 16]; + function integerify(B4, bi, r2) { + return B4[bi + (2 * r2 - 1) * 16]; } function stringToUTF8Bytes(s) { var arr = []; @@ -20454,8 +19821,8 @@ var require_scrypt_async = __commonJS({ throw new Error("scrypt: invalid r"); if (logN < 1 || logN > 31) throw new Error("scrypt: logN must be between 1 and 31"); - var N11 = 1 << logN >>> 0, XY, V, B4, tmp; - if (r * p >= 1 << 30 || r > MAX_UINT / 128 / p || r > MAX_UINT / 256 || N11 > MAX_UINT / 128 / r) + var N10 = 1 << logN >>> 0, XY, V, B3, tmp; + if (r * p >= 1 << 30 || r > MAX_UINT / 128 / p || r > MAX_UINT / 256 || N10 > MAX_UINT / 128 / r) throw new Error("scrypt: parameters are too large"); if (typeof password === "string") password = stringToUTF8Bytes(password); @@ -20463,19 +19830,19 @@ var require_scrypt_async = __commonJS({ salt = stringToUTF8Bytes(salt); if (typeof Int32Array !== "undefined") { XY = new Int32Array(64 * r); - V = new Int32Array(32 * N11 * r); + V = new Int32Array(32 * N10 * r); tmp = new Int32Array(16); } else { XY = []; V = []; tmp = new Array(16); } - B4 = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); + B3 = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); var xi = 0, yi = 32 * r; function smixStart(pos) { for (var i2 = 0; i2 < 32 * r; i2++) { var j = pos + i2 * 4; - XY[xi + i2] = (B4[j + 3] & 255) << 24 | (B4[j + 2] & 255) << 16 | (B4[j + 1] & 255) << 8 | (B4[j + 0] & 255) << 0; + XY[xi + i2] = (B3[j + 3] & 255) << 24 | (B3[j + 2] & 255) << 16 | (B3[j + 1] & 255) << 8 | (B3[j + 0] & 255) << 0; } } function smixStep1(start, end) { @@ -20488,10 +19855,10 @@ var require_scrypt_async = __commonJS({ } function smixStep2(start, end) { for (var i2 = start; i2 < end; i2 += 2) { - var j = integerify(XY, xi, r) & N11 - 1; + var j = integerify(XY, xi, r) & N10 - 1; blockXOR(XY, xi, V, j * (32 * r), 32 * r); blockMix(tmp, XY, xi, yi, r); - j = integerify(XY, yi, r) & N11 - 1; + j = integerify(XY, yi, r) & N10 - 1; blockXOR(XY, yi, V, j * (32 * r), 32 * r); blockMix(tmp, XY, yi, xi, r); } @@ -20499,10 +19866,10 @@ var require_scrypt_async = __commonJS({ function smixFinish(pos) { for (var i2 = 0; i2 < 32 * r; i2++) { var j = XY[xi + i2]; - B4[pos + i2 * 4 + 0] = j >>> 0 & 255; - B4[pos + i2 * 4 + 1] = j >>> 8 & 255; - B4[pos + i2 * 4 + 2] = j >>> 16 & 255; - B4[pos + i2 * 4 + 3] = j >>> 24 & 255; + B3[pos + i2 * 4 + 0] = j >>> 0 & 255; + B3[pos + i2 * 4 + 1] = j >>> 8 & 255; + B3[pos + i2 * 4 + 2] = j >>> 16 & 255; + B3[pos + i2 * 4 + 3] = j >>> 24 & 255; } } var nextTick = typeof setImmediate !== "undefined" ? setImmediate : setTimeout; @@ -20519,7 +19886,7 @@ var require_scrypt_async = __commonJS({ })(); } function getResult(enc) { - var result = PBKDF2_HMAC_SHA256_OneIter(password, B4, dkLen); + var result = PBKDF2_HMAC_SHA256_OneIter(password, B3, dkLen); if (enc === "base64") return bytesToBase64(result); else if (enc === "hex") @@ -20532,16 +19899,16 @@ var require_scrypt_async = __commonJS({ function calculateSync() { for (var i2 = 0; i2 < p; i2++) { smixStart(i2 * 128 * r); - smixStep1(0, N11); - smixStep2(0, N11); + smixStep1(0, N10); + smixStep2(0, N10); smixFinish(i2 * 128 * r); } callback(getResult(encoding)); } function calculateAsync(i2) { smixStart(i2 * 128 * r); - interruptedFor(0, N11, interruptStep * 2, smixStep1, function() { - interruptedFor(0, N11, interruptStep * 2, smixStep2, function() { + interruptedFor(0, N10, interruptStep * 2, smixStep1, function() { + interruptedFor(0, N10, interruptStep * 2, smixStep2, function() { smixFinish(i2 * 128 * r); if (i2 + 1 < p) { nextTick(function() { @@ -21859,7 +21226,7 @@ var require_nacl_fast = __commonJS({ crypto_box_beforenm(k, y, x3); return crypto_box_open_afternm(m3, c, d, n, k); } - var K3 = [ + var K2 = [ 1116352408, 3609767458, 1899447441, @@ -22066,8 +21433,8 @@ var require_nacl_fast = __commonJS({ b += l >>> 16; c += h2 & 65535; d += h2 >>> 16; - h2 = K3[i2 * 2]; - l = K3[i2 * 2 + 1]; + h2 = K2[i2 * 2]; + l = K2[i2 * 2 + 1]; a += l & 65535; b += l >>> 16; c += h2 & 65535; @@ -22764,22 +22131,22 @@ var require_nacl_fast = __commonJS({ randombytes = fn; }; (function() { - var crypto2 = typeof self !== "undefined" ? self.crypto || self.msCrypto : null; - if (crypto2 && crypto2.getRandomValues) { + var crypto3 = typeof self !== "undefined" ? self.crypto || self.msCrypto : null; + if (crypto3 && crypto3.getRandomValues) { var QUOTA = 65536; nacl4.setPRNG(function(x3, n) { var i2, v2 = new Uint8Array(n); for (i2 = 0; i2 < n; i2 += QUOTA) { - crypto2.getRandomValues(v2.subarray(i2, i2 + Math.min(n - i2, QUOTA))); + crypto3.getRandomValues(v2.subarray(i2, i2 + Math.min(n - i2, QUOTA))); } for (i2 = 0; i2 < n; i2++) x3[i2] = v2[i2]; cleanup(v2); }); } else if (typeof __require2 !== "undefined") { - crypto2 = __require2("crypto"); - if (crypto2 && crypto2.randomBytes) { + crypto3 = __require2("node:crypto"); + if (crypto3 && crypto3.randomBytes) { nacl4.setPRNG(function(x3, n) { - var i2, v2 = crypto2.randomBytes(n); + var i2, v2 = crypto3.randomBytes(n); for (i2 = 0; i2 < n; i2++) x3[i2] = v2[i2]; cleanup(v2); }); @@ -22811,9 +22178,9 @@ var sign; var verifySignature; var encrypt; var decrypt; -var init_esm7 = __esm({ +var init_esm6 = __esm({ "node_modules/.deno/@chelonia+crypto@1.0.1/node_modules/@chelonia/crypto/dist/esm/index.mjs"() { - init_esm6(); + init_esm5(); import_scrypt_async = __toESM(require_scrypt_async(), 1); import_tweetnacl = __toESM(require_nacl_fast(), 1); bufToStr = (() => { @@ -23212,34 +22579,6 @@ var init_errors3 = __esm({ ChelErrorResourceGone = ChelErrorGenerator("ChelErrorResourceGone", ChelErrorUnexpectedHttpResponseCode); } }); -var CHELONIA_RESET; -var CONTRACT_IS_SYNCING; -var CONTRACTS_MODIFIED; -var EVENT_HANDLED; -var EVENT_PUBLISHED; -var EVENT_PUBLISHING_ERROR; -var CONTRACT_REGISTERED; -var CONTRACT_IS_PENDING_KEY_REQUESTS; -var CONTRACT_HAS_RECEIVED_KEYS; -var PERSISTENT_ACTION_FAILURE; -var PERSISTENT_ACTION_SUCCESS; -var PERSISTENT_ACTION_TOTAL_FAILURE; -var init_events = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/events.mjs"() { - CHELONIA_RESET = "chelonia-reset"; - CONTRACT_IS_SYNCING = "contract-is-syncing"; - CONTRACTS_MODIFIED = "contracts-modified"; - EVENT_HANDLED = "event-handled"; - EVENT_PUBLISHED = "event-published"; - EVENT_PUBLISHING_ERROR = "event-publishing-error"; - CONTRACT_REGISTERED = "contract-registered"; - CONTRACT_IS_PENDING_KEY_REQUESTS = "contract-is-pending-key-requests"; - CONTRACT_HAS_RECEIVED_KEYS = "contract-has-received-keys"; - PERSISTENT_ACTION_FAILURE = "persistent-action-failure"; - PERSISTENT_ACTION_SUCCESS = "persistent-action-success"; - PERSISTENT_ACTION_TOTAL_FAILURE = "persistent-action-total_failure"; - } -}); var serdesTagSymbol; var serdesSerializeSymbol; var serdesDeserializeSymbol; @@ -23247,7 +22586,7 @@ var rawResult; var serializer; var deserializerTable; var deserializer; -var init_esm8 = __esm({ +var init_esm7 = __esm({ "node_modules/.deno/@chelonia+serdes@1.0.0/node_modules/@chelonia/serdes/dist/esm/index.js"() { serdesTagSymbol = Symbol("tag"); serdesSerializeSymbol = Symbol("serialize"); @@ -23428,9 +22767,9 @@ var isRawSignedData; var rawSignedIncomingData; var init_signedData = __esm({ "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/signedData.mjs"() { - init_esm7(); + init_esm6(); init_esm(); - init_esm5(); + init_esm4(); init_errors3(); init_functions(); rootStateFn = () => esm_default("chelonia/rootState"); @@ -23701,9 +23040,9 @@ var unwrapMaybeEncryptedData; var maybeEncryptedIncomingData; var init_encryptedData = __esm({ "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/encryptedData.mjs"() { - init_esm7(); + init_esm6(); init_esm(); - init_esm5(); + init_esm4(); init_errors3(); init_signedData(); rootStateFn2 = () => esm_default("chelonia/rootState"); @@ -23966,9 +23305,9 @@ var SPMessage; var keyOps; var init_SPMessage = __esm({ "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/SPMessage.mjs"() { + init_esm6(); init_esm7(); - init_esm8(); - init_esm5(); + init_esm4(); init_encryptedData(); init_functions(); init_signedData(); @@ -24361,10293 +23700,5970 @@ var init_SPMessage = __esm({ ]; } }); -var chelonia_utils_default; -var init_chelonia_utils = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/chelonia-utils.mjs"() { +var headPrefix; +var getContractIdFromLogHead; +var getLogHead; +var checkKey; +var parsePrefixableKey; +var prefixHandlers; +var dbPrimitiveSelectors; +var db_default; +var init_db = __esm({ + "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/db.mjs"() { + init_esm3(); + init_esm2(); init_esm(); - chelonia_utils_default = esm_default("sbp/selectors/register", { - // This selector is a wrapper for the `chelonia/kv/set` selector that uses - // the contract queue and allows referring to keys by name, with default key - // names set to `csk` and `cek` for signatures and encryption, respectively. - // For most 'simple' use cases, this selector is a better choice than - // `chelonia/kv/set`. However, the `chelonia/kv/set` primitive is needed if - // the queueing logic needs to be more advanced, the key to use requires - // custom logic or _if the `onconflict` callback also needs to be queued_. - "chelonia/kv/queuedSet": ({ contractID, key, data, onconflict, ifMatch, encryptionKeyName = "cek", signingKeyName = "csk" }) => { - return esm_default("chelonia/queueInvocation", contractID, () => { - return esm_default("chelonia/kv/set", contractID, key, data, { - ifMatch, - encryptionKeyId: esm_default("chelonia/contract/currentKeyIdByName", contractID, encryptionKeyName), - signingKeyId: esm_default("chelonia/contract/currentKeyIdByName", contractID, signingKeyName), - onconflict - }); - }); - } - }); - } -}); -async function* g(a, s, r) { - let d = new TextEncoder(), y = d.encode(`\r ---${a}`); - if (Array.isArray(s) && s.length < 1) { - await r.abort(Error("At least one part is required")); - return; - } - let l = 0; - for await (let e2 of s) { - l++; - let n, t; - if (!e2.body && e2.parts) if (t = e2.headers.get("content-type"), !t) n = A(), t = `multipart/mixed; boundary="${n}"`; - else if (!t.startsWith("multipart/") || !T.test(t)) { - await r.abort(Error("Invalid multipart content type: " + t)); - return; - } else { - let o2 = t.match(m); - (!o2 || !(n = o2[1] || o2[2])) && (n = A(), t = t.replace(T, `; boundary="${n}"`)); - } - await u(y).pipeTo(r, i), yield; - { - let o2 = [""]; - if (t) { - let p = false; - e2.headers.forEach((f, c) => { - c !== "content-type" ? o2.push(`${c}: ${f}`) : (p = true, o2.push(`${c}: ${t}`)); - }), p || o2.push(`content-type: ${t}`); - } else e2.headers.forEach((p, f) => { - o2.push(`${f}: ${p}`); - }); - e2.parts || !e2.body ? o2.push("") : o2.push("", ""); - let B4 = d.encode(o2.join(`\r -`)); - o2.length = 0, await u(B4).pipeTo(r, i), yield; - } - if (e2.body) { - if (e2.body instanceof ArrayBuffer || ArrayBuffer.isView(e2.body)) await u(e2.body).pipeTo(r, i); - else if (e2.body instanceof Blob) await e2.body.stream().pipeTo(r, i); - else if (e2.body instanceof ReadableStream) await e2.body.pipeTo(r, i); - else { - await r.abort(Error("Invalid body type")); + init_SPMessage(); + init_errors3(); + headPrefix = "head="; + getContractIdFromLogHead = (key) => { + if (!key.startsWith(headPrefix)) return; + return key.slice(headPrefix.length); + }; + getLogHead = (contractID) => `${headPrefix}${contractID}`; + checkKey = (key) => { + if (/[\x00-\x1f\x7f\t\\/<>:"|?*]/.test(key)) { + throw new Error(`bad key: ${JSON.stringify(key)}`); } - yield; - } else if (e2.parts) { - if (!n) { - await r.abort(Error("Runtime exception: undefined part boundary")); - return; + }; + parsePrefixableKey = (key) => { + const i2 = key.indexOf(":"); + if (i2 === -1) { + return ["", key]; } - yield* g(n, e2.parts, r), yield; - } - } - if (!l) { - await r.abort(Error("At least one part is required")); - return; - } - let b = d.encode(`\r ---${a}--`); - await u(b).pipeTo(r, i); -} -var m; -var M; -var u; -var T; -var h; -var A; -var i; -var w; -var x; -var init_encodeMultipartMessage = __esm({ - "node_modules/.deno/@apeleghq+multipart-parser@1.0.18/node_modules/@apeleghq/multipart-parser/dist/encodeMultipartMessage.mjs"() { - m = /;\s*boundary=(?:"([0-9a-zA-Z'()+_,\-./:=? ]{0,69}[0-9a-zA-Z'()+_,\-./:=?])"|([0-9a-zA-Z'+_\-.]{0,69}[0-9a-zA-Z'+_\-.]))/; - M = (a) => new ReadableStream({ pull(r) { - if (ArrayBuffer.isView(a)) r.enqueue(a.buffer.slice(a.byteOffset, a.byteOffset + a.byteLength)); - else if (a instanceof ArrayBuffer) r.enqueue(a); - else throw new TypeError("Expected ArrayBuffer or an ArrayBuffer view."); - r.close(); - } }); - u = M; - T = /;\s*boundary=(?:"([^"]+)"|([^;",]+))/; - h = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-."; - A = () => { - let a = new Uint8Array(24); - return globalThis.crypto.getRandomValues(a), Array.from(a).map((s) => h[s % h.length]).join(""); - }; - i = { preventClose: true }; - w = (a, s) => { - let r = new TransformStream(), d = g(a, s, r.writable), y = false, l = r.readable.getReader(); - return new ReadableStream({ start(e2) { - (async () => { - for (; ; ) try { - let n = await l.read(); - if (n.done) { - let t = new Uint8Array([13, 10]); - e2.enqueue(t.buffer.slice(t.byteOffset, t.byteOffset + t.byteLength)), e2.close(); - return; - } - e2.enqueue(n.value); - } catch (n) { - e2.error(n); - return; + const prefix = key.slice(0, i2 + 1); + if (prefix in prefixHandlers) { + return [prefix, key.slice(prefix.length)]; + } + throw new ChelErrorDBConnection(`Unknown prefix in '${key}'.`); + }; + prefixHandlers = { + // Decode buffers, but don't transform other values. + "": (value) => Buffer5.isBuffer(value) ? value.toString("utf8") : value, + "any:": (value) => value + /* + // 2025-03-24: Commented out because it's not used; currently, only `any:` + // is used in the `/file` route. + // Throw if the value if not a buffer. + 'blob:': value => { + if (Buffer.isBuffer(value)) { + return value + } + throw new ChelErrorDBConnection('Unexpected value: expected a buffer.') + } + */ + }; + esm_default("sbp/selectors/unsafe", ["chelonia.db/get", "chelonia.db/set", "chelonia.db/delete", "chelonia.db/iterKeys", "chelonia.db/keyCount"]); + dbPrimitiveSelectors = process.env.LIGHTWEIGHT_CLIENT === "true" ? { + "chelonia.db/get": function(key) { + const id = getContractIdFromLogHead(key); + if (!id) + return Promise.resolve(); + const state = esm_default("chelonia/rootState").contracts[id]; + const value = state?.HEAD ? JSON.stringify({ + HEAD: state.HEAD, + height: state.height, + previousKeyOp: state.previousKeyOp + }) : void 0; + return Promise.resolve(value); + }, + "chelonia.db/set": function() { + return Promise.resolve(); + }, + "chelonia.db/delete": function() { + return Promise.resolve(true); + }, + "chelonia.db/iterKeys": async function* () { + }, + "chelonia.db/keyCount": function() { + return Promise.resolve(0); + } + } : { + // eslint-disable-next-line require-await + "chelonia.db/get": async function(prefixableKey) { + const [prefix, key] = parsePrefixableKey(prefixableKey); + const value = esm_default("okTurtles.data/get", key); + if (value === void 0) { + return; + } + return prefixHandlers[prefix](value); + }, + // eslint-disable-next-line require-await + "chelonia.db/set": async function(key, value) { + checkKey(key); + return esm_default("okTurtles.data/set", key, value); + }, + // eslint-disable-next-line require-await + "chelonia.db/delete": async function(key) { + return esm_default("okTurtles.data/delete", key); + }, + "chelonia.db/iterKeys": async function* () { + yield* esm_default("okTurtles.data/iterKeys"); + }, + "chelonia.db/keyCount": function() { + return Promise.resolve(esm_default("okTurtles.data/keyCount")); + } + }; + db_default = esm_default("sbp/selectors/register", { + ...dbPrimitiveSelectors, + "chelonia/db/getEntryMeta": async (contractID, height) => { + const entryMetaJson = await esm_default("chelonia.db/get", `_private_hidx=${contractID}#${height}`); + if (!entryMetaJson) + return; + return JSON.parse(entryMetaJson); + }, + "chelonia/db/setEntryMeta": async (contractID, height, entryMeta) => { + const entryMetaJson = JSON.stringify(entryMeta); + await esm_default("chelonia.db/set", `_private_hidx=${contractID}#${height}`, entryMetaJson); + }, + "chelonia/db/latestHEADinfo": async (contractID) => { + const r = await esm_default("chelonia.db/get", getLogHead(contractID)); + return r && JSON.parse(r); + }, + "chelonia/db/deleteLatestHEADinfo": (contractID) => { + return esm_default("chelonia.db/set", getLogHead(contractID), ""); + }, + "chelonia/db/getEntry": async function(hash3) { + try { + const value = await esm_default("chelonia.db/get", hash3); + if (!value) + throw new Error(`no entry for ${hash3}!`); + return SPMessage.deserialize(value, this.transientSecretKeys, void 0, this.config.unwrapMaybeEncryptedData); + } catch (e2) { + throw new ChelErrorDBConnection(`${e2.name} during getEntry: ${e2.message}`); + } + }, + "chelonia/db/addEntry": function(entry) { + return esm_default("okTurtles.eventQueue/queueEvent", `chelonia/db/${entry.contractID()}`, ["chelonia/private/db/addEntry", entry]); + }, + // NEVER call this directly yourself! _always_ call 'chelonia/db/addEntry' instead + "chelonia/private/db/addEntry": async function(entry) { + try { + const { previousHEAD: entryPreviousHEAD, previousKeyOp: entryPreviousKeyOp, height: entryHeight } = entry.head(); + const contractID = entry.contractID(); + if (await esm_default("chelonia.db/get", entry.hash())) { + console.warn(`[chelonia.db] entry exists: ${entry.hash()}`); + return entry.hash(); } - })().catch(() => { - }); - }, async pull() { - if (y) return; - (await d.next()).done && (y = true, await r.writable.close()); - } }); - }; - x = w; - } -}); -var v; -var I; -var B; -var m2; -var o; -var R; -var S; -var init_decrypt = __esm({ - "node_modules/.deno/@apeleghq+rfc8188@1.0.8/node_modules/@apeleghq/rfc8188/dist/decrypt.mjs"() { - v = async (n, T2, w4, L) => { - let u2 = await globalThis.crypto.subtle.importKey("raw", T2, "HKDF", false, ["deriveKey", "deriveBits"]), d = await globalThis.crypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", info: n.cek_info, salt: w4 }, u2, n.params, false, L), A2 = await globalThis.crypto.subtle.deriveBits({ name: "HKDF", hash: "SHA-256", info: n.nonce_info, salt: w4 }, u2, n.nonce_length << 3); - return [d, function* () { - let s = new ArrayBuffer(n.nonce_length), e2 = new DataView(s), y = new Uint8Array(s), i2 = new Uint8Array(A2), b = 4294967295, f = (n.nonce_length >> 2) - 1, l = new Array(f).fill(0); - for (; ; ) { - for (let a = 0; a <= b; a++) { - e2.setUint32(e2.byteLength - 4, a, false); - let t = new Uint8Array(n.nonce_length); - for (let r = 0; r < t.length; r++) t[r] = i2[r] ^ y[r]; - yield t; - } - for (let a = 0; a < f; a++) { - if (a === f - 1 && l[a] === b) throw new RangeError("Maximum number of segments exceeded"); - if (l[a] = (l[a] + 1) % (b + 1), e2.setUint32(e2.byteLength - 4 * (a + 2), l[a], false), l[a] !== 0) break; - } - } - }()]; - }; - I = v; - B = (n) => ArrayBuffer.isView(n) ? new Uint8Array(n.buffer).subarray(n.byteOffset, n.byteOffset + n.byteLength) : new Uint8Array(n); - m2 = B; - o = { salt: {}, recordSize: {}, keyIdLen: {}, keyId: {}, payload: {}, done: {} }; - R = (n, T2, w4, L) => { - let u2 = new Uint8Array(16), d, A2, E3, s = 0, e2 = 0, y = new Uint8Array(256), i2 = o.salt, b = new TransformStream({ start: () => { - }, transform: async (f, l) => { - let a = m2(f), t = 0; - for (; t < f.byteLength; ) switch (i2) { - case o.salt: { - let r = a.subarray(t, t + u2.byteLength - e2); - if (u2.set(r, e2), e2 += r.byteLength, t += r.byteLength, e2 === u2.byteLength) { - e2 = 0, i2 = o.recordSize; - continue; + const HEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); + if (!entry.isFirstMessage()) { + if (!HEADinfo) { + throw new Error(`No latest HEAD for ${contractID} when attempting to process entry with previous HEAD ${entryPreviousHEAD} at height ${entryHeight}`); } - break; - } - case o.recordSize: { - let r = a.subarray(t, t + 4 - e2), g2 = new ArrayBuffer(4), h2 = new Uint8Array(g2), c = new DataView(g2); - if (h2.set(r, e2), s |= c.getUint32(0, false), e2 += r.byteLength, t += r.byteLength, e2 === 4) { - if (s <= n.tag_length + 1 || s > (L == null ? 4294967295 : Math.min(4294967295, L))) throw new RangeError("Invalid record size: " + s); - e2 = 0, i2 = o.keyIdLen; - continue; + const { HEAD: contractHEAD, previousKeyOp: contractPreviousKeyOp, height: contractHeight } = HEADinfo; + if (entryPreviousHEAD !== contractHEAD) { + console.warn(`[chelonia.db] bad previousHEAD: ${entryPreviousHEAD}! Expected: ${contractHEAD} for contractID: ${contractID}`); + throw new ChelErrorDBBadPreviousHEAD(`bad previousHEAD: ${entryPreviousHEAD}. Expected ${contractHEAD} for contractID: ${contractID}`); + } else if (entryPreviousKeyOp !== contractPreviousKeyOp) { + console.error(`[chelonia.db] bad previousKeyOp: ${entryPreviousKeyOp}! Expected: ${contractPreviousKeyOp} for contractID: ${contractID}`); + throw new ChelErrorDBBadPreviousHEAD(`bad previousKeyOp: ${entryPreviousKeyOp}. Expected ${contractPreviousKeyOp} for contractID: ${contractID}`); + } else if (!Number.isSafeInteger(entryHeight) || entryHeight !== contractHeight + 1) { + console.error(`[chelonia.db] bad height: ${entryHeight}! Expected: ${contractHeight + 1} for contractID: ${contractID}`); + throw new ChelErrorDBBadPreviousHEAD(`[chelonia.db] bad height: ${entryHeight}! Expected: ${contractHeight + 1} for contractID: ${contractID}`); } - break; - } - case o.keyIdLen: { - y[0] = a[t++], i2 = o.keyId; - continue; - } - case o.keyId: { - let r = a.subarray(t, t + y[0] - e2); - if (y.set(r, 1 + e2), e2 += r.byteLength, t += r.byteLength, e2 === y[0]) { - let g2 = await w4(y.subarray(1, 1 + y[0])); - w4 = void 0; - let h2 = await I(n, g2, u2, ["decrypt"]); - A2 = h2[0], E3 = h2[1], d = new Uint8Array(s), e2 = 0, i2 = o.payload; - continue; + } else { + if (HEADinfo) { + console.error(`[chelonia.db] bad previousHEAD: ${entryPreviousHEAD}! Expected: for contractID: ${contractID}`); + throw new ChelErrorDBBadPreviousHEAD(`bad previousHEAD: ${entryPreviousHEAD}. Expected for contractID: ${contractID}`); + } else if (entryHeight !== 0) { + console.error(`[chelonia.db] bad height: ${entryHeight}! Expected: 0 for contractID: ${contractID}`); + throw new ChelErrorDBBadPreviousHEAD(`[chelonia.db] bad height: ${entryHeight}! Expected: 0 for contractID: ${contractID}`); } - break; } - case o.payload: { - let r = a.subarray(t, t + s - e2); - if (d.set(r, e2), e2 += r.byteLength, t += r.byteLength, e2 === s) { - let h2 = E3.next().value, c = m2(await globalThis.crypto.subtle.decrypt({ name: n.params.name, iv: h2, tagLength: n.tag_length << 3 }, A2, d.subarray(0, e2))), p = c.byteLength - 1; - for (; p > 0 && c[p] === 0; p--) ; - if (c[p] === 2) { - if (t !== f.byteLength) throw new Error("Unexpected terminal padding delimiter"); - i2 = o.done; - } else if (c[p] !== 1) throw new Error("Invalid padding delimiter"); - l.enqueue(c.buffer.slice(0, p)), c.fill(0), e2 = 0; - continue; - } - break; + await esm_default("chelonia.db/set", entry.hash(), entry.serialize()); + await esm_default("chelonia.db/set", getLogHead(contractID), JSON.stringify({ + HEAD: entry.hash(), + previousKeyOp: entry.isKeyOp() ? entry.hash() : entry.previousKeyOp(), + height: entry.height() + })); + console.debug(`[chelonia.db] HEAD for ${contractID} updated to:`, entry.hash()); + await esm_default("chelonia/db/setEntryMeta", contractID, entryHeight, { + // The hash is used for reverse lookups (height to CID) + hash: entry.hash(), + // The date isn't currently used, but will be used for filtering messages + date: (/* @__PURE__ */ new Date()).toISOString(), + // isKeyOp is used for filtering messages (the actual filtering is + // done more efficiently a separate index key, but `isKeyOp` allows + // us to bootstrap this process without having to load the full message) + // The separate index key bears the prefix `_private_keyop_idx_`. + ...entry.isKeyOp() && { isKeyOp: true } + }); + return entry.hash(); + } catch (e2) { + if (e2.name.includes("ErrorDB")) { + throw e2; } - default: - throw new Error("Invalid state"); + throw new ChelErrorDBConnection(`${e2.name} during addEntry: ${e2.message}`); + } + }, + "chelonia/db/lastEntry": async function(contractID) { + try { + const latestHEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); + if (!latestHEADinfo) + throw new Error(`contract ${contractID} has no latest hash!`); + return esm_default("chelonia/db/getEntry", latestHEADinfo.HEAD); + } catch (e2) { + throw new ChelErrorDBConnection(`${e2.name} during lastEntry: ${e2.message}`); } - }, flush: async (f) => { - switch (i2) { - case o.done: - return; - case o.payload: { - if (e2 < 1 + n.tag_length) throw new Error("Unexpected end of data"); - let a = E3.next().value, t = m2(await globalThis.crypto.subtle.decrypt({ name: n.params.name, iv: a, tagLength: n.tag_length << 3 }, A2, d.subarray(0, e2))), r = t.byteLength - 1; - for (; r > 0 && t[r] === 0; r--) ; - if (t[r] !== 2) throw new Error("Unexpected non-terminal padding delimiter"); - f.enqueue(t.buffer.slice(0, r)), t.fill(0); - return; - } - default: - throw new Error("Invalid state"); - } - } }); - return T2.pipeThrough(b), b.readable; - }; - S = R; - } -}); -var e; -var init_encodings = __esm({ - "node_modules/.deno/@apeleghq+rfc8188@1.0.8/node_modules/@apeleghq/rfc8188/dist/encodings.mjs"() { - e = { params: { name: "AES-GCM", length: 256 }, get cek_info() { - return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 97, 101, 115, 50, 53, 54, 103, 99, 109, 0]); - }, get nonce_info() { - return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 110, 111, 110, 99, 101, 0]); - }, block_size: 16, tag_length: 16, nonce_length: 12 }; - } -}); -var R2; -var E; -var B2; -var w2; -var N; -var U; -var K; -var init_encrypt = __esm({ - "node_modules/.deno/@apeleghq+rfc8188@1.0.8/node_modules/@apeleghq/rfc8188/dist/encrypt.mjs"() { - R2 = async (e2, b, f, i2) => { - let A2 = await globalThis.crypto.subtle.importKey("raw", b, "HKDF", false, ["deriveKey", "deriveBits"]), y = await globalThis.crypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", info: e2.cek_info, salt: f }, A2, e2.params, false, i2), u2 = await globalThis.crypto.subtle.deriveBits({ name: "HKDF", hash: "SHA-256", info: e2.nonce_info, salt: f }, A2, e2.nonce_length << 3); - return [y, function* () { - let L = new ArrayBuffer(e2.nonce_length), c = new DataView(L), h2 = new Uint8Array(L), a = new Uint8Array(u2), g2 = 4294967295, o2 = (e2.nonce_length >> 2) - 1, s = new Array(o2).fill(0); - for (; ; ) { - for (let t = 0; t <= g2; t++) { - c.setUint32(c.byteLength - 4, t, false); - let n = new Uint8Array(e2.nonce_length); - for (let r = 0; r < n.length; r++) n[r] = a[r] ^ h2[r]; - yield n; - } - for (let t = 0; t < o2; t++) { - if (t === o2 - 1 && s[t] === g2) throw new RangeError("Maximum number of segments exceeded"); - if (s[t] = (s[t] + 1) % (g2 + 1), c.setUint32(c.byteLength - 4 * (t + 2), s[t], false), s[t] !== 0) break; - } - } - }()]; - }; - E = R2; - B2 = (e2) => ArrayBuffer.isView(e2) ? new Uint8Array(e2.buffer).subarray(e2.byteOffset, e2.byteOffset + e2.byteLength) : new Uint8Array(e2); - w2 = B2; - N = () => { - let e2 = new Uint8Array(16); - return globalThis.crypto.getRandomValues(e2), e2; - }; - U = async (e2, b, f, i2, A2, y) => { - if (f <= e2.tag_length + 1 || f > 4294967295) throw new RangeError("Invalid record size: " + f); - if (i2.byteLength > 255) throw new RangeError("Key ID too long"); - if (y && y.byteLength !== 16) throw new RangeError("Invald salt length: " + y.byteLength); - let u2 = f - e2.tag_length - 1, l = y ? w2(y) : N(), [L, c] = await E(e2, A2, l, ["encrypt"]); - A2 = void 0; - let h2 = new Uint8Array(u2), a = 0, g2 = new TransformStream({ start: (o2) => { - let s = l.byteLength + 4 + 1 + i2.byteLength, t = new ArrayBuffer(s); - new Uint8Array(t, 0, l.byteLength).set(l); - let r = new DataView(t, l.byteLength, 5); - r.setUint32(0, f, false), r.setUint8(4, i2.byteLength); - let d = new Uint8Array(t, l.byteLength + 4 + 1, i2.byteLength), m3 = w2(i2); - d.set(m3), o2.enqueue(t); - }, transform: async (o2, s) => { - let t = w2(o2), n = 0; - for (; n < o2.byteLength; ) { - let r = t.subarray(n, n + u2 - a); - if (h2.set(r, a), a += r.byteLength, n += r.byteLength, a === u2) { - let m3 = c.next().value, p = new Uint8Array(u2 + 1); - p.set(h2.subarray(0, a)), p[a] = 1; - let T2 = await globalThis.crypto.subtle.encrypt({ name: e2.params.name, iv: m3, tagLength: e2.tag_length << 3 }, L, p); - s.enqueue(T2), a = 0; - } - } - }, flush: async (o2) => { - let t = c.next().value, n = new Uint8Array(a + 1); - n.set(h2.subarray(0, a)), n[a] = 2; - let r = await globalThis.crypto.subtle.encrypt({ name: e2.params.name, iv: t, tagLength: e2.tag_length << 3 }, L, n); - o2.enqueue(r), h2.fill(0), n.fill(0); - } }); - return b.pipeThrough(g2), g2.readable; - }; - K = U; - } -}); -var wm; -var Secret; -var init_Secret = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/Secret.mjs"() { - init_esm8(); - wm = /* @__PURE__ */ new WeakMap(); - Secret = class { - static [serdesDeserializeSymbol](secret) { - return new this(secret); - } - static [serdesSerializeSymbol](secret) { - return wm.get(secret); - } - static get [serdesTagSymbol]() { - return "__chelonia_Secret"; - } - constructor(value) { - wm.set(this, value); - } - valueOf() { - return wm.get(this); } - }; + }); } }); -var INVITE_STATUS; -var init_constants = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/constants.mjs"() { - INVITE_STATUS = { - REVOKED: "revoked", - VALID: "valid", - USED: "used" +var require_lru_cache = __commonJS({ + "node_modules/.deno/lru-cache@7.14.0/node_modules/lru-cache/index.js"(exports2, module14) { + var perf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date; + var hasAbortController = typeof AbortController === "function"; + var AC = hasAbortController ? AbortController : class AbortController { + constructor() { + this.signal = new AS(); + } + abort() { + this.signal.dispatchEvent("abort"); + } }; - } -}); -function eventsAfter(contractID, { sinceHeight, limit, sinceHash, stream = true }) { - if (!contractID) { - throw new Error("Missing contract ID"); - } - let lastUrl; - const fetchEventsStreamReader = async () => { - requestLimit = Math.min(limit ?? MAX_EVENTS_AFTER, remainingEvents); - lastUrl = `${this.config.connectionURL}/eventsAfter/${contractID}/${sinceHeight}${Number.isInteger(requestLimit) ? `/${requestLimit}` : ""}`; - const eventsResponse = await this.config.fetch(lastUrl, { signal }); - if (!eventsResponse.ok) { - const msg = `${eventsResponse.status}: ${eventsResponse.statusText}`; - if (eventsResponse.status === 404 || eventsResponse.status === 410) { - throw new ChelErrorResourceGone(msg, { cause: eventsResponse.status }); + var hasAbortSignal = typeof AbortSignal === "function"; + var hasACAbortSignal = typeof AC.AbortSignal === "function"; + var AS = hasAbortSignal ? AbortSignal : hasACAbortSignal ? AC.AbortController : class AbortSignal { + constructor() { + this.aborted = false; + this._listeners = []; } - throw new ChelErrorUnexpectedHttpResponseCode(msg, { cause: eventsResponse.status }); - } - if (!eventsResponse.body) - throw new Error("Missing body"); - latestHeight = parseInt(eventsResponse.headers.get("shelter-headinfo-height"), 10); - if (!Number.isSafeInteger(latestHeight)) - throw new Error("Invalid latest height"); - requestCount++; - return eventsResponse.body.getReader(); - }; - if (!Number.isSafeInteger(sinceHeight) || sinceHeight < 0) { - throw new TypeError("Invalid since height value. Expected positive integer."); - } - const signal = this.abortController.signal; - let requestCount = 0; - let remainingEvents = limit ?? Number.POSITIVE_INFINITY; - let eventsStreamReader; - let latestHeight; - let state = "fetch"; - let requestLimit; - let count; - let buffer = ""; - let currentEvent; - const s = new ReadableStream({ - // The pull function is called whenever the internal buffer of the stream - // becomes empty and needs more data. - async pull(controller) { - try { - for (; ; ) { - switch (state) { - // When in 'fetch' state, initiate a new fetch request to obtain a - // stream reader for events. - case "fetch": { - eventsStreamReader = await fetchEventsStreamReader(); - state = "read-new-response"; - count = 0; - break; - } - case "read-eos": - // End of stream case - case "read-new-response": - // Just started reading a new response - case "read": { - const { done, value } = await eventsStreamReader.read(); - if (done) { - if (remainingEvents === 0 || sinceHeight >= latestHeight) { - controller.close(); - return; - } else if (state === "read-new-response" || buffer) { - throw new Error("Invalid response: done too early"); - } else { - state = "fetch"; - break; - } - } - if (!value) { - throw new Error("Invalid response: missing body"); - } - buffer = buffer + Buffer3.from(value).toString().trim(); - if (!buffer) - break; - if (state === "read-new-response") { - if (buffer[0] !== "[") { - throw new Error("Invalid response: no array start delimiter"); - } - buffer = buffer.slice(1); - } else if (state === "read-eos") { - throw new Error("Invalid data at the end of response"); - } - state = "events"; - break; - } - case "events": { - const nextIdx = buffer.search(/(?<=\s*)[,\]]/); - if (nextIdx < 0) { - state = "read"; - break; - } - let enqueued = false; - try { - const eventValue = buffer.slice(0, nextIdx).trim(); - if (eventValue) { - if (count === requestLimit) { - throw new Error("Received too many events"); - } - currentEvent = JSON.parse(b64ToStr(JSON.parse(eventValue))).message; - if (count === 0) { - const hash3 = SPMessage.deserializeHEAD(currentEvent).hash; - const height = SPMessage.deserializeHEAD(currentEvent).head.height; - if (height !== sinceHeight || sinceHash && sinceHash !== hash3) { - if (height === sinceHeight && sinceHash && sinceHash !== hash3) { - throw new ChelErrorForkedChain(`Forked chain: hash(${hash3}) !== since(${sinceHash})`); - } else { - throw new Error(`Unexpected data: hash(${hash3}) !== since(${sinceHash || ""}) or height(${height}) !== since(${sinceHeight})`); - } - } - } - if (count++ !== 0 || requestCount !== 0) { - controller.enqueue(currentEvent); - enqueued = true; - remainingEvents--; - } - } - if (buffer[nextIdx] === "]") { - if (currentEvent) { - const deserialized = SPMessage.deserializeHEAD(currentEvent); - sinceHeight = deserialized.head.height; - sinceHash = deserialized.hash; - state = "read-eos"; - } else { - state = "eod"; - } - buffer = buffer.slice(nextIdx + 1).trim(); - } else if (currentEvent) { - buffer = buffer.slice(nextIdx + 1).trimStart(); - } else { - throw new Error("Missing end delimiter"); - } - if (enqueued) { - return; - } - } catch (e2) { - console.error("[chelonia] Error during event parsing", e2); - throw e2; - } - break; - } - case "eod": { - if (remainingEvents === 0 || sinceHeight >= latestHeight) { - controller.close(); - } else { - throw new Error("Unexpected end of data"); - } - return; - } - } + dispatchEvent(type) { + if (type === "abort") { + this.aborted = true; + const e2 = { type, target: this }; + this.onabort(e2); + this._listeners.forEach((f) => f(e2), this); } - } catch (e2) { - console.error("[eventsAfter] Error", { lastUrl }, e2); - eventsStreamReader?.cancel("Error during pull").catch((e22) => { - console.error("Error canceling underlying event stream reader on error", e2, e22); - }); - throw e2; } - } - }); - if (stream) - return s; - return collectEventStream(s); -} -function buildShelterAuthorizationHeader(contractID, state) { - if (!state) - state = esm_default(this.config.stateSelector)[contractID]; - const SAKid = findKeyIdByName(state, "#sak"); - if (!SAKid) { - throw new Error(`Missing #sak in ${contractID}`); - } - const SAK = this.transientSecretKeys[SAKid]; - if (!SAK) { - throw new Error(`Missing secret #sak (${SAKid}) in ${contractID}`); - } - const deserializedSAK = typeof SAK === "string" ? deserializeKey(SAK) : SAK; - const nonceBytes = new Uint8Array(15); - globalThis.crypto.getRandomValues(nonceBytes); - const data = `${contractID} ${esm_default("chelonia/time")}.${Buffer3.from(nonceBytes).toString("base64")}`; - return `shelter ${data}.${sign(deserializedSAK, data)}`; -} -function verifyShelterAuthorizationHeader(authorization, rootState) { - const regex = /^shelter (([a-zA-Z0-9]+) ([0-9]+)\.([a-zA-Z0-9+/=]{20}))\.([a-zA-Z0-9+/=]+)$/i; - if (authorization.length > 1024) { - throw new Error("Authorization header too long"); - } - const matches = authorization.match(regex); - if (!matches) { - throw new Error("Unable to parse shelter authorization header"); - } - const [, data, contractID, timestamp, , signature] = matches; - if (Math.abs(parseInt(timestamp) - Date.now()) > 6e4) { - throw new Error("Invalid signature time range"); - } - if (!rootState) - rootState = esm_default("chelonia/rootState"); - if (!has(rootState, contractID)) { - throw new Error(`Contract ${contractID} from shelter authorization header not found`); - } - const SAKid = findKeyIdByName(rootState[contractID], "#sak"); - if (!SAKid) { - throw new Error(`Missing #sak in ${contractID}`); - } - const SAK = rootState[contractID]._vm.authorizedKeys[SAKid].data; - if (!SAK) { - throw new Error(`Missing secret #sak (${SAKid}) in ${contractID}`); - } - const deserializedSAK = deserializeKey(SAK); - verifySignature(deserializedSAK, data, signature); - return contractID; -} -var MAX_EVENTS_AFTER; -var copiedExistingData; -var findKeyIdByName; -var findForeignKeysByContractID; -var findRevokedKeyIdsByName; -var findSuitableSecretKeyId; -var findSuitablePublicKeyIds; -var validateActionPermissions; -var validateKeyPermissions; -var validateKeyAddPermissions; -var validateKeyDelPermissions; -var validateKeyUpdatePermissions; -var keyAdditionProcessor; -var subscribeToForeignKeyContracts; -var recreateEvent; -var getContractIDfromKeyId; -var clearObject; -var reactiveClearObject; -var checkCanBeGarbageCollected; -var collectEventStream; -var logEvtError; -var handleFetchResult; -var init_utils = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/utils.mjs"() { - init_esm7(); - init_esm(); - init_esm5(); - init_SPMessage(); - init_Secret(); - init_constants(); - init_errors3(); - init_events(); - init_functions(); - init_signedData(); - MAX_EVENTS_AFTER = Number.parseInt(process.env.MAX_EVENTS_AFTER || "", 10) || Infinity; - copiedExistingData = Symbol("copiedExistingData"); - findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight == null)?.id; - findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.foreignKey?.includes(contractID)).map((k) => k.id); - findRevokedKeyIdsByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys || {}).filter((k) => k.name === name && k._notAfterHeight != null).map((k) => k.id); - findSuitableSecretKeyId = (state, permissions, purposes, ringLevel, allowedActions) => { - return state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => { - return k._notAfterHeight == null && k.ringLevel <= (ringLevel ?? Number.POSITIVE_INFINITY) && esm_default("chelonia/haveSecretKey", k.id) && (Array.isArray(permissions) ? permissions.reduce((acc, permission) => acc && (k.permissions === "*" || k.permissions.includes(permission)), true) : permissions === k.permissions) && purposes.reduce((acc, purpose) => acc && k.purpose.includes(purpose), true) && (Array.isArray(allowedActions) ? allowedActions.reduce((acc, action) => acc && (k.allowedActions === "*" || !!k.allowedActions?.includes(action)), true) : allowedActions ? allowedActions === k.allowedActions : true); - }).sort((a, b) => b.ringLevel - a.ringLevel)[0]?.id; - }; - findSuitablePublicKeyIds = (state, permissions, purposes, ringLevel) => { - return state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.ringLevel <= (ringLevel ?? Number.POSITIVE_INFINITY) && (Array.isArray(permissions) ? permissions.reduce((acc, permission) => acc && (k.permissions === "*" || k.permissions.includes(permission)), true) : permissions === k.permissions) && purposes.reduce((acc, purpose) => acc && k.purpose.includes(purpose), true)).sort((a, b) => b.ringLevel - a.ringLevel).map((k) => k.id); - }; - validateActionPermissions = (msg, signingKey, state, opT, opV) => { - const data = isSignedData(opV) ? opV.valueOf() : opV; - if (signingKey.allowedActions !== "*" && (!Array.isArray(signingKey.allowedActions) || !signingKey.allowedActions.includes(data.action))) { - logEvtError(msg, `Signing key ${signingKey.id} is not allowed for action ${data.action}`); - return false; + onabort() { } - if (isSignedData(opV)) { - const s = opV; - const innerSigningKey = state._vm?.authorizedKeys?.[s.signingKeyId]; - if (!innerSigningKey && msg._direction === "outgoing") - return true; - if (!innerSigningKey || !Array.isArray(innerSigningKey.purpose) || !innerSigningKey.purpose.includes("sig") || innerSigningKey.permissions !== "*" && (!Array.isArray(innerSigningKey.permissions) || !innerSigningKey.permissions.includes(opT + "#inner"))) { - logEvtError(msg, `Signing key ${s.signingKeyId} is missing permissions for operation ${opT}`); - return false; + addEventListener(ev, fn) { + if (ev === "abort") { + this._listeners.push(fn); } - if (innerSigningKey.allowedActions !== "*" && (!Array.isArray(innerSigningKey.allowedActions) || !innerSigningKey.allowedActions.includes(data.action + "#inner"))) { - logEvtError(msg, `Signing key ${innerSigningKey.id} is not allowed for action ${data.action}`); - return false; + } + removeEventListener(ev, fn) { + if (ev === "abort") { + this._listeners = this._listeners.filter((f) => f !== fn); } } - return true; }; - validateKeyPermissions = (msg, config2, state, signingKeyId, opT, opV) => { - const signingKey = state._vm?.authorizedKeys?.[signingKeyId]; - if (!signingKey || !Array.isArray(signingKey.purpose) || !signingKey.purpose.includes("sig") || signingKey.permissions !== "*" && (!Array.isArray(signingKey.permissions) || !signingKey.permissions.includes(opT))) { - logEvtError(msg, `Signing key ${signingKeyId} is missing permissions for operation ${opT}`); - return false; - } - if (opT === SPMessage.OP_ACTION_UNENCRYPTED && !validateActionPermissions(msg, signingKey, state, opT, opV)) { - return false; + var warned = /* @__PURE__ */ new Set(); + var deprecatedOption = (opt, instead) => { + const code2 = `LRU_CACHE_OPTION_${opt}`; + if (shouldWarn(code2)) { + warn(code2, `${opt} option`, `options.${instead}`, LRUCache); } - if (!config2.skipActionProcessing && opT === SPMessage.OP_ACTION_ENCRYPTED && !validateActionPermissions(msg, signingKey, state, opT, opV.valueOf())) { - return false; + }; + var deprecatedMethod = (method, instead) => { + const code2 = `LRU_CACHE_METHOD_${method}`; + if (shouldWarn(code2)) { + const { prototype } = LRUCache; + const { get: get2 } = Object.getOwnPropertyDescriptor(prototype, method); + warn(code2, `${method} method`, `cache.${instead}()`, get2); } - return true; }; - validateKeyAddPermissions = function(contractID, signingKey, state, v2, skipPrivateCheck) { - const signingKeyPermissions = Array.isArray(signingKey.permissions) ? new Set(signingKey.permissions) : signingKey.permissions; - const signingKeyAllowedActions = Array.isArray(signingKey.allowedActions) ? new Set(signingKey.allowedActions) : signingKey.allowedActions; - if (!state._vm?.authorizedKeys?.[signingKey.id]) { - throw new Error("Singing key for OP_KEY_ADD or OP_KEY_UPDATE must exist in _vm.authorizedKeys. contractID=" + contractID + " signingKeyId=" + signingKey.id); + var deprecatedProperty = (field, instead) => { + const code2 = `LRU_CACHE_PROPERTY_${field}`; + if (shouldWarn(code2)) { + const { prototype } = LRUCache; + const { get: get2 } = Object.getOwnPropertyDescriptor(prototype, field); + warn(code2, `${field} property`, `cache.${instead}`, get2); } - const localSigningKey = state._vm.authorizedKeys[signingKey.id]; - v2.forEach((wk) => { - const data = this.config.unwrapMaybeEncryptedData(wk); - if (!data) - return; - const k = data.data; - if (!skipPrivateCheck && signingKey._private && !data.encryptionKeyId) { - throw new Error("Signing key is private but it tried adding a public key"); - } - if (!Number.isSafeInteger(k.ringLevel) || k.ringLevel < localSigningKey.ringLevel) { - throw new Error("Signing key has ringLevel " + localSigningKey.ringLevel + " but attempted to add or update a key with ringLevel " + k.ringLevel); - } - if (signingKeyPermissions !== "*") { - if (!Array.isArray(k.permissions) || !k.permissions.reduce((acc, cv) => acc && signingKeyPermissions.has(cv), true)) { - throw new Error("Unable to add or update a key with more permissions than the signing key. signingKey permissions: " + String(signingKey?.permissions) + "; key add permissions: " + String(k.permissions)); - } - } - if (signingKeyAllowedActions !== "*" && k.allowedActions) { - if (!signingKeyAllowedActions || !Array.isArray(k.allowedActions) || !k.allowedActions.reduce((acc, cv) => acc && signingKeyAllowedActions.has(cv), true)) { - throw new Error("Unable to add or update a key with more allowed actions than the signing key. signingKey allowed actions: " + String(signingKey?.allowedActions) + "; key add allowed actions: " + String(k.allowedActions)); - } - } - }); }; - validateKeyDelPermissions = function(contractID, signingKey, state, v2) { - if (!state._vm?.authorizedKeys?.[signingKey.id]) { - throw new Error("Singing key for OP_KEY_DEL must exist in _vm.authorizedKeys. contractID=" + contractID + " signingKeyId=" + signingKey.id); + var emitWarning = (...a) => { + typeof process === "object" && process && typeof process.emitWarning === "function" ? process.emitWarning(...a) : console.error(...a); + }; + var shouldWarn = (code2) => !warned.has(code2); + var warn = (code2, what, instead, fn) => { + warned.add(code2); + const msg = `The ${what} is deprecated. Please use ${instead} instead.`; + emitWarning(msg, "DeprecationWarning", code2, fn); + }; + var isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n); + var getUintArray = (max) => !isPosInt(max) ? null : max <= Math.pow(2, 8) ? Uint8Array : max <= Math.pow(2, 16) ? Uint16Array : max <= Math.pow(2, 32) ? Uint32Array : max <= Number.MAX_SAFE_INTEGER ? ZeroArray : null; + var ZeroArray = class extends Array { + constructor(size) { + super(size); + this.fill(0); } - const localSigningKey = state._vm.authorizedKeys[signingKey.id]; - v2.forEach((wid) => { - const data = this.config.unwrapMaybeEncryptedData(wid); - if (!data) - return; - const id = data.data; - const k = state._vm.authorizedKeys[id]; - if (!k) { - throw new Error("Nonexisting key ID " + id); - } - if (signingKey._private) { - throw new Error("Signing key is private"); - } - if (!k._private !== !data.encryptionKeyId) { - throw new Error("_private attribute must be preserved"); - } - if (!Number.isSafeInteger(k.ringLevel) || k.ringLevel < localSigningKey.ringLevel) { - throw new Error("Signing key has ringLevel " + localSigningKey.ringLevel + " but attempted to remove a key with ringLevel " + k.ringLevel); + }; + var Stack = class { + constructor(max) { + if (max === 0) { + return []; } - }); + const UintArray = getUintArray(max); + this.heap = new UintArray(max); + this.length = 0; + } + push(n) { + this.heap[this.length++] = n; + } + pop() { + return this.heap[--this.length]; + } }; - validateKeyUpdatePermissions = function(contractID, signingKey, state, v2) { - const updatedMap = /* @__PURE__ */ Object.create(null); - const keys = v2.map((wuk) => { - const data = this.config.unwrapMaybeEncryptedData(wuk); - if (!data) - return void 0; - const uk = data.data; - const existingKey = state._vm.authorizedKeys[uk.oldKeyId]; - if (!existingKey) { - throw new ChelErrorWarning("Missing old key ID " + uk.oldKeyId); + var LRUCache = class _LRUCache { + constructor(options2 = {}) { + const { + max = 0, + ttl, + ttlResolution = 1, + ttlAutopurge, + updateAgeOnGet, + updateAgeOnHas, + allowStale, + dispose, + disposeAfter, + noDisposeOnSet, + noUpdateTTL, + maxSize = 0, + maxEntrySize = 0, + sizeCalculation, + fetchMethod, + fetchContext, + noDeleteOnFetchRejection, + noDeleteOnStaleGet + } = options2; + const { length: length2, maxAge: maxAge2, stale } = options2 instanceof _LRUCache ? {} : options2; + if (max !== 0 && !isPosInt(max)) { + throw new TypeError("max option must be a nonnegative integer"); } - if (!existingKey._private !== !data.encryptionKeyId) { - throw new Error("_private attribute must be preserved"); + const UintArray = max ? getUintArray(max) : Array; + if (!UintArray) { + throw new Error("invalid max value: " + max); } - if (uk.name !== existingKey.name) { - throw new Error("Name cannot be updated"); + this.max = max; + this.maxSize = maxSize; + this.maxEntrySize = maxEntrySize || this.maxSize; + this.sizeCalculation = sizeCalculation || length2; + if (this.sizeCalculation) { + if (!this.maxSize && !this.maxEntrySize) { + throw new TypeError( + "cannot set sizeCalculation without setting maxSize or maxEntrySize" + ); + } + if (typeof this.sizeCalculation !== "function") { + throw new TypeError("sizeCalculation set to non-function"); + } } - if (!uk.id !== !uk.data) { - throw new Error("Both or none of the id and data attributes must be provided. Old key ID: " + uk.oldKeyId); + this.fetchMethod = fetchMethod || null; + if (this.fetchMethod && typeof this.fetchMethod !== "function") { + throw new TypeError( + "fetchMethod must be a function if specified" + ); } - if (uk.data && existingKey.meta?.private && !uk.meta?.private) { - throw new Error("Missing private key. Old key ID: " + uk.oldKeyId); + this.fetchContext = fetchContext; + if (!this.fetchMethod && fetchContext !== void 0) { + throw new TypeError( + "cannot set fetchContext without fetchMethod" + ); } - if (uk.id && uk.id !== uk.oldKeyId) { - updatedMap[uk.id] = uk.oldKeyId; + this.keyMap = /* @__PURE__ */ new Map(); + this.keyList = new Array(max).fill(null); + this.valList = new Array(max).fill(null); + this.next = new UintArray(max); + this.prev = new UintArray(max); + this.head = 0; + this.tail = 0; + this.free = new Stack(max); + this.initialFill = 1; + this.size = 0; + if (typeof dispose === "function") { + this.dispose = dispose; } - const updatedKey = omit2(existingKey, [ - "_notAfterHeight", - "_notBeforeHeight" - ]); - if (uk.permissions) { - updatedKey.permissions = uk.permissions; - } - if (uk.allowedActions) { - updatedKey.allowedActions = uk.allowedActions; - } - if (uk.purpose) { - updatedKey.purpose = uk.purpose; - } - if (uk.meta) { - updatedKey.meta = uk.meta; - } else if (updatedKey.meta) { - Object.defineProperty(updatedKey.meta, copiedExistingData, { value: true }); - } - if (uk.id) { - updatedKey.id = uk.id; - } - if (uk.data) { - updatedKey.data = uk.data; - } - return updatedKey; - }).filter(Boolean); - validateKeyAddPermissions.call(this, contractID, signingKey, state, keys, true); - return [keys, updatedMap]; - }; - keyAdditionProcessor = function(_msg, hash3, keys, state, contractID, _signingKey, internalSideEffectStack) { - const decryptedKeys = []; - const keysToPersist = []; - const storeSecretKey = (key, decryptedKey) => { - const decryptedDeserializedKey = deserializeKey(decryptedKey); - const transient = !!key.meta?.private?.transient; - esm_default("chelonia/storeSecretKeys", new Secret([ - { - key: decryptedDeserializedKey, - // We always set this to true because this could be done from - // an outgoing message - transient: true - } - ])); - if (!transient) { - keysToPersist.push({ key: decryptedDeserializedKey, transient }); + if (typeof disposeAfter === "function") { + this.disposeAfter = disposeAfter; + this.disposed = []; + } else { + this.disposeAfter = null; + this.disposed = null; } - }; - for (const wkey of keys) { - const data = this.config.unwrapMaybeEncryptedData(wkey); - if (!data) - continue; - const key = data.data; - let decryptedKey; - if (key.meta?.private?.content && !has(key.meta, copiedExistingData)) { - if (key.id && !esm_default("chelonia/haveSecretKey", key.id, !key.meta.private.transient)) { - const decryptedKeyResult = this.config.unwrapMaybeEncryptedData(key.meta.private.content); - if (decryptedKeyResult) { - if (decryptedKeyResult.encryptionKeyId == null) { - throw new Error("Expected encrypted data but got unencrypted data for key with ID: " + key.id); - } - decryptedKey = decryptedKeyResult.data; - decryptedKeys.push([key.id, decryptedKey]); - storeSecretKey(key, decryptedKey); + this.noDisposeOnSet = !!noDisposeOnSet; + this.noUpdateTTL = !!noUpdateTTL; + this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection; + if (this.maxEntrySize !== 0) { + if (this.maxSize !== 0) { + if (!isPosInt(this.maxSize)) { + throw new TypeError( + "maxSize must be a positive integer if specified" + ); } } - } - if (key.name === "#sak") { - if (data.encryptionKeyId) { - throw new Error("#sak may not be encrypted"); - } - if (key.permissions && (!Array.isArray(key.permissions) || key.permissions.length !== 0)) { - throw new Error("#sak may not have permissions"); - } - if (!Array.isArray(key.purpose) || key.purpose.length !== 1 || key.purpose[0] !== "sak") { - throw new Error("#sak must have exactly one purpose: 'sak'"); + if (!isPosInt(this.maxEntrySize)) { + throw new TypeError( + "maxEntrySize must be a positive integer if specified" + ); } - if (key.ringLevel !== 0) { - throw new Error("#sak must have ringLevel 0"); + this.initializeSizeTracking(); + } + this.allowStale = !!allowStale || !!stale; + this.noDeleteOnStaleGet = !!noDeleteOnStaleGet; + this.updateAgeOnGet = !!updateAgeOnGet; + this.updateAgeOnHas = !!updateAgeOnHas; + this.ttlResolution = isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1; + this.ttlAutopurge = !!ttlAutopurge; + this.ttl = ttl || maxAge2 || 0; + if (this.ttl) { + if (!isPosInt(this.ttl)) { + throw new TypeError( + "ttl must be a positive integer if specified" + ); } + this.initializeTTLTracking(); } - if (key.name.startsWith("#inviteKey-")) { - if (!state._vm.invites) - state._vm.invites = /* @__PURE__ */ Object.create(null); - const inviteSecret = decryptedKey || (has(this.transientSecretKeys, key.id) ? serializeKey(this.transientSecretKeys[key.id], true) : void 0); - state._vm.invites[key.id] = { - status: INVITE_STATUS.VALID, - initialQuantity: key.meta.quantity, - quantity: key.meta.quantity, - expires: key.meta.expires, - inviteSecret, - responses: [] - }; + if (this.max === 0 && this.ttl === 0 && this.maxSize === 0) { + throw new TypeError( + "At least one of max, maxSize, or ttl is required" + ); } - if (key.meta?.keyRequest?.contractID && findSuitableSecretKeyId(state, [SPMessage.OP_KEY_ADD], ["sig"])) { - const data2 = this.config.unwrapMaybeEncryptedData(key.meta.keyRequest.contractID); - if (data2 && internalSideEffectStack) { - const keyRequestContractID = data2.data; - const reference = this.config.unwrapMaybeEncryptedData(key.meta.keyRequest.reference); - internalSideEffectStack.push(() => { - esm_default("chelonia/private/queueEvent", keyRequestContractID, () => { - const rootState = esm_default(this.config.stateSelector); - const originatingContractState = rootState[contractID]; - if (esm_default("chelonia/contract/hasKeyShareBeenRespondedBy", originatingContractState, keyRequestContractID, reference)) { - return; - } - if (!has(rootState, keyRequestContractID)) { - this.config.reactiveSet(rootState, keyRequestContractID, /* @__PURE__ */ Object.create(null)); - } - const targetState = rootState[keyRequestContractID]; - if (!targetState._volatile) { - this.config.reactiveSet(targetState, "_volatile", /* @__PURE__ */ Object.create(null)); - } - if (!targetState._volatile.pendingKeyRequests) { - this.config.reactiveSet(rootState[keyRequestContractID]._volatile, "pendingKeyRequests", []); - } - if (targetState._volatile.pendingKeyRequests.some((pkr) => { - return pkr && pkr.contractID === contractID && pkr.hash === hash3; - })) { - return; - } - targetState._volatile.pendingKeyRequests.push({ - contractID, - name: key.name, - hash: hash3, - reference: reference?.data - }); - this.setPostSyncOp(contractID, "pending-keys-for-" + keyRequestContractID, [ - "okTurtles.events/emit", - CONTRACT_IS_PENDING_KEY_REQUESTS, - { contractID: keyRequestContractID } - ]); - }).catch((e2) => { - console.error("Error while setting or updating pendingKeyRequests", { contractID, keyRequestContractID, reference }, e2); - }); - }); + if (!this.ttlAutopurge && !this.max && !this.maxSize) { + const code2 = "LRU_CACHE_UNBOUNDED"; + if (shouldWarn(code2)) { + warned.add(code2); + const msg = "TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption."; + emitWarning(msg, "UnboundedCacheWarning", code2, _LRUCache); } } + if (stale) { + deprecatedOption("stale", "allowStale"); + } + if (maxAge2) { + deprecatedOption("maxAge", "ttl"); + } + if (length2) { + deprecatedOption("length", "sizeCalculation"); + } } - if (keysToPersist.length) { - internalSideEffectStack?.push(() => { - esm_default("chelonia/storeSecretKeys", new Secret(keysToPersist)); - }); + getRemainingTTL(key) { + return this.has(key, { updateAgeOnHas: false }) ? Infinity : 0; } - internalSideEffectStack?.push(() => subscribeToForeignKeyContracts.call(this, contractID, state)); - }; - subscribeToForeignKeyContracts = function(contractID, state) { - try { - Object.values(state._vm.authorizedKeys).filter((key) => !!key.foreignKey && findKeyIdByName(state, key.name) != null).forEach((key) => { - const foreignKey = String(key.foreignKey); - const fkUrl = new URL(foreignKey); - const foreignContract = fkUrl.pathname; - const foreignKeyName = fkUrl.searchParams.get("keyName"); - if (!foreignContract || !foreignKeyName) { - console.warn("Invalid foreign key: missing contract or key name", { - contractID, - keyId: key.id - }); - return; + initializeTTLTracking() { + this.ttls = new ZeroArray(this.max); + this.starts = new ZeroArray(this.max); + this.setItemTTL = (index, ttl, start = perf.now()) => { + this.starts[index] = ttl !== 0 ? start : 0; + this.ttls[index] = ttl; + if (ttl !== 0 && this.ttlAutopurge) { + const t = setTimeout(() => { + if (this.isStale(index)) { + this.delete(this.keyList[index]); + } + }, ttl + 1); + if (t.unref) { + t.unref(); + } } - const rootState = esm_default(this.config.stateSelector); - const signingKey = findSuitableSecretKeyId(state, [SPMessage.OP_KEY_DEL], ["sig"], key.ringLevel); - const canMirrorOperations = !!signingKey; - if (!canMirrorOperations) - return; - if (Array.isArray(rootState?.[foreignContract]?._volatile?.watch)) { - if (rootState[foreignContract]._volatile.watch.find((v2) => v2[0] === key.name && v2[1] === contractID)) { - return; + }; + this.updateItemAge = (index) => { + this.starts[index] = this.ttls[index] !== 0 ? perf.now() : 0; + }; + let cachedNow = 0; + const getNow = () => { + const n = perf.now(); + if (this.ttlResolution > 0) { + cachedNow = n; + const t = setTimeout( + () => cachedNow = 0, + this.ttlResolution + ); + if (t.unref) { + t.unref(); } } - if (!has(state._vm, "pendingWatch")) { - this.config.reactiveSet(state._vm, "pendingWatch", /* @__PURE__ */ Object.create(null)); + return n; + }; + this.getRemainingTTL = (key) => { + const index = this.keyMap.get(key); + if (index === void 0) { + return 0; } - if (!has(state._vm.pendingWatch, foreignContract)) { - this.config.reactiveSet(state._vm.pendingWatch, foreignContract, []); + return this.ttls[index] === 0 || this.starts[index] === 0 ? Infinity : this.starts[index] + this.ttls[index] - (cachedNow || getNow()); + }; + this.isStale = (index) => { + return this.ttls[index] !== 0 && this.starts[index] !== 0 && (cachedNow || getNow()) - this.starts[index] > this.ttls[index]; + }; + } + updateItemAge(index) { + } + setItemTTL(index, ttl, start) { + } + isStale(index) { + return false; + } + initializeSizeTracking() { + this.calculatedSize = 0; + this.sizes = new ZeroArray(this.max); + this.removeItemSize = (index) => { + this.calculatedSize -= this.sizes[index]; + this.sizes[index] = 0; + }; + this.requireSize = (k, v2, size, sizeCalculation) => { + if (!isPosInt(size)) { + if (sizeCalculation) { + if (typeof sizeCalculation !== "function") { + throw new TypeError("sizeCalculation must be a function"); + } + size = sizeCalculation(v2, k); + if (!isPosInt(size)) { + throw new TypeError( + "sizeCalculation return invalid (expect positive integer)" + ); + } + } else { + throw new TypeError( + "invalid size value (must be positive integer)" + ); + } } - if (!state._vm.pendingWatch[foreignContract].find(([n]) => n === foreignKeyName)) { - state._vm.pendingWatch[foreignContract].push([foreignKeyName, key.id]); + return size; + }; + this.addItemSize = (index, size) => { + this.sizes[index] = size; + const maxSize = this.maxSize - this.sizes[index]; + while (this.calculatedSize > maxSize) { + this.evict(true); } - this.setPostSyncOp(contractID, `watchForeignKeys-${contractID}`, [ - "chelonia/private/watchForeignKeys", - contractID - ]); - }); - } catch (e2) { - console.warn("Error at subscribeToForeignKeyContracts: " + (e2.message || e2)); - } - }; - recreateEvent = (entry, state, contractsState, disableAutoDedup) => { - const { HEAD: previousHEAD, height: previousHeight, previousKeyOp } = contractsState || {}; - if (!previousHEAD) { - throw new Error("recreateEvent: Giving up because the contract has been removed"); - } - const head = entry.head(); - const [opT, rawOpV] = entry.rawOp(); - const recreateOperation = (opT2, rawOpV2) => { - const opV = rawOpV2.valueOf(); - const recreateOperationInternal = (opT3, opV2) => { - let newOpV2; - if (opT3 === SPMessage.OP_KEY_ADD) { - if (!Array.isArray(opV2)) - throw new Error("Invalid message format"); - newOpV2 = opV2.filter((k) => { - const kId = k.valueOf().id; - return !has(state._vm.authorizedKeys, kId) || state._vm.authorizedKeys[kId]._notAfterHeight != null; - }); - if (newOpV2.length === 0) { - console.info("Omitting empty OP_KEY_ADD", { head }); - } else if (newOpV2.length === opV2.length) { - return opV2; + this.calculatedSize += this.sizes[index]; + }; + } + removeItemSize(index) { + } + addItemSize(index, size) { + } + requireSize(k, v2, size, sizeCalculation) { + if (size || sizeCalculation) { + throw new TypeError( + "cannot set size without setting maxSize or maxEntrySize on cache" + ); + } + } + *indexes({ allowStale = this.allowStale } = {}) { + if (this.size) { + for (let i2 = this.tail; true; ) { + if (!this.isValidIndex(i2)) { + break; } - } else if (opT3 === SPMessage.OP_KEY_DEL) { - if (!Array.isArray(opV2)) - throw new Error("Invalid message format"); - newOpV2 = opV2.filter((keyId2) => { - const kId = Object(keyId2).valueOf(); - return has(state._vm.authorizedKeys, kId) && state._vm.authorizedKeys[kId]._notAfterHeight == null; - }); - if (newOpV2.length === 0) { - console.info("Omitting empty OP_KEY_DEL", { head }); - } else if (newOpV2.length === opV2.length) { - return opV2; + if (allowStale || !this.isStale(i2)) { + yield i2; } - } else if (opT3 === SPMessage.OP_KEY_UPDATE) { - if (!Array.isArray(opV2)) - throw new Error("Invalid message format"); - newOpV2 = opV2.filter((k) => { - const oKId = k.valueOf().oldKeyId; - const nKId = k.valueOf().id; - return nKId == null || has(state._vm.authorizedKeys, oKId) && state._vm.authorizedKeys[oKId]._notAfterHeight == null; - }); - if (newOpV2.length === 0) { - console.info("Omitting empty OP_KEY_UPDATE", { head }); - } else if (newOpV2.length === opV2.length) { - return opV2; + if (i2 === this.head) { + break; + } else { + i2 = this.prev[i2]; + } + } + } + } + *rindexes({ allowStale = this.allowStale } = {}) { + if (this.size) { + for (let i2 = this.head; true; ) { + if (!this.isValidIndex(i2)) { + break; + } + if (allowStale || !this.isStale(i2)) { + yield i2; } - } else if (opT3 === SPMessage.OP_ATOMIC) { - if (!Array.isArray(opV2)) - throw new Error("Invalid message format"); - newOpV2 = opV2.map(([t, v2]) => [t, recreateOperationInternal(t, v2)]).filter(([, v2]) => !!v2); - if (newOpV2.length === 0) { - console.info("Omitting empty OP_ATOMIC", { head }); - } else if (newOpV2.length === opV2.length && newOpV2.reduce((acc, cv, i2) => acc && cv === opV2[i2], true)) { - return opV2; + if (i2 === this.tail) { + break; } else { - return newOpV2; + i2 = this.next[i2]; } - } else { - return opV2; } - }; - const newOpV = recreateOperationInternal(opT2, opV); - if (newOpV === opV) { - return rawOpV2; - } else if (newOpV === void 0) { - return; } - if (typeof rawOpV2.recreate !== "function") { - throw new Error("Unable to recreate operation"); + } + isValidIndex(index) { + return this.keyMap.get(this.keyList[index]) === index; + } + *entries() { + for (const i2 of this.indexes()) { + yield [this.keyList[i2], this.valList[i2]]; } - return rawOpV2.recreate(newOpV); - }; - const newRawOpV = disableAutoDedup ? rawOpV : recreateOperation(opT, rawOpV); - if (!newRawOpV) - return; - const newOp = [opT, newRawOpV]; - entry = SPMessage.cloneWith(head, newOp, { - previousKeyOp, - previousHEAD, - height: previousHeight + 1 - }); - return entry; - }; - getContractIDfromKeyId = (contractID, signingKeyId, state) => { - if (!signingKeyId) - return; - return signingKeyId && state._vm?.authorizedKeys?.[signingKeyId]?.foreignKey ? new URL(state._vm.authorizedKeys[signingKeyId].foreignKey).pathname : contractID; - }; - clearObject = (o2) => { - Object.keys(o2).forEach((k) => delete o2[k]); - }; - reactiveClearObject = (o2, fn) => { - Object.keys(o2).forEach((k) => fn(o2, k)); - }; - checkCanBeGarbageCollected = function(id) { - const rootState = esm_default(this.config.stateSelector); - return ( - // Check persistent references - (!has(rootState.contracts, id) || !rootState.contracts[id] || !has(rootState.contracts[id], "references")) && // Check ephemeral references - !has(this.ephemeralReferenceCount, id) && // Check foreign keys (i.e., that no keys from this contract are being watched) - (!has(rootState, id) || !has(rootState[id], "_volatile") || !has(rootState[id]._volatile, "watch") || rootState[id]._volatile.watch.length === 0 || rootState[id]._volatile.watch.filter(([, cID]) => this.subscriptionSet.has(cID)).length === 0) - ); - }; - collectEventStream = async (s) => { - const reader = s.getReader(); - const r = []; - for (; ; ) { - const { done, value } = await reader.read(); - if (done) - break; - r.push(value); } - return r; - }; - logEvtError = (msg, ...args) => { - if (msg._direction === "outgoing") { - console.warn(...args); - } else { - console.error(...args); + *rentries() { + for (const i2 of this.rindexes()) { + yield [this.keyList[i2], this.valList[i2]]; + } } - }; - handleFetchResult = (type) => { - return function(r) { - if (!r.ok) { - const msg = `${r.status}: ${r.statusText}`; - if (r.status === 404 || r.status === 410) { - throw new ChelErrorResourceGone(msg, { cause: r.status }); - } - throw new ChelErrorUnexpectedHttpResponseCode(msg, { cause: r.status }); + *keys() { + for (const i2 of this.indexes()) { + yield this.keyList[i2]; } - return r[type](); - }; - }; - } -}); -var supportsRequestStreams; -var streamToUint8Array; -var ArrayBufferToUint8ArrayStream; -var computeChunkDescriptors; -var fileStream; -var aes256gcmHandlers; -var noneHandlers; -var cipherHandlers; -var files_default; -var init_files = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/files.mjs"() { - init_encodeMultipartMessage(); - init_decrypt(); - init_encodings(); - init_encrypt(); - init_esm7(); - init_bytes(); - init_esm(); - init_esm5(); - init_functions(); - init_utils(); - supportsRequestStreams = typeof window !== "object" || (() => { - let duplexAccessed = false; - const hasContentType = new Request("", { - body: new ReadableStream(), - method: "POST", - get duplex() { - duplexAccessed = true; - return "half"; + } + *rkeys() { + for (const i2 of this.rindexes()) { + yield this.keyList[i2]; } - }).headers.has("content-type"); - return duplexAccessed && !hasContentType; - })(); - streamToUint8Array = async (s) => { - const reader = s.getReader(); - const chunks = []; - let length2 = 0; - for (; ; ) { - const result = await reader.read(); - if (result.done) - break; - chunks.push(coerce(result.value)); - length2 += result.value.byteLength; - } - const body = new Uint8Array(length2); - chunks.reduce((offset, chunk) => { - body.set(chunk, offset); - return offset + chunk.byteLength; - }, 0); - return body; - }; - ArrayBufferToUint8ArrayStream = async function(connectionURL, s) { - if (supportsRequestStreams === true) { - await this.config.fetch(`${connectionURL}/streams-test`, { - method: "POST", - body: new ReadableStream({ - start(c) { - c.enqueue(Buffer4.from("ok")); - c.close(); - } - }), - duplex: "half" - }).then((r) => { - if (!r.ok) - throw new Error("Unexpected response"); - supportsRequestStreams = 2; - }).catch(() => { - console.info("files: Disabling streams support because the streams test failed"); - supportsRequestStreams = false; - }); } - if (!supportsRequestStreams) { - return await streamToUint8Array(s); + *values() { + for (const i2 of this.indexes()) { + yield this.valList[i2]; + } } - return s.pipeThrough( - // eslint-disable-next-line no-undef - new TransformStream({ - transform(chunk, controller) { - controller.enqueue(coerce(chunk)); - } - }) - ); - }; - computeChunkDescriptors = (inStream) => { - let length2 = 0; - const [lengthStream, cidStream] = inStream.tee(); - const lengthPromise = new Promise((resolve82, reject) => { - lengthStream.pipeTo(new WritableStream({ - write(chunk) { - length2 += chunk.byteLength; - }, - close() { - resolve82(length2); - }, - abort(reason) { - reject(reason); - } - })); - }); - const cidPromise = createCIDfromStream(cidStream, multicodes.SHELTER_FILE_CHUNK); - return Promise.all([lengthPromise, cidPromise]); - }; - fileStream = (chelonia, manifest2) => { - const dataGenerator = async function* () { - let readSize = 0; - for (const chunk of manifest2.chunks) { - if (!Array.isArray(chunk) || typeof chunk[0] !== "number" || typeof chunk[1] !== "string") { - throw new Error("Invalid chunk descriptor"); - } - const chunkResponse = await chelonia.config.fetch(`${chelonia.config.connectionURL}/file/${chunk[1]}`, { - method: "GET", - signal: chelonia.abortController.signal - }); - if (!chunkResponse.ok) { - throw new Error("Unable to retrieve manifest"); - } - const chunkBinary = await chunkResponse.arrayBuffer(); - if (chunkBinary.byteLength !== chunk[0]) - throw new Error("mismatched chunk size"); - readSize += chunkBinary.byteLength; - if (readSize > manifest2.size) - throw new Error("read size exceeds declared size"); - if (createCID(coerce(chunkBinary), multicodes.SHELTER_FILE_CHUNK) !== chunk[1]) { - throw new Error("mismatched chunk hash"); - } - yield chunkBinary; - } - if (readSize !== manifest2.size) - throw new Error("mismatched size"); - }; - const dataIterator = dataGenerator(); - return new ReadableStream({ - async pull(controller) { - try { - const chunk = await dataIterator.next(); - if (chunk.done) { - controller.close(); - return; - } - controller.enqueue(chunk.value); - } catch (e2) { - controller.error(e2); - } + *rvalues() { + for (const i2 of this.rindexes()) { + yield this.valList[i2]; } - }); - }; - aes256gcmHandlers = { - upload: (_chelonia, manifestOptions) => { - const params = manifestOptions["cipher-params"]; - let IKM = params?.IKM; - const recordSize = params?.rs ?? 1 << 16; - if (!IKM) { - IKM = new Uint8Array(33); - self.crypto.getRandomValues(IKM); - } - const keyId2 = blake32Hash("aes256gcm-keyId" + blake32Hash(IKM)).slice(-8); - const binaryKeyId = Buffer4.from(keyId2); - return { - cipherParams: { - keyId: keyId2 - }, - streamHandler: async (stream) => { - return await K(e, stream, recordSize, binaryKeyId, IKM); - }, - downloadParams: { - IKM: Buffer4.from(IKM).toString("base64"), - rs: recordSize + } + [Symbol.iterator]() { + return this.entries(); + } + find(fn, getOptions = {}) { + for (const i2 of this.indexes()) { + if (fn(this.valList[i2], this.keyList[i2], this)) { + return this.get(this.keyList[i2], getOptions); } - }; - }, - download: (chelonia, downloadParams, manifest2) => { - const IKMb64 = downloadParams.IKM; - if (!IKMb64) { - throw new Error("Missing IKM in downloadParams"); } - const IKM = Buffer4.from(IKMb64, "base64"); - const keyId2 = blake32Hash("aes256gcm-keyId" + blake32Hash(IKM)).slice(-8); - if (!manifest2["cipher-params"] || !manifest2["cipher-params"].keyId) { - throw new Error("Missing cipher-params"); + } + forEach(fn, thisp = this) { + for (const i2 of this.indexes()) { + fn.call(thisp, this.valList[i2], this.keyList[i2], this); } - if (keyId2 !== manifest2["cipher-params"].keyId) { - throw new Error("Key ID mismatch"); + } + rforEach(fn, thisp = this) { + for (const i2 of this.rindexes()) { + fn.call(thisp, this.valList[i2], this.keyList[i2], this); } - const maxRecordSize = downloadParams.rs ?? 1 << 27; - return { - payloadHandler: async () => { - const bytes = await streamToUint8Array(S(e, fileStream(chelonia, manifest2), (actualKeyId) => { - if (Buffer4.from(actualKeyId).toString() !== keyId2) { - throw new Error("Invalid key ID"); - } - return IKM; - }, maxRecordSize)); - return new Blob([bytes], { type: manifest2.type || "application/octet-stream" }); - } - }; } - }; - noneHandlers = { - upload: () => { - return { - cipherParams: void 0, - streamHandler: (stream) => { - return stream; - }, - downloadParams: void 0 - }; - }, - download: (chelonia, _downloadParams, manifest2) => { - return { - payloadHandler: async () => { - const bytes = await streamToUint8Array(fileStream(chelonia, manifest2)); - return new Blob([bytes], { type: manifest2.type || "application/octet-stream" }); - } - }; + get prune() { + deprecatedMethod("prune", "purgeStale"); + return this.purgeStale; } - }; - cipherHandlers = { - aes256gcm: aes256gcmHandlers, - none: noneHandlers - }; - files_default = esm_default("sbp/selectors/register", { - "chelonia/fileUpload": async function(chunks, manifestOptions, { billableContractID } = {}) { - if (!Array.isArray(chunks)) - chunks = [chunks]; - const chunkDescriptors = []; - const cipherHandler = await cipherHandlers[manifestOptions.cipher]?.upload?.(this, manifestOptions); - if (!cipherHandler) - throw new Error("Unsupported cipher"); - const cipherParams = cipherHandler.cipherParams; - const transferParts = await Promise.all(chunks.map(async (chunk, i2) => { - const stream2 = chunk.stream(); - const encryptedStream = await cipherHandler.streamHandler(stream2); - const [body, s] = encryptedStream.tee(); - chunkDescriptors.push(computeChunkDescriptors(s)); - return { - headers: new Headers([ - ["content-disposition", `form-data; name="${i2}"; filename="${i2}"`], - ["content-type", "application/octet-stream"] - ]), - body - }; - })); - transferParts.push({ - headers: new Headers([ - ["content-disposition", 'form-data; name="manifest"; filename="manifest.json"'], - ["content-type", "application/vnd.shelter.filemanifest"] - ]), - body: new ReadableStream({ - async start(controller) { - const chunks2 = await Promise.all(chunkDescriptors); - const manifest2 = { - version: "1.0.0", - // ?? undefined coerces null and undefined to undefined - // This ensures that null or undefined values don't make it to the - // JSON (otherwise, null values _would_ be stringified as 'null') - type: manifestOptions.type ?? void 0, - meta: manifestOptions.meta ?? void 0, - cipher: manifestOptions.cipher, - "cipher-params": cipherParams, - size: chunks2.reduce((acc, [cv]) => acc + cv, 0), - chunks: chunks2, - "name-map": manifestOptions["name-map"] ?? void 0, - alternatives: manifestOptions.alternatives ?? void 0 - }; - controller.enqueue(Buffer4.from(JSON.stringify(manifest2))); - controller.close(); - } - }) - }); - const boundary = typeof self.crypto?.randomUUID === "function" ? self.crypto.randomUUID() : new Array(36).fill("").map(() => "abcdefghijklmnopqrstuvwxyz"[(0, Math.random)() * 26 | 0]).join(""); - const stream = x(boundary, transferParts); - const deletionToken = "deletionToken" + generateSalt(); - const deletionTokenHash = blake32Hash(deletionToken); - const uploadResponse = await this.config.fetch(`${this.config.connectionURL}/file`, { - method: "POST", - signal: this.abortController.signal, - body: await ArrayBufferToUint8ArrayStream.call(this, this.config.connectionURL, stream), - headers: new Headers([ - ...billableContractID ? [["authorization", buildShelterAuthorizationHeader.call(this, billableContractID)]] : [], - ["content-type", `multipart/form-data; boundary=${boundary}`], - ["shelter-deletion-token-digest", deletionTokenHash] - ]), - duplex: "half" - }); - if (!uploadResponse.ok) - throw new Error("Error uploading file"); - return { - download: { - manifestCid: await uploadResponse.text(), - downloadParams: cipherHandler.downloadParams - }, - delete: deletionToken - }; - }, - "chelonia/fileDownload": async function(downloadOptions, manifestChecker) { - const { manifestCid, downloadParams } = downloadOptions.valueOf(); - const manifestResponse = await this.config.fetch(`${this.config.connectionURL}/file/${manifestCid}`, { - method: "GET", - signal: this.abortController.signal - }); - if (!manifestResponse.ok) { - throw new Error("Unable to retrieve manifest"); - } - const manifestBinary = await manifestResponse.arrayBuffer(); - if (createCID(coerce(manifestBinary), multicodes.SHELTER_FILE_MANIFEST) !== manifestCid) { - throw new Error("mismatched manifest hash"); - } - const manifest2 = JSON.parse(Buffer4.from(manifestBinary).toString()); - if (typeof manifest2 !== "object") - throw new Error("manifest format is invalid"); - if (manifest2.version !== "1.0.0") - throw new Error("unsupported manifest version"); - if (!Array.isArray(manifest2.chunks)) - throw new Error("missing required field: chunks"); - if (manifestChecker) { - const proceed = await manifestChecker?.(manifest2); - if (!proceed) - return false; - } - const cipherHandler = await cipherHandlers[manifest2.cipher]?.download?.(this, downloadParams, manifest2); - if (!cipherHandler) - throw new Error("Unsupported cipher"); - return cipherHandler.payloadHandler(); - }, - "chelonia/fileDelete": async function(manifestCid, credentials = {}) { - if (!manifestCid) { - throw new TypeError("A manifest CID must be provided"); - } - if (!Array.isArray(manifestCid)) - manifestCid = [manifestCid]; - return await Promise.allSettled(manifestCid.map(async (cid) => { - const hasCredential = has(credentials, cid); - const hasToken = has(credentials[cid], "token") && credentials[cid].token; - const hasBillableContractID = has(credentials[cid], "billableContractID") && credentials[cid].billableContractID; - if (!hasCredential || hasToken === hasBillableContractID) { - throw new TypeError(`Either a token or a billable contract ID must be provided for ${cid}`); - } - const response = await this.config.fetch(`${this.config.connectionURL}/deleteFile/${cid}`, { - method: "POST", - signal: this.abortController.signal, - headers: new Headers([ - [ - "authorization", - hasToken ? `bearer ${credentials[cid].token.valueOf()}` : buildShelterAuthorizationHeader.call(this, credentials[cid].billableContractID) - ] - ]) - }); - if (!response.ok) { - throw new Error(`Unable to delete file ${cid}`); + purgeStale() { + let deleted = false; + for (const i2 of this.rindexes({ allowStale: true })) { + if (this.isStale(i2)) { + this.delete(this.keyList[i2]); + deleted = true; } - })); - } - }); - } -}); -var headPrefix; -var getContractIdFromLogHead; -var getLogHead; -var checkKey; -var parsePrefixableKey; -var prefixHandlers; -var dbPrimitiveSelectors; -var db_default; -var init_db = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/db.mjs"() { - init_esm3(); - init_esm2(); - init_esm(); - init_SPMessage(); - init_errors3(); - headPrefix = "head="; - getContractIdFromLogHead = (key) => { - if (!key.startsWith(headPrefix)) - return; - return key.slice(headPrefix.length); - }; - getLogHead = (contractID) => `${headPrefix}${contractID}`; - checkKey = (key) => { - if (/[\x00-\x1f\x7f\t\\/<>:"|?*]/.test(key)) { - throw new Error(`bad key: ${JSON.stringify(key)}`); - } - }; - parsePrefixableKey = (key) => { - const i2 = key.indexOf(":"); - if (i2 === -1) { - return ["", key]; - } - const prefix = key.slice(0, i2 + 1); - if (prefix in prefixHandlers) { - return [prefix, key.slice(prefix.length)]; - } - throw new ChelErrorDBConnection(`Unknown prefix in '${key}'.`); - }; - prefixHandlers = { - // Decode buffers, but don't transform other values. - "": (value) => Buffer5.isBuffer(value) ? value.toString("utf8") : value, - "any:": (value) => value - /* - // 2025-03-24: Commented out because it's not used; currently, only `any:` - // is used in the `/file` route. - // Throw if the value if not a buffer. - 'blob:': value => { - if (Buffer.isBuffer(value)) { - return value - } - throw new ChelErrorDBConnection('Unexpected value: expected a buffer.') - } - */ - }; - esm_default("sbp/selectors/unsafe", ["chelonia.db/get", "chelonia.db/set", "chelonia.db/delete", "chelonia.db/iterKeys", "chelonia.db/keyCount"]); - dbPrimitiveSelectors = process.env.LIGHTWEIGHT_CLIENT === "true" ? { - "chelonia.db/get": function(key) { - const id = getContractIdFromLogHead(key); - if (!id) - return Promise.resolve(); - const state = esm_default("chelonia/rootState").contracts[id]; - const value = state?.HEAD ? JSON.stringify({ - HEAD: state.HEAD, - height: state.height, - previousKeyOp: state.previousKeyOp - }) : void 0; - return Promise.resolve(value); - }, - "chelonia.db/set": function() { - return Promise.resolve(); - }, - "chelonia.db/delete": function() { - return Promise.resolve(true); - }, - "chelonia.db/iterKeys": async function* () { - }, - "chelonia.db/keyCount": function() { - return Promise.resolve(0); - } - } : { - // eslint-disable-next-line require-await - "chelonia.db/get": async function(prefixableKey) { - const [prefix, key] = parsePrefixableKey(prefixableKey); - const value = esm_default("okTurtles.data/get", key); - if (value === void 0) { - return; } - return prefixHandlers[prefix](value); - }, - // eslint-disable-next-line require-await - "chelonia.db/set": async function(key, value) { - checkKey(key); - return esm_default("okTurtles.data/set", key, value); - }, - // eslint-disable-next-line require-await - "chelonia.db/delete": async function(key) { - return esm_default("okTurtles.data/delete", key); - }, - "chelonia.db/iterKeys": async function* () { - yield* esm_default("okTurtles.data/iterKeys"); - }, - "chelonia.db/keyCount": function() { - return Promise.resolve(esm_default("okTurtles.data/keyCount")); + return deleted; } - }; - db_default = esm_default("sbp/selectors/register", { - ...dbPrimitiveSelectors, - "chelonia/db/getEntryMeta": async (contractID, height) => { - const entryMetaJson = await esm_default("chelonia.db/get", `_private_hidx=${contractID}#${height}`); - if (!entryMetaJson) - return; - return JSON.parse(entryMetaJson); - }, - "chelonia/db/setEntryMeta": async (contractID, height, entryMeta) => { - const entryMetaJson = JSON.stringify(entryMeta); - await esm_default("chelonia.db/set", `_private_hidx=${contractID}#${height}`, entryMetaJson); - }, - "chelonia/db/latestHEADinfo": async (contractID) => { - const r = await esm_default("chelonia.db/get", getLogHead(contractID)); - return r && JSON.parse(r); - }, - "chelonia/db/deleteLatestHEADinfo": (contractID) => { - return esm_default("chelonia.db/set", getLogHead(contractID), ""); - }, - "chelonia/db/getEntry": async function(hash3) { - try { - const value = await esm_default("chelonia.db/get", hash3); - if (!value) - throw new Error(`no entry for ${hash3}!`); - return SPMessage.deserialize(value, this.transientSecretKeys, void 0, this.config.unwrapMaybeEncryptedData); - } catch (e2) { - throw new ChelErrorDBConnection(`${e2.name} during getEntry: ${e2.message}`); - } - }, - "chelonia/db/addEntry": function(entry) { - return esm_default("okTurtles.eventQueue/queueEvent", `chelonia/db/${entry.contractID()}`, ["chelonia/private/db/addEntry", entry]); - }, - // NEVER call this directly yourself! _always_ call 'chelonia/db/addEntry' instead - "chelonia/private/db/addEntry": async function(entry) { - try { - const { previousHEAD: entryPreviousHEAD, previousKeyOp: entryPreviousKeyOp, height: entryHeight } = entry.head(); - const contractID = entry.contractID(); - if (await esm_default("chelonia.db/get", entry.hash())) { - console.warn(`[chelonia.db] entry exists: ${entry.hash()}`); - return entry.hash(); - } - const HEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); - if (!entry.isFirstMessage()) { - if (!HEADinfo) { - throw new Error(`No latest HEAD for ${contractID} when attempting to process entry with previous HEAD ${entryPreviousHEAD} at height ${entryHeight}`); - } - const { HEAD: contractHEAD, previousKeyOp: contractPreviousKeyOp, height: contractHeight } = HEADinfo; - if (entryPreviousHEAD !== contractHEAD) { - console.warn(`[chelonia.db] bad previousHEAD: ${entryPreviousHEAD}! Expected: ${contractHEAD} for contractID: ${contractID}`); - throw new ChelErrorDBBadPreviousHEAD(`bad previousHEAD: ${entryPreviousHEAD}. Expected ${contractHEAD} for contractID: ${contractID}`); - } else if (entryPreviousKeyOp !== contractPreviousKeyOp) { - console.error(`[chelonia.db] bad previousKeyOp: ${entryPreviousKeyOp}! Expected: ${contractPreviousKeyOp} for contractID: ${contractID}`); - throw new ChelErrorDBBadPreviousHEAD(`bad previousKeyOp: ${entryPreviousKeyOp}. Expected ${contractPreviousKeyOp} for contractID: ${contractID}`); - } else if (!Number.isSafeInteger(entryHeight) || entryHeight !== contractHeight + 1) { - console.error(`[chelonia.db] bad height: ${entryHeight}! Expected: ${contractHeight + 1} for contractID: ${contractID}`); - throw new ChelErrorDBBadPreviousHEAD(`[chelonia.db] bad height: ${entryHeight}! Expected: ${contractHeight + 1} for contractID: ${contractID}`); - } - } else { - if (HEADinfo) { - console.error(`[chelonia.db] bad previousHEAD: ${entryPreviousHEAD}! Expected: for contractID: ${contractID}`); - throw new ChelErrorDBBadPreviousHEAD(`bad previousHEAD: ${entryPreviousHEAD}. Expected for contractID: ${contractID}`); - } else if (entryHeight !== 0) { - console.error(`[chelonia.db] bad height: ${entryHeight}! Expected: 0 for contractID: ${contractID}`); - throw new ChelErrorDBBadPreviousHEAD(`[chelonia.db] bad height: ${entryHeight}! Expected: 0 for contractID: ${contractID}`); - } + dump() { + const arr = []; + for (const i2 of this.indexes({ allowStale: true })) { + const key = this.keyList[i2]; + const v2 = this.valList[i2]; + const value = this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; + const entry = { value }; + if (this.ttls) { + entry.ttl = this.ttls[i2]; + const age = perf.now() - this.starts[i2]; + entry.start = Math.floor(Date.now() - age); } - await esm_default("chelonia.db/set", entry.hash(), entry.serialize()); - await esm_default("chelonia.db/set", getLogHead(contractID), JSON.stringify({ - HEAD: entry.hash(), - previousKeyOp: entry.isKeyOp() ? entry.hash() : entry.previousKeyOp(), - height: entry.height() - })); - console.debug(`[chelonia.db] HEAD for ${contractID} updated to:`, entry.hash()); - await esm_default("chelonia/db/setEntryMeta", contractID, entryHeight, { - // The hash is used for reverse lookups (height to CID) - hash: entry.hash(), - // The date isn't currently used, but will be used for filtering messages - date: (/* @__PURE__ */ new Date()).toISOString(), - // isKeyOp is used for filtering messages (the actual filtering is - // done more efficiently a separate index key, but `isKeyOp` allows - // us to bootstrap this process without having to load the full message) - // The separate index key bears the prefix `_private_keyop_idx_`. - ...entry.isKeyOp() && { isKeyOp: true } - }); - return entry.hash(); - } catch (e2) { - if (e2.name.includes("ErrorDB")) { - throw e2; + if (this.sizes) { + entry.size = this.sizes[i2]; } - throw new ChelErrorDBConnection(`${e2.name} during addEntry: ${e2.message}`); + arr.unshift([key, entry]); } - }, - "chelonia/db/lastEntry": async function(contractID) { - try { - const latestHEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); - if (!latestHEADinfo) - throw new Error(`contract ${contractID} has no latest hash!`); - return esm_default("chelonia/db/getEntry", latestHEADinfo.HEAD); - } catch (e2) { - throw new ChelErrorDBConnection(`${e2.name} during lastEntry: ${e2.message}`); + return arr; + } + load(arr) { + this.clear(); + for (const [key, entry] of arr) { + if (entry.start) { + const age = Date.now() - entry.start; + entry.start = perf.now() - age; + } + this.set(key, entry.value, entry); } } - }); - } -}); -var missingDecryptionKeyIdsMap; -var getMsgMeta; -var keysToMap; -var keyRotationHelper; -var internals_default; -var eventsToReingest; -var reprocessDebounced; -var handleEvent; -var notImplemented; -var init_internals = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/internals.mjs"() { - init_esm(); - init_functions(); - init_esm5(); - init_SPMessage(); - init_Secret(); - init_constants(); - init_esm7(); - init_db(); - init_encryptedData(); - init_errors3(); - init_events(); - init_utils(); - init_signedData(); - missingDecryptionKeyIdsMap = /* @__PURE__ */ new WeakMap(); - getMsgMeta = function(message, contractID, state, index) { - const signingKeyId = message.signingKeyId(); - let innerSigningKeyId = null; - const config2 = this.config; - const result = { - signingKeyId, - get signingContractID() { - return getContractIDfromKeyId(contractID, signingKeyId, state); - }, - get innerSigningKeyId() { - if (innerSigningKeyId === null) { - const value = message.message(); - const data = config2.unwrapMaybeEncryptedData(value); - if (data?.data && isSignedData(data.data)) { - innerSigningKeyId = data.data.signingKeyId; + dispose(v2, k, reason) { + } + set(k, v2, { + ttl = this.ttl, + start, + noDisposeOnSet = this.noDisposeOnSet, + size = 0, + sizeCalculation = this.sizeCalculation, + noUpdateTTL = this.noUpdateTTL + } = {}) { + size = this.requireSize(k, v2, size, sizeCalculation); + if (this.maxEntrySize && size > this.maxEntrySize) { + return this; + } + let index = this.size === 0 ? void 0 : this.keyMap.get(k); + if (index === void 0) { + index = this.newIndex(); + this.keyList[index] = k; + this.valList[index] = v2; + this.keyMap.set(k, index); + this.next[this.tail] = index; + this.prev[index] = this.tail; + this.tail = index; + this.size++; + this.addItemSize(index, size); + noUpdateTTL = false; + } else { + const oldVal = this.valList[index]; + if (v2 !== oldVal) { + if (this.isBackgroundFetch(oldVal)) { + oldVal.__abortController.abort(); } else { - innerSigningKeyId = void 0; + if (!noDisposeOnSet) { + this.dispose(oldVal, k, "set"); + if (this.disposeAfter) { + this.disposed.push([oldVal, k, "set"]); + } + } } - return innerSigningKeyId; + this.removeItemSize(index); + this.valList[index] = v2; + this.addItemSize(index, size); } - }, - get innerSigningContractID() { - return getContractIDfromKeyId(contractID, result.innerSigningKeyId, state); - }, - index - }; - return result; - }; - keysToMap = function(keys_, height, authorizedKeys) { - const keys = keys_.map((key) => { - const data = this.config.unwrapMaybeEncryptedData(key); - if (!data) - return void 0; - if (data.encryptionKeyId) { - data.data._private = data.encryptionKeyId; - } - return data.data; - }).filter(Boolean); - const keysCopy = cloneDeep(keys); - return Object.fromEntries(keysCopy.map((key) => { - key._notBeforeHeight = height; - if (authorizedKeys?.[key.id]) { - if (authorizedKeys[key.id]._notAfterHeight == null) { - throw new ChelErrorKeyAlreadyExists(`Cannot set existing unrevoked key: ${key.id}`); - } - key._notBeforeHeight = Math.min(height, authorizedKeys[key.id]._notBeforeHeight ?? 0); - } else { - key._notBeforeHeight = height; + this.moveToTail(index); } - delete key._notAfterHeight; - return [key.id, key]; - })); - }; - keyRotationHelper = (contractID, state, config2, updatedKeysMap, requiredPermissions, outputSelector, outputMapper, internalSideEffectStack) => { - if (!internalSideEffectStack || !Array.isArray(state._volatile?.watch)) - return; - const rootState = esm_default(config2.stateSelector); - const watchMap = /* @__PURE__ */ Object.create(null); - state._volatile.watch.forEach(([name, cID]) => { - if (!updatedKeysMap[name] || watchMap[cID] === null) { - return; + if (ttl !== 0 && this.ttl === 0 && !this.ttls) { + this.initializeTTLTracking(); } - if (!watchMap[cID]) { - if (!rootState.contracts[cID]?.type || !findSuitableSecretKeyId(rootState[cID], [SPMessage.OP_KEY_UPDATE], ["sig"])) { - watchMap[cID] = null; - return; - } - watchMap[cID] = []; + if (!noUpdateTTL) { + this.setItemTTL(index, ttl, start); } - watchMap[cID].push(name); - }); - Object.entries(watchMap).forEach(([cID, names]) => { - if (!Array.isArray(names) || !names.length) - return; - const [keyNamesToUpdate, signingKeyId] = names.map((name) => { - const foreignContractKey = rootState[cID]?._vm?.authorizedKeys?.[updatedKeysMap[name].oldKeyId]; - if (!foreignContractKey) - return void 0; - const signingKeyId2 = findSuitableSecretKeyId(rootState[cID], requiredPermissions, ["sig"], foreignContractKey.ringLevel); - if (signingKeyId2) { - return [ - [name, foreignContractKey.name], - signingKeyId2, - rootState[cID]._vm.authorizedKeys[signingKeyId2].ringLevel - ]; + if (this.disposeAfter) { + while (this.disposed.length) { + this.disposeAfter(...this.disposed.shift()); } - return void 0; - }).filter(Boolean).reduce((acc, [name, signingKeyId2, ringLevel]) => { - acc[0].push(name); - return ringLevel < acc[2] ? [acc[0], signingKeyId2, ringLevel] : acc; - }, [[], void 0, Number.POSITIVE_INFINITY]); - if (!signingKeyId) - return; - const contractName = rootState.contracts[cID]?.type; - internalSideEffectStack?.push(() => { - esm_default(outputSelector, { - contractID: cID, - contractName, - data: keyNamesToUpdate.map(outputMapper).map((v2) => { - return v2; - }), - signingKeyId - }).catch((e2) => { - console.warn(`Error mirroring key operation (${outputSelector}) from ${contractID} to ${cID}: ${e2?.message || e2}`); - }); - }); - }); - }; - internals_default = esm_default("sbp/selectors/register", { - // DO NOT CALL ANY OF THESE YOURSELF! - "chelonia/private/state": function() { - return this.state; - }, - "chelonia/private/invoke": function(instance, invocation) { - if (this._instance !== instance) { - console.info("['chelonia/private/invoke] Not proceeding with invocation as Chelonia was restarted", { invocation }); - return; } - if (Array.isArray(invocation)) { - return esm_default(...invocation); - } else if (typeof invocation === "function") { - return invocation(); - } else { - throw new TypeError(`[chelonia/private/invoke] Expected invocation to be an array or a function. Saw ${typeof invocation} instead.`); - } - }, - "chelonia/private/queueEvent": function(queueName, invocation) { - return esm_default("okTurtles.eventQueue/queueEvent", queueName, [ - "chelonia/private/invoke", - this._instance, - invocation - ]); - }, - "chelonia/private/verifyManifestSignature": function(contractName, manifestHash, manifest2) { - if (!has(manifest2, "signature") || typeof manifest2.signature.keyId !== "string" || typeof manifest2.signature.value !== "string") { - throw new Error(`Invalid or missing signature field for manifest ${manifestHash} (named ${contractName})`); + return this; + } + newIndex() { + if (this.size === 0) { + return this.tail; } - const rootState = esm_default(this.config.stateSelector); - if (!has(rootState, "contractSigningKeys")) { - this.config.reactiveSet(rootState, "contractSigningKeys", /* @__PURE__ */ Object.create(null)); - } - const contractNameLookupKey = `name:${contractName}`; - let signatureValidated = false; - if (process.env.UNSAFE_TRUST_ALL_MANIFEST_SIGNING_KEYS !== "true" && has(rootState.contractSigningKeys, contractNameLookupKey)) { - console.info(`[chelonia] verifying signature for ${manifestHash} with an existing key`); - if (!has(rootState.contractSigningKeys[contractNameLookupKey], manifest2.signature.keyId)) { - console.error(`The manifest with ${manifestHash} (named ${contractName}) claims to be signed with a key with ID ${manifest2.signature.keyId}, which is not trusted. The trusted key IDs for this name are:`, Object.keys(rootState.contractSigningKeys[contractNameLookupKey])); - throw new Error(`Invalid or missing signature in manifest ${manifestHash} (named ${contractName}). It claims to be signed with a key with ID ${manifest2.signature.keyId}, which has not been authorized for this contract before.`); - } - const signingKey = rootState.contractSigningKeys[contractNameLookupKey][manifest2.signature.keyId]; - verifySignature(signingKey, manifest2.body + manifest2.head, manifest2.signature.value); - console.info(`[chelonia] successful signature verification for ${manifestHash} (named ${contractName}) using the already-trusted key ${manifest2.signature.keyId}.`); - signatureValidated = true; - } - const body = JSON.parse(manifest2.body); - if (!signatureValidated) { - console.info(`[chelonia] verifying signature for ${manifestHash} (named ${contractName}) for the first time`); - if (!has(body, "signingKeys") || !Array.isArray(body.signingKeys)) { - throw new Error(`Invalid manifest file ${manifestHash} (named ${contractName}). Its body doesn't contain a 'signingKeys' list'`); - } - let contractSigningKeys; - try { - contractSigningKeys = Object.fromEntries(body.signingKeys.map((serializedKey) => { - return [keyId(serializedKey), serializedKey]; - })); - } catch (e2) { - console.error(`[chelonia] Error parsing the public keys list for ${manifestHash} (named ${contractName})`, e2); - throw e2; - } - if (!has(contractSigningKeys, manifest2.signature.keyId)) { - throw new Error(`Invalid or missing signature in manifest ${manifestHash} (named ${contractName}). It claims to be signed with a key with ID ${manifest2.signature.keyId}, which is not listed in its 'signingKeys' field.`); - } - verifySignature(contractSigningKeys[manifest2.signature.keyId], manifest2.body + manifest2.head, manifest2.signature.value); - console.info(`[chelonia] successful signature verification for ${manifestHash} (named ${contractName}) using ${manifest2.signature.keyId}. The following key IDs will now be trusted for this contract name`, Object.keys(contractSigningKeys)); - signatureValidated = true; - rootState.contractSigningKeys[contractNameLookupKey] = contractSigningKeys; + if (this.size === this.max && this.max !== 0) { + return this.evict(false); } - return body; - }, - "chelonia/private/loadManifest": async function(contractName, manifestHash) { - if (!contractName || typeof contractName !== "string") { - throw new Error("Invalid or missing contract name"); + if (this.free.length !== 0) { + return this.free.pop(); } - if (this.manifestToContract[manifestHash]) { - console.warn("[chelonia]: already loaded manifest", manifestHash); - return; + return this.initialFill++; + } + pop() { + if (this.size) { + const val = this.valList[this.head]; + this.evict(true); + return val; } - const manifestSource = await esm_default("chelonia/out/fetchResource", manifestHash, { - code: multicodes.SHELTER_CONTRACT_MANIFEST - }); - const manifest2 = JSON.parse(manifestSource); - const body = esm_default("chelonia/private/verifyManifestSignature", contractName, manifestHash, manifest2); - if (body.name !== contractName) { - throw new Error(`Mismatched contract name. Expected ${contractName} but got ${body.name}`); - } - const contractInfo = this.config.contracts.defaults.preferSlim && body.contractSlim || body.contract; - console.info(`[chelonia] loading contract '${contractInfo.file}'@'${body.version}' from manifest: ${manifestHash}`); - const source = await esm_default("chelonia/out/fetchResource", contractInfo.hash, { - code: multicodes.SHELTER_CONTRACT_TEXT - }); - const reduceAllow = (acc, v2) => { - acc[v2] = true; - return acc; - }; - const allowedSels = [ - "okTurtles.events/on", - "chelonia/defineContract", - "chelonia/out/keyRequest" - ].concat(this.config.contracts.defaults.allowedSelectors).reduce(reduceAllow, {}); - const allowedDoms = this.config.contracts.defaults.allowedDomains.reduce(reduceAllow, {}); - const contractSBP = (selector, ...args) => { - const domain = domainFromSelector(selector); - if (selector.startsWith(contractName + "/")) { - selector = `${manifestHash}/${selector}`; - } - if (allowedSels[selector] || allowedDoms[domain]) { - return esm_default(selector, ...args); - } else { - console.error("[chelonia] selector not on allowlist", { - selector, - allowedSels, - allowedDoms - }); - throw new Error(`[chelonia] selector not on allowlist: '${selector}'`); + } + evict(free) { + const head = this.head; + const k = this.keyList[head]; + const v2 = this.valList[head]; + if (this.isBackgroundFetch(v2)) { + v2.__abortController.abort(); + } else { + this.dispose(v2, k, "evict"); + if (this.disposeAfter) { + this.disposed.push([v2, k, "evict"]); } - }; - const saferEval = new Function(` - return function (globals) { - // almost a real sandbox - // stops (() => this)().fetch - // needs additional step of locking down Function constructor to stop: - // new (()=>{}).constructor("console.log(typeof this.fetch)")() - globals.self = globals - globals.globalThis = globals - with (new Proxy(globals, { - get (o, p) { return o[p] }, - has (o, p) { /* console.log('has', p); */ return true } - })) { - (function () { - 'use strict' - ${source} - })() } + this.removeItemSize(head); + if (free) { + this.keyList[head] = null; + this.valList[head] = null; + this.free.push(head); + } + this.head = this.next[head]; + this.keyMap.delete(k); + this.size--; + return head; } - `)(); - this.defContractSBP = contractSBP; - this.defContractManifest = manifestHash; - saferEval({ - // pass in globals that we want access to by default in the sandbox - // note: you can undefine these by setting them to undefined in exposedGlobals - crypto: { - getRandomValues: (v2) => globalThis.crypto.getRandomValues(v2) - }, - ...typeof window === "object" && window && { - alert: window.alert.bind(window), - confirm: window.confirm.bind(window), - prompt: window.prompt.bind(window) - }, - isNaN, - console, - Object, - Error, - TypeError, - RangeError, - Math, - Symbol, - Date, - Array, - BigInt, - Boolean, - String, - Number, - Int8Array, - Int16Array, - Int32Array, - Uint8Array, - Uint16Array, - Uint32Array, - Float32Array, - Float64Array, - ArrayBuffer, - JSON, - RegExp, - parseFloat, - parseInt, - Promise, - Function, - Map, - WeakMap, - ...this.config.contracts.defaults.exposedGlobals, - require: (dep) => { - return dep === "@sbp/sbp" ? contractSBP : this.config.contracts.defaults.modules[dep]; - }, - sbp: contractSBP, - fetchServerTime: async (fallback = true) => { - try { - const response = await this.config.fetch(`${this.config.connectionURL}/time`, { - signal: this.abortController.signal - }); - return handleFetchResult("text")(response); - } catch (e2) { - console.warn("[fetchServerTime] Error", e2); - if (fallback) { - return new Date(esm_default("chelonia/time")).toISOString(); - } - throw new ChelErrorFetchServerTimeFailed("Can not fetch server time. Please check your internet connection."); + has(k, { updateAgeOnHas = this.updateAgeOnHas } = {}) { + const index = this.keyMap.get(k); + if (index !== void 0) { + if (!this.isStale(index)) { + if (updateAgeOnHas) { + this.updateItemAge(index); } + return true; } - }); - if (contractName !== this.defContract.name) { - throw new Error(`Invalid contract name for manifest ${manifestHash}. Expected ${contractName} but got ${this.defContract.name}`); } - this.defContractSelectors.forEach((s) => { - allowedSels[s] = true; - }); - this.manifestToContract[manifestHash] = { - slim: contractInfo === body.contractSlim, - info: contractInfo, - contract: this.defContract - }; - }, - // Warning: avoid using this unless you know what you're doing. Prefer using /remove. - "chelonia/private/removeImmediately": function(contractID, params) { - const state = esm_default(this.config.stateSelector); - const contractName = state.contracts[contractID]?.type; - if (!contractName) { - console.error("[chelonia/private/removeImmediately] Missing contract name for contract", { - contractID - }); - return; + return false; + } + // like get(), but without any LRU updating or TTL expiration + peek(k, { allowStale = this.allowStale } = {}) { + const index = this.keyMap.get(k); + if (index !== void 0 && (allowStale || !this.isStale(index))) { + const v2 = this.valList[index]; + return this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; } - const manifestHash = this.config.contracts.manifests[contractName]; - if (manifestHash) { - const destructor = `${manifestHash}/${contractName}/_cleanup`; - if (esm_default("sbp/selectors/fn", destructor)) { - try { - esm_default(destructor, { contractID, resync: !!params?.resync, state: state[contractID] }); - } catch (e2) { - console.error(`[chelonia/private/removeImmediately] Error at destructor for ${contractID}`, e2); + } + backgroundFetch(k, index, options2, context) { + const v2 = index === void 0 ? void 0 : this.valList[index]; + if (this.isBackgroundFetch(v2)) { + return v2; + } + const ac = new AC(); + const fetchOpts = { + signal: ac.signal, + options: options2, + context + }; + const cb = (v3) => { + if (!ac.signal.aborted) { + this.set(k, v3, fetchOpts.options); + } + return v3; + }; + const eb = (er) => { + if (this.valList[index] === p) { + const del = !options2.noDeleteOnFetchRejection || p.__staleWhileFetching === void 0; + if (del) { + this.delete(k); + } else { + this.valList[index] = p.__staleWhileFetching; } } - } - if (params?.resync) { - Object.keys(state.contracts[contractID]).filter((k) => k !== "references").forEach((k) => this.config.reactiveDel(state.contracts[contractID], k)); - Object.keys(state[contractID]).filter((k) => k !== "_volatile").forEach((k) => this.config.reactiveDel(state[contractID], k)); - if (state[contractID]._volatile) { - Object.keys(state[contractID]._volatile).filter((k) => k !== "watch").forEach((k) => this.config.reactiveDel(state[contractID]._volatile, k)); + if (p.__returned === p) { + throw er; } + }; + const pcall = (res) => res(this.fetchMethod(k, v2, fetchOpts)); + const p = new Promise(pcall).then(cb, eb); + p.__abortController = ac; + p.__staleWhileFetching = v2; + p.__returned = null; + if (index === void 0) { + this.set(k, p, fetchOpts.options); + index = this.keyMap.get(k); } else { - delete this.ephemeralReferenceCount[contractID]; - if (params?.permanent) { - this.config.reactiveSet(state.contracts, contractID, null); - } else { - this.config.reactiveDel(state.contracts, contractID); - } - this.config.reactiveDel(state, contractID); + this.valList[index] = p; } - this.subscriptionSet.delete(contractID); - esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { - added: [], - removed: [contractID], - permanent: params?.permanent, - resync: params?.resync - }); - }, - // used by, e.g. 'chelonia/contract/wait' - "chelonia/private/noop": function() { - }, - "chelonia/private/out/sync": function(contractIDs, params) { - const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; - const forcedSync = !!params?.force; - return Promise.all(listOfIds.map((contractID) => { - if (!forcedSync && this.subscriptionSet.has(contractID)) { - const rootState = esm_default(this.config.stateSelector); - if (!rootState[contractID]?._volatile?.dirty) { - return esm_default("chelonia/private/queueEvent", contractID, ["chelonia/private/noop"]); - } - } - return esm_default("chelonia/private/queueEvent", contractID, [ - "chelonia/private/in/syncContract", - contractID, - params - ]).catch((err) => { - console.error(`[chelonia] failed to sync ${contractID}:`, err); - throw err; - }); - })); - }, - "chelonia/private/out/publishEvent": function(entry, { maxAttempts = 5, headers, billableContractID, bearer, disableAutoDedup } = {}, hooks) { - const contractID = entry.contractID(); - const originalEntry = entry; - return esm_default("chelonia/private/queueEvent", `publish:${contractID}`, async () => { - let attempt = 1; - let lastAttemptedHeight; - await hooks?.prepublish?.(entry); - const onreceivedHandler = (_contractID, message) => { - if (entry.hash() === message.hash()) { - esm_default("okTurtles.events/off", EVENT_HANDLED, onreceivedHandler); - hooks.onprocessed(entry); - } - }; - if (typeof hooks?.onprocessed === "function") { - esm_default("okTurtles.events/on", EVENT_HANDLED, onreceivedHandler); - } - while (true) { - lastAttemptedHeight = entry.height(); - const newEntry = await esm_default("chelonia/private/queueEvent", contractID, async () => { - const rootState = esm_default(this.config.stateSelector); - const state = rootState[contractID]; - const isFirstMessage = entry.isFirstMessage(); - if (!state && !isFirstMessage) { - console.info(`[chelonia] Not sending message as contract state has been removed: ${entry.description()}`); - return; - } - if (hooks?.preSendCheck) { - if (!await hooks.preSendCheck(entry, state)) { - console.info(`[chelonia] Not sending message as preSendCheck hook returned non-truish value: ${entry.description()}`); - return; - } - } - await esm_default("chelonia/private/in/processMessage", entry, cloneDeep(state || {})); - if (!isFirstMessage) { - return recreateEvent(entry, state, rootState.contracts[contractID], disableAutoDedup); - } - return entry; - }); - if (!newEntry) - return; - await hooks?.beforeRequest?.(newEntry, entry); - entry = newEntry; - const r = await this.config.fetch(`${this.config.connectionURL}/event`, { - method: "POST", - body: entry.serialize(), - headers: { - ...headers, - ...bearer && { - Authorization: `Bearer ${bearer}` - }, - ...billableContractID && { - Authorization: buildShelterAuthorizationHeader.call(this, billableContractID) - }, - "Content-Type": "text/plain" - }, - signal: this.abortController.signal - }); - if (r.ok) { - await hooks?.postpublish?.(entry); - return entry; - } - try { - if (r.status === 409) { - if (attempt + 1 > maxAttempts) { - console.error(`[chelonia] failed to publish ${entry.description()} after ${attempt} attempts`, entry); - throw new Error(`publishEvent: ${r.status} - ${r.statusText}. attempt ${attempt}`); - } - const randDelay = randomIntFromRange(0, 1500); - console.warn(`[chelonia] publish attempt ${attempt} of ${maxAttempts} failed. Waiting ${randDelay} msec before resending ${entry.description()}`); - attempt += 1; - await delay(randDelay); - if (!entry.isFirstMessage() && entry.height() === lastAttemptedHeight) { - await esm_default("chelonia/private/out/sync", contractID, { force: true }); - } - } else { - const message = (await r.json())?.message; - console.error(`[chelonia] ERROR: failed to publish ${entry.description()}: ${r.status} - ${r.statusText}: ${message}`, entry); - throw new Error(`publishEvent: ${r.status} - ${r.statusText}: ${message}`); - } - } catch (e2) { - esm_default("okTurtles.events/off", EVENT_HANDLED, onreceivedHandler); - throw e2; - } - } - }).then((entry2) => { - esm_default("okTurtles.events/emit", EVENT_PUBLISHED, { - contractID, - message: entry2, - originalMessage: originalEntry - }); - return entry2; - }).catch((e2) => { - esm_default("okTurtles.events/emit", EVENT_PUBLISHING_ERROR, { - contractID, - message: entry, - originalMessage: originalEntry, - error: e2 + return p; + } + isBackgroundFetch(p) { + return p && typeof p === "object" && typeof p.then === "function" && Object.prototype.hasOwnProperty.call( + p, + "__staleWhileFetching" + ) && Object.prototype.hasOwnProperty.call(p, "__returned") && (p.__returned === p || p.__returned === null); + } + // this takes the union of get() and set() opts, because it does both + async fetch(k, { + // get options + allowStale = this.allowStale, + updateAgeOnGet = this.updateAgeOnGet, + noDeleteOnStaleGet = this.noDeleteOnStaleGet, + // set options + ttl = this.ttl, + noDisposeOnSet = this.noDisposeOnSet, + size = 0, + sizeCalculation = this.sizeCalculation, + noUpdateTTL = this.noUpdateTTL, + // fetch exclusive options + noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, + fetchContext = this.fetchContext, + forceRefresh = false + } = {}) { + if (!this.fetchMethod) { + return this.get(k, { + allowStale, + updateAgeOnGet, + noDeleteOnStaleGet }); - throw e2; - }); - }, - "chelonia/private/out/latestHEADinfo": function(contractID) { - return this.config.fetch(`${this.config.connectionURL}/latestHEADinfo/${contractID}`, { - cache: "no-store", - signal: this.abortController.signal - }).then(handleFetchResult("json")); - }, - "chelonia/private/postKeyShare": function(contractID, previousVolatileState, signingKey) { - const cheloniaState = esm_default(this.config.stateSelector); - const targetState = cheloniaState[contractID]; - if (!targetState) - return; - if (previousVolatileState && has(previousVolatileState, "watch")) { - if (!targetState._volatile) { - this.config.reactiveSet(targetState, "_volatile", /* @__PURE__ */ Object.create(null)); - } - if (!targetState._volatile.watch) { - this.config.reactiveSet(targetState._volatile, "watch", previousVolatileState.watch); - } else if (targetState._volatile.watch !== previousVolatileState.watch) { - previousVolatileState.watch.forEach((pWatch) => { - if (!targetState._volatile.watch.some((tWatch) => { - return tWatch[0] === pWatch[0] && tWatch[1] === pWatch[1]; - })) { - targetState._volatile.watch.push(pWatch); - } - }); - } - } - if (!Array.isArray(targetState._volatile?.pendingKeyRequests)) - return; - this.config.reactiveSet(targetState._volatile, "pendingKeyRequests", targetState._volatile.pendingKeyRequests.filter((pkr) => pkr?.name !== signingKey.name)); - }, - "chelonia/private/in/processMessage": async function(message, state, internalSideEffectStack, contractName) { - const [opT, opV] = message.op(); - const hash3 = message.hash(); - const height = message.height(); - const contractID = message.contractID(); - const manifestHash = message.manifest(); - const signingKeyId = message.signingKeyId(); - const direction = message.direction(); - const config2 = this.config; - const self2 = this; - const opName = Object.entries(SPMessage).find(([, y]) => y === opT)?.[0]; - console.debug("PROCESSING OPCODE:", opName, "to", contractID); - if (state?._volatile?.dirty) { - console.debug("IGNORING OPCODE BECAUSE CONTRACT STATE IS MARKED AS DIRTY.", "OPCODE:", opName, "CONTRACT:", contractID); - return; } - if (!state._vm) - state._vm = /* @__PURE__ */ Object.create(null); - const opFns = { - /* - There are two types of "errors" that we need to consider: - 1. "Ignoring" errors - 2. "Failure" errors - Example: OP_KEY_ADD - 1. IGNORING: an error is thrown because we wanted to add a key but the - key we wanted to add is already there. This is not a hard error, it's an - ignoring error. We don't care that the operation failed in this case because the intent was accomplished. - 2. FAILURE: an error is thrown while attempting to add a key that doesn't exist. - Example: OP_ACTION_ENCRYPTED - 1. IGNORING: An error is thrown because we don't have the key to decrypt the action. We ignore it. - 2. FAILURE: An error is thrown by the process function during processing. - Handling these in OP_ATOMIC - • ALL errors of class "IGNORING" should be ignored. They should not - impact our ability to process the rest of the operations in the OP_ATOMIC. - No matter how many of these are thrown, it doesn't affect the rest of the operations. - • ANY error of class "FAILURE" will call the rest of the operations to - fail and the state to be reverted to prior to the OP_ATOMIC. No side-effects should be run. Because an intention failed. - */ - async [SPMessage.OP_ATOMIC](v2) { - for (let i2 = 0; i2 < v2.length; i2++) { - const u2 = v2[i2]; - try { - if (u2[0] === SPMessage.OP_ATOMIC) - throw new Error("Cannot nest OP_ATOMIC"); - if (!validateKeyPermissions(message, config2, state, signingKeyId, u2[0], u2[1])) { - throw new Error("Inside OP_ATOMIC: no matching signing key was defined"); - } - await opFns[u2[0]](u2[1]); - } catch (e_) { - const e2 = e_; - if (e2 && typeof e2 === "object") { - if (e2.name === "ChelErrorDecryptionKeyNotFound") { - console.warn(`[chelonia] [OP_ATOMIC] WARN '${e2.name}' in processMessage for ${message.description()}: ${e2.message}`, e2, message.serialize()); - if (e2.cause) { - const missingDecryptionKeyIds = missingDecryptionKeyIdsMap.get(message); - if (missingDecryptionKeyIds) { - missingDecryptionKeyIds.add(e2.cause); - } else { - missingDecryptionKeyIdsMap.set(message, /* @__PURE__ */ new Set([e2.cause])); - } - } - continue; - } else { - logEvtError(message, `[chelonia] [OP_ATOMIC] ERROR '${e2.name}' in processMessage for ${message.description()}: ${e2.message || e2}`, e2, message.serialize()); - } - console.warn(`[chelonia] [OP_ATOMIC] Error processing ${message.description()}: ${message.serialize()}. Any side effects will be skipped!`); - if (config2.strictProcessing) { - throw e2; - } - config2.hooks.processError?.(e2, message, getMsgMeta.call(self2, message, contractID, state)); - if (e2.name === "ChelErrorWarning") - continue; - } else { - logEvtError(message, "Inside OP_ATOMIC: Non-object or null error thrown", contractID, message, i2, e2); - } - throw e2; - } - } - }, - [SPMessage.OP_CONTRACT](v2) { - state._vm.type = v2.type; - const keys = keysToMap.call(self2, v2.keys, height); - state._vm.authorizedKeys = keys; - keyAdditionProcessor.call(self2, message, hash3, v2.keys, state, contractID, signingKey, internalSideEffectStack); - }, - [SPMessage.OP_ACTION_ENCRYPTED](v2) { - if (config2.skipActionProcessing) { - if (!config2.skipDecryptionAttempts) { - console.log("OP_ACTION_ENCRYPTED: skipped action processing"); - } - return; - } - return opFns[SPMessage.OP_ACTION_UNENCRYPTED](v2.valueOf()); - }, - async [SPMessage.OP_ACTION_UNENCRYPTED](v2) { - if (!config2.skipActionProcessing) { - let innerSigningKeyId; - if (isSignedData(v2)) { - innerSigningKeyId = v2.signingKeyId; - v2 = v2.valueOf(); - } - const { data, meta, action } = v2; - if (!config2.whitelisted(action)) { - throw new Error(`chelonia: action not whitelisted: '${action}'`); - } - await esm_default(`${manifestHash}/${action}/process`, { - data, - meta, - hash: hash3, - height, - contractID, - direction: message.direction(), - signingKeyId, - get signingContractID() { - return getContractIDfromKeyId(contractID, signingKeyId, state); - }, - innerSigningKeyId, - get innerSigningContractID() { - return getContractIDfromKeyId(contractID, innerSigningKeyId, state); - } - }, state); - } - }, - [SPMessage.OP_KEY_SHARE](wv) { - const data = config2.unwrapMaybeEncryptedData(wv); - if (!data) - return; - const v2 = data.data; - for (const key of v2.keys) { - if (key.id && key.meta?.private?.content) { - if (!has(state._vm, "sharedKeyIds")) - state._vm.sharedKeyIds = []; - if (!state._vm.sharedKeyIds.some((sK) => sK.id === key.id)) { - state._vm.sharedKeyIds.push({ - id: key.id, - contractID: v2.contractID, - height, - keyRequestHash: v2.keyRequestHash, - keyRequestHeight: v2.keyRequestHeight - }); - } - } - } - if (has(v2, "keyRequestHash") && state._vm.authorizedKeys[signingKeyId].meta?.keyRequest) { - state._vm.authorizedKeys[signingKeyId].meta.keyRequest.responded = hash3; - } - internalSideEffectStack?.push(async () => { - delete self2.postSyncOperations[contractID]?.["pending-keys-for-" + v2.contractID]; - const cheloniaState = esm_default(self2.config.stateSelector); - const targetState = cheloniaState[v2.contractID]; - const missingDecryptionKeyIds = cheloniaState.contracts[v2.contractID]?.missingDecryptionKeyIds; - let newestEncryptionKeyHeight = Number.POSITIVE_INFINITY; - for (const key of v2.keys) { - if (key.id && key.meta?.private?.content) { - const transient = direction === "outgoing" || key.meta.private.transient; - if (!esm_default("chelonia/haveSecretKey", key.id, !transient)) { - try { - const decrypted = key.meta.private.content.valueOf(); - esm_default("chelonia/storeSecretKeys", new Secret([ - { - key: deserializeKey(decrypted), - transient - } - ])); - if (missingDecryptionKeyIds?.includes(key.id)) { - newestEncryptionKeyHeight = Number.NEGATIVE_INFINITY; - } else if ( - // Otherwise, we make an educated guess on whether a re-sync - // is needed based on the height. - targetState?._vm?.authorizedKeys?.[key.id]?._notBeforeHeight != null && Array.isArray(targetState._vm.authorizedKeys[key.id].purpose) && targetState._vm.authorizedKeys[key.id].purpose.includes("enc") - ) { - newestEncryptionKeyHeight = Math.min(newestEncryptionKeyHeight, targetState._vm.authorizedKeys[key.id]._notBeforeHeight); - } - } catch (e_) { - const e2 = e_; - if (e2?.name === "ChelErrorDecryptionKeyNotFound") { - console.warn(`OP_KEY_SHARE (${hash3} of ${contractID}) missing secret key: ${e2.message}`, e2); - } else { - console.error(`OP_KEY_SHARE (${hash3} of ${contractID}) error '${e2.message || e2}':`, e2); - } - } - } - } - } - const mustResync = !!(newestEncryptionKeyHeight < cheloniaState.contracts[v2.contractID]?.height); - if (mustResync) { - if (!has(targetState, "_volatile")) { - config2.reactiveSet(targetState, "_volatile", /* @__PURE__ */ Object.create(null)); - } - config2.reactiveSet(targetState._volatile, "dirty", true); - if (!Object.keys(targetState).some((k) => k !== "_volatile")) { - return; - } - const keyDict = /* @__PURE__ */ Object.create(null); - targetState._volatile?.watch?.forEach(([keyName, contractID2]) => { - if (!keyDict[keyName]) { - keyDict[keyName] = [contractID2]; - return; - } - keyDict[keyName].push(contractID2); - }); - const contractIdsToUpdate = Array.from(new Set(Object.entries(keyDict).flatMap(([keyName, contractIDs]) => { - const keyId2 = findKeyIdByName(targetState, keyName); - if ( - // Does the key exist? (i.e., is it a current key) - keyId2 && // Is it an encryption key? (signing keys don't build up a - // potentially invalid state because the private key isn't - // required for validation; however, missing encryption keys - // prevent message processing) - targetState._vm.authorizedKeys[keyId2].purpose.includes("enc") && // Is this a newly set key? (avoid re-syncing contracts that - // haven't been affected by the `OP_KEY_SHARE`) - targetState._vm.authorizedKeys[keyId2]._notBeforeHeight >= newestEncryptionKeyHeight - ) { - return contractIDs; - } - return []; - }))); - contractIdsToUpdate.forEach((contractID2) => { - const targetState2 = cheloniaState[contractID2]; - if (!targetState2) - return; - if (!has(targetState2, "_volatile")) { - config2.reactiveSet(targetState2, "_volatile", /* @__PURE__ */ Object.create(null)); - } - config2.reactiveSet(targetState2._volatile, "dirty", true); - }); - if (self2.subscriptionSet.has(v2.contractID)) { - const resync = esm_default("chelonia/private/queueEvent", v2.contractID, [ - "chelonia/private/in/syncContract", - v2.contractID - ]).then(() => { - esm_default("chelonia/private/out/sync", contractIdsToUpdate.filter((contractID2) => { - return self2.subscriptionSet.has(contractID2); - }), { force: true, resync: true }).catch((e2) => { - console.error("[chelonia] Error resyncing contracts with foreign key references after key rotation", e2); - }); - }).catch((e2) => { - console.error(`[chelonia] Error during sync for ${v2.contractID} during OP_KEY_SHARE for ${contractID}`); - if (v2.contractID === contractID) { - throw e2; - } - }); - if (v2.contractID !== contractID) { - await resync; - } - } - } - const previousVolatileState = targetState?._volatile; - esm_default("chelonia/private/queueEvent", v2.contractID, [ - "chelonia/private/postKeyShare", - v2.contractID, - mustResync ? previousVolatileState : null, - signingKey - ]).then(() => { - esm_default("chelonia/private/queueEvent", contractID, () => { - esm_default("okTurtles.events/emit", CONTRACT_HAS_RECEIVED_KEYS, { - contractID: v2.contractID, - sharedWithContractID: contractID, - signingKeyId, - get signingKeyName() { - return state._vm?.authorizedKeys?.[signingKeyId]?.name; - } - }); - }).catch((e2) => { - console.error(`[chelonia] Error while emitting the CONTRACT_HAS_RECEIVED_KEYS event for ${contractID}`, e2); - }); - }); - }); - }, - [SPMessage.OP_KEY_REQUEST](wv) { - const data = config2.unwrapMaybeEncryptedData(wv); - const v2 = data?.data || { - contractID: "(private)", - replyWith: { context: void 0 }, - request: "*" - }; - const originatingContractID = v2.contractID; - if (state._vm?.invites?.[signingKeyId]?.quantity != null) { - if (state._vm.invites[signingKeyId].quantity > 0) { - if (--state._vm.invites[signingKeyId].quantity <= 0) { - state._vm.invites[signingKeyId].status = INVITE_STATUS.USED; - } - } else { - logEvtError(message, "Ignoring OP_KEY_REQUEST because it exceeds allowed quantity: " + originatingContractID); - return; - } - } - if (state._vm?.invites?.[signingKeyId]?.expires != null) { - if (state._vm.invites[signingKeyId].expires < Date.now()) { - logEvtError(message, "Ignoring OP_KEY_REQUEST because it expired at " + state._vm.invites[signingKeyId].expires + ": " + originatingContractID); - return; - } - } - if (config2.skipActionProcessing || direction === "outgoing") { - return; - } - if (!has(v2.replyWith, "context")) { - logEvtError(message, "Ignoring OP_KEY_REQUEST because it is missing the context attribute"); - return; - } - const context = v2.replyWith.context; - if (data && (!Array.isArray(context) || context[0] !== originatingContractID)) { - logEvtError(message, "Ignoring OP_KEY_REQUEST because it is signed by the wrong contract"); - return; - } - if (v2.request !== "*") { - logEvtError(message, "Ignoring OP_KEY_REQUEST because it has an unsupported request attribute", v2.request); - return; - } - if (!state._vm.pendingKeyshares) - state._vm.pendingKeyshares = /* @__PURE__ */ Object.create(null); - state._vm.pendingKeyshares[message.hash()] = context ? [ - // Full-encryption (i.e., KRS encryption) requires that this request - // was encrypted and that the invite is marked as private - !!data?.encryptionKeyId, - message.height(), - signingKeyId, - context - ] : [!!data?.encryptionKeyId, message.height(), signingKeyId]; - if (data) { - internalSideEffectStack?.push(() => { - self2.setPostSyncOp(contractID, "respondToAllKeyRequests-" + message.contractID(), [ - "chelonia/private/respondToAllKeyRequests", - contractID - ]); - }); - } - }, - [SPMessage.OP_KEY_REQUEST_SEEN](wv) { - if (config2.skipActionProcessing) { - return; - } - const data = config2.unwrapMaybeEncryptedData(wv); - if (!data) - return; - const v2 = data.data; - if (state._vm.pendingKeyshares && v2.keyRequestHash in state._vm.pendingKeyshares) { - const hash4 = v2.keyRequestHash; - const pending = state._vm.pendingKeyshares[hash4]; - delete state._vm.pendingKeyshares[hash4]; - if (pending.length !== 4) - return; - const keyId2 = pending[2]; - const originatingContractID = pending[3][0]; - if (Array.isArray(state._vm?.invites?.[keyId2]?.responses)) { - state._vm?.invites?.[keyId2]?.responses.push(originatingContractID); - } - if (!has(state._vm, "keyshares")) - state._vm.keyshares = /* @__PURE__ */ Object.create(null); - const success = v2.success; - state._vm.keyshares[hash4] = { - contractID: originatingContractID, - height, - success, - ...success && { - hash: v2.keyShareHash - } - }; - } - }, - [SPMessage.OP_PROP_DEL]: notImplemented, - [SPMessage.OP_PROP_SET](v2) { - if (!state._vm.props) - state._vm.props = {}; - state._vm.props[v2.key] = v2.value; - }, - [SPMessage.OP_KEY_ADD](v2) { - const keys = keysToMap.call(self2, v2, height, state._vm.authorizedKeys); - const keysArray = Object.values(v2); - keysArray.forEach((k) => { - if (has(state._vm.authorizedKeys, k.id) && state._vm.authorizedKeys[k.id]._notAfterHeight == null) { - throw new ChelErrorWarning("Cannot use OP_KEY_ADD on existing keys. Key ID: " + k.id); - } - }); - validateKeyAddPermissions.call(self2, contractID, signingKey, state, v2); - state._vm.authorizedKeys = { ...state._vm.authorizedKeys, ...keys }; - keyAdditionProcessor.call(self2, message, hash3, v2, state, contractID, signingKey, internalSideEffectStack); - }, - [SPMessage.OP_KEY_DEL](v2) { - if (!state._vm.authorizedKeys) - state._vm.authorizedKeys = /* @__PURE__ */ Object.create(null); - if (!state._volatile) - state._volatile = /* @__PURE__ */ Object.create(null); - if (!state._volatile.pendingKeyRevocations) { - state._volatile.pendingKeyRevocations = /* @__PURE__ */ Object.create(null); - } - validateKeyDelPermissions.call(self2, contractID, signingKey, state, v2); - const keyIds = v2.map((k) => { - const data = config2.unwrapMaybeEncryptedData(k); - if (!data) - return void 0; - return data.data; - }).filter((keyId2) => { - if (!keyId2 || typeof keyId2 !== "string") - return false; - if (!has(state._vm.authorizedKeys, keyId2) || state._vm.authorizedKeys[keyId2]._notAfterHeight != null) { - console.warn("Attempted to delete non-existent key from contract", { - contractID, - keyId: keyId2 - }); - return false; - } - return true; - }); - keyIds.forEach((keyId2) => { - const key = state._vm.authorizedKeys[keyId2]; - state._vm.authorizedKeys[keyId2]._notAfterHeight = height; - if (has(state._volatile.pendingKeyRevocations, keyId2)) { - delete state._volatile.pendingKeyRevocations[keyId2]; - } - if (key.foreignKey) { - const fkUrl = new URL(key.foreignKey); - const foreignContract = fkUrl.pathname; - const foreignKeyName = fkUrl.searchParams.get("keyName"); - if (!foreignContract || !foreignKeyName) { - throw new Error("Invalid foreign key: missing contract or key name"); - } - internalSideEffectStack?.push(() => { - esm_default("chelonia/private/queueEvent", foreignContract, () => { - const rootState = esm_default(config2.stateSelector); - if (Array.isArray(rootState[foreignContract]?._volatile?.watch)) { - const oldWatch = rootState[foreignContract]._volatile.watch; - rootState[foreignContract]._volatile.watch = oldWatch.filter(([name, cID]) => name !== foreignKeyName || cID !== contractID); - if (oldWatch.length !== rootState[foreignContract]._volatile.watch.length) { - esm_default("chelonia/contract/release", foreignContract, { try: true }).catch((e2) => { - console.error(`[chelonia] Error at OP_KEY_DEL internalSideEffectStack while attempting to release foreign contract ${foreignContract}`, e2); - }); - } - } - }).catch((e2) => { - console.error("Error stopping watching events after removing key", { contractID, foreignContract, foreignKeyName, fkUrl }, e2); - }); - }); - const pendingWatch = state._vm.pendingWatch?.[foreignContract]; - if (pendingWatch) { - state._vm.pendingWatch[foreignContract] = pendingWatch.filter(([, kId]) => kId !== keyId2); - } - } - if (key.name.startsWith("#inviteKey-") && state._vm.invites[key.id]) { - state._vm.invites[key.id].status = INVITE_STATUS.REVOKED; - } - }); - if (Array.isArray(state._volatile?.watch)) { - const updatedKeysMap = /* @__PURE__ */ Object.create(null); - keyIds.forEach((keyId2) => { - updatedKeysMap[state._vm.authorizedKeys[keyId2].name] = { - name: state._vm.authorizedKeys[keyId2].name, - oldKeyId: keyId2 - }; - }); - keyRotationHelper(contractID, state, config2, updatedKeysMap, [SPMessage.OP_KEY_DEL], "chelonia/out/keyDel", (name) => updatedKeysMap[name[0]].oldKeyId, internalSideEffectStack); - } - }, - [SPMessage.OP_KEY_UPDATE](v2) { - if (!state._volatile) - state._volatile = /* @__PURE__ */ Object.create(null); - if (!state._volatile.pendingKeyRevocations) { - state._volatile.pendingKeyRevocations = /* @__PURE__ */ Object.create(null); - } - const [updatedKeys, updatedMap] = validateKeyUpdatePermissions.call(self2, contractID, signingKey, state, v2); - const keysToDelete = Object.values(updatedMap); - for (const keyId2 of keysToDelete) { - if (has(state._volatile.pendingKeyRevocations, keyId2)) { - delete state._volatile.pendingKeyRevocations[keyId2]; - } - state._vm.authorizedKeys[keyId2]._notAfterHeight = height; - } - for (const key of updatedKeys) { - if (!has(state._vm.authorizedKeys, key.id)) { - key._notBeforeHeight = height; - state._vm.authorizedKeys[key.id] = cloneDeep(key); - } - } - keyAdditionProcessor.call(self2, message, hash3, updatedKeys, state, contractID, signingKey, internalSideEffectStack); - if (Array.isArray(state._volatile?.watch)) { - const updatedKeysMap = /* @__PURE__ */ Object.create(null); - updatedKeys.forEach((key) => { - if (key.data) { - updatedKeysMap[key.name] = cloneDeep(key); - updatedKeysMap[key.name].oldKeyId = updatedMap[key.id]; - } - }); - keyRotationHelper(contractID, state, config2, updatedKeysMap, [SPMessage.OP_KEY_UPDATE], "chelonia/out/keyUpdate", (name) => ({ - name: name[1], - oldKeyId: updatedKeysMap[name[0]].oldKeyId, - id: updatedKeysMap[name[0]].id, - data: updatedKeysMap[name[0]].data - }), internalSideEffectStack); - } - }, - [SPMessage.OP_PROTOCOL_UPGRADE]: notImplemented + const options2 = { + allowStale, + updateAgeOnGet, + noDeleteOnStaleGet, + ttl, + noDisposeOnSet, + size, + sizeCalculation, + noUpdateTTL, + noDeleteOnFetchRejection }; - if (!this.config.skipActionProcessing && !this.manifestToContract[manifestHash]) { - const rootState = esm_default(this.config.stateSelector); - if (!contractName) { - contractName = has(rootState.contracts, contractID) && rootState.contracts[contractID] && has(rootState.contracts[contractID], "type") ? rootState.contracts[contractID].type : opT === SPMessage.OP_CONTRACT ? opV.type : ""; - } - if (!contractName) { - throw new Error(`Unable to determine the name for a contract and refusing to load it (contract ID was ${contractID} and its manifest hash was ${manifestHash})`); + let index = this.keyMap.get(k); + if (index === void 0) { + const p = this.backgroundFetch(k, index, options2, fetchContext); + return p.__returned = p; + } else { + const v2 = this.valList[index]; + if (this.isBackgroundFetch(v2)) { + return allowStale && v2.__staleWhileFetching !== void 0 ? v2.__staleWhileFetching : v2.__returned = v2; } - await esm_default("chelonia/private/loadManifest", contractName, manifestHash); - } - let processOp = true; - if (config2.preOp) { - processOp = config2.preOp(message, state) !== false && processOp; - } - let signingKey; - { - const stateForValidation = opT === SPMessage.OP_CONTRACT && !state?._vm?.authorizedKeys ? { - _vm: { - authorizedKeys: keysToMap.call(this, opV.keys, height) + if (!forceRefresh && !this.isStale(index)) { + this.moveToTail(index); + if (updateAgeOnGet) { + this.updateItemAge(index); } - } : state; - if (!validateKeyPermissions(message, config2, stateForValidation, signingKeyId, opT, opV)) { - throw new Error("No matching signing key was defined"); + return v2; } - signingKey = stateForValidation._vm.authorizedKeys[signingKeyId]; - } - if (config2[`preOp_${opT}`]) { - processOp = config2[`preOp_${opT}`](message, state) !== false && processOp; - } - if (processOp) { - await opFns[opT](opV); - config2.postOp?.(message, state); - config2[`postOp_${opT}`]?.(message, state); - } - }, - "chelonia/private/in/enqueueHandleEvent": function(contractID, event) { - return esm_default("chelonia/private/queueEvent", contractID, async () => { - await esm_default("chelonia/private/in/handleEvent", contractID, event); - esm_default("chelonia/private/enqueuePostSyncOps", contractID); - }); - }, - "chelonia/private/in/syncContract": async function(contractID, params) { - const state = esm_default(this.config.stateSelector); - if (state.contracts[contractID] === null) { - throw new ChelErrorResourceGone("Cannot sync permanently deleted contract " + contractID); + const p = this.backgroundFetch(k, index, options2, fetchContext); + return allowStale && p.__staleWhileFetching !== void 0 ? p.__staleWhileFetching : p.__returned = p; } - try { - this.currentSyncs[contractID] = { firstSync: !state.contracts[contractID]?.type }; - esm_default("okTurtles.events/emit", CONTRACT_IS_SYNCING, contractID, true); - const currentVolatileState = state[contractID]?._volatile || /* @__PURE__ */ Object.create(null); - if (currentVolatileState?.dirty || params?.resync) { - delete currentVolatileState.dirty; - currentVolatileState.resyncing = true; - esm_default("chelonia/private/removeImmediately", contractID, { resync: true }); - this.config.reactiveSet(state, contractID, /* @__PURE__ */ Object.create(null)); - this.config.reactiveSet(state[contractID], "_volatile", currentVolatileState); - } - const { HEAD: latestHEAD } = await esm_default("chelonia/out/latestHEADInfo", contractID); - console.debug(`[chelonia] syncContract: ${contractID} latestHash is: ${latestHEAD}`); - const { HEAD: recentHEAD, height: recentHeight } = state.contracts[contractID] || {}; - const isSubscribed = this.subscriptionSet.has(contractID); - if (!isSubscribed) { - const entry = this.pending.find((entry2) => entry2?.contractID === contractID); - if (!entry) { - this.pending.push({ contractID }); - } - } - this.postSyncOperations[contractID] = this.postSyncOperations[contractID] ?? /* @__PURE__ */ Object.create(null); - if (latestHEAD !== recentHEAD) { - console.debug(`[chelonia] Synchronizing Contract ${contractID}: our recent was ${recentHEAD || "undefined"} but the latest is ${latestHEAD}`); - const eventsStream = esm_default("chelonia/out/eventsAfter", contractID, { - sinceHeight: recentHeight ?? 0, - sinceHash: recentHEAD ?? contractID - }); - let latestHashFound = false; - const eventReader = eventsStream.getReader(); - for (let skip = has(state.contracts, contractID) && has(state.contracts[contractID], "HEAD"); ; skip = false) { - const { done, value: event } = await eventReader.read(); - if (done) { - if (!latestHashFound) { - throw new ChelErrorForkedChain(`expected hash ${latestHEAD} in list of events for contract ${contractID}`); - } - break; - } - if (!latestHashFound) { - latestHashFound = SPMessage.deserializeHEAD(event).hash === latestHEAD; + } + get(k, { + allowStale = this.allowStale, + updateAgeOnGet = this.updateAgeOnGet, + noDeleteOnStaleGet = this.noDeleteOnStaleGet + } = {}) { + const index = this.keyMap.get(k); + if (index !== void 0) { + const value = this.valList[index]; + const fetching = this.isBackgroundFetch(value); + if (this.isStale(index)) { + if (!fetching) { + if (!noDeleteOnStaleGet) { + this.delete(k); } - if (skip) - continue; - await esm_default("chelonia/private/in/handleEvent", contractID, event); - } - } else if (!isSubscribed) { - this.subscriptionSet.add(contractID); - esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { - added: [contractID], - removed: [] - }); - const entryIndex = this.pending.findIndex((entry) => entry?.contractID === contractID); - if (entryIndex !== -1) { - this.pending.splice(entryIndex, 1); + return allowStale ? value : void 0; + } else { + return allowStale ? value.__staleWhileFetching : void 0; } - console.debug(`[chelonia] added already synchronized ${contractID} to subscription set`); - } else { - console.debug(`[chelonia] contract ${contractID} was already synchronized`); - } - esm_default("chelonia/private/enqueuePostSyncOps", contractID); - } catch (e2) { - console.error(`[chelonia] syncContract error: ${e2.message || e2}`, e2); - this.config.hooks.syncContractError?.(e2, contractID); - throw e2; - } finally { - if (state[contractID]?._volatile?.resyncing) { - this.config.reactiveDel(state[contractID]._volatile, "resyncing"); - } - delete this.currentSyncs[contractID]; - esm_default("okTurtles.events/emit", CONTRACT_IS_SYNCING, contractID, false); - } - }, - "chelonia/private/enqueuePostSyncOps": function(contractID) { - if (!has(this.postSyncOperations, contractID)) - return; - Object.entries(this.postSyncOperations[contractID]).forEach(([key, op]) => { - delete this.postSyncOperations[contractID][key]; - esm_default("chelonia/private/queueEvent", contractID, op).catch((e2) => { - console.error(`Post-sync operation for ${contractID} failed`, { contractID, op, error: e2 }); - }); - }); - }, - "chelonia/private/watchForeignKeys": function(externalContractID) { - const state = esm_default(this.config.stateSelector); - const externalContractState = state[externalContractID]; - const pendingWatch = externalContractState?._vm?.pendingWatch; - if (!pendingWatch || !Object.keys(pendingWatch).length) - return; - const signingKey = findSuitableSecretKeyId(externalContractState, [SPMessage.OP_KEY_DEL], ["sig"]); - const canMirrorOperations = !!signingKey; - if (!canMirrorOperations) { - console.info("[chelonia/private/watchForeignKeys]: Returning as operations cannot be mirrored", { externalContractID }); - return; - } - Object.entries(pendingWatch).forEach(([contractID, keys]) => { - if (!Array.isArray(keys) || // Check that the keys exist and haven't been revoked - !keys.reduce((acc, [, id]) => { - return acc || has(externalContractState._vm.authorizedKeys, id); - }, false)) { - console.info("[chelonia/private/watchForeignKeys]: Skipping as none of the keys to watch exist", { - externalContractID, - contractID - }); - return; - } - esm_default("chelonia/private/queueEvent", contractID, [ - "chelonia/private/in/syncContractAndWatchKeys", - contractID, - externalContractID - ]).catch((e2) => { - console.error(`Error at syncContractAndWatchKeys for contractID ${contractID} and externalContractID ${externalContractID}`, e2); - }); - }); - }, - "chelonia/private/in/syncContractAndWatchKeys": async function(contractID, externalContractID) { - const rootState = esm_default(this.config.stateSelector); - const externalContractState = rootState[externalContractID]; - const pendingWatch = externalContractState?._vm?.pendingWatch?.[contractID]?.splice(0); - if (!Array.isArray(pendingWatch) || // Check that the keys exist and haven't been revoked - !pendingWatch.reduce((acc, [, id]) => { - return acc || has(externalContractState._vm.authorizedKeys, id) && findKeyIdByName(externalContractState, externalContractState._vm.authorizedKeys[id].name) != null; - }, false)) { - console.info("[chelonia/private/syncContractAndWatchKeys]: Skipping as none of the keys to watch exist", { - externalContractID, - contractID - }); - return; - } - if (!this.subscriptionSet.has(contractID)) { - await esm_default("chelonia/private/in/syncContract", contractID); - } - const contractState = rootState[contractID]; - const keysToDelete = []; - const keysToUpdate = []; - pendingWatch.forEach(([keyName, externalId]) => { - const keyId2 = findKeyIdByName(contractState, keyName); - if (!keyId2) { - keysToDelete.push(externalId); - return; - } else if (keyId2 !== externalId) { - keysToUpdate.push(externalId); - } - if (!contractState._volatile) { - this.config.reactiveSet(contractState, "_volatile", Object.create(null, { - watch: { - value: [[keyName, externalContractID]], - configurable: true, - enumerable: true, - writable: true - } - })); } else { - if (!contractState._volatile.watch) { - this.config.reactiveSet(contractState._volatile, "watch", [ - [keyName, externalContractID] - ]); - } - if (Array.isArray(contractState._volatile.watch) && !contractState._volatile.watch.find((v2) => v2[0] === keyName && v2[1] === externalContractID)) { - contractState._volatile.watch.push([keyName, externalContractID]); - } - } - }); - if (keysToDelete.length || keysToUpdate.length) { - if (!externalContractState._volatile) { - this.config.reactiveSet(externalContractState, "_volatile", /* @__PURE__ */ Object.create(null)); - } - if (!externalContractState._volatile.pendingKeyRevocations) { - this.config.reactiveSet(externalContractState._volatile, "pendingKeyRevocations", /* @__PURE__ */ Object.create(null)); - } - keysToDelete.forEach((id) => this.config.reactiveSet(externalContractState._volatile.pendingKeyRevocations, id, "del")); - keysToUpdate.forEach((id) => this.config.reactiveSet(externalContractState._volatile.pendingKeyRevocations, id, true)); - esm_default("chelonia/private/queueEvent", externalContractID, [ - "chelonia/private/deleteOrRotateRevokedKeys", - externalContractID - ]).catch((e2) => { - console.error(`Error at deleteOrRotateRevokedKeys for contractID ${contractID} and externalContractID ${externalContractID}`, e2); - }); - } - }, - // The following function gets called when we start watching a contract for - // foreign keys for the first time, and it ensures that, at the point the - // watching starts, keys are in sync between the two contracts (later on, - // this will be handled automatically for incoming OP_KEY_DEL and - // OP_KEY_UPDATE). - // For any given foreign key, there are three possible states: - // 1. The key is in sync with the foreign contract. In this case, there's - // nothing left to do. - // 2. The key has been rotated in the foreign contract (replaced by another - // key of the same name). We need to mirror this operation manually - // since watching only affects new messages we receive. - // 3. The key has been removed in the foreign contract. We also need to - // mirror the operation. - "chelonia/private/deleteOrRotateRevokedKeys": function(contractID) { - const rootState = esm_default(this.config.stateSelector); - const contractState = rootState[contractID]; - const pendingKeyRevocations = contractState?._volatile?.pendingKeyRevocations; - if (!pendingKeyRevocations || Object.keys(pendingKeyRevocations).length === 0) - return; - const keysToUpdate = Object.entries(pendingKeyRevocations).filter(([, v2]) => v2 === true).map(([id]) => id); - const [, keyUpdateSigningKeyId, keyUpdateArgs] = keysToUpdate.reduce((acc, keyId2) => { - const key = contractState._vm?.authorizedKeys?.[keyId2]; - if (!key || !key.foreignKey) - return acc; - const foreignKey = String(key.foreignKey); - const fkUrl = new URL(foreignKey); - const foreignContractID = fkUrl.pathname; - const foreignKeyName = fkUrl.searchParams.get("keyName"); - if (!foreignKeyName) - throw new Error("Missing foreign key name"); - const foreignState = rootState[foreignContractID]; - if (!foreignState) - return acc; - const fKeyId = findKeyIdByName(foreignState, foreignKeyName); - if (!fKeyId) { - if (pendingKeyRevocations[keyId2] === true) { - this.config.reactiveSet(pendingKeyRevocations, keyId2, "del"); - } - return acc; - } - const [currentRingLevel, currentSigningKeyId, currentKeyArgs] = acc; - const ringLevel = Math.min(currentRingLevel, key.ringLevel ?? Number.POSITIVE_INFINITY); - if (ringLevel >= currentRingLevel) { - currentKeyArgs.push({ - name: key.name, - oldKeyId: keyId2, - id: fKeyId, - data: foreignState._vm.authorizedKeys[fKeyId].data - }); - return [currentRingLevel, currentSigningKeyId, currentKeyArgs]; - } else if (Number.isFinite(ringLevel)) { - const signingKeyId = findSuitableSecretKeyId(contractState, [SPMessage.OP_KEY_UPDATE], ["sig"], ringLevel); - if (signingKeyId) { - currentKeyArgs.push({ - name: key.name, - oldKeyId: keyId2, - id: fKeyId, - data: foreignState._vm.authorizedKeys[fKeyId].data - }); - return [ringLevel, signingKeyId, currentKeyArgs]; + if (fetching) { + return void 0; } - } - return acc; - }, [ - Number.POSITIVE_INFINITY, - "", - [] - ]); - if (keyUpdateArgs.length !== 0) { - const contractName = contractState._vm.type; - esm_default("chelonia/out/keyUpdate", { - contractID, - contractName, - data: keyUpdateArgs, - signingKeyId: keyUpdateSigningKeyId - }).catch((e2) => { - console.error(`[chelonia/private/deleteOrRotateRevokedKeys] Error sending OP_KEY_UPDATE for ${contractID}`, e2.message); - }); - } - const keysToDelete = Object.entries(pendingKeyRevocations).filter(([, v2]) => v2 === "del").map(([id]) => id); - const [, keyDelSigningKeyId, keyIdsToDelete] = keysToDelete.reduce((acc, keyId2) => { - const [currentRingLevel, currentSigningKeyId, currentKeyIds] = acc; - const ringLevel = Math.min(currentRingLevel, contractState._vm?.authorizedKeys?.[keyId2]?.ringLevel ?? Number.POSITIVE_INFINITY); - if (ringLevel >= currentRingLevel) { - currentKeyIds.push(keyId2); - return [currentRingLevel, currentSigningKeyId, currentKeyIds]; - } else if (Number.isFinite(ringLevel)) { - const signingKeyId = findSuitableSecretKeyId(contractState, [SPMessage.OP_KEY_DEL], ["sig"], ringLevel); - if (signingKeyId) { - currentKeyIds.push(keyId2); - return [ringLevel, signingKeyId, currentKeyIds]; + this.moveToTail(index); + if (updateAgeOnGet) { + this.updateItemAge(index); } + return value; } - return acc; - }, [Number.POSITIVE_INFINITY, "", []]); - if (keyIdsToDelete.length !== 0) { - const contractName = contractState._vm.type; - esm_default("chelonia/out/keyDel", { - contractID, - contractName, - data: keyIdsToDelete, - signingKeyId: keyDelSigningKeyId - }).catch((e2) => { - console.error(`[chelonia/private/deleteRevokedKeys] Error sending OP_KEY_DEL for ${contractID}`, e2.message); - }); - } - }, - "chelonia/private/respondToAllKeyRequests": function(contractID) { - const state = esm_default(this.config.stateSelector); - const contractState = state[contractID] ?? {}; - const pending = contractState?._vm?.pendingKeyshares; - if (!pending) - return; - const signingKeyId = findSuitableSecretKeyId(contractState, [SPMessage.OP_ATOMIC, SPMessage.OP_KEY_REQUEST_SEEN, SPMessage.OP_KEY_SHARE], ["sig"]); - if (!signingKeyId) { - console.log("Unable to respond to key request because there is no suitable secret key with OP_KEY_REQUEST_SEEN permission"); - return; } - Object.entries(pending).map(([hash3, entry]) => { - if (!Array.isArray(entry) || entry.length !== 4) { - return void 0; + } + connect(p, n) { + this.prev[n] = p; + this.next[p] = n; + } + moveToTail(index) { + if (index !== this.tail) { + if (index === this.head) { + this.head = this.next[index]; + } else { + this.connect(this.prev[index], this.next[index]); } - const [, , , [originatingContractID]] = entry; - return esm_default("chelonia/private/queueEvent", originatingContractID, [ - "chelonia/private/respondToKeyRequest", - contractID, - signingKeyId, - hash3 - ]).catch((e2) => { - console.error(`respondToAllKeyRequests: Error responding to key request ${hash3} from ${originatingContractID} to ${contractID}`, e2); - }); - }); - }, - "chelonia/private/respondToKeyRequest": async function(contractID, signingKeyId, hash3) { - const state = esm_default(this.config.stateSelector); - const contractState = state[contractID]; - const entry = contractState?._vm?.pendingKeyshares?.[hash3]; - const instance = this._instance; - if (!Array.isArray(entry) || entry.length !== 4) { - return; + this.connect(this.tail, index); + this.tail = index; } - const [keyShareEncryption, height, , [originatingContractID, rv, originatingContractHeight, headJSON]] = entry; - entry.pop(); - const krsEncryption = !!contractState._vm.authorizedKeys?.[signingKeyId]?._private; - await esm_default("chelonia/private/in/syncContract", originatingContractID); - if (instance !== this._instance) - return; - const originatingState = state[originatingContractID]; - const contractName = state.contracts[contractID].type; - const originatingContractName = originatingState._vm.type; - const v2 = signedIncomingData(originatingContractID, originatingState, rv, originatingContractHeight, headJSON).valueOf(); - const { encryptionKeyId } = v2; - const responseKey = encryptedIncomingData(contractID, contractState, v2.responseKey, height, this.transientSecretKeys, headJSON).valueOf(); - const deserializedResponseKey = deserializeKey(responseKey); - const responseKeyId = keyId(deserializedResponseKey); - Promise.resolve().then(() => { - if (instance !== this._instance) - return; - if (!has(originatingState._vm.authorizedKeys, responseKeyId) || originatingState._vm.authorizedKeys[responseKeyId]._notAfterHeight != null) { - throw new Error(`Unable to respond to key request for ${originatingContractID}. Key ${responseKeyId} is not valid.`); - } - esm_default("chelonia/storeSecretKeys", new Secret([{ key: deserializedResponseKey }])); - const keys = pick2(state.secretKeys, Object.entries(contractState._vm.authorizedKeys).filter(([, key]) => !!key.meta?.private?.shareable).map(([kId]) => kId)); - if (!keys || Object.keys(keys).length === 0) { - console.info("respondToAllKeyRequests: no keys to share", { - contractID, - originatingContractID - }); - return; - } - const keySharePayload = { - contractID, - keys: Object.entries(keys).map(([keyId2, key]) => ({ - id: keyId2, - meta: { - private: { - content: encryptedOutgoingData(originatingContractID, encryptionKeyId, key), - shareable: true + } + get del() { + deprecatedMethod("del", "delete"); + return this.delete; + } + delete(k) { + let deleted = false; + if (this.size !== 0) { + const index = this.keyMap.get(k); + if (index !== void 0) { + deleted = true; + if (this.size === 1) { + this.clear(); + } else { + this.removeItemSize(index); + const v2 = this.valList[index]; + if (this.isBackgroundFetch(v2)) { + v2.__abortController.abort(); + } else { + this.dispose(v2, k, "delete"); + if (this.disposeAfter) { + this.disposed.push([v2, k, "delete"]); } } - })), - keyRequestHash: hash3, - keyRequestHeight: height - }; - if (!contractState?._vm?.pendingKeyshares?.[hash3]) { - return; - } - return keySharePayload; - }).then((keySharePayload) => { - if (instance !== this._instance || !keySharePayload) - return; - return esm_default("chelonia/out/keyShare", { - contractID: originatingContractID, - contractName: originatingContractName, - data: keyShareEncryption ? encryptedOutgoingData(originatingContractID, findSuitablePublicKeyIds(originatingState, [SPMessage.OP_KEY_SHARE], ["enc"])?.[0] || "", keySharePayload) : keySharePayload, - signingKeyId: responseKeyId - }).then((msg) => { - if (instance !== this._instance) - return; - const payload = { keyRequestHash: hash3, keyShareHash: msg.hash(), success: true }; - const connectionKeyPayload = { - contractID: originatingContractID, - keys: [ - { - id: responseKeyId, - meta: { - private: { - content: encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_REQUEST_SEEN], ["enc"])?.[0] || "", responseKey), - shareable: true - } - } - } - ] - }; - esm_default("chelonia/out/atomic", { - contractID, - contractName, - signingKeyId, - data: [ - [ - "chelonia/out/keyRequestResponse", - { - data: krsEncryption ? encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_REQUEST_SEEN], ["enc"])?.[0] || "", payload) : payload - } - ], - [ - // Upon successful key share, we want to share deserializedResponseKey - // with ourselves - "chelonia/out/keyShare", - { - data: keyShareEncryption ? encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_SHARE], ["enc"])?.[0] || "", connectionKeyPayload) : connectionKeyPayload - } - ] - ] - }).catch((e2) => { - console.error("Error at respondToKeyRequest while sending keyRequestResponse", e2); - }); - }); - }).catch((e2) => { - console.error("Error at respondToKeyRequest", e2); - const payload = { keyRequestHash: hash3, success: false }; - if (!contractState?._vm?.pendingKeyshares?.[hash3]) { - return; - } - esm_default("chelonia/out/keyRequestResponse", { - contractID, - contractName, - signingKeyId, - data: krsEncryption ? encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_REQUEST_SEEN], ["enc"])?.[0] || "", payload) : payload - }).catch((e3) => { - console.error("Error at respondToKeyRequest while sending keyRequestResponse in error handler", e3); - }); - }); - }, - "chelonia/private/in/handleEvent": async function(contractID, rawMessage) { - const state = esm_default(this.config.stateSelector); - const { preHandleEvent, postHandleEvent, handleEventError } = this.config.hooks; - let processingErrored = false; - let message; - try { - if (!this.config.acceptAllMessages && !this.pending.some((entry) => entry?.contractID === contractID) && !this.subscriptionSet.has(contractID)) { - console.warn(`[chelonia] WARN: ignoring unexpected event for ${contractID}:`, rawMessage); - return; - } - const contractStateCopy = state[contractID] ? cloneDeep(state[contractID]) : /* @__PURE__ */ Object.create(null); - message = SPMessage.deserialize(rawMessage, this.transientSecretKeys, contractStateCopy, this.config.unwrapMaybeEncryptedData); - if (message.contractID() !== contractID) { - throw new Error(`[chelonia] Wrong contract ID. Expected ${contractID} but got ${message.contractID()}`); - } - if (!message.isFirstMessage() && (!has(state.contracts, contractID) || !has(state, contractID))) { - throw new ChelErrorUnrecoverable("The event is not for a first message but the contract state is missing"); - } - preHandleEvent?.(message); - const proceed = handleEvent.checkMessageOrdering.call(this, message); - if (proceed === false) - return; - if (state[contractID]?._volatile?.dirty) { - console.info(`[chelonia] Ignoring message ${message.description()} as the contract is marked as dirty`); - return; - } - const internalSideEffectStack = !this.config.skipSideEffects ? [] : void 0; - missingDecryptionKeyIdsMap.delete(message); - try { - await handleEvent.processMutation.call(this, message, contractStateCopy, internalSideEffectStack); - } catch (e_) { - const e2 = e_; - if (e2?.name === "ChelErrorDecryptionKeyNotFound") { - console.warn(`[chelonia] WARN '${e2.name}' in processMutation for ${message.description()}: ${e2.message}`, e2, message.serialize()); - if (e2.cause) { - const missingDecryptionKeyIds = missingDecryptionKeyIdsMap.get(message); - if (missingDecryptionKeyIds) { - missingDecryptionKeyIds.add(e2.cause); - } else { - missingDecryptionKeyIdsMap.set(message, /* @__PURE__ */ new Set([e2.cause])); - } + this.keyMap.delete(k); + this.keyList[index] = null; + this.valList[index] = null; + if (index === this.tail) { + this.tail = this.prev[index]; + } else if (index === this.head) { + this.head = this.next[index]; + } else { + this.next[this.prev[index]] = this.next[index]; + this.prev[this.next[index]] = this.prev[index]; } - } else { - console.error(`[chelonia] ERROR '${e2.name}' in processMutation for ${message.description()}: ${e2.message || e2}`, e2, message.serialize()); - } - console.warn(`[chelonia] Error processing ${message.description()}: ${message.serialize()}. Any side effects will be skipped!`); - if (this.config.strictProcessing) { - throw e2; - } - processingErrored = e2?.name !== "ChelErrorWarning"; - this.config.hooks.processError?.(e2, message, getMsgMeta.call(this, message, contractID, contractStateCopy)); - if (e2.name === "ChelErrorUnrecoverable" || e2.name === "ChelErrorForkedChain" || message.isFirstMessage()) { - throw e2; - } - } - if (!processingErrored) { - if (Array.isArray(internalSideEffectStack) && internalSideEffectStack.length > 0) { - await Promise.all(internalSideEffectStack.map((fn) => Promise.resolve(fn({ state: contractStateCopy, message })).catch((e_) => { - const e2 = e_; - console.error(`[chelonia] ERROR '${e2.name}' in internal side effect for ${message.description()}: ${e2.message}`, e2, { message: message.serialize() }); - }))); - } - if (!this.config.skipActionProcessing && !this.config.skipSideEffects) { - await handleEvent.processSideEffects.call(this, message, contractStateCopy)?.catch((e_) => { - const e2 = e_; - console.error(`[chelonia] ERROR '${e2.name}' in sideEffect for ${message.description()}: ${e2.message}`, e2, { message: message.serialize() }); - this.config.hooks.sideEffectError?.(e2, message); - }); + this.size--; + this.free.push(index); } } - try { - const state2 = esm_default(this.config.stateSelector); - await handleEvent.applyProcessResult.call(this, { - message, - state: state2, - contractState: contractStateCopy, - processingErrored, - postHandleEvent - }); - } catch (e_) { - const e2 = e_; - console.error(`[chelonia] ERROR '${e2.name}' for ${message.description()} marking the event as processed: ${e2.message}`, e2, { message: message.serialize() }); - } - } catch (e_) { - const e2 = e_; - console.error(`[chelonia] ERROR in handleEvent: ${e2.message || e2}`, e2); - try { - handleEventError?.(e2, message); - } catch (e22) { - console.error("[chelonia] Ignoring user error in handleEventError hook:", e22); - } - throw e2; - } finally { - if (message) { - missingDecryptionKeyIdsMap.delete(message); - } } - } - }); - eventsToReingest = []; - reprocessDebounced = debounce((contractID) => esm_default("chelonia/private/out/sync", contractID, { force: true }).catch((e2) => { - console.error(`[chelonia] Error at reprocessDebounced for ${contractID}`, e2); - }), 1e3); - handleEvent = { - checkMessageOrdering(message) { - const contractID = message.contractID(); - const hash3 = message.hash(); - const height = message.height(); - const state = esm_default(this.config.stateSelector); - const latestProcessedHeight = state.contracts[contractID]?.height; - if (!Number.isSafeInteger(height)) { - throw new ChelErrorDBBadPreviousHEAD(`Message ${hash3} in contract ${contractID} has an invalid height.`); - } - if (message.isFirstMessage() ? latestProcessedHeight != null : !(latestProcessedHeight < height)) { - if (!this.config.strictOrdering) { - return false; + if (this.disposed) { + while (this.disposed.length) { + this.disposeAfter(...this.disposed.shift()); } - throw new ChelErrorAlreadyProcessed(`Message ${hash3} with height ${height} in contract ${contractID} has already been processed. Current height: ${latestProcessedHeight}.`); } - if (latestProcessedHeight + 1 < height) { - if (this.config.strictOrdering) { - throw new ChelErrorDBBadPreviousHEAD(`Unexpected message ${hash3} with height ${height} in contract ${contractID}: height is too high. Current height: ${latestProcessedHeight}.`); - } - if (eventsToReingest.length > 100) { - throw new ChelErrorUnrecoverable("more than 100 different bad previousHEAD errors"); - } - if (!eventsToReingest.includes(hash3)) { - console.warn(`[chelonia] WARN bad previousHEAD for ${message.description()}, will attempt to re-sync contract to reingest message`); - eventsToReingest.push(hash3); - reprocessDebounced(contractID); - return false; + return deleted; + } + clear() { + for (const index of this.rindexes({ allowStale: true })) { + const v2 = this.valList[index]; + if (this.isBackgroundFetch(v2)) { + v2.__abortController.abort(); } else { - console.error(`[chelonia] ERROR already attempted to reingest ${message.description()}, will not attempt again!`); - throw new ChelErrorDBBadPreviousHEAD(`Already attempted to reingest ${hash3}`); + const k = this.keyList[index]; + this.dispose(v2, k, "delete"); + if (this.disposeAfter) { + this.disposed.push([v2, k, "delete"]); + } } } - const reprocessIdx = eventsToReingest.indexOf(hash3); - if (reprocessIdx !== -1) { - console.warn(`[chelonia] WARN: successfully reingested ${message.description()}`); - eventsToReingest.splice(reprocessIdx, 1); - } - }, - async processMutation(message, state, internalSideEffectStack) { - const contractID = message.contractID(); - if (message.isFirstMessage()) { - if (Object.keys(state).some((k) => k !== "_volatile")) { - throw new ChelErrorUnrecoverable(`state for ${contractID} is already set`); - } + this.keyMap.clear(); + this.valList.fill(null); + this.keyList.fill(null); + if (this.ttls) { + this.ttls.fill(0); + this.starts.fill(0); } - await esm_default("chelonia/private/in/processMessage", message, state, internalSideEffectStack); - }, - processSideEffects(message, state) { - const opT = message.opType(); - if (![ - SPMessage.OP_ATOMIC, - SPMessage.OP_ACTION_ENCRYPTED, - SPMessage.OP_ACTION_UNENCRYPTED - ].includes(opT)) { - return; + if (this.sizes) { + this.sizes.fill(0); } - const contractID = message.contractID(); - const manifestHash = message.manifest(); - const hash3 = message.hash(); - const height = message.height(); - const signingKeyId = message.signingKeyId(); - const callSideEffect = async (field) => { - const wv = this.config.unwrapMaybeEncryptedData(field); - if (!wv) - return; - let v2 = wv.data; - let innerSigningKeyId; - if (isSignedData(v2)) { - innerSigningKeyId = v2.signingKeyId; - v2 = v2.valueOf(); + this.head = 0; + this.tail = 0; + this.initialFill = 1; + this.free.length = 0; + this.calculatedSize = 0; + this.size = 0; + if (this.disposed) { + while (this.disposed.length) { + this.disposeAfter(...this.disposed.shift()); } - const { action, data, meta } = v2; - const mutation = { - data, - meta, - hash: hash3, - height, - contractID, - description: message.description(), - direction: message.direction(), - signingKeyId, - get signingContractID() { - return getContractIDfromKeyId(contractID, signingKeyId, state); - }, - innerSigningKeyId, - get innerSigningContractID() { - return getContractIDfromKeyId(contractID, innerSigningKeyId, state); - } - }; - return await esm_default(`${manifestHash}/${action}/sideEffect`, mutation, state); - }; - const msg = Object(message.message()); - if (opT !== SPMessage.OP_ATOMIC) { - return callSideEffect(msg); - } - const reducer = (acc, [opT2, opV]) => { - if ([SPMessage.OP_ACTION_ENCRYPTED, SPMessage.OP_ACTION_UNENCRYPTED].includes(opT2)) { - acc.push(Object(opV)); - } - return acc; - }; - const actionsOpV = msg.reduce(reducer, []); - return Promise.allSettled(actionsOpV.map((action) => callSideEffect(action))).then((results) => { - const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason); - if (errors.length > 0) { - console.error("Side-effect errors", contractID, errors); - throw new AggregateError(errors, `Error at side effects for ${contractID}`); - } - }); - }, - async applyProcessResult({ message, state, contractState, processingErrored, postHandleEvent }) { - const contractID = message.contractID(); - const hash3 = message.hash(); - const height = message.height(); - await esm_default("chelonia/db/addEntry", message); - if (!processingErrored) { - this.config.reactiveSet(state, contractID, contractState); - try { - postHandleEvent?.(message); - } catch (e2) { - console.error(`[chelonia] ERROR '${e2.name}' for ${message.description()} in event post-handling: ${e2.message}`, e2, { message: message.serialize() }); - } - } - if (message.isFirstMessage()) { - const { type } = message.opValue(); - if (!has(state.contracts, contractID)) { - this.config.reactiveSet(state.contracts, contractID, /* @__PURE__ */ Object.create(null)); - } - this.config.reactiveSet(state.contracts[contractID], "type", type); - console.debug(`contract ${type} registered for ${contractID}`); - } - if (message.isKeyOp()) { - this.config.reactiveSet(state.contracts[contractID], "previousKeyOp", hash3); - } - this.config.reactiveSet(state.contracts[contractID], "HEAD", hash3); - this.config.reactiveSet(state.contracts[contractID], "height", height); - const missingDecryptionKeyIdsForMessage = missingDecryptionKeyIdsMap.get(message); - if (missingDecryptionKeyIdsForMessage) { - let missingDecryptionKeyIds = state.contracts[contractID].missingDecryptionKeyIds; - if (!missingDecryptionKeyIds) { - missingDecryptionKeyIds = []; - this.config.reactiveSet(state.contracts[contractID], "missingDecryptionKeyIds", missingDecryptionKeyIds); - } - missingDecryptionKeyIdsForMessage.forEach((keyId2) => { - if (missingDecryptionKeyIds.includes(keyId2)) - return; - missingDecryptionKeyIds.push(keyId2); - }); - } - if (!this.subscriptionSet.has(contractID)) { - const entry = this.pending.find((entry2) => entry2?.contractID === contractID); - if (entry) { - const index = this.pending.indexOf(entry); - if (index !== -1) { - this.pending.splice(index, 1); - } - } - this.subscriptionSet.add(contractID); - esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { - added: [contractID], - removed: [] - }); - } - if (!processingErrored) { - esm_default("okTurtles.events/emit", hash3, contractID, message); - esm_default("okTurtles.events/emit", EVENT_HANDLED, contractID, message); } } + get reset() { + deprecatedMethod("reset", "clear"); + return this.clear; + } + get length() { + deprecatedProperty("length", "size"); + return this.size; + } + static get AbortController() { + return AC; + } + static get AbortSignal() { + return AS; + } }; - notImplemented = (v2) => { - throw new Error(`chelonia: action not implemented to handle: ${JSON.stringify(v2)}.`); - }; + module14.exports = LRUCache; } }); -var wallBase; -var monotonicBase; -var resyncTimeout; -var watchdog; -var syncServerTime; -var time_sync_default; -var init_time_sync = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/time-sync.mjs"() { - init_esm(); - wallBase = Date.now(); - monotonicBase = performance.now(); - syncServerTime = async function() { - const startTime = performance.now(); - const time3 = await this.config.fetch(`${this.config.connectionURL}/time`, { - signal: this.abortController.signal - }); - const requestTimeElapsed = performance.now(); - if (requestTimeElapsed - startTime > 8e3) { - throw new Error("Error fetching server time: request took too long"); - } - if (!time3.ok) - throw new Error("Error fetching server time"); - const serverTime = new Date(await time3.text()).valueOf(); - if (Number.isNaN(serverTime)) - throw new Error("Unable to parse server time"); - const newMonotonicBase = performance.now(); - wallBase = serverTime + (requestTimeElapsed - startTime) / 2 + // Also take into account the time elapsed between `requestTimeElapsed` - // and this line (which should be very little) - (newMonotonicBase - requestTimeElapsed); - monotonicBase = newMonotonicBase; - }; - time_sync_default = esm_default("sbp/selectors/register", { - "chelonia/private/startClockSync": function() { - if (resyncTimeout !== void 0) { - throw new Error("chelonia/private/startClockSync has already been called"); - } - const resync = (delay2 = 3e5) => { - if (resyncTimeout !== null) - return; - const timeout = setTimeout(() => { - syncServerTime.call(this).then(() => { - if (resyncTimeout === timeout) - resyncTimeout = null; - resync(); - }).catch((e2) => { - if (resyncTimeout === timeout) { - resyncTimeout = null; - console.error("Error re-syncing server time; will re-attempt in 5s", e2); - setTimeout(() => resync(0), 5e3); - } else { - console.error("Error re-syncing server time; another attempt is in progress", e2); - } - }); - }, delay2); - resyncTimeout = timeout; +var requiredMethodNames; +var DatabaseBackend; +var init_DatabaseBackend = __esm({ + "src/serve/DatabaseBackend.ts"() { + "use strict"; + requiredMethodNames = ["init", "clear", "readData", "writeData", "deleteData", "close", "iterKeys", "keyCount"]; + DatabaseBackend = class _DatabaseBackend { + constructor() { + if (new.target === _DatabaseBackend) { + throw new Error("Class DatabaseBackend cannot be instantiated directly."); + } + const bindMethod = (name) => { + this[name] = this[name].bind(this); }; - let wallLast = Date.now(); - let monotonicLast = performance.now(); - watchdog = setInterval(() => { - const wallNow = Date.now(); - const monotonicNow = performance.now(); - const difference2 = Math.abs(Math.abs(wallNow - wallLast) - Math.abs(monotonicNow - monotonicLast)); - if (difference2 > 10) { - if (resyncTimeout != null) - clearTimeout(resyncTimeout); - resyncTimeout = null; - resync(0); - } - wallLast = wallNow; - monotonicLast = monotonicNow; - }, 1e4); - resyncTimeout = null; - resync(0); - }, - "chelonia/private/stopClockSync": () => { - if (resyncTimeout !== void 0) { - if (watchdog != null) - clearInterval(watchdog); - if (resyncTimeout != null) - clearTimeout(resyncTimeout); - watchdog = void 0; - resyncTimeout = void 0; - } - }, - // Get an estimate of the server's current time based on the time elapsed as - // measured locally (using a monotonic clock), which is used as an offset, and - // a previously retrieved server time. The time value is returned as a UNIX - // _millisecond_ timestamp (milliseconds since 1 Jan 1970 00:00:00 UTC) - "chelonia/time": function() { - const monotonicNow = performance.now(); - const wallNow = wallBase - monotonicBase + monotonicNow; - return Math.round(wallNow); + for (const name of requiredMethodNames) { + bindMethod(name); + } } - }); + }; } }); -function contractNameFromAction(action) { - const regexResult = ACTION_REGEX.exec(action); - const contractName = regexResult?.[2]; - if (!contractName) - throw new Error(`Poorly named action '${action}': missing contract name.`); - return contractName; -} -function outputEncryptedOrUnencryptedMessage({ contractID, innerSigningKeyId, encryptionKeyId, signingKeyId, data, meta }) { - const state = esm_default(this.config.stateSelector)[contractID]; - const signedMessage = innerSigningKeyId ? state._vm.authorizedKeys[innerSigningKeyId] && state._vm.authorizedKeys[innerSigningKeyId]?._notAfterHeight == null ? signedOutgoingData(contractID, innerSigningKeyId, data, this.transientSecretKeys) : signedOutgoingDataWithRawKey(this.transientSecretKeys[innerSigningKeyId], data) : data; - const payload = !encryptionKeyId ? signedMessage : encryptedOutgoingData(contractID, encryptionKeyId, signedMessage); - const message = signedOutgoingData(contractID, signingKeyId, payload, this.transientSecretKeys); - const rootState = esm_default(this.config.stateSelector); - const height = String(rootState.contracts[contractID].height); - const serializedData = { ...message.serialize((meta ?? "") + height), height }; - return serializedData; -} -function parseEncryptedOrUnencryptedMessage(ctx, { contractID, serializedData, meta }) { - if (!serializedData) { - throw new TypeError("[chelonia] parseEncryptedOrUnencryptedMessage: serializedData is required"); - } - const state = esm_default(ctx.config.stateSelector)[contractID]; - const numericHeight = parseInt(serializedData.height); - const rootState = esm_default(ctx.config.stateSelector); - const currentHeight = rootState.contracts[contractID].height; - if (!(numericHeight >= 0) || !(numericHeight <= currentHeight)) { - throw new Error(`[chelonia] parseEncryptedOrUnencryptedMessage: Invalid height ${serializedData.height}; it must be between 0 and ${currentHeight}`); +var database_fs_exports = {}; +__export(database_fs_exports, { + default: () => FsBackend +}); +async function testCaseSensitivity(backend) { + const { readData, writeData, deleteData } = backend; + const date3 = /* @__PURE__ */ new Date(); + const dateString = date3.toISOString(); + const originalKey = `_private_testCaseSensitivity_${date3.getTime()}_${(0, Math.random)().toFixed(8).slice(2)}`; + const differentlyCasedKey = "_P" + originalKey.slice(2); + await writeData(originalKey, dateString); + try { + const valueOriginalCase = await readData(originalKey); + const valueDifferentCase = await readData(differentlyCasedKey); + if (valueOriginalCase?.toString() !== dateString) { + console.error(`Unexpected value on case-sensitivity test; expected ${dateString}`); + throw new Error("Unexpected value: original key does not have the correct value"); + } + if (valueDifferentCase?.toString() === dateString) { + const errStr = "Filesystem database backend only works on case-sensitive filesystems. This appears to be a case insensitive file system. Set `skipFsCaseSensitivityCheck: true` on the FS backend configuration to skip."; + console.error(errStr); + throw new Error(errStr); + } + } finally { + await deleteData(originalKey); } - const aad = (meta ?? "") + serializedData.height; - const v2 = signedIncomingData(contractID, state, serializedData, numericHeight, aad, (message) => { - return maybeEncryptedIncomingData(contractID, state, message, numericHeight, ctx.transientSecretKeys, aad, void 0); - }); - let encryptionKeyId; - let innerSigningKeyId; - const unwrap2 = /* @__PURE__ */ (() => { - let result2; - return () => { - if (!result2) { - try { - let unwrapped; - unwrapped = v2.valueOf(); - if (isEncryptedData(unwrapped)) { - encryptionKeyId = unwrapped.encryptionKeyId; - unwrapped = unwrapped.valueOf(); - if (isSignedData(unwrapped)) { - innerSigningKeyId = unwrapped.signingKeyId; - unwrapped = unwrapped.valueOf(); - } else { - innerSigningKeyId = null; - } - } else { - encryptionKeyId = null; - innerSigningKeyId = null; - } - result2 = [unwrapped]; - } catch (e2) { - result2 = [void 0, e2]; - } +} +var ConfigSchema; +var splitAndGroup; +var FsBackend; +var init_database_fs = __esm({ + "src/serve/database-fs.ts"() { + "use strict"; + init_db(); + init_zod(); + init_DatabaseBackend(); + ConfigSchema = strictObject({ + dirname: optional(string2()), + depth: optional(number2()), + keyChunkLength: optional(number2()), + skipFsCaseSensitivityCheck: optional(boolean2()) + }); + splitAndGroup = (input, chunkLength, depth) => input.slice(0, chunkLength * depth).split("").reduce((acc, cv, i2) => { + acc[i2 / chunkLength | 0] = (acc[i2 / chunkLength | 0] || "") + cv; + return acc; + }, []); + FsBackend = class extends DatabaseBackend { + dataFolder = "data"; + depth = 0; + keyChunkLength = 2; + skipFsCaseSensitivityCheck = false; + constructor(options2 = {}) { + super(); + ConfigSchema.parse(options2); + if (options2.dirname) this.dataFolder = resolve9(options2.dirname); + if (options2.depth) this.depth = options2.depth; + if (options2.keyChunkLength) this.keyChunkLength = options2.keyChunkLength; + if (options2.skipFsCaseSensitivityCheck) this.skipFsCaseSensitivityCheck = true; } - if (result2.length === 2) { - throw result2[1]; + // Maps a given key to a real path on the filesystem. + mapKey(key) { + if (basename9(normalize8(key)) !== key) throw new TypeError("Invalid key"); + if (!this.depth) return join9(this.dataFolder, key); + const keyChunks = splitAndGroup(key, this.keyChunkLength, this.depth); + return join9(this.dataFolder, ...keyChunks, key); } - return result2[0]; - }; - })(); - const result = { - get contractID() { - return contractID; - }, - get innerSigningKeyId() { - if (innerSigningKeyId === void 0) { - try { - unwrap2(); - } catch { + async init() { + await mkdir(this.dataFolder, { mode: 488, recursive: true }); + if (!this.skipFsCaseSensitivityCheck) { + await testCaseSensitivity(this); } } - return innerSigningKeyId; - }, - get encryptionKeyId() { - if (encryptionKeyId === void 0) { - try { - unwrap2(); - } catch { - } + async clear() { + const names = await readdir(this.dataFolder); + const paths = names.map((name) => join9(this.dataFolder, name)); + await Promise.all( + paths.map((p) => rm(p, { recursive: true })) + ); } - return encryptionKeyId; - }, - get signingKeyId() { - return v2.signingKeyId; - }, - get data() { - return unwrap2(); - }, - get signingContractID() { - return getContractIDfromKeyId(contractID, result.signingKeyId, state); - }, - get innerSigningContractID() { - return getContractIDfromKeyId(contractID, result.innerSigningKeyId, state); - } - }; - return result; -} -async function outEncryptedOrUnencryptedAction(opType, params) { - const { atomic, action, contractID, data, hooks, publishOptions } = params; - const contractName = contractNameFromAction(action); - const manifestHash = this.config.contracts.manifests[contractName]; - const { contract } = this.manifestToContract[manifestHash]; - const state = contract.state(contractID); - const meta = await contract.metadata.create(); - const unencMessage = { action, data, meta }; - const signedMessage = params.innerSigningKeyId ? state._vm.authorizedKeys[params.innerSigningKeyId] && state._vm.authorizedKeys[params.innerSigningKeyId]?._notAfterHeight == null ? signedOutgoingData(contractID, params.innerSigningKeyId, unencMessage, this.transientSecretKeys) : signedOutgoingDataWithRawKey(this.transientSecretKeys[params.innerSigningKeyId], unencMessage) : unencMessage; - if (opType === SPMessage.OP_ACTION_ENCRYPTED && !params.encryptionKeyId) { - throw new Error("OP_ACTION_ENCRYPTED requires an encryption key ID be given"); - } - if (params.encryptionKey) { - if (params.encryptionKeyId !== keyId(params.encryptionKey)) { - throw new Error("OP_ACTION_ENCRYPTED raw encryption key does not match encryptionKeyId"); - } - } - const payload = opType === SPMessage.OP_ACTION_UNENCRYPTED ? signedMessage : params.encryptionKey ? encryptedOutgoingDataWithRawKey(params.encryptionKey, signedMessage) : encryptedOutgoingData(contractID, params.encryptionKeyId, signedMessage); - let message = SPMessage.createV1_0({ - contractID, - op: [ - opType, - signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) - ], - manifest: manifestHash - }); - if (!atomic) { - message = await esm_default("chelonia/private/out/publishEvent", message, publishOptions, hooks); - } - return message; -} -function gettersProxy(state, getters) { - const proxyGetters = new Proxy({}, { - get(_target, prop) { - return getters[prop](state, proxyGetters); - } - }); - return { getters: proxyGetters }; -} -var ACTION_REGEX; -var chelonia_default; -var init_chelonia = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/chelonia.mjs"() { - init_esm2(); - init_esm4(); - init_esm(); - init_esm5(); - init_functions(); - init_pubsub(); - init_esm7(); - init_errors3(); - init_events(); - init_SPMessage(); - init_chelonia_utils(); - init_encryptedData(); - init_files(); - init_internals(); - init_signedData(); - init_time_sync(); - init_utils(); - ACTION_REGEX = /^((([\w.]+)\/([^/]+))(?:\/(?:([^/]+)\/)?)?)\w*/; - chelonia_default = esm_default("sbp/selectors/register", { - // https://www.wordnik.com/words/chelonia - // https://gitlab.okturtles.org/okturtles/group-income/-/wikis/E2E-Protocol/Framework.md#alt-names - "chelonia/_init": function() { - this.config = { - // TODO: handle connecting to multiple servers for federation - get connectionURL() { - throw new Error("Invalid use of connectionURL before initialization"); - }, - // override! - set connectionURL(value) { - Object.defineProperty(this, "connectionURL", { value, writable: true }); - }, - stateSelector: "chelonia/private/state", - // override to integrate with, for example, vuex - contracts: { - defaults: { - modules: {}, - // '' => resolved module import - exposedGlobals: {}, - allowedDomains: [], - allowedSelectors: [], - preferSlim: false - }, - overrides: {}, - // override default values per-contract - manifests: {} - // override! contract names => manifest hashes - }, - whitelisted: (action) => !!this.whitelistedActions[action], - reactiveSet: (obj, key, value) => { - obj[key] = value; - return value; - }, - // example: set to Vue.set - fetch: (...args) => fetch(...args), - reactiveDel: (obj, key) => { - delete obj[key]; - }, - // acceptAllMessages disables checking whether we are expecting a message - // or not for processing - acceptAllMessages: false, - skipActionProcessing: false, - skipDecryptionAttempts: false, - skipSideEffects: false, - // Strict processing will treat all processing errors as unrecoverable - // This is useful, e.g., in the server, to prevent invalid messages from - // being added to the database - strictProcessing: false, - // Strict ordering will throw on past events with ChelErrorAlreadyProcessed - // Similarly, future events will not be reingested and will throw - // with ChelErrorDBBadPreviousHEAD - strictOrdering: false, - connectionOptions: { - maxRetries: Infinity, - // See https://github.com/okTurtles/group-income/issues/1183 - reconnectOnTimeout: true - // can be enabled since we are not doing auth via web sockets - }, - hooks: { - preHandleEvent: null, - // async (message: SPMessage) => {} - postHandleEvent: null, - // async (message: SPMessage) => {} - processError: null, - // (e: Error, message: SPMessage) => {} - sideEffectError: null, - // (e: Error, message: SPMessage) => {} - handleEventError: null, - // (e: Error, message: SPMessage) => {} - syncContractError: null, - // (e: Error, contractID: string) => {} - pubsubError: null - // (e:Error, socket: Socket) - }, - unwrapMaybeEncryptedData - }; - this._instance = /* @__PURE__ */ Object.create(null); - this.abortController = new AbortController(); - this.state = { - contracts: {}, - // contractIDs => { type, HEAD } (contracts we've subscribed to) - pending: [] - // prevents processing unexpected data from a malicious server - }; - this.manifestToContract = {}; - this.whitelistedActions = {}; - this.currentSyncs = /* @__PURE__ */ Object.create(null); - this.postSyncOperations = /* @__PURE__ */ Object.create(null); - this.sideEffectStacks = /* @__PURE__ */ Object.create(null); - this.sideEffectStack = (contractID) => { - let stack = this.sideEffectStacks[contractID]; - if (!stack) { - this.sideEffectStacks[contractID] = stack = []; - } - return stack; - }; - this.setPostSyncOp = (contractID, key, op) => { - this.postSyncOperations[contractID] = this.postSyncOperations[contractID] || /* @__PURE__ */ Object.create(null); - this.postSyncOperations[contractID][key] = op; - }; - const secretKeyGetter = (o2, p) => { - if (has(o2, p)) - return o2[p]; - const rootState = esm_default(this.config.stateSelector); - if (rootState?.secretKeys && has(rootState.secretKeys, p)) { - const key = deserializeKey(rootState.secretKeys[p]); - o2[p] = key; - return key; - } - }; - const secretKeyList = (o2) => { - const rootState = esm_default(this.config.stateSelector); - const stateKeys = Object.keys(rootState?.secretKeys || {}); - return Array.from(/* @__PURE__ */ new Set([...Object.keys(o2), ...stateKeys])); - }; - this.transientSecretKeys = new Proxy(/* @__PURE__ */ Object.create(null), { - get: secretKeyGetter, - ownKeys: secretKeyList - }); - this.ephemeralReferenceCount = /* @__PURE__ */ Object.create(null); - this.subscriptionSet = /* @__PURE__ */ new Set(); - this.pending = []; - }, - "chelonia/config": function() { - return { - ...cloneDeep(this.config), - fetch: this.config.fetch, - reactiveSet: this.config.reactiveSet, - reactiveDel: this.config.reactiveDel - }; - }, - "chelonia/configure": async function(config2) { - merge2(this.config, config2); - Object.assign(this.config.hooks, config2.hooks || {}); - if (config2.contracts) { - Object.assign(this.config.contracts.defaults, config2.contracts.defaults || {}); - const manifests = this.config.contracts.manifests; - console.debug("[chelonia] preloading manifests:", Object.keys(manifests)); - for (const contractName in manifests) { - await esm_default("chelonia/private/loadManifest", contractName, manifests[contractName]); - } - } - if (has(config2, "skipDecryptionAttempts")) { - if (config2.skipDecryptionAttempts) { - this.config.unwrapMaybeEncryptedData = (data) => { - if (data == null) - return; - if (!isEncryptedData(data)) { - return { - encryptionKeyId: null, - data - }; - } - }; - } else { - this.config.unwrapMaybeEncryptedData = unwrapMaybeEncryptedData; - } - } - }, - "chelonia/reset": async function(newState, postCleanupFn) { - if (typeof newState === "function" && typeof postCleanupFn === "undefined") { - postCleanupFn = newState; - newState = void 0; - } - if (this.pubsub) { - esm_default("chelonia/private/stopClockSync"); - } - Object.keys(this.postSyncOperations).forEach((cID) => { - esm_default("chelonia/private/enqueuePostSyncOps", cID); - }); - await esm_default("chelonia/contract/waitPublish"); - await esm_default("chelonia/contract/wait"); - Object.keys(this.postSyncOperations).forEach((cID) => { - esm_default("chelonia/private/enqueuePostSyncOps", cID); - }); - await esm_default("chelonia/contract/waitPublish"); - await esm_default("chelonia/contract/wait"); - const result = await postCleanupFn?.(); - const rootState = esm_default(this.config.stateSelector); - this._instance = /* @__PURE__ */ Object.create(null); - this.abortController.abort(); - this.abortController = new AbortController(); - reactiveClearObject(rootState, this.config.reactiveDel); - this.config.reactiveSet(rootState, "contracts", /* @__PURE__ */ Object.create(null)); - clearObject(this.ephemeralReferenceCount); - this.pending.splice(0); - clearObject(this.currentSyncs); - clearObject(this.postSyncOperations); - clearObject(this.sideEffectStacks); - const removedContractIDs = Array.from(this.subscriptionSet); - this.subscriptionSet.clear(); - esm_default("chelonia/clearTransientSecretKeys"); - esm_default("okTurtles.events/emit", CHELONIA_RESET); - esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { - added: [], - removed: removedContractIDs - }); - if (this.pubsub) { - esm_default("chelonia/private/startClockSync"); - } - if (newState) { - Object.entries(newState).forEach(([key, value]) => { - this.config.reactiveSet(rootState, key, value); - }); - } - return result; - }, - "chelonia/storeSecretKeys": function(wkeys) { - const rootState = esm_default(this.config.stateSelector); - if (!rootState.secretKeys) { - this.config.reactiveSet(rootState, "secretKeys", /* @__PURE__ */ Object.create(null)); - } - let keys = wkeys.valueOf(); - if (!keys) - return; - if (!Array.isArray(keys)) - keys = [keys]; - keys.forEach(({ key, transient }) => { - if (!key) - return; - if (typeof key === "string") { - key = deserializeKey(key); - } - const id = keyId(key); - if (!has(this.transientSecretKeys, id)) { - this.transientSecretKeys[id] = key; - } - if (transient) - return; - if (!has(rootState.secretKeys, id)) { - this.config.reactiveSet(rootState.secretKeys, id, serializeKey(key, true)); - } - }); - }, - "chelonia/clearTransientSecretKeys": function(ids) { - if (Array.isArray(ids)) { - ids.forEach((id) => { - delete this.transientSecretKeys[id]; - }); - } else { - Object.keys(this.transientSecretKeys).forEach((id) => { - delete this.transientSecretKeys[id]; - }); - } - }, - "chelonia/haveSecretKey": function(keyId2, persistent) { - if (!persistent && has(this.transientSecretKeys, keyId2)) - return true; - const rootState = esm_default(this.config.stateSelector); - return !!rootState?.secretKeys && has(rootState.secretKeys, keyId2); - }, - "chelonia/contract/isResyncing": function(contractIDOrState) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - return !!contractIDOrState?._volatile?.dirty || !!contractIDOrState?._volatile?.resyncing; - }, - "chelonia/contract/hasKeyShareBeenRespondedBy": function(contractIDOrState, requestedToContractID, reference) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - const result = Object.values(contractIDOrState?._vm.authorizedKeys || {}).some((r) => { - return r?.meta?.keyRequest?.responded && r.meta.keyRequest.contractID === requestedToContractID && (!reference || r.meta.keyRequest.reference === reference); + async readData(key) { + checkKey(key); + return await readFile(this.mapKey(key)).catch((err) => { + if (err.code !== "ENOENT") throw err; }); - return result; - }, - "chelonia/contract/waitingForKeyShareTo": function(contractIDOrState, requestingContractID, reference) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - const result = contractIDOrState._volatile?.pendingKeyRequests?.filter((r) => { - return r && (!requestingContractID || r.contractID === requestingContractID) && (!reference || r.reference === reference); - })?.map(({ name }) => name); - if (!result?.length) - return null; - return result; - }, - "chelonia/contract/successfulKeySharesByContractID": function(contractIDOrState, requestingContractID) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - const keyShares = Object.values(contractIDOrState._vm.keyshares || {}); - if (!keyShares?.length) - return; - const result = /* @__PURE__ */ Object.create(null); - keyShares.forEach((kS) => { - if (!kS.success) - return; - if (requestingContractID && kS.contractID !== requestingContractID) + } + async writeData(key, value) { + const path8 = this.mapKey(key); + if (this.depth) await mkdir(dirname9(path8), { mode: 488, recursive: true }); + await writeFile(path8, value); + } + async deleteData(key) { + await unlink(this.mapKey(key)).catch((e2) => { + if (e2?.code === "ENOENT") { return; - if (!result[kS.contractID]) - result[kS.contractID] = []; - result[kS.contractID].push({ height: kS.height, hash: kS.hash }); - }); - Object.keys(result).forEach((cID) => { - result[cID].sort((a, b) => { - return b.height - a.height; - }); - }); - return result; - }, - "chelonia/contract/hasKeysToPerformOperation": function(contractIDOrState, operation) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - const op = operation !== "*" ? [operation] : operation; - return !!findSuitableSecretKeyId(contractIDOrState, op, ["sig"]); - }, - // Did sourceContractIDOrState receive an OP_KEY_SHARE to perform the given - // operation on contractIDOrState? - "chelonia/contract/receivedKeysToPerformOperation": function(sourceContractIDOrState, contractIDOrState, operation) { - const rootState = esm_default(this.config.stateSelector); - if (typeof sourceContractIDOrState === "string") { - sourceContractIDOrState = rootState[sourceContractIDOrState]; - } - if (typeof contractIDOrState === "string") { - contractIDOrState = rootState[contractIDOrState]; - } - const op = operation !== "*" ? [operation] : operation; - const keyId2 = findSuitableSecretKeyId(contractIDOrState, op, ["sig"]); - return sourceContractIDOrState?._vm?.sharedKeyIds?.some((sK) => sK.id === keyId2); - }, - "chelonia/contract/currentKeyIdByName": function(contractIDOrState, name, requireSecretKey) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - const currentKeyId = findKeyIdByName(contractIDOrState, name); - if (requireSecretKey && !esm_default("chelonia/haveSecretKey", currentKeyId)) { - return; - } - return currentKeyId; - }, - "chelonia/contract/foreignKeysByContractID": function(contractIDOrState, foreignContractID) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - return findForeignKeysByContractID(contractIDOrState, foreignContractID); - }, - "chelonia/contract/historicalKeyIdsByName": function(contractIDOrState, name) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - const currentKeyId = findKeyIdByName(contractIDOrState, name); - const revokedKeyIds = findRevokedKeyIdsByName(contractIDOrState, name); - return currentKeyId ? [currentKeyId, ...revokedKeyIds] : revokedKeyIds; - }, - "chelonia/contract/suitableSigningKey": function(contractIDOrState, permissions, purposes, ringLevel, allowedActions) { - if (typeof contractIDOrState === "string") { - const rootState = esm_default(this.config.stateSelector); - contractIDOrState = rootState[contractIDOrState]; - } - const keyId2 = findSuitableSecretKeyId(contractIDOrState, permissions, purposes, ringLevel, allowedActions); - return keyId2; - }, - "chelonia/contract/setPendingKeyRevocation": function(contractID, names) { - const rootState = esm_default(this.config.stateSelector); - const state = rootState[contractID]; - if (!state._volatile) - this.config.reactiveSet(state, "_volatile", /* @__PURE__ */ Object.create(null)); - if (!state._volatile.pendingKeyRevocations) { - this.config.reactiveSet(state._volatile, "pendingKeyRevocations", /* @__PURE__ */ Object.create(null)); - } - for (const name of names) { - const keyId2 = findKeyIdByName(state, name); - if (keyId2) { - this.config.reactiveSet(state._volatile.pendingKeyRevocations, keyId2, true); - } else { - console.warn("[setPendingKeyRevocation] Unable to find keyId for name", { - contractID, - name - }); - } - } - }, - "chelonia/shelterAuthorizationHeader"(contractID) { - return buildShelterAuthorizationHeader.call(this, contractID); - }, - // The purpose of the 'chelonia/crypto/*' selectors is so that they can be called - // from contracts without including the crypto code (i.e., importing crypto.js) - // This function takes a function as a parameter that returns a string - // It does not a string directly to prevent accidentally logging the value, - // which is a secret - "chelonia/crypto/keyId": (inKey) => { - return keyId(inKey.valueOf()); - }, - // TODO: allow connecting to multiple servers at once - "chelonia/connect": function(options2 = {}) { - if (!this.config.connectionURL) - throw new Error("config.connectionURL missing"); - if (!this.config.connectionOptions) - throw new Error("config.connectionOptions missing"); - if (this.pubsub) { - this.pubsub.destroy(); - } - let pubsubURL = this.config.connectionURL; - if (true) { - pubsubURL += `?debugID=${randomHexString(6)}`; - } - if (this.pubsub) { - esm_default("chelonia/private/stopClockSync"); - } - esm_default("chelonia/private/startClockSync"); - this.pubsub = createClient(pubsubURL, { - ...this.config.connectionOptions, - handlers: { - ...options2.handlers, - // Every time we get a REQUEST_TYPE.SUB response, which happens for - // 'new' subscriptions as well as every time the connection is reset - "subscription-succeeded": function(event) { - const { channelID } = event.detail; - if (this.subscriptionSet.has(channelID)) { - esm_default("chelonia/private/out/sync", channelID, { force: true }).catch((err) => { - console.warn(`[chelonia] Syncing contract ${channelID} failed: ${err.message}`); - }); - } - options2.handlers?.["subscription-succeeded"]?.call(this, event); - } - }, - // Map message handlers to transparently handle encryption and signatures - messageHandlers: { - ...Object.fromEntries(Object.entries(options2.messageHandlers || {}).map(([k, v2]) => { - switch (k) { - case NOTIFICATION_TYPE.PUB: - return [ - k, - (msg) => { - if (!msg.channelID) { - console.info("[chelonia] Discarding pub event without channelID"); - return; - } - if (!this.subscriptionSet.has(msg.channelID)) { - console.info(`[chelonia] Discarding pub event for ${msg.channelID} because it's not in the current subscriptionSet`); - return; - } - esm_default("chelonia/queueInvocation", msg.channelID, () => { - v2.call(this.pubsub, parseEncryptedOrUnencryptedMessage(this, { - contractID: msg.channelID, - serializedData: msg.data - })); - }).catch((e2) => { - console.error(`[chelonia] Error processing pub event for ${msg.channelID}`, e2); - }); - } - ]; - case NOTIFICATION_TYPE.KV: - return [ - k, - (msg) => { - if (!msg.channelID || !msg.key) { - console.info("[chelonia] Discarding kv event without channelID or key"); - return; - } - if (!this.subscriptionSet.has(msg.channelID)) { - console.info(`[chelonia] Discarding kv event for ${msg.channelID} because it's not in the current subscriptionSet`); - return; - } - esm_default("chelonia/queueInvocation", msg.channelID, () => { - v2.call(this.pubsub, [ - msg.key, - parseEncryptedOrUnencryptedMessage(this, { - contractID: msg.channelID, - meta: msg.key, - serializedData: JSON.parse(Buffer6.from(msg.data).toString()) - }) - ]); - }).catch((e2) => { - console.error(`[chelonia] Error processing kv event for ${msg.channelID} and key ${msg.key}`, msg, e2); - }); - } - ]; - case NOTIFICATION_TYPE.DELETION: - return [ - k, - (msg) => v2.call(this.pubsub, msg.data) - ]; - default: - return [k, v2]; - } - })), - [NOTIFICATION_TYPE.ENTRY](msg) { - const { contractID } = SPMessage.deserializeHEAD(msg.data); - esm_default("chelonia/private/in/enqueueHandleEvent", contractID, msg.data); - } } + throw e2; }); - if (!this.contractsModifiedListener) { - this.contractsModifiedListener = () => esm_default("chelonia/pubsub/update"); - esm_default("okTurtles.events/on", CONTRACTS_MODIFIED, this.contractsModifiedListener); - } - return this.pubsub; - }, - // This selector is defined primarily for ingesting web push notifications, - // although it can be used as a general-purpose API to process events received - // from other external sources that are not managed by Chelonia itself (i.e. sources - // other than the Chelonia-managed websocket connection and RESTful API). - "chelonia/handleEvent": async function(event) { - const { contractID } = SPMessage.deserializeHEAD(event); - return await esm_default("chelonia/private/in/enqueueHandleEvent", contractID, event); - }, - "chelonia/defineContract": function(contract) { - if (!ACTION_REGEX.exec(contract.name)) - throw new Error(`bad contract name: ${contract.name}`); - if (!contract.metadata) - contract.metadata = { validate() { - }, create: () => ({}) }; - if (!contract.getters) - contract.getters = {}; - contract.state = (contractID) => esm_default(this.config.stateSelector)[contractID]; - contract.manifest = this.defContractManifest; - contract.sbp = this.defContractSBP; - this.defContractSelectors = []; - this.defContract = contract; - this.defContractSelectors.push(...esm_default("sbp/selectors/register", { - // expose getters for Vuex integration and other conveniences - [`${contract.manifest}/${contract.name}/getters`]: () => contract.getters, - // 2 ways to cause sideEffects to happen: by defining a sideEffect function in the - // contract, or by calling /pushSideEffect w/async SBP call. Can also do both. - [`${contract.manifest}/${contract.name}/pushSideEffect`]: (contractID, asyncSbpCall) => { - const [sel] = asyncSbpCall; - if (sel.startsWith(contract.name + "/")) { - asyncSbpCall[0] = `${contract.manifest}/${sel}`; - } - this.sideEffectStack(contractID).push(asyncSbpCall); - } - })); - for (const action in contract.actions) { - contractNameFromAction(action); - this.whitelistedActions[action] = true; - this.defContractSelectors.push(...esm_default("sbp/selectors/register", { - [`${contract.manifest}/${action}/process`]: async (message, state) => { - const { meta, data, contractID } = message; - state = state || contract.state(contractID); - const gProxy = gettersProxy(state, contract.getters); - await contract.metadata.validate(meta, { state, ...gProxy, contractID }); - await contract.actions[action].validate(data, { - state, - ...gProxy, - meta, - message, - contractID - }); - this.sideEffectStacks[contractID] = []; - await contract.actions[action].process(message, { state, ...gProxy }); - }, - // 'mutation' is an object that's similar to 'message', but not identical - [`${contract.manifest}/${action}/sideEffect`]: async (mutation, state) => { - if (contract.actions[action].sideEffect) { - state = state || contract.state(mutation.contractID); - if (!state) { - console.warn(`[${contract.manifest}/${action}/sideEffect]: Skipping side-effect since there is no contract state for contract ${mutation.contractID}`); - return; - } - const stateCopy = cloneDeep(state); - const gProxy = gettersProxy(stateCopy, contract.getters); - await contract.actions[action].sideEffect(mutation, { state: stateCopy, ...gProxy }); - } - const sideEffects = this.sideEffectStack(mutation.contractID); - while (sideEffects.length > 0) { - const sideEffect = sideEffects.shift(); - try { - await contract.sbp(...sideEffect); - } catch (e_) { - const e2 = e_; - console.error(`[chelonia] ERROR: '${e2.name}' ${e2.message}, for pushed sideEffect of ${mutation.description}:`, sideEffect); - this.sideEffectStacks[mutation.contractID] = []; - throw e2; - } - } - } - })); - } - for (const method in contract.methods) { - this.defContractSelectors.push(...esm_default("sbp/selectors/register", { - [`${contract.manifest}/${method}`]: contract.methods[method] - })); - } - esm_default("okTurtles.events/emit", CONTRACT_REGISTERED, contract); - }, - "chelonia/queueInvocation": (contractID, sbpInvocation) => { - return esm_default("chelonia/private/queueEvent", contractID, ["chelonia/private/noop"]).then(() => esm_default("chelonia/private/queueEvent", "public:" + contractID, sbpInvocation)); - }, - "chelonia/begin": async (...invocations) => { - for (const invocation of invocations) { - await esm_default(...invocation); - } - }, - // call this manually to resubscribe/unsubscribe from contracts as needed - // if you are using a custom stateSelector and reload the state (e.g. upon login) - "chelonia/pubsub/update": function() { - const client = this.pubsub; - const subscribedIDs = [...client.subscriptionSet]; - const currentIDs = Array.from(this.subscriptionSet); - const leaveSubscribed = intersection2(subscribedIDs, currentIDs); - const toUnsubscribe = difference(subscribedIDs, leaveSubscribed); - const toSubscribe = difference(currentIDs, leaveSubscribed); - try { - for (const contractID of toUnsubscribe) { - client.unsub(contractID); - } - for (const contractID of toSubscribe) { - client.sub(contractID); + } + close() { + } + async *iterKeys() { + const entries = await readdir(this.dataFolder, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isFile()) { + yield entry.name; } - } catch (e2) { - console.error(`[chelonia] pubsub/update: error ${e2.name}: ${e2.message}`, { toUnsubscribe, toSubscribe }, e2); - this.config.hooks.pubsubError?.(e2, client); } - }, - // resolves when all pending actions for these contractID(s) finish - "chelonia/contract/wait": function(contractIDs) { - const listOfIds = contractIDs ? typeof contractIDs === "string" ? [contractIDs] : contractIDs : Object.keys(esm_default(this.config.stateSelector).contracts); - return Promise.all(listOfIds.flatMap((cID) => { - return esm_default("chelonia/queueInvocation", cID, ["chelonia/private/noop"]); - })); - }, - // resolves when all pending *writes* for these contractID(s) finish - "chelonia/contract/waitPublish": function(contractIDs) { - const listOfIds = contractIDs ? typeof contractIDs === "string" ? [contractIDs] : contractIDs : Object.keys(esm_default(this.config.stateSelector).contracts); - return Promise.all(listOfIds.flatMap((cID) => { - return esm_default("chelonia/private/queueEvent", `publish:${cID}`, ["chelonia/private/noop"]); - })); - }, - // 'chelonia/contract' - selectors related to injecting remote data and monitoring contracts - // TODO: add an optional parameter to "retain" the contract (see #828) - // eslint-disable-next-line require-await - "chelonia/contract/sync": async function(contractIDs, params) { - const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; - listOfIds.forEach((id) => { - if (checkCanBeGarbageCollected.call(this, id)) { - if (process.env.CI) { - Promise.reject(new Error("[chelonia] Missing reference count for contract " + id)); - } - console.error("[chelonia] Missing reference count for contract " + id); - throw new Error("Missing reference count for contract"); - } - }); - return esm_default("chelonia/private/out/sync", listOfIds, { ...params, force: true }); - }, - "chelonia/contract/isSyncing": function(contractID, { firstSync = false } = {}) { - const isSyncing = !!this.currentSyncs[contractID]; - return firstSync ? isSyncing && this.currentSyncs[contractID].firstSync : isSyncing; - }, - "chelonia/contract/currentSyncs": function() { - return Object.keys(this.currentSyncs); - }, - // Because `/remove` is done asynchronously and a contract might be removed - // much later than when the call to remove was made, an optional callback - // can be passed to verify whether to proceed with removal. This is used as - // part of the `/release` mechanism to prevent removing contracts that have - // acquired new references since the call to `/remove`. - "chelonia/contract/remove": function(contractIDs, { confirmRemovalCallback, permanent } = {}) { - const rootState = esm_default(this.config.stateSelector); - const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; - return Promise.all(listOfIds.map((contractID) => { - if (!rootState?.contracts?.[contractID]) { - return void 0; - } - return esm_default("chelonia/private/queueEvent", contractID, () => { - if (confirmRemovalCallback && !confirmRemovalCallback(contractID)) { - return; - } - const rootState2 = esm_default(this.config.stateSelector); - const fkContractIDs = Array.from(new Set(Object.values(rootState2[contractID]?._vm?.authorizedKeys ?? {}).filter((k) => { - return !!k.foreignKey; - }).map((k) => { - try { - const fkUrl = new URL(k.foreignKey); - return fkUrl.pathname; - } catch { - return void 0; - } - }).filter(Boolean))); - esm_default("chelonia/private/removeImmediately", contractID, { permanent }); - if (fkContractIDs.length) { - esm_default("chelonia/contract/release", fkContractIDs, { try: true }).catch((e2) => { - console.error("[chelonia] Error attempting to release foreign key contracts", e2); - }); - } - }); - })); - }, - "chelonia/contract/retain": async function(contractIDs, params) { - const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; - const rootState = esm_default(this.config.stateSelector); - if (listOfIds.length === 0) - return Promise.resolve(); - const checkIfDeleted = (id) => { - if (rootState.contracts[id] === null) { - console.error("[chelonia/contract/retain] Called /retain on permanently deleted contract.", id); - throw new ChelErrorResourceGone("Unable to retain permanently deleted contract " + id); - } - }; - if (!params?.ephemeral) { - listOfIds.forEach((id) => { - checkIfDeleted(id); - if (!has(rootState.contracts, id)) { - this.config.reactiveSet(rootState.contracts, id, /* @__PURE__ */ Object.create(null)); - } - this.config.reactiveSet(rootState.contracts[id], "references", (rootState.contracts[id].references ?? 0) + 1); - }); - } else { - listOfIds.forEach((id) => { - checkIfDeleted(id); - if (!has(this.ephemeralReferenceCount, id)) { - this.ephemeralReferenceCount[id] = 1; - } else { - this.ephemeralReferenceCount[id] = this.ephemeralReferenceCount[id] + 1; - } - }); - } - return await esm_default("chelonia/private/out/sync", listOfIds); - }, - // the `try` parameter does not affect (ephemeral or persistent) reference - // counts, but rather removes a contract if the reference count is zero - // and the contract isn't being monitored for foreign keys. This parameter - // is meant mostly for internal chelonia use, so that removing or releasing - // a contract can also remove other contracts that this first contract - // was monitoring. - "chelonia/contract/release": async function(contractIDs, params) { - const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; - const rootState = esm_default(this.config.stateSelector); - if (!params?.try) { - if (!params?.ephemeral) { - listOfIds.forEach((id) => { - if (rootState.contracts[id] === null) { - console.warn("[chelonia/contract/release] Called /release on permanently deleted contract. This has no effect.", id); - return; - } - if (has(rootState.contracts, id) && has(rootState.contracts[id], "references")) { - const current = rootState.contracts[id].references; - if (current === 0) { - console.error("[chelonia/contract/release] Invalid negative reference count for", id); - if (process.env.CI) { - Promise.reject(new Error("Invalid negative reference count: " + id)); - } - throw new Error("Invalid negative reference count"); - } - if (current <= 1) { - this.config.reactiveDel(rootState.contracts[id], "references"); - } else { - this.config.reactiveSet(rootState.contracts[id], "references", current - 1); - } - } else { - console.error("[chelonia/contract/release] Invalid negative reference count for", id); - if (process.env.CI) { - Promise.reject(new Error("Invalid negative reference count: " + id)); - } - throw new Error("Invalid negative reference count"); - } - }); - } else { - listOfIds.forEach((id) => { - if (rootState.contracts[id] === null) { - console.warn("[chelonia/contract/release] Called /release on permanently deleted contract. This has no effect.", id); - return; - } - if (has(this.ephemeralReferenceCount, id)) { - const current = this.ephemeralReferenceCount[id] ?? 0; - if (current <= 1) { - delete this.ephemeralReferenceCount[id]; - } else { - this.ephemeralReferenceCount[id] = current - 1; - } - } else { - console.error("[chelonia/contract/release] Invalid negative ephemeral reference count for", id); - if (process.env.CI) { - Promise.reject(new Error("Invalid negative ephemeral reference count: " + id)); - } - throw new Error("Invalid negative ephemeral reference count"); - } - }); - } - } - const boundCheckCanBeGarbageCollected = checkCanBeGarbageCollected.bind(this); - const idsToRemove = listOfIds.filter(boundCheckCanBeGarbageCollected); - return idsToRemove.length ? await esm_default("chelonia/contract/remove", idsToRemove, { - confirmRemovalCallback: boundCheckCanBeGarbageCollected - }) : void 0; - }, - "chelonia/contract/disconnect": async function(contractID, contractIDToDisconnect) { - const state = esm_default(this.config.stateSelector); - const contractState = state[contractID]; - const keyIds = Object.values(contractState._vm.authorizedKeys).filter((k) => { - return k._notAfterHeight == null && k.meta?.keyRequest?.contractID === contractIDToDisconnect; - }).map((k) => k.id); - if (!keyIds.length) - return; - return await esm_default("chelonia/out/keyDel", { - contractID, - contractName: contractState._vm.type, - data: keyIds, - signingKeyId: findSuitableSecretKeyId(contractState, [SPMessage.OP_KEY_DEL], ["sig"]) - }); - }, - "chelonia/in/processMessage": function(messageOrRawMessage, state) { - const stateCopy = cloneDeep(state); - const message = typeof messageOrRawMessage === "string" ? SPMessage.deserialize(messageOrRawMessage, this.transientSecretKeys, stateCopy, this.config.unwrapMaybeEncryptedData) : messageOrRawMessage; - return esm_default("chelonia/private/in/processMessage", message, stateCopy).then(() => stateCopy).catch((e2) => { - console.warn(`chelonia/in/processMessage: reverting mutation ${message.description()}: ${message.serialize()}`, e2); - return state; - }); - }, - "chelonia/out/fetchResource": async function(cid, { code: code2 } = {}) { - const parsedCID = parseCID(cid); - if (code2 != null) { - if (parsedCID.code !== code2) { - throw new Error(`Invalid CID content type. Expected ${code2}, got ${parsedCID.code}`); - } - } - const local = await esm_default("chelonia.db/get", cid); - if (local != null) - return local; - const url2 = `${this.config.connectionURL}/file/${cid}`; - const data = await this.config.fetch(url2, { signal: this.abortController.signal }).then(handleFetchResult("text")); - const ourHash = createCID(data, parsedCID.code); - if (ourHash !== cid) { - throw new Error(`expected hash ${cid}. Got: ${ourHash}`); - } - await esm_default("chelonia.db/set", cid, data); - return data; - }, - "chelonia/out/latestHEADInfo": function(contractID) { - return this.config.fetch(`${this.config.connectionURL}/latestHEADinfo/${contractID}`, { - cache: "no-store", - signal: this.abortController.signal - }).then(handleFetchResult("json")); - }, - "chelonia/out/deserializedHEAD": async function(hash3, { contractID } = {}) { - const message = await esm_default("chelonia/out/fetchResource", hash3, { - code: multicodes.SHELTER_CONTRACT_DATA - }); - const deserializedHEAD = SPMessage.deserializeHEAD(message); - if (contractID && deserializedHEAD.contractID !== contractID) { - throw new Error("chelonia/out/deserializedHEAD: Mismatched contract ID"); - } - return deserializedHEAD; - }, - "chelonia/out/eventsAfter": eventsAfter, - "chelonia/out/eventsBefore": function(contractID, { beforeHeight, limit, stream }) { - if (limit <= 0) { - console.error('[chelonia] invalid params error: "limit" needs to be positive integer'); - } - const offset = Math.max(0, beforeHeight - limit + 1); - const eventsAfterLimit = Math.min(beforeHeight + 1, limit); - return esm_default("chelonia/out/eventsAfter", contractID, { - sinceHeight: offset, - limit: eventsAfterLimit, - stream - }); - }, - "chelonia/out/eventsBetween": function(contractID, { startHash, endHeight = Number.POSITIVE_INFINITY, offset = 0, limit = 0, stream = true }) { - if (offset < 0) { - console.error('[chelonia] invalid params error: "offset" needs to be positive integer or zero'); - return; - } - let reader; - const s = new ReadableStream({ - start: async (controller) => { - const deserializedHEAD = await esm_default("chelonia/out/deserializedHEAD", startHash, { contractID }); - const startOffset = Math.max(0, deserializedHEAD.head.height - offset); - const ourLimit = limit ? Math.min(endHeight - startOffset + 1, limit) : endHeight - startOffset + 1; - if (ourLimit < 1) { - controller.close(); - return; - } - reader = esm_default("chelonia/out/eventsAfter", contractID, { - sinceHeight: startOffset, - limit: ourLimit - }).getReader(); - }, - async pull(controller) { - const { done, value } = await reader.read(); - if (done) { - controller.close(); - } else { - controller.enqueue(value); - } - } - }); - if (stream) - return s; - return collectEventStream(s); - }, - "chelonia/rootState": function() { - return esm_default(this.config.stateSelector); - }, - "chelonia/latestContractState": async function(contractID, options2 = { forceSync: false }) { - const rootState = esm_default(this.config.stateSelector); - if (rootState.contracts[contractID] === null) { - throw new ChelErrorResourceGone("Permanently deleted contract " + contractID); - } - if (!options2.forceSync && rootState[contractID] && Object.keys(rootState[contractID]).some((x3) => x3 !== "_volatile")) { - return cloneDeep(rootState[contractID]); - } - let state = /* @__PURE__ */ Object.create(null); - let contractName = rootState.contracts[contractID]?.type; - const eventsStream = esm_default("chelonia/out/eventsAfter", contractID, { - sinceHeight: 0, - sinceHash: contractID - }); - const eventsStreamReader = eventsStream.getReader(); - if (rootState[contractID]) - state._volatile = rootState[contractID]._volatile; - for (; ; ) { - const { value: event, done } = await eventsStreamReader.read(); - if (done) - return state; - const stateCopy = cloneDeep(state); - try { - await esm_default("chelonia/private/in/processMessage", SPMessage.deserialize(event, this.transientSecretKeys, state, this.config.unwrapMaybeEncryptedData), state, void 0, contractName); - if (!contractName && state._vm) { - contractName = state._vm.type; - } - } catch (e2) { - console.warn(`[chelonia] latestContractState: '${e2.name}': ${e2.message} processing:`, event, e2.stack); - if (e2 instanceof ChelErrorUnrecoverable) - throw e2; - state = stateCopy; - } - } - }, - "chelonia/contract/state": function(contractID, height) { - const state = esm_default(this.config.stateSelector)[contractID]; - const stateCopy = state && cloneDeep(state); - if (stateCopy?._vm && height != null) { - Object.keys(stateCopy._vm.authorizedKeys).forEach((keyId2) => { - if (stateCopy._vm.authorizedKeys[keyId2]._notBeforeHeight > height) { - delete stateCopy._vm.authorizedKeys[keyId2]; - } - }); - } - return stateCopy; - }, - "chelonia/contract/fullState": function(contractID) { - const rootState = esm_default(this.config.stateSelector); - if (Array.isArray(contractID)) { - return Object.fromEntries(contractID.map((contractID2) => { - return [ - contractID2, - { - contractState: rootState[contractID2], - cheloniaState: rootState.contracts[contractID2] - } - ]; - })); - } - return { - contractState: rootState[contractID], - cheloniaState: rootState.contracts[contractID] - }; - }, - // 'chelonia/out' - selectors that send data out to the server - "chelonia/out/registerContract": async function(params) { - const { contractName, keys, hooks, publishOptions, signingKeyId, actionSigningKeyId, actionEncryptionKeyId } = params; - const manifestHash = this.config.contracts.manifests[contractName]; - const contractInfo = this.manifestToContract[manifestHash]; - if (!contractInfo) - throw new Error(`contract not defined: ${contractName}`); - const signingKey = this.transientSecretKeys[signingKeyId]; - if (!signingKey) - throw new Error(`Signing key ${signingKeyId} is not defined`); - const payload = { - type: contractName, - keys - }; - const contractMsg = SPMessage.createV1_0({ - contractID: null, - height: 0, - op: [ - SPMessage.OP_CONTRACT, - signedOutgoingDataWithRawKey(signingKey, payload) - ], - manifest: manifestHash - }); - const contractID = contractMsg.hash(); - await esm_default("chelonia/private/out/publishEvent", contractMsg, params.namespaceRegistration ? { - ...publishOptions, - headers: { - ...publishOptions?.headers, - "shelter-namespace-registration": params.namespaceRegistration - } - } : publishOptions, hooks && { - prepublish: hooks.prepublishContract, - postpublish: hooks.postpublishContract - }); - await esm_default("chelonia/private/out/sync", contractID); - const msg = await esm_default(actionEncryptionKeyId ? "chelonia/out/actionEncrypted" : "chelonia/out/actionUnencrypted", { - action: contractName, - contractID, - data: params.data, - signingKeyId: actionSigningKeyId ?? signingKeyId, - encryptionKeyId: actionEncryptionKeyId, - hooks, - publishOptions - }); - return msg; - }, - "chelonia/out/ownResources": async function(contractID) { - if (!contractID) { - throw new TypeError("A contract ID must be provided"); - } - const response = await this.config.fetch(`${this.config.connectionURL}/ownResources`, { - method: "GET", - signal: this.abortController.signal, - headers: new Headers([ - ["authorization", buildShelterAuthorizationHeader.call(this, contractID)] - ]) - }); - if (!response.ok) { - console.error("Unable to fetch own resources", contractID, response.status); - throw new Error(`Unable to fetch own resources for ${contractID}: ${response.status}`); - } - return response.json(); - }, - "chelonia/out/deleteContract": async function(contractID, credentials = {}) { - if (!contractID) { - throw new TypeError("A contract ID must be provided"); - } - if (!Array.isArray(contractID)) - contractID = [contractID]; - return await Promise.allSettled(contractID.map(async (cid) => { - const hasCredential = has(credentials, cid); - const hasToken = has(credentials[cid], "token") && credentials[cid].token; - const hasBillableContractID = has(credentials[cid], "billableContractID") && credentials[cid].billableContractID; - if (!hasCredential || hasToken === hasBillableContractID) { - throw new TypeError(`Either a token or a billable contract ID must be provided for ${cid}`); - } - const response = await this.config.fetch(`${this.config.connectionURL}/deleteContract/${cid}`, { - method: "POST", - signal: this.abortController.signal, - headers: new Headers([ - [ - "authorization", - hasToken ? `bearer ${credentials[cid].token.valueOf()}` : buildShelterAuthorizationHeader.call(this, credentials[cid].billableContractID) - ] - ]) - }); - if (!response.ok) { - if (response.status === 404 || response.status === 410) { - console.warn("Contract appears to have been deleted already", cid, response.status); - return; - } - console.error("Unable to delete contract", cid, response.status); - throw new Error(`Unable to delete contract ${cid}: ${response.status}`); - } - })); - }, - // all of these functions will do both the creation of the SPMessage - // and the sending of it via 'chelonia/private/out/publishEvent' - "chelonia/out/actionEncrypted": function(params) { - return outEncryptedOrUnencryptedAction.call(this, SPMessage.OP_ACTION_ENCRYPTED, params); - }, - "chelonia/out/actionUnencrypted": function(params) { - return outEncryptedOrUnencryptedAction.call(this, SPMessage.OP_ACTION_UNENCRYPTED, params); - }, - "chelonia/out/keyShare": async function(params) { - const { atomic, originatingContractName, originatingContractID, contractName, contractID, data, hooks, publishOptions } = params; - const originatingManifestHash = this.config.contracts.manifests[originatingContractName]; - const destinationManifestHash = this.config.contracts.manifests[contractName]; - const originatingContract = originatingContractID ? this.manifestToContract[originatingManifestHash]?.contract : void 0; - const destinationContract = this.manifestToContract[destinationManifestHash]?.contract; - if (originatingContractID && !originatingContract || !destinationContract) { - throw new Error("Contract name not found"); - } - const payload = data; - if (!params.signingKeyId && !params.signingKey) { - throw new TypeError("Either signingKeyId or signingKey must be specified"); - } - let msg = SPMessage.createV1_0({ - contractID, - op: [ - SPMessage.OP_KEY_SHARE, - params.signingKeyId ? signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) : signedOutgoingDataWithRawKey(params.signingKey, payload) - ], - manifest: destinationManifestHash - }); - if (!atomic) { - msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); - } - return msg; - }, - "chelonia/out/keyAdd": async function(params) { - const { atomic, contractID, contractName, data, hooks, publishOptions } = params; - const manifestHash = this.config.contracts.manifests[contractName]; - const contract = this.manifestToContract[manifestHash]?.contract; - if (!contract) { - throw new Error("Contract name not found"); - } - const state = contract.state(contractID); - const payload = params.skipExistingKeyCheck ? data : data.filter((wk) => { - const k = isEncryptedData(wk) ? wk.valueOf() : wk; - if (has(state._vm.authorizedKeys, k.id)) { - if (state._vm.authorizedKeys[k.id]._notAfterHeight == null) { - return false; - } - } - return true; - }); - if (payload.length === 0) - return; - let msg = SPMessage.createV1_0({ - contractID, - op: [ - SPMessage.OP_KEY_ADD, - signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) - ], - manifest: manifestHash - }); - if (!atomic) { - msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); - } - return msg; - }, - "chelonia/out/keyDel": async function(params) { - const { atomic, contractID, contractName, data, hooks, publishOptions } = params; - const manifestHash = this.config.contracts.manifests[contractName]; - const contract = this.manifestToContract[manifestHash]?.contract; - if (!contract) { - throw new Error("Contract name not found"); - } - const state = contract.state(contractID); - const payload = data.map((keyId2) => { - if (isEncryptedData(keyId2)) - return keyId2; - if (!has(state._vm.authorizedKeys, keyId2) || state._vm.authorizedKeys[keyId2]._notAfterHeight != null) { - return void 0; - } - if (state._vm.authorizedKeys[keyId2]._private) { - return encryptedOutgoingData(contractID, state._vm.authorizedKeys[keyId2]._private, keyId2); - } else { - return keyId2; - } - }).filter(Boolean); - let msg = SPMessage.createV1_0({ - contractID, - op: [ - SPMessage.OP_KEY_DEL, - signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) - ], - manifest: manifestHash - }); - if (!atomic) { - msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); - } - return msg; - }, - "chelonia/out/keyUpdate": async function(params) { - const { atomic, contractID, contractName, data, hooks, publishOptions } = params; - const manifestHash = this.config.contracts.manifests[contractName]; - const contract = this.manifestToContract[manifestHash]?.contract; - if (!contract) { - throw new Error("Contract name not found"); - } - const state = contract.state(contractID); - const payload = data.map((key) => { - if (isEncryptedData(key)) - return key; - const { oldKeyId } = key; - if (state._vm.authorizedKeys[oldKeyId]._private) { - return encryptedOutgoingData(contractID, state._vm.authorizedKeys[oldKeyId]._private, key); - } else { - return key; - } - }); - let msg = SPMessage.createV1_0({ - contractID, - op: [ - SPMessage.OP_KEY_UPDATE, - signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) - ], - manifest: manifestHash - }); - if (!atomic) { - msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); - } - return msg; - }, - "chelonia/out/keyRequest": async function(params) { - const { originatingContractID, originatingContractName, contractID, contractName, hooks, publishOptions, innerSigningKeyId, encryptionKeyId, innerEncryptionKeyId, encryptKeyRequestMetadata, reference } = params; - const manifestHash = this.config.contracts.manifests[contractName]; - const originatingManifestHash = this.config.contracts.manifests[originatingContractName]; - const contract = this.manifestToContract[manifestHash]?.contract; - const originatingContract = this.manifestToContract[originatingManifestHash]?.contract; - if (!contract) { - throw new Error("Contract name not found"); - } - const rootState = esm_default(this.config.stateSelector); - try { - await esm_default("chelonia/contract/retain", contractID, { ephemeral: true }); - const state = contract.state(contractID); - const originatingState = originatingContract.state(originatingContractID); - const havePendingKeyRequest = Object.values(originatingState._vm.authorizedKeys).findIndex((k) => { - return k._notAfterHeight == null && k.meta?.keyRequest?.contractID === contractID && state?._volatile?.pendingKeyRequests?.some((pkr) => pkr.name === k.name); - }) !== -1; - if (havePendingKeyRequest) { - return; - } - const keyRequestReplyKey = keygen(EDWARDS25519SHA512BATCH); - const keyRequestReplyKeyId = keyId(keyRequestReplyKey); - const keyRequestReplyKeyP = serializeKey(keyRequestReplyKey, false); - const keyRequestReplyKeyS = serializeKey(keyRequestReplyKey, true); - const signingKeyId = findSuitableSecretKeyId(originatingState, [SPMessage.OP_KEY_ADD], ["sig"]); - if (!signingKeyId) { - throw new ChelErrorUnexpected(`Unable to send key request. Originating contract is missing a key with OP_KEY_ADD permission. contractID=${contractID} originatingContractID=${originatingContractID}`); - } - const keyAddOp = () => esm_default("chelonia/out/keyAdd", { - contractID: originatingContractID, - contractName: originatingContractName, - data: [ - { - id: keyRequestReplyKeyId, - name: "#krrk-" + keyRequestReplyKeyId, - purpose: ["sig"], - ringLevel: Number.MAX_SAFE_INTEGER, - permissions: params.permissions === "*" ? "*" : Array.isArray(params.permissions) ? [...params.permissions, SPMessage.OP_KEY_SHARE] : [SPMessage.OP_KEY_SHARE], - allowedActions: params.allowedActions, - meta: { - private: { - content: encryptedOutgoingData(originatingContractID, encryptionKeyId, keyRequestReplyKeyS), - shareable: false - }, - keyRequest: { - ...reference && { - reference: encryptKeyRequestMetadata ? encryptedOutgoingData(originatingContractID, encryptionKeyId, reference) : reference - }, - contractID: encryptKeyRequestMetadata ? encryptedOutgoingData(originatingContractID, encryptionKeyId, contractID) : contractID - } - }, - data: keyRequestReplyKeyP - } - ], - signingKeyId - }).catch((e2) => { - console.error(`[chelonia] Error sending OP_KEY_ADD for ${originatingContractID} during key request to ${contractID}`, e2); - throw e2; - }); - const payload = { - contractID: originatingContractID, - height: rootState.contracts[originatingContractID].height, - replyWith: signedOutgoingData(originatingContractID, innerSigningKeyId, { - encryptionKeyId, - responseKey: encryptedOutgoingData(contractID, innerEncryptionKeyId, keyRequestReplyKeyS) - }, this.transientSecretKeys), - request: "*" - }; - let msg = SPMessage.createV1_0({ - contractID, - op: [ - SPMessage.OP_KEY_REQUEST, - signedOutgoingData(contractID, params.signingKeyId, encryptKeyRequestMetadata ? encryptedOutgoingData(contractID, innerEncryptionKeyId, payload) : payload, this.transientSecretKeys) - ], - manifest: manifestHash - }); - msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, { - ...hooks, - // We ensure that both messages are placed into the publish queue - prepublish: (...args) => { - return keyAddOp().then(() => hooks?.prepublish?.(...args)); - } - }); - return msg; - } finally { - await esm_default("chelonia/contract/release", contractID, { ephemeral: true }); - } - }, - "chelonia/out/keyRequestResponse": async function(params) { - const { atomic, contractID, contractName, data, hooks, publishOptions } = params; - const manifestHash = this.config.contracts.manifests[contractName]; - const contract = this.manifestToContract[manifestHash]?.contract; - if (!contract) { - throw new Error("Contract name not found"); - } - const payload = data; - let message = SPMessage.createV1_0({ - contractID, - op: [ - SPMessage.OP_KEY_REQUEST_SEEN, - signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) - ], - manifest: manifestHash - }); - if (!atomic) { - message = await esm_default("chelonia/private/out/publishEvent", message, publishOptions, hooks); - } - return message; - }, - "chelonia/out/atomic": async function(params) { - const { contractID, contractName, data, hooks, publishOptions } = params; - const manifestHash = this.config.contracts.manifests[contractName]; - const contract = this.manifestToContract[manifestHash]?.contract; - if (!contract) { - throw new Error("Contract name not found"); - } - const payload = (await Promise.all(data.map(([selector, opParams]) => { - if (![ - "chelonia/out/actionEncrypted", - "chelonia/out/actionUnencrypted", - "chelonia/out/keyAdd", - "chelonia/out/keyDel", - "chelonia/out/keyUpdate", - "chelonia/out/keyRequestResponse", - "chelonia/out/keyShare" - ].includes(selector)) { - throw new Error("Selector not allowed in OP_ATOMIC: " + selector); - } - return esm_default(selector, { - ...opParams, - ...params, - data: opParams.data, - atomic: true - }); - }))).flat().filter(Boolean).map((msg2) => { - return [msg2.opType(), msg2.opValue()]; - }); - let msg = SPMessage.createV1_0({ - contractID, - op: [ - SPMessage.OP_ATOMIC, - signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) - ], - manifest: manifestHash - }); - msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); - return msg; - }, - "chelonia/out/protocolUpgrade": async function() { - }, - "chelonia/out/propSet": async function() { - }, - "chelonia/out/propDel": async function() { - }, - "chelonia/out/encryptedOrUnencryptedPubMessage": function({ contractID, innerSigningKeyId, encryptionKeyId, signingKeyId, data }) { - const serializedData = outputEncryptedOrUnencryptedMessage.call(this, { - contractID, - innerSigningKeyId, - encryptionKeyId, - signingKeyId, - data - }); - this.pubsub.pub(contractID, serializedData); - }, - // Note: This is a bare-bones function designed for precise control. In many - // situations, the `chelonia/kv/queuedSet` selector (in chelonia-utils.js) - // will be simpler and more appropriate to use. - // In most situations, you want to use some queuing strategy (which this - // selector doesn't provide) alongside writing to the KV store. Therefore, as - // a general rule, you shouldn't be calling this selector directly unless - // you're building a utility library or if you have very specific needs. In - // this case, see if `chelonia/kv/queuedSet` covers your needs. - // `data` is allowed to be falsy, in which case a fetch will occur first and - // the `onconflict` handler will be called. - "chelonia/kv/set": async function(contractID, key, data, { ifMatch, innerSigningKeyId, encryptionKeyId, signingKeyId, maxAttempts, onconflict }) { - maxAttempts = maxAttempts ?? 3; - const url2 = `${this.config.connectionURL}/kv/${encodeURIComponent(contractID)}/${encodeURIComponent(key)}`; - const hasOnconflict = typeof onconflict === "function"; - let response; - const resolveData = async () => { - let currentValue; - if (response.ok || response.status === 409 || response.status === 412) { - const serializedDataText = await response.text(); - currentValue = serializedDataText ? parseEncryptedOrUnencryptedMessage(this, { - contractID, - serializedData: JSON.parse(serializedDataText), - meta: key - }) : void 0; - } else if (response.status !== 404 && response.status !== 410) { - throw new ChelErrorUnexpectedHttpResponseCode("[kv/set] Invalid response code: " + response.status); - } - const result = await onconflict({ - contractID, - key, - failedData: data, - status: response.status, - // If no x-cid or etag header was returned, `ifMatch` would likely be - // returned as undefined, which will then use the `''` fallback value - // when writing. This allows 404 / 410 responses to work even if no - // etag is explicitly given - etag: response.headers.get("x-cid") || response.headers.get("etag"), - get currentData() { - return currentValue?.data; - }, - currentValue - }); - if (!result) - return false; - data = result[0]; - ifMatch = result[1]; - return true; - }; - for (; ; ) { - if (data !== void 0) { - const serializedData = outputEncryptedOrUnencryptedMessage.call(this, { - contractID, - innerSigningKeyId, - encryptionKeyId, - signingKeyId, - data, - meta: key - }); - response = await this.config.fetch(url2, { - headers: new Headers([ - ["authorization", buildShelterAuthorizationHeader.call(this, contractID)], - ["if-match", ifMatch || '""'] - ]), - method: "POST", - body: JSON.stringify(serializedData), - signal: this.abortController.signal - }); - } else { - if (!hasOnconflict) { - throw TypeError("onconflict required with empty data"); - } - response = await this.config.fetch(url2, { - headers: new Headers([ - ["authorization", buildShelterAuthorizationHeader.call(this, contractID)] - ]), - signal: this.abortController.signal - }); - if (await resolveData()) { - continue; - } else { - break; - } - } - if (!response.ok) { - if (response.status === 409 || response.status === 412) { - if (--maxAttempts <= 0) { - throw new Error("kv/set conflict setting KV value"); - } - await delay(randomIntFromRange(0, 1500)); - if (hasOnconflict) { - if (await resolveData()) { - continue; - } else { - break; - } - } else { - throw new Error(`kv/set failed with status ${response.status} and no onconflict handler was provided`); - } - } - throw new ChelErrorUnexpectedHttpResponseCode("kv/set invalid response status: " + response.status); - } - break; - } - }, - "chelonia/kv/get": async function(contractID, key) { - const response = await this.config.fetch(`${this.config.connectionURL}/kv/${encodeURIComponent(contractID)}/${encodeURIComponent(key)}`, { - headers: new Headers([ - ["authorization", buildShelterAuthorizationHeader.call(this, contractID)] - ]), - signal: this.abortController.signal - }); - if (response.status === 404) { - return null; - } - if (!response.ok) { - throw new Error("Invalid response status: " + response.status); - } - const data = await response.json(); - return parseEncryptedOrUnencryptedMessage(this, { - contractID, - serializedData: data, - meta: key - }); - }, - // To set filters for a contract, call with `filter` set to an array of KV - // keys to receive updates for over the WebSocket. An empty array means that - // no KV updates will be sent. - // Calling with a single argument (the contract ID) will remove filters, - // meaning that KV updates will be sent for _any_ KV key. - // The last call takes precedence, so, for example, calling with filter - // set to `['foo', 'bar']` and then with `['baz']` means that KV updates will - // be received for `baz` only, not for `foo`, `bar` or any other keys. - "chelonia/kv/setFilter": function(contractID, filter) { - this.pubsub.setKvFilter(contractID, filter); - }, - "chelonia/parseEncryptedOrUnencryptedDetachedMessage": function({ contractID, serializedData, meta }) { - return parseEncryptedOrUnencryptedMessage(this, { - contractID, - serializedData, - meta - }); } - }); - esm_default("sbp/domains/lock", ["chelonia"]); - } -}); -var require_assertError = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/assertError.js"(exports2, module14) { - "use strict"; - module14.exports = class AssertError extends Error { - name = "AssertError"; - constructor(message, ctor) { - super(message || "Unknown error"); - if (typeof Error.captureStackTrace === "function") { - Error.captureStackTrace(this, ctor); - } + async keyCount() { + const entries = await readdir(this.dataFolder, { withFileTypes: true }); + return entries.filter((e2) => e2.isFile()).length; } }; } }); -var require_stringify = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/stringify.js"(exports2, module14) { +var require_verbatim_string = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/RESP/verbatim-string.js"(exports2) { "use strict"; - module14.exports = function(...args) { - try { - return JSON.stringify(...args); - } catch (err) { - return "[Cannot display object: " + err.message + "]"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.VerbatimString = void 0; + var VerbatimString = class extends String { + format; + constructor(format52, value) { + super(value); + this.format = format52; } }; + exports2.VerbatimString = VerbatimString; } }); -var require_assert = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/assert.js"(exports2, module14) { +var require_errors = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/errors.js"(exports2) { "use strict"; - var AssertError = require_assertError(); - var Stringify = require_stringify(); - var assert2 = module14.exports = function(condition, ...args) { - if (condition) { - return; - } - if (args.length === 1 && args[0] instanceof Error) { - throw args[0]; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.MultiErrorReply = exports2.CommandTimeoutDuringMaintenanceError = exports2.SocketTimeoutDuringMaintenanceError = exports2.TimeoutError = exports2.BlobError = exports2.SimpleError = exports2.ErrorReply = exports2.ReconnectStrategyError = exports2.RootNodesUnavailableError = exports2.SocketClosedUnexpectedlyError = exports2.DisconnectsClientError = exports2.ClientOfflineError = exports2.ClientClosedError = exports2.SocketTimeoutError = exports2.ConnectionTimeoutError = exports2.WatchError = exports2.AbortError = void 0; + var AbortError = class extends Error { + constructor() { + super("The command was aborted"); } - const msgs = args.filter((arg) => arg !== "").map((arg) => { - return typeof arg === "string" ? arg : arg instanceof Error ? arg.message : Stringify(arg); - }); - throw new AssertError(msgs.join(" "), assert2); }; - } -}); -var require_reach = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/reach.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var internals = {}; - module14.exports = function(obj, chain, options2) { - if (chain === false || chain === null || chain === void 0) { - return obj; - } - options2 = options2 || {}; - if (typeof options2 === "string") { - options2 = { separator: options2 }; - } - const isChainArray = Array.isArray(chain); - Assert(!isChainArray || !options2.separator, "Separator option is not valid for array-based chain"); - const path8 = isChainArray ? chain : chain.split(options2.separator || "."); - let ref = obj; - for (let i2 = 0; i2 < path8.length; ++i2) { - let key = path8[i2]; - const type = options2.iterables && internals.iterables(ref); - if (Array.isArray(ref) || type === "set") { - const number3 = Number(key); - if (Number.isInteger(number3)) { - key = number3 < 0 ? ref.length + number3 : number3; - } - } - if (!ref || typeof ref === "function" && options2.functions === false || // Defaults to true - !type && ref[key] === void 0) { - Assert(!options2.strict || i2 + 1 === path8.length, "Missing segment", key, "in reach path ", chain); - Assert(typeof ref === "object" || options2.functions === true || typeof ref !== "function", "Invalid segment", key, "in reach path ", chain); - ref = options2.default; - break; - } - if (!type) { - ref = ref[key]; - } else if (type === "set") { - ref = [...ref][key]; - } else { - ref = ref.get(key); - } + exports2.AbortError = AbortError; + var WatchError = class extends Error { + constructor(message = "One (or more) of the watched keys has been changed") { + super(message); } - return ref; }; - internals.iterables = function(ref) { - if (ref instanceof Set) { - return "set"; + exports2.WatchError = WatchError; + var ConnectionTimeoutError = class extends Error { + constructor() { + super("Connection timeout"); } - if (ref instanceof Map) { - return "map"; + }; + exports2.ConnectionTimeoutError = ConnectionTimeoutError; + var SocketTimeoutError = class extends Error { + constructor(timeout) { + super(`Socket timeout timeout. Expecting data, but didn't receive any in ${timeout}ms.`); } }; - } -}); -var require_types = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/types.js"(exports2, module14) { - "use strict"; - var internals = {}; - exports2 = module14.exports = { - array: Array.prototype, - buffer: Buffer && Buffer.prototype, - // $lab:coverage:ignore$ - date: Date.prototype, - error: Error.prototype, - generic: Object.prototype, - map: Map.prototype, - promise: Promise.prototype, - regex: RegExp.prototype, - set: Set.prototype, - url: URL.prototype, - weakMap: WeakMap.prototype, - weakSet: WeakSet.prototype + exports2.SocketTimeoutError = SocketTimeoutError; + var ClientClosedError = class extends Error { + constructor() { + super("The client is closed"); + } }; - internals.typeMap = /* @__PURE__ */ new Map([ - ["[object Error]", exports2.error], - ["[object Map]", exports2.map], - ["[object Promise]", exports2.promise], - ["[object Set]", exports2.set], - ["[object URL]", exports2.url], - ["[object WeakMap]", exports2.weakMap], - ["[object WeakSet]", exports2.weakSet] - ]); - exports2.getInternalProto = function(obj) { - if (Array.isArray(obj)) { - return exports2.array; + exports2.ClientClosedError = ClientClosedError; + var ClientOfflineError = class extends Error { + constructor() { + super("The client is offline"); } - if (Buffer && obj instanceof Buffer) { - return exports2.buffer; + }; + exports2.ClientOfflineError = ClientOfflineError; + var DisconnectsClientError = class extends Error { + constructor() { + super("Disconnects client"); } - if (obj instanceof Date) { - return exports2.date; + }; + exports2.DisconnectsClientError = DisconnectsClientError; + var SocketClosedUnexpectedlyError = class extends Error { + constructor() { + super("Socket closed unexpectedly"); } - if (obj instanceof RegExp) { - return exports2.regex; + }; + exports2.SocketClosedUnexpectedlyError = SocketClosedUnexpectedlyError; + var RootNodesUnavailableError = class extends Error { + constructor() { + super("All the root nodes are unavailable"); } - if (obj instanceof Error) { - return exports2.error; + }; + exports2.RootNodesUnavailableError = RootNodesUnavailableError; + var ReconnectStrategyError = class extends Error { + originalError; + socketError; + constructor(originalError, socketError) { + super(originalError.message); + this.originalError = originalError; + this.socketError = socketError; } - const objName = Object.prototype.toString.call(obj); - return internals.typeMap.get(objName) || exports2.generic; }; - } -}); -var require_utils = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/utils.js"(exports2) { - "use strict"; - exports2.keys = function(obj, options2 = {}) { - return options2.symbols !== false ? Reflect.ownKeys(obj) : Object.getOwnPropertyNames(obj); + exports2.ReconnectStrategyError = ReconnectStrategyError; + var ErrorReply = class extends Error { }; - } -}); -var require_clone = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/clone.js"(exports2, module14) { - "use strict"; - var Reach = require_reach(); - var Types = require_types(); - var Utils = require_utils(); - var internals = { - needsProtoHack: /* @__PURE__ */ new Set([Types.set, Types.map, Types.weakSet, Types.weakMap]), - structuredCloneExists: typeof structuredClone === "function" + exports2.ErrorReply = ErrorReply; + var SimpleError = class extends ErrorReply { }; - module14.exports = internals.clone = function(obj, options2 = {}, _seen = null) { - if (typeof obj !== "object" || obj === null) { - return obj; - } - let clone2 = internals.clone; - let seen = _seen; - if (options2.shallow) { - if (options2.shallow !== true) { - return internals.cloneWithShallow(obj, options2); - } - clone2 = (value) => value; - } else if (seen) { - const lookup = seen.get(obj); - if (lookup) { - return lookup; - } - } else { - seen = /* @__PURE__ */ new Map(); - } - const baseProto = Types.getInternalProto(obj); - switch (baseProto) { - case Types.buffer: - return Buffer?.from(obj); - case Types.date: - return new Date(obj.getTime()); - case Types.regex: - case Types.url: - return new baseProto.constructor(obj); - } - const newObj = internals.base(obj, baseProto, options2); - if (newObj === obj) { - return obj; - } - if (seen) { - seen.set(obj, newObj); - } - if (baseProto === Types.set) { - for (const value of obj) { - newObj.add(clone2(value, options2, seen)); - } - } else if (baseProto === Types.map) { - for (const [key, value] of obj) { - newObj.set(key, clone2(value, options2, seen)); - } - } - const keys = Utils.keys(obj, options2); - for (const key of keys) { - if (key === "__proto__") { - continue; - } - if (baseProto === Types.array && key === "length") { - newObj.length = obj.length; - continue; - } - if (internals.structuredCloneExists && baseProto === Types.error && key === "stack") { - continue; - } - const descriptor = Object.getOwnPropertyDescriptor(obj, key); - if (descriptor) { - if (descriptor.get || descriptor.set) { - Object.defineProperty(newObj, key, descriptor); - } else if (descriptor.enumerable) { - newObj[key] = clone2(obj[key], options2, seen); - } else { - Object.defineProperty(newObj, key, { enumerable: false, writable: true, configurable: true, value: clone2(obj[key], options2, seen) }); - } - } else { - Object.defineProperty(newObj, key, { - enumerable: true, - writable: true, - configurable: true, - value: clone2(obj[key], options2, seen) - }); - } - } - return newObj; + exports2.SimpleError = SimpleError; + var BlobError = class extends ErrorReply { }; - internals.cloneWithShallow = function(source, options2) { - const keys = options2.shallow; - options2 = Object.assign({}, options2); - options2.shallow = false; - const seen = /* @__PURE__ */ new Map(); - for (const key of keys) { - const ref = Reach(source, key); - if (typeof ref === "object" || typeof ref === "function") { - seen.set(ref, ref); - } - } - return internals.clone(source, options2, seen); + exports2.BlobError = BlobError; + var TimeoutError = class extends Error { }; - internals.base = function(obj, baseProto, options2) { - if (options2.prototype === false) { - if (internals.needsProtoHack.has(baseProto)) { - return new baseProto.constructor(); - } - return baseProto === Types.array ? [] : {}; - } - const proto3 = Object.getPrototypeOf(obj); - if (proto3 && proto3.isImmutable) { - return obj; - } - if (baseProto === Types.array) { - const newObj = []; - if (proto3 !== baseProto) { - Object.setPrototypeOf(newObj, proto3); - } - return newObj; - } else if (baseProto === Types.error && internals.structuredCloneExists && (proto3 === baseProto || Error.isPrototypeOf(proto3.constructor))) { - const err = structuredClone(obj); - if (Object.getPrototypeOf(err) !== proto3) { - Object.setPrototypeOf(err, proto3); - } - return err; - } - if (internals.needsProtoHack.has(baseProto)) { - const newObj = new proto3.constructor(); - if (proto3 !== baseProto) { - Object.setPrototypeOf(newObj, proto3); - } - return newObj; + exports2.TimeoutError = TimeoutError; + var SocketTimeoutDuringMaintenanceError = class extends TimeoutError { + constructor(timeout) { + super(`Socket timeout during maintenance. Expecting data, but didn't receive any in ${timeout}ms.`); } - return Object.create(proto3); }; - } -}); -var require_merge = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/merge.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var Utils = require_utils(); - var internals = {}; - module14.exports = internals.merge = function(target, source, options2) { - Assert(target && typeof target === "object", "Invalid target value: must be an object"); - Assert(source === null || source === void 0 || typeof source === "object", "Invalid source value: must be null, undefined, or an object"); - if (!source) { - return target; + exports2.SocketTimeoutDuringMaintenanceError = SocketTimeoutDuringMaintenanceError; + var CommandTimeoutDuringMaintenanceError = class extends TimeoutError { + constructor(timeout) { + super(`Command timeout during maintenance. Waited to write command for more than ${timeout}ms.`); } - options2 = Object.assign({ nullOverride: true, mergeArrays: true }, options2); - if (Array.isArray(source)) { - Assert(Array.isArray(target), "Cannot merge array onto an object"); - if (!options2.mergeArrays) { - target.length = 0; - } - for (let i2 = 0; i2 < source.length; ++i2) { - target.push(Clone(source[i2], { symbols: options2.symbols })); - } - return target; + }; + exports2.CommandTimeoutDuringMaintenanceError = CommandTimeoutDuringMaintenanceError; + var MultiErrorReply = class extends ErrorReply { + replies; + errorIndexes; + constructor(replies, errorIndexes) { + super(`${errorIndexes.length} commands failed, see .replies and .errorIndexes for more information`); + this.replies = replies; + this.errorIndexes = errorIndexes; } - const keys = Utils.keys(source, options2); - for (let i2 = 0; i2 < keys.length; ++i2) { - const key = keys[i2]; - if (key === "__proto__" || !Object.prototype.propertyIsEnumerable.call(source, key)) { - continue; - } - const value = source[key]; - if (value && typeof value === "object") { - if (target[key] === value) { - continue; - } - if (!target[key] || typeof target[key] !== "object" || Array.isArray(target[key]) !== Array.isArray(value) || value instanceof Date || Buffer && Buffer.isBuffer(value) || // $lab:coverage:ignore$ - value instanceof RegExp) { - target[key] = Clone(value, { symbols: options2.symbols }); - } else { - internals.merge(target[key], value, options2); - } - } else { - if (value !== null && value !== void 0) { - target[key] = value; - } else if (options2.nullOverride) { - target[key] = value; - } + *errors() { + for (const index of this.errorIndexes) { + yield this.replies[index]; } } - return target; }; + exports2.MultiErrorReply = MultiErrorReply; } }); -var require_applyToDefaults = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/applyToDefaults.js"(exports2, module14) { +var require_decoder = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/RESP/decoder.js"(exports2) { "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var Merge = require_merge(); - var Reach = require_reach(); - var internals = {}; - module14.exports = function(defaults, source, options2 = {}) { - Assert(defaults && typeof defaults === "object", "Invalid defaults value: must be an object"); - Assert(!source || source === true || typeof source === "object", "Invalid source value: must be true, falsy or an object"); - Assert(typeof options2 === "object", "Invalid options: must be an object"); - if (!source) { - return null; - } - if (options2.shallow) { - return internals.applyToDefaultsWithShallow(defaults, source, options2); - } - const copy2 = Clone(defaults); - if (source === true) { - return copy2; - } - const nullOverride = options2.nullOverride !== void 0 ? options2.nullOverride : false; - return Merge(copy2, source, { nullOverride, mergeArrays: false }); + var _a2; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.Decoder = exports2.PUSH_TYPE_MAPPING = exports2.RESP_TYPES = void 0; + var verbatim_string_1 = require_verbatim_string(); + var errors_1 = require_errors(); + exports2.RESP_TYPES = { + NULL: 95, + // _ + BOOLEAN: 35, + // # + NUMBER: 58, + // : + BIG_NUMBER: 40, + // ( + DOUBLE: 44, + // , + SIMPLE_STRING: 43, + // + + BLOB_STRING: 36, + // $ + VERBATIM_STRING: 61, + // = + SIMPLE_ERROR: 45, + // - + BLOB_ERROR: 33, + // ! + ARRAY: 42, + // * + SET: 126, + // ~ + MAP: 37, + // % + PUSH: 62 + // > }; - internals.applyToDefaultsWithShallow = function(defaults, source, options2) { - const keys = options2.shallow; - Assert(Array.isArray(keys), "Invalid keys"); - const seen = /* @__PURE__ */ new Map(); - const merge3 = source === true ? null : /* @__PURE__ */ new Set(); - for (let key of keys) { - key = Array.isArray(key) ? key : key.split("."); - const ref = Reach(defaults, key); - if (ref && typeof ref === "object") { - seen.set(ref, merge3 && Reach(source, key) || ref); - } else if (merge3) { - merge3.add(key); - } - } - const copy2 = Clone(defaults, {}, seen); - if (!merge3) { - return copy2; + var ASCII = { + "\r": 13, + "t": 116, + "+": 43, + "-": 45, + "0": 48, + ".": 46, + "i": 105, + "n": 110, + "E": 69, + "e": 101 + }; + exports2.PUSH_TYPE_MAPPING = { + [exports2.RESP_TYPES.BLOB_STRING]: Buffer + }; + var Decoder2 = class { + onReply; + onErrorReply; + onPush; + getTypeMapping; + #cursor = 0; + #next; + constructor(config2) { + this.onReply = config2.onReply; + this.onErrorReply = config2.onErrorReply; + this.onPush = config2.onPush; + this.getTypeMapping = config2.getTypeMapping; } - for (const key of merge3) { - internals.reachCopy(copy2, source, key); + reset() { + this.#cursor = 0; + this.#next = void 0; } - const nullOverride = options2.nullOverride !== void 0 ? options2.nullOverride : false; - return Merge(copy2, source, { nullOverride, mergeArrays: false }); - }; - internals.reachCopy = function(dst, src2, path8) { - for (const segment of path8) { - if (!(segment in src2)) { + write(chunk) { + if (this.#cursor >= chunk.length) { + this.#cursor -= chunk.length; return; } - const val = src2[segment]; - if (typeof val !== "object" || val === null) { - return; + if (this.#next) { + if (this.#next(chunk) || this.#cursor >= chunk.length) { + this.#cursor -= chunk.length; + return; + } } - src2 = val; + do { + const type = chunk[this.#cursor]; + if (++this.#cursor === chunk.length) { + this.#next = this.#continueDecodeTypeValue.bind(this, type); + break; + } + if (this.#decodeTypeValue(type, chunk)) { + break; + } + } while (this.#cursor < chunk.length); + this.#cursor -= chunk.length; } - const value = src2; - let ref = dst; - for (let i2 = 0; i2 < path8.length - 1; ++i2) { - const segment = path8[i2]; - if (typeof ref[segment] !== "object") { - ref[segment] = {}; + #continueDecodeTypeValue(type, chunk) { + this.#next = void 0; + return this.#decodeTypeValue(type, chunk); + } + #decodeTypeValue(type, chunk) { + switch (type) { + case exports2.RESP_TYPES.NULL: + this.onReply(this.#decodeNull()); + return false; + case exports2.RESP_TYPES.BOOLEAN: + return this.#handleDecodedValue(this.onReply, this.#decodeBoolean(chunk)); + case exports2.RESP_TYPES.NUMBER: + return this.#handleDecodedValue(this.onReply, this.#decodeNumber(this.getTypeMapping()[exports2.RESP_TYPES.NUMBER], chunk)); + case exports2.RESP_TYPES.BIG_NUMBER: + return this.#handleDecodedValue(this.onReply, this.#decodeBigNumber(this.getTypeMapping()[exports2.RESP_TYPES.BIG_NUMBER], chunk)); + case exports2.RESP_TYPES.DOUBLE: + return this.#handleDecodedValue(this.onReply, this.#decodeDouble(this.getTypeMapping()[exports2.RESP_TYPES.DOUBLE], chunk)); + case exports2.RESP_TYPES.SIMPLE_STRING: + return this.#handleDecodedValue(this.onReply, this.#decodeSimpleString(this.getTypeMapping()[exports2.RESP_TYPES.SIMPLE_STRING], chunk)); + case exports2.RESP_TYPES.BLOB_STRING: + return this.#handleDecodedValue(this.onReply, this.#decodeBlobString(this.getTypeMapping()[exports2.RESP_TYPES.BLOB_STRING], chunk)); + case exports2.RESP_TYPES.VERBATIM_STRING: + return this.#handleDecodedValue(this.onReply, this.#decodeVerbatimString(this.getTypeMapping()[exports2.RESP_TYPES.VERBATIM_STRING], chunk)); + case exports2.RESP_TYPES.SIMPLE_ERROR: + return this.#handleDecodedValue(this.onErrorReply, this.#decodeSimpleError(chunk)); + case exports2.RESP_TYPES.BLOB_ERROR: + return this.#handleDecodedValue(this.onErrorReply, this.#decodeBlobError(chunk)); + case exports2.RESP_TYPES.ARRAY: + return this.#handleDecodedValue(this.onReply, this.#decodeArray(this.getTypeMapping(), chunk)); + case exports2.RESP_TYPES.SET: + return this.#handleDecodedValue(this.onReply, this.#decodeSet(this.getTypeMapping(), chunk)); + case exports2.RESP_TYPES.MAP: + return this.#handleDecodedValue(this.onReply, this.#decodeMap(this.getTypeMapping(), chunk)); + case exports2.RESP_TYPES.PUSH: + return this.#handleDecodedValue(this.onPush, this.#decodeArray(exports2.PUSH_TYPE_MAPPING, chunk)); + default: + throw new Error(`Unknown RESP type ${type} "${String.fromCharCode(type)}"`); } - ref = ref[segment]; } - ref[path8[path8.length - 1]] = value; - }; - } -}); -var require_bench = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/bench.js"(exports2, module14) { - "use strict"; - var internals = {}; - module14.exports = internals.Bench = class { - constructor() { - this.ts = 0; - this.reset(); + #handleDecodedValue(cb, value) { + if (typeof value === "function") { + this.#next = this.#continueDecodeValue.bind(this, cb, value); + return true; + } + cb(value); + return false; } - reset() { - this.ts = internals.Bench.now(); + #continueDecodeValue(cb, next, chunk) { + this.#next = void 0; + return this.#handleDecodedValue(cb, next(chunk)); } - elapsed() { - return internals.Bench.now() - this.ts; + #decodeNull() { + this.#cursor += 2; + return null; } - static now() { - const ts = process.hrtime(); - return ts[0] * 1e3 + ts[1] / 1e6; + #decodeBoolean(chunk) { + const boolean3 = chunk[this.#cursor] === ASCII.t; + this.#cursor += 3; + return boolean3; } - }; - } -}); -var require_ignore = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/ignore.js"(exports2, module14) { - "use strict"; - module14.exports = function() { - }; - } -}); -var require_block = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/block.js"(exports2, module14) { - "use strict"; - var Ignore = require_ignore(); - module14.exports = function() { - return new Promise(Ignore); - }; - } -}); -var require_deepEqual = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/deepEqual.js"(exports2, module14) { - "use strict"; - var Types = require_types(); - var internals = { - mismatched: null - }; - module14.exports = function(obj, ref, options2) { - options2 = Object.assign({ prototype: true }, options2); - return !!internals.isDeepEqual(obj, ref, options2, []); - }; - internals.isDeepEqual = function(obj, ref, options2, seen) { - if (obj === ref) { - return obj !== 0 || 1 / obj === 1 / ref; + #decodeNumber(type, chunk) { + if (type === String) { + return this.#decodeSimpleString(String, chunk); + } + switch (chunk[this.#cursor]) { + case ASCII["+"]: + return this.#maybeDecodeNumberValue(false, chunk); + case ASCII["-"]: + return this.#maybeDecodeNumberValue(true, chunk); + default: + return this.#decodeNumberValue(false, this.#decodeUnsingedNumber.bind(this, 0), chunk); + } } - const type = typeof obj; - if (type !== typeof ref) { - return false; + #maybeDecodeNumberValue(isNegative, chunk) { + const cb = this.#decodeUnsingedNumber.bind(this, 0); + return ++this.#cursor === chunk.length ? this.#decodeNumberValue.bind(this, isNegative, cb) : this.#decodeNumberValue(isNegative, cb, chunk); } - if (obj === null || ref === null) { - return false; + #decodeNumberValue(isNegative, numberCb, chunk) { + const number3 = numberCb(chunk); + return typeof number3 === "function" ? this.#decodeNumberValue.bind(this, isNegative, number3) : isNegative ? -number3 : number3; } - if (type === "function") { - if (!options2.deepFunction || obj.toString() !== ref.toString()) { - return false; - } - } else if (type !== "object") { - return obj !== obj && ref !== ref; - } - const instanceType = internals.getSharedType(obj, ref, !!options2.prototype); - switch (instanceType) { - case Types.buffer: - return Buffer && Buffer.prototype.equals.call(obj, ref); - // $lab:coverage:ignore$ - case Types.promise: - return obj === ref; - case Types.regex: - case Types.url: - return obj.toString() === ref.toString(); - case internals.mismatched: - return false; + #decodeUnsingedNumber(number3, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII["\r"]) { + this.#cursor = cursor + 2; + return number3; + } + number3 = number3 * 10 + byte - ASCII["0"]; + } while (++cursor < chunk.length); + this.#cursor = cursor; + return this.#decodeUnsingedNumber.bind(this, number3); } - for (let i2 = seen.length - 1; i2 >= 0; --i2) { - if (seen[i2].isSame(obj, ref)) { - return true; + #decodeBigNumber(type, chunk) { + if (type === String) { + return this.#decodeSimpleString(String, chunk); + } + switch (chunk[this.#cursor]) { + case ASCII["+"]: + return this.#maybeDecodeBigNumberValue(false, chunk); + case ASCII["-"]: + return this.#maybeDecodeBigNumberValue(true, chunk); + default: + return this.#decodeBigNumberValue(false, this.#decodeUnsingedBigNumber.bind(this, 0n), chunk); } } - seen.push(new internals.SeenEntry(obj, ref)); - try { - return !!internals.isDeepEqualObj(instanceType, obj, ref, options2, seen); - } finally { - seen.pop(); + #maybeDecodeBigNumberValue(isNegative, chunk) { + const cb = this.#decodeUnsingedBigNumber.bind(this, 0n); + return ++this.#cursor === chunk.length ? this.#decodeBigNumberValue.bind(this, isNegative, cb) : this.#decodeBigNumberValue(isNegative, cb, chunk); } - }; - internals.getSharedType = function(obj, ref, checkPrototype) { - if (checkPrototype) { - if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) { - return internals.mismatched; - } - return Types.getInternalProto(obj); + #decodeBigNumberValue(isNegative, bigNumberCb, chunk) { + const bigNumber = bigNumberCb(chunk); + return typeof bigNumber === "function" ? this.#decodeBigNumberValue.bind(this, isNegative, bigNumber) : isNegative ? -bigNumber : bigNumber; } - const type = Types.getInternalProto(obj); - if (type !== Types.getInternalProto(ref)) { - return internals.mismatched; + #decodeUnsingedBigNumber(bigNumber, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII["\r"]) { + this.#cursor = cursor + 2; + return bigNumber; + } + bigNumber = bigNumber * 10n + BigInt(byte - ASCII["0"]); + } while (++cursor < chunk.length); + this.#cursor = cursor; + return this.#decodeUnsingedBigNumber.bind(this, bigNumber); } - return type; - }; - internals.valueOf = function(obj) { - const objValueOf = obj.valueOf; - if (objValueOf === void 0) { - return obj; + #decodeDouble(type, chunk) { + if (type === String) { + return this.#decodeSimpleString(String, chunk); + } + switch (chunk[this.#cursor]) { + case ASCII.n: + this.#cursor += 5; + return NaN; + case ASCII["+"]: + return this.#maybeDecodeDoubleInteger(false, chunk); + case ASCII["-"]: + return this.#maybeDecodeDoubleInteger(true, chunk); + default: + return this.#decodeDoubleInteger(false, 0, chunk); + } } - try { - return objValueOf.call(obj); - } catch (err) { - return err; + #maybeDecodeDoubleInteger(isNegative, chunk) { + return ++this.#cursor === chunk.length ? this.#decodeDoubleInteger.bind(this, isNegative, 0) : this.#decodeDoubleInteger(isNegative, 0, chunk); } - }; - internals.hasOwnEnumerableProperty = function(obj, key) { - return Object.prototype.propertyIsEnumerable.call(obj, key); - }; - internals.isSetSimpleEqual = function(obj, ref) { - for (const entry of Set.prototype.values.call(obj)) { - if (!Set.prototype.has.call(ref, entry)) { - return false; + #decodeDoubleInteger(isNegative, integer2, chunk) { + if (chunk[this.#cursor] === ASCII.i) { + this.#cursor += 5; + return isNegative ? -Infinity : Infinity; } + return this.#continueDecodeDoubleInteger(isNegative, integer2, chunk); } - return true; - }; - internals.isDeepEqualObj = function(instanceType, obj, ref, options2, seen) { - const { isDeepEqual, valueOf, hasOwnEnumerableProperty } = internals; - const { keys, getOwnPropertySymbols } = Object; - if (instanceType === Types.array) { - if (options2.part) { - for (const objValue of obj) { - for (const refValue of ref) { - if (isDeepEqual(objValue, refValue, options2, seen)) { - return true; - } - } - } - } else { - if (obj.length !== ref.length) { - return false; + #continueDecodeDoubleInteger(isNegative, integer2, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + switch (byte) { + case ASCII["."]: + this.#cursor = cursor + 1; + return this.#cursor < chunk.length ? this.#decodeDoubleDecimal(isNegative, 0, integer2, chunk) : this.#decodeDoubleDecimal.bind(this, isNegative, 0, integer2); + case ASCII.E: + case ASCII.e: + this.#cursor = cursor + 1; + const i2 = isNegative ? -integer2 : integer2; + return this.#cursor < chunk.length ? this.#decodeDoubleExponent(i2, chunk) : this.#decodeDoubleExponent.bind(this, i2); + case ASCII["\r"]: + this.#cursor = cursor + 2; + return isNegative ? -integer2 : integer2; + default: + integer2 = integer2 * 10 + byte - ASCII["0"]; } - for (let i2 = 0; i2 < obj.length; ++i2) { - if (!isDeepEqual(obj[i2], ref[i2], options2, seen)) { - return false; - } + } while (++cursor < chunk.length); + this.#cursor = cursor; + return this.#continueDecodeDoubleInteger.bind(this, isNegative, integer2); + } + // Precalculated multipliers for decimal points to improve performance + // "... about 15 to 17 decimal places ..." + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#:~:text=about%2015%20to%2017%20decimal%20places + static #DOUBLE_DECIMAL_MULTIPLIERS = [ + 0.1, + 0.01, + 1e-3, + 1e-4, + 1e-5, + 1e-6, + 1e-7, + 1e-8, + 1e-9, + 1e-10, + 1e-11, + 1e-12, + 1e-13, + 1e-14, + 1e-15, + 1e-16, + 1e-17 + ]; + #decodeDoubleDecimal(isNegative, decimalIndex, double, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + switch (byte) { + case ASCII.E: + case ASCII.e: + this.#cursor = cursor + 1; + const d = isNegative ? -double : double; + return this.#cursor === chunk.length ? this.#decodeDoubleExponent.bind(this, d) : this.#decodeDoubleExponent(d, chunk); + case ASCII["\r"]: + this.#cursor = cursor + 2; + return isNegative ? -double : double; } - return true; - } - } else if (instanceType === Types.set) { - if (obj.size !== ref.size) { - return false; - } - if (!internals.isSetSimpleEqual(obj, ref)) { - const ref2 = new Set(Set.prototype.values.call(ref)); - for (const objEntry of Set.prototype.values.call(obj)) { - if (ref2.delete(objEntry)) { - continue; - } - let found = false; - for (const refEntry of ref2) { - if (isDeepEqual(objEntry, refEntry, options2, seen)) { - ref2.delete(refEntry); - found = true; - break; - } - } - if (!found) { - return false; - } + if (decimalIndex < _a2.#DOUBLE_DECIMAL_MULTIPLIERS.length) { + double += (byte - ASCII["0"]) * _a2.#DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; } + } while (++cursor < chunk.length); + this.#cursor = cursor; + return this.#decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); + } + #decodeDoubleExponent(double, chunk) { + switch (chunk[this.#cursor]) { + case ASCII["+"]: + return ++this.#cursor === chunk.length ? this.#continueDecodeDoubleExponent.bind(this, false, double, 0) : this.#continueDecodeDoubleExponent(false, double, 0, chunk); + case ASCII["-"]: + return ++this.#cursor === chunk.length ? this.#continueDecodeDoubleExponent.bind(this, true, double, 0) : this.#continueDecodeDoubleExponent(true, double, 0, chunk); } - } else if (instanceType === Types.map) { - if (obj.size !== ref.size) { - return false; - } - for (const [key, value] of Map.prototype.entries.call(obj)) { - if (value === void 0 && !Map.prototype.has.call(ref, key)) { - return false; + return this.#continueDecodeDoubleExponent(false, double, 0, chunk); + } + #continueDecodeDoubleExponent(isNegative, double, exponent, chunk) { + let cursor = this.#cursor; + do { + const byte = chunk[cursor]; + if (byte === ASCII["\r"]) { + this.#cursor = cursor + 2; + return double * 10 ** (isNegative ? -exponent : exponent); } - if (!isDeepEqual(value, Map.prototype.get.call(ref, key), options2, seen)) { - return false; + exponent = exponent * 10 + byte - ASCII["0"]; + } while (++cursor < chunk.length); + this.#cursor = cursor; + return this.#continueDecodeDoubleExponent.bind(this, isNegative, double, exponent); + } + #findCRLF(chunk, cursor) { + while (chunk[cursor] !== ASCII["\r"]) { + if (++cursor === chunk.length) { + this.#cursor = chunk.length; + return -1; } } - } else if (instanceType === Types.error) { - if (obj.name !== ref.name || obj.message !== ref.message) { - return false; - } - } - const valueOfObj = valueOf(obj); - const valueOfRef = valueOf(ref); - if ((obj !== valueOfObj || ref !== valueOfRef) && !isDeepEqual(valueOfObj, valueOfRef, options2, seen)) { - return false; + this.#cursor = cursor + 2; + return cursor; } - const objKeys = keys(obj); - if (!options2.part && objKeys.length !== keys(ref).length && !options2.skip) { - return false; + #decodeSimpleString(type, chunk) { + const start = this.#cursor, crlfIndex = this.#findCRLF(chunk, start); + if (crlfIndex === -1) { + return this.#continueDecodeSimpleString.bind(this, [chunk.subarray(start)], type); + } + const slice = chunk.subarray(start, crlfIndex); + return type === Buffer ? slice : slice.toString(); } - let skipped = 0; - for (const key of objKeys) { - if (options2.skip && options2.skip.includes(key)) { - if (ref[key] === void 0) { - ++skipped; - } - continue; + #continueDecodeSimpleString(chunks, type, chunk) { + const start = this.#cursor, crlfIndex = this.#findCRLF(chunk, start); + if (crlfIndex === -1) { + chunks.push(chunk.subarray(start)); + return this.#continueDecodeSimpleString.bind(this, chunks, type); } - if (!hasOwnEnumerableProperty(ref, key)) { - return false; + chunks.push(chunk.subarray(start, crlfIndex)); + const buffer = Buffer.concat(chunks); + return type === Buffer ? buffer : buffer.toString(); + } + #decodeBlobString(type, chunk) { + if (chunk[this.#cursor] === ASCII["-"]) { + this.#cursor += 4; + return null; } - if (!isDeepEqual(obj[key], ref[key], options2, seen)) { - return false; + const length2 = this.#decodeUnsingedNumber(0, chunk); + if (typeof length2 === "function") { + return this.#continueDecodeBlobStringLength.bind(this, length2, type); + } else if (this.#cursor >= chunk.length) { + return this.#decodeBlobStringWithLength.bind(this, length2, type); } + return this.#decodeBlobStringWithLength(length2, type, chunk); } - if (!options2.part && objKeys.length - skipped !== keys(ref).length) { - return false; - } - if (options2.symbols !== false) { - const objSymbols = getOwnPropertySymbols(obj); - const refSymbols = new Set(getOwnPropertySymbols(ref)); - for (const key of objSymbols) { - if (!options2.skip?.includes(key)) { - if (hasOwnEnumerableProperty(obj, key)) { - if (!hasOwnEnumerableProperty(ref, key)) { - return false; - } - if (!isDeepEqual(obj[key], ref[key], options2, seen)) { - return false; - } - } else if (hasOwnEnumerableProperty(ref, key)) { - return false; - } - } - refSymbols.delete(key); + #continueDecodeBlobStringLength(lengthCb, type, chunk) { + const length2 = lengthCb(chunk); + if (typeof length2 === "function") { + return this.#continueDecodeBlobStringLength.bind(this, length2, type); + } else if (this.#cursor >= chunk.length) { + return this.#decodeBlobStringWithLength.bind(this, length2, type); } - for (const key of refSymbols) { - if (hasOwnEnumerableProperty(ref, key)) { - return false; - } + return this.#decodeBlobStringWithLength(length2, type, chunk); + } + #decodeStringWithLength(length2, skip, type, chunk) { + const end = this.#cursor + length2; + if (end >= chunk.length) { + const slice2 = chunk.subarray(this.#cursor); + this.#cursor = chunk.length; + return this.#continueDecodeStringWithLength.bind(this, length2 - slice2.length, [slice2], skip, type); } + const slice = chunk.subarray(this.#cursor, end); + this.#cursor = end + skip; + return type === Buffer ? slice : slice.toString(); } - return true; - }; - internals.SeenEntry = class { - constructor(obj, ref) { - this.obj = obj; - this.ref = ref; + #continueDecodeStringWithLength(length2, chunks, skip, type, chunk) { + const end = this.#cursor + length2; + if (end >= chunk.length) { + const slice = chunk.subarray(this.#cursor); + chunks.push(slice); + this.#cursor = chunk.length; + return this.#continueDecodeStringWithLength.bind(this, length2 - slice.length, chunks, skip, type); + } + chunks.push(chunk.subarray(this.#cursor, end)); + this.#cursor = end + skip; + const buffer = Buffer.concat(chunks); + return type === Buffer ? buffer : buffer.toString(); } - isSame(obj, ref) { - return this.obj === obj && this.ref === ref; + #decodeBlobStringWithLength(length2, type, chunk) { + return this.#decodeStringWithLength(length2, 2, type, chunk); } - }; - } -}); -var require_escapeRegex = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/escapeRegex.js"(exports2, module14) { - "use strict"; - module14.exports = function(string3) { - return string3.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, "\\$&"); - }; - } -}); -var require_contain = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/contain.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var DeepEqual = require_deepEqual(); - var EscapeRegex = require_escapeRegex(); - var Utils = require_utils(); - var internals = {}; - module14.exports = function(ref, values, options2 = {}) { - if (typeof values !== "object") { - values = [values]; + #decodeVerbatimString(type, chunk) { + return this.#continueDecodeVerbatimStringLength(this.#decodeUnsingedNumber.bind(this, 0), type, chunk); } - Assert(!Array.isArray(values) || values.length, "Values array cannot be empty"); - if (typeof ref === "string") { - return internals.string(ref, values, options2); + #continueDecodeVerbatimStringLength(lengthCb, type, chunk) { + const length2 = lengthCb(chunk); + return typeof length2 === "function" ? this.#continueDecodeVerbatimStringLength.bind(this, length2, type) : this.#decodeVerbatimStringWithLength(length2, type, chunk); } - if (Array.isArray(ref)) { - return internals.array(ref, values, options2); + #decodeVerbatimStringWithLength(length2, type, chunk) { + const stringLength = length2 - 4; + if (type === verbatim_string_1.VerbatimString) { + return this.#decodeVerbatimStringFormat(stringLength, chunk); + } + this.#cursor += 4; + return this.#cursor >= chunk.length ? this.#decodeBlobStringWithLength.bind(this, stringLength, type) : this.#decodeBlobStringWithLength(stringLength, type, chunk); } - Assert(typeof ref === "object", "Reference must be string or an object"); - return internals.object(ref, values, options2); - }; - internals.array = function(ref, values, options2) { - if (!Array.isArray(values)) { - values = [values]; + #decodeVerbatimStringFormat(stringLength, chunk) { + const formatCb = this.#decodeStringWithLength.bind(this, 3, 1, String); + return this.#cursor >= chunk.length ? this.#continueDecodeVerbatimStringFormat.bind(this, stringLength, formatCb) : this.#continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk); } - if (!ref.length) { - return false; + #continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk) { + const format52 = formatCb(chunk); + return typeof format52 === "function" ? this.#continueDecodeVerbatimStringFormat.bind(this, stringLength, format52) : this.#decodeVerbatimStringWithFormat(stringLength, format52, chunk); } - if (options2.only && options2.once && ref.length !== values.length) { - return false; + #decodeVerbatimStringWithFormat(stringLength, format52, chunk) { + return this.#continueDecodeVerbatimStringWithFormat(format52, this.#decodeBlobStringWithLength.bind(this, stringLength, String), chunk); } - let compare; - const map = /* @__PURE__ */ new Map(); - for (const value of values) { - if (!options2.deep || !value || typeof value !== "object") { - const existing = map.get(value); - if (existing) { - ++existing.allowed; - } else { - map.set(value, { allowed: 1, hits: 0 }); - } - } else { - compare = compare ?? internals.compare(options2); - let found = false; - for (const [key, existing] of map.entries()) { - if (compare(key, value)) { - ++existing.allowed; - found = true; - break; - } - } - if (!found) { - map.set(value, { allowed: 1, hits: 0 }); - } - } + #continueDecodeVerbatimStringWithFormat(format52, stringCb, chunk) { + const string3 = stringCb(chunk); + return typeof string3 === "function" ? this.#continueDecodeVerbatimStringWithFormat.bind(this, format52, string3) : new verbatim_string_1.VerbatimString(format52, string3); } - let hits = 0; - for (const item of ref) { - let match; - if (!options2.deep || !item || typeof item !== "object") { - match = map.get(item); - } else { - compare = compare ?? internals.compare(options2); - for (const [key, existing] of map.entries()) { - if (compare(key, item)) { - match = existing; - break; - } - } - } - if (match) { - ++match.hits; - ++hits; - if (options2.once && match.hits > match.allowed) { - return false; - } - } + #decodeSimpleError(chunk) { + const string3 = this.#decodeSimpleString(String, chunk); + return typeof string3 === "function" ? this.#continueDecodeSimpleError.bind(this, string3) : new errors_1.SimpleError(string3); } - if (options2.only && hits !== ref.length) { - return false; + #continueDecodeSimpleError(stringCb, chunk) { + const string3 = stringCb(chunk); + return typeof string3 === "function" ? this.#continueDecodeSimpleError.bind(this, string3) : new errors_1.SimpleError(string3); } - for (const match of map.values()) { - if (match.hits === match.allowed) { - continue; - } - if (match.hits < match.allowed && !options2.part) { - return false; - } + #decodeBlobError(chunk) { + const string3 = this.#decodeBlobString(String, chunk); + return typeof string3 === "function" ? this.#continueDecodeBlobError.bind(this, string3) : new errors_1.BlobError(string3); } - return !!hits; - }; - internals.object = function(ref, values, options2) { - Assert(options2.once === void 0, "Cannot use option once with object"); - const keys = Utils.keys(ref, options2); - if (!keys.length) { - return false; + #continueDecodeBlobError(stringCb, chunk) { + const string3 = stringCb(chunk); + return typeof string3 === "function" ? this.#continueDecodeBlobError.bind(this, string3) : new errors_1.BlobError(string3); } - if (Array.isArray(values)) { - return internals.array(keys, values, options2); + #decodeNestedType(typeMapping, chunk) { + const type = chunk[this.#cursor]; + return ++this.#cursor === chunk.length ? this.#decodeNestedTypeValue.bind(this, type, typeMapping) : this.#decodeNestedTypeValue(type, typeMapping, chunk); } - const symbols2 = Object.getOwnPropertySymbols(values).filter((sym) => values.propertyIsEnumerable(sym)); - const targets = [...Object.keys(values), ...symbols2]; - const compare = internals.compare(options2); - const set = new Set(targets); - for (const key of keys) { - if (!set.has(key)) { - if (options2.only) { - return false; - } - continue; + #decodeNestedTypeValue(type, typeMapping, chunk) { + switch (type) { + case exports2.RESP_TYPES.NULL: + return this.#decodeNull(); + case exports2.RESP_TYPES.BOOLEAN: + return this.#decodeBoolean(chunk); + case exports2.RESP_TYPES.NUMBER: + return this.#decodeNumber(typeMapping[exports2.RESP_TYPES.NUMBER], chunk); + case exports2.RESP_TYPES.BIG_NUMBER: + return this.#decodeBigNumber(typeMapping[exports2.RESP_TYPES.BIG_NUMBER], chunk); + case exports2.RESP_TYPES.DOUBLE: + return this.#decodeDouble(typeMapping[exports2.RESP_TYPES.DOUBLE], chunk); + case exports2.RESP_TYPES.SIMPLE_STRING: + return this.#decodeSimpleString(typeMapping[exports2.RESP_TYPES.SIMPLE_STRING], chunk); + case exports2.RESP_TYPES.BLOB_STRING: + return this.#decodeBlobString(typeMapping[exports2.RESP_TYPES.BLOB_STRING], chunk); + case exports2.RESP_TYPES.VERBATIM_STRING: + return this.#decodeVerbatimString(typeMapping[exports2.RESP_TYPES.VERBATIM_STRING], chunk); + case exports2.RESP_TYPES.SIMPLE_ERROR: + return this.#decodeSimpleError(chunk); + case exports2.RESP_TYPES.BLOB_ERROR: + return this.#decodeBlobError(chunk); + case exports2.RESP_TYPES.ARRAY: + return this.#decodeArray(typeMapping, chunk); + case exports2.RESP_TYPES.SET: + return this.#decodeSet(typeMapping, chunk); + case exports2.RESP_TYPES.MAP: + return this.#decodeMap(typeMapping, chunk); + default: + throw new Error(`Unknown RESP type ${type} "${String.fromCharCode(type)}"`); } - if (!compare(values[key], ref[key])) { - return false; + } + #decodeArray(typeMapping, chunk) { + if (chunk[this.#cursor] === ASCII["-"]) { + this.#cursor += 4; + return null; } - set.delete(key); + return this.#decodeArrayWithLength(this.#decodeUnsingedNumber(0, chunk), typeMapping, chunk); } - if (set.size) { - return options2.part ? set.size < targets.length : false; + #decodeArrayWithLength(length2, typeMapping, chunk) { + return typeof length2 === "function" ? this.#continueDecodeArrayLength.bind(this, length2, typeMapping) : this.#decodeArrayItems(new Array(length2), 0, typeMapping, chunk); } - return true; - }; - internals.string = function(ref, values, options2) { - if (ref === "") { - return values.length === 1 && values[0] === "" || // '' contains '' - !options2.once && !values.some((v2) => v2 !== ""); + #continueDecodeArrayLength(lengthCb, typeMapping, chunk) { + return this.#decodeArrayWithLength(lengthCb(chunk), typeMapping, chunk); } - const map = /* @__PURE__ */ new Map(); - const patterns = []; - for (const value of values) { - Assert(typeof value === "string", "Cannot compare string reference to non-string value"); - if (value) { - const existing = map.get(value); - if (existing) { - ++existing.allowed; - } else { - map.set(value, { allowed: 1, hits: 0 }); - patterns.push(EscapeRegex(value)); + #decodeArrayItems(array2, filled, typeMapping, chunk) { + for (let i2 = filled; i2 < array2.length; i2++) { + if (this.#cursor >= chunk.length) { + return this.#decodeArrayItems.bind(this, array2, i2, typeMapping); } - } else if (options2.once || options2.only) { - return false; + const item = this.#decodeNestedType(typeMapping, chunk); + if (typeof item === "function") { + return this.#continueDecodeArrayItems.bind(this, array2, i2, item, typeMapping); + } + array2[i2] = item; } + return array2; } - if (!patterns.length) { - return true; + #continueDecodeArrayItems(array2, filled, itemCb, typeMapping, chunk) { + const item = itemCb(chunk); + if (typeof item === "function") { + return this.#continueDecodeArrayItems.bind(this, array2, filled, item, typeMapping); + } + array2[filled++] = item; + return this.#decodeArrayItems(array2, filled, typeMapping, chunk); } - const regex = new RegExp(`(${patterns.join("|")})`, "g"); - const leftovers = ref.replace(regex, ($0, $1) => { - ++map.get($1).hits; - return ""; - }); - if (options2.only && leftovers) { - return false; + #decodeSet(typeMapping, chunk) { + const length2 = this.#decodeUnsingedNumber(0, chunk); + if (typeof length2 === "function") { + return this.#continueDecodeSetLength.bind(this, length2, typeMapping); + } + return this.#decodeSetItems(length2, typeMapping, chunk); } - let any = false; - for (const match of map.values()) { - if (match.hits) { - any = true; + #continueDecodeSetLength(lengthCb, typeMapping, chunk) { + const length2 = lengthCb(chunk); + return typeof length2 === "function" ? this.#continueDecodeSetLength.bind(this, length2, typeMapping) : this.#decodeSetItems(length2, typeMapping, chunk); + } + #decodeSetItems(length2, typeMapping, chunk) { + return typeMapping[exports2.RESP_TYPES.SET] === Set ? this.#decodeSetAsSet(/* @__PURE__ */ new Set(), length2, typeMapping, chunk) : this.#decodeArrayItems(new Array(length2), 0, typeMapping, chunk); + } + #decodeSetAsSet(set, remaining, typeMapping, chunk) { + while (remaining > 0) { + if (this.#cursor >= chunk.length) { + return this.#decodeSetAsSet.bind(this, set, remaining, typeMapping); + } + const item = this.#decodeNestedType(typeMapping, chunk); + if (typeof item === "function") { + return this.#continueDecodeSetAsSet.bind(this, set, remaining, item, typeMapping); + } + set.add(item); + --remaining; } - if (match.hits === match.allowed) { - continue; + return set; + } + #continueDecodeSetAsSet(set, remaining, itemCb, typeMapping, chunk) { + const item = itemCb(chunk); + if (typeof item === "function") { + return this.#continueDecodeSetAsSet.bind(this, set, remaining, item, typeMapping); } - if (match.hits < match.allowed && !options2.part) { - return false; + set.add(item); + return this.#decodeSetAsSet(set, remaining - 1, typeMapping, chunk); + } + #decodeMap(typeMapping, chunk) { + const length2 = this.#decodeUnsingedNumber(0, chunk); + if (typeof length2 === "function") { + return this.#continueDecodeMapLength.bind(this, length2, typeMapping); } - if (options2.once) { - return false; + return this.#decodeMapItems(length2, typeMapping, chunk); + } + #continueDecodeMapLength(lengthCb, typeMapping, chunk) { + const length2 = lengthCb(chunk); + return typeof length2 === "function" ? this.#continueDecodeMapLength.bind(this, length2, typeMapping) : this.#decodeMapItems(length2, typeMapping, chunk); + } + #decodeMapItems(length2, typeMapping, chunk) { + switch (typeMapping[exports2.RESP_TYPES.MAP]) { + case Map: + return this.#decodeMapAsMap(/* @__PURE__ */ new Map(), length2, typeMapping, chunk); + case Array: + return this.#decodeArrayItems(new Array(length2 * 2), 0, typeMapping, chunk); + default: + return this.#decodeMapAsObject(/* @__PURE__ */ Object.create(null), length2, typeMapping, chunk); } } - return !!any; - }; - internals.compare = function(options2) { - if (!options2.deep) { - return internals.shallow; + #decodeMapAsMap(map, remaining, typeMapping, chunk) { + while (remaining > 0) { + if (this.#cursor >= chunk.length) { + return this.#decodeMapAsMap.bind(this, map, remaining, typeMapping); + } + const key = this.#decodeMapKey(typeMapping, chunk); + if (typeof key === "function") { + return this.#continueDecodeMapKey.bind(this, map, remaining, key, typeMapping); + } + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapValue.bind(this, map, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); + } + const value = this.#decodeNestedType(typeMapping, chunk); + if (typeof value === "function") { + return this.#continueDecodeMapValue.bind(this, map, remaining, key, value, typeMapping); + } + map.set(key, value); + --remaining; + } + return map; } - const hasOnly = options2.only !== void 0; - const hasPart = options2.part !== void 0; - const flags = { - prototype: hasOnly ? options2.only : hasPart ? !options2.part : false, - part: hasOnly ? !options2.only : hasPart ? options2.part : false - }; - return (a, b) => DeepEqual(a, b, flags); - }; - internals.shallow = function(a, b) { - return a === b; - }; - } -}); -var require_escapeHeaderAttribute = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/escapeHeaderAttribute.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - module14.exports = function(attribute) { - Assert(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/.test(attribute), "Bad attribute value (" + attribute + ")"); - return attribute.replace(/\\/g, "\\\\").replace(/\"/g, '\\"'); - }; - } -}); -var require_escapeHtml = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/escapeHtml.js"(exports2, module14) { - "use strict"; - var internals = {}; - module14.exports = function(input) { - if (!input) { - return ""; + #decodeMapKey(typeMapping, chunk) { + const type = chunk[this.#cursor]; + return ++this.#cursor === chunk.length ? this.#decodeMapKeyValue.bind(this, type, typeMapping) : this.#decodeMapKeyValue(type, typeMapping, chunk); } - let escaped = ""; - for (let i2 = 0; i2 < input.length; ++i2) { - const charCode = input.charCodeAt(i2); - if (internals.isSafe(charCode)) { - escaped += input[i2]; - } else { - escaped += internals.escapeHtmlChar(charCode); + #decodeMapKeyValue(type, typeMapping, chunk) { + switch (type) { + // decode simple string map key as string (and not as buffer) + case exports2.RESP_TYPES.SIMPLE_STRING: + return this.#decodeSimpleString(String, chunk); + // decode blob string map key as string (and not as buffer) + case exports2.RESP_TYPES.BLOB_STRING: + return this.#decodeBlobString(String, chunk); + default: + return this.#decodeNestedTypeValue(type, typeMapping, chunk); } } - return escaped; - }; - internals.escapeHtmlChar = function(charCode) { - const namedEscape = internals.namedHtml.get(charCode); - if (namedEscape) { - return namedEscape; + #continueDecodeMapKey(map, remaining, keyCb, typeMapping, chunk) { + const key = keyCb(chunk); + if (typeof key === "function") { + return this.#continueDecodeMapKey.bind(this, map, remaining, key, typeMapping); + } + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapValue.bind(this, map, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); + } + const value = this.#decodeNestedType(typeMapping, chunk); + if (typeof value === "function") { + return this.#continueDecodeMapValue.bind(this, map, remaining, key, value, typeMapping); + } + map.set(key, value); + return this.#decodeMapAsMap(map, remaining - 1, typeMapping, chunk); } - if (charCode >= 256) { - return "&#" + charCode + ";"; + #continueDecodeMapValue(map, remaining, key, valueCb, typeMapping, chunk) { + const value = valueCb(chunk); + if (typeof value === "function") { + return this.#continueDecodeMapValue.bind(this, map, remaining, key, value, typeMapping); + } + map.set(key, value); + return this.#decodeMapAsMap(map, remaining - 1, typeMapping, chunk); } - const hexValue = charCode.toString(16).padStart(2, "0"); - return `&#x${hexValue};`; - }; - internals.isSafe = function(charCode) { - return internals.safeCharCodes.has(charCode); - }; - internals.namedHtml = /* @__PURE__ */ new Map([ - [38, "&"], - [60, "<"], - [62, ">"], - [34, """], - [160, " "], - [162, "¢"], - [163, "£"], - [164, "¤"], - [169, "©"], - [174, "®"] - ]); - internals.safeCharCodes = function() { - const safe = /* @__PURE__ */ new Set(); - for (let i2 = 32; i2 < 123; ++i2) { - if (i2 >= 97 || // a-z - i2 >= 65 && i2 <= 90 || // A-Z - i2 >= 48 && i2 <= 57 || // 0-9 - i2 === 32 || // space - i2 === 46 || // . - i2 === 44 || // , - i2 === 45 || // - - i2 === 58 || // : - i2 === 95) { - safe.add(i2); - } - } - return safe; - }(); - } -}); -var require_escapeJson = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/escapeJson.js"(exports2, module14) { - "use strict"; - var internals = {}; - module14.exports = function(input) { - if (!input) { - return ""; + #decodeMapAsObject(object2, remaining, typeMapping, chunk) { + while (remaining > 0) { + if (this.#cursor >= chunk.length) { + return this.#decodeMapAsObject.bind(this, object2, remaining, typeMapping); + } + const key = this.#decodeMapKey(typeMapping, chunk); + if (typeof key === "function") { + return this.#continueDecodeMapAsObjectKey.bind(this, object2, remaining, key, typeMapping); + } + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); + } + const value = this.#decodeNestedType(typeMapping, chunk); + if (typeof value === "function") { + return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, value, typeMapping); + } + object2[key] = value; + --remaining; + } + return object2; + } + #continueDecodeMapAsObjectKey(object2, remaining, keyCb, typeMapping, chunk) { + const key = keyCb(chunk); + if (typeof key === "function") { + return this.#continueDecodeMapAsObjectKey.bind(this, object2, remaining, key, typeMapping); + } + if (this.#cursor >= chunk.length) { + return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); + } + const value = this.#decodeNestedType(typeMapping, chunk); + if (typeof value === "function") { + return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, value, typeMapping); + } + object2[key] = value; + return this.#decodeMapAsObject(object2, remaining - 1, typeMapping, chunk); + } + #continueDecodeMapAsObjectValue(object2, remaining, key, valueCb, typeMapping, chunk) { + const value = valueCb(chunk); + if (typeof value === "function") { + return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, value, typeMapping); + } + object2[key] = value; + return this.#decodeMapAsObject(object2, remaining - 1, typeMapping, chunk); } - return input.replace(/[<>&\u2028\u2029]/g, internals.escape); - }; - internals.escape = function(char) { - return internals.replacements.get(char); }; - internals.replacements = /* @__PURE__ */ new Map([ - ["<", "\\u003c"], - [">", "\\u003e"], - ["&", "\\u0026"], - ["\u2028", "\\u2028"], - ["\u2029", "\\u2029"] - ]); + exports2.Decoder = Decoder2; + _a2 = Decoder2; } }); -var require_flatten = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/flatten.js"(exports2, module14) { +var require_lua_script = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/lua-script.js"(exports2) { "use strict"; - var internals = {}; - module14.exports = internals.flatten = function(array2, target) { - const result = target || []; - for (const entry of array2) { - if (Array.isArray(entry)) { - internals.flatten(entry, result); - } else { - result.push(entry); - } - } - return result; - }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.scriptSha1 = exports2.defineScript = void 0; + var node_crypto_1 = __require2("node:crypto"); + function defineScript(script) { + return { + ...script, + SHA1: scriptSha1(script.SCRIPT) + }; + } + exports2.defineScript = defineScript; + function scriptSha1(script) { + return (0, node_crypto_1.createHash)("sha1").update(script).digest("hex"); + } + exports2.scriptSha1 = scriptSha1; } }); -var require_intersect = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/intersect.js"(exports2, module14) { +var require_ACL_CAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_CAT.js"(exports2) { "use strict"; - var internals = {}; - module14.exports = function(array1, array2, options2 = {}) { - if (!array1 || !array2) { - return options2.first ? null : []; - } - const common4 = []; - const hash3 = Array.isArray(array1) ? new Set(array1) : array1; - const found = /* @__PURE__ */ new Set(); - for (const value of array2) { - if (internals.has(hash3, value) && !found.has(value)) { - if (options2.first) { - return value; - } - common4.push(value); - found.add(value); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Lists ACL categories or commands in a category + * @param parser - The Redis command parser + * @param categoryName - Optional category name to filter commands + */ + parseCommand(parser3, categoryName) { + parser3.push("ACL", "CAT"); + if (categoryName) { + parser3.push(categoryName); } - } - return options2.first ? null : common4; - }; - internals.has = function(ref, key) { - if (typeof ref.has === "function") { - return ref.has(key); - } - return ref[key] !== void 0; + }, + transformReply: void 0 }; } }); -var require_isPromise = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/isPromise.js"(exports2, module14) { +var require_ACL_DELUSER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_DELUSER.js"(exports2) { "use strict"; - module14.exports = function(promise) { - return typeof promise?.then === "function"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Deletes one or more users from the ACL + * @param parser - The Redis command parser + * @param username - Username(s) to delete + */ + parseCommand(parser3, username) { + parser3.push("ACL", "DELUSER"); + parser3.pushVariadic(username); + }, + transformReply: void 0 }; } }); -var require_once = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/once.js"(exports2, module14) { +var require_ACL_DRYRUN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_DRYRUN.js"(exports2) { "use strict"; - var internals = { - wrapped: Symbol("wrapped") - }; - module14.exports = function(method) { - if (method[internals.wrapped]) { - return method; - } - let once = false; - const wrappedFn = function(...args) { - if (!once) { - once = true; - method(...args); - } - }; - wrappedFn[internals.wrapped] = true; - return wrappedFn; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Simulates ACL operations without executing them + * @param parser - The Redis command parser + * @param username - Username to simulate ACL operations for + * @param command - Command arguments to simulate + */ + parseCommand(parser3, username, command2) { + parser3.push("ACL", "DRYRUN", username, ...command2); + }, + transformReply: void 0 }; } }); -var require_reachTemplate = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/reachTemplate.js"(exports2, module14) { +var require_ACL_GENPASS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_GENPASS.js"(exports2) { "use strict"; - var Reach = require_reach(); - module14.exports = function(obj, template, options2) { - return template.replace(/{([^{}]+)}/g, ($0, chain) => { - const value = Reach(obj, chain, options2); - return value ?? ""; - }); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Generates a secure password for ACL users + * @param parser - The Redis command parser + * @param bits - Optional number of bits for password entropy + */ + parseCommand(parser3, bits) { + parser3.push("ACL", "GENPASS"); + if (bits) { + parser3.push(bits.toString()); + } + }, + transformReply: void 0 }; } }); -var require_wait = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/wait.js"(exports2, module14) { +var require_ACL_GETUSER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_GETUSER.js"(exports2) { "use strict"; - var internals = { - maxTimer: 2 ** 31 - 1 - // ~25 days - }; - module14.exports = function(timeout, returnValue, options2) { - if (typeof timeout === "bigint") { - timeout = Number(timeout); - } - if (timeout >= Number.MAX_SAFE_INTEGER) { - timeout = Infinity; - } - if (typeof timeout !== "number" && timeout !== void 0) { - throw new TypeError("Timeout must be a number or bigint"); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns ACL information about a specific user + * @param parser - The Redis command parser + * @param username - Username to get information for + */ + parseCommand(parser3, username) { + parser3.push("ACL", "GETUSER", username); + }, + transformReply: { + 2: (reply) => ({ + flags: reply[1], + passwords: reply[3], + commands: reply[5], + keys: reply[7], + channels: reply[9], + selectors: reply[11]?.map((selector) => { + const inferred = selector; + return { + commands: inferred[1], + keys: inferred[3], + channels: inferred[5] + }; + }) + }), + 3: void 0 } - return new Promise((resolve82) => { - const _setTimeout = options2 ? options2.setTimeout : setTimeout; - const activate = () => { - const time3 = Math.min(timeout, internals.maxTimer); - timeout -= time3; - _setTimeout(() => timeout > 0 ? activate() : resolve82(returnValue), time3); - }; - if (timeout !== Infinity) { - activate(); - } - }); }; } }); -var require_lib = __commonJS({ - "node_modules/.deno/@hapi+hoek@11.0.7/node_modules/@hapi/hoek/lib/index.js"(exports2) { - "use strict"; - exports2.applyToDefaults = require_applyToDefaults(); - exports2.assert = require_assert(); - exports2.AssertError = require_assertError(); - exports2.Bench = require_bench(); - exports2.block = require_block(); - exports2.clone = require_clone(); - exports2.contain = require_contain(); - exports2.deepEqual = require_deepEqual(); - exports2.escapeHeaderAttribute = require_escapeHeaderAttribute(); - exports2.escapeHtml = require_escapeHtml(); - exports2.escapeJson = require_escapeJson(); - exports2.escapeRegex = require_escapeRegex(); - exports2.flatten = require_flatten(); - exports2.ignore = require_ignore(); - exports2.intersect = require_intersect(); - exports2.isPromise = require_isPromise(); - exports2.merge = require_merge(); - exports2.once = require_once(); - exports2.reach = require_reach(); - exports2.reachTemplate = require_reachTemplate(); - exports2.stringify = require_stringify(); - exports2.wait = require_wait(); +var require_ACL_LIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LIST.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns all configured ACL users and their permissions + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("ACL", "LIST"); + }, + transformReply: void 0 + }; } }); -var require_lib2 = __commonJS({ - "node_modules/.deno/@hapi+boom@10.0.1/node_modules/@hapi/boom/lib/index.js"(exports2) { - "use strict"; - var Hoek = require_lib(); - var internals = { - codes: /* @__PURE__ */ new Map([ - [100, "Continue"], - [101, "Switching Protocols"], - [102, "Processing"], - [200, "OK"], - [201, "Created"], - [202, "Accepted"], - [203, "Non-Authoritative Information"], - [204, "No Content"], - [205, "Reset Content"], - [206, "Partial Content"], - [207, "Multi-Status"], - [300, "Multiple Choices"], - [301, "Moved Permanently"], - [302, "Moved Temporarily"], - [303, "See Other"], - [304, "Not Modified"], - [305, "Use Proxy"], - [307, "Temporary Redirect"], - [400, "Bad Request"], - [401, "Unauthorized"], - [402, "Payment Required"], - [403, "Forbidden"], - [404, "Not Found"], - [405, "Method Not Allowed"], - [406, "Not Acceptable"], - [407, "Proxy Authentication Required"], - [408, "Request Time-out"], - [409, "Conflict"], - [410, "Gone"], - [411, "Length Required"], - [412, "Precondition Failed"], - [413, "Request Entity Too Large"], - [414, "Request-URI Too Large"], - [415, "Unsupported Media Type"], - [416, "Requested Range Not Satisfiable"], - [417, "Expectation Failed"], - [418, "I'm a teapot"], - [422, "Unprocessable Entity"], - [423, "Locked"], - [424, "Failed Dependency"], - [425, "Too Early"], - [426, "Upgrade Required"], - [428, "Precondition Required"], - [429, "Too Many Requests"], - [431, "Request Header Fields Too Large"], - [451, "Unavailable For Legal Reasons"], - [500, "Internal Server Error"], - [501, "Not Implemented"], - [502, "Bad Gateway"], - [503, "Service Unavailable"], - [504, "Gateway Time-out"], - [505, "HTTP Version Not Supported"], - [506, "Variant Also Negotiates"], - [507, "Insufficient Storage"], - [509, "Bandwidth Limit Exceeded"], - [510, "Not Extended"], - [511, "Network Authentication Required"] - ]) +var require_ACL_LOAD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LOAD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Reloads ACL configuration from the ACL file + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("ACL", "LOAD"); + }, + transformReply: void 0 }; - exports2.Boom = class extends Error { - constructor(messageOrError, options2 = {}) { - if (messageOrError instanceof Error) { - return exports2.boomify(Hoek.clone(messageOrError), options2); - } - const { statusCode = 500, data = null, ctor = exports2.Boom } = options2; - const error2 = new Error(messageOrError ? messageOrError : void 0); - Error.captureStackTrace(error2, ctor); - error2.data = data; - const boom = internals.initialize(error2, statusCode); - Object.defineProperty(boom, "typeof", { value: ctor }); - if (options2.decorate) { - Object.assign(boom, options2.decorate); - } - return boom; + } +}); +var require_parser = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/parser.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.BasicCommandParser = void 0; + var BasicCommandParser = class { + #redisArgs = []; + #keys = []; + preserve; + get redisArgs() { + return this.#redisArgs; } - static [Symbol.hasInstance](instance) { - if (this === exports2.Boom) { - return exports2.isBoom(instance); - } - return this.prototype.isPrototypeOf(instance); + get keys() { + return this.#keys; } - }; - exports2.isBoom = function(err, statusCode) { - return err instanceof Error && !!err.isBoom && (!statusCode || err.output.statusCode === statusCode); - }; - exports2.boomify = function(err, options2) { - Hoek.assert(err instanceof Error, "Cannot wrap non-Error object"); - options2 = options2 || {}; - if (options2.data !== void 0) { - err.data = options2.data; + get firstKey() { + return this.#keys[0]; } - if (options2.decorate) { - Object.assign(err, options2.decorate); + get cacheKey() { + const tmp = new Array(this.#redisArgs.length * 2); + for (let i2 = 0; i2 < this.#redisArgs.length; i2++) { + tmp[i2] = this.#redisArgs[i2].length; + tmp[i2 + this.#redisArgs.length] = this.#redisArgs[i2]; + } + return tmp.join("_"); } - if (!err.isBoom) { - return internals.initialize(err, options2.statusCode ?? 500, options2.message); + push(...arg) { + this.#redisArgs.push(...arg); } - if (options2.override === false || // Defaults to true - !options2.statusCode && !options2.message) { - return err; + pushVariadic(vals) { + if (Array.isArray(vals)) { + for (const val of vals) { + this.push(val); + } + } else { + this.push(vals); + } } - return internals.initialize(err, options2.statusCode ?? err.output.statusCode, options2.message); - }; - exports2.badRequest = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 400, data, ctor: exports2.badRequest }); - }; - exports2.unauthorized = function(message, scheme, attributes) { - const err = new exports2.Boom(message, { statusCode: 401, ctor: exports2.unauthorized }); - if (!scheme) { - return err; + pushVariadicWithLength(vals) { + if (Array.isArray(vals)) { + this.#redisArgs.push(vals.length.toString()); + } else { + this.#redisArgs.push("1"); + } + this.pushVariadic(vals); } - if (typeof scheme !== "string") { - err.output.headers["WWW-Authenticate"] = scheme.join(", "); - return err; + pushVariadicNumber(vals) { + if (Array.isArray(vals)) { + for (const val of vals) { + this.push(val.toString()); + } + } else { + this.push(vals.toString()); + } } - let wwwAuthenticate = `${scheme}`; - if (attributes || message) { - err.output.payload.attributes = {}; + pushKey(key) { + this.#keys.push(key); + this.#redisArgs.push(key); } - if (attributes) { - if (typeof attributes === "string") { - wwwAuthenticate += " " + Hoek.escapeHeaderAttribute(attributes); - err.output.payload.attributes = attributes; + pushKeysLength(keys) { + if (Array.isArray(keys)) { + this.#redisArgs.push(keys.length.toString()); } else { - wwwAuthenticate += " " + Object.keys(attributes).map((name) => { - const value = attributes[name] ?? ""; - err.output.payload.attributes[name] = value; - return `${name}="${Hoek.escapeHeaderAttribute(value.toString())}"`; - }).join(", "); + this.#redisArgs.push("1"); } + this.pushKeys(keys); } - if (message) { - if (attributes) { - wwwAuthenticate += ","; + pushKeys(keys) { + if (Array.isArray(keys)) { + this.#keys.push(...keys); + this.#redisArgs.push(...keys); + } else { + this.#keys.push(keys); + this.#redisArgs.push(keys); } - wwwAuthenticate += ` error="${Hoek.escapeHeaderAttribute(message)}"`; - err.output.payload.attributes.error = message; - } else { - err.isMissing = true; } - err.output.headers["WWW-Authenticate"] = wwwAuthenticate; - return err; - }; - exports2.paymentRequired = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 402, data, ctor: exports2.paymentRequired }); }; - exports2.forbidden = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 403, data, ctor: exports2.forbidden }); + exports2.BasicCommandParser = BasicCommandParser; + } +}); +var require_generic_transformers = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/generic-transformers.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transformRedisJsonNullReply = exports2.transformRedisJsonReply = exports2.transformRedisJsonArgument = exports2.transformStreamsMessagesReplyResp3 = exports2.transformStreamsMessagesReplyResp2 = exports2.transformStreamMessagesReply = exports2.transformStreamMessageNullReply = exports2.transformStreamMessageReply = exports2.parseArgs = exports2.parseZKeysArguments = exports2.transformRangeReply = exports2.parseSlotRangesArguments = exports2.transformFunctionListItemReply = exports2.RedisFunctionFlags = exports2.transformCommandReply = exports2.CommandCategories = exports2.CommandFlags = exports2.parseOptionalVariadicArgument = exports2.pushVariadicArgument = exports2.pushVariadicNumberArguments = exports2.pushVariadicArguments = exports2.pushEvalArguments = exports2.evalFirstKeyIndex = exports2.transformPXAT = exports2.transformEXAT = exports2.transformSortedSetReply = exports2.transformTuplesReply = exports2.createTransformTuplesReplyFunc = exports2.transformTuplesToMap = exports2.transformNullableDoubleReply = exports2.createTransformNullableDoubleReplyResp2Func = exports2.transformDoubleArrayReply = exports2.createTransformDoubleReplyResp2Func = exports2.transformDoubleReply = exports2.transformStringDoubleArgument = exports2.transformDoubleArgument = exports2.transformBooleanArrayReply = exports2.transformBooleanReply = exports2.isArrayReply = exports2.isNullReply = void 0; + var parser_1 = require_parser(); + var decoder_1 = require_decoder(); + function isNullReply(reply) { + return reply === null; + } + exports2.isNullReply = isNullReply; + function isArrayReply(reply) { + return Array.isArray(reply); + } + exports2.isArrayReply = isArrayReply; + exports2.transformBooleanReply = { + 2: (reply) => reply === 1, + 3: void 0 }; - exports2.notFound = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 404, data, ctor: exports2.notFound }); + exports2.transformBooleanArrayReply = { + 2: (reply) => { + return reply.map(exports2.transformBooleanReply[2]); + }, + 3: void 0 }; - exports2.methodNotAllowed = function(messageOrError, data, allow) { - const err = new exports2.Boom(messageOrError, { statusCode: 405, data, ctor: exports2.methodNotAllowed }); - if (typeof allow === "string") { - allow = [allow]; - } - if (Array.isArray(allow)) { - err.output.headers.Allow = allow.join(", "); + function transformDoubleArgument(num) { + switch (num) { + case Infinity: + return "+inf"; + case -Infinity: + return "-inf"; + default: + return num.toString(); } - return err; - }; - exports2.notAcceptable = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 406, data, ctor: exports2.notAcceptable }); - }; - exports2.proxyAuthRequired = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 407, data, ctor: exports2.proxyAuthRequired }); - }; - exports2.clientTimeout = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 408, data, ctor: exports2.clientTimeout }); - }; - exports2.conflict = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 409, data, ctor: exports2.conflict }); + } + exports2.transformDoubleArgument = transformDoubleArgument; + function transformStringDoubleArgument(num) { + if (typeof num !== "number") + return num; + return transformDoubleArgument(num); + } + exports2.transformStringDoubleArgument = transformStringDoubleArgument; + exports2.transformDoubleReply = { + 2: (reply, preserve, typeMapping) => { + const double = typeMapping ? typeMapping[decoder_1.RESP_TYPES.DOUBLE] : void 0; + switch (double) { + case String: { + return reply; + } + default: { + let ret; + switch (reply.toString()) { + case "inf": + case "+inf": + ret = Infinity; + case "-inf": + ret = -Infinity; + case "nan": + ret = NaN; + default: + ret = Number(reply); + } + return ret; + } + } + }, + 3: void 0 }; - exports2.resourceGone = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 410, data, ctor: exports2.resourceGone }); + function createTransformDoubleReplyResp2Func(preserve, typeMapping) { + return (reply) => { + return exports2.transformDoubleReply[2](reply, preserve, typeMapping); + }; + } + exports2.createTransformDoubleReplyResp2Func = createTransformDoubleReplyResp2Func; + exports2.transformDoubleArrayReply = { + 2: (reply, preserve, typeMapping) => { + return reply.map(createTransformDoubleReplyResp2Func(preserve, typeMapping)); + }, + 3: void 0 }; - exports2.lengthRequired = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 411, data, ctor: exports2.lengthRequired }); - }; - exports2.preconditionFailed = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 412, data, ctor: exports2.preconditionFailed }); - }; - exports2.entityTooLarge = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 413, data, ctor: exports2.entityTooLarge }); - }; - exports2.uriTooLong = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 414, data, ctor: exports2.uriTooLong }); - }; - exports2.unsupportedMediaType = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 415, data, ctor: exports2.unsupportedMediaType }); - }; - exports2.rangeNotSatisfiable = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 416, data, ctor: exports2.rangeNotSatisfiable }); - }; - exports2.expectationFailed = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 417, data, ctor: exports2.expectationFailed }); - }; - exports2.teapot = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 418, data, ctor: exports2.teapot }); - }; - exports2.badData = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 422, data, ctor: exports2.badData }); - }; - exports2.locked = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 423, data, ctor: exports2.locked }); - }; - exports2.failedDependency = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 424, data, ctor: exports2.failedDependency }); - }; - exports2.tooEarly = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 425, data, ctor: exports2.tooEarly }); - }; - exports2.preconditionRequired = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 428, data, ctor: exports2.preconditionRequired }); - }; - exports2.tooManyRequests = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 429, data, ctor: exports2.tooManyRequests }); - }; - exports2.illegal = function(messageOrError, data) { - return new exports2.Boom(messageOrError, { statusCode: 451, data, ctor: exports2.illegal }); - }; - exports2.internal = function(message, data, statusCode = 500) { - return internals.serverError(message, data, statusCode, exports2.internal); - }; - exports2.notImplemented = function(message, data) { - return internals.serverError(message, data, 501, exports2.notImplemented); - }; - exports2.badGateway = function(message, data) { - return internals.serverError(message, data, 502, exports2.badGateway); - }; - exports2.serverUnavailable = function(message, data) { - return internals.serverError(message, data, 503, exports2.serverUnavailable); - }; - exports2.gatewayTimeout = function(message, data) { - return internals.serverError(message, data, 504, exports2.gatewayTimeout); - }; - exports2.badImplementation = function(message, data) { - const err = internals.serverError(message, data, 500, exports2.badImplementation); - err.isDeveloperError = true; - return err; - }; - internals.initialize = function(err, statusCode, message) { - const numberCode = parseInt(statusCode, 10); - Hoek.assert(!isNaN(numberCode) && numberCode >= 400, "First argument must be a number (400+):", statusCode); - err.isBoom = true; - err.isServer = numberCode >= 500; - if (!err.hasOwnProperty("data")) { - err.data = null; - } - err.output = { - statusCode: numberCode, - payload: {}, - headers: {} + function createTransformNullableDoubleReplyResp2Func(preserve, typeMapping) { + return (reply) => { + return exports2.transformNullableDoubleReply[2](reply, preserve, typeMapping); }; - Object.defineProperty(err, "reformat", { value: internals.reformat, configurable: true }); - if (!message && !err.message) { - err.reformat(); - message = err.output.payload.error; - } - if (message) { - const props = Object.getOwnPropertyDescriptor(err, "message") || Object.getOwnPropertyDescriptor(Object.getPrototypeOf(err), "message"); - Hoek.assert(!props || props.configurable && !props.get, "The error is not compatible with boom"); - err.message = message + (err.message ? ": " + err.message : ""); - err.output.payload.message = err.message; - } - err.reformat(); - return err; - }; - internals.reformat = function(debug = false) { - this.output.payload.statusCode = this.output.statusCode; - this.output.payload.error = internals.codes.get(this.output.statusCode) || "Unknown"; - if (this.output.statusCode === 500 && debug !== true) { - this.output.payload.message = "An internal server error occurred"; - } else if (this.message) { - this.output.payload.message = this.message; - } - }; - internals.serverError = function(messageOrError, data, statusCode, ctor) { - if (data instanceof Error && !data.isBoom) { - return exports2.boomify(data, { statusCode, message: messageOrError }); - } - return new exports2.Boom(messageOrError, { statusCode, data, ctor }); - }; - } -}); -var require_lru_cache = __commonJS({ - "node_modules/.deno/lru-cache@7.14.0/node_modules/lru-cache/index.js"(exports2, module14) { - var perf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date; - var hasAbortController = typeof AbortController === "function"; - var AC = hasAbortController ? AbortController : class AbortController { - constructor() { - this.signal = new AS(); - } - abort() { - this.signal.dispatchEvent("abort"); - } + } + exports2.createTransformNullableDoubleReplyResp2Func = createTransformNullableDoubleReplyResp2Func; + exports2.transformNullableDoubleReply = { + 2: (reply, preserve, typeMapping) => { + if (reply === null) + return null; + return exports2.transformDoubleReply[2](reply, preserve, typeMapping); + }, + 3: void 0 }; - var hasAbortSignal = typeof AbortSignal === "function"; - var hasACAbortSignal = typeof AC.AbortSignal === "function"; - var AS = hasAbortSignal ? AbortSignal : hasACAbortSignal ? AC.AbortController : class AbortSignal { - constructor() { - this.aborted = false; - this._listeners = []; + function transformTuplesToMap(reply, func) { + const message = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < reply.length; i2 += 2) { + message[reply[i2].toString()] = func(reply[i2 + 1]); } - dispatchEvent(type) { - if (type === "abort") { - this.aborted = true; - const e2 = { type, target: this }; - this.onabort(e2); - this._listeners.forEach((f) => f(e2), this); + return message; + } + exports2.transformTuplesToMap = transformTuplesToMap; + function createTransformTuplesReplyFunc(preserve, typeMapping) { + return (reply) => { + return transformTuplesReply(reply, preserve, typeMapping); + }; + } + exports2.createTransformTuplesReplyFunc = createTransformTuplesReplyFunc; + function transformTuplesReply(reply, preserve, typeMapping) { + const mapType = typeMapping ? typeMapping[decoder_1.RESP_TYPES.MAP] : void 0; + const inferred = reply; + switch (mapType) { + case Array: { + return reply; } - } - onabort() { - } - addEventListener(ev, fn) { - if (ev === "abort") { - this._listeners.push(fn); + case Map: { + const ret = /* @__PURE__ */ new Map(); + for (let i2 = 0; i2 < inferred.length; i2 += 2) { + ret.set(inferred[i2].toString(), inferred[i2 + 1]); + } + return ret; + ; } - } - removeEventListener(ev, fn) { - if (ev === "abort") { - this._listeners = this._listeners.filter((f) => f !== fn); + default: { + const ret = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < inferred.length; i2 += 2) { + ret[inferred[i2].toString()] = inferred[i2 + 1]; + } + return ret; + ; } } - }; - var warned = /* @__PURE__ */ new Set(); - var deprecatedOption = (opt, instead) => { - const code2 = `LRU_CACHE_OPTION_${opt}`; - if (shouldWarn(code2)) { - warn(code2, `${opt} option`, `options.${instead}`, LRUCache); + } + exports2.transformTuplesReply = transformTuplesReply; + exports2.transformSortedSetReply = { + 2: (reply, preserve, typeMapping) => { + const inferred = reply, members = []; + for (let i2 = 0; i2 < inferred.length; i2 += 2) { + members.push({ + value: inferred[i2], + score: exports2.transformDoubleReply[2](inferred[i2 + 1], preserve, typeMapping) + }); + } + return members; + }, + 3: (reply) => { + return reply.map((member) => { + const [value, score] = member; + return { + value, + score + }; + }); } }; - var deprecatedMethod = (method, instead) => { - const code2 = `LRU_CACHE_METHOD_${method}`; - if (shouldWarn(code2)) { - const { prototype } = LRUCache; - const { get: get2 } = Object.getOwnPropertyDescriptor(prototype, method); - warn(code2, `${method} method`, `cache.${instead}()`, get2); + function transformEXAT(EXAT) { + return (typeof EXAT === "number" ? EXAT : Math.floor(EXAT.getTime() / 1e3)).toString(); + } + exports2.transformEXAT = transformEXAT; + function transformPXAT(PXAT) { + return (typeof PXAT === "number" ? PXAT : PXAT.getTime()).toString(); + } + exports2.transformPXAT = transformPXAT; + function evalFirstKeyIndex(options2) { + return options2?.keys?.[0]; + } + exports2.evalFirstKeyIndex = evalFirstKeyIndex; + function pushEvalArguments(args, options2) { + if (options2?.keys) { + args.push(options2.keys.length.toString(), ...options2.keys); + } else { + args.push("0"); } - }; - var deprecatedProperty = (field, instead) => { - const code2 = `LRU_CACHE_PROPERTY_${field}`; - if (shouldWarn(code2)) { - const { prototype } = LRUCache; - const { get: get2 } = Object.getOwnPropertyDescriptor(prototype, field); - warn(code2, `${field} property`, `cache.${instead}`, get2); + if (options2?.arguments) { + args.push(...options2.arguments); } - }; - var emitWarning = (...a) => { - typeof process === "object" && process && typeof process.emitWarning === "function" ? process.emitWarning(...a) : console.error(...a); - }; - var shouldWarn = (code2) => !warned.has(code2); - var warn = (code2, what, instead, fn) => { - warned.add(code2); - const msg = `The ${what} is deprecated. Please use ${instead} instead.`; - emitWarning(msg, "DeprecationWarning", code2, fn); - }; - var isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n); - var getUintArray = (max) => !isPosInt(max) ? null : max <= Math.pow(2, 8) ? Uint8Array : max <= Math.pow(2, 16) ? Uint16Array : max <= Math.pow(2, 32) ? Uint32Array : max <= Number.MAX_SAFE_INTEGER ? ZeroArray : null; - var ZeroArray = class extends Array { - constructor(size) { - super(size); - this.fill(0); + return args; + } + exports2.pushEvalArguments = pushEvalArguments; + function pushVariadicArguments(args, value) { + if (Array.isArray(value)) { + args = args.concat(value); + } else { + args.push(value); } - }; - var Stack = class { - constructor(max) { - if (max === 0) { - return []; + return args; + } + exports2.pushVariadicArguments = pushVariadicArguments; + function pushVariadicNumberArguments(args, value) { + if (Array.isArray(value)) { + for (const item of value) { + args.push(item.toString()); } - const UintArray = getUintArray(max); - this.heap = new UintArray(max); - this.length = 0; - } - push(n) { - this.heap[this.length++] = n; + } else { + args.push(value.toString()); } - pop() { - return this.heap[--this.length]; + return args; + } + exports2.pushVariadicNumberArguments = pushVariadicNumberArguments; + function pushVariadicArgument(args, value) { + if (Array.isArray(value)) { + args.push(value.length.toString(), ...value); + } else { + args.push("1", value); } - }; - var LRUCache = class _LRUCache { - constructor(options2 = {}) { - const { - max = 0, - ttl, - ttlResolution = 1, - ttlAutopurge, - updateAgeOnGet, - updateAgeOnHas, - allowStale, - dispose, - disposeAfter, - noDisposeOnSet, - noUpdateTTL, - maxSize = 0, - maxEntrySize = 0, - sizeCalculation, - fetchMethod, - fetchContext, - noDeleteOnFetchRejection, - noDeleteOnStaleGet - } = options2; - const { length: length2, maxAge: maxAge2, stale } = options2 instanceof _LRUCache ? {} : options2; - if (max !== 0 && !isPosInt(max)) { - throw new TypeError("max option must be a nonnegative integer"); - } - const UintArray = max ? getUintArray(max) : Array; - if (!UintArray) { - throw new Error("invalid max value: " + max); - } - this.max = max; - this.maxSize = maxSize; - this.maxEntrySize = maxEntrySize || this.maxSize; - this.sizeCalculation = sizeCalculation || length2; - if (this.sizeCalculation) { - if (!this.maxSize && !this.maxEntrySize) { - throw new TypeError( - "cannot set sizeCalculation without setting maxSize or maxEntrySize" - ); - } - if (typeof this.sizeCalculation !== "function") { - throw new TypeError("sizeCalculation set to non-function"); - } - } - this.fetchMethod = fetchMethod || null; - if (this.fetchMethod && typeof this.fetchMethod !== "function") { - throw new TypeError( - "fetchMethod must be a function if specified" - ); - } - this.fetchContext = fetchContext; - if (!this.fetchMethod && fetchContext !== void 0) { - throw new TypeError( - "cannot set fetchContext without fetchMethod" - ); - } - this.keyMap = /* @__PURE__ */ new Map(); - this.keyList = new Array(max).fill(null); - this.valList = new Array(max).fill(null); - this.next = new UintArray(max); - this.prev = new UintArray(max); - this.head = 0; - this.tail = 0; - this.free = new Stack(max); - this.initialFill = 1; - this.size = 0; - if (typeof dispose === "function") { - this.dispose = dispose; - } - if (typeof disposeAfter === "function") { - this.disposeAfter = disposeAfter; - this.disposed = []; - } else { - this.disposeAfter = null; - this.disposed = null; + return args; + } + exports2.pushVariadicArgument = pushVariadicArgument; + function parseOptionalVariadicArgument(parser3, name, value) { + if (value === void 0) + return; + parser3.push(name); + parser3.pushVariadicWithLength(value); + } + exports2.parseOptionalVariadicArgument = parseOptionalVariadicArgument; + var CommandFlags; + (function(CommandFlags2) { + CommandFlags2["WRITE"] = "write"; + CommandFlags2["READONLY"] = "readonly"; + CommandFlags2["DENYOOM"] = "denyoom"; + CommandFlags2["ADMIN"] = "admin"; + CommandFlags2["PUBSUB"] = "pubsub"; + CommandFlags2["NOSCRIPT"] = "noscript"; + CommandFlags2["RANDOM"] = "random"; + CommandFlags2["SORT_FOR_SCRIPT"] = "sort_for_script"; + CommandFlags2["LOADING"] = "loading"; + CommandFlags2["STALE"] = "stale"; + CommandFlags2["SKIP_MONITOR"] = "skip_monitor"; + CommandFlags2["ASKING"] = "asking"; + CommandFlags2["FAST"] = "fast"; + CommandFlags2["MOVABLEKEYS"] = "movablekeys"; + })(CommandFlags || (exports2.CommandFlags = CommandFlags = {})); + var CommandCategories; + (function(CommandCategories2) { + CommandCategories2["KEYSPACE"] = "@keyspace"; + CommandCategories2["READ"] = "@read"; + CommandCategories2["WRITE"] = "@write"; + CommandCategories2["SET"] = "@set"; + CommandCategories2["SORTEDSET"] = "@sortedset"; + CommandCategories2["LIST"] = "@list"; + CommandCategories2["HASH"] = "@hash"; + CommandCategories2["STRING"] = "@string"; + CommandCategories2["BITMAP"] = "@bitmap"; + CommandCategories2["HYPERLOGLOG"] = "@hyperloglog"; + CommandCategories2["GEO"] = "@geo"; + CommandCategories2["STREAM"] = "@stream"; + CommandCategories2["PUBSUB"] = "@pubsub"; + CommandCategories2["ADMIN"] = "@admin"; + CommandCategories2["FAST"] = "@fast"; + CommandCategories2["SLOW"] = "@slow"; + CommandCategories2["BLOCKING"] = "@blocking"; + CommandCategories2["DANGEROUS"] = "@dangerous"; + CommandCategories2["CONNECTION"] = "@connection"; + CommandCategories2["TRANSACTION"] = "@transaction"; + CommandCategories2["SCRIPTING"] = "@scripting"; + })(CommandCategories || (exports2.CommandCategories = CommandCategories = {})); + function transformCommandReply([name, arity, flags, firstKeyIndex, lastKeyIndex, step, categories]) { + return { + name, + arity, + flags: new Set(flags), + firstKeyIndex, + lastKeyIndex, + step, + categories: new Set(categories) + }; + } + exports2.transformCommandReply = transformCommandReply; + var RedisFunctionFlags; + (function(RedisFunctionFlags2) { + RedisFunctionFlags2["NO_WRITES"] = "no-writes"; + RedisFunctionFlags2["ALLOW_OOM"] = "allow-oom"; + RedisFunctionFlags2["ALLOW_STALE"] = "allow-stale"; + RedisFunctionFlags2["NO_CLUSTER"] = "no-cluster"; + })(RedisFunctionFlags || (exports2.RedisFunctionFlags = RedisFunctionFlags = {})); + function transformFunctionListItemReply(reply) { + return { + libraryName: reply[1], + engine: reply[3], + functions: reply[5].map((fn) => ({ + name: fn[1], + description: fn[3], + flags: fn[5] + })) + }; + } + exports2.transformFunctionListItemReply = transformFunctionListItemReply; + function parseSlotRangeArguments(parser3, range) { + parser3.push(range.start.toString(), range.end.toString()); + } + function parseSlotRangesArguments(parser3, ranges) { + if (Array.isArray(ranges)) { + for (const range of ranges) { + parseSlotRangeArguments(parser3, range); } - this.noDisposeOnSet = !!noDisposeOnSet; - this.noUpdateTTL = !!noUpdateTTL; - this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection; - if (this.maxEntrySize !== 0) { - if (this.maxSize !== 0) { - if (!isPosInt(this.maxSize)) { - throw new TypeError( - "maxSize must be a positive integer if specified" - ); + } else { + parseSlotRangeArguments(parser3, ranges); + } + } + exports2.parseSlotRangesArguments = parseSlotRangesArguments; + function transformRangeReply([start, end]) { + return { + start, + end + }; + } + exports2.transformRangeReply = transformRangeReply; + function parseZKeysArguments(parser3, keys) { + if (Array.isArray(keys)) { + parser3.push(keys.length.toString()); + if (keys.length) { + if (isPlainKeys(keys)) { + parser3.pushKeys(keys); + } else { + for (let i2 = 0; i2 < keys.length; i2++) { + parser3.pushKey(keys[i2].key); + } + parser3.push("WEIGHTS"); + for (let i2 = 0; i2 < keys.length; i2++) { + parser3.push(transformDoubleArgument(keys[i2].weight)); } } - if (!isPosInt(this.maxEntrySize)) { - throw new TypeError( - "maxEntrySize must be a positive integer if specified" - ); - } - this.initializeSizeTracking(); - } - this.allowStale = !!allowStale || !!stale; - this.noDeleteOnStaleGet = !!noDeleteOnStaleGet; - this.updateAgeOnGet = !!updateAgeOnGet; - this.updateAgeOnHas = !!updateAgeOnHas; - this.ttlResolution = isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1; - this.ttlAutopurge = !!ttlAutopurge; - this.ttl = ttl || maxAge2 || 0; - if (this.ttl) { - if (!isPosInt(this.ttl)) { - throw new TypeError( - "ttl must be a positive integer if specified" - ); - } - this.initializeTTLTracking(); - } - if (this.max === 0 && this.ttl === 0 && this.maxSize === 0) { - throw new TypeError( - "At least one of max, maxSize, or ttl is required" - ); - } - if (!this.ttlAutopurge && !this.max && !this.maxSize) { - const code2 = "LRU_CACHE_UNBOUNDED"; - if (shouldWarn(code2)) { - warned.add(code2); - const msg = "TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption."; - emitWarning(msg, "UnboundedCacheWarning", code2, _LRUCache); - } - } - if (stale) { - deprecatedOption("stale", "allowStale"); } - if (maxAge2) { - deprecatedOption("maxAge", "ttl"); - } - if (length2) { - deprecatedOption("length", "sizeCalculation"); + } else { + parser3.push("1"); + if (isPlainKey(keys)) { + parser3.pushKey(keys); + } else { + parser3.pushKey(keys.key); + parser3.push("WEIGHTS", transformDoubleArgument(keys.weight)); } } - getRemainingTTL(key) { - return this.has(key, { updateAgeOnHas: false }) ? Infinity : 0; + } + exports2.parseZKeysArguments = parseZKeysArguments; + function isPlainKey(key) { + return typeof key === "string" || key instanceof Buffer; + } + function isPlainKeys(keys) { + return isPlainKey(keys[0]); + } + function parseArgs2(command2, ...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + if (parser3.preserve) { + redisArgs.preserve = parser3.preserve; } - initializeTTLTracking() { - this.ttls = new ZeroArray(this.max); - this.starts = new ZeroArray(this.max); - this.setItemTTL = (index, ttl, start = perf.now()) => { - this.starts[index] = ttl !== 0 ? start : 0; - this.ttls[index] = ttl; - if (ttl !== 0 && this.ttlAutopurge) { - const t = setTimeout(() => { - if (this.isStale(index)) { - this.delete(this.keyList[index]); - } - }, ttl + 1); - if (t.unref) { - t.unref(); - } - } - }; - this.updateItemAge = (index) => { - this.starts[index] = this.ttls[index] !== 0 ? perf.now() : 0; - }; - let cachedNow = 0; - const getNow = () => { - const n = perf.now(); - if (this.ttlResolution > 0) { - cachedNow = n; - const t = setTimeout( - () => cachedNow = 0, - this.ttlResolution - ); - if (t.unref) { - t.unref(); - } - } - return n; - }; - this.getRemainingTTL = (key) => { - const index = this.keyMap.get(key); - if (index === void 0) { - return 0; - } - return this.ttls[index] === 0 || this.starts[index] === 0 ? Infinity : this.starts[index] + this.ttls[index] - (cachedNow || getNow()); - }; - this.isStale = (index) => { - return this.ttls[index] !== 0 && this.starts[index] !== 0 && (cachedNow || getNow()) - this.starts[index] > this.ttls[index]; - }; - } - updateItemAge(index) { - } - setItemTTL(index, ttl, start) { - } - isStale(index) { - return false; - } - initializeSizeTracking() { - this.calculatedSize = 0; - this.sizes = new ZeroArray(this.max); - this.removeItemSize = (index) => { - this.calculatedSize -= this.sizes[index]; - this.sizes[index] = 0; - }; - this.requireSize = (k, v2, size, sizeCalculation) => { - if (!isPosInt(size)) { - if (sizeCalculation) { - if (typeof sizeCalculation !== "function") { - throw new TypeError("sizeCalculation must be a function"); - } - size = sizeCalculation(v2, k); - if (!isPosInt(size)) { - throw new TypeError( - "sizeCalculation return invalid (expect positive integer)" - ); + return redisArgs; + } + exports2.parseArgs = parseArgs2; + function transformStreamMessageReply(typeMapping, reply) { + const [id, message] = reply; + return { + id, + message: transformTuplesReply(message, void 0, typeMapping) + }; + } + exports2.transformStreamMessageReply = transformStreamMessageReply; + function transformStreamMessageNullReply(typeMapping, reply) { + return isNullReply(reply) ? reply : transformStreamMessageReply(typeMapping, reply); + } + exports2.transformStreamMessageNullReply = transformStreamMessageNullReply; + function transformStreamMessagesReply(r, typeMapping) { + const reply = r; + return reply.map(transformStreamMessageReply.bind(void 0, typeMapping)); + } + exports2.transformStreamMessagesReply = transformStreamMessagesReply; + function transformStreamsMessagesReplyResp2(reply, preserve, typeMapping) { + if (reply === null) + return null; + switch (typeMapping ? typeMapping[decoder_1.RESP_TYPES.MAP] : void 0) { + /* FUTURE: a response type for when resp3 is working properly + case Map: { + const ret = new Map(); + + for (let i=0; i < reply.length; i++) { + const stream = reply[i] as unknown as UnwrapReply; + + const name = stream[0]; + const rawMessages = stream[1]; + + ret.set(name.toString(), transformStreamMessagesReply(rawMessages, typeMapping)); } - } else { - throw new TypeError( - "invalid size value (must be positive integer)" - ); - } - } - return size; - }; - this.addItemSize = (index, size) => { - this.sizes[index] = size; - const maxSize = this.maxSize - this.sizes[index]; - while (this.calculatedSize > maxSize) { - this.evict(true); - } - this.calculatedSize += this.sizes[index]; - }; - } - removeItemSize(index) { - } - addItemSize(index, size) { - } - requireSize(k, v2, size, sizeCalculation) { - if (size || sizeCalculation) { - throw new TypeError( - "cannot set size without setting maxSize or maxEntrySize on cache" - ); - } - } - *indexes({ allowStale = this.allowStale } = {}) { - if (this.size) { - for (let i2 = this.tail; true; ) { - if (!this.isValidIndex(i2)) { - break; + + return ret as unknown as MapReply; } - if (allowStale || !this.isStale(i2)) { - yield i2; + case Array: { + const ret: Array = []; + + for (let i=0; i < reply.length; i++) { + const stream = reply[i] as unknown as UnwrapReply; + + const name = stream[0]; + const rawMessages = stream[1]; + + ret.push(name); + ret.push(transformStreamMessagesReply(rawMessages, typeMapping)); + } + + return ret as unknown as MapReply; } - if (i2 === this.head) { - break; - } else { - i2 = this.prev[i2]; + default: { + const ret: Record = Object.create(null); + + for (let i=0; i < reply.length; i++) { + const stream = reply[i] as unknown as UnwrapReply; + + const name = stream[0] as unknown as UnwrapReply; + const rawMessages = stream[1]; + + ret[name.toString()] = transformStreamMessagesReply(rawMessages); + } + + return ret as unknown as MapReply; } + */ + // V4 compatible response type + default: { + const ret = []; + for (let i2 = 0; i2 < reply.length; i2++) { + const stream = reply[i2]; + ret.push({ + name: stream[0], + messages: transformStreamMessagesReply(stream[1]) + }); } + return ret; } } - *rindexes({ allowStale = this.allowStale } = {}) { - if (this.size) { - for (let i2 = this.head; true; ) { - if (!this.isValidIndex(i2)) { - break; - } - if (allowStale || !this.isStale(i2)) { - yield i2; - } - if (i2 === this.tail) { - break; - } else { - i2 = this.next[i2]; - } - } + } + exports2.transformStreamsMessagesReplyResp2 = transformStreamsMessagesReplyResp2; + function transformStreamsMessagesReplyResp3(reply) { + if (reply === null) + return null; + if (reply instanceof Map) { + const ret = /* @__PURE__ */ new Map(); + for (const [n, rawMessages] of reply) { + const name = n; + ret.set(name.toString(), transformStreamMessagesReply(rawMessages)); } - } - isValidIndex(index) { - return this.keyMap.get(this.keyList[index]) === index; - } - *entries() { - for (const i2 of this.indexes()) { - yield [this.keyList[i2], this.valList[i2]]; + return ret; + } else if (reply instanceof Array) { + const ret = []; + for (let i2 = 0; i2 < reply.length; i2 += 2) { + const name = reply[i2]; + const rawMessages = reply[i2 + 1]; + ret.push(name); + ret.push(transformStreamMessagesReply(rawMessages)); } - } - *rentries() { - for (const i2 of this.rindexes()) { - yield [this.keyList[i2], this.valList[i2]]; + return ret; + } else { + const ret = /* @__PURE__ */ Object.create(null); + for (const [name, rawMessages] of Object.entries(reply)) { + ret[name] = transformStreamMessagesReply(rawMessages); } + return ret; } - *keys() { - for (const i2 of this.indexes()) { - yield this.keyList[i2]; + } + exports2.transformStreamsMessagesReplyResp3 = transformStreamsMessagesReplyResp3; + function transformRedisJsonArgument(json) { + return JSON.stringify(json); + } + exports2.transformRedisJsonArgument = transformRedisJsonArgument; + function transformRedisJsonReply(json) { + const res = JSON.parse(json.toString()); + return res; + } + exports2.transformRedisJsonReply = transformRedisJsonReply; + function transformRedisJsonNullReply(json) { + return isNullReply(json) ? json : transformRedisJsonReply(json); + } + exports2.transformRedisJsonNullReply = transformRedisJsonNullReply; + } +}); +var require_ACL_LOG = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LOG.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns ACL security events log entries + * @param parser - The Redis command parser + * @param count - Optional maximum number of entries to return + */ + parseCommand(parser3, count) { + parser3.push("ACL", "LOG"); + if (count != void 0) { + parser3.push(count.toString()); } + }, + transformReply: { + 2: (reply, preserve, typeMapping) => { + return reply.map((item) => { + const inferred = item; + return { + count: inferred[1], + reason: inferred[3], + context: inferred[5], + object: inferred[7], + username: inferred[9], + "age-seconds": generic_transformers_1.transformDoubleReply[2](inferred[11], preserve, typeMapping), + "client-info": inferred[13], + "entry-id": inferred[15], + "timestamp-created": inferred[17], + "timestamp-last-updated": inferred[19] + }; + }); + }, + 3: void 0 } - *rkeys() { - for (const i2 of this.rindexes()) { - yield this.keyList[i2]; + }; + } +}); +var require_ACL_LOG_RESET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LOG_RESET.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ACL_LOG_1 = __importDefault(require_ACL_LOG()); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: ACL_LOG_1.default.IS_READ_ONLY, + /** + * Clears the ACL security events log + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("ACL", "LOG", "RESET"); + }, + transformReply: void 0 + }; + } +}); +var require_ACL_SAVE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_SAVE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Saves the current ACL configuration to the ACL file + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("ACL", "SAVE"); + }, + transformReply: void 0 + }; + } +}); +var require_ACL_SETUSER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_SETUSER.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Creates or modifies ACL user with specified rules + * @param parser - The Redis command parser + * @param username - Username to create or modify + * @param rule - ACL rule(s) to apply to the user + */ + parseCommand(parser3, username, rule) { + parser3.push("ACL", "SETUSER", username); + parser3.pushVariadic(rule); + }, + transformReply: void 0 + }; + } +}); +var require_ACL_USERS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_USERS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns a list of all configured ACL usernames + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("ACL", "USERS"); + }, + transformReply: void 0 + }; + } +}); +var require_ACL_WHOAMI = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_WHOAMI.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the username of the current connection + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("ACL", "WHOAMI"); + }, + transformReply: void 0 + }; + } +}); +var require_APPEND = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/APPEND.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Appends a value to a string key + * @param parser - The Redis command parser + * @param key - The key to append to + * @param value - The value to append + */ + parseCommand(parser3, key, value) { + parser3.push("APPEND", key, value); + }, + transformReply: void 0 + }; + } +}); +var require_ASKING = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ASKING.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.ASKING_CMD = void 0; + exports2.ASKING_CMD = "ASKING"; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Tells a Redis cluster node that the client is ok receiving such redirects + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push(exports2.ASKING_CMD); + }, + transformReply: void 0 + }; + } +}); +var require_AUTH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/AUTH.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Authenticates the connection using a password or username and password + * @param parser - The Redis command parser + * @param options - Authentication options containing username and/or password + * @param options.username - Optional username for authentication + * @param options.password - Password for authentication + */ + parseCommand(parser3, { username, password }) { + parser3.push("AUTH"); + if (username !== void 0) { + parser3.push(username); } - } - *values() { - for (const i2 of this.indexes()) { - yield this.valList[i2]; + parser3.push(password); + }, + transformReply: void 0 + }; + } +}); +var require_BGREWRITEAOF = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BGREWRITEAOF.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Asynchronously rewrites the append-only file + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("BGREWRITEAOF"); + }, + transformReply: void 0 + }; + } +}); +var require_BGSAVE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BGSAVE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Asynchronously saves the dataset to disk + * @param parser - The Redis command parser + * @param options - Optional configuration + * @param options.SCHEDULE - Schedule a BGSAVE operation when no BGSAVE is already in progress + */ + parseCommand(parser3, options2) { + parser3.push("BGSAVE"); + if (options2?.SCHEDULE) { + parser3.push("SCHEDULE"); } - } - *rvalues() { - for (const i2 of this.rindexes()) { - yield this.valList[i2]; + }, + transformReply: void 0 + }; + } +}); +var require_BITCOUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITCOUNT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, + /** + * Returns the count of set bits in a string key + * @param parser - The Redis command parser + * @param key - The key to count bits in + * @param range - Optional range specification + * @param range.start - Start offset in bytes/bits + * @param range.end - End offset in bytes/bits + * @param range.mode - Optional counting mode: BYTE or BIT + */ + parseCommand(parser3, key, range) { + parser3.push("BITCOUNT"); + parser3.pushKey(key); + if (range) { + parser3.push(range.start.toString()); + parser3.push(range.end.toString()); + if (range.mode) { + parser3.push(range.mode); + } } - } - [Symbol.iterator]() { - return this.entries(); - } - find(fn, getOptions = {}) { - for (const i2 of this.indexes()) { - if (fn(this.valList[i2], this.keyList[i2], this)) { - return this.get(this.keyList[i2], getOptions); + }, + transformReply: void 0 + }; + } +}); +var require_BITFIELD_RO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITFIELD_RO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, + /** + * Performs read-only bitfield integer operations on strings + * @param parser - The Redis command parser + * @param key - The key holding the string + * @param operations - Array of GET operations to perform on the bitfield + */ + parseCommand(parser3, key, operations) { + parser3.push("BITFIELD_RO"); + parser3.pushKey(key); + for (const operation of operations) { + parser3.push("GET"); + parser3.push(operation.encoding); + parser3.push(operation.offset.toString()); + } + }, + transformReply: void 0 + }; + } +}); +var require_BITFIELD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITFIELD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Performs arbitrary bitfield integer operations on strings + * @param parser - The Redis command parser + * @param key - The key holding the string + * @param operations - Array of bitfield operations to perform: GET, SET, INCRBY or OVERFLOW + */ + parseCommand(parser3, key, operations) { + parser3.push("BITFIELD"); + parser3.pushKey(key); + for (const options2 of operations) { + switch (options2.operation) { + case "GET": + parser3.push("GET", options2.encoding, options2.offset.toString()); + break; + case "SET": + parser3.push("SET", options2.encoding, options2.offset.toString(), options2.value.toString()); + break; + case "INCRBY": + parser3.push("INCRBY", options2.encoding, options2.offset.toString(), options2.increment.toString()); + break; + case "OVERFLOW": + parser3.push("OVERFLOW", options2.behavior); + break; } } - } - forEach(fn, thisp = this) { - for (const i2 of this.indexes()) { - fn.call(thisp, this.valList[i2], this.keyList[i2], this); + }, + transformReply: void 0 + }; + } +}); +var require_BITOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITOP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Performs bitwise operations between strings + * @param parser - The Redis command parser + * @param operation - Bitwise operation to perform: AND, OR, XOR, NOT, DIFF, DIFF1, ANDOR, ONE + * @param destKey - Destination key to store the result + * @param key - Source key(s) to perform operation on + */ + parseCommand(parser3, operation, destKey, key) { + parser3.push("BITOP", operation); + parser3.pushKey(destKey); + parser3.pushKeys(key); + }, + transformReply: void 0 + }; + } +}); +var require_BITPOS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITPOS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, + /** + * Returns the position of first bit set to 0 or 1 in a string + * @param parser - The Redis command parser + * @param key - The key holding the string + * @param bit - The bit value to look for (0 or 1) + * @param start - Optional starting position in bytes/bits + * @param end - Optional ending position in bytes/bits + * @param mode - Optional counting mode: BYTE or BIT + */ + parseCommand(parser3, key, bit, start, end, mode) { + parser3.push("BITPOS"); + parser3.pushKey(key); + parser3.push(bit.toString()); + if (start !== void 0) { + parser3.push(start.toString()); } - } - rforEach(fn, thisp = this) { - for (const i2 of this.rindexes()) { - fn.call(thisp, this.valList[i2], this.keyList[i2], this); + if (end !== void 0) { + parser3.push(end.toString()); } - } - get prune() { - deprecatedMethod("prune", "purgeStale"); - return this.purgeStale; - } - purgeStale() { - let deleted = false; - for (const i2 of this.rindexes({ allowStale: true })) { - if (this.isStale(i2)) { - this.delete(this.keyList[i2]); - deleted = true; - } + if (mode) { + parser3.push(mode); } - return deleted; + }, + transformReply: void 0 + }; + } +}); +var require_BLMOVE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BLMOVE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Pop an element from a list, push it to another list and return it; or block until one is available + * @param parser - The Redis command parser + * @param source - Key of the source list + * @param destination - Key of the destination list + * @param sourceSide - Side of source list to pop from (LEFT or RIGHT) + * @param destinationSide - Side of destination list to push to (LEFT or RIGHT) + * @param timeout - Timeout in seconds, 0 to block indefinitely + */ + parseCommand(parser3, source, destination, sourceSide, destinationSide, timeout) { + parser3.push("BLMOVE"); + parser3.pushKeys([source, destination]); + parser3.push(sourceSide, destinationSide, timeout.toString()); + }, + transformReply: void 0 + }; + } +}); +var require_LMPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LMPOP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseLMPopArguments = void 0; + function parseLMPopArguments(parser3, keys, side, options2) { + parser3.pushKeysLength(keys); + parser3.push(side); + if (options2?.COUNT !== void 0) { + parser3.push("COUNT", options2.COUNT.toString()); } - dump() { - const arr = []; - for (const i2 of this.indexes({ allowStale: true })) { - const key = this.keyList[i2]; - const v2 = this.valList[i2]; - const value = this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; - const entry = { value }; - if (this.ttls) { - entry.ttl = this.ttls[i2]; - const age = perf.now() - this.starts[i2]; - entry.start = Math.floor(Date.now() - age); - } - if (this.sizes) { - entry.size = this.sizes[i2]; - } - arr.unshift([key, entry]); - } - return arr; + } + exports2.parseLMPopArguments = parseLMPopArguments; + exports2.default = { + IS_READ_ONLY: false, + /** + * Constructs the LMPOP command + * + * @param parser - The command parser + * @param args - Arguments including keys, side (LEFT or RIGHT), and options + * @see https://redis.io/commands/lmpop/ + */ + parseCommand(parser3, ...args) { + parser3.push("LMPOP"); + parseLMPopArguments(parser3, ...args); + }, + transformReply: void 0 + }; + } +}); +var require_BLMPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BLMPOP.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - load(arr) { - this.clear(); - for (const [key, entry] of arr) { - if (entry.start) { - const age = Date.now() - entry.start; - entry.start = perf.now() - age; - } - this.set(key, entry.value, entry); - } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - dispose(v2, k, reason) { + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var LMPOP_1 = __importStar(require_LMPOP()); + exports2.default = { + IS_READ_ONLY: false, + /** + * Pops elements from multiple lists; blocks until elements are available + * @param parser - The Redis command parser + * @param timeout - Timeout in seconds, 0 to block indefinitely + * @param args - Additional arguments for LMPOP command + */ + parseCommand(parser3, timeout, ...args) { + parser3.push("BLMPOP", timeout.toString()); + (0, LMPOP_1.parseLMPopArguments)(parser3, ...args); + }, + transformReply: LMPOP_1.default.transformReply + }; + } +}); +var require_BLPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BLPOP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Removes and returns the first element in a list, or blocks until one is available + * @param parser - The Redis command parser + * @param key - Key of the list to pop from, or array of keys to try sequentially + * @param timeout - Maximum seconds to block, 0 to block indefinitely + */ + parseCommand(parser3, key, timeout) { + parser3.push("BLPOP"); + parser3.pushKeys(key); + parser3.push(timeout.toString()); + }, + transformReply(reply) { + if (reply === null) + return null; + return { + key: reply[0], + element: reply[1] + }; } - set(k, v2, { - ttl = this.ttl, - start, - noDisposeOnSet = this.noDisposeOnSet, - size = 0, - sizeCalculation = this.sizeCalculation, - noUpdateTTL = this.noUpdateTTL - } = {}) { - size = this.requireSize(k, v2, size, sizeCalculation); - if (this.maxEntrySize && size > this.maxEntrySize) { - return this; - } - let index = this.size === 0 ? void 0 : this.keyMap.get(k); - if (index === void 0) { - index = this.newIndex(); - this.keyList[index] = k; - this.valList[index] = v2; - this.keyMap.set(k, index); - this.next[this.tail] = index; - this.prev[index] = this.tail; - this.tail = index; - this.size++; - this.addItemSize(index, size); - noUpdateTTL = false; - } else { - const oldVal = this.valList[index]; - if (v2 !== oldVal) { - if (this.isBackgroundFetch(oldVal)) { - oldVal.__abortController.abort(); - } else { - if (!noDisposeOnSet) { - this.dispose(oldVal, k, "set"); - if (this.disposeAfter) { - this.disposed.push([oldVal, k, "set"]); - } - } - } - this.removeItemSize(index); - this.valList[index] = v2; - this.addItemSize(index, size); - } - this.moveToTail(index); - } - if (ttl !== 0 && this.ttl === 0 && !this.ttls) { - this.initializeTTLTracking(); - } - if (!noUpdateTTL) { - this.setItemTTL(index, ttl, start); - } - if (this.disposeAfter) { - while (this.disposed.length) { - this.disposeAfter(...this.disposed.shift()); - } - } - return this; + }; + } +}); +var require_BRPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BRPOP.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var BLPOP_1 = __importDefault(require_BLPOP()); + exports2.default = { + IS_READ_ONLY: true, + /** + * Removes and returns the last element in a list, or blocks until one is available + * @param parser - The Redis command parser + * @param key - Key of the list to pop from, or array of keys to try sequentially + * @param timeout - Maximum seconds to block, 0 to block indefinitely + */ + parseCommand(parser3, key, timeout) { + parser3.push("BRPOP"); + parser3.pushKeys(key); + parser3.push(timeout.toString()); + }, + transformReply: BLPOP_1.default.transformReply + }; + } +}); +var require_BRPOPLPUSH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BRPOPLPUSH.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Pops an element from a list, pushes it to another list and returns it; blocks until element is available + * @param parser - The Redis command parser + * @param source - Key of the source list to pop from + * @param destination - Key of the destination list to push to + * @param timeout - Maximum seconds to block, 0 to block indefinitely + */ + parseCommand(parser3, source, destination, timeout) { + parser3.push("BRPOPLPUSH"); + parser3.pushKeys([source, destination]); + parser3.push(timeout.toString()); + }, + transformReply: void 0 + }; + } +}); +var require_ZMPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZMPOP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseZMPopArguments = void 0; + var generic_transformers_1 = require_generic_transformers(); + function parseZMPopArguments(parser3, keys, side, options2) { + parser3.pushKeysLength(keys); + parser3.push(side); + if (options2?.COUNT) { + parser3.push("COUNT", options2.COUNT.toString()); } - newIndex() { - if (this.size === 0) { - return this.tail; - } - if (this.size === this.max && this.max !== 0) { - return this.evict(false); - } - if (this.free.length !== 0) { - return this.free.pop(); + } + exports2.parseZMPopArguments = parseZMPopArguments; + exports2.default = { + IS_READ_ONLY: false, + /** + * Removes and returns up to count members with the highest/lowest scores from the first non-empty sorted set. + * @param parser - The Redis command parser. + * @param keys - Keys of the sorted sets to pop from. + * @param side - Side to pop from (MIN or MAX). + * @param options - Optional parameters including COUNT. + */ + parseCommand(parser3, keys, side, options2) { + parser3.push("ZMPOP"); + parseZMPopArguments(parser3, keys, side, options2); + }, + transformReply: { + 2(reply, preserve, typeMapping) { + return reply === null ? null : { + key: reply[0], + members: reply[1].map((member) => { + const [value, score] = member; + return { + value, + score: generic_transformers_1.transformDoubleReply[2](score, preserve, typeMapping) + }; + }) + }; + }, + 3(reply) { + return reply === null ? null : { + key: reply[0], + members: generic_transformers_1.transformSortedSetReply[3](reply[1]) + }; } - return this.initialFill++; } - pop() { - if (this.size) { - const val = this.valList[this.head]; - this.evict(true); - return val; - } + }; + } +}); +var require_BZMPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BZMPOP.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - evict(free) { - const head = this.head; - const k = this.keyList[head]; - const v2 = this.valList[head]; - if (this.isBackgroundFetch(v2)) { - v2.__abortController.abort(); - } else { - this.dispose(v2, k, "evict"); - if (this.disposeAfter) { - this.disposed.push([v2, k, "evict"]); - } - } - this.removeItemSize(head); - if (free) { - this.keyList[head] = null; - this.valList[head] = null; - this.free.push(head); - } - this.head = this.next[head]; - this.keyMap.delete(k); - this.size--; - return head; - } - has(k, { updateAgeOnHas = this.updateAgeOnHas } = {}) { - const index = this.keyMap.get(k); - if (index !== void 0) { - if (!this.isStale(index)) { - if (updateAgeOnHas) { - this.updateItemAge(index); - } - return true; - } - } - return false; - } - // like get(), but without any LRU updating or TTL expiration - peek(k, { allowStale = this.allowStale } = {}) { - const index = this.keyMap.get(k); - if (index !== void 0 && (allowStale || !this.isStale(index))) { - const v2 = this.valList[index]; - return this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; - } - } - backgroundFetch(k, index, options2, context) { - const v2 = index === void 0 ? void 0 : this.valList[index]; - if (this.isBackgroundFetch(v2)) { - return v2; - } - const ac = new AC(); - const fetchOpts = { - signal: ac.signal, - options: options2, - context - }; - const cb = (v3) => { - if (!ac.signal.aborted) { - this.set(k, v3, fetchOpts.options); - } - return v3; - }; - const eb = (er) => { - if (this.valList[index] === p) { - const del = !options2.noDeleteOnFetchRejection || p.__staleWhileFetching === void 0; - if (del) { - this.delete(k); - } else { - this.valList[index] = p.__staleWhileFetching; - } - } - if (p.__returned === p) { - throw er; - } - }; - const pcall = (res) => res(this.fetchMethod(k, v2, fetchOpts)); - const p = new Promise(pcall).then(cb, eb); - p.__abortController = ac; - p.__staleWhileFetching = v2; - p.__returned = null; - if (index === void 0) { - this.set(k, p, fetchOpts.options); - index = this.keyMap.get(k); - } else { - this.valList[index] = p; - } - return p; - } - isBackgroundFetch(p) { - return p && typeof p === "object" && typeof p.then === "function" && Object.prototype.hasOwnProperty.call( - p, - "__staleWhileFetching" - ) && Object.prototype.hasOwnProperty.call(p, "__returned") && (p.__returned === p || p.__returned === null); - } - // this takes the union of get() and set() opts, because it does both - async fetch(k, { - // get options - allowStale = this.allowStale, - updateAgeOnGet = this.updateAgeOnGet, - noDeleteOnStaleGet = this.noDeleteOnStaleGet, - // set options - ttl = this.ttl, - noDisposeOnSet = this.noDisposeOnSet, - size = 0, - sizeCalculation = this.sizeCalculation, - noUpdateTTL = this.noUpdateTTL, - // fetch exclusive options - noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, - fetchContext = this.fetchContext, - forceRefresh = false - } = {}) { - if (!this.fetchMethod) { - return this.get(k, { - allowStale, - updateAgeOnGet, - noDeleteOnStaleGet - }); - } - const options2 = { - allowStale, - updateAgeOnGet, - noDeleteOnStaleGet, - ttl, - noDisposeOnSet, - size, - sizeCalculation, - noUpdateTTL, - noDeleteOnFetchRejection - }; - let index = this.keyMap.get(k); - if (index === void 0) { - const p = this.backgroundFetch(k, index, options2, fetchContext); - return p.__returned = p; - } else { - const v2 = this.valList[index]; - if (this.isBackgroundFetch(v2)) { - return allowStale && v2.__staleWhileFetching !== void 0 ? v2.__staleWhileFetching : v2.__returned = v2; - } - if (!forceRefresh && !this.isStale(index)) { - this.moveToTail(index); - if (updateAgeOnGet) { - this.updateItemAge(index); - } - return v2; - } - const p = this.backgroundFetch(k, index, options2, fetchContext); - return allowStale && p.__staleWhileFetching !== void 0 ? p.__staleWhileFetching : p.__returned = p; - } - } - get(k, { - allowStale = this.allowStale, - updateAgeOnGet = this.updateAgeOnGet, - noDeleteOnStaleGet = this.noDeleteOnStaleGet - } = {}) { - const index = this.keyMap.get(k); - if (index !== void 0) { - const value = this.valList[index]; - const fetching = this.isBackgroundFetch(value); - if (this.isStale(index)) { - if (!fetching) { - if (!noDeleteOnStaleGet) { - this.delete(k); - } - return allowStale ? value : void 0; - } else { - return allowStale ? value.__staleWhileFetching : void 0; - } - } else { - if (fetching) { - return void 0; - } - this.moveToTail(index); - if (updateAgeOnGet) { - this.updateItemAge(index); - } - return value; - } - } - } - connect(p, n) { - this.prev[n] = p; - this.next[p] = n; - } - moveToTail(index) { - if (index !== this.tail) { - if (index === this.head) { - this.head = this.next[index]; - } else { - this.connect(this.prev[index], this.next[index]); - } - this.connect(this.tail, index); - this.tail = index; - } - } - get del() { - deprecatedMethod("del", "delete"); - return this.delete; - } - delete(k) { - let deleted = false; - if (this.size !== 0) { - const index = this.keyMap.get(k); - if (index !== void 0) { - deleted = true; - if (this.size === 1) { - this.clear(); - } else { - this.removeItemSize(index); - const v2 = this.valList[index]; - if (this.isBackgroundFetch(v2)) { - v2.__abortController.abort(); - } else { - this.dispose(v2, k, "delete"); - if (this.disposeAfter) { - this.disposed.push([v2, k, "delete"]); - } - } - this.keyMap.delete(k); - this.keyList[index] = null; - this.valList[index] = null; - if (index === this.tail) { - this.tail = this.prev[index]; - } else if (index === this.head) { - this.head = this.next[index]; - } else { - this.next[this.prev[index]] = this.next[index]; - this.prev[this.next[index]] = this.prev[index]; - } - this.size--; - this.free.push(index); - } - } - } - if (this.disposed) { - while (this.disposed.length) { - this.disposeAfter(...this.disposed.shift()); - } - } - return deleted; - } - clear() { - for (const index of this.rindexes({ allowStale: true })) { - const v2 = this.valList[index]; - if (this.isBackgroundFetch(v2)) { - v2.__abortController.abort(); - } else { - const k = this.keyList[index]; - this.dispose(v2, k, "delete"); - if (this.disposeAfter) { - this.disposed.push([v2, k, "delete"]); - } - } - } - this.keyMap.clear(); - this.valList.fill(null); - this.keyList.fill(null); - if (this.ttls) { - this.ttls.fill(0); - this.starts.fill(0); - } - if (this.sizes) { - this.sizes.fill(0); - } - this.head = 0; - this.tail = 0; - this.initialFill = 1; - this.free.length = 0; - this.calculatedSize = 0; - this.size = 0; - if (this.disposed) { - while (this.disposed.length) { - this.disposeAfter(...this.disposed.shift()); - } - } - } - get reset() { - deprecatedMethod("reset", "clear"); - return this.clear; - } - get length() { - deprecatedProperty("length", "size"); - return this.size; - } - static get AbortController() { - return AC; - } - static get AbortSignal() { - return AS; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ZMPOP_1 = __importStar(require_ZMPOP()); + exports2.default = { + IS_READ_ONLY: false, + /** + * Removes and returns members from one or more sorted sets in the specified order; blocks until elements are available + * @param parser - The Redis command parser + * @param timeout - Maximum seconds to block, 0 to block indefinitely + * @param args - Additional arguments specifying the keys, min/max count, and order (MIN/MAX) + */ + parseCommand(parser3, timeout, ...args) { + parser3.push("BZMPOP", timeout.toString()); + (0, ZMPOP_1.parseZMPopArguments)(parser3, ...args); + }, + transformReply: ZMPOP_1.default.transformReply }; - module14.exports = LRUCache; - } -}); -var SERVER_EXITING; -var SERVER_RUNNING; -var init_events2 = __esm({ - "src/serve/events.ts"() { - "use strict"; - SERVER_EXITING = "server-exiting"; - SERVER_RUNNING = "server-running"; } }); -var import_npm_nconf; -var vapidPublicKey; -var vapidPrivateKey; -var vapid; -var initVapid; -var generateJwt; -var getVapidPublicKey; -var vapidAuthorization; -var init_vapid = __esm({ - "src/serve/vapid.ts"() { +var require_BZPOPMAX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BZPOPMAX.js"(exports2) { "use strict"; - init_esm(); - import_npm_nconf = __toESM(require_nconf()); - initVapid = async () => { - const vapidEmail = import_npm_nconf.default.get("server:vapid:email"); - if (!vapidEmail) { - console.warn('Missing VAPID identification. Please set `server:vapid:email` to a value like "some@domain.example".'); - } - vapid = { VAPID_EMAIL: vapidEmail?.replace(/^mailto:/i, "") || "test@example.com" }; - const vapidKeyPair = await esm_default("chelonia.db/get", "_private_immutable_vapid_key").then(async (vapidKeyPair2) => { - if (!vapidKeyPair2) { - console.info("Generating new VAPID keypair..."); - const keyPair = await crypto.subtle.generateKey( - { - name: "ECDSA", - namedCurve: "P-256" - // Use P-256 curve - }, - true, - // Whether the key is extractable - ["sign", "verify"] - // Usages - ); - const serializedKeyPair2 = await Promise.all([ - crypto.subtle.exportKey("jwk", keyPair.privateKey), - crypto.subtle.exportKey("raw", keyPair.publicKey).then( - (key) => Buffer7.from(key).toString("base64url") - ) - ]); - return esm_default("chelonia.db/set", "_private_immutable_vapid_key", JSON.stringify(serializedKeyPair2)).then(() => { - console.info("Successfully saved newly generated VAPID keys"); - return [keyPair.privateKey, serializedKeyPair2[1]]; - }); + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Removes and returns the member with the highest score in a sorted set, or blocks until one is available + * @param parser - The Redis command parser + * @param keys - Key of the sorted set, or array of keys to try sequentially + * @param timeout - Maximum seconds to block, 0 to block indefinitely + */ + parseCommand(parser3, keys, timeout) { + parser3.push("BZPOPMAX"); + parser3.pushKeys(keys); + parser3.push(timeout.toString()); + }, + transformReply: { + 2(reply, preserve, typeMapping) { + return reply === null ? null : { + key: reply[0], + value: reply[1], + score: generic_transformers_1.transformDoubleReply[2](reply[2], preserve, typeMapping) + }; + }, + 3(reply) { + return reply === null ? null : { + key: reply[0], + value: reply[1], + score: reply[2] + }; } - const serializedKeyPair = JSON.parse(vapidKeyPair2); - return [ - await crypto.subtle.importKey( - "jwk", - serializedKeyPair[0], - { name: "ECDSA", namedCurve: "P-256" }, - false, - ["sign"] - ), - serializedKeyPair[1] - ]; - }); - vapidPrivateKey = vapidKeyPair[0]; - vapidPublicKey = vapidKeyPair[1]; - }; - generateJwt = async (endpoint) => { - const now = Date.now() / 1e3 | 0; - const audience = endpoint.origin; - const header = Buffer7.from(JSON.stringify( - Object.fromEntries([["typ", "JWT"], ["alg", "ES256"]]) - )).toString("base64url"); - const body = Buffer7.from(JSON.stringify( - // We're expecting to use the JWT immediately. We set a 10-minute window - // for using the JWT (5 minutes into the past, 5 minutes into the future) - // to account for potential network delays and clock drift. - Object.fromEntries([ - // token audience - ["aud", audience], - // 'expiry' / 'not after' value for the token - ["exp", now + 300], - // (optional) issuance time for the token - ["iat", now], - // 'not before' value for the JWT - ["nbf", now - 300], - // URI used for identifying ourselves. This can be used by the push - // provider to get in touch in case of issues. - ["sub", `mailto:${vapid.VAPID_EMAIL}`] - ]) - )).toString("base64url"); - const signature = Buffer7.from( - await crypto.subtle.sign( - { name: "ECDSA", hash: "SHA-256" }, - vapidPrivateKey, - Buffer7.from([header, body].join(".")) - ) - ).toString("base64url"); - return [header, body, signature].join("."); - }; - getVapidPublicKey = () => vapidPublicKey; - vapidAuthorization = async (endpoint) => { - const jwt = await generateJwt(endpoint); - return `vapid t=${jwt}, k=${vapidPublicKey}`; - }; - } -}); -var AUTHSALT; -var CONTRACTSALT; -var CS; -var SU; -var SALT_LENGTH_IN_OCTETS; -var init_zkppConstants = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/zkppConstants.mjs"() { - AUTHSALT = "AUTHSALT"; - CONTRACTSALT = "CONTRACTSALT"; - CS = "CS"; - SU = "SU"; - SALT_LENGTH_IN_OCTETS = 24; - } -}); -var import_scrypt_async2; -var import_tweetnacl2; -var base64ToBase64url; -var base64urlToBase64; -var hashStringArray; -var hashRawStringArray; -var randomNonce; -var hash2; -var computeCAndHc; -var encryptContractSalt; -var encryptSaltUpdate; -var decryptSaltUpdate; -var boxKeyPair; -var saltAgreement; -var parseRegisterSalt; -var init_zkpp = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/zkpp.mjs"() { - import_scrypt_async2 = __toESM(require_scrypt_async(), 1); - import_tweetnacl2 = __toESM(require_nacl_fast(), 1); - init_zkppConstants(); - base64ToBase64url = (s) => s.replace(/\//g, "_").replace(/\+/g, "-").replace(/=*$/, ""); - base64urlToBase64 = (s) => s.replace(/_/g, "/").replace(/-/g, "+") + "=".repeat((4 - s.length % 4) % 4); - hashStringArray = (...args) => { - return import_tweetnacl2.default.hash(Buffer8.concat(args.map((s) => import_tweetnacl2.default.hash(Buffer8.from(s))))); - }; - hashRawStringArray = (...args) => { - return import_tweetnacl2.default.hash(Buffer8.concat(args.map((s) => Buffer8.from(s)))); - }; - randomNonce = () => { - return base64ToBase64url(Buffer8.from(import_tweetnacl2.default.randomBytes(12)).toString("base64")); - }; - hash2 = (v2) => { - return base64ToBase64url(Buffer8.from(import_tweetnacl2.default.hash(Buffer8.from(v2))).toString("base64")); - }; - computeCAndHc = (r, s, h2) => { - const \u0127 = hashStringArray(r, s); - const c = hashStringArray(h2, \u0127); - const hc = import_tweetnacl2.default.hash(c); - return [c, hc]; - }; - encryptContractSalt = (c, contractSalt) => { - const encryptionKey = hashRawStringArray(CS, c).slice(0, import_tweetnacl2.default.secretbox.keyLength); - const nonce = import_tweetnacl2.default.randomBytes(import_tweetnacl2.default.secretbox.nonceLength); - const encryptedContractSalt = import_tweetnacl2.default.secretbox(Buffer8.from(contractSalt), nonce, encryptionKey); - return base64ToBase64url(Buffer8.concat([nonce, encryptedContractSalt]).toString("base64")); - }; - encryptSaltUpdate = (secret, recordId, record2) => { - const nonce = import_tweetnacl2.default.randomBytes(import_tweetnacl2.default.secretbox.nonceLength); - const encryptionKey = hashRawStringArray(SU, secret, nonce, recordId).slice(0, import_tweetnacl2.default.secretbox.keyLength); - const encryptedRecord = import_tweetnacl2.default.secretbox(Buffer8.from(record2), nonce, encryptionKey); - return base64ToBase64url(Buffer8.concat([nonce, encryptedRecord]).toString("base64")); - }; - decryptSaltUpdate = (secret, recordId, encryptedRecordBox) => { - const encryptedRecordBoxBuf = Buffer8.from(base64urlToBase64(encryptedRecordBox), "base64"); - const nonce = encryptedRecordBoxBuf.subarray(0, import_tweetnacl2.default.secretbox.nonceLength); - const encryptionKey = hashRawStringArray(SU, secret, nonce, recordId).slice(0, import_tweetnacl2.default.secretbox.keyLength); - const encryptedRecord = encryptedRecordBoxBuf.subarray(import_tweetnacl2.default.secretbox.nonceLength); - const decrypted = import_tweetnacl2.default.secretbox.open(encryptedRecord, nonce, encryptionKey); - if (!decrypted) - throw new Error("Failed to decrypt salt update"); - return Buffer8.from(decrypted).toString(); - }; - boxKeyPair = () => { - return import_tweetnacl2.default.box.keyPair(); - }; - saltAgreement = (publicKey, secretKey) => { - const publicKeyBuf = Buffer8.from(base64urlToBase64(publicKey), "base64"); - const dhKey = import_tweetnacl2.default.box.before(publicKeyBuf, secretKey); - if (!publicKeyBuf || publicKeyBuf.byteLength !== import_tweetnacl2.default.box.publicKeyLength) { - return false; - } - const authSalt = Buffer8.from(hashStringArray(AUTHSALT, dhKey)).subarray(0, SALT_LENGTH_IN_OCTETS).toString("base64"); - const contractSalt = Buffer8.from(hashStringArray(CONTRACTSALT, dhKey)).subarray(0, SALT_LENGTH_IN_OCTETS).toString("base64"); - return [authSalt, contractSalt]; - }; - parseRegisterSalt = (publicKey, secretKey, encryptedHashedPassword) => { - const saltAgreementRes = saltAgreement(publicKey, secretKey); - if (!saltAgreementRes) { - return false; - } - const [authSalt, contractSalt] = saltAgreementRes; - const encryptionKey = import_tweetnacl2.default.hash(Buffer8.from(authSalt + contractSalt)).slice(0, import_tweetnacl2.default.secretbox.keyLength); - const encryptedHashedPasswordBuf = Buffer8.from(base64urlToBase64(encryptedHashedPassword), "base64"); - const hashedPasswordBuf = import_tweetnacl2.default.secretbox.open(encryptedHashedPasswordBuf.subarray(import_tweetnacl2.default.box.nonceLength), encryptedHashedPasswordBuf.subarray(0, import_tweetnacl2.default.box.nonceLength), encryptionKey); - if (!hashedPasswordBuf) { - return false; } - return [authSalt, contractSalt, hashedPasswordBuf, encryptionKey]; }; } }); -var import_npm_tweetnacl; -var nacl3; -var recordSecret; -var challengeSecret; -var registrationSecret; -var hashUpdateSecret; -var initZkpp; -var maxAge; -var computeZkppSaltRecordId; -var getZkppSaltRecord; -var setZkppSaltRecord; -var getChallenge; -var verifyChallenge; -var registrationKey; -var register; -var contractSaltVerifyC; -var getContractSalt; -var updateContractSalt; -var redeemSaltRegistrationToken; -var redeemSaltUpdateToken; -var init_zkppSalt = __esm({ - "src/serve/zkppSalt.ts"() { - "use strict"; - init_zkpp(); - init_zkppConstants(); - init_esm(); - import_npm_tweetnacl = __toESM(require_nacl_fast()); - nacl3 = import_npm_tweetnacl.default; - initZkpp = async () => { - const IKM = await esm_default("chelonia.db/get", "_private_immutable_zkpp_ikm").then((IKM2) => { - if (!IKM2) { - const secret = randomBytes2(33).toString("base64"); - return esm_default("chelonia.db/set", "_private_immutable_zkpp_ikm", secret).then(() => { - return secret; - }); - } - return IKM2; - }); - recordSecret = Buffer9.from(hashStringArray("private/recordSecret", IKM)).toString("base64"); - challengeSecret = Buffer9.from(hashStringArray("private/challengeSecret", IKM)).toString("base64"); - registrationSecret = Buffer9.from(hashStringArray("private/registrationSecret", IKM)).toString("base64"); - hashUpdateSecret = Buffer9.from(hashStringArray("private/hashUpdateSecret", IKM)).toString("base64"); - }; - maxAge = 30; - computeZkppSaltRecordId = async (contractID) => { - const recordId = `_private_rid_${contractID}`; - const record2 = await esm_default("chelonia.db/get", recordId); - if (!record2) { - return null; - } - const recordBuf = Buffer9.concat([Buffer9.from(contractID), Buffer9.from(record2)]); - return hash2(recordBuf); - }; - getZkppSaltRecord = async (contractID) => { - const recordId = `_private_rid_${contractID}`; - const record2 = await esm_default("chelonia.db/get", recordId); - if (record2) { - const encryptionKey = hashStringArray("REK", contractID, recordSecret).slice(0, nacl3.secretbox.keyLength); - const recordBuf = Buffer9.from(base64urlToBase64(record2), "base64"); - const nonce = recordBuf.slice(0, nacl3.secretbox.nonceLength); - const recordCiphertext = recordBuf.slice(nacl3.secretbox.nonceLength); - const recordPlaintext = nacl3.secretbox.open(recordCiphertext, nonce, encryptionKey); - if (!recordPlaintext) { - return null; - } - const recordString = Buffer9.from(recordPlaintext).toString("utf-8"); - try { - const recordObj = JSON.parse(recordString); - if (!Array.isArray(recordObj) || recordObj.length !== 3 && recordObj.length !== 4 || recordObj.slice(0, 3).some((r) => !r || typeof r !== "string") || recordObj[3] != null && typeof recordObj[3] !== "string") { - console.error("Error validating encrypted JSON object " + recordId); - return null; - } - const [hashedPassword, authSalt, contractSalt, cid] = recordObj; - return { - hashedPassword, - authSalt, - contractSalt, - cid - }; - } catch { - console.error("Error parsing encrypted JSON object " + recordId); - } - } - return null; - }; - setZkppSaltRecord = async (contractID, hashedPassword, authSalt, contractSalt, cid) => { - const recordId = `_private_rid_${contractID}`; - const encryptionKey = hashStringArray("REK", contractID, recordSecret).slice(0, nacl3.secretbox.keyLength); - const nonce = nacl3.randomBytes(nacl3.secretbox.nonceLength); - const recordPlaintext = JSON.stringify([hashedPassword, authSalt, contractSalt, cid]); - const recordCiphertext = nacl3.secretbox(Buffer9.from(recordPlaintext), nonce, encryptionKey); - const recordBuf = Buffer9.concat([nonce, recordCiphertext]); - const record2 = base64ToBase64url(recordBuf.toString("base64")); - await esm_default("chelonia.db/set", recordId, record2); - }; - getChallenge = async (contract, b) => { - const record2 = await getZkppSaltRecord(contract); - if (!record2) { - console.debug("getChallenge: Error obtaining ZKPP salt record for contract ID " + contract); - return false; - } - const { authSalt } = record2; - const s = randomNonce(); - const now = (Date.now() / 1e3 | 0).toString(16); - const sig = [now, base64ToBase64url(Buffer9.from(hashStringArray(contract, b, s, now, challengeSecret)).toString("base64"))].join(","); - return { - authSalt, - s, - sig - }; - }; - verifyChallenge = (contractID, r, s, userSig) => { - if (!/^[a-fA-F0-9]{1,11},[a-zA-Z0-9_-]{86}(?:==)?$/.test(userSig)) { - console.info(`wrong signature format for challenge for contract: ${contractID}`); - return false; - } - const [then, mac] = userSig.split(","); - const now = Date.now() / 1e3 | 0; - const iThen = Number.parseInt(then, 16); - if (!(iThen <= now) || !(iThen >= now - maxAge)) { - return false; - } - const b = hash2(r); - const sig = hashStringArray(contractID, b, s, then, challengeSecret); - const macBuf = Buffer9.from(base64urlToBase64(mac), "base64"); - return sig.byteLength === macBuf.byteLength && timingSafeEqual(sig, macBuf); - }; - registrationKey = (provisionalId, b) => { - const encryptionKey = hashStringArray("REG", provisionalId, registrationSecret).slice(0, nacl3.secretbox.keyLength); - const nonce = nacl3.randomBytes(nacl3.secretbox.nonceLength); - const keyPair = boxKeyPair(); - const s = base64ToBase64url(Buffer9.concat([nonce, nacl3.secretbox(keyPair.secretKey, nonce, encryptionKey)]).toString("base64")); - const now = (Date.now() / 1e3 | 0).toString(16); - const sig = [now, base64ToBase64url(Buffer9.from(hashStringArray(provisionalId, b, s, now, challengeSecret)).toString("base64"))].join(","); - return { - s, - p: base64ToBase64url(Buffer9.from(keyPair.publicKey).toString("base64")), - sig - }; - }; - register = (provisionalId, clientPublicKey, encryptedSecretKey, userSig, encryptedHashedPassword) => { - if (!verifyChallenge(provisionalId, clientPublicKey, encryptedSecretKey, userSig)) { - console.warn("register: Error validating challenge: " + JSON.stringify({ contract: provisionalId, clientPublicKey, userSig })); - throw new Error("register: Invalid challenge"); - } - const encryptedSecretKeyBuf = Buffer9.from(base64urlToBase64(encryptedSecretKey), "base64"); - const encryptionKey = hashStringArray("REG", provisionalId, registrationSecret).slice(0, nacl3.secretbox.keyLength); - const secretKeyBuf = nacl3.secretbox.open(encryptedSecretKeyBuf.slice(nacl3.secretbox.nonceLength), encryptedSecretKeyBuf.slice(0, nacl3.secretbox.nonceLength), encryptionKey); - if (!secretKeyBuf) { - console.warn(`register: Error decrypting arguments for contract ID ${provisionalId} (${JSON.stringify({ clientPublicKey, userSig })})`); - return false; - } - const parseRegisterSaltRes = parseRegisterSalt(clientPublicKey, secretKeyBuf, encryptedHashedPassword); - if (!parseRegisterSaltRes) { - console.warn(`register: Error parsing registration salt for contract ID ${provisionalId} (${JSON.stringify({ clientPublicKey, userSig })})`); - return false; - } - const [authSalt, contractSalt, hashedPasswordBuf, sharedEncryptionKey] = parseRegisterSaltRes; - const token = encryptSaltUpdate( - hashUpdateSecret, - provisionalId, - JSON.stringify([Date.now(), Buffer9.from(hashedPasswordBuf).toString(), authSalt, contractSalt]) - ); - return encryptContractSalt(sharedEncryptionKey, token); - }; - contractSaltVerifyC = (h2, r, s, userHc) => { - const [c, hc] = computeCAndHc(r, s, h2); - const userHcBuf = Buffer9.from(base64urlToBase64(userHc), "base64"); - if (hc.byteLength === userHcBuf.byteLength && timingSafeEqual(hc, userHcBuf)) { - return c; - } - return false; - }; - getContractSalt = async (contract, r, s, sig, hc) => { - if (!verifyChallenge(contract, r, s, sig)) { - console.debug("getContractSalt: Error validating challenge: " + JSON.stringify({ contract, r, s, sig })); - throw new Error("getContractSalt: Bad challenge"); - } - const record2 = await getZkppSaltRecord(contract); - if (!record2) { - console.error("getContractSalt: Error obtaining ZKPP salt record for contract ID " + contract); - return false; - } - const { hashedPassword, contractSalt, cid } = record2; - const c = contractSaltVerifyC(hashedPassword, r, s, hc); - if (!c) { - console.error(`getContractSalt: Error verifying challenge for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); - throw new Error("getContractSalt: Bad challenge"); - } - return encryptContractSalt(c, JSON.stringify([contractSalt, cid])); - }; - updateContractSalt = async (contract, r, s, sig, hc, encryptedArgs) => { - if (!verifyChallenge(contract, r, s, sig)) { - console.warn("update: Error validating challenge: " + JSON.stringify({ contract, r, s, sig })); - throw new Error("update: Bad challenge"); - } - const record2 = await getZkppSaltRecord(contract); - if (!record2) { - console.error("update: Error obtaining ZKPP salt record for contract ID " + contract); - return false; - } - const { hashedPassword, contractSalt: oldContractSalt } = record2; - const c = contractSaltVerifyC(hashedPassword, r, s, hc); - if (!c) { - console.error(`update: Error verifying challenge for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); - throw new Error("update: Bad challenge"); - } - const encryptionKey = hashRawStringArray(SU, c).slice(0, nacl3.secretbox.keyLength); - const encryptedArgsBuf = Buffer9.from(base64urlToBase64(encryptedArgs), "base64"); - const nonce = encryptedArgsBuf.slice(0, nacl3.secretbox.nonceLength); - const encryptedArgsCiphertext = encryptedArgsBuf.slice(nacl3.secretbox.nonceLength); - const args = nacl3.secretbox.open(encryptedArgsCiphertext, nonce, encryptionKey); - if (!args) { - console.error(`update: Error decrypting arguments for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); - return false; - } - try { - const hashedPassword2 = Buffer9.from(args).toString(); - const recordId = await computeZkppSaltRecordId(contract); - if (!recordId) { - console.error(`update: Error obtaining record ID for contract ID ${contract}`); - return false; - } - const authSalt = Buffer9.from(hashStringArray(AUTHSALT, c)).slice(0, SALT_LENGTH_IN_OCTETS).toString("base64"); - const contractSalt = Buffer9.from(hashStringArray(CONTRACTSALT, c)).slice(0, SALT_LENGTH_IN_OCTETS).toString("base64"); - const token = encryptSaltUpdate( - hashUpdateSecret, - recordId, - JSON.stringify([Date.now(), hashedPassword2, authSalt, contractSalt]) - ); - return encryptContractSalt(c, JSON.stringify([oldContractSalt, token])); - } catch { - console.error(`update: Error parsing encrypted arguments for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); - } - return false; - }; - redeemSaltRegistrationToken = async (provisoryRegistrationKey, contract, token) => { - const decryptedToken = decryptSaltUpdate( - hashUpdateSecret, - provisoryRegistrationKey, - token - ); - const [timestamp, hashedPassword, authSalt, contractSalt] = JSON.parse(decryptedToken); - if (timestamp < Date.now() - 18e4) { - throw new Error("ZKPP token expired"); - } - await setZkppSaltRecord(contract, hashedPassword, authSalt, contractSalt); +var require_BZPOPMIN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BZPOPMIN.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - redeemSaltUpdateToken = async (contract, token) => { - const recordId = await computeZkppSaltRecordId(contract); - if (!recordId) { - throw new Error("Record ID not found"); - } - const decryptedToken = decryptSaltUpdate( - hashUpdateSecret, - recordId, - token - ); - const [timestamp, hashedPassword, authSalt, contractSalt] = JSON.parse(decryptedToken); - if (timestamp < Date.now() - 18e4) { - throw new Error("ZKPP token expired"); - } - return (cid) => { - return setZkppSaltRecord(contract, hashedPassword, authSalt, contractSalt, cid); - }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var BZPOPMAX_1 = __importDefault(require_BZPOPMAX()); + exports2.default = { + IS_READ_ONLY: BZPOPMAX_1.default.IS_READ_ONLY, + /** + * Removes and returns the member with the lowest score in a sorted set, or blocks until one is available + * @param parser - The Redis command parser + * @param keys - Key of the sorted set, or array of keys to try sequentially + * @param timeout - Maximum seconds to block, 0 to block indefinitely + */ + parseCommand(parser3, keys, timeout) { + parser3.push("BZPOPMIN"); + parser3.pushKeys(keys); + parser3.push(timeout.toString()); + }, + transformReply: BZPOPMAX_1.default.transformReply }; } }); -function namespaceKey(name) { - return "name=" + name; -} -var KEYOP_SEGMENT_LENGTH; -var updateSize; -var appendToIndexFactory; -var appendToNamesIndex; -var removeFromIndexFactory; -var lookupUltimateOwner; -var init_db_utils = __esm({ - "src/serve/db-utils.ts"() { +var require_CLIENT_CACHING = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_CACHING.js"(exports2) { "use strict"; - init_esm(); - KEYOP_SEGMENT_LENGTH = 1e4; - updateSize = async (resourceID, sizeKey, size, skipIfDeleted) => { - if (!Number.isSafeInteger(size)) { - throw new TypeError(`Invalid given size ${size} for ${resourceID}`); - } - await esm_default("okTurtles.eventQueue/queueEvent", sizeKey, async () => { - const storedSize = await esm_default("chelonia.db/get", sizeKey, { bypassCache: true }); - if (skipIfDeleted && storedSize == null) return; - const existingSize = parseInt(storedSize ?? "0", 10); - if (!(existingSize >= 0)) { - throw new TypeError(`Invalid stored size ${existingSize} for ${resourceID}`); - } - const updatedSize = existingSize + size; - if (!(updatedSize >= 0)) { - throw new TypeError(`Invalid stored updated size ${updatedSize} for ${resourceID}`); - } - await esm_default("chelonia.db/set", sizeKey, updatedSize.toString(10)); - }); - }; - appendToIndexFactory = (key) => { - return (value) => { - return esm_default("okTurtles.eventQueue/queueEvent", key, async () => { - const currentIndex = await esm_default("chelonia.db/get", key, { bypassCache: true }); - if (currentIndex) { - if ( - // Check if the value is at the end - currentIndex.endsWith("\0" + value) || // Check if the value is at the start - currentIndex.startsWith(value + "\0") || // Check if the current index is exactly the value - currentIndex === value || // Check if the value is in the middle - currentIndex.includes("\0" + value + "\0") - ) { - return; - } - await esm_default("chelonia.db/set", key, `${currentIndex}\0${value}`); - return; - } - await esm_default("chelonia.db/set", key, value); - }); - }; - }; - appendToNamesIndex = appendToIndexFactory("_private_names_index"); - removeFromIndexFactory = (key) => { - return (values) => { - return esm_default("okTurtles.eventQueue/queueEvent", key, async () => { - let existingEntries = await esm_default("chelonia.db/get", key, { bypassCache: true }); - if (!existingEntries) return; - if (!Array.isArray(values)) { - values = [values]; - } - for (const value of values) { - if (existingEntries.endsWith("\0" + value)) { - existingEntries = existingEntries.slice(0, -value.length - 1); - continue; - } - if (existingEntries.startsWith(value + "\0")) { - existingEntries = existingEntries.slice(value.length + 1); - continue; - } - if (existingEntries === value) { - existingEntries = void 0; - break; - } - const entryIndex = existingEntries.indexOf("\0" + value + "\0"); - if (entryIndex === -1) continue; - existingEntries = existingEntries.slice(0, entryIndex) + existingEntries.slice(entryIndex + value.length + 1); - } - if (existingEntries) { - await esm_default("chelonia.db/set", key, existingEntries); - } else { - await esm_default("chelonia.db/delete", key); - } - }); - }; - }; - lookupUltimateOwner = async (resourceID) => { - let ownerID = resourceID; - for (let depth = 128; depth >= 0; depth--) { - const newOwnerID = await esm_default("chelonia.db/get", `_private_owner_${ownerID}`, { bypassCache: true }); - if (!newOwnerID) break; - if (!depth) { - throw new Error("Exceeded max depth looking up owner for " + resourceID); - } - ownerID = newOwnerID; - } - return ownerID; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Instructs the server about tracking or not keys in the next request + * @param parser - The Redis command parser + * @param value - Whether to enable (true) or disable (false) tracking + */ + parseCommand(parser3, value) { + parser3.push("CLIENT", "CACHING", value ? "YES" : "NO"); + }, + transformReply: void 0 }; } }); -var requiredMethodNames; -var DatabaseBackend; -var init_DatabaseBackend = __esm({ - "src/serve/DatabaseBackend.ts"() { +var require_CLIENT_GETNAME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_GETNAME.js"(exports2) { "use strict"; - requiredMethodNames = ["init", "clear", "readData", "writeData", "deleteData", "close", "iterKeys", "keyCount"]; - DatabaseBackend = class _DatabaseBackend { - constructor() { - if (new.target === _DatabaseBackend) { - throw new Error("Class DatabaseBackend cannot be instantiated directly."); - } - const bindMethod = (name) => { - this[name] = this[name].bind(this); - }; - for (const name of requiredMethodNames) { - bindMethod(name); - } - } + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the name of the current connection + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLIENT", "GETNAME"); + }, + transformReply: void 0 }; } }); -var database_fs_exports = {}; -__export(database_fs_exports, { - default: () => FsBackend -}); -async function testCaseSensitivity(backend) { - const { readData, writeData, deleteData } = backend; - const date3 = /* @__PURE__ */ new Date(); - const dateString = date3.toISOString(); - const originalKey = `_private_testCaseSensitivity_${date3.getTime()}_${(0, Math.random)().toFixed(8).slice(2)}`; - const differentlyCasedKey = "_P" + originalKey.slice(2); - await writeData(originalKey, dateString); - try { - const valueOriginalCase = await readData(originalKey); - const valueDifferentCase = await readData(differentlyCasedKey); - if (valueOriginalCase?.toString() !== dateString) { - console.error(`Unexpected value on case-sensitivity test; expected ${dateString}`); - throw new Error("Unexpected value: original key does not have the correct value"); - } - if (valueDifferentCase?.toString() === dateString) { - const errStr = "Filesystem database backend only works on case-sensitive filesystems. This appears to be a case insensitive file system. Set `skipFsCaseSensitivityCheck: true` on the FS backend configuration to skip."; - console.error(errStr); - throw new Error(errStr); - } - } finally { - await deleteData(originalKey); - } -} -var ConfigSchema; -var splitAndGroup; -var FsBackend; -var init_database_fs = __esm({ - "src/serve/database-fs.ts"() { +var require_CLIENT_GETREDIR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_GETREDIR.js"(exports2) { "use strict"; - init_db(); - init_zod(); - init_DatabaseBackend(); - ConfigSchema = strictObject({ - dirname: optional(string2()), - depth: optional(number2()), - keyChunkLength: optional(number2()), - skipFsCaseSensitivityCheck: optional(boolean2()) - }); - splitAndGroup = (input, chunkLength, depth) => input.slice(0, chunkLength * depth).split("").reduce((acc, cv, i2) => { - acc[i2 / chunkLength | 0] = (acc[i2 / chunkLength | 0] || "") + cv; - return acc; - }, []); - FsBackend = class extends DatabaseBackend { - dataFolder = "data"; - depth = 0; - keyChunkLength = 2; - skipFsCaseSensitivityCheck = false; - constructor(options2 = {}) { - super(); - ConfigSchema.parse(options2); - if (options2.dirname) this.dataFolder = resolve9(options2.dirname); - if (options2.depth) this.depth = options2.depth; - if (options2.keyChunkLength) this.keyChunkLength = options2.keyChunkLength; - if (options2.skipFsCaseSensitivityCheck) this.skipFsCaseSensitivityCheck = true; - } - // Maps a given key to a real path on the filesystem. - mapKey(key) { - if (basename9(normalize8(key)) !== key) throw new TypeError("Invalid key"); - if (!this.depth) return join9(this.dataFolder, key); - const keyChunks = splitAndGroup(key, this.keyChunkLength, this.depth); - return join9(this.dataFolder, ...keyChunks, key); - } - async init() { - await mkdir(this.dataFolder, { mode: 488, recursive: true }); - if (!this.skipFsCaseSensitivityCheck) { - await testCaseSensitivity(this); - } - } - async clear() { - const names = await readdir(this.dataFolder); - const paths = names.map((name) => join9(this.dataFolder, name)); - await Promise.all( - paths.map((p) => rm(p, { recursive: true })) - ); - } - async readData(key) { - checkKey(key); - return await readFile(this.mapKey(key)).catch((err) => { - if (err.code !== "ENOENT") throw err; - }); - } - async writeData(key, value) { - const path8 = this.mapKey(key); - if (this.depth) await mkdir(dirname9(path8), { mode: 488, recursive: true }); - await writeFile(path8, value); - } - async deleteData(key) { - await unlink(this.mapKey(key)).catch((e2) => { - if (e2?.code === "ENOENT") { - return; - } - throw e2; - }); - } - close() { - } - async *iterKeys() { - const entries = await readdir(this.dataFolder, { withFileTypes: true }); - for (const entry of entries) { - if (entry.isFile()) { - yield entry.name; - } - } - } - async keyCount() { - const entries = await readdir(this.dataFolder, { withFileTypes: true }); - return entries.filter((e2) => e2.isFile()).length; - } + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the ID of the client to which the current client is redirecting tracking notifications + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLIENT", "GETREDIR"); + }, + transformReply: void 0 }; } }); -var require_verbatim_string = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/RESP/verbatim-string.js"(exports2) { +var require_CLIENT_ID = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_ID.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.VerbatimString = void 0; - var VerbatimString = class extends String { - format; - constructor(format52, value) { - super(value); - this.format = format52; - } + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the client ID for the current connection + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLIENT", "ID"); + }, + transformReply: void 0 }; - exports2.VerbatimString = VerbatimString; } }); -var require_errors = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/errors.js"(exports2) { +var require_CLIENT_INFO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_INFO.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.MultiErrorReply = exports2.CommandTimeoutDuringMaintenanceError = exports2.SocketTimeoutDuringMaintenanceError = exports2.TimeoutError = exports2.BlobError = exports2.SimpleError = exports2.ErrorReply = exports2.ReconnectStrategyError = exports2.RootNodesUnavailableError = exports2.SocketClosedUnexpectedlyError = exports2.DisconnectsClientError = exports2.ClientOfflineError = exports2.ClientClosedError = exports2.SocketTimeoutError = exports2.ConnectionTimeoutError = exports2.WatchError = exports2.AbortError = void 0; - var AbortError = class extends Error { - constructor() { - super("The command was aborted"); - } - }; - exports2.AbortError = AbortError; - var WatchError = class extends Error { - constructor(message = "One (or more) of the watched keys has been changed") { - super(message); - } - }; - exports2.WatchError = WatchError; - var ConnectionTimeoutError = class extends Error { - constructor() { - super("Connection timeout"); - } - }; - exports2.ConnectionTimeoutError = ConnectionTimeoutError; - var SocketTimeoutError = class extends Error { - constructor(timeout) { - super(`Socket timeout timeout. Expecting data, but didn't receive any in ${timeout}ms.`); - } - }; - exports2.SocketTimeoutError = SocketTimeoutError; - var ClientClosedError = class extends Error { - constructor() { - super("The client is closed"); + var CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns information and statistics about the current client connection + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLIENT", "INFO"); + }, + transformReply(rawReply) { + const map = {}; + for (const item of rawReply.toString().matchAll(CLIENT_INFO_REGEX)) { + map[item[1]] = item[2]; + } + const reply = { + id: Number(map.id), + addr: map.addr, + fd: Number(map.fd), + name: map.name, + age: Number(map.age), + idle: Number(map.idle), + flags: map.flags, + db: Number(map.db), + sub: Number(map.sub), + psub: Number(map.psub), + multi: Number(map.multi), + qbuf: Number(map.qbuf), + qbufFree: Number(map["qbuf-free"]), + argvMem: Number(map["argv-mem"]), + obl: Number(map.obl), + oll: Number(map.oll), + omem: Number(map.omem), + totMem: Number(map["tot-mem"]), + events: map.events, + cmd: map.cmd, + user: map.user, + libName: map["lib-name"], + libVer: map["lib-ver"] + }; + if (map.laddr !== void 0) { + reply.laddr = map.laddr; + } + if (map.redir !== void 0) { + reply.redir = Number(map.redir); + } + if (map.ssub !== void 0) { + reply.ssub = Number(map.ssub); + } + if (map["multi-mem"] !== void 0) { + reply.multiMem = Number(map["multi-mem"]); + } + if (map.resp !== void 0) { + reply.resp = Number(map.resp); + } + return reply; } }; - exports2.ClientClosedError = ClientClosedError; - var ClientOfflineError = class extends Error { - constructor() { - super("The client is offline"); - } + } +}); +var require_CLIENT_KILL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_KILL.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.CLIENT_KILL_FILTERS = void 0; + exports2.CLIENT_KILL_FILTERS = { + ADDRESS: "ADDR", + LOCAL_ADDRESS: "LADDR", + ID: "ID", + TYPE: "TYPE", + USER: "USER", + SKIP_ME: "SKIPME", + MAXAGE: "MAXAGE" }; - exports2.ClientOfflineError = ClientOfflineError; - var DisconnectsClientError = class extends Error { - constructor() { - super("Disconnects client"); - } + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Closes client connections matching the specified filters + * @param parser - The Redis command parser + * @param filters - One or more filters to match client connections to kill + */ + parseCommand(parser3, filters) { + parser3.push("CLIENT", "KILL"); + if (Array.isArray(filters)) { + for (const filter of filters) { + pushFilter(parser3, filter); + } + } else { + pushFilter(parser3, filters); + } + }, + transformReply: void 0 }; - exports2.DisconnectsClientError = DisconnectsClientError; - var SocketClosedUnexpectedlyError = class extends Error { - constructor() { - super("Socket closed unexpectedly"); + function pushFilter(parser3, filter) { + if (filter === exports2.CLIENT_KILL_FILTERS.SKIP_ME) { + parser3.push("SKIPME"); + return; } - }; - exports2.SocketClosedUnexpectedlyError = SocketClosedUnexpectedlyError; - var RootNodesUnavailableError = class extends Error { - constructor() { - super("All the root nodes are unavailable"); + parser3.push(filter.filter); + switch (filter.filter) { + case exports2.CLIENT_KILL_FILTERS.ADDRESS: + parser3.push(filter.address); + break; + case exports2.CLIENT_KILL_FILTERS.LOCAL_ADDRESS: + parser3.push(filter.localAddress); + break; + case exports2.CLIENT_KILL_FILTERS.ID: + parser3.push(typeof filter.id === "number" ? filter.id.toString() : filter.id); + break; + case exports2.CLIENT_KILL_FILTERS.TYPE: + parser3.push(filter.type); + break; + case exports2.CLIENT_KILL_FILTERS.USER: + parser3.push(filter.username); + break; + case exports2.CLIENT_KILL_FILTERS.SKIP_ME: + parser3.push(filter.skipMe ? "yes" : "no"); + break; + case exports2.CLIENT_KILL_FILTERS.MAXAGE: + parser3.push(filter.maxAge.toString()); + break; } + } + } +}); +var require_CLIENT_LIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_LIST.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - exports2.RootNodesUnavailableError = RootNodesUnavailableError; - var ReconnectStrategyError = class extends Error { - originalError; - socketError; - constructor(originalError, socketError) { - super(originalError.message); - this.originalError = originalError; - this.socketError = socketError; + Object.defineProperty(exports2, "__esModule", { value: true }); + var CLIENT_INFO_1 = __importDefault(require_CLIENT_INFO()); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns information about all client connections. Can be filtered by type or ID + * @param parser - The Redis command parser + * @param filter - Optional filter to return only specific client types or IDs + */ + parseCommand(parser3, filter) { + parser3.push("CLIENT", "LIST"); + if (filter) { + if (filter.TYPE !== void 0) { + parser3.push("TYPE", filter.TYPE); + } else { + parser3.push("ID"); + parser3.pushVariadic(filter.ID); + } + } + }, + transformReply(rawReply) { + const split = rawReply.toString().split("\n"), length2 = split.length - 1, reply = []; + for (let i2 = 0; i2 < length2; i2++) { + reply.push(CLIENT_INFO_1.default.transformReply(split[i2])); + } + return reply; } }; - exports2.ReconnectStrategyError = ReconnectStrategyError; - var ErrorReply = class extends Error { - }; - exports2.ErrorReply = ErrorReply; - var SimpleError = class extends ErrorReply { - }; - exports2.SimpleError = SimpleError; - var BlobError = class extends ErrorReply { + } +}); +var require_CLIENT_NO_EVICT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_NO-EVICT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Controls whether to prevent the client's connections from being evicted + * @param parser - The Redis command parser + * @param value - Whether to enable (true) or disable (false) the no-evict mode + */ + parseCommand(parser3, value) { + parser3.push("CLIENT", "NO-EVICT", value ? "ON" : "OFF"); + }, + transformReply: void 0 }; - exports2.BlobError = BlobError; - var TimeoutError = class extends Error { + } +}); +var require_CLIENT_NO_TOUCH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_NO-TOUCH.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Controls whether to prevent the client from touching the LRU/LFU of keys + * @param parser - The Redis command parser + * @param value - Whether to enable (true) or disable (false) the no-touch mode + */ + parseCommand(parser3, value) { + parser3.push("CLIENT", "NO-TOUCH", value ? "ON" : "OFF"); + }, + transformReply: void 0 }; - exports2.TimeoutError = TimeoutError; - var SocketTimeoutDuringMaintenanceError = class extends TimeoutError { - constructor(timeout) { - super(`Socket timeout during maintenance. Expecting data, but didn't receive any in ${timeout}ms.`); - } + } +}); +var require_CLIENT_PAUSE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_PAUSE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Stops the server from processing client commands for the specified duration + * @param parser - The Redis command parser + * @param timeout - Time in milliseconds to pause command processing + * @param mode - Optional mode: 'WRITE' to pause only write commands, 'ALL' to pause all commands + */ + parseCommand(parser3, timeout, mode) { + parser3.push("CLIENT", "PAUSE", timeout.toString()); + if (mode) { + parser3.push(mode); + } + }, + transformReply: void 0 }; - exports2.SocketTimeoutDuringMaintenanceError = SocketTimeoutDuringMaintenanceError; - var CommandTimeoutDuringMaintenanceError = class extends TimeoutError { - constructor(timeout) { - super(`Command timeout during maintenance. Waited to write command for more than ${timeout}ms.`); - } + } +}); +var require_CLIENT_SETNAME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_SETNAME.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Assigns a name to the current connection + * @param parser - The Redis command parser + * @param name - The name to assign to the connection + */ + parseCommand(parser3, name) { + parser3.push("CLIENT", "SETNAME", name); + }, + transformReply: void 0 }; - exports2.CommandTimeoutDuringMaintenanceError = CommandTimeoutDuringMaintenanceError; - var MultiErrorReply = class extends ErrorReply { - replies; - errorIndexes; - constructor(replies, errorIndexes) { - super(`${errorIndexes.length} commands failed, see .replies and .errorIndexes for more information`); - this.replies = replies; - this.errorIndexes = errorIndexes; - } - *errors() { - for (const index of this.errorIndexes) { - yield this.replies[index]; + } +}); +var require_CLIENT_TRACKING = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_TRACKING.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Controls server-assisted client side caching for the current connection + * @param parser - The Redis command parser + * @param mode - Whether to enable (true) or disable (false) tracking + * @param options - Optional configuration including REDIRECT, BCAST, PREFIX, OPTIN, OPTOUT, and NOLOOP options + */ + parseCommand(parser3, mode, options2) { + parser3.push("CLIENT", "TRACKING", mode ? "ON" : "OFF"); + if (mode) { + if (options2?.REDIRECT) { + parser3.push("REDIRECT", options2.REDIRECT.toString()); + } + if (isBroadcast(options2)) { + parser3.push("BCAST"); + if (options2?.PREFIX) { + if (Array.isArray(options2.PREFIX)) { + for (const prefix of options2.PREFIX) { + parser3.push("PREFIX", prefix); + } + } else { + parser3.push("PREFIX", options2.PREFIX); + } + } + } else if (isOptIn(options2)) { + parser3.push("OPTIN"); + } else if (isOptOut(options2)) { + parser3.push("OPTOUT"); + } + if (options2?.NOLOOP) { + parser3.push("NOLOOP"); + } } - } + }, + transformReply: void 0 }; - exports2.MultiErrorReply = MultiErrorReply; + function isBroadcast(options2) { + return options2?.BCAST === true; + } + function isOptIn(options2) { + return options2?.OPTIN === true; + } + function isOptOut(options2) { + return options2?.OPTOUT === true; + } } }); -var require_decoder = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/RESP/decoder.js"(exports2) { +var require_CLIENT_TRACKINGINFO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_TRACKINGINFO.js"(exports2) { "use strict"; - var _a2; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.Decoder = exports2.PUSH_TYPE_MAPPING = exports2.RESP_TYPES = void 0; - var verbatim_string_1 = require_verbatim_string(); - var errors_1 = require_errors(); - exports2.RESP_TYPES = { - NULL: 95, - // _ - BOOLEAN: 35, - // # - NUMBER: 58, - // : - BIG_NUMBER: 40, - // ( - DOUBLE: 44, - // , - SIMPLE_STRING: 43, - // + - BLOB_STRING: 36, - // $ - VERBATIM_STRING: 61, - // = - SIMPLE_ERROR: 45, - // - - BLOB_ERROR: 33, - // ! - ARRAY: 42, - // * - SET: 126, - // ~ - MAP: 37, - // % - PUSH: 62 - // > + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns information about the current connection's key tracking state + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLIENT", "TRACKINGINFO"); + }, + transformReply: { + 2: (reply) => ({ + flags: reply[1], + redirect: reply[3], + prefixes: reply[5] + }), + 3: void 0 + } }; - var ASCII = { - "\r": 13, - "t": 116, - "+": 43, - "-": 45, - "0": 48, - ".": 46, - "i": 105, - "n": 110, - "E": 69, - "e": 101 + } +}); +var require_CLIENT_UNPAUSE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_UNPAUSE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Resumes processing of client commands after a CLIENT PAUSE + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLIENT", "UNPAUSE"); + }, + transformReply: void 0 }; - exports2.PUSH_TYPE_MAPPING = { - [exports2.RESP_TYPES.BLOB_STRING]: Buffer + } +}); +var require_CLUSTER_ADDSLOTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_ADDSLOTS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Assigns hash slots to the current node in a Redis Cluster + * @param parser - The Redis command parser + * @param slots - One or more hash slots to be assigned + */ + parseCommand(parser3, slots) { + parser3.push("CLUSTER", "ADDSLOTS"); + parser3.pushVariadicNumber(slots); + }, + transformReply: void 0 }; - var Decoder2 = class { - onReply; - onErrorReply; - onPush; - getTypeMapping; - #cursor = 0; - #next; - constructor(config2) { - this.onReply = config2.onReply; - this.onErrorReply = config2.onErrorReply; - this.onPush = config2.onPush; - this.getTypeMapping = config2.getTypeMapping; - } - reset() { - this.#cursor = 0; - this.#next = void 0; - } - write(chunk) { - if (this.#cursor >= chunk.length) { - this.#cursor -= chunk.length; - return; - } - if (this.#next) { - if (this.#next(chunk) || this.#cursor >= chunk.length) { - this.#cursor -= chunk.length; - return; - } - } - do { - const type = chunk[this.#cursor]; - if (++this.#cursor === chunk.length) { - this.#next = this.#continueDecodeTypeValue.bind(this, type); - break; - } - if (this.#decodeTypeValue(type, chunk)) { - break; - } - } while (this.#cursor < chunk.length); - this.#cursor -= chunk.length; - } - #continueDecodeTypeValue(type, chunk) { - this.#next = void 0; - return this.#decodeTypeValue(type, chunk); - } - #decodeTypeValue(type, chunk) { - switch (type) { - case exports2.RESP_TYPES.NULL: - this.onReply(this.#decodeNull()); - return false; - case exports2.RESP_TYPES.BOOLEAN: - return this.#handleDecodedValue(this.onReply, this.#decodeBoolean(chunk)); - case exports2.RESP_TYPES.NUMBER: - return this.#handleDecodedValue(this.onReply, this.#decodeNumber(this.getTypeMapping()[exports2.RESP_TYPES.NUMBER], chunk)); - case exports2.RESP_TYPES.BIG_NUMBER: - return this.#handleDecodedValue(this.onReply, this.#decodeBigNumber(this.getTypeMapping()[exports2.RESP_TYPES.BIG_NUMBER], chunk)); - case exports2.RESP_TYPES.DOUBLE: - return this.#handleDecodedValue(this.onReply, this.#decodeDouble(this.getTypeMapping()[exports2.RESP_TYPES.DOUBLE], chunk)); - case exports2.RESP_TYPES.SIMPLE_STRING: - return this.#handleDecodedValue(this.onReply, this.#decodeSimpleString(this.getTypeMapping()[exports2.RESP_TYPES.SIMPLE_STRING], chunk)); - case exports2.RESP_TYPES.BLOB_STRING: - return this.#handleDecodedValue(this.onReply, this.#decodeBlobString(this.getTypeMapping()[exports2.RESP_TYPES.BLOB_STRING], chunk)); - case exports2.RESP_TYPES.VERBATIM_STRING: - return this.#handleDecodedValue(this.onReply, this.#decodeVerbatimString(this.getTypeMapping()[exports2.RESP_TYPES.VERBATIM_STRING], chunk)); - case exports2.RESP_TYPES.SIMPLE_ERROR: - return this.#handleDecodedValue(this.onErrorReply, this.#decodeSimpleError(chunk)); - case exports2.RESP_TYPES.BLOB_ERROR: - return this.#handleDecodedValue(this.onErrorReply, this.#decodeBlobError(chunk)); - case exports2.RESP_TYPES.ARRAY: - return this.#handleDecodedValue(this.onReply, this.#decodeArray(this.getTypeMapping(), chunk)); - case exports2.RESP_TYPES.SET: - return this.#handleDecodedValue(this.onReply, this.#decodeSet(this.getTypeMapping(), chunk)); - case exports2.RESP_TYPES.MAP: - return this.#handleDecodedValue(this.onReply, this.#decodeMap(this.getTypeMapping(), chunk)); - case exports2.RESP_TYPES.PUSH: - return this.#handleDecodedValue(this.onPush, this.#decodeArray(exports2.PUSH_TYPE_MAPPING, chunk)); - default: - throw new Error(`Unknown RESP type ${type} "${String.fromCharCode(type)}"`); - } - } - #handleDecodedValue(cb, value) { - if (typeof value === "function") { - this.#next = this.#continueDecodeValue.bind(this, cb, value); - return true; - } - cb(value); - return false; - } - #continueDecodeValue(cb, next, chunk) { - this.#next = void 0; - return this.#handleDecodedValue(cb, next(chunk)); - } - #decodeNull() { - this.#cursor += 2; - return null; - } - #decodeBoolean(chunk) { - const boolean3 = chunk[this.#cursor] === ASCII.t; - this.#cursor += 3; - return boolean3; - } - #decodeNumber(type, chunk) { - if (type === String) { - return this.#decodeSimpleString(String, chunk); - } - switch (chunk[this.#cursor]) { - case ASCII["+"]: - return this.#maybeDecodeNumberValue(false, chunk); - case ASCII["-"]: - return this.#maybeDecodeNumberValue(true, chunk); - default: - return this.#decodeNumberValue(false, this.#decodeUnsingedNumber.bind(this, 0), chunk); - } - } - #maybeDecodeNumberValue(isNegative, chunk) { - const cb = this.#decodeUnsingedNumber.bind(this, 0); - return ++this.#cursor === chunk.length ? this.#decodeNumberValue.bind(this, isNegative, cb) : this.#decodeNumberValue(isNegative, cb, chunk); - } - #decodeNumberValue(isNegative, numberCb, chunk) { - const number3 = numberCb(chunk); - return typeof number3 === "function" ? this.#decodeNumberValue.bind(this, isNegative, number3) : isNegative ? -number3 : number3; - } - #decodeUnsingedNumber(number3, chunk) { - let cursor = this.#cursor; - do { - const byte = chunk[cursor]; - if (byte === ASCII["\r"]) { - this.#cursor = cursor + 2; - return number3; - } - number3 = number3 * 10 + byte - ASCII["0"]; - } while (++cursor < chunk.length); - this.#cursor = cursor; - return this.#decodeUnsingedNumber.bind(this, number3); - } - #decodeBigNumber(type, chunk) { - if (type === String) { - return this.#decodeSimpleString(String, chunk); - } - switch (chunk[this.#cursor]) { - case ASCII["+"]: - return this.#maybeDecodeBigNumberValue(false, chunk); - case ASCII["-"]: - return this.#maybeDecodeBigNumberValue(true, chunk); - default: - return this.#decodeBigNumberValue(false, this.#decodeUnsingedBigNumber.bind(this, 0n), chunk); + } +}); +var require_CLUSTER_ADDSLOTSRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_ADDSLOTSRANGE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Assigns hash slot ranges to the current node in a Redis Cluster + * @param parser - The Redis command parser + * @param ranges - One or more slot ranges to be assigned, each specified as [start, end] + */ + parseCommand(parser3, ranges) { + parser3.push("CLUSTER", "ADDSLOTSRANGE"); + (0, generic_transformers_1.parseSlotRangesArguments)(parser3, ranges); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_BUMPEPOCH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_BUMPEPOCH.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Advances the cluster config epoch + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "BUMPEPOCH"); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_COUNT_FAILURE_REPORTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the number of failure reports for a given node + * @param parser - The Redis command parser + * @param nodeId - The ID of the node to check + */ + parseCommand(parser3, nodeId) { + parser3.push("CLUSTER", "COUNT-FAILURE-REPORTS", nodeId); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_COUNTKEYSINSLOT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_COUNTKEYSINSLOT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the number of keys in the specified hash slot + * @param parser - The Redis command parser + * @param slot - The hash slot to check + */ + parseCommand(parser3, slot) { + parser3.push("CLUSTER", "COUNTKEYSINSLOT", slot.toString()); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_DELSLOTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_DELSLOTS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Removes hash slots from the current node in a Redis Cluster + * @param parser - The Redis command parser + * @param slots - One or more hash slots to be removed + */ + parseCommand(parser3, slots) { + parser3.push("CLUSTER", "DELSLOTS"); + parser3.pushVariadicNumber(slots); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_DELSLOTSRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_DELSLOTSRANGE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Removes hash slot ranges from the current node in a Redis Cluster + * @param parser - The Redis command parser + * @param ranges - One or more slot ranges to be removed, each specified as [start, end] + */ + parseCommand(parser3, ranges) { + parser3.push("CLUSTER", "DELSLOTSRANGE"); + (0, generic_transformers_1.parseSlotRangesArguments)(parser3, ranges); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_FAILOVER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_FAILOVER.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.FAILOVER_MODES = void 0; + exports2.FAILOVER_MODES = { + FORCE: "FORCE", + TAKEOVER: "TAKEOVER" + }; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Forces a replica to perform a manual failover of its master + * @param parser - The Redis command parser + * @param options - Optional configuration with FORCE or TAKEOVER mode + */ + parseCommand(parser3, options2) { + parser3.push("CLUSTER", "FAILOVER"); + if (options2?.mode) { + parser3.push(options2.mode); } + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_FLUSHSLOTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_FLUSHSLOTS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Deletes all hash slots from the current node in a Redis Cluster + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "FLUSHSLOTS"); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_FORGET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_FORGET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Removes a node from the cluster + * @param parser - The Redis command parser + * @param nodeId - The ID of the node to remove + */ + parseCommand(parser3, nodeId) { + parser3.push("CLUSTER", "FORGET", nodeId); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_GETKEYSINSLOT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_GETKEYSINSLOT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns a number of keys from the specified hash slot + * @param parser - The Redis command parser + * @param slot - The hash slot to get keys from + * @param count - Maximum number of keys to return + */ + parseCommand(parser3, slot, count) { + parser3.push("CLUSTER", "GETKEYSINSLOT", slot.toString(), count.toString()); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_INFO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns information about the state of a Redis Cluster + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "INFO"); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_KEYSLOT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_KEYSLOT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the hash slot number for a given key + * @param parser - The Redis command parser + * @param key - The key to get the hash slot for + */ + parseCommand(parser3, key) { + parser3.push("CLUSTER", "KEYSLOT", key); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_LINKS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_LINKS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns information about all cluster links (lower level connections to other nodes) + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "LINKS"); + }, + transformReply: { + 2: (reply) => reply.map((link) => { + const unwrapped = link; + return { + direction: unwrapped[1], + node: unwrapped[3], + "create-time": unwrapped[5], + events: unwrapped[7], + "send-buffer-allocated": unwrapped[9], + "send-buffer-used": unwrapped[11] + }; + }), + 3: void 0 } - #maybeDecodeBigNumberValue(isNegative, chunk) { - const cb = this.#decodeUnsingedBigNumber.bind(this, 0n); - return ++this.#cursor === chunk.length ? this.#decodeBigNumberValue.bind(this, isNegative, cb) : this.#decodeBigNumberValue(isNegative, cb, chunk); - } - #decodeBigNumberValue(isNegative, bigNumberCb, chunk) { - const bigNumber = bigNumberCb(chunk); - return typeof bigNumber === "function" ? this.#decodeBigNumberValue.bind(this, isNegative, bigNumber) : isNegative ? -bigNumber : bigNumber; - } - #decodeUnsingedBigNumber(bigNumber, chunk) { - let cursor = this.#cursor; - do { - const byte = chunk[cursor]; - if (byte === ASCII["\r"]) { - this.#cursor = cursor + 2; - return bigNumber; - } - bigNumber = bigNumber * 10n + BigInt(byte - ASCII["0"]); - } while (++cursor < chunk.length); - this.#cursor = cursor; - return this.#decodeUnsingedBigNumber.bind(this, bigNumber); - } - #decodeDouble(type, chunk) { - if (type === String) { - return this.#decodeSimpleString(String, chunk); - } - switch (chunk[this.#cursor]) { - case ASCII.n: - this.#cursor += 5; - return NaN; - case ASCII["+"]: - return this.#maybeDecodeDoubleInteger(false, chunk); - case ASCII["-"]: - return this.#maybeDecodeDoubleInteger(true, chunk); - default: - return this.#decodeDoubleInteger(false, 0, chunk); - } - } - #maybeDecodeDoubleInteger(isNegative, chunk) { - return ++this.#cursor === chunk.length ? this.#decodeDoubleInteger.bind(this, isNegative, 0) : this.#decodeDoubleInteger(isNegative, 0, chunk); - } - #decodeDoubleInteger(isNegative, integer2, chunk) { - if (chunk[this.#cursor] === ASCII.i) { - this.#cursor += 5; - return isNegative ? -Infinity : Infinity; + }; + } +}); +var require_CLUSTER_MEET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_MEET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Initiates a handshake with another node in the cluster + * @param parser - The Redis command parser + * @param host - Host name or IP address of the node + * @param port - TCP port of the node + */ + parseCommand(parser3, host, port) { + parser3.push("CLUSTER", "MEET", host, port.toString()); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_MYID = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_MYID.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the node ID of the current Redis Cluster node + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "MYID"); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_MYSHARDID = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_MYSHARDID.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the shard ID of the current Redis Cluster node + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "MYSHARDID"); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_NODES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_NODES.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns serialized information about the nodes in a Redis Cluster + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "NODES"); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_REPLICAS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_REPLICAS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the replica nodes replicating from the specified primary node + * @param parser - The Redis command parser + * @param nodeId - Node ID of the primary node + */ + parseCommand(parser3, nodeId) { + parser3.push("CLUSTER", "REPLICAS", nodeId); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_REPLICATE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_REPLICATE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Reconfigures a node as a replica of the specified primary node + * @param parser - The Redis command parser + * @param nodeId - Node ID of the primary node to replicate + */ + parseCommand(parser3, nodeId) { + parser3.push("CLUSTER", "REPLICATE", nodeId); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_RESET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_RESET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Resets a Redis Cluster node, clearing all information and returning it to a brand new state + * @param parser - The Redis command parser + * @param options - Options for the reset operation + */ + parseCommand(parser3, options2) { + parser3.push("CLUSTER", "RESET"); + if (options2?.mode) { + parser3.push(options2.mode); } - return this.#continueDecodeDoubleInteger(isNegative, integer2, chunk); - } - #continueDecodeDoubleInteger(isNegative, integer2, chunk) { - let cursor = this.#cursor; - do { - const byte = chunk[cursor]; - switch (byte) { - case ASCII["."]: - this.#cursor = cursor + 1; - return this.#cursor < chunk.length ? this.#decodeDoubleDecimal(isNegative, 0, integer2, chunk) : this.#decodeDoubleDecimal.bind(this, isNegative, 0, integer2); - case ASCII.E: - case ASCII.e: - this.#cursor = cursor + 1; - const i2 = isNegative ? -integer2 : integer2; - return this.#cursor < chunk.length ? this.#decodeDoubleExponent(i2, chunk) : this.#decodeDoubleExponent.bind(this, i2); - case ASCII["\r"]: - this.#cursor = cursor + 2; - return isNegative ? -integer2 : integer2; - default: - integer2 = integer2 * 10 + byte - ASCII["0"]; - } - } while (++cursor < chunk.length); - this.#cursor = cursor; - return this.#continueDecodeDoubleInteger.bind(this, isNegative, integer2); - } - // Precalculated multipliers for decimal points to improve performance - // "... about 15 to 17 decimal places ..." - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#:~:text=about%2015%20to%2017%20decimal%20places - static #DOUBLE_DECIMAL_MULTIPLIERS = [ - 0.1, - 0.01, - 1e-3, - 1e-4, - 1e-5, - 1e-6, - 1e-7, - 1e-8, - 1e-9, - 1e-10, - 1e-11, - 1e-12, - 1e-13, - 1e-14, - 1e-15, - 1e-16, - 1e-17 - ]; - #decodeDoubleDecimal(isNegative, decimalIndex, double, chunk) { - let cursor = this.#cursor; - do { - const byte = chunk[cursor]; - switch (byte) { - case ASCII.E: - case ASCII.e: - this.#cursor = cursor + 1; - const d = isNegative ? -double : double; - return this.#cursor === chunk.length ? this.#decodeDoubleExponent.bind(this, d) : this.#decodeDoubleExponent(d, chunk); - case ASCII["\r"]: - this.#cursor = cursor + 2; - return isNegative ? -double : double; - } - if (decimalIndex < _a2.#DOUBLE_DECIMAL_MULTIPLIERS.length) { - double += (byte - ASCII["0"]) * _a2.#DOUBLE_DECIMAL_MULTIPLIERS[decimalIndex++]; - } - } while (++cursor < chunk.length); - this.#cursor = cursor; - return this.#decodeDoubleDecimal.bind(this, isNegative, decimalIndex, double); - } - #decodeDoubleExponent(double, chunk) { - switch (chunk[this.#cursor]) { - case ASCII["+"]: - return ++this.#cursor === chunk.length ? this.#continueDecodeDoubleExponent.bind(this, false, double, 0) : this.#continueDecodeDoubleExponent(false, double, 0, chunk); - case ASCII["-"]: - return ++this.#cursor === chunk.length ? this.#continueDecodeDoubleExponent.bind(this, true, double, 0) : this.#continueDecodeDoubleExponent(true, double, 0, chunk); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_SAVECONFIG = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SAVECONFIG.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Forces a Redis Cluster node to save the cluster configuration to disk + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "SAVECONFIG"); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_SET_CONFIG_EPOCH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SET-CONFIG-EPOCH.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Sets the configuration epoch for a Redis Cluster node + * @param parser - The Redis command parser + * @param configEpoch - The configuration epoch to set + */ + parseCommand(parser3, configEpoch) { + parser3.push("CLUSTER", "SET-CONFIG-EPOCH", configEpoch.toString()); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_SETSLOT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SETSLOT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.CLUSTER_SLOT_STATES = void 0; + exports2.CLUSTER_SLOT_STATES = { + IMPORTING: "IMPORTING", + MIGRATING: "MIGRATING", + STABLE: "STABLE", + NODE: "NODE" + }; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Assigns a hash slot to a specific Redis Cluster node + * @param parser - The Redis command parser + * @param slot - The slot number to assign + * @param state - The state to set for the slot (IMPORTING, MIGRATING, STABLE, NODE) + * @param nodeId - Node ID (required for IMPORTING, MIGRATING, and NODE states) + */ + parseCommand(parser3, slot, state, nodeId) { + parser3.push("CLUSTER", "SETSLOT", slot.toString(), state); + if (nodeId) { + parser3.push(nodeId); } - return this.#continueDecodeDoubleExponent(false, double, 0, chunk); + }, + transformReply: void 0 + }; + } +}); +var require_CLUSTER_SLOTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SLOTS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns information about which Redis Cluster node handles which hash slots + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("CLUSTER", "SLOTS"); + }, + transformReply(reply) { + return reply.map(([from3, to, master, ...replicas]) => ({ + from: from3, + to, + master: transformNode(master), + replicas: replicas.map(transformNode) + })); } - #continueDecodeDoubleExponent(isNegative, double, exponent, chunk) { - let cursor = this.#cursor; - do { - const byte = chunk[cursor]; - if (byte === ASCII["\r"]) { - this.#cursor = cursor + 2; - return double * 10 ** (isNegative ? -exponent : exponent); - } - exponent = exponent * 10 + byte - ASCII["0"]; - } while (++cursor < chunk.length); - this.#cursor = cursor; - return this.#continueDecodeDoubleExponent.bind(this, isNegative, double, exponent); + }; + function transformNode(node) { + const [host, port, id] = node; + return { + host, + port, + id + }; + } + } +}); +var require_COMMAND_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_COUNT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the total number of commands available in the Redis server + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("COMMAND", "COUNT"); + }, + transformReply: void 0 + }; + } +}); +var require_COMMAND_GETKEYS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_GETKEYS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Extracts the key names from a Redis command + * @param parser - The Redis command parser + * @param args - Command arguments to analyze + */ + parseCommand(parser3, args) { + parser3.push("COMMAND", "GETKEYS"); + parser3.push(...args); + }, + transformReply: void 0 + }; + } +}); +var require_COMMAND_GETKEYSANDFLAGS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_GETKEYSANDFLAGS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Extracts the key names and access flags from a Redis command + * @param parser - The Redis command parser + * @param args - Command arguments to analyze + */ + parseCommand(parser3, args) { + parser3.push("COMMAND", "GETKEYSANDFLAGS"); + parser3.push(...args); + }, + transformReply(reply) { + return reply.map((entry) => { + const [key, flags] = entry; + return { + key, + flags + }; + }); } - #findCRLF(chunk, cursor) { - while (chunk[cursor] !== ASCII["\r"]) { - if (++cursor === chunk.length) { - this.#cursor = chunk.length; - return -1; - } - } - this.#cursor = cursor + 2; - return cursor; + }; + } +}); +var require_COMMAND_INFO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns details about specific Redis commands + * @param parser - The Redis command parser + * @param commands - Array of command names to get information about + */ + parseCommand(parser3, commands) { + parser3.push("COMMAND", "INFO", ...commands); + }, + // TODO: This works, as we don't currently handle any of the items returned as a map + transformReply(reply) { + return reply.map((command2) => command2 ? (0, generic_transformers_1.transformCommandReply)(command2) : null); } - #decodeSimpleString(type, chunk) { - const start = this.#cursor, crlfIndex = this.#findCRLF(chunk, start); - if (crlfIndex === -1) { - return this.#continueDecodeSimpleString.bind(this, [chunk.subarray(start)], type); + }; + } +}); +var require_COMMAND_LIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_LIST.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.COMMAND_LIST_FILTER_BY = void 0; + exports2.COMMAND_LIST_FILTER_BY = { + MODULE: "MODULE", + ACLCAT: "ACLCAT", + PATTERN: "PATTERN" + }; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns a list of all commands supported by the Redis server + * @param parser - The Redis command parser + * @param options - Options for filtering the command list + */ + parseCommand(parser3, options2) { + parser3.push("COMMAND", "LIST"); + if (options2?.FILTERBY) { + parser3.push("FILTERBY", options2.FILTERBY.type, options2.FILTERBY.value); } - const slice = chunk.subarray(start, crlfIndex); - return type === Buffer ? slice : slice.toString(); - } - #continueDecodeSimpleString(chunks, type, chunk) { - const start = this.#cursor, crlfIndex = this.#findCRLF(chunk, start); - if (crlfIndex === -1) { - chunks.push(chunk.subarray(start)); - return this.#continueDecodeSimpleString.bind(this, chunks, type); - } - chunks.push(chunk.subarray(start, crlfIndex)); - const buffer = Buffer.concat(chunks); - return type === Buffer ? buffer : buffer.toString(); - } - #decodeBlobString(type, chunk) { - if (chunk[this.#cursor] === ASCII["-"]) { - this.#cursor += 4; - return null; - } - const length2 = this.#decodeUnsingedNumber(0, chunk); - if (typeof length2 === "function") { - return this.#continueDecodeBlobStringLength.bind(this, length2, type); - } else if (this.#cursor >= chunk.length) { - return this.#decodeBlobStringWithLength.bind(this, length2, type); - } - return this.#decodeBlobStringWithLength(length2, type, chunk); - } - #continueDecodeBlobStringLength(lengthCb, type, chunk) { - const length2 = lengthCb(chunk); - if (typeof length2 === "function") { - return this.#continueDecodeBlobStringLength.bind(this, length2, type); - } else if (this.#cursor >= chunk.length) { - return this.#decodeBlobStringWithLength.bind(this, length2, type); - } - return this.#decodeBlobStringWithLength(length2, type, chunk); - } - #decodeStringWithLength(length2, skip, type, chunk) { - const end = this.#cursor + length2; - if (end >= chunk.length) { - const slice2 = chunk.subarray(this.#cursor); - this.#cursor = chunk.length; - return this.#continueDecodeStringWithLength.bind(this, length2 - slice2.length, [slice2], skip, type); - } - const slice = chunk.subarray(this.#cursor, end); - this.#cursor = end + skip; - return type === Buffer ? slice : slice.toString(); - } - #continueDecodeStringWithLength(length2, chunks, skip, type, chunk) { - const end = this.#cursor + length2; - if (end >= chunk.length) { - const slice = chunk.subarray(this.#cursor); - chunks.push(slice); - this.#cursor = chunk.length; - return this.#continueDecodeStringWithLength.bind(this, length2 - slice.length, chunks, skip, type); - } - chunks.push(chunk.subarray(this.#cursor, end)); - this.#cursor = end + skip; - const buffer = Buffer.concat(chunks); - return type === Buffer ? buffer : buffer.toString(); - } - #decodeBlobStringWithLength(length2, type, chunk) { - return this.#decodeStringWithLength(length2, 2, type, chunk); - } - #decodeVerbatimString(type, chunk) { - return this.#continueDecodeVerbatimStringLength(this.#decodeUnsingedNumber.bind(this, 0), type, chunk); - } - #continueDecodeVerbatimStringLength(lengthCb, type, chunk) { - const length2 = lengthCb(chunk); - return typeof length2 === "function" ? this.#continueDecodeVerbatimStringLength.bind(this, length2, type) : this.#decodeVerbatimStringWithLength(length2, type, chunk); - } - #decodeVerbatimStringWithLength(length2, type, chunk) { - const stringLength = length2 - 4; - if (type === verbatim_string_1.VerbatimString) { - return this.#decodeVerbatimStringFormat(stringLength, chunk); - } - this.#cursor += 4; - return this.#cursor >= chunk.length ? this.#decodeBlobStringWithLength.bind(this, stringLength, type) : this.#decodeBlobStringWithLength(stringLength, type, chunk); - } - #decodeVerbatimStringFormat(stringLength, chunk) { - const formatCb = this.#decodeStringWithLength.bind(this, 3, 1, String); - return this.#cursor >= chunk.length ? this.#continueDecodeVerbatimStringFormat.bind(this, stringLength, formatCb) : this.#continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk); - } - #continueDecodeVerbatimStringFormat(stringLength, formatCb, chunk) { - const format52 = formatCb(chunk); - return typeof format52 === "function" ? this.#continueDecodeVerbatimStringFormat.bind(this, stringLength, format52) : this.#decodeVerbatimStringWithFormat(stringLength, format52, chunk); - } - #decodeVerbatimStringWithFormat(stringLength, format52, chunk) { - return this.#continueDecodeVerbatimStringWithFormat(format52, this.#decodeBlobStringWithLength.bind(this, stringLength, String), chunk); - } - #continueDecodeVerbatimStringWithFormat(format52, stringCb, chunk) { - const string3 = stringCb(chunk); - return typeof string3 === "function" ? this.#continueDecodeVerbatimStringWithFormat.bind(this, format52, string3) : new verbatim_string_1.VerbatimString(format52, string3); - } - #decodeSimpleError(chunk) { - const string3 = this.#decodeSimpleString(String, chunk); - return typeof string3 === "function" ? this.#continueDecodeSimpleError.bind(this, string3) : new errors_1.SimpleError(string3); - } - #continueDecodeSimpleError(stringCb, chunk) { - const string3 = stringCb(chunk); - return typeof string3 === "function" ? this.#continueDecodeSimpleError.bind(this, string3) : new errors_1.SimpleError(string3); - } - #decodeBlobError(chunk) { - const string3 = this.#decodeBlobString(String, chunk); - return typeof string3 === "function" ? this.#continueDecodeBlobError.bind(this, string3) : new errors_1.BlobError(string3); - } - #continueDecodeBlobError(stringCb, chunk) { - const string3 = stringCb(chunk); - return typeof string3 === "function" ? this.#continueDecodeBlobError.bind(this, string3) : new errors_1.BlobError(string3); - } - #decodeNestedType(typeMapping, chunk) { - const type = chunk[this.#cursor]; - return ++this.#cursor === chunk.length ? this.#decodeNestedTypeValue.bind(this, type, typeMapping) : this.#decodeNestedTypeValue(type, typeMapping, chunk); - } - #decodeNestedTypeValue(type, typeMapping, chunk) { - switch (type) { - case exports2.RESP_TYPES.NULL: - return this.#decodeNull(); - case exports2.RESP_TYPES.BOOLEAN: - return this.#decodeBoolean(chunk); - case exports2.RESP_TYPES.NUMBER: - return this.#decodeNumber(typeMapping[exports2.RESP_TYPES.NUMBER], chunk); - case exports2.RESP_TYPES.BIG_NUMBER: - return this.#decodeBigNumber(typeMapping[exports2.RESP_TYPES.BIG_NUMBER], chunk); - case exports2.RESP_TYPES.DOUBLE: - return this.#decodeDouble(typeMapping[exports2.RESP_TYPES.DOUBLE], chunk); - case exports2.RESP_TYPES.SIMPLE_STRING: - return this.#decodeSimpleString(typeMapping[exports2.RESP_TYPES.SIMPLE_STRING], chunk); - case exports2.RESP_TYPES.BLOB_STRING: - return this.#decodeBlobString(typeMapping[exports2.RESP_TYPES.BLOB_STRING], chunk); - case exports2.RESP_TYPES.VERBATIM_STRING: - return this.#decodeVerbatimString(typeMapping[exports2.RESP_TYPES.VERBATIM_STRING], chunk); - case exports2.RESP_TYPES.SIMPLE_ERROR: - return this.#decodeSimpleError(chunk); - case exports2.RESP_TYPES.BLOB_ERROR: - return this.#decodeBlobError(chunk); - case exports2.RESP_TYPES.ARRAY: - return this.#decodeArray(typeMapping, chunk); - case exports2.RESP_TYPES.SET: - return this.#decodeSet(typeMapping, chunk); - case exports2.RESP_TYPES.MAP: - return this.#decodeMap(typeMapping, chunk); - default: - throw new Error(`Unknown RESP type ${type} "${String.fromCharCode(type)}"`); - } - } - #decodeArray(typeMapping, chunk) { - if (chunk[this.#cursor] === ASCII["-"]) { - this.#cursor += 4; - return null; - } - return this.#decodeArrayWithLength(this.#decodeUnsingedNumber(0, chunk), typeMapping, chunk); - } - #decodeArrayWithLength(length2, typeMapping, chunk) { - return typeof length2 === "function" ? this.#continueDecodeArrayLength.bind(this, length2, typeMapping) : this.#decodeArrayItems(new Array(length2), 0, typeMapping, chunk); - } - #continueDecodeArrayLength(lengthCb, typeMapping, chunk) { - return this.#decodeArrayWithLength(lengthCb(chunk), typeMapping, chunk); - } - #decodeArrayItems(array2, filled, typeMapping, chunk) { - for (let i2 = filled; i2 < array2.length; i2++) { - if (this.#cursor >= chunk.length) { - return this.#decodeArrayItems.bind(this, array2, i2, typeMapping); - } - const item = this.#decodeNestedType(typeMapping, chunk); - if (typeof item === "function") { - return this.#continueDecodeArrayItems.bind(this, array2, i2, item, typeMapping); - } - array2[i2] = item; - } - return array2; - } - #continueDecodeArrayItems(array2, filled, itemCb, typeMapping, chunk) { - const item = itemCb(chunk); - if (typeof item === "function") { - return this.#continueDecodeArrayItems.bind(this, array2, filled, item, typeMapping); - } - array2[filled++] = item; - return this.#decodeArrayItems(array2, filled, typeMapping, chunk); - } - #decodeSet(typeMapping, chunk) { - const length2 = this.#decodeUnsingedNumber(0, chunk); - if (typeof length2 === "function") { - return this.#continueDecodeSetLength.bind(this, length2, typeMapping); - } - return this.#decodeSetItems(length2, typeMapping, chunk); - } - #continueDecodeSetLength(lengthCb, typeMapping, chunk) { - const length2 = lengthCb(chunk); - return typeof length2 === "function" ? this.#continueDecodeSetLength.bind(this, length2, typeMapping) : this.#decodeSetItems(length2, typeMapping, chunk); - } - #decodeSetItems(length2, typeMapping, chunk) { - return typeMapping[exports2.RESP_TYPES.SET] === Set ? this.#decodeSetAsSet(/* @__PURE__ */ new Set(), length2, typeMapping, chunk) : this.#decodeArrayItems(new Array(length2), 0, typeMapping, chunk); - } - #decodeSetAsSet(set, remaining, typeMapping, chunk) { - while (remaining > 0) { - if (this.#cursor >= chunk.length) { - return this.#decodeSetAsSet.bind(this, set, remaining, typeMapping); - } - const item = this.#decodeNestedType(typeMapping, chunk); - if (typeof item === "function") { - return this.#continueDecodeSetAsSet.bind(this, set, remaining, item, typeMapping); - } - set.add(item); - --remaining; - } - return set; - } - #continueDecodeSetAsSet(set, remaining, itemCb, typeMapping, chunk) { - const item = itemCb(chunk); - if (typeof item === "function") { - return this.#continueDecodeSetAsSet.bind(this, set, remaining, item, typeMapping); - } - set.add(item); - return this.#decodeSetAsSet(set, remaining - 1, typeMapping, chunk); - } - #decodeMap(typeMapping, chunk) { - const length2 = this.#decodeUnsingedNumber(0, chunk); - if (typeof length2 === "function") { - return this.#continueDecodeMapLength.bind(this, length2, typeMapping); - } - return this.#decodeMapItems(length2, typeMapping, chunk); - } - #continueDecodeMapLength(lengthCb, typeMapping, chunk) { - const length2 = lengthCb(chunk); - return typeof length2 === "function" ? this.#continueDecodeMapLength.bind(this, length2, typeMapping) : this.#decodeMapItems(length2, typeMapping, chunk); - } - #decodeMapItems(length2, typeMapping, chunk) { - switch (typeMapping[exports2.RESP_TYPES.MAP]) { - case Map: - return this.#decodeMapAsMap(/* @__PURE__ */ new Map(), length2, typeMapping, chunk); - case Array: - return this.#decodeArrayItems(new Array(length2 * 2), 0, typeMapping, chunk); - default: - return this.#decodeMapAsObject(/* @__PURE__ */ Object.create(null), length2, typeMapping, chunk); - } - } - #decodeMapAsMap(map, remaining, typeMapping, chunk) { - while (remaining > 0) { - if (this.#cursor >= chunk.length) { - return this.#decodeMapAsMap.bind(this, map, remaining, typeMapping); - } - const key = this.#decodeMapKey(typeMapping, chunk); - if (typeof key === "function") { - return this.#continueDecodeMapKey.bind(this, map, remaining, key, typeMapping); - } - if (this.#cursor >= chunk.length) { - return this.#continueDecodeMapValue.bind(this, map, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); - } - const value = this.#decodeNestedType(typeMapping, chunk); - if (typeof value === "function") { - return this.#continueDecodeMapValue.bind(this, map, remaining, key, value, typeMapping); - } - map.set(key, value); - --remaining; - } - return map; - } - #decodeMapKey(typeMapping, chunk) { - const type = chunk[this.#cursor]; - return ++this.#cursor === chunk.length ? this.#decodeMapKeyValue.bind(this, type, typeMapping) : this.#decodeMapKeyValue(type, typeMapping, chunk); - } - #decodeMapKeyValue(type, typeMapping, chunk) { - switch (type) { - // decode simple string map key as string (and not as buffer) - case exports2.RESP_TYPES.SIMPLE_STRING: - return this.#decodeSimpleString(String, chunk); - // decode blob string map key as string (and not as buffer) - case exports2.RESP_TYPES.BLOB_STRING: - return this.#decodeBlobString(String, chunk); - default: - return this.#decodeNestedTypeValue(type, typeMapping, chunk); - } - } - #continueDecodeMapKey(map, remaining, keyCb, typeMapping, chunk) { - const key = keyCb(chunk); - if (typeof key === "function") { - return this.#continueDecodeMapKey.bind(this, map, remaining, key, typeMapping); - } - if (this.#cursor >= chunk.length) { - return this.#continueDecodeMapValue.bind(this, map, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); - } - const value = this.#decodeNestedType(typeMapping, chunk); - if (typeof value === "function") { - return this.#continueDecodeMapValue.bind(this, map, remaining, key, value, typeMapping); - } - map.set(key, value); - return this.#decodeMapAsMap(map, remaining - 1, typeMapping, chunk); - } - #continueDecodeMapValue(map, remaining, key, valueCb, typeMapping, chunk) { - const value = valueCb(chunk); - if (typeof value === "function") { - return this.#continueDecodeMapValue.bind(this, map, remaining, key, value, typeMapping); - } - map.set(key, value); - return this.#decodeMapAsMap(map, remaining - 1, typeMapping, chunk); - } - #decodeMapAsObject(object2, remaining, typeMapping, chunk) { - while (remaining > 0) { - if (this.#cursor >= chunk.length) { - return this.#decodeMapAsObject.bind(this, object2, remaining, typeMapping); - } - const key = this.#decodeMapKey(typeMapping, chunk); - if (typeof key === "function") { - return this.#continueDecodeMapAsObjectKey.bind(this, object2, remaining, key, typeMapping); - } - if (this.#cursor >= chunk.length) { - return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); - } - const value = this.#decodeNestedType(typeMapping, chunk); - if (typeof value === "function") { - return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, value, typeMapping); - } - object2[key] = value; - --remaining; - } - return object2; - } - #continueDecodeMapAsObjectKey(object2, remaining, keyCb, typeMapping, chunk) { - const key = keyCb(chunk); - if (typeof key === "function") { - return this.#continueDecodeMapAsObjectKey.bind(this, object2, remaining, key, typeMapping); - } - if (this.#cursor >= chunk.length) { - return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, this.#decodeNestedType.bind(this, typeMapping), typeMapping); - } - const value = this.#decodeNestedType(typeMapping, chunk); - if (typeof value === "function") { - return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, value, typeMapping); - } - object2[key] = value; - return this.#decodeMapAsObject(object2, remaining - 1, typeMapping, chunk); - } - #continueDecodeMapAsObjectValue(object2, remaining, key, valueCb, typeMapping, chunk) { - const value = valueCb(chunk); - if (typeof value === "function") { - return this.#continueDecodeMapAsObjectValue.bind(this, object2, remaining, key, value, typeMapping); - } - object2[key] = value; - return this.#decodeMapAsObject(object2, remaining - 1, typeMapping, chunk); + }, + transformReply: void 0 + }; + } +}); +var require_COMMAND = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns an array with details about all Redis commands + * @param parser - The Redis command parser + */ + parseCommand(parser3) { + parser3.push("COMMAND"); + }, + // TODO: This works, as we don't currently handle any of the items returned as a map + transformReply(reply) { + return reply.map(generic_transformers_1.transformCommandReply); } }; - exports2.Decoder = Decoder2; - _a2 = Decoder2; } }); -var require_lua_script = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/lua-script.js"(exports2) { +var require_CONFIG_GET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_GET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.scriptSha1 = exports2.defineScript = void 0; - var node_crypto_1 = __require2("node:crypto"); - function defineScript(script) { - return { - ...script, - SHA1: scriptSha1(script.SCRIPT) - }; - } - exports2.defineScript = defineScript; - function scriptSha1(script) { - return (0, node_crypto_1.createHash)("sha1").update(script).digest("hex"); - } - exports2.scriptSha1 = scriptSha1; + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Gets the values of configuration parameters + * @param parser - The Redis command parser + * @param parameters - Pattern or specific configuration parameter names + */ + parseCommand(parser3, parameters) { + parser3.push("CONFIG", "GET"); + parser3.pushVariadic(parameters); + }, + transformReply: { + 2: generic_transformers_1.transformTuplesReply, + 3: void 0 + } + }; } }); -var require_ACL_CAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_CAT.js"(exports2) { +var require_CONFIG_RESETSTAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_RESETSTAT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Lists ACL categories or commands in a category + * Resets the statistics reported by Redis using the INFO command * @param parser - The Redis command parser - * @param categoryName - Optional category name to filter commands */ - parseCommand(parser3, categoryName) { - parser3.push("ACL", "CAT"); - if (categoryName) { - parser3.push(categoryName); - } + parseCommand(parser3) { + parser3.push("CONFIG", "RESETSTAT"); }, transformReply: void 0 }; } }); -var require_ACL_DELUSER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_DELUSER.js"(exports2) { +var require_CONFIG_REWRITE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_REWRITE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Deletes one or more users from the ACL + * Rewrites the Redis configuration file with the current configuration * @param parser - The Redis command parser - * @param username - Username(s) to delete */ - parseCommand(parser3, username) { - parser3.push("ACL", "DELUSER"); - parser3.pushVariadic(username); + parseCommand(parser3) { + parser3.push("CONFIG", "REWRITE"); }, transformReply: void 0 }; } }); -var require_ACL_DRYRUN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_DRYRUN.js"(exports2) { +var require_CONFIG_SET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_SET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Simulates ACL operations without executing them + * Sets configuration parameters to the specified values * @param parser - The Redis command parser - * @param username - Username to simulate ACL operations for - * @param command - Command arguments to simulate + * @param parameterOrConfig - Either a single parameter name or a configuration object + * @param value - Value for the parameter (when using single parameter format) */ - parseCommand(parser3, username, command2) { - parser3.push("ACL", "DRYRUN", username, ...command2); + parseCommand(parser3, ...[parameterOrConfig, value]) { + parser3.push("CONFIG", "SET"); + if (typeof parameterOrConfig === "string" || parameterOrConfig instanceof Buffer) { + parser3.push(parameterOrConfig, value); + } else { + for (const [key, value2] of Object.entries(parameterOrConfig)) { + parser3.push(key, value2); + } + } }, transformReply: void 0 }; } }); -var require_ACL_GENPASS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_GENPASS.js"(exports2) { +var require_COPY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COPY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Generates a secure password for ACL users + * Copies the value stored at the source key to the destination key * @param parser - The Redis command parser - * @param bits - Optional number of bits for password entropy + * @param source - Source key + * @param destination - Destination key + * @param options - Options for the copy operation */ - parseCommand(parser3, bits) { - parser3.push("ACL", "GENPASS"); - if (bits) { - parser3.push(bits.toString()); + parseCommand(parser3, source, destination, options2) { + parser3.push("COPY"); + parser3.pushKeys([source, destination]); + if (options2?.DB) { + parser3.push("DB", options2.DB.toString()); + } + if (options2?.REPLACE) { + parser3.push("REPLACE"); } }, transformReply: void 0 }; } }); -var require_ACL_GETUSER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_GETUSER.js"(exports2) { +var require_DBSIZE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DBSIZE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns ACL information about a specific user + * Returns the number of keys in the current database * @param parser - The Redis command parser - * @param username - Username to get information for */ - parseCommand(parser3, username) { - parser3.push("ACL", "GETUSER", username); + parseCommand(parser3) { + parser3.push("DBSIZE"); }, - transformReply: { - 2: (reply) => ({ - flags: reply[1], - passwords: reply[3], - commands: reply[5], - keys: reply[7], - channels: reply[9], - selectors: reply[11]?.map((selector) => { - const inferred = selector; - return { - commands: inferred[1], - keys: inferred[3], - channels: inferred[5] - }; - }) - }), - 3: void 0 - } + transformReply: void 0 }; } }); -var require_ACL_LIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LIST.js"(exports2) { +var require_DECR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DECR.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Returns all configured ACL users and their permissions + * Decrements the integer value of a key by one * @param parser - The Redis command parser + * @param key - Key to decrement */ - parseCommand(parser3) { - parser3.push("ACL", "LIST"); + parseCommand(parser3, key) { + parser3.push("DECR"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_ACL_LOAD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LOAD.js"(exports2) { +var require_DECRBY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DECRBY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Reloads ACL configuration from the ACL file + * Decrements the integer value of a key by the given number * @param parser - The Redis command parser + * @param key - Key to decrement + * @param decrement - Decrement amount */ - parseCommand(parser3) { - parser3.push("ACL", "LOAD"); + parseCommand(parser3, key, decrement) { + parser3.push("DECRBY"); + parser3.pushKey(key); + parser3.push(decrement.toString()); }, transformReply: void 0 }; } }); -var require_parser = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/parser.js"(exports2) { +var require_DEL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DEL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.BasicCommandParser = void 0; - var BasicCommandParser = class { - #redisArgs = []; - #keys = []; - preserve; - get redisArgs() { - return this.#redisArgs; - } - get keys() { - return this.#keys; + exports2.default = { + IS_READ_ONLY: false, + /** + * Removes the specified keys. A key is ignored if it does not exist + * @param parser - The Redis command parser + * @param keys - One or more keys to delete + */ + parseCommand(parser3, keys) { + parser3.push("DEL"); + parser3.pushKeys(keys); + }, + transformReply: void 0 + }; + } +}); +var require_DUMP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DUMP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns a serialized version of the value stored at the key + * @param parser - The Redis command parser + * @param key - Key to dump + */ + parseCommand(parser3, key) { + parser3.push("DUMP"); + parser3.pushKey(key); + }, + transformReply: void 0 + }; + } +}); +var require_ECHO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ECHO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the given string + * @param parser - The Redis command parser + * @param message - Message to echo back + */ + parseCommand(parser3, message) { + parser3.push("ECHO", message); + }, + transformReply: void 0 + }; + } +}); +var require_EVAL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVAL.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseEvalArguments = void 0; + function parseEvalArguments(parser3, script, options2) { + parser3.push(script); + if (options2?.keys) { + parser3.pushKeysLength(options2.keys); + } else { + parser3.push("0"); } - get firstKey() { - return this.#keys[0]; + if (options2?.arguments) { + parser3.push(...options2.arguments); } - get cacheKey() { - const tmp = new Array(this.#redisArgs.length * 2); - for (let i2 = 0; i2 < this.#redisArgs.length; i2++) { - tmp[i2] = this.#redisArgs[i2].length; - tmp[i2 + this.#redisArgs.length] = this.#redisArgs[i2]; - } - return tmp.join("_"); + } + exports2.parseEvalArguments = parseEvalArguments; + exports2.default = { + IS_READ_ONLY: false, + /** + * Executes a Lua script server side + * @param parser - The Redis command parser + * @param script - Lua script to execute + * @param options - Script execution options including keys and arguments + */ + parseCommand(...args) { + args[0].push("EVAL"); + parseEvalArguments(...args); + }, + transformReply: void 0 + }; + } +}); +var require_EVAL_RO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVAL_RO.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - push(...arg) { - this.#redisArgs.push(...arg); + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - pushVariadic(vals) { - if (Array.isArray(vals)) { - for (const val of vals) { - this.push(val); - } - } else { - this.push(vals); - } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var EVAL_1 = __importStar(require_EVAL()); + exports2.default = { + IS_READ_ONLY: true, + /** + * Executes a read-only Lua script server side + * @param parser - The Redis command parser + * @param script - Lua script to execute + * @param options - Script execution options including keys and arguments + */ + parseCommand(...args) { + args[0].push("EVAL_RO"); + (0, EVAL_1.parseEvalArguments)(...args); + }, + transformReply: EVAL_1.default.transformReply + }; + } +}); +var require_EVALSHA_RO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVALSHA_RO.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - pushVariadicWithLength(vals) { - if (Array.isArray(vals)) { - this.#redisArgs.push(vals.length.toString()); - } else { - this.#redisArgs.push("1"); - } - this.pushVariadic(vals); + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - pushVariadicNumber(vals) { - if (Array.isArray(vals)) { - for (const val of vals) { - this.push(val.toString()); - } - } else { - this.push(vals.toString()); - } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var EVAL_1 = __importStar(require_EVAL()); + exports2.default = { + IS_READ_ONLY: true, + /** + * Executes a read-only Lua script server side using the script's SHA1 digest + * @param parser - The Redis command parser + * @param sha1 - SHA1 digest of the script + * @param options - Script execution options including keys and arguments + */ + parseCommand(...args) { + args[0].push("EVALSHA_RO"); + (0, EVAL_1.parseEvalArguments)(...args); + }, + transformReply: EVAL_1.default.transformReply + }; + } +}); +var require_EVALSHA = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVALSHA.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - pushKey(key) { - this.#keys.push(key); - this.#redisArgs.push(key); + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - pushKeysLength(keys) { - if (Array.isArray(keys)) { - this.#redisArgs.push(keys.length.toString()); - } else { - this.#redisArgs.push("1"); + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var EVAL_1 = __importStar(require_EVAL()); + exports2.default = { + IS_READ_ONLY: false, + /** + * Executes a Lua script server side using the script's SHA1 digest + * @param parser - The Redis command parser + * @param sha1 - SHA1 digest of the script + * @param options - Script execution options including keys and arguments + */ + parseCommand(...args) { + args[0].push("EVALSHA"); + (0, EVAL_1.parseEvalArguments)(...args); + }, + transformReply: EVAL_1.default.transformReply + }; + } +}); +var require_GEOADD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOADD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds geospatial items to the specified key + * @param parser - The Redis command parser + * @param key - Key to add the geospatial items to + * @param toAdd - Geospatial member(s) to add + * @param options - Options for the GEOADD command + */ + parseCommand(parser3, key, toAdd, options2) { + parser3.push("GEOADD"); + parser3.pushKey(key); + if (options2?.condition) { + parser3.push(options2.condition); + } else if (options2?.NX) { + parser3.push("NX"); + } else if (options2?.XX) { + parser3.push("XX"); } - this.pushKeys(keys); - } - pushKeys(keys) { - if (Array.isArray(keys)) { - this.#keys.push(...keys); - this.#redisArgs.push(...keys); + if (options2?.CH) { + parser3.push("CH"); + } + if (Array.isArray(toAdd)) { + for (const member of toAdd) { + pushMember(parser3, member); + } } else { - this.#keys.push(keys); - this.#redisArgs.push(keys); + pushMember(parser3, toAdd); + } + }, + transformReply: void 0 + }; + function pushMember(parser3, { longitude, latitude, member }) { + parser3.push(longitude.toString(), latitude.toString(), member); + } + } +}); +var require_GEODIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEODIST.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, + /** + * Returns the distance between two members in a geospatial index + * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param member1 - First member in the geospatial index + * @param member2 - Second member in the geospatial index + * @param unit - Unit of distance (m, km, ft, mi) + */ + parseCommand(parser3, key, member1, member2, unit) { + parser3.push("GEODIST"); + parser3.pushKey(key); + parser3.push(member1, member2); + if (unit) { + parser3.push(unit); } + }, + transformReply(reply) { + return reply === null ? null : Number(reply); } }; - exports2.BasicCommandParser = BasicCommandParser; } }); -var require_generic_transformers = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/generic-transformers.js"(exports2) { +var require_GEOHASH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOHASH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.transformRedisJsonNullReply = exports2.transformRedisJsonReply = exports2.transformRedisJsonArgument = exports2.transformStreamsMessagesReplyResp3 = exports2.transformStreamsMessagesReplyResp2 = exports2.transformStreamMessagesReply = exports2.transformStreamMessageNullReply = exports2.transformStreamMessageReply = exports2.parseArgs = exports2.parseZKeysArguments = exports2.transformRangeReply = exports2.parseSlotRangesArguments = exports2.transformFunctionListItemReply = exports2.RedisFunctionFlags = exports2.transformCommandReply = exports2.CommandCategories = exports2.CommandFlags = exports2.parseOptionalVariadicArgument = exports2.pushVariadicArgument = exports2.pushVariadicNumberArguments = exports2.pushVariadicArguments = exports2.pushEvalArguments = exports2.evalFirstKeyIndex = exports2.transformPXAT = exports2.transformEXAT = exports2.transformSortedSetReply = exports2.transformTuplesReply = exports2.createTransformTuplesReplyFunc = exports2.transformTuplesToMap = exports2.transformNullableDoubleReply = exports2.createTransformNullableDoubleReplyResp2Func = exports2.transformDoubleArrayReply = exports2.createTransformDoubleReplyResp2Func = exports2.transformDoubleReply = exports2.transformStringDoubleArgument = exports2.transformDoubleArgument = exports2.transformBooleanArrayReply = exports2.transformBooleanReply = exports2.isArrayReply = exports2.isNullReply = void 0; - var parser_1 = require_parser(); - var decoder_1 = require_decoder(); - function isNullReply(reply) { - return reply === null; - } - exports2.isNullReply = isNullReply; - function isArrayReply(reply) { - return Array.isArray(reply); - } - exports2.isArrayReply = isArrayReply; - exports2.transformBooleanReply = { - 2: (reply) => reply === 1, - 3: void 0 + exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, + /** + * Returns the Geohash string representation of one or more position members + * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param member - One or more members in the geospatial index + */ + parseCommand(parser3, key, member) { + parser3.push("GEOHASH"); + parser3.pushKey(key); + parser3.pushVariadic(member); + }, + transformReply: void 0 }; - exports2.transformBooleanArrayReply = { - 2: (reply) => { - return reply.map(exports2.transformBooleanReply[2]); + } +}); +var require_GEOPOS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOPOS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, + /** + * Returns the longitude and latitude of one or more members in a geospatial index + * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param member - One or more members in the geospatial index + */ + parseCommand(parser3, key, member) { + parser3.push("GEOPOS"); + parser3.pushKey(key); + parser3.pushVariadic(member); }, - 3: void 0 + transformReply(reply) { + return reply.map((item) => { + const unwrapped = item; + return unwrapped === null ? null : { + longitude: unwrapped[0], + latitude: unwrapped[1] + }; + }); + } }; - function transformDoubleArgument(num) { - switch (num) { - case Infinity: - return "+inf"; - case -Infinity: - return "-inf"; - default: - return num.toString(); + } +}); +var require_GEOSEARCH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOSEARCH.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseGeoSearchOptions = exports2.parseGeoSearchArguments = void 0; + function parseGeoSearchArguments(parser3, key, from3, by, options2) { + parser3.pushKey(key); + if (typeof from3 === "string" || from3 instanceof Buffer) { + parser3.push("FROMMEMBER", from3); + } else { + parser3.push("FROMLONLAT", from3.longitude.toString(), from3.latitude.toString()); } + if ("radius" in by) { + parser3.push("BYRADIUS", by.radius.toString(), by.unit); + } else { + parser3.push("BYBOX", by.width.toString(), by.height.toString(), by.unit); + } + parseGeoSearchOptions(parser3, options2); } - exports2.transformDoubleArgument = transformDoubleArgument; - function transformStringDoubleArgument(num) { - if (typeof num !== "number") - return num; - return transformDoubleArgument(num); - } - exports2.transformStringDoubleArgument = transformStringDoubleArgument; - exports2.transformDoubleReply = { - 2: (reply, preserve, typeMapping) => { - const double = typeMapping ? typeMapping[decoder_1.RESP_TYPES.DOUBLE] : void 0; - switch (double) { - case String: { - return reply; - } - default: { - let ret; - switch (reply.toString()) { - case "inf": - case "+inf": - ret = Infinity; - case "-inf": - ret = -Infinity; - case "nan": - ret = NaN; - default: - ret = Number(reply); - } - return ret; + exports2.parseGeoSearchArguments = parseGeoSearchArguments; + function parseGeoSearchOptions(parser3, options2) { + if (options2?.SORT) { + parser3.push(options2.SORT); + } + if (options2?.COUNT) { + if (typeof options2.COUNT === "number") { + parser3.push("COUNT", options2.COUNT.toString()); + } else { + parser3.push("COUNT", options2.COUNT.value.toString()); + if (options2.COUNT.ANY) { + parser3.push("ANY"); } } - }, - 3: void 0 - }; - function createTransformDoubleReplyResp2Func(preserve, typeMapping) { - return (reply) => { - return exports2.transformDoubleReply[2](reply, preserve, typeMapping); - }; + } } - exports2.createTransformDoubleReplyResp2Func = createTransformDoubleReplyResp2Func; - exports2.transformDoubleArrayReply = { - 2: (reply, preserve, typeMapping) => { - return reply.map(createTransformDoubleReplyResp2Func(preserve, typeMapping)); + exports2.parseGeoSearchOptions = parseGeoSearchOptions; + exports2.default = { + IS_READ_ONLY: true, + /** + * Queries members inside an area of a geospatial index + * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param from - Center point of the search (member name or coordinates) + * @param by - Search area specification (radius or box dimensions) + * @param options - Additional search options + */ + parseCommand(parser3, key, from3, by, options2) { + parser3.push("GEOSEARCH"); + parseGeoSearchArguments(parser3, key, from3, by, options2); }, - 3: void 0 + transformReply: void 0 }; - function createTransformNullableDoubleReplyResp2Func(preserve, typeMapping) { - return (reply) => { - return exports2.transformNullableDoubleReply[2](reply, preserve, typeMapping); - }; - } - exports2.createTransformNullableDoubleReplyResp2Func = createTransformNullableDoubleReplyResp2Func; - exports2.transformNullableDoubleReply = { - 2: (reply, preserve, typeMapping) => { - if (reply === null) - return null; - return exports2.transformDoubleReply[2](reply, preserve, typeMapping); - }, - 3: void 0 - }; - function transformTuplesToMap(reply, func) { - const message = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < reply.length; i2 += 2) { - message[reply[i2].toString()] = func(reply[i2 + 1]); - } - return message; - } - exports2.transformTuplesToMap = transformTuplesToMap; - function createTransformTuplesReplyFunc(preserve, typeMapping) { - return (reply) => { - return transformTuplesReply(reply, preserve, typeMapping); - }; - } - exports2.createTransformTuplesReplyFunc = createTransformTuplesReplyFunc; - function transformTuplesReply(reply, preserve, typeMapping) { - const mapType = typeMapping ? typeMapping[decoder_1.RESP_TYPES.MAP] : void 0; - const inferred = reply; - switch (mapType) { - case Array: { - return reply; - } - case Map: { - const ret = /* @__PURE__ */ new Map(); - for (let i2 = 0; i2 < inferred.length; i2 += 2) { - ret.set(inferred[i2].toString(), inferred[i2 + 1]); - } - return ret; - ; - } - default: { - const ret = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < inferred.length; i2 += 2) { - ret[inferred[i2].toString()] = inferred[i2 + 1]; - } - return ret; - ; - } - } - } - exports2.transformTuplesReply = transformTuplesReply; - exports2.transformSortedSetReply = { - 2: (reply, preserve, typeMapping) => { - const inferred = reply, members = []; - for (let i2 = 0; i2 < inferred.length; i2 += 2) { - members.push({ - value: inferred[i2], - score: exports2.transformDoubleReply[2](inferred[i2 + 1], preserve, typeMapping) - }); - } - return members; - }, - 3: (reply) => { - return reply.map((member) => { - const [value, score] = member; - return { - value, - score - }; - }); - } - }; - function transformEXAT(EXAT) { - return (typeof EXAT === "number" ? EXAT : Math.floor(EXAT.getTime() / 1e3)).toString(); - } - exports2.transformEXAT = transformEXAT; - function transformPXAT(PXAT) { - return (typeof PXAT === "number" ? PXAT : PXAT.getTime()).toString(); - } - exports2.transformPXAT = transformPXAT; - function evalFirstKeyIndex(options2) { - return options2?.keys?.[0]; - } - exports2.evalFirstKeyIndex = evalFirstKeyIndex; - function pushEvalArguments(args, options2) { - if (options2?.keys) { - args.push(options2.keys.length.toString(), ...options2.keys); - } else { - args.push("0"); - } - if (options2?.arguments) { - args.push(...options2.arguments); - } - return args; - } - exports2.pushEvalArguments = pushEvalArguments; - function pushVariadicArguments(args, value) { - if (Array.isArray(value)) { - args = args.concat(value); - } else { - args.push(value); - } - return args; - } - exports2.pushVariadicArguments = pushVariadicArguments; - function pushVariadicNumberArguments(args, value) { - if (Array.isArray(value)) { - for (const item of value) { - args.push(item.toString()); - } - } else { - args.push(value.toString()); - } - return args; - } - exports2.pushVariadicNumberArguments = pushVariadicNumberArguments; - function pushVariadicArgument(args, value) { - if (Array.isArray(value)) { - args.push(value.length.toString(), ...value); - } else { - args.push("1", value); - } - return args; - } - exports2.pushVariadicArgument = pushVariadicArgument; - function parseOptionalVariadicArgument(parser3, name, value) { - if (value === void 0) - return; - parser3.push(name); - parser3.pushVariadicWithLength(value); - } - exports2.parseOptionalVariadicArgument = parseOptionalVariadicArgument; - var CommandFlags; - (function(CommandFlags2) { - CommandFlags2["WRITE"] = "write"; - CommandFlags2["READONLY"] = "readonly"; - CommandFlags2["DENYOOM"] = "denyoom"; - CommandFlags2["ADMIN"] = "admin"; - CommandFlags2["PUBSUB"] = "pubsub"; - CommandFlags2["NOSCRIPT"] = "noscript"; - CommandFlags2["RANDOM"] = "random"; - CommandFlags2["SORT_FOR_SCRIPT"] = "sort_for_script"; - CommandFlags2["LOADING"] = "loading"; - CommandFlags2["STALE"] = "stale"; - CommandFlags2["SKIP_MONITOR"] = "skip_monitor"; - CommandFlags2["ASKING"] = "asking"; - CommandFlags2["FAST"] = "fast"; - CommandFlags2["MOVABLEKEYS"] = "movablekeys"; - })(CommandFlags || (exports2.CommandFlags = CommandFlags = {})); - var CommandCategories; - (function(CommandCategories2) { - CommandCategories2["KEYSPACE"] = "@keyspace"; - CommandCategories2["READ"] = "@read"; - CommandCategories2["WRITE"] = "@write"; - CommandCategories2["SET"] = "@set"; - CommandCategories2["SORTEDSET"] = "@sortedset"; - CommandCategories2["LIST"] = "@list"; - CommandCategories2["HASH"] = "@hash"; - CommandCategories2["STRING"] = "@string"; - CommandCategories2["BITMAP"] = "@bitmap"; - CommandCategories2["HYPERLOGLOG"] = "@hyperloglog"; - CommandCategories2["GEO"] = "@geo"; - CommandCategories2["STREAM"] = "@stream"; - CommandCategories2["PUBSUB"] = "@pubsub"; - CommandCategories2["ADMIN"] = "@admin"; - CommandCategories2["FAST"] = "@fast"; - CommandCategories2["SLOW"] = "@slow"; - CommandCategories2["BLOCKING"] = "@blocking"; - CommandCategories2["DANGEROUS"] = "@dangerous"; - CommandCategories2["CONNECTION"] = "@connection"; - CommandCategories2["TRANSACTION"] = "@transaction"; - CommandCategories2["SCRIPTING"] = "@scripting"; - })(CommandCategories || (exports2.CommandCategories = CommandCategories = {})); - function transformCommandReply([name, arity, flags, firstKeyIndex, lastKeyIndex, step, categories]) { - return { - name, - arity, - flags: new Set(flags), - firstKeyIndex, - lastKeyIndex, - step, - categories: new Set(categories) - }; - } - exports2.transformCommandReply = transformCommandReply; - var RedisFunctionFlags; - (function(RedisFunctionFlags2) { - RedisFunctionFlags2["NO_WRITES"] = "no-writes"; - RedisFunctionFlags2["ALLOW_OOM"] = "allow-oom"; - RedisFunctionFlags2["ALLOW_STALE"] = "allow-stale"; - RedisFunctionFlags2["NO_CLUSTER"] = "no-cluster"; - })(RedisFunctionFlags || (exports2.RedisFunctionFlags = RedisFunctionFlags = {})); - function transformFunctionListItemReply(reply) { - return { - libraryName: reply[1], - engine: reply[3], - functions: reply[5].map((fn) => ({ - name: fn[1], - description: fn[3], - flags: fn[5] - })) - }; - } - exports2.transformFunctionListItemReply = transformFunctionListItemReply; - function parseSlotRangeArguments(parser3, range) { - parser3.push(range.start.toString(), range.end.toString()); - } - function parseSlotRangesArguments(parser3, ranges) { - if (Array.isArray(ranges)) { - for (const range of ranges) { - parseSlotRangeArguments(parser3, range); - } - } else { - parseSlotRangeArguments(parser3, ranges); - } - } - exports2.parseSlotRangesArguments = parseSlotRangesArguments; - function transformRangeReply([start, end]) { - return { - start, - end - }; - } - exports2.transformRangeReply = transformRangeReply; - function parseZKeysArguments(parser3, keys) { - if (Array.isArray(keys)) { - parser3.push(keys.length.toString()); - if (keys.length) { - if (isPlainKeys(keys)) { - parser3.pushKeys(keys); - } else { - for (let i2 = 0; i2 < keys.length; i2++) { - parser3.pushKey(keys[i2].key); - } - parser3.push("WEIGHTS"); - for (let i2 = 0; i2 < keys.length; i2++) { - parser3.push(transformDoubleArgument(keys[i2].weight)); - } - } - } - } else { - parser3.push("1"); - if (isPlainKey(keys)) { - parser3.pushKey(keys); - } else { - parser3.pushKey(keys.key); - parser3.push("WEIGHTS", transformDoubleArgument(keys.weight)); - } - } - } - exports2.parseZKeysArguments = parseZKeysArguments; - function isPlainKey(key) { - return typeof key === "string" || key instanceof Buffer; - } - function isPlainKeys(keys) { - return isPlainKey(keys[0]); - } - function parseArgs2(command2, ...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - if (parser3.preserve) { - redisArgs.preserve = parser3.preserve; - } - return redisArgs; - } - exports2.parseArgs = parseArgs2; - function transformStreamMessageReply(typeMapping, reply) { - const [id, message] = reply; - return { - id, - message: transformTuplesReply(message, void 0, typeMapping) - }; - } - exports2.transformStreamMessageReply = transformStreamMessageReply; - function transformStreamMessageNullReply(typeMapping, reply) { - return isNullReply(reply) ? reply : transformStreamMessageReply(typeMapping, reply); - } - exports2.transformStreamMessageNullReply = transformStreamMessageNullReply; - function transformStreamMessagesReply(r, typeMapping) { - const reply = r; - return reply.map(transformStreamMessageReply.bind(void 0, typeMapping)); - } - exports2.transformStreamMessagesReply = transformStreamMessagesReply; - function transformStreamsMessagesReplyResp2(reply, preserve, typeMapping) { - if (reply === null) - return null; - switch (typeMapping ? typeMapping[decoder_1.RESP_TYPES.MAP] : void 0) { - /* FUTURE: a response type for when resp3 is working properly - case Map: { - const ret = new Map(); - - for (let i=0; i < reply.length; i++) { - const stream = reply[i] as unknown as UnwrapReply; - - const name = stream[0]; - const rawMessages = stream[1]; - - ret.set(name.toString(), transformStreamMessagesReply(rawMessages, typeMapping)); - } - - return ret as unknown as MapReply; - } - case Array: { - const ret: Array = []; - - for (let i=0; i < reply.length; i++) { - const stream = reply[i] as unknown as UnwrapReply; - - const name = stream[0]; - const rawMessages = stream[1]; - - ret.push(name); - ret.push(transformStreamMessagesReply(rawMessages, typeMapping)); - } - - return ret as unknown as MapReply; - } - default: { - const ret: Record = Object.create(null); - - for (let i=0; i < reply.length; i++) { - const stream = reply[i] as unknown as UnwrapReply; - - const name = stream[0] as unknown as UnwrapReply; - const rawMessages = stream[1]; - - ret[name.toString()] = transformStreamMessagesReply(rawMessages); - } - - return ret as unknown as MapReply; - } - */ - // V4 compatible response type - default: { - const ret = []; - for (let i2 = 0; i2 < reply.length; i2++) { - const stream = reply[i2]; - ret.push({ - name: stream[0], - messages: transformStreamMessagesReply(stream[1]) - }); - } - return ret; - } - } - } - exports2.transformStreamsMessagesReplyResp2 = transformStreamsMessagesReplyResp2; - function transformStreamsMessagesReplyResp3(reply) { - if (reply === null) - return null; - if (reply instanceof Map) { - const ret = /* @__PURE__ */ new Map(); - for (const [n, rawMessages] of reply) { - const name = n; - ret.set(name.toString(), transformStreamMessagesReply(rawMessages)); - } - return ret; - } else if (reply instanceof Array) { - const ret = []; - for (let i2 = 0; i2 < reply.length; i2 += 2) { - const name = reply[i2]; - const rawMessages = reply[i2 + 1]; - ret.push(name); - ret.push(transformStreamMessagesReply(rawMessages)); - } - return ret; - } else { - const ret = /* @__PURE__ */ Object.create(null); - for (const [name, rawMessages] of Object.entries(reply)) { - ret[name] = transformStreamMessagesReply(rawMessages); - } - return ret; - } - } - exports2.transformStreamsMessagesReplyResp3 = transformStreamsMessagesReplyResp3; - function transformRedisJsonArgument(json) { - return JSON.stringify(json); - } - exports2.transformRedisJsonArgument = transformRedisJsonArgument; - function transformRedisJsonReply(json) { - const res = JSON.parse(json.toString()); - return res; - } - exports2.transformRedisJsonReply = transformRedisJsonReply; - function transformRedisJsonNullReply(json) { - return isNullReply(json) ? json : transformRedisJsonReply(json); - } - exports2.transformRedisJsonNullReply = transformRedisJsonNullReply; } }); -var require_ACL_LOG = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LOG.js"(exports2) { +var require_GEORADIUS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); + exports2.parseGeoRadiusArguments = void 0; + var GEOSEARCH_1 = require_GEOSEARCH(); + function parseGeoRadiusArguments(parser3, key, from3, radius, unit, options2) { + parser3.pushKey(key); + parser3.push(from3.longitude.toString(), from3.latitude.toString(), radius.toString(), unit); + (0, GEOSEARCH_1.parseGeoSearchOptions)(parser3, options2); + } + exports2.parseGeoRadiusArguments = parseGeoRadiusArguments; exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Returns ACL security events log entries + * Queries members in a geospatial index based on a radius from a center point * @param parser - The Redis command parser - * @param count - Optional maximum number of entries to return + * @param key - Key of the geospatial index + * @param from - Center coordinates for the search + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param options - Additional search options */ - parseCommand(parser3, count) { - parser3.push("ACL", "LOG"); - if (count != void 0) { - parser3.push(count.toString()); - } + parseCommand(...args) { + args[0].push("GEORADIUS"); + return parseGeoRadiusArguments(...args); }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - return reply.map((item) => { - const inferred = item; - return { - count: inferred[1], - reason: inferred[3], - context: inferred[5], - object: inferred[7], - username: inferred[9], - "age-seconds": generic_transformers_1.transformDoubleReply[2](inferred[11], preserve, typeMapping), - "client-info": inferred[13], - "entry-id": inferred[15], - "timestamp-created": inferred[17], - "timestamp-last-updated": inferred[19] - }; - }); - }, - 3: void 0 - } + transformReply: void 0 }; } }); -var require_ACL_LOG_RESET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_LOG_RESET.js"(exports2) { +var require_GEOSEARCH_WITH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOSEARCH_WITH.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var ACL_LOG_1 = __importDefault(require_ACL_LOG()); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: ACL_LOG_1.default.IS_READ_ONLY, - /** - * Clears the ACL security events log - * @param parser - The Redis command parser - */ - parseCommand(parser3) { - parser3.push("ACL", "LOG", "RESET"); - }, - transformReply: void 0 + exports2.GEO_REPLY_WITH = void 0; + var GEOSEARCH_1 = __importDefault(require_GEOSEARCH()); + exports2.GEO_REPLY_WITH = { + DISTANCE: "WITHDIST", + HASH: "WITHHASH", + COORDINATES: "WITHCOORD" }; - } -}); -var require_ACL_SAVE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_SAVE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: GEOSEARCH_1.default.IS_READ_ONLY, /** - * Saves the current ACL configuration to the ACL file + * Queries members inside an area of a geospatial index with additional information * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param from - Center point of the search (member name or coordinates) + * @param by - Search area specification (radius or box dimensions) + * @param replyWith - Information to include with each returned member + * @param options - Additional search options */ - parseCommand(parser3) { - parser3.push("ACL", "SAVE"); + parseCommand(parser3, key, from3, by, replyWith, options2) { + GEOSEARCH_1.default.parseCommand(parser3, key, from3, by, options2); + parser3.push(...replyWith); + parser3.preserve = replyWith; }, - transformReply: void 0 + transformReply(reply, replyWith) { + const replyWithSet = new Set(replyWith); + let index = 0; + const distanceIndex = replyWithSet.has(exports2.GEO_REPLY_WITH.DISTANCE) && ++index, hashIndex = replyWithSet.has(exports2.GEO_REPLY_WITH.HASH) && ++index, coordinatesIndex = replyWithSet.has(exports2.GEO_REPLY_WITH.COORDINATES) && ++index; + return reply.map((raw2) => { + const unwrapped = raw2; + const item = { + member: unwrapped[0] + }; + if (distanceIndex) { + item.distance = unwrapped[distanceIndex]; + } + if (hashIndex) { + item.hash = unwrapped[hashIndex]; + } + if (coordinatesIndex) { + const [longitude, latitude] = unwrapped[coordinatesIndex]; + item.coordinates = { + longitude, + latitude + }; + } + return item; + }); + } }; } }); -var require_ACL_SETUSER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_SETUSER.js"(exports2) { +var require_GEORADIUS_WITH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_WITH.js"(exports2) { "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseGeoRadiusWithArguments = void 0; + var GEORADIUS_1 = __importStar(require_GEORADIUS()); + var GEOSEARCH_WITH_1 = __importDefault(require_GEOSEARCH_WITH()); + function parseGeoRadiusWithArguments(parser3, key, from3, radius, unit, replyWith, options2) { + (0, GEORADIUS_1.parseGeoRadiusArguments)(parser3, key, from3, radius, unit, options2); + parser3.pushVariadic(replyWith); + parser3.preserve = replyWith; + } + exports2.parseGeoRadiusWithArguments = parseGeoRadiusWithArguments; + exports2.default = { + IS_READ_ONLY: GEORADIUS_1.default.IS_READ_ONLY, /** - * Creates or modifies ACL user with specified rules + * Queries members in a geospatial index based on a radius from a center point with additional information * @param parser - The Redis command parser - * @param username - Username to create or modify - * @param rule - ACL rule(s) to apply to the user + * @param key - Key of the geospatial index + * @param from - Center coordinates for the search + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param replyWith - Information to include with each returned member + * @param options - Additional search options */ - parseCommand(parser3, username, rule) { - parser3.push("ACL", "SETUSER", username); - parser3.pushVariadic(rule); + parseCommand(parser3, key, from3, radius, unit, replyWith, options2) { + parser3.push("GEORADIUS"); + parseGeoRadiusWithArguments(parser3, key, from3, radius, unit, replyWith, options2); }, - transformReply: void 0 + transformReply: GEOSEARCH_WITH_1.default.transformReply }; } }); -var require_ACL_USERS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_USERS.js"(exports2) { +var require_GEORADIUS_RO_WITH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_RO_WITH.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var GEORADIUS_WITH_1 = require_GEORADIUS_WITH(); + var GEORADIUS_WITH_2 = __importDefault(require_GEORADIUS_WITH()); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns a list of all configured ACL usernames + * Read-only variant that queries members in a geospatial index based on a radius from a center point with additional information * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param from - Center coordinates for the search + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param replyWith - Information to include with each returned member + * @param options - Additional search options */ - parseCommand(parser3) { - parser3.push("ACL", "USERS"); + parseCommand(...args) { + args[0].push("GEORADIUS_RO"); + (0, GEORADIUS_WITH_1.parseGeoRadiusWithArguments)(...args); }, - transformReply: void 0 + transformReply: GEORADIUS_WITH_2.default.transformReply }; } }); -var require_ACL_WHOAMI = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ACL_WHOAMI.js"(exports2) { +var require_GEORADIUS_RO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_RO.js"(exports2) { "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var GEORADIUS_1 = __importStar(require_GEORADIUS()); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns the username of the current connection + * Read-only variant that queries members in a geospatial index based on a radius from a center point * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param from - Center coordinates for the search + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param options - Additional search options */ - parseCommand(parser3) { - parser3.push("ACL", "WHOAMI"); + parseCommand(...args) { + args[0].push("GEORADIUS_RO"); + (0, GEORADIUS_1.parseGeoRadiusArguments)(...args); + }, + transformReply: GEORADIUS_1.default.transformReply + }; + } +}); +var require_GEORADIUS_STORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_STORE.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var GEORADIUS_1 = __importStar(require_GEORADIUS()); + exports2.default = { + IS_READ_ONLY: GEORADIUS_1.default.IS_READ_ONLY, + /** + * Queries members in a geospatial index based on a radius from a center point and stores the results + * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param from - Center coordinates for the search + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param destination - Key to store the results + * @param options - Additional search and storage options + */ + parseCommand(parser3, key, from3, radius, unit, destination, options2) { + parser3.push("GEORADIUS"); + (0, GEORADIUS_1.parseGeoRadiusArguments)(parser3, key, from3, radius, unit, options2); + if (options2?.STOREDIST) { + parser3.push("STOREDIST"); + parser3.pushKey(destination); + } else { + parser3.push("STORE"); + parser3.pushKey(destination); + } }, transformReply: void 0 }; } }); -var require_APPEND = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/APPEND.js"(exports2) { +var require_GEORADIUSBYMEMBER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseGeoRadiusByMemberArguments = void 0; + var GEOSEARCH_1 = require_GEOSEARCH(); + function parseGeoRadiusByMemberArguments(parser3, key, from3, radius, unit, options2) { + parser3.pushKey(key); + parser3.push(from3, radius.toString(), unit); + (0, GEOSEARCH_1.parseGeoSearchOptions)(parser3, options2); + } + exports2.parseGeoRadiusByMemberArguments = parseGeoRadiusByMemberArguments; exports2.default = { IS_READ_ONLY: false, /** - * Appends a value to a string key + * Queries members in a geospatial index based on a radius from a member * @param parser - The Redis command parser - * @param key - The key to append to - * @param value - The value to append + * @param key - Key of the geospatial index + * @param from - Member name to use as center point + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param options - Additional search options */ - parseCommand(parser3, key, value) { - parser3.push("APPEND", key, value); + parseCommand(parser3, key, from3, radius, unit, options2) { + parser3.push("GEORADIUSBYMEMBER"); + parseGeoRadiusByMemberArguments(parser3, key, from3, radius, unit, options2); }, transformReply: void 0 }; } }); -var require_ASKING = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ASKING.js"(exports2) { +var require_GEORADIUSBYMEMBER_WITH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_WITH.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.ASKING_CMD = void 0; - exports2.ASKING_CMD = "ASKING"; + exports2.parseGeoRadiusByMemberWithArguments = void 0; + var GEORADIUSBYMEMBER_1 = __importDefault(require_GEORADIUSBYMEMBER()); + var GEOSEARCH_1 = require_GEOSEARCH(); + var GEOSEARCH_WITH_1 = __importDefault(require_GEOSEARCH_WITH()); + function parseGeoRadiusByMemberWithArguments(parser3, key, from3, radius, unit, replyWith, options2) { + parser3.pushKey(key); + parser3.push(from3, radius.toString(), unit); + (0, GEOSEARCH_1.parseGeoSearchOptions)(parser3, options2); + parser3.push(...replyWith); + parser3.preserve = replyWith; + } + exports2.parseGeoRadiusByMemberWithArguments = parseGeoRadiusByMemberWithArguments; exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: GEORADIUSBYMEMBER_1.default.IS_READ_ONLY, /** - * Tells a Redis cluster node that the client is ok receiving such redirects + * Queries members in a geospatial index based on a radius from a member with additional information * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param from - Member name to use as center point + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param replyWith - Information to include with each returned member + * @param options - Additional search options */ - parseCommand(parser3) { - parser3.push(exports2.ASKING_CMD); + parseCommand(parser3, key, from3, radius, unit, replyWith, options2) { + parser3.push("GEORADIUSBYMEMBER"); + parseGeoRadiusByMemberWithArguments(parser3, key, from3, radius, unit, replyWith, options2); }, - transformReply: void 0 + transformReply: GEOSEARCH_WITH_1.default.transformReply }; } }); -var require_AUTH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/AUTH.js"(exports2) { +var require_GEORADIUSBYMEMBER_RO_WITH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_RO_WITH.js"(exports2) { "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var GEORADIUSBYMEMBER_WITH_1 = __importStar(require_GEORADIUSBYMEMBER_WITH()); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Authenticates the connection using a password or username and password + * Read-only variant that queries members in a geospatial index based on a radius from a member with additional information * @param parser - The Redis command parser - * @param options - Authentication options containing username and/or password - * @param options.username - Optional username for authentication - * @param options.password - Password for authentication + * @param key - Key of the geospatial index + * @param from - Member name to use as center point + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param withValues - Information to include with each returned member */ - parseCommand(parser3, { username, password }) { - parser3.push("AUTH"); - if (username !== void 0) { - parser3.push(username); - } - parser3.push(password); + parseCommand(...args) { + const parser3 = args[0]; + parser3.push("GEORADIUSBYMEMBER_RO"); + (0, GEORADIUSBYMEMBER_WITH_1.parseGeoRadiusByMemberWithArguments)(...args); }, - transformReply: void 0 + transformReply: GEORADIUSBYMEMBER_WITH_1.default.transformReply }; } }); -var require_BGREWRITEAOF = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BGREWRITEAOF.js"(exports2) { +var require_GEORADIUSBYMEMBER_RO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_RO.js"(exports2) { "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var GEORADIUSBYMEMBER_1 = __importStar(require_GEORADIUSBYMEMBER()); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Asynchronously rewrites the append-only file + * Read-only variant that queries members in a geospatial index based on a radius from a member * @param parser - The Redis command parser + * @param key - Key of the geospatial index + * @param from - Member name to use as center point + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param options - Additional search options */ - parseCommand(parser3) { - parser3.push("BGREWRITEAOF"); + parseCommand(...args) { + const parser3 = args[0]; + parser3.push("GEORADIUSBYMEMBER_RO"); + (0, GEORADIUSBYMEMBER_1.parseGeoRadiusByMemberArguments)(...args); }, - transformReply: void 0 + transformReply: GEORADIUSBYMEMBER_1.default.transformReply }; } }); -var require_BGSAVE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BGSAVE.js"(exports2) { +var require_GEORADIUSBYMEMBER_STORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_STORE.js"(exports2) { "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var GEORADIUSBYMEMBER_1 = __importStar(require_GEORADIUSBYMEMBER()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: GEORADIUSBYMEMBER_1.default.IS_READ_ONLY, /** - * Asynchronously saves the dataset to disk + * Queries members in a geospatial index based on a radius from a member and stores the results * @param parser - The Redis command parser - * @param options - Optional configuration - * @param options.SCHEDULE - Schedule a BGSAVE operation when no BGSAVE is already in progress + * @param key - Key of the geospatial index + * @param from - Member name to use as center point + * @param radius - Radius of the search area + * @param unit - Unit of distance (m, km, ft, mi) + * @param destination - Key to store the results + * @param options - Additional search and storage options */ - parseCommand(parser3, options2) { - parser3.push("BGSAVE"); - if (options2?.SCHEDULE) { - parser3.push("SCHEDULE"); + parseCommand(parser3, key, from3, radius, unit, destination, options2) { + parser3.push("GEORADIUSBYMEMBER"); + (0, GEORADIUSBYMEMBER_1.parseGeoRadiusByMemberArguments)(parser3, key, from3, radius, unit, options2); + if (options2?.STOREDIST) { + parser3.push("STOREDIST"); + parser3.pushKey(destination); + } else { + parser3.push("STORE"); + parser3.pushKey(destination); } }, transformReply: void 0 }; } }); -var require_BITCOUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITCOUNT.js"(exports2) { +var require_GEOSEARCHSTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOSEARCHSTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var GEOSEARCH_1 = require_GEOSEARCH(); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Returns the count of set bits in a string key + * Searches a geospatial index and stores the results in a new sorted set * @param parser - The Redis command parser - * @param key - The key to count bits in - * @param range - Optional range specification - * @param range.start - Start offset in bytes/bits - * @param range.end - End offset in bytes/bits - * @param range.mode - Optional counting mode: BYTE or BIT + * @param destination - Key to store the results + * @param source - Key of the geospatial index to search + * @param from - Center point of the search (member name or coordinates) + * @param by - Search area specification (radius or box dimensions) + * @param options - Additional search and storage options */ - parseCommand(parser3, key, range) { - parser3.push("BITCOUNT"); - parser3.pushKey(key); - if (range) { - parser3.push(range.start.toString()); - parser3.push(range.end.toString()); - if (range.mode) { - parser3.push(range.mode); - } + parseCommand(parser3, destination, source, from3, by, options2) { + parser3.push("GEOSEARCHSTORE"); + if (destination !== void 0) { + parser3.pushKey(destination); + } + (0, GEOSEARCH_1.parseGeoSearchArguments)(parser3, source, from3, by, options2); + if (options2?.STOREDIST) { + parser3.push("STOREDIST"); } }, transformReply: void 0 }; } }); -var require_BITFIELD_RO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITFIELD_RO.js"(exports2) { +var require_GET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { CACHEABLE: true, IS_READ_ONLY: true, /** - * Performs read-only bitfield integer operations on strings + * Gets the value of a key * @param parser - The Redis command parser - * @param key - The key holding the string - * @param operations - Array of GET operations to perform on the bitfield + * @param key - Key to get the value of */ - parseCommand(parser3, key, operations) { - parser3.push("BITFIELD_RO"); + parseCommand(parser3, key) { + parser3.push("GET"); parser3.pushKey(key); - for (const operation of operations) { - parser3.push("GET"); - parser3.push(operation.encoding); - parser3.push(operation.offset.toString()); - } }, transformReply: void 0 }; } }); -var require_BITFIELD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITFIELD.js"(exports2) { +var require_GETBIT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETBIT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Performs arbitrary bitfield integer operations on strings + * Returns the bit value at a given offset in a string value * @param parser - The Redis command parser - * @param key - The key holding the string - * @param operations - Array of bitfield operations to perform: GET, SET, INCRBY or OVERFLOW + * @param key - Key to retrieve the bit from + * @param offset - Bit offset */ - parseCommand(parser3, key, operations) { - parser3.push("BITFIELD"); + parseCommand(parser3, key, offset) { + parser3.push("GETBIT"); parser3.pushKey(key); - for (const options2 of operations) { - switch (options2.operation) { - case "GET": - parser3.push("GET", options2.encoding, options2.offset.toString()); - break; - case "SET": - parser3.push("SET", options2.encoding, options2.offset.toString(), options2.value.toString()); - break; - case "INCRBY": - parser3.push("INCRBY", options2.encoding, options2.offset.toString(), options2.increment.toString()); - break; - case "OVERFLOW": - parser3.push("OVERFLOW", options2.behavior); - break; - } - } + parser3.push(offset.toString()); }, transformReply: void 0 }; } }); -var require_BITOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITOP.js"(exports2) { +var require_GETDEL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETDEL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Performs bitwise operations between strings + * Gets the value of a key and deletes the key * @param parser - The Redis command parser - * @param operation - Bitwise operation to perform: AND, OR, XOR, NOT, DIFF, DIFF1, ANDOR, ONE - * @param destKey - Destination key to store the result - * @param key - Source key(s) to perform operation on + * @param key - Key to get and delete */ - parseCommand(parser3, operation, destKey, key) { - parser3.push("BITOP", operation); - parser3.pushKey(destKey); - parser3.pushKeys(key); + parseCommand(parser3, key) { + parser3.push("GETDEL"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_BITPOS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BITPOS.js"(exports2) { +var require_GETEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETEX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns the position of first bit set to 0 or 1 in a string + * Gets the value of a key and optionally sets its expiration * @param parser - The Redis command parser - * @param key - The key holding the string - * @param bit - The bit value to look for (0 or 1) - * @param start - Optional starting position in bytes/bits - * @param end - Optional ending position in bytes/bits - * @param mode - Optional counting mode: BYTE or BIT + * @param key - Key to get value from + * @param options - Options for setting expiration */ - parseCommand(parser3, key, bit, start, end, mode) { - parser3.push("BITPOS"); + parseCommand(parser3, key, options2) { + parser3.push("GETEX"); parser3.pushKey(key); - parser3.push(bit.toString()); - if (start !== void 0) { - parser3.push(start.toString()); - } - if (end !== void 0) { - parser3.push(end.toString()); - } - if (mode) { - parser3.push(mode); + if ("type" in options2) { + switch (options2.type) { + case "EX": + case "PX": + parser3.push(options2.type, options2.value.toString()); + break; + case "EXAT": + case "PXAT": + parser3.push(options2.type, (0, generic_transformers_1.transformEXAT)(options2.value)); + break; + case "PERSIST": + parser3.push("PERSIST"); + break; + } + } else { + if ("EX" in options2) { + parser3.push("EX", options2.EX.toString()); + } else if ("PX" in options2) { + parser3.push("PX", options2.PX.toString()); + } else if ("EXAT" in options2) { + parser3.push("EXAT", (0, generic_transformers_1.transformEXAT)(options2.EXAT)); + } else if ("PXAT" in options2) { + parser3.push("PXAT", (0, generic_transformers_1.transformPXAT)(options2.PXAT)); + } else { + parser3.push("PERSIST"); + } } }, transformReply: void 0 }; } }); -var require_BLMOVE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BLMOVE.js"(exports2) { +var require_GETRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETRANGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Pop an element from a list, push it to another list and return it; or block until one is available + * Returns a substring of the string stored at a key * @param parser - The Redis command parser - * @param source - Key of the source list - * @param destination - Key of the destination list - * @param sourceSide - Side of source list to pop from (LEFT or RIGHT) - * @param destinationSide - Side of destination list to push to (LEFT or RIGHT) - * @param timeout - Timeout in seconds, 0 to block indefinitely + * @param key - Key to get substring from + * @param start - Start position of the substring + * @param end - End position of the substring */ - parseCommand(parser3, source, destination, sourceSide, destinationSide, timeout) { - parser3.push("BLMOVE"); - parser3.pushKeys([source, destination]); - parser3.push(sourceSide, destinationSide, timeout.toString()); + parseCommand(parser3, key, start, end) { + parser3.push("GETRANGE"); + parser3.pushKey(key); + parser3.push(start.toString(), end.toString()); }, transformReply: void 0 }; } }); -var require_LMPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LMPOP.js"(exports2) { +var require_GETSET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETSET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseLMPopArguments = void 0; - function parseLMPopArguments(parser3, keys, side, options2) { - parser3.pushKeysLength(keys); - parser3.push(side); - if (options2?.COUNT !== void 0) { - parser3.push("COUNT", options2.COUNT.toString()); - } - } - exports2.parseLMPopArguments = parseLMPopArguments; exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Constructs the LMPOP command - * - * @param parser - The command parser - * @param args - Arguments including keys, side (LEFT or RIGHT), and options - * @see https://redis.io/commands/lmpop/ + * Sets a key to a new value and returns its old value + * @param parser - The Redis command parser + * @param key - Key to set + * @param value - Value to set */ - parseCommand(parser3, ...args) { - parser3.push("LMPOP"); - parseLMPopArguments(parser3, ...args); + parseCommand(parser3, key, value) { + parser3.push("GETSET"); + parser3.pushKey(key); + parser3.push(value); }, transformReply: void 0 }; } }); -var require_BLMPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BLMPOP.js"(exports2) { +var require_EXISTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXISTS.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var LMPOP_1 = __importStar(require_LMPOP()); exports2.default = { - IS_READ_ONLY: false, + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Pops elements from multiple lists; blocks until elements are available + * Determines if the specified keys exist * @param parser - The Redis command parser - * @param timeout - Timeout in seconds, 0 to block indefinitely - * @param args - Additional arguments for LMPOP command + * @param keys - One or more keys to check */ - parseCommand(parser3, timeout, ...args) { - parser3.push("BLMPOP", timeout.toString()); - (0, LMPOP_1.parseLMPopArguments)(parser3, ...args); + parseCommand(parser3, keys) { + parser3.push("EXISTS"); + parser3.pushKeys(keys); }, - transformReply: LMPOP_1.default.transformReply + transformReply: void 0 }; } }); -var require_BLPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BLPOP.js"(exports2) { +var require_EXPIRE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXPIRE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, /** - * Removes and returns the first element in a list, or blocks until one is available + * Sets a timeout on key. After the timeout has expired, the key will be automatically deleted * @param parser - The Redis command parser - * @param key - Key of the list to pop from, or array of keys to try sequentially - * @param timeout - Maximum seconds to block, 0 to block indefinitely + * @param key - Key to set expiration on + * @param seconds - Number of seconds until key expiration + * @param mode - Expiration mode: NX (only if key has no expiry), XX (only if key has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) */ - parseCommand(parser3, key, timeout) { - parser3.push("BLPOP"); - parser3.pushKeys(key); - parser3.push(timeout.toString()); + parseCommand(parser3, key, seconds, mode) { + parser3.push("EXPIRE"); + parser3.pushKey(key); + parser3.push(seconds.toString()); + if (mode) { + parser3.push(mode); + } }, - transformReply(reply) { - if (reply === null) - return null; - return { - key: reply[0], - element: reply[1] - }; - } + transformReply: void 0 }; } }); -var require_BRPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BRPOP.js"(exports2) { +var require_EXPIREAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXPIREAT.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + /** + * Sets the expiration for a key at a specific Unix timestamp + * @param parser - The Redis command parser + * @param key - Key to set expiration on + * @param timestamp - Unix timestamp (seconds since January 1, 1970) or Date object + * @param mode - Expiration mode: NX (only if key has no expiry), XX (only if key has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) + */ + parseCommand(parser3, key, timestamp, mode) { + parser3.push("EXPIREAT"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformEXAT)(timestamp)); + if (mode) { + parser3.push(mode); + } + }, + transformReply: void 0 }; + } +}); +var require_EXPIRETIME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXPIRETIME.js"(exports2) { + "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var BLPOP_1 = __importDefault(require_BLPOP()); exports2.default = { IS_READ_ONLY: true, /** - * Removes and returns the last element in a list, or blocks until one is available + * Returns the absolute Unix timestamp (since January 1, 1970) at which the given key will expire * @param parser - The Redis command parser - * @param key - Key of the list to pop from, or array of keys to try sequentially - * @param timeout - Maximum seconds to block, 0 to block indefinitely + * @param key - Key to check expiration time */ - parseCommand(parser3, key, timeout) { - parser3.push("BRPOP"); - parser3.pushKeys(key); - parser3.push(timeout.toString()); + parseCommand(parser3, key) { + parser3.push("EXPIRETIME"); + parser3.pushKey(key); }, - transformReply: BLPOP_1.default.transformReply + transformReply: void 0 }; } }); -var require_BRPOPLPUSH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BRPOPLPUSH.js"(exports2) { +var require_FLUSHALL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FLUSHALL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.REDIS_FLUSH_MODES = void 0; + exports2.REDIS_FLUSH_MODES = { + ASYNC: "ASYNC", + SYNC: "SYNC" + }; exports2.default = { + NOT_KEYED_COMMAND: true, IS_READ_ONLY: false, /** - * Pops an element from a list, pushes it to another list and returns it; blocks until element is available + * Removes all keys from all databases * @param parser - The Redis command parser - * @param source - Key of the source list to pop from - * @param destination - Key of the destination list to push to - * @param timeout - Maximum seconds to block, 0 to block indefinitely + * @param mode - Optional flush mode (ASYNC or SYNC) */ - parseCommand(parser3, source, destination, timeout) { - parser3.push("BRPOPLPUSH"); - parser3.pushKeys([source, destination]); - parser3.push(timeout.toString()); + parseCommand(parser3, mode) { + parser3.push("FLUSHALL"); + if (mode) { + parser3.push(mode); + } }, transformReply: void 0 }; } }); -var require_ZMPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZMPOP.js"(exports2) { +var require_FLUSHDB = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FLUSHDB.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseZMPopArguments = void 0; - var generic_transformers_1 = require_generic_transformers(); - function parseZMPopArguments(parser3, keys, side, options2) { - parser3.pushKeysLength(keys); - parser3.push(side); - if (options2?.COUNT) { - parser3.push("COUNT", options2.COUNT.toString()); - } - } - exports2.parseZMPopArguments = parseZMPopArguments; exports2.default = { + NOT_KEYED_COMMAND: true, IS_READ_ONLY: false, /** - * Removes and returns up to count members with the highest/lowest scores from the first non-empty sorted set. - * @param parser - The Redis command parser. - * @param keys - Keys of the sorted sets to pop from. - * @param side - Side to pop from (MIN or MAX). - * @param options - Optional parameters including COUNT. + * Removes all keys from the current database + * @param parser - The Redis command parser + * @param mode - Optional flush mode (ASYNC or SYNC) */ - parseCommand(parser3, keys, side, options2) { - parser3.push("ZMPOP"); - parseZMPopArguments(parser3, keys, side, options2); - }, - transformReply: { - 2(reply, preserve, typeMapping) { - return reply === null ? null : { - key: reply[0], - members: reply[1].map((member) => { - const [value, score] = member; - return { - value, - score: generic_transformers_1.transformDoubleReply[2](score, preserve, typeMapping) - }; - }) - }; - }, - 3(reply) { - return reply === null ? null : { - key: reply[0], - members: generic_transformers_1.transformSortedSetReply[3](reply[1]) - }; + parseCommand(parser3, mode) { + parser3.push("FLUSHDB"); + if (mode) { + parser3.push(mode); } - } + }, + transformReply: void 0 }; } }); -var require_BZMPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BZMPOP.js"(exports2) { +var require_FCALL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FCALL.js"(exports2) { "use strict"; var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { if (k2 === void 0) k2 = k; @@ -34677,2741 +29693,2532 @@ var require_BZMPOP = __commonJS({ return result; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var ZMPOP_1 = __importStar(require_ZMPOP()); + var EVAL_1 = __importStar(require_EVAL()); exports2.default = { IS_READ_ONLY: false, /** - * Removes and returns members from one or more sorted sets in the specified order; blocks until elements are available + * Invokes a Redis function * @param parser - The Redis command parser - * @param timeout - Maximum seconds to block, 0 to block indefinitely - * @param args - Additional arguments specifying the keys, min/max count, and order (MIN/MAX) + * @param functionName - Name of the function to call + * @param options - Function execution options including keys and arguments */ - parseCommand(parser3, timeout, ...args) { - parser3.push("BZMPOP", timeout.toString()); - (0, ZMPOP_1.parseZMPopArguments)(parser3, ...args); + parseCommand(...args) { + args[0].push("FCALL"); + (0, EVAL_1.parseEvalArguments)(...args); }, - transformReply: ZMPOP_1.default.transformReply + transformReply: EVAL_1.default.transformReply }; } }); -var require_BZPOPMAX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BZPOPMAX.js"(exports2) { +var require_FCALL_RO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FCALL_RO.js"(exports2) { "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes and returns the member with the highest score in a sorted set, or blocks until one is available - * @param parser - The Redis command parser - * @param keys - Key of the sorted set, or array of keys to try sequentially - * @param timeout - Maximum seconds to block, 0 to block indefinitely - */ - parseCommand(parser3, keys, timeout) { - parser3.push("BZPOPMAX"); - parser3.pushKeys(keys); - parser3.push(timeout.toString()); - }, - transformReply: { - 2(reply, preserve, typeMapping) { - return reply === null ? null : { - key: reply[0], - value: reply[1], - score: generic_transformers_1.transformDoubleReply[2](reply[2], preserve, typeMapping) - }; - }, - 3(reply) { - return reply === null ? null : { - key: reply[0], - value: reply[1], - score: reply[2] - }; - } + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - }; - } -}); -var require_BZPOPMIN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/BZPOPMIN.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var BZPOPMAX_1 = __importDefault(require_BZPOPMAX()); + var EVAL_1 = __importStar(require_EVAL()); exports2.default = { - IS_READ_ONLY: BZPOPMAX_1.default.IS_READ_ONLY, + IS_READ_ONLY: false, /** - * Removes and returns the member with the lowest score in a sorted set, or blocks until one is available + * Invokes a read-only Redis function * @param parser - The Redis command parser - * @param keys - Key of the sorted set, or array of keys to try sequentially - * @param timeout - Maximum seconds to block, 0 to block indefinitely + * @param functionName - Name of the function to call + * @param options - Function execution options including keys and arguments */ - parseCommand(parser3, keys, timeout) { - parser3.push("BZPOPMIN"); - parser3.pushKeys(keys); - parser3.push(timeout.toString()); + parseCommand(...args) { + args[0].push("FCALL_RO"); + (0, EVAL_1.parseEvalArguments)(...args); }, - transformReply: BZPOPMAX_1.default.transformReply + transformReply: EVAL_1.default.transformReply }; } }); -var require_CLIENT_CACHING = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_CACHING.js"(exports2) { +var require_FUNCTION_DELETE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_DELETE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Instructs the server about tracking or not keys in the next request + * Deletes a library and all its functions * @param parser - The Redis command parser - * @param value - Whether to enable (true) or disable (false) tracking + * @param library - Name of the library to delete */ - parseCommand(parser3, value) { - parser3.push("CLIENT", "CACHING", value ? "YES" : "NO"); + parseCommand(parser3, library) { + parser3.push("FUNCTION", "DELETE", library); }, transformReply: void 0 }; } }); -var require_CLIENT_GETNAME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_GETNAME.js"(exports2) { +var require_FUNCTION_DUMP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_DUMP.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the name of the current connection + * Returns a serialized payload representing the current functions loaded in the server * @param parser - The Redis command parser */ parseCommand(parser3) { - parser3.push("CLIENT", "GETNAME"); + parser3.push("FUNCTION", "DUMP"); }, transformReply: void 0 }; } }); -var require_CLIENT_GETREDIR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_GETREDIR.js"(exports2) { +var require_FUNCTION_FLUSH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_FLUSH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Returns the ID of the client to which the current client is redirecting tracking notifications + * Deletes all the libraries and functions from a Redis server * @param parser - The Redis command parser + * @param mode - Optional flush mode (ASYNC or SYNC) */ - parseCommand(parser3) { - parser3.push("CLIENT", "GETREDIR"); + parseCommand(parser3, mode) { + parser3.push("FUNCTION", "FLUSH"); + if (mode) { + parser3.push(mode); + } }, transformReply: void 0 }; } }); -var require_CLIENT_ID = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_ID.js"(exports2) { +var require_FUNCTION_KILL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_KILL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the client ID for the current connection + * Kills a function that is currently executing * @param parser - The Redis command parser */ parseCommand(parser3) { - parser3.push("CLIENT", "ID"); + parser3.push("FUNCTION", "KILL"); }, transformReply: void 0 }; } }); -var require_CLIENT_INFO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_INFO.js"(exports2) { +var require_FUNCTION_LIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_LIST.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var CLIENT_INFO_REGEX = /([^\s=]+)=([^\s]*)/g; exports2.default = { NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Returns information and statistics about the current client connection + * Returns all libraries and functions * @param parser - The Redis command parser + * @param options - Options for listing functions */ - parseCommand(parser3) { - parser3.push("CLIENT", "INFO"); - }, - transformReply(rawReply) { - const map = {}; - for (const item of rawReply.toString().matchAll(CLIENT_INFO_REGEX)) { - map[item[1]] = item[2]; - } - const reply = { - id: Number(map.id), - addr: map.addr, - fd: Number(map.fd), - name: map.name, - age: Number(map.age), - idle: Number(map.idle), - flags: map.flags, - db: Number(map.db), - sub: Number(map.sub), - psub: Number(map.psub), - multi: Number(map.multi), - qbuf: Number(map.qbuf), - qbufFree: Number(map["qbuf-free"]), - argvMem: Number(map["argv-mem"]), - obl: Number(map.obl), - oll: Number(map.oll), - omem: Number(map.omem), - totMem: Number(map["tot-mem"]), - events: map.events, - cmd: map.cmd, - user: map.user, - libName: map["lib-name"], - libVer: map["lib-ver"] - }; - if (map.laddr !== void 0) { - reply.laddr = map.laddr; - } - if (map.redir !== void 0) { - reply.redir = Number(map.redir); - } - if (map.ssub !== void 0) { - reply.ssub = Number(map.ssub); - } - if (map["multi-mem"] !== void 0) { - reply.multiMem = Number(map["multi-mem"]); - } - if (map.resp !== void 0) { - reply.resp = Number(map.resp); - } - return reply; - } - }; - } -}); -var require_CLIENT_KILL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_KILL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.CLIENT_KILL_FILTERS = void 0; - exports2.CLIENT_KILL_FILTERS = { - ADDRESS: "ADDR", - LOCAL_ADDRESS: "LADDR", - ID: "ID", - TYPE: "TYPE", - USER: "USER", - SKIP_ME: "SKIPME", - MAXAGE: "MAXAGE" - }; - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Closes client connections matching the specified filters - * @param parser - The Redis command parser - * @param filters - One or more filters to match client connections to kill - */ - parseCommand(parser3, filters) { - parser3.push("CLIENT", "KILL"); - if (Array.isArray(filters)) { - for (const filter of filters) { - pushFilter(parser3, filter); - } - } else { - pushFilter(parser3, filters); + parseCommand(parser3, options2) { + parser3.push("FUNCTION", "LIST"); + if (options2?.LIBRARYNAME) { + parser3.push("LIBRARYNAME", options2.LIBRARYNAME); } }, - transformReply: void 0 - }; - function pushFilter(parser3, filter) { - if (filter === exports2.CLIENT_KILL_FILTERS.SKIP_ME) { - parser3.push("SKIPME"); - return; - } - parser3.push(filter.filter); - switch (filter.filter) { - case exports2.CLIENT_KILL_FILTERS.ADDRESS: - parser3.push(filter.address); - break; - case exports2.CLIENT_KILL_FILTERS.LOCAL_ADDRESS: - parser3.push(filter.localAddress); - break; - case exports2.CLIENT_KILL_FILTERS.ID: - parser3.push(typeof filter.id === "number" ? filter.id.toString() : filter.id); - break; - case exports2.CLIENT_KILL_FILTERS.TYPE: - parser3.push(filter.type); - break; - case exports2.CLIENT_KILL_FILTERS.USER: - parser3.push(filter.username); - break; - case exports2.CLIENT_KILL_FILTERS.SKIP_ME: - parser3.push(filter.skipMe ? "yes" : "no"); - break; - case exports2.CLIENT_KILL_FILTERS.MAXAGE: - parser3.push(filter.maxAge.toString()); - break; + transformReply: { + 2: (reply) => { + return reply.map((library) => { + const unwrapped = library; + return { + library_name: unwrapped[1], + engine: unwrapped[3], + functions: unwrapped[5].map((fn) => { + const unwrapped2 = fn; + return { + name: unwrapped2[1], + description: unwrapped2[3], + flags: unwrapped2[5] + }; + }) + }; + }); + }, + 3: void 0 } - } + }; } }); -var require_CLIENT_LIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_LIST.js"(exports2) { +var require_FUNCTION_LIST_WITHCODE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_LIST_WITHCODE.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var CLIENT_INFO_1 = __importDefault(require_CLIENT_INFO()); + var FUNCTION_LIST_1 = __importDefault(require_FUNCTION_LIST()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + NOT_KEYED_COMMAND: FUNCTION_LIST_1.default.NOT_KEYED_COMMAND, + IS_READ_ONLY: FUNCTION_LIST_1.default.IS_READ_ONLY, /** - * Returns information about all client connections. Can be filtered by type or ID + * Returns all libraries and functions including their source code * @param parser - The Redis command parser - * @param filter - Optional filter to return only specific client types or IDs + * @param options - Options for listing functions */ - parseCommand(parser3, filter) { - parser3.push("CLIENT", "LIST"); - if (filter) { - if (filter.TYPE !== void 0) { - parser3.push("TYPE", filter.TYPE); - } else { - parser3.push("ID"); - parser3.pushVariadic(filter.ID); - } - } + parseCommand(...args) { + FUNCTION_LIST_1.default.parseCommand(...args); + args[0].push("WITHCODE"); }, - transformReply(rawReply) { - const split = rawReply.toString().split("\n"), length2 = split.length - 1, reply = []; - for (let i2 = 0; i2 < length2; i2++) { - reply.push(CLIENT_INFO_1.default.transformReply(split[i2])); - } - return reply; + transformReply: { + 2: (reply) => { + return reply.map((library) => { + const unwrapped = library; + return { + library_name: unwrapped[1], + engine: unwrapped[3], + functions: unwrapped[5].map((fn) => { + const unwrapped2 = fn; + return { + name: unwrapped2[1], + description: unwrapped2[3], + flags: unwrapped2[5] + }; + }), + library_code: unwrapped[7] + }; + }); + }, + 3: void 0 } }; } }); -var require_CLIENT_NO_EVICT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_NO-EVICT.js"(exports2) { +var require_FUNCTION_LOAD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_LOAD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Controls whether to prevent the client's connections from being evicted + * Loads a library to Redis * @param parser - The Redis command parser - * @param value - Whether to enable (true) or disable (false) the no-evict mode + * @param code - Library code to load + * @param options - Function load options */ - parseCommand(parser3, value) { - parser3.push("CLIENT", "NO-EVICT", value ? "ON" : "OFF"); + parseCommand(parser3, code2, options2) { + parser3.push("FUNCTION", "LOAD"); + if (options2?.REPLACE) { + parser3.push("REPLACE"); + } + parser3.push(code2); }, transformReply: void 0 }; } }); -var require_CLIENT_NO_TOUCH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_NO-TOUCH.js"(exports2) { +var require_FUNCTION_RESTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_RESTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Controls whether to prevent the client from touching the LRU/LFU of keys + * Restores libraries from the dump payload * @param parser - The Redis command parser - * @param value - Whether to enable (true) or disable (false) the no-touch mode + * @param dump - Serialized payload of functions to restore + * @param options - Options for the restore operation */ - parseCommand(parser3, value) { - parser3.push("CLIENT", "NO-TOUCH", value ? "ON" : "OFF"); + parseCommand(parser3, dump, options2) { + parser3.push("FUNCTION", "RESTORE", dump); + if (options2?.mode) { + parser3.push(options2.mode); + } }, transformReply: void 0 }; } }); -var require_CLIENT_PAUSE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_PAUSE.js"(exports2) { +var require_FUNCTION_STATS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_STATS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Stops the server from processing client commands for the specified duration + * Returns information about the function that is currently running and information about the available execution engines * @param parser - The Redis command parser - * @param timeout - Time in milliseconds to pause command processing - * @param mode - Optional mode: 'WRITE' to pause only write commands, 'ALL' to pause all commands */ - parseCommand(parser3, timeout, mode) { - parser3.push("CLIENT", "PAUSE", timeout.toString()); - if (mode) { - parser3.push(mode); - } + parseCommand(parser3) { + parser3.push("FUNCTION", "STATS"); }, - transformReply: void 0 + transformReply: { + 2: (reply) => { + return { + running_script: transformRunningScript(reply[1]), + engines: transformEngines(reply[3]) + }; + }, + 3: void 0 + } }; + function transformRunningScript(reply) { + if ((0, generic_transformers_1.isNullReply)(reply)) { + return null; + } + const unwraped = reply; + return { + name: unwraped[1], + command: unwraped[3], + duration_ms: unwraped[5] + }; + } + function transformEngines(reply) { + const unwraped = reply; + const engines = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < unwraped.length; i2++) { + const name = unwraped[i2], stats = unwraped[++i2], unwrapedStats = stats; + engines[name.toString()] = { + libraries_count: unwrapedStats[1], + functions_count: unwrapedStats[3] + }; + } + return engines; + } } }); -var require_CLIENT_SETNAME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_SETNAME.js"(exports2) { +var require_HDEL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HDEL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Assigns a name to the current connection + * Removes one or more fields from a hash * @param parser - The Redis command parser - * @param name - The name to assign to the connection + * @param key - Key of the hash + * @param field - Field(s) to remove */ - parseCommand(parser3, name) { - parser3.push("CLIENT", "SETNAME", name); + parseCommand(parser3, key, field) { + parser3.push("HDEL"); + parser3.pushKey(key); + parser3.pushVariadic(field); }, transformReply: void 0 }; } }); -var require_CLIENT_TRACKING = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_TRACKING.js"(exports2) { +var require_HELLO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HELLO.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Controls server-assisted client side caching for the current connection + * Handshakes with the Redis server and switches to the specified protocol version * @param parser - The Redis command parser - * @param mode - Whether to enable (true) or disable (false) tracking - * @param options - Optional configuration including REDIRECT, BCAST, PREFIX, OPTIN, OPTOUT, and NOLOOP options + * @param protover - Protocol version to use + * @param options - Additional options for authentication and connection naming */ - parseCommand(parser3, mode, options2) { - parser3.push("CLIENT", "TRACKING", mode ? "ON" : "OFF"); - if (mode) { - if (options2?.REDIRECT) { - parser3.push("REDIRECT", options2.REDIRECT.toString()); - } - if (isBroadcast(options2)) { - parser3.push("BCAST"); - if (options2?.PREFIX) { - if (Array.isArray(options2.PREFIX)) { - for (const prefix of options2.PREFIX) { - parser3.push("PREFIX", prefix); - } - } else { - parser3.push("PREFIX", options2.PREFIX); - } - } - } else if (isOptIn(options2)) { - parser3.push("OPTIN"); - } else if (isOptOut(options2)) { - parser3.push("OPTOUT"); + parseCommand(parser3, protover, options2) { + parser3.push("HELLO"); + if (protover) { + parser3.push(protover.toString()); + if (options2?.AUTH) { + parser3.push("AUTH", options2.AUTH.username, options2.AUTH.password); } - if (options2?.NOLOOP) { - parser3.push("NOLOOP"); + if (options2?.SETNAME) { + parser3.push("SETNAME", options2.SETNAME); } } }, - transformReply: void 0 - }; - function isBroadcast(options2) { - return options2?.BCAST === true; - } - function isOptIn(options2) { - return options2?.OPTIN === true; - } - function isOptOut(options2) { - return options2?.OPTOUT === true; - } - } -}); -var require_CLIENT_TRACKINGINFO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_TRACKINGINFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Returns information about the current connection's key tracking state - * @param parser - The Redis command parser - */ - parseCommand(parser3) { - parser3.push("CLIENT", "TRACKINGINFO"); - }, transformReply: { 2: (reply) => ({ - flags: reply[1], - redirect: reply[3], - prefixes: reply[5] + server: reply[1], + version: reply[3], + proto: reply[5], + id: reply[7], + mode: reply[9], + role: reply[11], + modules: reply[13] }), 3: void 0 } }; } }); -var require_CLIENT_UNPAUSE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLIENT_UNPAUSE.js"(exports2) { +var require_HEXISTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXISTS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Resumes processing of client commands after a CLIENT PAUSE + * Determines whether a field exists in a hash * @param parser - The Redis command parser + * @param key - Key of the hash + * @param field - Field to check */ - parseCommand(parser3) { - parser3.push("CLIENT", "UNPAUSE"); + parseCommand(parser3, key, field) { + parser3.push("HEXISTS"); + parser3.pushKey(key); + parser3.push(field); }, transformReply: void 0 }; } }); -var require_CLUSTER_ADDSLOTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_ADDSLOTS.js"(exports2) { +var require_HEXPIRE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXPIRE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.HASH_EXPIRATION = void 0; + exports2.HASH_EXPIRATION = { + /** The field does not exist */ + FIELD_NOT_EXISTS: -2, + /** Specified NX | XX | GT | LT condition not met */ + CONDITION_NOT_MET: 0, + /** Expiration time was set or updated */ + UPDATED: 1, + /** Field deleted because the specified expiration time is in the past */ + DELETED: 2 + }; exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Assigns hash slots to the current node in a Redis Cluster + * Sets a timeout on hash fields. After the timeout has expired, the fields will be automatically deleted * @param parser - The Redis command parser - * @param slots - One or more hash slots to be assigned + * @param key - Key of the hash + * @param fields - Fields to set expiration on + * @param seconds - Number of seconds until field expiration + * @param mode - Expiration mode: NX (only if field has no expiry), XX (only if field has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) */ - parseCommand(parser3, slots) { - parser3.push("CLUSTER", "ADDSLOTS"); - parser3.pushVariadicNumber(slots); + parseCommand(parser3, key, fields, seconds, mode) { + parser3.push("HEXPIRE"); + parser3.pushKey(key); + parser3.push(seconds.toString()); + if (mode) { + parser3.push(mode); + } + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_ADDSLOTSRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_ADDSLOTSRANGE.js"(exports2) { +var require_HEXPIREAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXPIREAT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Assigns hash slot ranges to the current node in a Redis Cluster + * Sets the expiration for hash fields at a specific Unix timestamp * @param parser - The Redis command parser - * @param ranges - One or more slot ranges to be assigned, each specified as [start, end] + * @param key - Key of the hash + * @param fields - Fields to set expiration on + * @param timestamp - Unix timestamp (seconds since January 1, 1970) or Date object + * @param mode - Expiration mode: NX (only if field has no expiry), XX (only if field has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) */ - parseCommand(parser3, ranges) { - parser3.push("CLUSTER", "ADDSLOTSRANGE"); - (0, generic_transformers_1.parseSlotRangesArguments)(parser3, ranges); + parseCommand(parser3, key, fields, timestamp, mode) { + parser3.push("HEXPIREAT"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformEXAT)(timestamp)); + if (mode) { + parser3.push(mode); + } + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_BUMPEPOCH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_BUMPEPOCH.js"(exports2) { +var require_HEXPIRETIME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXPIRETIME.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.HASH_EXPIRATION_TIME = void 0; + exports2.HASH_EXPIRATION_TIME = { + /** The field does not exist */ + FIELD_NOT_EXISTS: -2, + /** The field exists but has no associated expire */ + NO_EXPIRATION: -1 + }; exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Advances the cluster config epoch + * Returns the absolute Unix timestamp (since January 1, 1970) at which the given hash fields will expire * @param parser - The Redis command parser + * @param key - Key of the hash + * @param fields - Fields to check expiration time */ - parseCommand(parser3) { - parser3.push("CLUSTER", "BUMPEPOCH"); + parseCommand(parser3, key, fields) { + parser3.push("HEXPIRETIME"); + parser3.pushKey(key); + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_COUNT_FAILURE_REPORTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_COUNT-FAILURE-REPORTS.js"(exports2) { +var require_HGET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns the number of failure reports for a given node + * Gets the value of a field in a hash * @param parser - The Redis command parser - * @param nodeId - The ID of the node to check + * @param key - Key of the hash + * @param field - Field to get the value of */ - parseCommand(parser3, nodeId) { - parser3.push("CLUSTER", "COUNT-FAILURE-REPORTS", nodeId); + parseCommand(parser3, key, field) { + parser3.push("HGET"); + parser3.pushKey(key); + parser3.push(field); }, transformReply: void 0 }; } }); -var require_CLUSTER_COUNTKEYSINSLOT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_COUNTKEYSINSLOT.js"(exports2) { +var require_HGETALL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGETALL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns the number of keys in the specified hash slot + * Gets all fields and values in a hash * @param parser - The Redis command parser - * @param slot - The hash slot to check + * @param key - Key of the hash */ - parseCommand(parser3, slot) { - parser3.push("CLUSTER", "COUNTKEYSINSLOT", slot.toString()); + parseCommand(parser3, key) { + parser3.push("HGETALL"); + parser3.pushKey(key); }, - transformReply: void 0 + TRANSFORM_LEGACY_REPLY: true, + transformReply: { + 2: generic_transformers_1.transformTuplesReply, + 3: void 0 + } }; } }); -var require_CLUSTER_DELSLOTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_DELSLOTS.js"(exports2) { +var require_HGETDEL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGETDEL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Removes hash slots from the current node in a Redis Cluster + * Gets and deletes the specified fields from a hash * @param parser - The Redis command parser - * @param slots - One or more hash slots to be removed + * @param key - Key of the hash + * @param fields - Fields to get and delete */ - parseCommand(parser3, slots) { - parser3.push("CLUSTER", "DELSLOTS"); - parser3.pushVariadicNumber(slots); + parseCommand(parser3, key, fields) { + parser3.push("HGETDEL"); + parser3.pushKey(key); + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_DELSLOTSRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_DELSLOTSRANGE.js"(exports2) { - "use strict"; +var require_HGETEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGETEX.js"(exports2) { + "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Removes hash slot ranges from the current node in a Redis Cluster + * Gets the values of the specified fields in a hash and optionally sets their expiration * @param parser - The Redis command parser - * @param ranges - One or more slot ranges to be removed, each specified as [start, end] + * @param key - Key of the hash + * @param fields - Fields to get values from + * @param options - Options for setting expiration */ - parseCommand(parser3, ranges) { - parser3.push("CLUSTER", "DELSLOTSRANGE"); - (0, generic_transformers_1.parseSlotRangesArguments)(parser3, ranges); + parseCommand(parser3, key, fields, options2) { + parser3.push("HGETEX"); + parser3.pushKey(key); + if (options2?.expiration) { + if (typeof options2.expiration === "string") { + parser3.push(options2.expiration); + } else if (options2.expiration.type === "PERSIST") { + parser3.push("PERSIST"); + } else { + parser3.push(options2.expiration.type, options2.expiration.value.toString()); + } + } + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_FAILOVER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_FAILOVER.js"(exports2) { +var require_HINCRBY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HINCRBY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.FAILOVER_MODES = void 0; - exports2.FAILOVER_MODES = { - FORCE: "FORCE", - TAKEOVER: "TAKEOVER" - }; exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Forces a replica to perform a manual failover of its master + * Increments the integer value of a field in a hash by the given number * @param parser - The Redis command parser - * @param options - Optional configuration with FORCE or TAKEOVER mode + * @param key - Key of the hash + * @param field - Field to increment + * @param increment - Increment amount */ - parseCommand(parser3, options2) { - parser3.push("CLUSTER", "FAILOVER"); - if (options2?.mode) { - parser3.push(options2.mode); - } + parseCommand(parser3, key, field, increment2) { + parser3.push("HINCRBY"); + parser3.pushKey(key); + parser3.push(field, increment2.toString()); }, transformReply: void 0 }; } }); -var require_CLUSTER_FLUSHSLOTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_FLUSHSLOTS.js"(exports2) { +var require_HINCRBYFLOAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HINCRBYFLOAT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Deletes all hash slots from the current node in a Redis Cluster + * Increments the float value of a field in a hash by the given amount * @param parser - The Redis command parser + * @param key - Key of the hash + * @param field - Field to increment + * @param increment - Increment amount (float) */ - parseCommand(parser3) { - parser3.push("CLUSTER", "FLUSHSLOTS"); + parseCommand(parser3, key, field, increment2) { + parser3.push("HINCRBYFLOAT"); + parser3.pushKey(key); + parser3.push(field, increment2.toString()); }, transformReply: void 0 }; } }); -var require_CLUSTER_FORGET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_FORGET.js"(exports2) { +var require_HKEYS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HKEYS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Removes a node from the cluster + * Gets all field names in a hash * @param parser - The Redis command parser - * @param nodeId - The ID of the node to remove + * @param key - Key of the hash */ - parseCommand(parser3, nodeId) { - parser3.push("CLUSTER", "FORGET", nodeId); + parseCommand(parser3, key) { + parser3.push("HKEYS"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_CLUSTER_GETKEYSINSLOT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_GETKEYSINSLOT.js"(exports2) { +var require_HLEN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HLEN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns a number of keys from the specified hash slot - * @param parser - The Redis command parser - * @param slot - The hash slot to get keys from - * @param count - Maximum number of keys to return + * Gets the number of fields in a hash. + * @param parser - The Redis command parser. + * @param key - Key of the hash. */ - parseCommand(parser3, slot, count) { - parser3.push("CLUSTER", "GETKEYSINSLOT", slot.toString(), count.toString()); + parseCommand(parser3, key) { + parser3.push("HLEN"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_CLUSTER_INFO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_INFO.js"(exports2) { +var require_HMGET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HMGET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns information about the state of a Redis Cluster - * @param parser - The Redis command parser + * Gets the values of all the specified fields in a hash. + * @param parser - The Redis command parser. + * @param key - Key of the hash. + * @param fields - Fields to get from the hash. */ - parseCommand(parser3) { - parser3.push("CLUSTER", "INFO"); + parseCommand(parser3, key, fields) { + parser3.push("HMGET"); + parser3.pushKey(key); + parser3.pushVariadic(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_KEYSLOT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_KEYSLOT.js"(exports2) { +var require_HPERSIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPERSIST.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Returns the hash slot number for a given key - * @param parser - The Redis command parser - * @param key - The key to get the hash slot for + * Removes the expiration from the specified fields in a hash. + * @param parser - The Redis command parser. + * @param key - Key of the hash. + * @param fields - Fields to remove expiration from. */ - parseCommand(parser3, key) { - parser3.push("CLUSTER", "KEYSLOT", key); + parseCommand(parser3, key, fields) { + parser3.push("HPERSIST"); + parser3.pushKey(key); + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_LINKS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_LINKS.js"(exports2) { +var require_HPEXPIRE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPEXPIRE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Returns information about all cluster links (lower level connections to other nodes) - * @param parser - The Redis command parser + * Parses the arguments for the `HPEXPIRE` command. + * + * @param parser - The command parser instance. + * @param key - The key of the hash. + * @param fields - The fields to set the expiration for. + * @param ms - The expiration time in milliseconds. + * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT'). */ - parseCommand(parser3) { - parser3.push("CLUSTER", "LINKS"); + parseCommand(parser3, key, fields, ms, mode) { + parser3.push("HPEXPIRE"); + parser3.pushKey(key); + parser3.push(ms.toString()); + if (mode) { + parser3.push(mode); + } + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, - transformReply: { - 2: (reply) => reply.map((link) => { - const unwrapped = link; - return { - direction: unwrapped[1], - node: unwrapped[3], - "create-time": unwrapped[5], - events: unwrapped[7], - "send-buffer-allocated": unwrapped[9], - "send-buffer-used": unwrapped[11] - }; - }), - 3: void 0 - } + transformReply: void 0 }; } }); -var require_CLUSTER_MEET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_MEET.js"(exports2) { +var require_HPEXPIREAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPEXPIREAT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Initiates a handshake with another node in the cluster - * @param parser - The Redis command parser - * @param host - Host name or IP address of the node - * @param port - TCP port of the node + * Parses the arguments for the `HPEXPIREAT` command. + * + * @param parser - The command parser instance. + * @param key - The key of the hash. + * @param fields - The fields to set the expiration for. + * @param timestamp - The expiration timestamp (Unix timestamp or Date object). + * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT'). */ - parseCommand(parser3, host, port) { - parser3.push("CLUSTER", "MEET", host, port.toString()); + parseCommand(parser3, key, fields, timestamp, mode) { + parser3.push("HPEXPIREAT"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformPXAT)(timestamp)); + if (mode) { + parser3.push(mode); + } + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_MYID = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_MYID.js"(exports2) { +var require_HPEXPIRETIME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPEXPIRETIME.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the node ID of the current Redis Cluster node - * @param parser - The Redis command parser + * Constructs the HPEXPIRETIME command + * + * @param parser - The command parser + * @param key - The key to retrieve expiration time for + * @param fields - The fields to retrieve expiration time for + * @see https://redis.io/commands/hpexpiretime/ */ - parseCommand(parser3) { - parser3.push("CLUSTER", "MYID"); + parseCommand(parser3, key, fields) { + parser3.push("HPEXPIRETIME"); + parser3.pushKey(key); + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_MYSHARDID = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_MYSHARDID.js"(exports2) { +var require_HPTTL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPTTL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the shard ID of the current Redis Cluster node - * @param parser - The Redis command parser + * Constructs the HPTTL command + * + * @param parser - The command parser + * @param key - The key to check time-to-live for + * @param fields - The fields to check time-to-live for + * @see https://redis.io/commands/hpttl/ */ - parseCommand(parser3) { - parser3.push("CLUSTER", "MYSHARDID"); + parseCommand(parser3, key, fields) { + parser3.push("HPTTL"); + parser3.pushKey(key); + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_CLUSTER_NODES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_NODES.js"(exports2) { +var require_HRANDFIELD_COUNT_WITHVALUES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HRANDFIELD_COUNT_WITHVALUES.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns serialized information about the nodes in a Redis Cluster - * @param parser - The Redis command parser + * Constructs the HRANDFIELD command with count parameter and WITHVALUES option + * + * @param parser - The command parser + * @param key - The key of the hash to get random fields from + * @param count - The number of fields to return (positive: unique fields, negative: may repeat fields) + * @see https://redis.io/commands/hrandfield/ */ - parseCommand(parser3) { - parser3.push("CLUSTER", "NODES"); + parseCommand(parser3, key, count) { + parser3.push("HRANDFIELD"); + parser3.pushKey(key); + parser3.push(count.toString(), "WITHVALUES"); }, - transformReply: void 0 + transformReply: { + 2: (rawReply) => { + const reply = []; + let i2 = 0; + while (i2 < rawReply.length) { + reply.push({ + field: rawReply[i2++], + value: rawReply[i2++] + }); + } + return reply; + }, + 3: (reply) => { + return reply.map((entry) => { + const [field, value] = entry; + return { + field, + value + }; + }); + } + } }; } }); -var require_CLUSTER_REPLICAS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_REPLICAS.js"(exports2) { +var require_HRANDFIELD_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HRANDFIELD_COUNT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the replica nodes replicating from the specified primary node - * @param parser - The Redis command parser - * @param nodeId - Node ID of the primary node + * Constructs the HRANDFIELD command with count parameter + * + * @param parser - The command parser + * @param key - The key of the hash to get random fields from + * @param count - The number of fields to return (positive: unique fields, negative: may repeat fields) + * @see https://redis.io/commands/hrandfield/ */ - parseCommand(parser3, nodeId) { - parser3.push("CLUSTER", "REPLICAS", nodeId); + parseCommand(parser3, key, count) { + parser3.push("HRANDFIELD"); + parser3.pushKey(key); + parser3.push(count.toString()); }, transformReply: void 0 }; } }); -var require_CLUSTER_REPLICATE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_REPLICATE.js"(exports2) { +var require_HRANDFIELD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HRANDFIELD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Reconfigures a node as a replica of the specified primary node - * @param parser - The Redis command parser - * @param nodeId - Node ID of the primary node to replicate + * Constructs the HRANDFIELD command + * + * @param parser - The command parser + * @param key - The key of the hash to get a random field from + * @see https://redis.io/commands/hrandfield/ */ - parseCommand(parser3, nodeId) { - parser3.push("CLUSTER", "REPLICATE", nodeId); + parseCommand(parser3, key) { + parser3.push("HRANDFIELD"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_CLUSTER_RESET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_RESET.js"(exports2) { +var require_SCAN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCAN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.pushScanArguments = exports2.parseScanArguments = void 0; + function parseScanArguments(parser3, cursor, options2) { + parser3.push(cursor); + if (options2?.MATCH) { + parser3.push("MATCH", options2.MATCH); + } + if (options2?.COUNT) { + parser3.push("COUNT", options2.COUNT.toString()); + } + } + exports2.parseScanArguments = parseScanArguments; + function pushScanArguments(args, cursor, options2) { + args.push(cursor.toString()); + if (options2?.MATCH) { + args.push("MATCH", options2.MATCH); + } + if (options2?.COUNT) { + args.push("COUNT", options2.COUNT.toString()); + } + return args; + } + exports2.pushScanArguments = pushScanArguments; exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Resets a Redis Cluster node, clearing all information and returning it to a brand new state - * @param parser - The Redis command parser - * @param options - Options for the reset operation + * Constructs the SCAN command + * + * @param parser - The command parser + * @param cursor - The cursor position to start scanning from + * @param options - Scan options + * @see https://redis.io/commands/scan/ */ - parseCommand(parser3, options2) { - parser3.push("CLUSTER", "RESET"); - if (options2?.mode) { - parser3.push(options2.mode); + parseCommand(parser3, cursor, options2) { + parser3.push("SCAN"); + parseScanArguments(parser3, cursor, options2); + if (options2?.TYPE) { + parser3.push("TYPE", options2.TYPE); } }, - transformReply: void 0 + /** + * Transforms the SCAN reply into a structured object + * + * @param reply - The raw reply containing cursor and keys + * @returns Object with cursor and keys properties + */ + transformReply([cursor, keys]) { + return { + cursor, + keys + }; + } }; } }); -var require_CLUSTER_SAVECONFIG = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SAVECONFIG.js"(exports2) { +var require_HSCAN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSCAN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var SCAN_1 = require_SCAN(); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Forces a Redis Cluster node to save the cluster configuration to disk - * @param parser - The Redis command parser + * Constructs the HSCAN command + * + * @param parser - The command parser + * @param key - The key of the hash to scan + * @param cursor - The cursor position to start scanning from + * @param options - Options for the scan (COUNT, MATCH, TYPE) + * @see https://redis.io/commands/hscan/ */ - parseCommand(parser3) { - parser3.push("CLUSTER", "SAVECONFIG"); + parseCommand(parser3, key, cursor, options2) { + parser3.push("HSCAN"); + parser3.pushKey(key); + (0, SCAN_1.parseScanArguments)(parser3, cursor, options2); }, - transformReply: void 0 + transformReply([cursor, rawEntries]) { + const entries = []; + let i2 = 0; + while (i2 < rawEntries.length) { + entries.push({ + field: rawEntries[i2++], + value: rawEntries[i2++] + }); + } + return { + cursor, + entries + }; + } }; } }); -var require_CLUSTER_SET_CONFIG_EPOCH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SET-CONFIG-EPOCH.js"(exports2) { +var require_HSCAN_NOVALUES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSCAN_NOVALUES.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var HSCAN_1 = __importDefault(require_HSCAN()); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Sets the configuration epoch for a Redis Cluster node - * @param parser - The Redis command parser - * @param configEpoch - The configuration epoch to set + * Constructs the HSCAN command with NOVALUES option + * + * @param args - The same parameters as HSCAN command + * @see https://redis.io/commands/hscan/ */ - parseCommand(parser3, configEpoch) { - parser3.push("CLUSTER", "SET-CONFIG-EPOCH", configEpoch.toString()); + parseCommand(...args) { + const parser3 = args[0]; + HSCAN_1.default.parseCommand(...args); + parser3.push("NOVALUES"); }, - transformReply: void 0 + transformReply([cursor, fields]) { + return { + cursor, + fields + }; + } }; } }); -var require_CLUSTER_SETSLOT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SETSLOT.js"(exports2) { +var require_HSET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.CLUSTER_SLOT_STATES = void 0; - exports2.CLUSTER_SLOT_STATES = { - IMPORTING: "IMPORTING", - MIGRATING: "MIGRATING", - STABLE: "STABLE", - NODE: "NODE" - }; exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Assigns a hash slot to a specific Redis Cluster node - * @param parser - The Redis command parser - * @param slot - The slot number to assign - * @param state - The state to set for the slot (IMPORTING, MIGRATING, STABLE, NODE) - * @param nodeId - Node ID (required for IMPORTING, MIGRATING, and NODE states) + * Constructs the HSET command + * + * @param parser - The command parser + * @param key - The key of the hash + * @param value - Either the field name (when using single field) or an object/map/array of field-value pairs + * @param fieldValue - The value to set (only used with single field variant) + * @see https://redis.io/commands/hset/ */ - parseCommand(parser3, slot, state, nodeId) { - parser3.push("CLUSTER", "SETSLOT", slot.toString(), state); - if (nodeId) { - parser3.push(nodeId); + parseCommand(parser3, ...[key, value, fieldValue]) { + parser3.push("HSET"); + parser3.pushKey(key); + if (typeof value === "string" || typeof value === "number" || value instanceof Buffer) { + parser3.push(convertValue(value), convertValue(fieldValue)); + } else if (value instanceof Map) { + pushMap(parser3, value); + } else if (Array.isArray(value)) { + pushTuples(parser3, value); + } else { + pushObject(parser3, value); } }, transformReply: void 0 }; - } -}); -var require_CLUSTER_SLOTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CLUSTER_SLOTS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Returns information about which Redis Cluster node handles which hash slots - * @param parser - The Redis command parser - */ - parseCommand(parser3) { - parser3.push("CLUSTER", "SLOTS"); - }, - transformReply(reply) { - return reply.map(([from3, to, master, ...replicas]) => ({ - from: from3, - to, - master: transformNode(master), - replicas: replicas.map(transformNode) - })); + function pushMap(parser3, map) { + for (const [key, value] of map.entries()) { + parser3.push(convertValue(key), convertValue(value)); } - }; - function transformNode(node) { - const [host, port, id] = node; - return { - host, - port, - id - }; + } + function pushTuples(parser3, tuples) { + for (const tuple of tuples) { + if (Array.isArray(tuple)) { + pushTuples(parser3, tuple); + continue; + } + parser3.push(convertValue(tuple)); + } + } + function pushObject(parser3, object2) { + for (const key of Object.keys(object2)) { + parser3.push(convertValue(key), convertValue(object2[key])); + } + } + function convertValue(value) { + return typeof value === "number" ? value.toString() : value; } } }); -var require_COMMAND_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_COUNT.js"(exports2) { +var require_HSETEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSETEX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var parser_1 = require_parser(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Returns the total number of commands available in the Redis server - * @param parser - The Redis command parser + * Constructs the HSETEX command + * + * @param parser - The command parser + * @param key - The key of the hash + * @param fields - Object, Map, or Array of field-value pairs to set + * @param options - Optional configuration for expiration and mode settings + * @see https://redis.io/commands/hsetex/ */ - parseCommand(parser3) { - parser3.push("COMMAND", "COUNT"); + parseCommand(parser3, key, fields, options2) { + parser3.push("HSETEX"); + parser3.pushKey(key); + if (options2?.mode) { + parser3.push(options2.mode); + } + if (options2?.expiration) { + if (typeof options2.expiration === "string") { + parser3.push(options2.expiration); + } else if (options2.expiration.type === "KEEPTTL") { + parser3.push("KEEPTTL"); + } else { + parser3.push(options2.expiration.type, options2.expiration.value.toString()); + } + } + parser3.push("FIELDS"); + if (fields instanceof Map) { + pushMap(parser3, fields); + } else if (Array.isArray(fields)) { + pushTuples(parser3, fields); + } else { + pushObject(parser3, fields); + } }, transformReply: void 0 }; + function pushMap(parser3, map) { + parser3.push(map.size.toString()); + for (const [key, value] of map.entries()) { + parser3.push(convertValue(key), convertValue(value)); + } + } + function pushTuples(parser3, tuples) { + const tmpParser = new parser_1.BasicCommandParser(); + _pushTuples(tmpParser, tuples); + if (tmpParser.redisArgs.length % 2 != 0) { + throw Error("invalid number of arguments, expected key value ....[key value] pairs, got key without value"); + } + parser3.push((tmpParser.redisArgs.length / 2).toString()); + parser3.push(...tmpParser.redisArgs); + } + function _pushTuples(parser3, tuples) { + for (const tuple of tuples) { + if (Array.isArray(tuple)) { + _pushTuples(parser3, tuple); + continue; + } + parser3.push(convertValue(tuple)); + } + } + function pushObject(parser3, object2) { + const len = Object.keys(object2).length; + if (len == 0) { + throw Error("object without keys"); + } + parser3.push(len.toString()); + for (const key of Object.keys(object2)) { + parser3.push(convertValue(key), convertValue(object2[key])); + } + } + function convertValue(value) { + return typeof value === "number" ? value.toString() : value; + } } }); -var require_COMMAND_GETKEYS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_GETKEYS.js"(exports2) { +var require_HSETNX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSETNX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Extracts the key names from a Redis command - * @param parser - The Redis command parser - * @param args - Command arguments to analyze + * Constructs the HSETNX command + * + * @param parser - The command parser + * @param key - The key of the hash + * @param field - The field to set if it does not exist + * @param value - The value to set + * @see https://redis.io/commands/hsetnx/ */ - parseCommand(parser3, args) { - parser3.push("COMMAND", "GETKEYS"); - parser3.push(...args); + parseCommand(parser3, key, field, value) { + parser3.push("HSETNX"); + parser3.pushKey(key); + parser3.push(field, value); }, transformReply: void 0 }; } }); -var require_COMMAND_GETKEYSANDFLAGS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_GETKEYSANDFLAGS.js"(exports2) { +var require_HSTRLEN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSTRLEN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Extracts the key names and access flags from a Redis command - * @param parser - The Redis command parser - * @param args - Command arguments to analyze + * Constructs the HSTRLEN command + * + * @param parser - The command parser + * @param key - The key of the hash + * @param field - The field to get the string length of + * @see https://redis.io/commands/hstrlen/ */ - parseCommand(parser3, args) { - parser3.push("COMMAND", "GETKEYSANDFLAGS"); - parser3.push(...args); + parseCommand(parser3, key, field) { + parser3.push("HSTRLEN"); + parser3.pushKey(key); + parser3.push(field); }, - transformReply(reply) { - return reply.map((entry) => { - const [key, flags] = entry; - return { - key, - flags - }; - }); - } + transformReply: void 0 }; } }); -var require_COMMAND_INFO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_INFO.js"(exports2) { +var require_HTTL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HTTL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns details about specific Redis commands - * @param parser - The Redis command parser - * @param commands - Array of command names to get information about + * Returns the remaining time to live of field(s) in a hash. + * @param parser - The Redis command parser. + * @param key - Key of the hash. + * @param fields - Fields to check time to live. */ - parseCommand(parser3, commands) { - parser3.push("COMMAND", "INFO", ...commands); + parseCommand(parser3, key, fields) { + parser3.push("HTTL"); + parser3.pushKey(key); + parser3.push("FIELDS"); + parser3.pushVariadicWithLength(fields); }, - // TODO: This works, as we don't currently handle any of the items returned as a map - transformReply(reply) { - return reply.map((command2) => command2 ? (0, generic_transformers_1.transformCommandReply)(command2) : null); - } + transformReply: void 0 }; } }); -var require_COMMAND_LIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND_LIST.js"(exports2) { +var require_HVALS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HVALS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.COMMAND_LIST_FILTER_BY = void 0; - exports2.COMMAND_LIST_FILTER_BY = { - MODULE: "MODULE", - ACLCAT: "ACLCAT", - PATTERN: "PATTERN" - }; exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns a list of all commands supported by the Redis server - * @param parser - The Redis command parser - * @param options - Options for filtering the command list + * Gets all values in a hash. + * @param parser - The Redis command parser. + * @param key - Key of the hash. */ - parseCommand(parser3, options2) { - parser3.push("COMMAND", "LIST"); - if (options2?.FILTERBY) { - parser3.push("FILTERBY", options2.FILTERBY.type, options2.FILTERBY.value); - } + parseCommand(parser3, key) { + parser3.push("HVALS"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_COMMAND = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COMMAND.js"(exports2) { +var require_INCR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INCR.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Returns an array with details about all Redis commands - * @param parser - The Redis command parser + * Constructs the INCR command + * + * @param parser - The command parser + * @param key - The key to increment + * @see https://redis.io/commands/incr/ */ - parseCommand(parser3) { - parser3.push("COMMAND"); + parseCommand(parser3, key) { + parser3.push("INCR"); + parser3.pushKey(key); }, - // TODO: This works, as we don't currently handle any of the items returned as a map - transformReply(reply) { - return reply.map(generic_transformers_1.transformCommandReply); - } + transformReply: void 0 }; } }); -var require_CONFIG_GET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_GET.js"(exports2) { +var require_INCRBY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INCRBY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Gets the values of configuration parameters - * @param parser - The Redis command parser - * @param parameters - Pattern or specific configuration parameter names + * Constructs the INCRBY command + * + * @param parser - The command parser + * @param key - The key to increment + * @param increment - The amount to increment by + * @see https://redis.io/commands/incrby/ */ - parseCommand(parser3, parameters) { - parser3.push("CONFIG", "GET"); - parser3.pushVariadic(parameters); + parseCommand(parser3, key, increment2) { + parser3.push("INCRBY"); + parser3.pushKey(key); + parser3.push(increment2.toString()); }, - transformReply: { - 2: generic_transformers_1.transformTuplesReply, - 3: void 0 - } + transformReply: void 0 }; } }); -var require_CONFIG_RESETSTAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_RESETSTAT.js"(exports2) { +var require_INCRBYFLOAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INCRBYFLOAT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Resets the statistics reported by Redis using the INFO command - * @param parser - The Redis command parser + * Constructs the INCRBYFLOAT command + * + * @param parser - The command parser + * @param key - The key to increment + * @param increment - The floating-point value to increment by + * @see https://redis.io/commands/incrbyfloat/ */ - parseCommand(parser3) { - parser3.push("CONFIG", "RESETSTAT"); + parseCommand(parser3, key, increment2) { + parser3.push("INCRBYFLOAT"); + parser3.pushKey(key); + parser3.push(increment2.toString()); }, transformReply: void 0 }; } }); -var require_CONFIG_REWRITE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_REWRITE.js"(exports2) { +var require_INFO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INFO.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Rewrites the Redis configuration file with the current configuration - * @param parser - The Redis command parser + * Constructs the INFO command + * + * @param parser - The command parser + * @param section - Optional specific section of information to retrieve + * @see https://redis.io/commands/info/ */ - parseCommand(parser3) { - parser3.push("CONFIG", "REWRITE"); + parseCommand(parser3, section) { + parser3.push("INFO"); + if (section) { + parser3.push(section); + } }, transformReply: void 0 }; } }); -var require_CONFIG_SET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/CONFIG_SET.js"(exports2) { +var require_KEYS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/KEYS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Sets configuration parameters to the specified values - * @param parser - The Redis command parser - * @param parameterOrConfig - Either a single parameter name or a configuration object - * @param value - Value for the parameter (when using single parameter format) + * Constructs the KEYS command + * + * @param parser - The command parser + * @param pattern - The pattern to match keys against + * @see https://redis.io/commands/keys/ */ - parseCommand(parser3, ...[parameterOrConfig, value]) { - parser3.push("CONFIG", "SET"); - if (typeof parameterOrConfig === "string" || parameterOrConfig instanceof Buffer) { - parser3.push(parameterOrConfig, value); - } else { - for (const [key, value2] of Object.entries(parameterOrConfig)) { - parser3.push(key, value2); - } - } + parseCommand(parser3, pattern) { + parser3.push("KEYS", pattern); }, transformReply: void 0 }; } }); -var require_COPY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/COPY.js"(exports2) { +var require_LASTSAVE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LASTSAVE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Copies the value stored at the source key to the destination key - * @param parser - The Redis command parser - * @param source - Source key - * @param destination - Destination key - * @param options - Options for the copy operation + * Constructs the LASTSAVE command + * + * @param parser - The command parser + * @see https://redis.io/commands/lastsave/ */ - parseCommand(parser3, source, destination, options2) { - parser3.push("COPY"); - parser3.pushKeys([source, destination]); - if (options2?.DB) { - parser3.push("DB", options2.DB.toString()); - } - if (options2?.REPLACE) { - parser3.push("REPLACE"); - } + parseCommand(parser3) { + parser3.push("LASTSAVE"); }, transformReply: void 0 }; } }); -var require_DBSIZE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DBSIZE.js"(exports2) { +var require_LATENCY_DOCTOR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_DOCTOR.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the number of keys in the current database - * @param parser - The Redis command parser + * Constructs the LATENCY DOCTOR command + * + * @param parser - The command parser + * @see https://redis.io/commands/latency-doctor/ */ parseCommand(parser3) { - parser3.push("DBSIZE"); + parser3.push("LATENCY", "DOCTOR"); }, transformReply: void 0 }; } }); -var require_DECR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DECR.js"(exports2) { +var require_LATENCY_GRAPH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_GRAPH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.LATENCY_EVENTS = void 0; + exports2.LATENCY_EVENTS = { + ACTIVE_DEFRAG_CYCLE: "active-defrag-cycle", + AOF_FSYNC_ALWAYS: "aof-fsync-always", + AOF_STAT: "aof-stat", + AOF_REWRITE_DIFF_WRITE: "aof-rewrite-diff-write", + AOF_RENAME: "aof-rename", + AOF_WRITE: "aof-write", + AOF_WRITE_ACTIVE_CHILD: "aof-write-active-child", + AOF_WRITE_ALONE: "aof-write-alone", + AOF_WRITE_PENDING_FSYNC: "aof-write-pending-fsync", + COMMAND: "command", + EXPIRE_CYCLE: "expire-cycle", + EVICTION_CYCLE: "eviction-cycle", + EVICTION_DEL: "eviction-del", + FAST_COMMAND: "fast-command", + FORK: "fork", + RDB_UNLINK_TEMP_FILE: "rdb-unlink-temp-file" + }; exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Decrements the integer value of a key by one - * @param parser - The Redis command parser - * @param key - Key to decrement + * Constructs the LATENCY GRAPH command + * + * @param parser - The command parser + * @param event - The latency event to get the graph for + * @see https://redis.io/commands/latency-graph/ */ - parseCommand(parser3, key) { - parser3.push("DECR"); - parser3.pushKey(key); + parseCommand(parser3, event) { + parser3.push("LATENCY", "GRAPH", event); }, transformReply: void 0 }; } }); -var require_DECRBY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DECRBY.js"(exports2) { +var require_LATENCY_HISTORY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_HISTORY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Decrements the integer value of a key by the given number - * @param parser - The Redis command parser - * @param key - Key to decrement - * @param decrement - Decrement amount + * Constructs the LATENCY HISTORY command + * + * @param parser - The command parser + * @param event - The latency event to get the history for + * @see https://redis.io/commands/latency-history/ */ - parseCommand(parser3, key, decrement) { - parser3.push("DECRBY"); - parser3.pushKey(key); - parser3.push(decrement.toString()); + parseCommand(parser3, event) { + parser3.push("LATENCY", "HISTORY", event); }, transformReply: void 0 }; } }); -var require_DEL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DEL.js"(exports2) { +var require_LATENCY_LATEST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_LATEST.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Removes the specified keys. A key is ignored if it does not exist - * @param parser - The Redis command parser - * @param keys - One or more keys to delete + * Constructs the LATENCY LATEST command + * + * @param parser - The command parser + * @see https://redis.io/commands/latency-latest/ */ - parseCommand(parser3, keys) { - parser3.push("DEL"); - parser3.pushKeys(keys); + parseCommand(parser3) { + parser3.push("LATENCY", "LATEST"); }, transformReply: void 0 }; } }); -var require_DUMP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/DUMP.js"(exports2) { +var require_LATENCY_RESET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_RESET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.LATENCY_EVENTS = void 0; + var LATENCY_GRAPH_1 = require_LATENCY_GRAPH(); + Object.defineProperty(exports2, "LATENCY_EVENTS", { enumerable: true, get: function() { + return LATENCY_GRAPH_1.LATENCY_EVENTS; + } }); exports2.default = { - IS_READ_ONLY: true, + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: false, /** - * Returns a serialized version of the value stored at the key - * @param parser - The Redis command parser - * @param key - Key to dump + * Constructs the LATENCY RESET command + * * @param parser - The command parser + * @param events - The latency events to reset. If not specified, all events are reset. + * @see https://redis.io/commands/latency-reset/ */ - parseCommand(parser3, key) { - parser3.push("DUMP"); - parser3.pushKey(key); + parseCommand(parser3, ...events) { + const args = ["LATENCY", "RESET"]; + if (events.length > 0) { + args.push(...events); + } + parser3.push(...args); }, transformReply: void 0 }; } }); -var require_ECHO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ECHO.js"(exports2) { +var require_LCS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the given string - * @param parser - The Redis command parser - * @param message - Message to echo back + * Constructs the LCS command (Longest Common Substring) + * + * @param parser - The command parser + * @param key1 - First key containing the first string + * @param key2 - Second key containing the second string + * @see https://redis.io/commands/lcs/ */ - parseCommand(parser3, message) { - parser3.push("ECHO", message); + parseCommand(parser3, key1, key2) { + parser3.push("LCS"); + parser3.pushKeys([key1, key2]); }, transformReply: void 0 }; } }); -var require_EVAL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVAL.js"(exports2) { +var require_LCS_IDX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS_IDX.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseEvalArguments = void 0; - function parseEvalArguments(parser3, script, options2) { - parser3.push(script); - if (options2?.keys) { - parser3.pushKeysLength(options2.keys); - } else { - parser3.push("0"); - } - if (options2?.arguments) { - parser3.push(...options2.arguments); - } - } - exports2.parseEvalArguments = parseEvalArguments; + var LCS_1 = __importDefault(require_LCS()); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: LCS_1.default.IS_READ_ONLY, /** - * Executes a Lua script server side - * @param parser - The Redis command parser - * @param script - Lua script to execute - * @param options - Script execution options including keys and arguments + * Constructs the LCS command with IDX option + * + * @param parser - The command parser + * @param key1 - First key containing the first string + * @param key2 - Second key containing the second string + * @param options - Additional options for the LCS IDX command + * @see https://redis.io/commands/lcs/ */ - parseCommand(...args) { - args[0].push("EVAL"); - parseEvalArguments(...args); + parseCommand(parser3, key1, key2, options2) { + LCS_1.default.parseCommand(parser3, key1, key2); + parser3.push("IDX"); + if (options2?.MINMATCHLEN) { + parser3.push("MINMATCHLEN", options2.MINMATCHLEN.toString()); + } }, - transformReply: void 0 + transformReply: { + 2: (reply) => ({ + matches: reply[1], + len: reply[3] + }), + 3: void 0 + } }; } }); -var require_EVAL_RO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVAL_RO.js"(exports2) { +var require_LCS_IDX_WITHMATCHLEN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS_IDX_WITHMATCHLEN.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var EVAL_1 = __importStar(require_EVAL()); + var LCS_IDX_1 = __importDefault(require_LCS_IDX()); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: LCS_IDX_1.default.IS_READ_ONLY, /** - * Executes a read-only Lua script server side - * @param parser - The Redis command parser - * @param script - Lua script to execute - * @param options - Script execution options including keys and arguments + * Constructs the LCS command with IDX and WITHMATCHLEN options + * + * @param args - The same parameters as LCS_IDX command + * @see https://redis.io/commands/lcs/ */ parseCommand(...args) { - args[0].push("EVAL_RO"); - (0, EVAL_1.parseEvalArguments)(...args); + const parser3 = args[0]; + LCS_IDX_1.default.parseCommand(...args); + parser3.push("WITHMATCHLEN"); }, - transformReply: EVAL_1.default.transformReply + transformReply: { + 2: (reply) => ({ + matches: reply[1], + len: reply[3] + }), + 3: void 0 + } }; } }); -var require_EVALSHA_RO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVALSHA_RO.js"(exports2) { +var require_LCS_LEN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS_LEN.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var EVAL_1 = __importStar(require_EVAL()); + var LCS_1 = __importDefault(require_LCS()); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: LCS_1.default.IS_READ_ONLY, /** - * Executes a read-only Lua script server side using the script's SHA1 digest - * @param parser - The Redis command parser - * @param sha1 - SHA1 digest of the script - * @param options - Script execution options including keys and arguments + * Constructs the LCS command with LEN option + * + * @param args - The same parameters as LCS command + * @see https://redis.io/commands/lcs/ */ parseCommand(...args) { - args[0].push("EVALSHA_RO"); - (0, EVAL_1.parseEvalArguments)(...args); + const parser3 = args[0]; + LCS_1.default.parseCommand(...args); + parser3.push("LEN"); }, - transformReply: EVAL_1.default.transformReply + transformReply: void 0 }; } }); -var require_EVALSHA = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EVALSHA.js"(exports2) { +var require_LINDEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LINDEX.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var EVAL_1 = __importStar(require_EVAL()); exports2.default = { - IS_READ_ONLY: false, + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Executes a Lua script server side using the script's SHA1 digest - * @param parser - The Redis command parser - * @param sha1 - SHA1 digest of the script - * @param options - Script execution options including keys and arguments + * Constructs the LINDEX command + * + * @param parser - The command parser + * @param key - The key of the list + * @param index - The index of the element to retrieve + * @see https://redis.io/commands/lindex/ */ - parseCommand(...args) { - args[0].push("EVALSHA"); - (0, EVAL_1.parseEvalArguments)(...args); + parseCommand(parser3, key, index) { + parser3.push("LINDEX"); + parser3.pushKey(key); + parser3.push(index.toString()); }, - transformReply: EVAL_1.default.transformReply + transformReply: void 0 }; } }); -var require_GEOADD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOADD.js"(exports2) { +var require_LINSERT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LINSERT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Adds geospatial items to the specified key - * @param parser - The Redis command parser - * @param key - Key to add the geospatial items to - * @param toAdd - Geospatial member(s) to add - * @param options - Options for the GEOADD command + * Constructs the LINSERT command + * + * @param parser - The command parser + * @param key - The key of the list + * @param position - The position where to insert (BEFORE or AFTER) + * @param pivot - The element to find in the list + * @param element - The element to insert + * @see https://redis.io/commands/linsert/ */ - parseCommand(parser3, key, toAdd, options2) { - parser3.push("GEOADD"); + parseCommand(parser3, key, position, pivot, element) { + parser3.push("LINSERT"); parser3.pushKey(key); - if (options2?.condition) { - parser3.push(options2.condition); - } else if (options2?.NX) { - parser3.push("NX"); - } else if (options2?.XX) { - parser3.push("XX"); - } - if (options2?.CH) { - parser3.push("CH"); - } - if (Array.isArray(toAdd)) { - for (const member of toAdd) { - pushMember(parser3, member); - } - } else { - pushMember(parser3, toAdd); - } + parser3.push(position, pivot, element); }, transformReply: void 0 }; - function pushMember(parser3, { longitude, latitude, member }) { - parser3.push(longitude.toString(), latitude.toString(), member); - } } }); -var require_GEODIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEODIST.js"(exports2) { +var require_LLEN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LLEN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns the distance between two members in a geospatial index - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param member1 - First member in the geospatial index - * @param member2 - Second member in the geospatial index - * @param unit - Unit of distance (m, km, ft, mi) + * Constructs the LLEN command + * + * @param parser - The command parser + * @param key - The key of the list to get the length of + * @see https://redis.io/commands/llen/ */ - parseCommand(parser3, key, member1, member2, unit) { - parser3.push("GEODIST"); + parseCommand(parser3, key) { + parser3.push("LLEN"); parser3.pushKey(key); - parser3.push(member1, member2); - if (unit) { - parser3.push(unit); - } }, - transformReply(reply) { - return reply === null ? null : Number(reply); - } + transformReply: void 0 }; } }); -var require_GEOHASH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOHASH.js"(exports2) { +var require_LMOVE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LMOVE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Returns the Geohash string representation of one or more position members - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param member - One or more members in the geospatial index + * Constructs the LMOVE command + * + * @param parser - The command parser + * @param source - The source list key + * @param destination - The destination list key + * @param sourceSide - The side to pop from (LEFT or RIGHT) + * @param destinationSide - The side to push to (LEFT or RIGHT) + * @see https://redis.io/commands/lmove/ */ - parseCommand(parser3, key, member) { - parser3.push("GEOHASH"); - parser3.pushKey(key); - parser3.pushVariadic(member); + parseCommand(parser3, source, destination, sourceSide, destinationSide) { + parser3.push("LMOVE"); + parser3.pushKeys([source, destination]); + parser3.push(sourceSide, destinationSide); }, transformReply: void 0 }; } }); -var require_GEOPOS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOPOS.js"(exports2) { +var require_LOLWUT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LOLWUT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns the longitude and latitude of one or more members in a geospatial index - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param member - One or more members in the geospatial index + * Constructs the LOLWUT command + * + * @param parser - The command parser + * @param version - Optional version parameter + * @param optionalArguments - Additional optional numeric arguments + * @see https://redis.io/commands/lolwut/ */ - parseCommand(parser3, key, member) { - parser3.push("GEOPOS"); - parser3.pushKey(key); - parser3.pushVariadic(member); + parseCommand(parser3, version3, ...optionalArguments) { + parser3.push("LOLWUT"); + if (version3) { + parser3.push("VERSION", version3.toString()); + parser3.pushVariadic(optionalArguments.map(String)); + } }, - transformReply(reply) { - return reply.map((item) => { - const unwrapped = item; - return unwrapped === null ? null : { - longitude: unwrapped[0], - latitude: unwrapped[1] - }; - }); - } + transformReply: void 0 }; } }); -var require_GEOSEARCH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOSEARCH.js"(exports2) { +var require_LPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOP.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseGeoSearchOptions = exports2.parseGeoSearchArguments = void 0; - function parseGeoSearchArguments(parser3, key, from3, by, options2) { - parser3.pushKey(key); - if (typeof from3 === "string" || from3 instanceof Buffer) { - parser3.push("FROMMEMBER", from3); - } else { - parser3.push("FROMLONLAT", from3.longitude.toString(), from3.latitude.toString()); - } - if ("radius" in by) { - parser3.push("BYRADIUS", by.radius.toString(), by.unit); - } else { - parser3.push("BYBOX", by.width.toString(), by.height.toString(), by.unit); - } - parseGeoSearchOptions(parser3, options2); - } - exports2.parseGeoSearchArguments = parseGeoSearchArguments; - function parseGeoSearchOptions(parser3, options2) { - if (options2?.SORT) { - parser3.push(options2.SORT); - } - if (options2?.COUNT) { - if (typeof options2.COUNT === "number") { - parser3.push("COUNT", options2.COUNT.toString()); - } else { - parser3.push("COUNT", options2.COUNT.value.toString()); - if (options2.COUNT.ANY) { - parser3.push("ANY"); - } - } - } - } - exports2.parseGeoSearchOptions = parseGeoSearchOptions; exports2.default = { - IS_READ_ONLY: true, /** - * Queries members inside an area of a geospatial index - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Center point of the search (member name or coordinates) - * @param by - Search area specification (radius or box dimensions) - * @param options - Additional search options + * Constructs the LPOP command + * + * @param parser - The command parser + * @param key - The key of the list to pop from + * @see https://redis.io/commands/lpop/ */ - parseCommand(parser3, key, from3, by, options2) { - parser3.push("GEOSEARCH"); - parseGeoSearchArguments(parser3, key, from3, by, options2); + parseCommand(parser3, key) { + parser3.push("LPOP"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_GEORADIUS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS.js"(exports2) { +var require_LPOP_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOP_COUNT.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseGeoRadiusArguments = void 0; - var GEOSEARCH_1 = require_GEOSEARCH(); - function parseGeoRadiusArguments(parser3, key, from3, radius, unit, options2) { - parser3.pushKey(key); - parser3.push(from3.longitude.toString(), from3.latitude.toString(), radius.toString(), unit); - (0, GEOSEARCH_1.parseGeoSearchOptions)(parser3, options2); - } - exports2.parseGeoRadiusArguments = parseGeoRadiusArguments; + var LPOP_1 = __importDefault(require_LPOP()); exports2.default = { IS_READ_ONLY: false, /** - * Queries members in a geospatial index based on a radius from a center point - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Center coordinates for the search - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param options - Additional search options + * Constructs the LPOP command with count parameter + * + * @param parser - The command parser + * @param key - The key of the list to pop from + * @param count - The number of elements to pop + * @see https://redis.io/commands/lpop/ */ - parseCommand(...args) { - args[0].push("GEORADIUS"); - return parseGeoRadiusArguments(...args); + parseCommand(parser3, key, count) { + LPOP_1.default.parseCommand(parser3, key); + parser3.push(count.toString()); }, transformReply: void 0 }; } }); -var require_GEOSEARCH_WITH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOSEARCH_WITH.js"(exports2) { +var require_LPOS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, + /** + * Constructs the LPOS command + * + * @param parser - The command parser + * @param key - The key of the list + * @param element - The element to search for + * @param options - Optional parameters for RANK and MAXLEN + * @see https://redis.io/commands/lpos/ + */ + parseCommand(parser3, key, element, options2) { + parser3.push("LPOS"); + parser3.pushKey(key); + parser3.push(element); + if (options2?.RANK !== void 0) { + parser3.push("RANK", options2.RANK.toString()); + } + if (options2?.MAXLEN !== void 0) { + parser3.push("MAXLEN", options2.MAXLEN.toString()); + } + }, + transformReply: void 0 + }; + } +}); +var require_LPOS_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOS_COUNT.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.GEO_REPLY_WITH = void 0; - var GEOSEARCH_1 = __importDefault(require_GEOSEARCH()); - exports2.GEO_REPLY_WITH = { - DISTANCE: "WITHDIST", - HASH: "WITHHASH", - COORDINATES: "WITHCOORD" - }; + var LPOS_1 = __importDefault(require_LPOS()); exports2.default = { - IS_READ_ONLY: GEOSEARCH_1.default.IS_READ_ONLY, + CACHEABLE: LPOS_1.default.CACHEABLE, + IS_READ_ONLY: LPOS_1.default.IS_READ_ONLY, /** - * Queries members inside an area of a geospatial index with additional information - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Center point of the search (member name or coordinates) - * @param by - Search area specification (radius or box dimensions) - * @param replyWith - Information to include with each returned member - * @param options - Additional search options + * Constructs the LPOS command with COUNT option + * + * @param parser - The command parser + * @param key - The key of the list + * @param element - The element to search for + * @param count - The number of positions to return + * @param options - Optional parameters for RANK and MAXLEN + * @see https://redis.io/commands/lpos/ */ - parseCommand(parser3, key, from3, by, replyWith, options2) { - GEOSEARCH_1.default.parseCommand(parser3, key, from3, by, options2); - parser3.push(...replyWith); - parser3.preserve = replyWith; + parseCommand(parser3, key, element, count, options2) { + LPOS_1.default.parseCommand(parser3, key, element, options2); + parser3.push("COUNT", count.toString()); }, - transformReply(reply, replyWith) { - const replyWithSet = new Set(replyWith); - let index = 0; - const distanceIndex = replyWithSet.has(exports2.GEO_REPLY_WITH.DISTANCE) && ++index, hashIndex = replyWithSet.has(exports2.GEO_REPLY_WITH.HASH) && ++index, coordinatesIndex = replyWithSet.has(exports2.GEO_REPLY_WITH.COORDINATES) && ++index; - return reply.map((raw) => { - const unwrapped = raw; - const item = { - member: unwrapped[0] - }; - if (distanceIndex) { - item.distance = unwrapped[distanceIndex]; - } - if (hashIndex) { - item.hash = unwrapped[hashIndex]; - } - if (coordinatesIndex) { - const [longitude, latitude] = unwrapped[coordinatesIndex]; - item.coordinates = { - longitude, - latitude - }; - } - return item; - }); - } + transformReply: void 0 }; } }); -var require_GEORADIUS_WITH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_WITH.js"(exports2) { +var require_LPUSH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPUSH.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseGeoRadiusWithArguments = void 0; - var GEORADIUS_1 = __importStar(require_GEORADIUS()); - var GEOSEARCH_WITH_1 = __importDefault(require_GEOSEARCH_WITH()); - function parseGeoRadiusWithArguments(parser3, key, from3, radius, unit, replyWith, options2) { - (0, GEORADIUS_1.parseGeoRadiusArguments)(parser3, key, from3, radius, unit, options2); - parser3.pushVariadic(replyWith); - parser3.preserve = replyWith; - } - exports2.parseGeoRadiusWithArguments = parseGeoRadiusWithArguments; exports2.default = { - IS_READ_ONLY: GEORADIUS_1.default.IS_READ_ONLY, /** - * Queries members in a geospatial index based on a radius from a center point with additional information - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Center coordinates for the search - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param replyWith - Information to include with each returned member - * @param options - Additional search options + * Constructs the LPUSH command + * + * @param parser - The command parser + * @param key - The key of the list + * @param elements - One or more elements to push to the list + * @see https://redis.io/commands/lpush/ */ - parseCommand(parser3, key, from3, radius, unit, replyWith, options2) { - parser3.push("GEORADIUS"); - parseGeoRadiusWithArguments(parser3, key, from3, radius, unit, replyWith, options2); + parseCommand(parser3, key, elements) { + parser3.push("LPUSH"); + parser3.pushKey(key); + parser3.pushVariadic(elements); }, - transformReply: GEOSEARCH_WITH_1.default.transformReply + transformReply: void 0 }; } }); -var require_GEORADIUS_RO_WITH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_RO_WITH.js"(exports2) { +var require_LPUSHX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPUSHX.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var GEORADIUS_WITH_1 = require_GEORADIUS_WITH(); - var GEORADIUS_WITH_2 = __importDefault(require_GEORADIUS_WITH()); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, /** - * Read-only variant that queries members in a geospatial index based on a radius from a center point with additional information - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Center coordinates for the search - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param replyWith - Information to include with each returned member - * @param options - Additional search options + * Constructs the LPUSHX command + * + * @param parser - The command parser + * @param key - The key of the list + * @param elements - One or more elements to push to the list if it exists + * @see https://redis.io/commands/lpushx/ */ - parseCommand(...args) { - args[0].push("GEORADIUS_RO"); - (0, GEORADIUS_WITH_1.parseGeoRadiusWithArguments)(...args); + parseCommand(parser3, key, elements) { + parser3.push("LPUSHX"); + parser3.pushKey(key); + parser3.pushVariadic(elements); }, - transformReply: GEORADIUS_WITH_2.default.transformReply + transformReply: void 0 }; } }); -var require_GEORADIUS_RO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_RO.js"(exports2) { +var require_LRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LRANGE.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var GEORADIUS_1 = __importStar(require_GEORADIUS()); exports2.default = { CACHEABLE: true, IS_READ_ONLY: true, /** - * Read-only variant that queries members in a geospatial index based on a radius from a center point - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Center coordinates for the search - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param options - Additional search options + * Constructs the LRANGE command + * + * @param parser - The command parser + * @param key - The key of the list + * @param start - The starting index + * @param stop - The ending index + * @see https://redis.io/commands/lrange/ */ - parseCommand(...args) { - args[0].push("GEORADIUS_RO"); - (0, GEORADIUS_1.parseGeoRadiusArguments)(...args); + parseCommand(parser3, key, start, stop) { + parser3.push("LRANGE"); + parser3.pushKey(key); + parser3.push(start.toString(), stop.toString()); }, - transformReply: GEORADIUS_1.default.transformReply + transformReply: void 0 }; } }); -var require_GEORADIUS_STORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUS_STORE.js"(exports2) { +var require_LREM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LREM.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var GEORADIUS_1 = __importStar(require_GEORADIUS()); exports2.default = { - IS_READ_ONLY: GEORADIUS_1.default.IS_READ_ONLY, + IS_READ_ONLY: true, /** - * Queries members in a geospatial index based on a radius from a center point and stores the results - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Center coordinates for the search - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param destination - Key to store the results - * @param options - Additional search and storage options + * Constructs the LREM command + * + * @param parser - The command parser + * @param key - The key of the list + * @param count - The count of elements to remove (negative: from tail to head, 0: all occurrences, positive: from head to tail) + * @param element - The element to remove + * @see https://redis.io/commands/lrem/ */ - parseCommand(parser3, key, from3, radius, unit, destination, options2) { - parser3.push("GEORADIUS"); - (0, GEORADIUS_1.parseGeoRadiusArguments)(parser3, key, from3, radius, unit, options2); - if (options2?.STOREDIST) { - parser3.push("STOREDIST"); - parser3.pushKey(destination); - } else { - parser3.push("STORE"); - parser3.pushKey(destination); - } + parseCommand(parser3, key, count, element) { + parser3.push("LREM"); + parser3.pushKey(key); + parser3.push(count.toString()); + parser3.push(element); }, transformReply: void 0 }; } }); -var require_GEORADIUSBYMEMBER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER.js"(exports2) { +var require_LSET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LSET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseGeoRadiusByMemberArguments = void 0; - var GEOSEARCH_1 = require_GEOSEARCH(); - function parseGeoRadiusByMemberArguments(parser3, key, from3, radius, unit, options2) { - parser3.pushKey(key); - parser3.push(from3, radius.toString(), unit); - (0, GEOSEARCH_1.parseGeoSearchOptions)(parser3, options2); - } - exports2.parseGeoRadiusByMemberArguments = parseGeoRadiusByMemberArguments; exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Queries members in a geospatial index based on a radius from a member - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Member name to use as center point - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param options - Additional search options + * Constructs the LSET command + * + * @param parser - The command parser + * @param key - The key of the list + * @param index - The index of the element to replace + * @param element - The new value to set + * @see https://redis.io/commands/lset/ */ - parseCommand(parser3, key, from3, radius, unit, options2) { - parser3.push("GEORADIUSBYMEMBER"); - parseGeoRadiusByMemberArguments(parser3, key, from3, radius, unit, options2); + parseCommand(parser3, key, index, element) { + parser3.push("LSET"); + parser3.pushKey(key); + parser3.push(index.toString(), element); }, transformReply: void 0 }; } }); -var require_GEORADIUSBYMEMBER_WITH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_WITH.js"(exports2) { +var require_LTRIM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LTRIM.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseGeoRadiusByMemberWithArguments = void 0; - var GEORADIUSBYMEMBER_1 = __importDefault(require_GEORADIUSBYMEMBER()); - var GEOSEARCH_1 = require_GEOSEARCH(); - var GEOSEARCH_WITH_1 = __importDefault(require_GEOSEARCH_WITH()); - function parseGeoRadiusByMemberWithArguments(parser3, key, from3, radius, unit, replyWith, options2) { - parser3.pushKey(key); - parser3.push(from3, radius.toString(), unit); - (0, GEOSEARCH_1.parseGeoSearchOptions)(parser3, options2); - parser3.push(...replyWith); - parser3.preserve = replyWith; - } - exports2.parseGeoRadiusByMemberWithArguments = parseGeoRadiusByMemberWithArguments; exports2.default = { - IS_READ_ONLY: GEORADIUSBYMEMBER_1.default.IS_READ_ONLY, /** - * Queries members in a geospatial index based on a radius from a member with additional information - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Member name to use as center point - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param replyWith - Information to include with each returned member - * @param options - Additional search options + * Constructs the LTRIM command + * + * @param parser - The command parser + * @param key - The key of the list + * @param start - The starting index + * @param stop - The ending index + * @see https://redis.io/commands/ltrim/ */ - parseCommand(parser3, key, from3, radius, unit, replyWith, options2) { - parser3.push("GEORADIUSBYMEMBER"); - parseGeoRadiusByMemberWithArguments(parser3, key, from3, radius, unit, replyWith, options2); + parseCommand(parser3, key, start, stop) { + parser3.push("LTRIM"); + parser3.pushKey(key); + parser3.push(start.toString(), stop.toString()); }, - transformReply: GEOSEARCH_WITH_1.default.transformReply + transformReply: void 0 }; } }); -var require_GEORADIUSBYMEMBER_RO_WITH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_RO_WITH.js"(exports2) { +var require_MEMORY_DOCTOR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_DOCTOR.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var GEORADIUSBYMEMBER_WITH_1 = __importStar(require_GEORADIUSBYMEMBER_WITH()); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Read-only variant that queries members in a geospatial index based on a radius from a member with additional information - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Member name to use as center point - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param withValues - Information to include with each returned member + * Constructs the MEMORY DOCTOR command + * + * @param parser - The command parser + * @see https://redis.io/commands/memory-doctor/ */ - parseCommand(...args) { - const parser3 = args[0]; - parser3.push("GEORADIUSBYMEMBER_RO"); - (0, GEORADIUSBYMEMBER_WITH_1.parseGeoRadiusByMemberWithArguments)(...args); + parseCommand(parser3) { + parser3.push("MEMORY", "DOCTOR"); }, - transformReply: GEORADIUSBYMEMBER_WITH_1.default.transformReply + transformReply: void 0 }; } }); -var require_GEORADIUSBYMEMBER_RO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_RO.js"(exports2) { +var require_MEMORY_MALLOC_STATS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_MALLOC-STATS.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var GEORADIUSBYMEMBER_1 = __importStar(require_GEORADIUSBYMEMBER()); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Read-only variant that queries members in a geospatial index based on a radius from a member - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Member name to use as center point - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param options - Additional search options - */ - parseCommand(...args) { - const parser3 = args[0]; - parser3.push("GEORADIUSBYMEMBER_RO"); - (0, GEORADIUSBYMEMBER_1.parseGeoRadiusByMemberArguments)(...args); - }, - transformReply: GEORADIUSBYMEMBER_1.default.transformReply - }; - } -}); -var require_GEORADIUSBYMEMBER_STORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEORADIUSBYMEMBER_STORE.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var GEORADIUSBYMEMBER_1 = __importStar(require_GEORADIUSBYMEMBER()); - exports2.default = { - IS_READ_ONLY: GEORADIUSBYMEMBER_1.default.IS_READ_ONLY, - /** - * Queries members in a geospatial index based on a radius from a member and stores the results - * @param parser - The Redis command parser - * @param key - Key of the geospatial index - * @param from - Member name to use as center point - * @param radius - Radius of the search area - * @param unit - Unit of distance (m, km, ft, mi) - * @param destination - Key to store the results - * @param options - Additional search and storage options + * Constructs the MEMORY MALLOC-STATS command + * + * @param parser - The command parser + * @see https://redis.io/commands/memory-malloc-stats/ */ - parseCommand(parser3, key, from3, radius, unit, destination, options2) { - parser3.push("GEORADIUSBYMEMBER"); - (0, GEORADIUSBYMEMBER_1.parseGeoRadiusByMemberArguments)(parser3, key, from3, radius, unit, options2); - if (options2?.STOREDIST) { - parser3.push("STOREDIST"); - parser3.pushKey(destination); - } else { - parser3.push("STORE"); - parser3.pushKey(destination); - } + parseCommand(parser3) { + parser3.push("MEMORY", "MALLOC-STATS"); }, transformReply: void 0 }; } }); -var require_GEOSEARCHSTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GEOSEARCHSTORE.js"(exports2) { +var require_MEMORY_PURGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_PURGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var GEOSEARCH_1 = require_GEOSEARCH(); exports2.default = { + NOT_KEYED_COMMAND: true, IS_READ_ONLY: false, /** - * Searches a geospatial index and stores the results in a new sorted set - * @param parser - The Redis command parser - * @param destination - Key to store the results - * @param source - Key of the geospatial index to search - * @param from - Center point of the search (member name or coordinates) - * @param by - Search area specification (radius or box dimensions) - * @param options - Additional search and storage options + * Constructs the MEMORY PURGE command + * + * @param parser - The command parser + * @see https://redis.io/commands/memory-purge/ */ - parseCommand(parser3, destination, source, from3, by, options2) { - parser3.push("GEOSEARCHSTORE"); - if (destination !== void 0) { - parser3.pushKey(destination); - } - (0, GEOSEARCH_1.parseGeoSearchArguments)(parser3, source, from3, by, options2); - if (options2?.STOREDIST) { - parser3.push("STOREDIST"); - } + parseCommand(parser3) { + parser3.push("MEMORY", "PURGE"); }, transformReply: void 0 }; } }); -var require_GET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GET.js"(exports2) { +var require_MEMORY_STATS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_STATS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Gets the value of a key - * @param parser - The Redis command parser - * @param key - Key to get the value of + * Constructs the MEMORY STATS command + * + * @param parser - The command parser + * @see https://redis.io/commands/memory-stats/ */ - parseCommand(parser3, key) { - parser3.push("GET"); - parser3.pushKey(key); + parseCommand(parser3) { + parser3.push("MEMORY", "STATS"); }, - transformReply: void 0 - }; - } -}); -var require_GETBIT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETBIT.js"(exports2) { + transformReply: { + 2: (rawReply, preserve, typeMapping) => { + const reply = {}; + let i2 = 0; + while (i2 < rawReply.length) { + switch (rawReply[i2].toString()) { + case "dataset.percentage": + case "peak.percentage": + case "allocator-fragmentation.ratio": + case "allocator-rss.ratio": + case "rss-overhead.ratio": + case "fragmentation": + reply[rawReply[i2++]] = generic_transformers_1.transformDoubleReply[2](rawReply[i2++], preserve, typeMapping); + break; + default: + reply[rawReply[i2++]] = rawReply[i2++]; + } + } + return reply; + }, + 3: void 0 + } + }; + } +}); +var require_MEMORY_USAGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_USAGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Returns the bit value at a given offset in a string value - * @param parser - The Redis command parser - * @param key - Key to retrieve the bit from - * @param offset - Bit offset + * Constructs the MEMORY USAGE command + * + * @param parser - The command parser + * @param key - The key to get memory usage for + * @param options - Optional parameters including SAMPLES + * @see https://redis.io/commands/memory-usage/ */ - parseCommand(parser3, key, offset) { - parser3.push("GETBIT"); + parseCommand(parser3, key, options2) { + parser3.push("MEMORY", "USAGE"); parser3.pushKey(key); - parser3.push(offset.toString()); + if (options2?.SAMPLES) { + parser3.push("SAMPLES", options2.SAMPLES.toString()); + } }, transformReply: void 0 }; } }); -var require_GETDEL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETDEL.js"(exports2) { +var require_MGET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MGET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Gets the value of a key and deletes the key - * @param parser - The Redis command parser - * @param key - Key to get and delete + * Constructs the MGET command + * + * @param parser - The command parser + * @param keys - Array of keys to get + * @see https://redis.io/commands/mget/ */ - parseCommand(parser3, key) { - parser3.push("GETDEL"); - parser3.pushKey(key); + parseCommand(parser3, keys) { + parser3.push("MGET"); + parser3.pushKeys(keys); }, transformReply: void 0 }; } }); -var require_GETEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETEX.js"(exports2) { +var require_MIGRATE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MIGRATE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Gets the value of a key and optionally sets its expiration - * @param parser - The Redis command parser - * @param key - Key to get value from - * @param options - Options for setting expiration + * Constructs the MIGRATE command + * + * @param parser - The command parser + * @param host - Target Redis instance host + * @param port - Target Redis instance port + * @param key - Key or keys to migrate + * @param destinationDb - Target database index + * @param timeout - Timeout in milliseconds + * @param options - Optional parameters including COPY, REPLACE, and AUTH + * @see https://redis.io/commands/migrate/ */ - parseCommand(parser3, key, options2) { - parser3.push("GETEX"); - parser3.pushKey(key); - if ("type" in options2) { - switch (options2.type) { - case "EX": - case "PX": - parser3.push(options2.type, options2.value.toString()); - break; - case "EXAT": - case "PXAT": - parser3.push(options2.type, (0, generic_transformers_1.transformEXAT)(options2.value)); - break; - case "PERSIST": - parser3.push("PERSIST"); - break; - } + parseCommand(parser3, host, port, key, destinationDb, timeout, options2) { + parser3.push("MIGRATE", host, port.toString()); + const isKeyArray = Array.isArray(key); + if (isKeyArray) { + parser3.push(""); } else { - if ("EX" in options2) { - parser3.push("EX", options2.EX.toString()); - } else if ("PX" in options2) { - parser3.push("PX", options2.PX.toString()); - } else if ("EXAT" in options2) { - parser3.push("EXAT", (0, generic_transformers_1.transformEXAT)(options2.EXAT)); - } else if ("PXAT" in options2) { - parser3.push("PXAT", (0, generic_transformers_1.transformPXAT)(options2.PXAT)); + parser3.push(key); + } + parser3.push(destinationDb.toString(), timeout.toString()); + if (options2?.COPY) { + parser3.push("COPY"); + } + if (options2?.REPLACE) { + parser3.push("REPLACE"); + } + if (options2?.AUTH) { + if (options2.AUTH.username) { + parser3.push("AUTH2", options2.AUTH.username, options2.AUTH.password); } else { - parser3.push("PERSIST"); + parser3.push("AUTH", options2.AUTH.password); } } + if (isKeyArray) { + parser3.push("KEYS"); + parser3.pushVariadic(key); + } }, transformReply: void 0 }; } }); -var require_GETRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETRANGE.js"(exports2) { +var require_MODULE_LIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MODULE_LIST.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns a substring of the string stored at a key - * @param parser - The Redis command parser - * @param key - Key to get substring from - * @param start - Start position of the substring - * @param end - End position of the substring + * Constructs the MODULE LIST command + * + * @param parser - The command parser + * @see https://redis.io/commands/module-list/ */ - parseCommand(parser3, key, start, end) { - parser3.push("GETRANGE"); - parser3.pushKey(key); - parser3.push(start.toString(), end.toString()); + parseCommand(parser3) { + parser3.push("MODULE", "LIST"); }, - transformReply: void 0 + transformReply: { + 2: (reply) => { + return reply.map((module15) => { + const unwrapped = module15; + return { + name: unwrapped[1], + ver: unwrapped[3] + }; + }); + }, + 3: void 0 + } }; } }); -var require_GETSET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/GETSET.js"(exports2) { +var require_MODULE_LOAD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MODULE_LOAD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Sets a key to a new value and returns its old value - * @param parser - The Redis command parser - * @param key - Key to set - * @param value - Value to set + * Constructs the MODULE LOAD command + * + * @param parser - The command parser + * @param path - Path to the module file + * @param moduleArguments - Optional arguments to pass to the module + * @see https://redis.io/commands/module-load/ */ - parseCommand(parser3, key, value) { - parser3.push("GETSET"); - parser3.pushKey(key); - parser3.push(value); + parseCommand(parser3, path8, moduleArguments) { + parser3.push("MODULE", "LOAD", path8); + if (moduleArguments) { + parser3.push(...moduleArguments); + } }, transformReply: void 0 }; } }); -var require_EXISTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXISTS.js"(exports2) { +var require_MODULE_UNLOAD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MODULE_UNLOAD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Determines if the specified keys exist - * @param parser - The Redis command parser - * @param keys - One or more keys to check + * Constructs the MODULE UNLOAD command + * + * @param parser - The command parser + * @param name - The name of the module to unload + * @see https://redis.io/commands/module-unload/ */ - parseCommand(parser3, keys) { - parser3.push("EXISTS"); - parser3.pushKeys(keys); + parseCommand(parser3, name) { + parser3.push("MODULE", "UNLOAD", name); }, transformReply: void 0 }; } }); -var require_EXPIRE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXPIRE.js"(exports2) { +var require_MOVE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MOVE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { /** - * Sets a timeout on key. After the timeout has expired, the key will be automatically deleted - * @param parser - The Redis command parser - * @param key - Key to set expiration on - * @param seconds - Number of seconds until key expiration - * @param mode - Expiration mode: NX (only if key has no expiry), XX (only if key has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) + * Constructs the MOVE command + * + * @param parser - The command parser + * @param key - The key to move + * @param db - The destination database index + * @see https://redis.io/commands/move/ */ - parseCommand(parser3, key, seconds, mode) { - parser3.push("EXPIRE"); + parseCommand(parser3, key, db2) { + parser3.push("MOVE"); parser3.pushKey(key); - parser3.push(seconds.toString()); - if (mode) { - parser3.push(mode); - } + parser3.push(db2.toString()); }, transformReply: void 0 }; } }); -var require_EXPIREAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXPIREAT.js"(exports2) { +var require_MSET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MSET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); + exports2.parseMSetArguments = void 0; + function parseMSetArguments(parser3, toSet) { + if (Array.isArray(toSet)) { + if (toSet.length == 0) { + throw new Error("empty toSet Argument"); + } + if (Array.isArray(toSet[0])) { + for (const tuple of toSet) { + parser3.pushKey(tuple[0]); + parser3.push(tuple[1]); + } + } else { + const arr = toSet; + for (let i2 = 0; i2 < arr.length; i2 += 2) { + parser3.pushKey(arr[i2]); + parser3.push(arr[i2 + 1]); + } + } + } else { + for (const tuple of Object.entries(toSet)) { + parser3.pushKey(tuple[0]); + parser3.push(tuple[1]); + } + } + } + exports2.parseMSetArguments = parseMSetArguments; exports2.default = { + IS_READ_ONLY: true, /** - * Sets the expiration for a key at a specific Unix timestamp - * @param parser - The Redis command parser - * @param key - Key to set expiration on - * @param timestamp - Unix timestamp (seconds since January 1, 1970) or Date object - * @param mode - Expiration mode: NX (only if key has no expiry), XX (only if key has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) + * Constructs the MSET command + * + * @param parser - The command parser + * @param toSet - Key-value pairs to set (array of tuples, flat array, or object) + * @see https://redis.io/commands/mset/ */ - parseCommand(parser3, key, timestamp, mode) { - parser3.push("EXPIREAT"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformEXAT)(timestamp)); - if (mode) { - parser3.push(mode); - } + parseCommand(parser3, toSet) { + parser3.push("MSET"); + return parseMSetArguments(parser3, toSet); }, transformReply: void 0 }; } }); -var require_EXPIRETIME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/EXPIRETIME.js"(exports2) { +var require_MSETNX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MSETNX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var MSET_1 = require_MSET(); exports2.default = { IS_READ_ONLY: true, /** - * Returns the absolute Unix timestamp (since January 1, 1970) at which the given key will expire - * @param parser - The Redis command parser - * @param key - Key to check expiration time + * Constructs the MSETNX command + * + * @param parser - The command parser + * @param toSet - Key-value pairs to set if none of the keys exist (array of tuples, flat array, or object) + * @see https://redis.io/commands/msetnx/ */ - parseCommand(parser3, key) { - parser3.push("EXPIRETIME"); - parser3.pushKey(key); + parseCommand(parser3, toSet) { + parser3.push("MSETNX"); + return (0, MSET_1.parseMSetArguments)(parser3, toSet); }, transformReply: void 0 }; } }); -var require_FLUSHALL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FLUSHALL.js"(exports2) { +var require_OBJECT_ENCODING = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_ENCODING.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.REDIS_FLUSH_MODES = void 0; - exports2.REDIS_FLUSH_MODES = { - ASYNC: "ASYNC", - SYNC: "SYNC" - }; exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Removes all keys from all databases - * @param parser - The Redis command parser - * @param mode - Optional flush mode (ASYNC or SYNC) + * Constructs the OBJECT ENCODING command + * + * @param parser - The command parser + * @param key - The key to get the internal encoding for + * @see https://redis.io/commands/object-encoding/ */ - parseCommand(parser3, mode) { - parser3.push("FLUSHALL"); - if (mode) { - parser3.push(mode); - } + parseCommand(parser3, key) { + parser3.push("OBJECT", "ENCODING"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_FLUSHDB = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FLUSHDB.js"(exports2) { +var require_OBJECT_FREQ = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_FREQ.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Removes all keys from the current database - * @param parser - The Redis command parser - * @param mode - Optional flush mode (ASYNC or SYNC) + * Constructs the OBJECT FREQ command + * + * @param parser - The command parser + * @param key - The key to get the access frequency for + * @see https://redis.io/commands/object-freq/ */ - parseCommand(parser3, mode) { - parser3.push("FLUSHDB"); - if (mode) { - parser3.push(mode); - } + parseCommand(parser3, key) { + parser3.push("OBJECT", "FREQ"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_FCALL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FCALL.js"(exports2) { +var require_OBJECT_IDLETIME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_IDLETIME.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var EVAL_1 = __importStar(require_EVAL()); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Invokes a Redis function - * @param parser - The Redis command parser - * @param functionName - Name of the function to call - * @param options - Function execution options including keys and arguments + * Constructs the OBJECT IDLETIME command + * + * @param parser - The command parser + * @param key - The key to get the idle time for + * @see https://redis.io/commands/object-idletime/ */ - parseCommand(...args) { - args[0].push("FCALL"); - (0, EVAL_1.parseEvalArguments)(...args); + parseCommand(parser3, key) { + parser3.push("OBJECT", "IDLETIME"); + parser3.pushKey(key); }, - transformReply: EVAL_1.default.transformReply + transformReply: void 0 }; } }); -var require_FCALL_RO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FCALL_RO.js"(exports2) { +var require_OBJECT_REFCOUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_REFCOUNT.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var EVAL_1 = __importStar(require_EVAL()); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Invokes a read-only Redis function - * @param parser - The Redis command parser - * @param functionName - Name of the function to call - * @param options - Function execution options including keys and arguments + * Constructs the OBJECT REFCOUNT command + * + * @param parser - The command parser + * @param key - The key to get the reference count for + * @see https://redis.io/commands/object-refcount/ */ - parseCommand(...args) { - args[0].push("FCALL_RO"); - (0, EVAL_1.parseEvalArguments)(...args); + parseCommand(parser3, key) { + parser3.push("OBJECT", "REFCOUNT"); + parser3.pushKey(key); }, - transformReply: EVAL_1.default.transformReply + transformReply: void 0 }; } }); -var require_FUNCTION_DELETE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_DELETE.js"(exports2) { +var require_PERSIST = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PERSIST.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, /** - * Deletes a library and all its functions - * @param parser - The Redis command parser - * @param library - Name of the library to delete + * Constructs the PERSIST command + * + * @param parser - The command parser + * @param key - The key to remove the expiration from + * @see https://redis.io/commands/persist/ */ - parseCommand(parser3, library) { - parser3.push("FUNCTION", "DELETE", library); + parseCommand(parser3, key) { + parser3.push("PERSIST"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_FUNCTION_DUMP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_DUMP.js"(exports2) { +var require_PEXPIRE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PEXPIRE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Returns a serialized payload representing the current functions loaded in the server - * @param parser - The Redis command parser + * Constructs the PEXPIRE command + * + * @param parser - The command parser + * @param key - The key to set the expiration for + * @param ms - The expiration time in milliseconds + * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT') + * @see https://redis.io/commands/pexpire/ */ - parseCommand(parser3) { - parser3.push("FUNCTION", "DUMP"); + parseCommand(parser3, key, ms, mode) { + parser3.push("PEXPIRE"); + parser3.pushKey(key); + parser3.push(ms.toString()); + if (mode) { + parser3.push(mode); + } }, transformReply: void 0 }; } }); -var require_FUNCTION_FLUSH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_FLUSH.js"(exports2) { +var require_PEXPIREAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PEXPIREAT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Deletes all the libraries and functions from a Redis server - * @param parser - The Redis command parser - * @param mode - Optional flush mode (ASYNC or SYNC) + * Constructs the PEXPIREAT command + * + * @param parser - The command parser + * @param key - The key to set the expiration for + * @param msTimestamp - The expiration timestamp in milliseconds (Unix timestamp or Date object) + * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT') + * @see https://redis.io/commands/pexpireat/ */ - parseCommand(parser3, mode) { - parser3.push("FUNCTION", "FLUSH"); + parseCommand(parser3, key, msTimestamp, mode) { + parser3.push("PEXPIREAT"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformPXAT)(msTimestamp)); if (mode) { parser3.push(mode); } @@ -37420,3500 +32227,3612 @@ var require_FUNCTION_FLUSH = __commonJS({ }; } }); -var require_FUNCTION_KILL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_KILL.js"(exports2) { +var require_PEXPIRETIME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PEXPIRETIME.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Kills a function that is currently executing - * @param parser - The Redis command parser + * Constructs the PEXPIRETIME command + * + * @param parser - The command parser + * @param key - The key to get the expiration time for in milliseconds + * @see https://redis.io/commands/pexpiretime/ */ - parseCommand(parser3) { - parser3.push("FUNCTION", "KILL"); + parseCommand(parser3, key) { + parser3.push("PEXPIRETIME"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_FUNCTION_LIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_LIST.js"(exports2) { +var require_PFADD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PFADD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Returns all libraries and functions - * @param parser - The Redis command parser - * @param options - Options for listing functions + * Constructs the PFADD command + * + * @param parser - The command parser + * @param key - The key of the HyperLogLog + * @param element - Optional elements to add + * @see https://redis.io/commands/pfadd/ */ - parseCommand(parser3, options2) { - parser3.push("FUNCTION", "LIST"); - if (options2?.LIBRARYNAME) { - parser3.push("LIBRARYNAME", options2.LIBRARYNAME); + parseCommand(parser3, key, element) { + parser3.push("PFADD"); + parser3.pushKey(key); + if (element) { + parser3.pushVariadic(element); } }, - transformReply: { - 2: (reply) => { - return reply.map((library) => { - const unwrapped = library; - return { - library_name: unwrapped[1], - engine: unwrapped[3], - functions: unwrapped[5].map((fn) => { - const unwrapped2 = fn; - return { - name: unwrapped2[1], - description: unwrapped2[3], - flags: unwrapped2[5] - }; - }) - }; - }); - }, - 3: void 0 - } + transformReply: void 0 }; } }); -var require_FUNCTION_LIST_WITHCODE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_LIST_WITHCODE.js"(exports2) { +var require_PFCOUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PFCOUNT.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var FUNCTION_LIST_1 = __importDefault(require_FUNCTION_LIST()); exports2.default = { - NOT_KEYED_COMMAND: FUNCTION_LIST_1.default.NOT_KEYED_COMMAND, - IS_READ_ONLY: FUNCTION_LIST_1.default.IS_READ_ONLY, + IS_READ_ONLY: true, /** - * Returns all libraries and functions including their source code - * @param parser - The Redis command parser - * @param options - Options for listing functions + * Constructs the PFCOUNT command + * + * @param parser - The command parser + * @param keys - One or more keys of HyperLogLog structures to count + * @see https://redis.io/commands/pfcount/ */ - parseCommand(...args) { - FUNCTION_LIST_1.default.parseCommand(...args); - args[0].push("WITHCODE"); + parseCommand(parser3, keys) { + parser3.push("PFCOUNT"); + parser3.pushKeys(keys); }, - transformReply: { - 2: (reply) => { - return reply.map((library) => { - const unwrapped = library; - return { - library_name: unwrapped[1], - engine: unwrapped[3], - functions: unwrapped[5].map((fn) => { - const unwrapped2 = fn; - return { - name: unwrapped2[1], - description: unwrapped2[3], - flags: unwrapped2[5] - }; - }), - library_code: unwrapped[7] - }; - }); - }, - 3: void 0 - } + transformReply: void 0 }; } }); -var require_FUNCTION_LOAD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_LOAD.js"(exports2) { +var require_PFMERGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PFMERGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, /** - * Loads a library to Redis - * @param parser - The Redis command parser - * @param code - Library code to load - * @param options - Function load options + * Constructs the PFMERGE command + * + * @param parser - The command parser + * @param destination - The destination key to merge to + * @param sources - One or more source keys to merge from + * @see https://redis.io/commands/pfmerge/ */ - parseCommand(parser3, code2, options2) { - parser3.push("FUNCTION", "LOAD"); - if (options2?.REPLACE) { - parser3.push("REPLACE"); + parseCommand(parser3, destination, sources) { + parser3.push("PFMERGE"); + parser3.pushKey(destination); + if (sources) { + parser3.pushKeys(sources); } - parser3.push(code2); }, transformReply: void 0 }; } }); -var require_FUNCTION_RESTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_RESTORE.js"(exports2) { +var require_PING = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PING.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Restores libraries from the dump payload - * @param parser - The Redis command parser - * @param dump - Serialized payload of functions to restore - * @param options - Options for the restore operation + * Constructs the PING command + * + * @param parser - The command parser + * @param message - Optional message to be returned instead of PONG + * @see https://redis.io/commands/ping/ */ - parseCommand(parser3, dump, options2) { - parser3.push("FUNCTION", "RESTORE", dump); - if (options2?.mode) { - parser3.push(options2.mode); + parseCommand(parser3, message) { + parser3.push("PING"); + if (message) { + parser3.push(message); } }, transformReply: void 0 }; } }); -var require_FUNCTION_STATS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/FUNCTION_STATS.js"(exports2) { +var require_PSETEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PSETEX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Returns information about the function that is currently running and information about the available execution engines - * @param parser - The Redis command parser + * Constructs the PSETEX command + * + * @param parser - The command parser + * @param key - The key to set + * @param ms - The expiration time in milliseconds + * @param value - The value to set + * @see https://redis.io/commands/psetex/ */ - parseCommand(parser3) { - parser3.push("FUNCTION", "STATS"); + parseCommand(parser3, key, ms, value) { + parser3.push("PSETEX"); + parser3.pushKey(key); + parser3.push(ms.toString(), value); }, - transformReply: { - 2: (reply) => { - return { - running_script: transformRunningScript(reply[1]), - engines: transformEngines(reply[3]) - }; - }, - 3: void 0 - } + transformReply: void 0 }; - function transformRunningScript(reply) { - if ((0, generic_transformers_1.isNullReply)(reply)) { - return null; - } - const unwraped = reply; - return { - name: unwraped[1], - command: unwraped[3], - duration_ms: unwraped[5] - }; - } - function transformEngines(reply) { - const unwraped = reply; - const engines = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < unwraped.length; i2++) { - const name = unwraped[i2], stats = unwraped[++i2], unwrapedStats = stats; - engines[name.toString()] = { - libraries_count: unwrapedStats[1], - functions_count: unwrapedStats[3] - }; - } - return engines; - } } }); -var require_HDEL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HDEL.js"(exports2) { +var require_PTTL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PTTL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + IS_READ_ONLY: true, /** - * Removes one or more fields from a hash - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param field - Field(s) to remove + * Constructs the PTTL command + * + * @param parser - The command parser + * @param key - The key to get the time to live in milliseconds + * @see https://redis.io/commands/pttl/ */ - parseCommand(parser3, key, field) { - parser3.push("HDEL"); + parseCommand(parser3, key) { + parser3.push("PTTL"); parser3.pushKey(key); - parser3.pushVariadic(field); }, transformReply: void 0 }; } }); -var require_HELLO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HELLO.js"(exports2) { +var require_PUBLISH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBLISH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + IS_FORWARD_COMMAND: true, /** - * Handshakes with the Redis server and switches to the specified protocol version - * @param parser - The Redis command parser - * @param protover - Protocol version to use - * @param options - Additional options for authentication and connection naming + * Constructs the PUBLISH command + * + * @param parser - The command parser + * @param channel - The channel to publish to + * @param message - The message to publish + * @see https://redis.io/commands/publish/ */ - parseCommand(parser3, protover, options2) { - parser3.push("HELLO"); - if (protover) { - parser3.push(protover.toString()); - if (options2?.AUTH) { - parser3.push("AUTH", options2.AUTH.username, options2.AUTH.password); - } - if (options2?.SETNAME) { - parser3.push("SETNAME", options2.SETNAME); - } - } + parseCommand(parser3, channel, message) { + parser3.push("PUBLISH", channel, message); }, - transformReply: { - 2: (reply) => ({ - server: reply[1], - version: reply[3], - proto: reply[5], - id: reply[7], - mode: reply[9], - role: reply[11], - modules: reply[13] - }), - 3: void 0 - } + transformReply: void 0 }; } }); -var require_HEXISTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXISTS.js"(exports2) { +var require_PUBSUB_CHANNELS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_CHANNELS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Determines whether a field exists in a hash - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param field - Field to check + * Constructs the PUBSUB CHANNELS command + * + * @param parser - The command parser + * @param pattern - Optional pattern to filter channels + * @see https://redis.io/commands/pubsub-channels/ */ - parseCommand(parser3, key, field) { - parser3.push("HEXISTS"); - parser3.pushKey(key); - parser3.push(field); + parseCommand(parser3, pattern) { + parser3.push("PUBSUB", "CHANNELS"); + if (pattern) { + parser3.push(pattern); + } }, transformReply: void 0 }; } }); -var require_HEXPIRE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXPIRE.js"(exports2) { +var require_PUBSUB_NUMPAT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_NUMPAT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.HASH_EXPIRATION = void 0; - exports2.HASH_EXPIRATION = { - /** The field does not exist */ - FIELD_NOT_EXISTS: -2, - /** Specified NX | XX | GT | LT condition not met */ - CONDITION_NOT_MET: 0, - /** Expiration time was set or updated */ - UPDATED: 1, - /** Field deleted because the specified expiration time is in the past */ - DELETED: 2 - }; exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Sets a timeout on hash fields. After the timeout has expired, the fields will be automatically deleted - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param fields - Fields to set expiration on - * @param seconds - Number of seconds until field expiration - * @param mode - Expiration mode: NX (only if field has no expiry), XX (only if field has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) + * Constructs the PUBSUB NUMPAT command + * + * @param parser - The command parser + * @see https://redis.io/commands/pubsub-numpat/ */ - parseCommand(parser3, key, fields, seconds, mode) { - parser3.push("HEXPIRE"); - parser3.pushKey(key); - parser3.push(seconds.toString()); - if (mode) { - parser3.push(mode); - } - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parseCommand(parser3) { + parser3.push("PUBSUB", "NUMPAT"); }, transformReply: void 0 }; } }); -var require_HEXPIREAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXPIREAT.js"(exports2) { +var require_PUBSUB_NUMSUB = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_NUMSUB.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Sets the expiration for hash fields at a specific Unix timestamp - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param fields - Fields to set expiration on - * @param timestamp - Unix timestamp (seconds since January 1, 1970) or Date object - * @param mode - Expiration mode: NX (only if field has no expiry), XX (only if field has existing expiry), GT (only if new expiry is greater than current), LT (only if new expiry is less than current) + * Constructs the PUBSUB NUMSUB command + * + * @param parser - The command parser + * @param channels - Optional channel names to get subscription count for + * @see https://redis.io/commands/pubsub-numsub/ */ - parseCommand(parser3, key, fields, timestamp, mode) { - parser3.push("HEXPIREAT"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformEXAT)(timestamp)); - if (mode) { - parser3.push(mode); + parseCommand(parser3, channels) { + parser3.push("PUBSUB", "NUMSUB"); + if (channels) { + parser3.pushVariadic(channels); } - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); }, - transformReply: void 0 + /** + * Transforms the PUBSUB NUMSUB reply into a record of channel name to subscriber count + * + * @param rawReply - The raw reply from Redis + * @returns Record mapping channel names to their subscriber counts + */ + transformReply(rawReply) { + const reply = /* @__PURE__ */ Object.create(null); + let i2 = 0; + while (i2 < rawReply.length) { + reply[rawReply[i2++].toString()] = Number(rawReply[i2++]); + } + return reply; + } }; } }); -var require_HEXPIRETIME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HEXPIRETIME.js"(exports2) { +var require_PUBSUB_SHARDNUMSUB = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_SHARDNUMSUB.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.HASH_EXPIRATION_TIME = void 0; - exports2.HASH_EXPIRATION_TIME = { - /** The field does not exist */ - FIELD_NOT_EXISTS: -2, - /** The field exists but has no associated expire */ - NO_EXPIRATION: -1 - }; exports2.default = { IS_READ_ONLY: true, /** - * Returns the absolute Unix timestamp (since January 1, 1970) at which the given hash fields will expire - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param fields - Fields to check expiration time + * Constructs the PUBSUB SHARDNUMSUB command + * + * @param parser - The command parser + * @param channels - Optional shard channel names to get subscription count for + * @see https://redis.io/commands/pubsub-shardnumsub/ */ - parseCommand(parser3, key, fields) { - parser3.push("HEXPIRETIME"); - parser3.pushKey(key); - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parseCommand(parser3, channels) { + parser3.push("PUBSUB", "SHARDNUMSUB"); + if (channels) { + parser3.pushVariadic(channels); + } }, - transformReply: void 0 + /** + * Transforms the PUBSUB SHARDNUMSUB reply into a record of shard channel name to subscriber count + * + * @param reply - The raw reply from Redis + * @returns Record mapping shard channel names to their subscriber counts + */ + transformReply(reply) { + const transformedReply = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < reply.length; i2 += 2) { + transformedReply[reply[i2].toString()] = reply[i2 + 1]; + } + return transformedReply; + } }; } }); -var require_HGET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGET.js"(exports2) { +var require_PUBSUB_SHARDCHANNELS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_SHARDCHANNELS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Gets the value of a field in a hash - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param field - Field to get the value of + * Constructs the PUBSUB SHARDCHANNELS command + * + * @param parser - The command parser + * @param pattern - Optional pattern to filter shard channels + * @see https://redis.io/commands/pubsub-shardchannels/ */ - parseCommand(parser3, key, field) { - parser3.push("HGET"); - parser3.pushKey(key); - parser3.push(field); + parseCommand(parser3, pattern) { + parser3.push("PUBSUB", "SHARDCHANNELS"); + if (pattern) { + parser3.push(pattern); + } }, transformReply: void 0 }; } }); -var require_HGETALL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGETALL.js"(exports2) { +var require_RANDOMKEY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RANDOMKEY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Gets all fields and values in a hash - * @param parser - The Redis command parser - * @param key - Key of the hash + * Constructs the RANDOMKEY command + * + * @param parser - The command parser + * @see https://redis.io/commands/randomkey/ */ - parseCommand(parser3, key) { - parser3.push("HGETALL"); - parser3.pushKey(key); + parseCommand(parser3) { + parser3.push("RANDOMKEY"); }, - TRANSFORM_LEGACY_REPLY: true, - transformReply: { - 2: generic_transformers_1.transformTuplesReply, - 3: void 0 - } + transformReply: void 0 }; } }); -var require_HGETDEL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGETDEL.js"(exports2) { +var require_READONLY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/READONLY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Gets and deletes the specified fields from a hash - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param fields - Fields to get and delete + * Constructs the READONLY command + * + * @param parser - The command parser + * @see https://redis.io/commands/readonly/ */ - parseCommand(parser3, key, fields) { - parser3.push("HGETDEL"); - parser3.pushKey(key); - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parseCommand(parser3) { + parser3.push("READONLY"); }, transformReply: void 0 }; } }); -var require_HGETEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HGETEX.js"(exports2) { +var require_RENAME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RENAME.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + IS_READ_ONLY: true, /** - * Gets the values of the specified fields in a hash and optionally sets their expiration - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param fields - Fields to get values from - * @param options - Options for setting expiration + * Constructs the RENAME command + * + * @param parser - The command parser + * @param key - The key to rename + * @param newKey - The new key name + * @see https://redis.io/commands/rename/ */ - parseCommand(parser3, key, fields, options2) { - parser3.push("HGETEX"); - parser3.pushKey(key); - if (options2?.expiration) { - if (typeof options2.expiration === "string") { - parser3.push(options2.expiration); - } else if (options2.expiration.type === "PERSIST") { - parser3.push("PERSIST"); - } else { - parser3.push(options2.expiration.type, options2.expiration.value.toString()); - } - } - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parseCommand(parser3, key, newKey) { + parser3.push("RENAME"); + parser3.pushKeys([key, newKey]); }, transformReply: void 0 }; } }); -var require_HINCRBY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HINCRBY.js"(exports2) { +var require_RENAMENX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RENAMENX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + IS_READ_ONLY: true, /** - * Increments the integer value of a field in a hash by the given number - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param field - Field to increment - * @param increment - Increment amount + * Constructs the RENAMENX command + * + * @param parser - The command parser + * @param key - The key to rename + * @param newKey - The new key name, if it doesn't exist + * @see https://redis.io/commands/renamenx/ */ - parseCommand(parser3, key, field, increment2) { - parser3.push("HINCRBY"); - parser3.pushKey(key); - parser3.push(field, increment2.toString()); + parseCommand(parser3, key, newKey) { + parser3.push("RENAMENX"); + parser3.pushKeys([key, newKey]); }, transformReply: void 0 }; } }); -var require_HINCRBYFLOAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HINCRBYFLOAT.js"(exports2) { +var require_REPLICAOF = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/REPLICAOF.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Increments the float value of a field in a hash by the given amount - * @param parser - The Redis command parser - * @param key - Key of the hash - * @param field - Field to increment - * @param increment - Increment amount (float) + * Constructs the REPLICAOF command + * + * @param parser - The command parser + * @param host - The host of the master to replicate from + * @param port - The port of the master to replicate from + * @see https://redis.io/commands/replicaof/ */ - parseCommand(parser3, key, field, increment2) { - parser3.push("HINCRBYFLOAT"); - parser3.pushKey(key); - parser3.push(field, increment2.toString()); + parseCommand(parser3, host, port) { + parser3.push("REPLICAOF", host, port.toString()); }, transformReply: void 0 }; } }); -var require_HKEYS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HKEYS.js"(exports2) { +var require_RESTORE_ASKING = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RESTORE-ASKING.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Gets all field names in a hash - * @param parser - The Redis command parser - * @param key - Key of the hash + * Constructs the RESTORE-ASKING command + * + * @param parser - The command parser + * @see https://redis.io/commands/restore-asking/ */ - parseCommand(parser3, key) { - parser3.push("HKEYS"); - parser3.pushKey(key); + parseCommand(parser3) { + parser3.push("RESTORE-ASKING"); }, transformReply: void 0 }; } }); -var require_HLEN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HLEN.js"(exports2) { +var require_RESTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RESTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Gets the number of fields in a hash. - * @param parser - The Redis command parser. - * @param key - Key of the hash. + * Constructs the RESTORE command + * + * @param parser - The command parser + * @param key - The key to restore + * @param ttl - Time to live in milliseconds, 0 for no expiry + * @param serializedValue - The serialized value from DUMP command + * @param options - Options for the RESTORE command + * @see https://redis.io/commands/restore/ */ - parseCommand(parser3, key) { - parser3.push("HLEN"); + parseCommand(parser3, key, ttl, serializedValue, options2) { + parser3.push("RESTORE"); parser3.pushKey(key); + parser3.push(ttl.toString(), serializedValue); + if (options2?.REPLACE) { + parser3.push("REPLACE"); + } + if (options2?.ABSTTL) { + parser3.push("ABSTTL"); + } + if (options2?.IDLETIME) { + parser3.push("IDLETIME", options2.IDLETIME.toString()); + } + if (options2?.FREQ) { + parser3.push("FREQ", options2.FREQ.toString()); + } }, transformReply: void 0 }; } }); -var require_HMGET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HMGET.js"(exports2) { +var require_ROLE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ROLE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Gets the values of all the specified fields in a hash. - * @param parser - The Redis command parser. - * @param key - Key of the hash. - * @param fields - Fields to get from the hash. + * Constructs the ROLE command + * + * @param parser - The command parser + * @see https://redis.io/commands/role/ */ - parseCommand(parser3, key, fields) { - parser3.push("HMGET"); - parser3.pushKey(key); - parser3.pushVariadic(fields); + parseCommand(parser3) { + parser3.push("ROLE"); }, - transformReply: void 0 + /** + * Transforms the ROLE reply into a structured object + * + * @param reply - The raw reply from Redis + * @returns Structured object representing role information + */ + transformReply(reply) { + switch (reply[0]) { + case "master": { + const [role, replicationOffest, replicas] = reply; + return { + role, + replicationOffest, + replicas: replicas.map((replica) => { + const [host, port, replicationOffest2] = replica; + return { + host, + port: Number(port), + replicationOffest: Number(replicationOffest2) + }; + }) + }; + } + case "slave": { + const [role, masterHost, masterPort, state, dataReceived] = reply; + return { + role, + master: { + host: masterHost, + port: masterPort + }, + state, + dataReceived + }; + } + case "sentinel": { + const [role, masterNames] = reply; + return { + role, + masterNames + }; + } + } + } }; } }); -var require_HPERSIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPERSIST.js"(exports2) { +var require_RPOP_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPOP_COUNT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { /** - * Removes the expiration from the specified fields in a hash. - * @param parser - The Redis command parser. - * @param key - Key of the hash. - * @param fields - Fields to remove expiration from. + * Constructs the RPOP command with count parameter + * + * @param parser - The command parser + * @param key - The list key to pop from + * @param count - The number of elements to pop + * @see https://redis.io/commands/rpop/ */ - parseCommand(parser3, key, fields) { - parser3.push("HPERSIST"); + parseCommand(parser3, key, count) { + parser3.push("RPOP"); parser3.pushKey(key); - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parser3.push(count.toString()); }, transformReply: void 0 }; } }); -var require_HPEXPIRE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPEXPIRE.js"(exports2) { +var require_RPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPOP.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { /** - * Parses the arguments for the `HPEXPIRE` command. + * Constructs the RPOP command * - * @param parser - The command parser instance. - * @param key - The key of the hash. - * @param fields - The fields to set the expiration for. - * @param ms - The expiration time in milliseconds. - * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT'). + * @param parser - The command parser + * @param key - The list key to pop from + * @see https://redis.io/commands/rpop/ */ - parseCommand(parser3, key, fields, ms, mode) { - parser3.push("HPEXPIRE"); + parseCommand(parser3, key) { + parser3.push("RPOP"); parser3.pushKey(key); - parser3.push(ms.toString()); - if (mode) { - parser3.push(mode); - } - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); }, transformReply: void 0 }; } }); -var require_HPEXPIREAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPEXPIREAT.js"(exports2) { +var require_RPOPLPUSH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPOPLPUSH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { - IS_READ_ONLY: true, /** - * Parses the arguments for the `HPEXPIREAT` command. + * Constructs the RPOPLPUSH command * - * @param parser - The command parser instance. - * @param key - The key of the hash. - * @param fields - The fields to set the expiration for. - * @param timestamp - The expiration timestamp (Unix timestamp or Date object). - * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT'). + * @param parser - The command parser + * @param source - The source list key + * @param destination - The destination list key + * @see https://redis.io/commands/rpoplpush/ */ - parseCommand(parser3, key, fields, timestamp, mode) { - parser3.push("HPEXPIREAT"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformPXAT)(timestamp)); - if (mode) { - parser3.push(mode); - } - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parseCommand(parser3, source, destination) { + parser3.push("RPOPLPUSH"); + parser3.pushKeys([source, destination]); }, transformReply: void 0 }; } }); -var require_HPEXPIRETIME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPEXPIRETIME.js"(exports2) { +var require_RPUSH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPUSH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, /** - * Constructs the HPEXPIRETIME command + * Constructs the RPUSH command * * @param parser - The command parser - * @param key - The key to retrieve expiration time for - * @param fields - The fields to retrieve expiration time for - * @see https://redis.io/commands/hpexpiretime/ + * @param key - The list key to push to + * @param element - One or more elements to push + * @see https://redis.io/commands/rpush/ */ - parseCommand(parser3, key, fields) { - parser3.push("HPEXPIRETIME"); + parseCommand(parser3, key, element) { + parser3.push("RPUSH"); parser3.pushKey(key); - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parser3.pushVariadic(element); }, transformReply: void 0 }; } }); -var require_HPTTL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HPTTL.js"(exports2) { +var require_RPUSHX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPUSHX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, /** - * Constructs the HPTTL command + * Constructs the RPUSHX command * * @param parser - The command parser - * @param key - The key to check time-to-live for - * @param fields - The fields to check time-to-live for - * @see https://redis.io/commands/hpttl/ + * @param key - The list key to push to (only if it exists) + * @param element - One or more elements to push + * @see https://redis.io/commands/rpushx/ */ - parseCommand(parser3, key, fields) { - parser3.push("HPTTL"); + parseCommand(parser3, key, element) { + parser3.push("RPUSHX"); parser3.pushKey(key); - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parser3.pushVariadic(element); }, transformReply: void 0 }; } }); -var require_HRANDFIELD_COUNT_WITHVALUES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HRANDFIELD_COUNT_WITHVALUES.js"(exports2) { +var require_SADD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SADD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, /** - * Constructs the HRANDFIELD command with count parameter and WITHVALUES option + * Constructs the SADD command * * @param parser - The command parser - * @param key - The key of the hash to get random fields from - * @param count - The number of fields to return (positive: unique fields, negative: may repeat fields) - * @see https://redis.io/commands/hrandfield/ + * @param key - The set key to add members to + * @param members - One or more members to add to the set + * @see https://redis.io/commands/sadd/ */ - parseCommand(parser3, key, count) { - parser3.push("HRANDFIELD"); + parseCommand(parser3, key, members) { + parser3.push("SADD"); parser3.pushKey(key); - parser3.push(count.toString(), "WITHVALUES"); + parser3.pushVariadic(members); }, - transformReply: { - 2: (rawReply) => { - const reply = []; - let i2 = 0; - while (i2 < rawReply.length) { - reply.push({ - field: rawReply[i2++], - value: rawReply[i2++] - }); - } - return reply; - }, - 3: (reply) => { - return reply.map((entry) => { - const [field, value] = entry; - return { - field, - value - }; - }); - } - } + transformReply: void 0 }; } }); -var require_HRANDFIELD_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HRANDFIELD_COUNT.js"(exports2) { +var require_SCARD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCARD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the HRANDFIELD command with count parameter + * Constructs the SCARD command * * @param parser - The command parser - * @param key - The key of the hash to get random fields from - * @param count - The number of fields to return (positive: unique fields, negative: may repeat fields) - * @see https://redis.io/commands/hrandfield/ + * @param key - The set key to get the cardinality of + * @see https://redis.io/commands/scard/ */ - parseCommand(parser3, key, count) { - parser3.push("HRANDFIELD"); + parseCommand(parser3, key) { + parser3.push("SCARD"); parser3.pushKey(key); - parser3.push(count.toString()); }, transformReply: void 0 }; } }); -var require_HRANDFIELD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HRANDFIELD.js"(exports2) { +var require_SCRIPT_DEBUG = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_DEBUG.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the HRANDFIELD command + * Constructs the SCRIPT DEBUG command * * @param parser - The command parser - * @param key - The key of the hash to get a random field from - * @see https://redis.io/commands/hrandfield/ + * @param mode - Debug mode: YES, SYNC, or NO + * @see https://redis.io/commands/script-debug/ */ - parseCommand(parser3, key) { - parser3.push("HRANDFIELD"); - parser3.pushKey(key); + parseCommand(parser3, mode) { + parser3.push("SCRIPT", "DEBUG", mode); }, transformReply: void 0 }; } }); -var require_SCAN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCAN.js"(exports2) { +var require_SCRIPT_EXISTS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_EXISTS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.pushScanArguments = exports2.parseScanArguments = void 0; - function parseScanArguments(parser3, cursor, options2) { - parser3.push(cursor); - if (options2?.MATCH) { - parser3.push("MATCH", options2.MATCH); - } - if (options2?.COUNT) { - parser3.push("COUNT", options2.COUNT.toString()); - } - } - exports2.parseScanArguments = parseScanArguments; - function pushScanArguments(args, cursor, options2) { - args.push(cursor.toString()); - if (options2?.MATCH) { - args.push("MATCH", options2.MATCH); - } - if (options2?.COUNT) { - args.push("COUNT", options2.COUNT.toString()); - } - return args; - } - exports2.pushScanArguments = pushScanArguments; exports2.default = { NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the SCAN command + * Constructs the SCRIPT EXISTS command * * @param parser - The command parser - * @param cursor - The cursor position to start scanning from - * @param options - Scan options - * @see https://redis.io/commands/scan/ + * @param sha1 - One or more SHA1 digests of scripts + * @see https://redis.io/commands/script-exists/ */ - parseCommand(parser3, cursor, options2) { - parser3.push("SCAN"); - parseScanArguments(parser3, cursor, options2); - if (options2?.TYPE) { - parser3.push("TYPE", options2.TYPE); - } + parseCommand(parser3, sha1) { + parser3.push("SCRIPT", "EXISTS"); + parser3.pushVariadic(sha1); }, - /** - * Transforms the SCAN reply into a structured object - * - * @param reply - The raw reply containing cursor and keys - * @returns Object with cursor and keys properties - */ - transformReply([cursor, keys]) { - return { - cursor, - keys - }; - } + transformReply: void 0 }; } }); -var require_HSCAN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSCAN.js"(exports2) { +var require_SCRIPT_FLUSH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_FLUSH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var SCAN_1 = require_SCAN(); exports2.default = { + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the HSCAN command + * Constructs the SCRIPT FLUSH command * * @param parser - The command parser - * @param key - The key of the hash to scan - * @param cursor - The cursor position to start scanning from - * @param options - Options for the scan (COUNT, MATCH, TYPE) - * @see https://redis.io/commands/hscan/ + * @param mode - Optional flush mode: ASYNC or SYNC + * @see https://redis.io/commands/script-flush/ */ - parseCommand(parser3, key, cursor, options2) { - parser3.push("HSCAN"); - parser3.pushKey(key); - (0, SCAN_1.parseScanArguments)(parser3, cursor, options2); - }, - transformReply([cursor, rawEntries]) { - const entries = []; - let i2 = 0; - while (i2 < rawEntries.length) { - entries.push({ - field: rawEntries[i2++], - value: rawEntries[i2++] - }); + parseCommand(parser3, mode) { + parser3.push("SCRIPT", "FLUSH"); + if (mode) { + parser3.push(mode); } - return { - cursor, - entries - }; - } + }, + transformReply: void 0 }; } }); -var require_HSCAN_NOVALUES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSCAN_NOVALUES.js"(exports2) { +var require_SCRIPT_KILL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_KILL.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var HSCAN_1 = __importDefault(require_HSCAN()); exports2.default = { + NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the HSCAN command with NOVALUES option + * Constructs the SCRIPT KILL command * - * @param args - The same parameters as HSCAN command - * @see https://redis.io/commands/hscan/ + * @param parser - The command parser + * @see https://redis.io/commands/script-kill/ */ - parseCommand(...args) { - const parser3 = args[0]; - HSCAN_1.default.parseCommand(...args); - parser3.push("NOVALUES"); + parseCommand(parser3) { + parser3.push("SCRIPT", "KILL"); }, - transformReply([cursor, fields]) { - return { - cursor, - fields - }; - } + transformReply: void 0 }; } }); -var require_HSET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSET.js"(exports2) { +var require_SCRIPT_LOAD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_LOAD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Constructs the HSET command + * Constructs the SCRIPT LOAD command * * @param parser - The command parser - * @param key - The key of the hash - * @param value - Either the field name (when using single field) or an object/map/array of field-value pairs - * @param fieldValue - The value to set (only used with single field variant) - * @see https://redis.io/commands/hset/ + * @param script - The Lua script to load + * @see https://redis.io/commands/script-load/ */ - parseCommand(parser3, ...[key, value, fieldValue]) { - parser3.push("HSET"); - parser3.pushKey(key); - if (typeof value === "string" || typeof value === "number" || value instanceof Buffer) { - parser3.push(convertValue(value), convertValue(fieldValue)); - } else if (value instanceof Map) { - pushMap(parser3, value); - } else if (Array.isArray(value)) { - pushTuples(parser3, value); - } else { - pushObject(parser3, value); - } + parseCommand(parser3, script) { + parser3.push("SCRIPT", "LOAD", script); }, transformReply: void 0 }; - function pushMap(parser3, map) { - for (const [key, value] of map.entries()) { - parser3.push(convertValue(key), convertValue(value)); - } - } - function pushTuples(parser3, tuples) { - for (const tuple of tuples) { - if (Array.isArray(tuple)) { - pushTuples(parser3, tuple); - continue; - } - parser3.push(convertValue(tuple)); - } - } - function pushObject(parser3, object2) { - for (const key of Object.keys(object2)) { - parser3.push(convertValue(key), convertValue(object2[key])); - } - } - function convertValue(value) { - return typeof value === "number" ? value.toString() : value; - } } }); -var require_HSETEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSETEX.js"(exports2) { +var require_SDIFF = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SDIFF.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var parser_1 = require_parser(); exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Constructs the HSETEX command + * Constructs the SDIFF command * * @param parser - The command parser - * @param key - The key of the hash - * @param fields - Object, Map, or Array of field-value pairs to set - * @param options - Optional configuration for expiration and mode settings - * @see https://redis.io/commands/hsetex/ + * @param keys - One or more set keys to compute the difference from + * @see https://redis.io/commands/sdiff/ */ - parseCommand(parser3, key, fields, options2) { - parser3.push("HSETEX"); - parser3.pushKey(key); - if (options2?.mode) { - parser3.push(options2.mode); - } - if (options2?.expiration) { - if (typeof options2.expiration === "string") { - parser3.push(options2.expiration); - } else if (options2.expiration.type === "KEEPTTL") { - parser3.push("KEEPTTL"); - } else { - parser3.push(options2.expiration.type, options2.expiration.value.toString()); - } - } - parser3.push("FIELDS"); - if (fields instanceof Map) { - pushMap(parser3, fields); - } else if (Array.isArray(fields)) { - pushTuples(parser3, fields); - } else { - pushObject(parser3, fields); - } + parseCommand(parser3, keys) { + parser3.push("SDIFF"); + parser3.pushKeys(keys); }, transformReply: void 0 }; - function pushMap(parser3, map) { - parser3.push(map.size.toString()); - for (const [key, value] of map.entries()) { - parser3.push(convertValue(key), convertValue(value)); - } - } - function pushTuples(parser3, tuples) { - const tmpParser = new parser_1.BasicCommandParser(); - _pushTuples(tmpParser, tuples); - if (tmpParser.redisArgs.length % 2 != 0) { - throw Error("invalid number of arguments, expected key value ....[key value] pairs, got key without value"); - } - parser3.push((tmpParser.redisArgs.length / 2).toString()); - parser3.push(...tmpParser.redisArgs); - } - function _pushTuples(parser3, tuples) { - for (const tuple of tuples) { - if (Array.isArray(tuple)) { - _pushTuples(parser3, tuple); - continue; - } - parser3.push(convertValue(tuple)); - } - } - function pushObject(parser3, object2) { - const len = Object.keys(object2).length; - if (len == 0) { - throw Error("object without keys"); - } - parser3.push(len.toString()); - for (const key of Object.keys(object2)) { - parser3.push(convertValue(key), convertValue(object2[key])); - } - } - function convertValue(value) { - return typeof value === "number" ? value.toString() : value; - } } }); -var require_HSETNX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSETNX.js"(exports2) { +var require_SDIFFSTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SDIFFSTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, /** - * Constructs the HSETNX command + * Constructs the SDIFFSTORE command * * @param parser - The command parser - * @param key - The key of the hash - * @param field - The field to set if it does not exist - * @param value - The value to set - * @see https://redis.io/commands/hsetnx/ + * @param destination - The destination key to store the result + * @param keys - One or more set keys to compute the difference from + * @see https://redis.io/commands/sdiffstore/ */ - parseCommand(parser3, key, field, value) { - parser3.push("HSETNX"); - parser3.pushKey(key); - parser3.push(field, value); + parseCommand(parser3, destination, keys) { + parser3.push("SDIFFSTORE"); + parser3.pushKey(destination); + parser3.pushKeys(keys); }, transformReply: void 0 }; } }); -var require_HSTRLEN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HSTRLEN.js"(exports2) { +var require_SET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SET.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, /** - * Constructs the HSTRLEN command + * Constructs the SET command * * @param parser - The command parser - * @param key - The key of the hash - * @param field - The field to get the string length of - * @see https://redis.io/commands/hstrlen/ + * @param key - The key to set + * @param value - The value to set + * @param options - Additional options for the SET command + * @see https://redis.io/commands/set/ */ - parseCommand(parser3, key, field) { - parser3.push("HSTRLEN"); + parseCommand(parser3, key, value, options2) { + parser3.push("SET"); parser3.pushKey(key); - parser3.push(field); + parser3.push(typeof value === "number" ? value.toString() : value); + if (options2?.expiration) { + if (typeof options2.expiration === "string") { + parser3.push(options2.expiration); + } else if (options2.expiration.type === "KEEPTTL") { + parser3.push("KEEPTTL"); + } else { + parser3.push(options2.expiration.type, options2.expiration.value.toString()); + } + } else if (options2?.EX !== void 0) { + parser3.push("EX", options2.EX.toString()); + } else if (options2?.PX !== void 0) { + parser3.push("PX", options2.PX.toString()); + } else if (options2?.EXAT !== void 0) { + parser3.push("EXAT", options2.EXAT.toString()); + } else if (options2?.PXAT !== void 0) { + parser3.push("PXAT", options2.PXAT.toString()); + } else if (options2?.KEEPTTL) { + parser3.push("KEEPTTL"); + } + if (options2?.condition) { + parser3.push(options2.condition); + } else if (options2?.NX) { + parser3.push("NX"); + } else if (options2?.XX) { + parser3.push("XX"); + } + if (options2?.GET) { + parser3.push("GET"); + } }, transformReply: void 0 }; } }); -var require_HTTL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HTTL.js"(exports2) { +var require_SETBIT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETBIT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Returns the remaining time to live of field(s) in a hash. - * @param parser - The Redis command parser. - * @param key - Key of the hash. - * @param fields - Fields to check time to live. + * Constructs the SETBIT command + * + * @param parser - The command parser + * @param key - The key to set the bit on + * @param offset - The bit offset (zero-based) + * @param value - The bit value (0 or 1) + * @see https://redis.io/commands/setbit/ */ - parseCommand(parser3, key, fields) { - parser3.push("HTTL"); + parseCommand(parser3, key, offset, value) { + parser3.push("SETBIT"); parser3.pushKey(key); - parser3.push("FIELDS"); - parser3.pushVariadicWithLength(fields); + parser3.push(offset.toString(), value.toString()); }, transformReply: void 0 }; } }); -var require_HVALS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/HVALS.js"(exports2) { +var require_SETEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETEX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, /** - * Gets all values in a hash. - * @param parser - The Redis command parser. - * @param key - Key of the hash. + * Constructs the SETEX command + * + * @param parser - The command parser + * @param key - The key to set + * @param seconds - The expiration time in seconds + * @param value - The value to set + * @see https://redis.io/commands/setex/ */ - parseCommand(parser3, key) { - parser3.push("HVALS"); + parseCommand(parser3, key, seconds, value) { + parser3.push("SETEX"); parser3.pushKey(key); + parser3.push(seconds.toString(), value); }, transformReply: void 0 }; } }); -var require_INCR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INCR.js"(exports2) { +var require_SETNX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETNX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { /** - * Constructs the INCR command + * Constructs the SETNX command * * @param parser - The command parser - * @param key - The key to increment - * @see https://redis.io/commands/incr/ + * @param key - The key to set if it doesn't exist + * @param value - The value to set + * @see https://redis.io/commands/setnx/ */ - parseCommand(parser3, key) { - parser3.push("INCR"); + parseCommand(parser3, key, value) { + parser3.push("SETNX"); parser3.pushKey(key); + parser3.push(value); }, transformReply: void 0 }; } }); -var require_INCRBY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INCRBY.js"(exports2) { +var require_SETRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETRANGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { /** - * Constructs the INCRBY command + * Constructs the SETRANGE command * * @param parser - The command parser - * @param key - The key to increment - * @param increment - The amount to increment by - * @see https://redis.io/commands/incrby/ + * @param key - The key to modify + * @param offset - The offset at which to start writing + * @param value - The value to write at the offset + * @see https://redis.io/commands/setrange/ */ - parseCommand(parser3, key, increment2) { - parser3.push("INCRBY"); + parseCommand(parser3, key, offset, value) { + parser3.push("SETRANGE"); parser3.pushKey(key); - parser3.push(increment2.toString()); + parser3.push(offset.toString(), value); }, transformReply: void 0 }; } }); -var require_INCRBYFLOAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INCRBYFLOAT.js"(exports2) { +var require_SINTER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SINTER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Constructs the INCRBYFLOAT command + * Constructs the SINTER command * * @param parser - The command parser - * @param key - The key to increment - * @param increment - The floating-point value to increment by - * @see https://redis.io/commands/incrbyfloat/ + * @param keys - One or more set keys to compute the intersection from + * @see https://redis.io/commands/sinter/ */ - parseCommand(parser3, key, increment2) { - parser3.push("INCRBYFLOAT"); - parser3.pushKey(key); - parser3.push(increment2.toString()); + parseCommand(parser3, keys) { + parser3.push("SINTER"); + parser3.pushKeys(keys); }, transformReply: void 0 }; } }); -var require_INFO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/INFO.js"(exports2) { +var require_SINTERCARD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SINTERCARD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the INFO command + * Constructs the SINTERCARD command * * @param parser - The command parser - * @param section - Optional specific section of information to retrieve - * @see https://redis.io/commands/info/ + * @param keys - One or more set keys to compute the intersection cardinality from + * @param options - Options for the SINTERCARD command or a number for LIMIT (backwards compatibility) + * @see https://redis.io/commands/sintercard/ */ - parseCommand(parser3, section) { - parser3.push("INFO"); - if (section) { - parser3.push(section); + parseCommand(parser3, keys, options2) { + parser3.push("SINTERCARD"); + parser3.pushKeysLength(keys); + if (typeof options2 === "number") { + parser3.push("LIMIT", options2.toString()); + } else if (options2?.LIMIT !== void 0) { + parser3.push("LIMIT", options2.LIMIT.toString()); } }, transformReply: void 0 }; } }); -var require_KEYS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/KEYS.js"(exports2) { +var require_SINTERSTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SINTERSTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the KEYS command + * Constructs the SINTERSTORE command * * @param parser - The command parser - * @param pattern - The pattern to match keys against - * @see https://redis.io/commands/keys/ + * @param destination - The destination key to store the result + * @param keys - One or more set keys to compute the intersection from + * @see https://redis.io/commands/sinterstore/ */ - parseCommand(parser3, pattern) { - parser3.push("KEYS", pattern); + parseCommand(parser3, destination, keys) { + parser3.push("SINTERSTORE"); + parser3.pushKey(destination); + parser3.pushKeys(keys); }, transformReply: void 0 }; } }); -var require_LASTSAVE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LASTSAVE.js"(exports2) { +var require_SISMEMBER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SISMEMBER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the LASTSAVE command + * Constructs the SISMEMBER command * * @param parser - The command parser - * @see https://redis.io/commands/lastsave/ + * @param key - The set key to check membership in + * @param member - The member to check for existence + * @see https://redis.io/commands/sismember/ */ - parseCommand(parser3) { - parser3.push("LASTSAVE"); + parseCommand(parser3, key, member) { + parser3.push("SISMEMBER"); + parser3.pushKey(key); + parser3.push(member); }, transformReply: void 0 }; } }); -var require_LATENCY_DOCTOR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_DOCTOR.js"(exports2) { +var require_SMEMBERS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SMEMBERS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the LATENCY DOCTOR command + * Constructs the SMEMBERS command * * @param parser - The command parser - * @see https://redis.io/commands/latency-doctor/ + * @param key - The set key to get all members from + * @see https://redis.io/commands/smembers/ */ - parseCommand(parser3) { - parser3.push("LATENCY", "DOCTOR"); + parseCommand(parser3, key) { + parser3.push("SMEMBERS"); + parser3.pushKey(key); }, - transformReply: void 0 + transformReply: { + 2: void 0, + 3: void 0 + } }; } }); -var require_LATENCY_GRAPH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_GRAPH.js"(exports2) { +var require_SMISMEMBER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SMISMEMBER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.LATENCY_EVENTS = void 0; - exports2.LATENCY_EVENTS = { - ACTIVE_DEFRAG_CYCLE: "active-defrag-cycle", - AOF_FSYNC_ALWAYS: "aof-fsync-always", - AOF_STAT: "aof-stat", - AOF_REWRITE_DIFF_WRITE: "aof-rewrite-diff-write", - AOF_RENAME: "aof-rename", - AOF_WRITE: "aof-write", - AOF_WRITE_ACTIVE_CHILD: "aof-write-active-child", - AOF_WRITE_ALONE: "aof-write-alone", - AOF_WRITE_PENDING_FSYNC: "aof-write-pending-fsync", - COMMAND: "command", - EXPIRE_CYCLE: "expire-cycle", - EVICTION_CYCLE: "eviction-cycle", - EVICTION_DEL: "eviction-del", - FAST_COMMAND: "fast-command", - FORK: "fork", - RDB_UNLINK_TEMP_FILE: "rdb-unlink-temp-file" - }; exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the LATENCY GRAPH command + * Constructs the SMISMEMBER command * * @param parser - The command parser - * @param event - The latency event to get the graph for - * @see https://redis.io/commands/latency-graph/ + * @param key - The set key to check membership in + * @param members - The members to check for existence + * @see https://redis.io/commands/smismember/ */ - parseCommand(parser3, event) { - parser3.push("LATENCY", "GRAPH", event); + parseCommand(parser3, key, members) { + parser3.push("SMISMEMBER"); + parser3.pushKey(key); + parser3.pushVariadic(members); }, transformReply: void 0 }; } }); -var require_LATENCY_HISTORY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_HISTORY.js"(exports2) { +var require_SMOVE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SMOVE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the LATENCY HISTORY command + * Constructs the SMOVE command * * @param parser - The command parser - * @param event - The latency event to get the history for - * @see https://redis.io/commands/latency-history/ + * @param source - The source set key + * @param destination - The destination set key + * @param member - The member to move + * @see https://redis.io/commands/smove/ */ - parseCommand(parser3, event) { - parser3.push("LATENCY", "HISTORY", event); + parseCommand(parser3, source, destination, member) { + parser3.push("SMOVE"); + parser3.pushKeys([source, destination]); + parser3.push(member); }, transformReply: void 0 }; } }); -var require_LATENCY_LATEST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_LATEST.js"(exports2) { +var require_SORT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SORT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseSortArguments = void 0; + function parseSortArguments(parser3, key, options2) { + parser3.pushKey(key); + if (options2?.BY) { + parser3.push("BY", options2.BY); + } + if (options2?.LIMIT) { + parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + } + if (options2?.GET) { + if (Array.isArray(options2.GET)) { + for (const pattern of options2.GET) { + parser3.push("GET", pattern); + } + } else { + parser3.push("GET", options2.GET); + } + } + if (options2?.DIRECTION) { + parser3.push(options2.DIRECTION); + } + if (options2?.ALPHA) { + parser3.push("ALPHA"); + } + } + exports2.parseSortArguments = parseSortArguments; exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the LATENCY LATEST command + * Constructs the SORT command * * @param parser - The command parser - * @see https://redis.io/commands/latency-latest/ + * @param key - The key to sort (list, set, or sorted set) + * @param options - Sort options + * @see https://redis.io/commands/sort/ */ - parseCommand(parser3) { - parser3.push("LATENCY", "LATEST"); + parseCommand(parser3, key, options2) { + parser3.push("SORT"); + parseSortArguments(parser3, key, options2); }, transformReply: void 0 }; } }); -var require_LATENCY_RESET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LATENCY_RESET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.LATENCY_EVENTS = void 0; - var LATENCY_GRAPH_1 = require_LATENCY_GRAPH(); - Object.defineProperty(exports2, "LATENCY_EVENTS", { enumerable: true, get: function() { - return LATENCY_GRAPH_1.LATENCY_EVENTS; - } }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, - /** - * Constructs the LATENCY RESET command - * * @param parser - The command parser - * @param events - The latency events to reset. If not specified, all events are reset. - * @see https://redis.io/commands/latency-reset/ - */ - parseCommand(parser3, ...events) { - const args = ["LATENCY", "RESET"]; - if (events.length > 0) { - args.push(...events); - } - parser3.push(...args); - }, - transformReply: void 0 - }; - } -}); -var require_LCS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS.js"(exports2) { +var require_SORT_RO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SORT_RO.js"(exports2) { "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var SORT_1 = __importStar(require_SORT()); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the LCS command (Longest Common Substring) - * - * @param parser - The command parser - * @param key1 - First key containing the first string - * @param key2 - Second key containing the second string - * @see https://redis.io/commands/lcs/ + * Read-only variant of SORT that sorts the elements in a list, set or sorted set. + * @param args - Same parameters as the SORT command. */ - parseCommand(parser3, key1, key2) { - parser3.push("LCS"); - parser3.pushKeys([key1, key2]); + parseCommand(...args) { + const parser3 = args[0]; + parser3.push("SORT_RO"); + (0, SORT_1.parseSortArguments)(...args); }, - transformReply: void 0 + transformReply: SORT_1.default.transformReply }; } }); -var require_LCS_IDX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS_IDX.js"(exports2) { +var require_SORT_STORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SORT_STORE.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var LCS_1 = __importDefault(require_LCS()); + var SORT_1 = __importDefault(require_SORT()); exports2.default = { - IS_READ_ONLY: LCS_1.default.IS_READ_ONLY, + IS_READ_ONLY: false, /** - * Constructs the LCS command with IDX option - * - * @param parser - The command parser - * @param key1 - First key containing the first string - * @param key2 - Second key containing the second string - * @param options - Additional options for the LCS IDX command - * @see https://redis.io/commands/lcs/ + * Sorts the elements in a list, set or sorted set and stores the result in a new list. + * @param parser - The Redis command parser. + * @param source - Key of the source list, set or sorted set. + * @param destination - Destination key where the result will be stored. + * @param options - Optional sorting parameters. */ - parseCommand(parser3, key1, key2, options2) { - LCS_1.default.parseCommand(parser3, key1, key2); - parser3.push("IDX"); - if (options2?.MINMATCHLEN) { - parser3.push("MINMATCHLEN", options2.MINMATCHLEN.toString()); - } + parseCommand(parser3, source, destination, options2) { + SORT_1.default.parseCommand(parser3, source, options2); + parser3.push("STORE", destination); }, - transformReply: { - 2: (reply) => ({ - matches: reply[1], - len: reply[3] - }), - 3: void 0 - } + transformReply: void 0 }; } }); -var require_LCS_IDX_WITHMATCHLEN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS_IDX_WITHMATCHLEN.js"(exports2) { +var require_SPOP_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SPOP_COUNT.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var LCS_IDX_1 = __importDefault(require_LCS_IDX()); exports2.default = { - IS_READ_ONLY: LCS_IDX_1.default.IS_READ_ONLY, + IS_READ_ONLY: false, /** - * Constructs the LCS command with IDX and WITHMATCHLEN options + * Constructs the SPOP command to remove and return multiple random members from a set * - * @param args - The same parameters as LCS_IDX command - * @see https://redis.io/commands/lcs/ + * @param parser - The command parser + * @param key - The key of the set to pop from + * @param count - The number of members to pop + * @see https://redis.io/commands/spop/ */ - parseCommand(...args) { - const parser3 = args[0]; - LCS_IDX_1.default.parseCommand(...args); - parser3.push("WITHMATCHLEN"); + parseCommand(parser3, key, count) { + parser3.push("SPOP"); + parser3.pushKey(key); + parser3.push(count.toString()); }, - transformReply: { - 2: (reply) => ({ - matches: reply[1], - len: reply[3] - }), - 3: void 0 - } + transformReply: void 0 }; } }); -var require_LCS_LEN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LCS_LEN.js"(exports2) { +var require_SPOP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SPOP.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var LCS_1 = __importDefault(require_LCS()); exports2.default = { - IS_READ_ONLY: LCS_1.default.IS_READ_ONLY, + IS_READ_ONLY: false, /** - * Constructs the LCS command with LEN option + * Constructs the SPOP command to remove and return a random member from a set * - * @param args - The same parameters as LCS command - * @see https://redis.io/commands/lcs/ + * @param parser - The command parser + * @param key - The key of the set to pop from + * @see https://redis.io/commands/spop/ */ - parseCommand(...args) { - const parser3 = args[0]; - LCS_1.default.parseCommand(...args); - parser3.push("LEN"); + parseCommand(parser3, key) { + parser3.push("SPOP"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_LINDEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LINDEX.js"(exports2) { +var require_SPUBLISH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SPUBLISH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the LINDEX command + * Constructs the SPUBLISH command to post a message to a Sharded Pub/Sub channel * * @param parser - The command parser - * @param key - The key of the list - * @param index - The index of the element to retrieve - * @see https://redis.io/commands/lindex/ + * @param channel - The channel to publish to + * @param message - The message to publish + * @see https://redis.io/commands/spublish/ */ - parseCommand(parser3, key, index) { - parser3.push("LINDEX"); - parser3.pushKey(key); - parser3.push(index.toString()); + parseCommand(parser3, channel, message) { + parser3.push("SPUBLISH"); + parser3.pushKey(channel); + parser3.push(message); }, transformReply: void 0 }; } }); -var require_LINSERT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LINSERT.js"(exports2) { +var require_SRANDMEMBER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SRANDMEMBER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the LINSERT command + * Constructs the SRANDMEMBER command to get a random member from a set * * @param parser - The command parser - * @param key - The key of the list - * @param position - The position where to insert (BEFORE or AFTER) - * @param pivot - The element to find in the list - * @param element - The element to insert - * @see https://redis.io/commands/linsert/ + * @param key - The key of the set to get random member from + * @see https://redis.io/commands/srandmember/ */ - parseCommand(parser3, key, position, pivot, element) { - parser3.push("LINSERT"); + parseCommand(parser3, key) { + parser3.push("SRANDMEMBER"); parser3.pushKey(key); - parser3.push(position, pivot, element); }, transformReply: void 0 }; } }); -var require_LLEN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LLEN.js"(exports2) { +var require_SRANDMEMBER_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SRANDMEMBER_COUNT.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var SRANDMEMBER_1 = __importDefault(require_SRANDMEMBER()); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + IS_READ_ONLY: SRANDMEMBER_1.default.IS_READ_ONLY, /** - * Constructs the LLEN command + * Constructs the SRANDMEMBER command to get multiple random members from a set * * @param parser - The command parser - * @param key - The key of the list to get the length of - * @see https://redis.io/commands/llen/ + * @param key - The key of the set to get random members from + * @param count - The number of members to return. If negative, may return the same member multiple times + * @see https://redis.io/commands/srandmember/ */ - parseCommand(parser3, key) { - parser3.push("LLEN"); - parser3.pushKey(key); + parseCommand(parser3, key, count) { + SRANDMEMBER_1.default.parseCommand(parser3, key); + parser3.push(count.toString()); }, transformReply: void 0 }; } }); -var require_LMOVE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LMOVE.js"(exports2) { +var require_SREM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SREM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { IS_READ_ONLY: false, /** - * Constructs the LMOVE command + * Constructs the SREM command to remove one or more members from a set * * @param parser - The command parser - * @param source - The source list key - * @param destination - The destination list key - * @param sourceSide - The side to pop from (LEFT or RIGHT) - * @param destinationSide - The side to push to (LEFT or RIGHT) - * @see https://redis.io/commands/lmove/ + * @param key - The key of the set to remove members from + * @param members - One or more members to remove from the set + * @returns The number of members that were removed from the set + * @see https://redis.io/commands/srem/ */ - parseCommand(parser3, source, destination, sourceSide, destinationSide) { - parser3.push("LMOVE"); - parser3.pushKeys([source, destination]); - parser3.push(sourceSide, destinationSide); + parseCommand(parser3, key, members) { + parser3.push("SREM"); + parser3.pushKey(key); + parser3.pushVariadic(members); }, transformReply: void 0 }; } }); -var require_LOLWUT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LOLWUT.js"(exports2) { +var require_SSCAN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SSCAN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var SCAN_1 = require_SCAN(); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the LOLWUT command + * Constructs the SSCAN command to incrementally iterate over elements in a set * * @param parser - The command parser - * @param version - Optional version parameter - * @param optionalArguments - Additional optional numeric arguments - * @see https://redis.io/commands/lolwut/ + * @param key - The key of the set to scan + * @param cursor - The cursor position to start scanning from + * @param options - Optional scanning parameters (COUNT and MATCH) + * @returns Iterator containing cursor position and matching members + * @see https://redis.io/commands/sscan/ */ - parseCommand(parser3, version3, ...optionalArguments) { - parser3.push("LOLWUT"); - if (version3) { - parser3.push("VERSION", version3.toString()); - parser3.pushVariadic(optionalArguments.map(String)); - } + parseCommand(parser3, key, cursor, options2) { + parser3.push("SSCAN"); + parser3.pushKey(key); + (0, SCAN_1.parseScanArguments)(parser3, cursor, options2); }, - transformReply: void 0 + /** + * Transforms the SSCAN reply into a cursor result object + * + * @param cursor - The next cursor position + * @param members - Array of matching set members + * @returns Object containing cursor and members array + */ + transformReply([cursor, members]) { + return { + cursor, + members + }; + } }; } }); -var require_LPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOP.js"(exports2) { +var require_STRLEN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/STRLEN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Constructs the LPOP command + * Constructs the STRLEN command to get the length of a string value * * @param parser - The command parser - * @param key - The key of the list to pop from - * @see https://redis.io/commands/lpop/ + * @param key - The key holding the string value + * @returns The length of the string value, or 0 when key does not exist + * @see https://redis.io/commands/strlen/ */ parseCommand(parser3, key) { - parser3.push("LPOP"); + parser3.push("STRLEN"); parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_LPOP_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOP_COUNT.js"(exports2) { +var require_SUNION = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SUNION.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var LPOP_1 = __importDefault(require_LPOP()); exports2.default = { - IS_READ_ONLY: false, + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Constructs the LPOP command with count parameter + * Constructs the SUNION command to return the members of the set resulting from the union of all the given sets * * @param parser - The command parser - * @param key - The key of the list to pop from - * @param count - The number of elements to pop - * @see https://redis.io/commands/lpop/ + * @param keys - One or more set keys to compute the union from + * @returns Array of all elements that are members of at least one of the given sets + * @see https://redis.io/commands/sunion/ */ - parseCommand(parser3, key, count) { - LPOP_1.default.parseCommand(parser3, key); - parser3.push(count.toString()); + parseCommand(parser3, keys) { + parser3.push("SUNION"); + parser3.pushKeys(keys); }, transformReply: void 0 }; } }); -var require_LPOS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOS.js"(exports2) { +var require_SUNIONSTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SUNIONSTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the LPOS command + * Constructs the SUNIONSTORE command to store the union of multiple sets into a destination set * * @param parser - The command parser - * @param key - The key of the list - * @param element - The element to search for - * @param options - Optional parameters for RANK and MAXLEN - * @see https://redis.io/commands/lpos/ + * @param destination - The destination key to store the resulting set + * @param keys - One or more source set keys to compute the union from + * @returns The number of elements in the resulting set + * @see https://redis.io/commands/sunionstore/ */ - parseCommand(parser3, key, element, options2) { - parser3.push("LPOS"); - parser3.pushKey(key); - parser3.push(element); - if (options2?.RANK !== void 0) { - parser3.push("RANK", options2.RANK.toString()); - } - if (options2?.MAXLEN !== void 0) { - parser3.push("MAXLEN", options2.MAXLEN.toString()); - } + parseCommand(parser3, destination, keys) { + parser3.push("SUNIONSTORE"); + parser3.pushKey(destination); + parser3.pushKeys(keys); }, transformReply: void 0 }; } }); -var require_LPOS_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPOS_COUNT.js"(exports2) { +var require_SWAPDB = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SWAPDB.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var LPOS_1 = __importDefault(require_LPOS()); exports2.default = { - CACHEABLE: LPOS_1.default.CACHEABLE, - IS_READ_ONLY: LPOS_1.default.IS_READ_ONLY, + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: false, /** - * Constructs the LPOS command with COUNT option - * - * @param parser - The command parser - * @param key - The key of the list - * @param element - The element to search for - * @param count - The number of positions to return - * @param options - Optional parameters for RANK and MAXLEN - * @see https://redis.io/commands/lpos/ + * Swaps the data of two Redis databases. + * @param parser - The Redis command parser. + * @param index1 - First database index. + * @param index2 - Second database index. */ - parseCommand(parser3, key, element, count, options2) { - LPOS_1.default.parseCommand(parser3, key, element, options2); - parser3.push("COUNT", count.toString()); + parseCommand(parser3, index1, index2) { + parser3.push("SWAPDB", index1.toString(), index2.toString()); }, transformReply: void 0 }; } }); -var require_LPUSH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPUSH.js"(exports2) { +var require_TIME = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TIME.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Constructs the LPUSH command + * Constructs the TIME command to return the server's current time * * @param parser - The command parser - * @param key - The key of the list - * @param elements - One or more elements to push to the list - * @see https://redis.io/commands/lpush/ + * @returns Array containing the Unix timestamp in seconds and microseconds + * @see https://redis.io/commands/time/ */ - parseCommand(parser3, key, elements) { - parser3.push("LPUSH"); - parser3.pushKey(key); - parser3.pushVariadic(elements); + parseCommand(parser3) { + parser3.push("TIME"); }, transformReply: void 0 }; } }); -var require_LPUSHX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LPUSHX.js"(exports2) { +var require_TOUCH = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TOUCH.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the LPUSHX command + * Constructs the TOUCH command to alter the last access time of keys * * @param parser - The command parser - * @param key - The key of the list - * @param elements - One or more elements to push to the list if it exists - * @see https://redis.io/commands/lpushx/ + * @param key - One or more keys to touch + * @returns The number of keys that were touched + * @see https://redis.io/commands/touch/ */ - parseCommand(parser3, key, elements) { - parser3.push("LPUSHX"); - parser3.pushKey(key); - parser3.pushVariadic(elements); + parseCommand(parser3, key) { + parser3.push("TOUCH"); + parser3.pushKeys(key); }, transformReply: void 0 }; } }); -var require_LRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LRANGE.js"(exports2) { +var require_TTL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TTL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the LRANGE command + * Constructs the TTL command to get the remaining time to live of a key * * @param parser - The command parser - * @param key - The key of the list - * @param start - The starting index - * @param stop - The ending index - * @see https://redis.io/commands/lrange/ + * @param key - Key to check + * @returns Time to live in seconds, -2 if key does not exist, -1 if has no timeout + * @see https://redis.io/commands/ttl/ */ - parseCommand(parser3, key, start, stop) { - parser3.push("LRANGE"); + parseCommand(parser3, key) { + parser3.push("TTL"); parser3.pushKey(key); - parser3.push(start.toString(), stop.toString()); }, transformReply: void 0 }; } }); -var require_LREM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LREM.js"(exports2) { +var require_TYPE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TYPE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the LREM command + * Constructs the TYPE command to determine the data type stored at key * * @param parser - The command parser - * @param key - The key of the list - * @param count - The count of elements to remove (negative: from tail to head, 0: all occurrences, positive: from head to tail) - * @param element - The element to remove - * @see https://redis.io/commands/lrem/ + * @param key - Key to check + * @returns String reply: "none", "string", "list", "set", "zset", "hash", "stream" + * @see https://redis.io/commands/type/ */ - parseCommand(parser3, key, count, element) { - parser3.push("LREM"); + parseCommand(parser3, key) { + parser3.push("TYPE"); parser3.pushKey(key); - parser3.push(count.toString()); - parser3.push(element); }, transformReply: void 0 }; } }); -var require_LSET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LSET.js"(exports2) { +var require_UNLINK = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/UNLINK.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the LSET command + * Constructs the UNLINK command to asynchronously delete one or more keys * * @param parser - The command parser - * @param key - The key of the list - * @param index - The index of the element to replace - * @param element - The new value to set - * @see https://redis.io/commands/lset/ + * @param keys - One or more keys to unlink + * @returns The number of keys that were unlinked + * @see https://redis.io/commands/unlink/ */ - parseCommand(parser3, key, index, element) { - parser3.push("LSET"); - parser3.pushKey(key); - parser3.push(index.toString(), element); + parseCommand(parser3, keys) { + parser3.push("UNLINK"); + parser3.pushKeys(keys); }, transformReply: void 0 }; } }); -var require_LTRIM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/LTRIM.js"(exports2) { +var require_WAIT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/WAIT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, /** - * Constructs the LTRIM command + * Constructs the WAIT command to synchronize with replicas * * @param parser - The command parser - * @param key - The key of the list - * @param start - The starting index - * @param stop - The ending index - * @see https://redis.io/commands/ltrim/ + * @param numberOfReplicas - Number of replicas that must acknowledge the write + * @param timeout - Maximum time to wait in milliseconds + * @returns The number of replicas that acknowledged the write + * @see https://redis.io/commands/wait/ */ - parseCommand(parser3, key, start, stop) { - parser3.push("LTRIM"); - parser3.pushKey(key); - parser3.push(start.toString(), stop.toString()); + parseCommand(parser3, numberOfReplicas, timeout) { + parser3.push("WAIT", numberOfReplicas.toString(), timeout.toString()); }, transformReply: void 0 }; } }); -var require_MEMORY_DOCTOR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_DOCTOR.js"(exports2) { +var require_XACK = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XACK.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MEMORY DOCTOR command + * Constructs the XACK command to acknowledge the processing of stream messages in a consumer group * * @param parser - The command parser - * @see https://redis.io/commands/memory-doctor/ + * @param key - The stream key + * @param group - The consumer group name + * @param id - One or more message IDs to acknowledge + * @returns The number of messages successfully acknowledged + * @see https://redis.io/commands/xack/ */ - parseCommand(parser3) { - parser3.push("MEMORY", "DOCTOR"); + parseCommand(parser3, key, group, id) { + parser3.push("XACK"); + parser3.pushKey(key); + parser3.push(group); + parser3.pushVariadic(id); }, transformReply: void 0 }; } }); -var require_MEMORY_MALLOC_STATS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_MALLOC-STATS.js"(exports2) { +var require_XACKDEL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XACKDEL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MEMORY MALLOC-STATS command + * Constructs the XACKDEL command to acknowledge and delete one or multiple messages for a stream consumer group * * @param parser - The command parser - * @see https://redis.io/commands/memory-malloc-stats/ + * @param key - The stream key + * @param group - The consumer group name + * @param id - One or more message IDs to acknowledge and delete + * @param policy - Policy to apply when deleting entries (optional, defaults to KEEPREF) + * @returns Array of integers: -1 (not found), 1 (acknowledged and deleted), 2 (acknowledged with dangling refs) + * @see https://redis.io/commands/xackdel/ */ - parseCommand(parser3) { - parser3.push("MEMORY", "MALLOC-STATS"); + parseCommand(parser3, key, group, id, policy) { + parser3.push("XACKDEL"); + parser3.pushKey(key); + parser3.push(group); + if (policy) { + parser3.push(policy); + } + parser3.push("IDS"); + parser3.pushVariadicWithLength(id); }, transformReply: void 0 }; } }); -var require_MEMORY_PURGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_PURGE.js"(exports2) { +var require_XADD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XADD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseXAddArguments = void 0; + function parseXAddArguments(optional2, parser3, key, id, message, options2) { + parser3.push("XADD"); + parser3.pushKey(key); + if (optional2) { + parser3.push(optional2); + } + if (options2?.TRIM) { + if (options2.TRIM.strategy) { + parser3.push(options2.TRIM.strategy); + } + if (options2.TRIM.strategyModifier) { + parser3.push(options2.TRIM.strategyModifier); + } + parser3.push(options2.TRIM.threshold.toString()); + if (options2.TRIM.limit) { + parser3.push("LIMIT", options2.TRIM.limit.toString()); + } + if (options2.TRIM.policy) { + parser3.push(options2.TRIM.policy); + } + } + parser3.push(id); + for (const [key2, value] of Object.entries(message)) { + parser3.push(key2, value); + } + } + exports2.parseXAddArguments = parseXAddArguments; exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: false, /** - * Constructs the MEMORY PURGE command + * Constructs the XADD command to append a new entry to a stream * * @param parser - The command parser - * @see https://redis.io/commands/memory-purge/ + * @param key - The stream key + * @param id - Message ID (* for auto-generation) + * @param message - Key-value pairs representing the message fields + * @param options - Additional options for stream trimming + * @returns The ID of the added entry + * @see https://redis.io/commands/xadd/ */ - parseCommand(parser3) { - parser3.push("MEMORY", "PURGE"); + parseCommand(...args) { + return parseXAddArguments(void 0, ...args); }, transformReply: void 0 }; } }); -var require_MEMORY_STATS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_STATS.js"(exports2) { +var require_XADD_NOMKSTREAM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XADD_NOMKSTREAM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); + var XADD_1 = require_XADD(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MEMORY STATS command + * Constructs the XADD command with NOMKSTREAM option to append a new entry to an existing stream * - * @param parser - The command parser - * @see https://redis.io/commands/memory-stats/ + * @param args - Arguments tuple containing parser, key, id, message, and options + * @returns The ID of the added entry, or null if the stream doesn't exist + * @see https://redis.io/commands/xadd/ */ - parseCommand(parser3) { - parser3.push("MEMORY", "STATS"); + parseCommand(...args) { + return (0, XADD_1.parseXAddArguments)("NOMKSTREAM", ...args); }, - transformReply: { - 2: (rawReply, preserve, typeMapping) => { - const reply = {}; - let i2 = 0; - while (i2 < rawReply.length) { - switch (rawReply[i2].toString()) { - case "dataset.percentage": - case "peak.percentage": - case "allocator-fragmentation.ratio": - case "allocator-rss.ratio": - case "rss-overhead.ratio": - case "fragmentation": - reply[rawReply[i2++]] = generic_transformers_1.transformDoubleReply[2](rawReply[i2++], preserve, typeMapping); - break; - default: - reply[rawReply[i2++]] = rawReply[i2++]; - } - } - return reply; - }, - 3: void 0 - } + transformReply: void 0 }; } }); -var require_MEMORY_USAGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MEMORY_USAGE.js"(exports2) { +var require_XAUTOCLAIM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XAUTOCLAIM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MEMORY USAGE command + * Constructs the XAUTOCLAIM command to automatically claim pending messages in a consumer group * * @param parser - The command parser - * @param key - The key to get memory usage for - * @param options - Optional parameters including SAMPLES - * @see https://redis.io/commands/memory-usage/ + * @param key - The stream key + * @param group - The consumer group name + * @param consumer - The consumer name that will claim the messages + * @param minIdleTime - Minimum idle time in milliseconds for a message to be claimed + * @param start - Message ID to start scanning from + * @param options - Additional options for the claim operation + * @returns Object containing nextId, claimed messages, and list of deleted message IDs + * @see https://redis.io/commands/xautoclaim/ */ - parseCommand(parser3, key, options2) { - parser3.push("MEMORY", "USAGE"); + parseCommand(parser3, key, group, consumer, minIdleTime, start, options2) { + parser3.push("XAUTOCLAIM"); parser3.pushKey(key); - if (options2?.SAMPLES) { - parser3.push("SAMPLES", options2.SAMPLES.toString()); + parser3.push(group, consumer, minIdleTime.toString(), start); + if (options2?.COUNT) { + parser3.push("COUNT", options2.COUNT.toString()); } }, - transformReply: void 0 + /** + * Transforms the raw XAUTOCLAIM reply into a structured object + * + * @param reply - Raw reply from Redis + * @param preserve - Preserve options (unused) + * @param typeMapping - Type mapping for message fields + * @returns Structured object containing nextId, messages, and deletedMessages + */ + transformReply(reply, preserve, typeMapping) { + return { + nextId: reply[0], + messages: reply[1].map(generic_transformers_1.transformStreamMessageNullReply.bind(void 0, typeMapping)), + deletedMessages: reply[2] + }; + } }; } }); -var require_MGET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MGET.js"(exports2) { +var require_XAUTOCLAIM_JUSTID = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XAUTOCLAIM_JUSTID.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var XAUTOCLAIM_1 = __importDefault(require_XAUTOCLAIM()); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + IS_READ_ONLY: XAUTOCLAIM_1.default.IS_READ_ONLY, /** - * Constructs the MGET command + * Constructs the XAUTOCLAIM command with JUSTID option to get only message IDs * - * @param parser - The command parser - * @param keys - Array of keys to get - * @see https://redis.io/commands/mget/ + * @param args - Same parameters as XAUTOCLAIM command + * @returns Object containing nextId and arrays of claimed and deleted message IDs + * @see https://redis.io/commands/xautoclaim/ */ - parseCommand(parser3, keys) { - parser3.push("MGET"); - parser3.pushKeys(keys); + parseCommand(...args) { + const parser3 = args[0]; + XAUTOCLAIM_1.default.parseCommand(...args); + parser3.push("JUSTID"); }, - transformReply: void 0 + /** + * Transforms the raw XAUTOCLAIM JUSTID reply into a structured object + * + * @param reply - Raw reply from Redis + * @returns Structured object containing nextId, message IDs, and deleted message IDs + */ + transformReply(reply) { + return { + nextId: reply[0], + messages: reply[1], + deletedMessages: reply[2] + }; + } }; } }); -var require_MIGRATE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MIGRATE.js"(exports2) { +var require_XCLAIM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XCLAIM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { IS_READ_ONLY: false, /** - * Constructs the MIGRATE command + * Constructs the XCLAIM command to claim pending messages in a consumer group * * @param parser - The command parser - * @param host - Target Redis instance host - * @param port - Target Redis instance port - * @param key - Key or keys to migrate - * @param destinationDb - Target database index - * @param timeout - Timeout in milliseconds - * @param options - Optional parameters including COPY, REPLACE, and AUTH - * @see https://redis.io/commands/migrate/ + * @param key - The stream key + * @param group - The consumer group name + * @param consumer - The consumer name that will claim the messages + * @param minIdleTime - Minimum idle time in milliseconds for a message to be claimed + * @param id - One or more message IDs to claim + * @param options - Additional options for the claim operation + * @returns Array of claimed messages + * @see https://redis.io/commands/xclaim/ */ - parseCommand(parser3, host, port, key, destinationDb, timeout, options2) { - parser3.push("MIGRATE", host, port.toString()); - const isKeyArray = Array.isArray(key); - if (isKeyArray) { - parser3.push(""); - } else { - parser3.push(key); + parseCommand(parser3, key, group, consumer, minIdleTime, id, options2) { + parser3.push("XCLAIM"); + parser3.pushKey(key); + parser3.push(group, consumer, minIdleTime.toString()); + parser3.pushVariadic(id); + if (options2?.IDLE !== void 0) { + parser3.push("IDLE", options2.IDLE.toString()); } - parser3.push(destinationDb.toString(), timeout.toString()); - if (options2?.COPY) { - parser3.push("COPY"); + if (options2?.TIME !== void 0) { + parser3.push("TIME", (options2.TIME instanceof Date ? options2.TIME.getTime() : options2.TIME).toString()); } - if (options2?.REPLACE) { - parser3.push("REPLACE"); + if (options2?.RETRYCOUNT !== void 0) { + parser3.push("RETRYCOUNT", options2.RETRYCOUNT.toString()); } - if (options2?.AUTH) { - if (options2.AUTH.username) { - parser3.push("AUTH2", options2.AUTH.username, options2.AUTH.password); - } else { - parser3.push("AUTH", options2.AUTH.password); - } + if (options2?.FORCE) { + parser3.push("FORCE"); } - if (isKeyArray) { - parser3.push("KEYS"); - parser3.pushVariadic(key); + if (options2?.LASTID !== void 0) { + parser3.push("LASTID", options2.LASTID); } }, - transformReply: void 0 + /** + * Transforms the raw XCLAIM reply into an array of messages + * + * @param reply - Raw reply from Redis + * @param preserve - Preserve options (unused) + * @param typeMapping - Type mapping for message fields + * @returns Array of claimed messages with their fields + */ + transformReply(reply, preserve, typeMapping) { + return reply.map(generic_transformers_1.transformStreamMessageNullReply.bind(void 0, typeMapping)); + } }; } }); -var require_MODULE_LIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MODULE_LIST.js"(exports2) { +var require_XCLAIM_JUSTID = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XCLAIM_JUSTID.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var XCLAIM_1 = __importDefault(require_XCLAIM()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: XCLAIM_1.default.IS_READ_ONLY, /** - * Constructs the MODULE LIST command + * Constructs the XCLAIM command with JUSTID option to get only message IDs * - * @param parser - The command parser - * @see https://redis.io/commands/module-list/ + * @param args - Same parameters as XCLAIM command + * @returns Array of successfully claimed message IDs + * @see https://redis.io/commands/xclaim/ */ - parseCommand(parser3) { - parser3.push("MODULE", "LIST"); + parseCommand(...args) { + const parser3 = args[0]; + XCLAIM_1.default.parseCommand(...args); + parser3.push("JUSTID"); }, - transformReply: { - 2: (reply) => { - return reply.map((module15) => { - const unwrapped = module15; - return { - name: unwrapped[1], - ver: unwrapped[3] - }; - }); - }, - 3: void 0 - } + /** + * Transforms the XCLAIM JUSTID reply into an array of message IDs + * + * @returns Array of claimed message IDs + */ + transformReply: void 0 }; } }); -var require_MODULE_LOAD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MODULE_LOAD.js"(exports2) { +var require_XDEL = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XDEL.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MODULE LOAD command + * Constructs the XDEL command to remove one or more messages from a stream * * @param parser - The command parser - * @param path - Path to the module file - * @param moduleArguments - Optional arguments to pass to the module - * @see https://redis.io/commands/module-load/ + * @param key - The stream key + * @param id - One or more message IDs to delete + * @returns The number of messages actually deleted + * @see https://redis.io/commands/xdel/ */ - parseCommand(parser3, path8, moduleArguments) { - parser3.push("MODULE", "LOAD", path8); - if (moduleArguments) { - parser3.push(...moduleArguments); - } + parseCommand(parser3, key, id) { + parser3.push("XDEL"); + parser3.pushKey(key); + parser3.pushVariadic(id); }, transformReply: void 0 }; } }); -var require_MODULE_UNLOAD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MODULE_UNLOAD.js"(exports2) { +var require_XDELEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XDELEX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MODULE UNLOAD command + * Constructs the XDELEX command to delete one or multiple entries from the stream * * @param parser - The command parser - * @param name - The name of the module to unload - * @see https://redis.io/commands/module-unload/ + * @param key - The stream key + * @param id - One or more message IDs to delete + * @param policy - Policy to apply when deleting entries (optional, defaults to KEEPREF) + * @returns Array of integers: -1 (not found), 1 (deleted), 2 (dangling refs) + * @see https://redis.io/commands/xdelex/ */ - parseCommand(parser3, name) { - parser3.push("MODULE", "UNLOAD", name); + parseCommand(parser3, key, id, policy) { + parser3.push("XDELEX"); + parser3.pushKey(key); + if (policy) { + parser3.push(policy); + } + parser3.push("IDS"); + parser3.pushVariadicWithLength(id); }, transformReply: void 0 }; } }); -var require_MOVE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MOVE.js"(exports2) { +var require_XGROUP_CREATE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_CREATE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the MOVE command + * Constructs the XGROUP CREATE command to create a consumer group for a stream * * @param parser - The command parser - * @param key - The key to move - * @param db - The destination database index - * @see https://redis.io/commands/move/ + * @param key - The stream key + * @param group - Name of the consumer group + * @param id - ID of the last delivered item in the stream ('$' for last item, '0' for all items) + * @param options - Additional options for group creation + * @returns 'OK' if successful + * @see https://redis.io/commands/xgroup-create/ */ - parseCommand(parser3, key, db2) { - parser3.push("MOVE"); + parseCommand(parser3, key, group, id, options2) { + parser3.push("XGROUP", "CREATE"); parser3.pushKey(key); - parser3.push(db2.toString()); + parser3.push(group, id); + if (options2?.MKSTREAM) { + parser3.push("MKSTREAM"); + } + if (options2?.ENTRIESREAD) { + parser3.push("ENTRIESREAD", options2.ENTRIESREAD.toString()); + } }, transformReply: void 0 }; } }); -var require_MSET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MSET.js"(exports2) { +var require_XGROUP_CREATECONSUMER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_CREATECONSUMER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseMSetArguments = void 0; - function parseMSetArguments(parser3, toSet) { - if (Array.isArray(toSet)) { - if (toSet.length == 0) { - throw new Error("empty toSet Argument"); - } - if (Array.isArray(toSet[0])) { - for (const tuple of toSet) { - parser3.pushKey(tuple[0]); - parser3.push(tuple[1]); - } - } else { - const arr = toSet; - for (let i2 = 0; i2 < arr.length; i2 += 2) { - parser3.pushKey(arr[i2]); - parser3.push(arr[i2 + 1]); - } - } - } else { - for (const tuple of Object.entries(toSet)) { - parser3.pushKey(tuple[0]); - parser3.push(tuple[1]); - } - } - } - exports2.parseMSetArguments = parseMSetArguments; exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MSET command + * Constructs the XGROUP CREATECONSUMER command to create a new consumer in a consumer group * * @param parser - The command parser - * @param toSet - Key-value pairs to set (array of tuples, flat array, or object) - * @see https://redis.io/commands/mset/ + * @param key - The stream key + * @param group - Name of the consumer group + * @param consumer - Name of the consumer to create + * @returns 1 if the consumer was created, 0 if it already existed + * @see https://redis.io/commands/xgroup-createconsumer/ */ - parseCommand(parser3, toSet) { - parser3.push("MSET"); - return parseMSetArguments(parser3, toSet); + parseCommand(parser3, key, group, consumer) { + parser3.push("XGROUP", "CREATECONSUMER"); + parser3.pushKey(key); + parser3.push(group, consumer); }, transformReply: void 0 }; } }); -var require_MSETNX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/MSETNX.js"(exports2) { +var require_XGROUP_DELCONSUMER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_DELCONSUMER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var MSET_1 = require_MSET(); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the MSETNX command + * Constructs the XGROUP DELCONSUMER command to remove a consumer from a consumer group * * @param parser - The command parser - * @param toSet - Key-value pairs to set if none of the keys exist (array of tuples, flat array, or object) - * @see https://redis.io/commands/msetnx/ + * @param key - The stream key + * @param group - Name of the consumer group + * @param consumer - Name of the consumer to remove + * @returns The number of pending messages owned by the deleted consumer + * @see https://redis.io/commands/xgroup-delconsumer/ */ - parseCommand(parser3, toSet) { - parser3.push("MSETNX"); - return (0, MSET_1.parseMSetArguments)(parser3, toSet); + parseCommand(parser3, key, group, consumer) { + parser3.push("XGROUP", "DELCONSUMER"); + parser3.pushKey(key); + parser3.push(group, consumer); }, transformReply: void 0 }; } }); -var require_OBJECT_ENCODING = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_ENCODING.js"(exports2) { +var require_XGROUP_DESTROY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_DESTROY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the OBJECT ENCODING command + * Constructs the XGROUP DESTROY command to remove a consumer group * * @param parser - The command parser - * @param key - The key to get the internal encoding for - * @see https://redis.io/commands/object-encoding/ + * @param key - The stream key + * @param group - Name of the consumer group to destroy + * @returns 1 if the group was destroyed, 0 if it did not exist + * @see https://redis.io/commands/xgroup-destroy/ */ - parseCommand(parser3, key) { - parser3.push("OBJECT", "ENCODING"); + parseCommand(parser3, key, group) { + parser3.push("XGROUP", "DESTROY"); parser3.pushKey(key); + parser3.push(group); }, transformReply: void 0 }; } }); -var require_OBJECT_FREQ = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_FREQ.js"(exports2) { +var require_XGROUP_SETID = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_SETID.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the OBJECT FREQ command + * Constructs the XGROUP SETID command to set the last delivered ID for a consumer group * * @param parser - The command parser - * @param key - The key to get the access frequency for - * @see https://redis.io/commands/object-freq/ + * @param key - The stream key + * @param group - Name of the consumer group + * @param id - ID to set as last delivered message ('$' for last item, '0' for all items) + * @param options - Additional options for setting the group ID + * @returns 'OK' if successful + * @see https://redis.io/commands/xgroup-setid/ */ - parseCommand(parser3, key) { - parser3.push("OBJECT", "FREQ"); + parseCommand(parser3, key, group, id, options2) { + parser3.push("XGROUP", "SETID"); parser3.pushKey(key); + parser3.push(group, id); + if (options2?.ENTRIESREAD) { + parser3.push("ENTRIESREAD", options2.ENTRIESREAD.toString()); + } }, transformReply: void 0 }; } }); -var require_OBJECT_IDLETIME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_IDLETIME.js"(exports2) { +var require_XINFO_CONSUMERS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XINFO_CONSUMERS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the OBJECT IDLETIME command + * Constructs the XINFO CONSUMERS command to list the consumers in a consumer group * * @param parser - The command parser - * @param key - The key to get the idle time for - * @see https://redis.io/commands/object-idletime/ - */ - parseCommand(parser3, key) { - parser3.push("OBJECT", "IDLETIME"); + * @param key - The stream key + * @param group - Name of the consumer group + * @returns Array of consumer information objects + * @see https://redis.io/commands/xinfo-consumers/ + */ + parseCommand(parser3, key, group) { + parser3.push("XINFO", "CONSUMERS"); parser3.pushKey(key); + parser3.push(group); }, - transformReply: void 0 + transformReply: { + /** + * Transforms RESP2 reply into a structured consumer information array + * + * @param reply - Raw RESP2 reply from Redis + * @returns Array of consumer information objects + */ + 2: (reply) => { + return reply.map((consumer) => { + const unwrapped = consumer; + return { + name: unwrapped[1], + pending: unwrapped[3], + idle: unwrapped[5], + inactive: unwrapped[7] + }; + }); + }, + 3: void 0 + } }; } }); -var require_OBJECT_REFCOUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/OBJECT_REFCOUNT.js"(exports2) { +var require_XINFO_GROUPS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XINFO_GROUPS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the OBJECT REFCOUNT command + * Constructs the XINFO GROUPS command to list the consumer groups of a stream * * @param parser - The command parser - * @param key - The key to get the reference count for - * @see https://redis.io/commands/object-refcount/ + * @param key - The stream key + * @returns Array of consumer group information objects + * @see https://redis.io/commands/xinfo-groups/ */ parseCommand(parser3, key) { - parser3.push("OBJECT", "REFCOUNT"); + parser3.push("XINFO", "GROUPS"); parser3.pushKey(key); }, - transformReply: void 0 + transformReply: { + /** + * Transforms RESP2 reply into a structured consumer group information array + * + * @param reply - Raw RESP2 reply from Redis + * @returns Array of consumer group information objects containing: + * name - Name of the consumer group + * consumers - Number of consumers in the group + * pending - Number of pending messages for the group + * last-delivered-id - ID of the last delivered message + * entries-read - Number of entries read in the group (Redis 7.0+) + * lag - Number of entries not read by the group (Redis 7.0+) + */ + 2: (reply) => { + return reply.map((group) => { + const unwrapped = group; + return { + name: unwrapped[1], + consumers: unwrapped[3], + pending: unwrapped[5], + "last-delivered-id": unwrapped[7], + "entries-read": unwrapped[9], + lag: unwrapped[11] + }; + }); + }, + 3: void 0 + } }; } }); -var require_PERSIST = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PERSIST.js"(exports2) { +var require_XINFO_STREAM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XINFO_STREAM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { + IS_READ_ONLY: true, /** - * Constructs the PERSIST command + * Constructs the XINFO STREAM command to get detailed information about a stream * * @param parser - The command parser - * @param key - The key to remove the expiration from - * @see https://redis.io/commands/persist/ + * @param key - The stream key + * @returns Detailed information about the stream including its length, structure, and entries + * @see https://redis.io/commands/xinfo-stream/ */ parseCommand(parser3, key) { - parser3.push("PERSIST"); + parser3.push("XINFO", "STREAM"); parser3.pushKey(key); }, - transformReply: void 0 + transformReply: { + // TODO: is there a "type safe" way to do it? + 2(reply) { + const parsedReply = {}; + for (let i2 = 0; i2 < reply.length; i2 += 2) { + switch (reply[i2]) { + case "first-entry": + case "last-entry": + parsedReply[reply[i2]] = transformEntry(reply[i2 + 1]); + break; + default: + parsedReply[reply[i2]] = reply[i2 + 1]; + break; + } + } + return parsedReply; + }, + 3(reply) { + if (reply instanceof Map) { + reply.set("first-entry", transformEntry(reply.get("first-entry"))); + reply.set("last-entry", transformEntry(reply.get("last-entry"))); + } else if (reply instanceof Array) { + reply[17] = transformEntry(reply[17]); + reply[19] = transformEntry(reply[19]); + } else { + reply["first-entry"] = transformEntry(reply["first-entry"]); + reply["last-entry"] = transformEntry(reply["last-entry"]); + } + return reply; + } + } }; + function transformEntry(entry) { + if ((0, generic_transformers_1.isNullReply)(entry)) + return entry; + const [id, message] = entry; + return { + id, + message: (0, generic_transformers_1.transformTuplesReply)(message) + }; + } } }); -var require_PEXPIRE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PEXPIRE.js"(exports2) { +var require_XLEN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XLEN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the PEXPIRE command + * Constructs the XLEN command to get the number of entries in a stream * * @param parser - The command parser - * @param key - The key to set the expiration for - * @param ms - The expiration time in milliseconds - * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT') - * @see https://redis.io/commands/pexpire/ + * @param key - The stream key + * @returns The number of entries inside the stream + * @see https://redis.io/commands/xlen/ */ - parseCommand(parser3, key, ms, mode) { - parser3.push("PEXPIRE"); + parseCommand(parser3, key) { + parser3.push("XLEN"); parser3.pushKey(key); - parser3.push(ms.toString()); - if (mode) { - parser3.push(mode); - } }, transformReply: void 0 }; } }); -var require_PEXPIREAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PEXPIREAT.js"(exports2) { +var require_XPENDING_RANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XPENDING_RANGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the PEXPIREAT command + * Constructs the XPENDING command with range parameters to get detailed information about pending messages * * @param parser - The command parser - * @param key - The key to set the expiration for - * @param msTimestamp - The expiration timestamp in milliseconds (Unix timestamp or Date object) - * @param mode - Optional mode for the command ('NX', 'XX', 'GT', 'LT') - * @see https://redis.io/commands/pexpireat/ + * @param key - The stream key + * @param group - Name of the consumer group + * @param start - Start of ID range (use '-' for minimum ID) + * @param end - End of ID range (use '+' for maximum ID) + * @param count - Maximum number of messages to return + * @param options - Additional filtering options + * @returns Array of pending message details + * @see https://redis.io/commands/xpending/ */ - parseCommand(parser3, key, msTimestamp, mode) { - parser3.push("PEXPIREAT"); + parseCommand(parser3, key, group, start, end, count, options2) { + parser3.push("XPENDING"); parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformPXAT)(msTimestamp)); - if (mode) { - parser3.push(mode); + parser3.push(group); + if (options2?.IDLE !== void 0) { + parser3.push("IDLE", options2.IDLE.toString()); + } + parser3.push(start, end, count.toString()); + if (options2?.consumer) { + parser3.push(options2.consumer); } }, - transformReply: void 0 + /** + * Transforms the raw XPENDING RANGE reply into a structured array of message details + * + * @param reply - Raw reply from Redis + * @returns Array of objects containing message ID, consumer, idle time, and delivery count + */ + transformReply(reply) { + return reply.map((pending) => { + const unwrapped = pending; + return { + id: unwrapped[0], + consumer: unwrapped[1], + millisecondsSinceLastDelivery: unwrapped[2], + deliveriesCounter: unwrapped[3] + }; + }); + } }; } }); -var require_PEXPIRETIME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PEXPIRETIME.js"(exports2) { +var require_XPENDING = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XPENDING.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the PEXPIRETIME command + * Constructs the XPENDING command to inspect pending messages of a consumer group * * @param parser - The command parser - * @param key - The key to get the expiration time for in milliseconds - * @see https://redis.io/commands/pexpiretime/ + * @param key - The stream key + * @param group - Name of the consumer group + * @returns Summary of pending messages including total count, ID range, and per-consumer stats + * @see https://redis.io/commands/xpending/ */ - parseCommand(parser3, key) { - parser3.push("PEXPIRETIME"); + parseCommand(parser3, key, group) { + parser3.push("XPENDING"); parser3.pushKey(key); + parser3.push(group); }, - transformReply: void 0 + /** + * Transforms the raw XPENDING reply into a structured object + * + * @param reply - Raw reply from Redis + * @returns Object containing pending count, ID range, and consumer statistics + */ + transformReply(reply) { + const consumers = reply[3]; + return { + pending: reply[0], + firstId: reply[1], + lastId: reply[2], + consumers: consumers === null ? null : consumers.map((consumer) => { + const [name, deliveriesCounter] = consumer; + return { + name, + deliveriesCounter: Number(deliveriesCounter) + }; + }) + }; + } }; } }); -var require_PFADD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PFADD.js"(exports2) { +var require_XRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XRANGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.xRangeArguments = void 0; + var generic_transformers_1 = require_generic_transformers(); + function xRangeArguments(start, end, options2) { + const args = [start, end]; + if (options2?.COUNT) { + args.push("COUNT", options2.COUNT.toString()); + } + return args; + } + exports2.xRangeArguments = xRangeArguments; exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the PFADD command + * Constructs the XRANGE command to read stream entries in a specific range * * @param parser - The command parser - * @param key - The key of the HyperLogLog - * @param element - Optional elements to add - * @see https://redis.io/commands/pfadd/ + * @param key - The stream key + * @param args - Arguments tuple containing start ID, end ID, and options + * @returns Array of messages in the specified range + * @see https://redis.io/commands/xrange/ */ - parseCommand(parser3, key, element) { - parser3.push("PFADD"); + parseCommand(parser3, key, ...args) { + parser3.push("XRANGE"); parser3.pushKey(key); - if (element) { - parser3.pushVariadic(element); - } + parser3.pushVariadic(xRangeArguments(args[0], args[1], args[2])); }, - transformReply: void 0 - }; - } -}); -var require_PFCOUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PFCOUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, /** - * Constructs the PFCOUNT command + * Transforms the raw XRANGE reply into structured message objects * - * @param parser - The command parser - * @param keys - One or more keys of HyperLogLog structures to count - * @see https://redis.io/commands/pfcount/ + * @param reply - Raw reply from Redis + * @param preserve - Preserve options (unused) + * @param typeMapping - Type mapping for message fields + * @returns Array of structured message objects */ - parseCommand(parser3, keys) { - parser3.push("PFCOUNT"); - parser3.pushKeys(keys); - }, - transformReply: void 0 + transformReply(reply, preserve, typeMapping) { + return reply.map(generic_transformers_1.transformStreamMessageReply.bind(void 0, typeMapping)); + } }; } }); -var require_PFMERGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PFMERGE.js"(exports2) { +var require_XREAD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XREAD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.pushXReadStreams = void 0; + var generic_transformers_1 = require_generic_transformers(); + function pushXReadStreams(parser3, streams) { + parser3.push("STREAMS"); + if (Array.isArray(streams)) { + for (let i2 = 0; i2 < streams.length; i2++) { + parser3.pushKey(streams[i2].key); + } + for (let i2 = 0; i2 < streams.length; i2++) { + parser3.push(streams[i2].id); + } + } else { + parser3.pushKey(streams.key); + parser3.push(streams.id); + } + } + exports2.pushXReadStreams = pushXReadStreams; exports2.default = { + IS_READ_ONLY: true, /** - * Constructs the PFMERGE command + * Constructs the XREAD command to read messages from one or more streams * * @param parser - The command parser - * @param destination - The destination key to merge to - * @param sources - One or more source keys to merge from - * @see https://redis.io/commands/pfmerge/ + * @param streams - Single stream or array of streams to read from + * @param options - Additional options for reading streams + * @returns Array of stream entries, each containing the stream name and its messages + * @see https://redis.io/commands/xread/ */ - parseCommand(parser3, destination, sources) { - parser3.push("PFMERGE"); - parser3.pushKey(destination); - if (sources) { - parser3.pushKeys(sources); + parseCommand(parser3, streams, options2) { + parser3.push("XREAD"); + if (options2?.COUNT) { + parser3.push("COUNT", options2.COUNT.toString()); + } + if (options2?.BLOCK !== void 0) { + parser3.push("BLOCK", options2.BLOCK.toString()); } + pushXReadStreams(parser3, streams); }, - transformReply: void 0 + /** + * Transform functions for different RESP versions + */ + transformReply: { + 2: generic_transformers_1.transformStreamsMessagesReplyResp2, + 3: void 0 + }, + unstableResp3: true }; } }); -var require_PING = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PING.js"(exports2) { +var require_XREADGROUP = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XREADGROUP.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var XREAD_1 = require_XREAD(); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the PING command + * Constructs the XREADGROUP command to read messages from streams as a consumer group member * * @param parser - The command parser - * @param message - Optional message to be returned instead of PONG - * @see https://redis.io/commands/ping/ + * @param group - Name of the consumer group + * @param consumer - Name of the consumer in the group + * @param streams - Single stream or array of streams to read from + * @param options - Additional options for reading streams + * @returns Array of stream entries, each containing the stream name and its messages + * @see https://redis.io/commands/xreadgroup/ */ - parseCommand(parser3, message) { - parser3.push("PING"); - if (message) { - parser3.push(message); + parseCommand(parser3, group, consumer, streams, options2) { + parser3.push("XREADGROUP", "GROUP", group, consumer); + if (options2?.COUNT !== void 0) { + parser3.push("COUNT", options2.COUNT.toString()); + } + if (options2?.BLOCK !== void 0) { + parser3.push("BLOCK", options2.BLOCK.toString()); + } + if (options2?.NOACK) { + parser3.push("NOACK"); } + (0, XREAD_1.pushXReadStreams)(parser3, streams); }, - transformReply: void 0 + /** + * Transform functions for different RESP versions + */ + transformReply: { + 2: generic_transformers_1.transformStreamsMessagesReplyResp2, + 3: void 0 + }, + unstableResp3: true }; } }); -var require_PSETEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PSETEX.js"(exports2) { +var require_XREVRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XREVRANGE.js"(exports2) { "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var XRANGE_1 = __importStar(require_XRANGE()); exports2.default = { + CACHEABLE: XRANGE_1.default.CACHEABLE, + IS_READ_ONLY: XRANGE_1.default.IS_READ_ONLY, /** - * Constructs the PSETEX command + * Constructs the XREVRANGE command to read stream entries in reverse order * * @param parser - The command parser - * @param key - The key to set - * @param ms - The expiration time in milliseconds - * @param value - The value to set - * @see https://redis.io/commands/psetex/ + * @param key - The stream key + * @param args - Arguments tuple containing start ID, end ID, and options + * @returns Array of messages in the specified range in reverse order + * @see https://redis.io/commands/xrevrange/ */ - parseCommand(parser3, key, ms, value) { - parser3.push("PSETEX"); + parseCommand(parser3, key, ...args) { + parser3.push("XREVRANGE"); parser3.pushKey(key); - parser3.push(ms.toString(), value); + parser3.pushVariadic((0, XRANGE_1.xRangeArguments)(args[0], args[1], args[2])); }, - transformReply: void 0 + transformReply: XRANGE_1.default.transformReply }; } }); -var require_PTTL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PTTL.js"(exports2) { +var require_XSETID = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XSETID.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: true, - /** - * Constructs the PTTL command - * - * @param parser - The command parser - * @param key - The key to get the time to live in milliseconds - * @see https://redis.io/commands/pttl/ - */ - parseCommand(parser3, key) { - parser3.push("PTTL"); + IS_READ_ONLY: false, + parseCommand(parser3, key, lastId, options2) { + parser3.push("XSETID"); parser3.pushKey(key); + parser3.push(lastId); + if (options2?.ENTRIESADDED) { + parser3.push("ENTRIESADDED", options2.ENTRIESADDED.toString()); + } + if (options2?.MAXDELETEDID) { + parser3.push("MAXDELETEDID", options2.MAXDELETEDID); + } }, transformReply: void 0 }; } }); -var require_PUBLISH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBLISH.js"(exports2) { +var require_XTRIM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XTRIM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - IS_FORWARD_COMMAND: true, + IS_READ_ONLY: false, /** - * Constructs the PUBLISH command + * Constructs the XTRIM command to trim a stream by length or minimum ID * * @param parser - The command parser - * @param channel - The channel to publish to - * @param message - The message to publish - * @see https://redis.io/commands/publish/ + * @param key - The stream key + * @param strategy - Trim by maximum length (MAXLEN) or minimum ID (MINID) + * @param threshold - Maximum length or minimum ID threshold + * @param options - Additional options for trimming + * @returns Number of entries removed from the stream + * @see https://redis.io/commands/xtrim/ */ - parseCommand(parser3, channel, message) { - parser3.push("PUBLISH", channel, message); + parseCommand(parser3, key, strategy, threshold, options2) { + parser3.push("XTRIM"); + parser3.pushKey(key); + parser3.push(strategy); + if (options2?.strategyModifier) { + parser3.push(options2.strategyModifier); + } + parser3.push(threshold.toString()); + if (options2?.LIMIT) { + parser3.push("LIMIT", options2.LIMIT.toString()); + } + if (options2?.policy) { + parser3.push(options2.policy); + } }, transformReply: void 0 }; } }); -var require_PUBSUB_CHANNELS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_CHANNELS.js"(exports2) { +var require_ZADD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZADD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.pushMembers = void 0; + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Constructs the PUBSUB CHANNELS command + * Constructs the ZADD command to add one or more members to a sorted set * * @param parser - The command parser - * @param pattern - Optional pattern to filter channels - * @see https://redis.io/commands/pubsub-channels/ + * @param key - The sorted set key + * @param members - One or more members to add with their scores + * @param options - Additional options for adding members + * @returns Number of new members added (or changed members if CH is set) + * @see https://redis.io/commands/zadd/ */ - parseCommand(parser3, pattern) { - parser3.push("PUBSUB", "CHANNELS"); - if (pattern) { - parser3.push(pattern); + parseCommand(parser3, key, members, options2) { + parser3.push("ZADD"); + parser3.pushKey(key); + if (options2?.condition) { + parser3.push(options2.condition); + } else if (options2?.NX) { + parser3.push("NX"); + } else if (options2?.XX) { + parser3.push("XX"); + } + if (options2?.comparison) { + parser3.push(options2.comparison); + } else if (options2?.LT) { + parser3.push("LT"); + } else if (options2?.GT) { + parser3.push("GT"); + } + if (options2?.CH) { + parser3.push("CH"); } + pushMembers(parser3, members); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformDoubleReply }; + function pushMembers(parser3, members) { + if (Array.isArray(members)) { + for (const member of members) { + pushMember(parser3, member); + } + } else { + pushMember(parser3, members); + } + } + exports2.pushMembers = pushMembers; + function pushMember(parser3, member) { + parser3.push((0, generic_transformers_1.transformDoubleArgument)(member.score), member.value); + } } }); -var require_PUBSUB_NUMPAT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_NUMPAT.js"(exports2) { +var require_ZADD_INCR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZADD_INCR.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var ZADD_1 = require_ZADD(); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, /** - * Constructs the PUBSUB NUMPAT command + * Constructs the ZADD command with INCR option to increment the score of a member * * @param parser - The command parser - * @see https://redis.io/commands/pubsub-numpat/ + * @param key - The sorted set key + * @param members - Member(s) whose score to increment + * @param options - Additional options for the increment operation + * @returns The new score of the member after increment (null if member does not exist with XX option) + * @see https://redis.io/commands/zadd/ */ - parseCommand(parser3) { - parser3.push("PUBSUB", "NUMPAT"); + parseCommand(parser3, key, members, options2) { + parser3.push("ZADD"); + parser3.pushKey(key); + if (options2?.condition) { + parser3.push(options2.condition); + } + if (options2?.comparison) { + parser3.push(options2.comparison); + } + if (options2?.CH) { + parser3.push("CH"); + } + parser3.push("INCR"); + (0, ZADD_1.pushMembers)(parser3, members); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformNullableDoubleReply }; } }); -var require_PUBSUB_NUMSUB = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_NUMSUB.js"(exports2) { +var require_ZCARD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZCARD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the PUBSUB NUMSUB command + * Constructs the ZCARD command to get the cardinality (number of members) of a sorted set * * @param parser - The command parser - * @param channels - Optional channel names to get subscription count for - * @see https://redis.io/commands/pubsub-numsub/ + * @param key - The sorted set key + * @returns Number of members in the sorted set + * @see https://redis.io/commands/zcard/ */ - parseCommand(parser3, channels) { - parser3.push("PUBSUB", "NUMSUB"); - if (channels) { - parser3.pushVariadic(channels); - } + parseCommand(parser3, key) { + parser3.push("ZCARD"); + parser3.pushKey(key); }, - /** - * Transforms the PUBSUB NUMSUB reply into a record of channel name to subscriber count - * - * @param rawReply - The raw reply from Redis - * @returns Record mapping channel names to their subscriber counts - */ - transformReply(rawReply) { - const reply = /* @__PURE__ */ Object.create(null); - let i2 = 0; - while (i2 < rawReply.length) { - reply[rawReply[i2++].toString()] = Number(rawReply[i2++]); - } - return reply; - } + transformReply: void 0 }; } }); -var require_PUBSUB_SHARDNUMSUB = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_SHARDNUMSUB.js"(exports2) { +var require_ZCOUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZCOUNT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the PUBSUB SHARDNUMSUB command - * - * @param parser - The command parser - * @param channels - Optional shard channel names to get subscription count for - * @see https://redis.io/commands/pubsub-shardnumsub/ + * Returns the number of elements in the sorted set with a score between min and max. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param min - Minimum score to count from (inclusive). + * @param max - Maximum score to count to (inclusive). */ - parseCommand(parser3, channels) { - parser3.push("PUBSUB", "SHARDNUMSUB"); - if (channels) { - parser3.pushVariadic(channels); - } + parseCommand(parser3, key, min, max) { + parser3.push("ZCOUNT"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); }, - /** - * Transforms the PUBSUB SHARDNUMSUB reply into a record of shard channel name to subscriber count - * - * @param reply - The raw reply from Redis - * @returns Record mapping shard channel names to their subscriber counts - */ - transformReply(reply) { - const transformedReply = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < reply.length; i2 += 2) { - transformedReply[reply[i2].toString()] = reply[i2 + 1]; - } - return transformedReply; - } + transformReply: void 0 }; } }); -var require_PUBSUB_SHARDCHANNELS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/PUBSUB_SHARDCHANNELS.js"(exports2) { +var require_ZDIFF = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZDIFF.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the PUBSUB SHARDCHANNELS command - * - * @param parser - The command parser - * @param pattern - Optional pattern to filter shard channels - * @see https://redis.io/commands/pubsub-shardchannels/ + * Returns the difference between the first sorted set and all the successive sorted sets. + * @param parser - The Redis command parser. + * @param keys - Keys of the sorted sets. */ - parseCommand(parser3, pattern) { - parser3.push("PUBSUB", "SHARDCHANNELS"); - if (pattern) { - parser3.push(pattern); - } + parseCommand(parser3, keys) { + parser3.push("ZDIFF"); + parser3.pushKeysLength(keys); }, transformReply: void 0 }; } }); -var require_RANDOMKEY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RANDOMKEY.js"(exports2) { +var require_ZDIFF_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZDIFF_WITHSCORES.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var ZDIFF_1 = __importDefault(require_ZDIFF()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: ZDIFF_1.default.IS_READ_ONLY, /** - * Constructs the RANDOMKEY command - * - * @param parser - The command parser - * @see https://redis.io/commands/randomkey/ + * Returns the difference between the first sorted set and all successive sorted sets with their scores. + * @param parser - The Redis command parser. + * @param keys - Keys of the sorted sets. */ - parseCommand(parser3) { - parser3.push("RANDOMKEY"); + parseCommand(parser3, keys) { + ZDIFF_1.default.parseCommand(parser3, keys); + parser3.push("WITHSCORES"); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_READONLY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/READONLY.js"(exports2) { +var require_ZDIFFSTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZDIFFSTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the READONLY command - * - * @param parser - The command parser - * @see https://redis.io/commands/readonly/ + * Computes the difference between the first and all successive sorted sets and stores it in a new key. + * @param parser - The Redis command parser. + * @param destination - Destination key where the result will be stored. + * @param inputKeys - Keys of the sorted sets to find the difference between. */ - parseCommand(parser3) { - parser3.push("READONLY"); + parseCommand(parser3, destination, inputKeys) { + parser3.push("ZDIFFSTORE"); + parser3.pushKey(destination); + parser3.pushKeysLength(inputKeys); }, transformReply: void 0 }; } }); -var require_RENAME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RENAME.js"(exports2) { +var require_ZINCRBY = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINCRBY.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - IS_READ_ONLY: true, /** - * Constructs the RENAME command - * - * @param parser - The command parser - * @param key - The key to rename - * @param newKey - The new key name - * @see https://redis.io/commands/rename/ + * Increments the score of a member in a sorted set by the specified increment. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param increment - Value to increment the score by. + * @param member - Member whose score should be incremented. */ - parseCommand(parser3, key, newKey) { - parser3.push("RENAME"); - parser3.pushKeys([key, newKey]); + parseCommand(parser3, key, increment2, member) { + parser3.push("ZINCRBY"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformDoubleArgument)(increment2), member); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformDoubleReply }; } }); -var require_RENAMENX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RENAMENX.js"(exports2) { +var require_ZINTER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseZInterArguments = void 0; + var generic_transformers_1 = require_generic_transformers(); + function parseZInterArguments(parser3, keys, options2) { + (0, generic_transformers_1.parseZKeysArguments)(parser3, keys); + if (options2?.AGGREGATE) { + parser3.push("AGGREGATE", options2.AGGREGATE); + } + } + exports2.parseZInterArguments = parseZInterArguments; exports2.default = { IS_READ_ONLY: true, /** - * Constructs the RENAMENX command - * - * @param parser - The command parser - * @param key - The key to rename - * @param newKey - The new key name, if it doesn't exist - * @see https://redis.io/commands/renamenx/ + * Intersects multiple sorted sets and returns the result as a new sorted set. + * @param parser - The Redis command parser. + * @param keys - Keys of the sorted sets to intersect. + * @param options - Optional parameters for the intersection operation. */ - parseCommand(parser3, key, newKey) { - parser3.push("RENAMENX"); - parser3.pushKeys([key, newKey]); + parseCommand(parser3, keys, options2) { + parser3.push("ZINTER"); + parseZInterArguments(parser3, keys, options2); }, transformReply: void 0 }; } }); -var require_REPLICAOF = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/REPLICAOF.js"(exports2) { +var require_ZINTER_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTER_WITHSCORES.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var ZINTER_1 = __importDefault(require_ZINTER()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: ZINTER_1.default.IS_READ_ONLY, /** - * Constructs the REPLICAOF command - * - * @param parser - The command parser - * @param host - The host of the master to replicate from - * @param port - The port of the master to replicate from - * @see https://redis.io/commands/replicaof/ + * Intersects multiple sorted sets and returns the result with scores. + * @param args - Same parameters as ZINTER command. */ - parseCommand(parser3, host, port) { - parser3.push("REPLICAOF", host, port.toString()); + parseCommand(...args) { + ZINTER_1.default.parseCommand(...args); + args[0].push("WITHSCORES"); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_RESTORE_ASKING = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RESTORE-ASKING.js"(exports2) { +var require_ZINTERCARD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTERCARD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, IS_READ_ONLY: true, /** - * Constructs the RESTORE-ASKING command - * - * @param parser - The command parser - * @see https://redis.io/commands/restore-asking/ + * Returns the cardinality of the intersection of multiple sorted sets. + * @param parser - The Redis command parser. + * @param keys - Keys of the sorted sets to intersect. + * @param options - Limit option or options object with limit. */ - parseCommand(parser3) { - parser3.push("RESTORE-ASKING"); + parseCommand(parser3, keys, options2) { + parser3.push("ZINTERCARD"); + parser3.pushKeysLength(keys); + if (typeof options2 === "number") { + parser3.push("LIMIT", options2.toString()); + } else if (options2?.LIMIT) { + parser3.push("LIMIT", options2.LIMIT.toString()); + } }, transformReply: void 0 }; } }); -var require_RESTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RESTORE.js"(exports2) { +var require_ZINTERSTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTERSTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var ZINTER_1 = require_ZINTER(); exports2.default = { IS_READ_ONLY: false, /** - * Constructs the RESTORE command - * - * @param parser - The command parser - * @param key - The key to restore - * @param ttl - Time to live in milliseconds, 0 for no expiry - * @param serializedValue - The serialized value from DUMP command - * @param options - Options for the RESTORE command - * @see https://redis.io/commands/restore/ + * Stores the result of intersection of multiple sorted sets in a new sorted set. + * @param parser - The Redis command parser. + * @param destination - Destination key where the result will be stored. + * @param keys - Keys of the sorted sets to intersect. + * @param options - Optional parameters for the intersection operation. */ - parseCommand(parser3, key, ttl, serializedValue, options2) { - parser3.push("RESTORE"); - parser3.pushKey(key); - parser3.push(ttl.toString(), serializedValue); - if (options2?.REPLACE) { - parser3.push("REPLACE"); - } - if (options2?.ABSTTL) { - parser3.push("ABSTTL"); - } - if (options2?.IDLETIME) { - parser3.push("IDLETIME", options2.IDLETIME.toString()); - } - if (options2?.FREQ) { - parser3.push("FREQ", options2.FREQ.toString()); - } + parseCommand(parser3, destination, keys, options2) { + parser3.push("ZINTERSTORE"); + parser3.pushKey(destination); + (0, ZINTER_1.parseZInterArguments)(parser3, keys, options2); }, transformReply: void 0 }; } }); -var require_ROLE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ROLE.js"(exports2) { +var require_ZLEXCOUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZLEXCOUNT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the ROLE command - * - * @param parser - The command parser - * @see https://redis.io/commands/role/ + * Returns the number of elements in the sorted set between the lexicographical range specified by min and max. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param min - Minimum lexicographical value (inclusive). + * @param max - Maximum lexicographical value (inclusive). */ - parseCommand(parser3) { - parser3.push("ROLE"); + parseCommand(parser3, key, min, max) { + parser3.push("ZLEXCOUNT"); + parser3.pushKey(key); + parser3.push(min); + parser3.push(max); }, - /** - * Transforms the ROLE reply into a structured object - * - * @param reply - The raw reply from Redis - * @returns Structured object representing role information - */ - transformReply(reply) { - switch (reply[0]) { - case "master": { - const [role, replicationOffest, replicas] = reply; - return { - role, - replicationOffest, - replicas: replicas.map((replica) => { - const [host, port, replicationOffest2] = replica; - return { - host, - port: Number(port), - replicationOffest: Number(replicationOffest2) - }; - }) - }; - } - case "slave": { - const [role, masterHost, masterPort, state, dataReceived] = reply; - return { - role, - master: { - host: masterHost, - port: masterPort - }, - state, - dataReceived - }; - } - case "sentinel": { - const [role, masterNames] = reply; - return { - role, - masterNames - }; - } - } - } + transformReply: void 0 }; } }); -var require_RPOP_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPOP_COUNT.js"(exports2) { +var require_ZMSCORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZMSCORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Constructs the RPOP command with count parameter - * - * @param parser - The command parser - * @param key - The list key to pop from - * @param count - The number of elements to pop - * @see https://redis.io/commands/rpop/ + * Returns the scores associated with the specified members in the sorted set stored at key. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param member - One or more members to get scores for. */ - parseCommand(parser3, key, count) { - parser3.push("RPOP"); + parseCommand(parser3, key, member) { + parser3.push("ZMSCORE"); parser3.pushKey(key); - parser3.push(count.toString()); + parser3.pushVariadic(member); }, - transformReply: void 0 + transformReply: { + 2: (reply, preserve, typeMapping) => { + return reply.map((0, generic_transformers_1.createTransformNullableDoubleReplyResp2Func)(preserve, typeMapping)); + }, + 3: void 0 + } }; } }); -var require_RPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPOP.js"(exports2) { +var require_ZPOPMAX_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMAX_COUNT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the RPOP command - * - * @param parser - The command parser - * @param key - The list key to pop from - * @see https://redis.io/commands/rpop/ + * Removes and returns up to count members with the highest scores in the sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param count - Number of members to pop. */ - parseCommand(parser3, key) { - parser3.push("RPOP"); + parseCommand(parser3, key, count) { + parser3.push("ZPOPMAX"); parser3.pushKey(key); + parser3.push(count.toString()); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_RPOPLPUSH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPOPLPUSH.js"(exports2) { +var require_ZPOPMAX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMAX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the RPOPLPUSH command - * - * @param parser - The command parser - * @param source - The source list key - * @param destination - The destination list key - * @see https://redis.io/commands/rpoplpush/ + * Removes and returns the member with the highest score in the sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. */ - parseCommand(parser3, source, destination) { - parser3.push("RPOPLPUSH"); - parser3.pushKeys([source, destination]); + parseCommand(parser3, key) { + parser3.push("ZPOPMAX"); + parser3.pushKey(key); }, - transformReply: void 0 - }; - } -}); -var require_RPUSH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPUSH.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - /** - * Constructs the RPUSH command - * - * @param parser - The command parser - * @param key - The list key to push to - * @param element - One or more elements to push - * @see https://redis.io/commands/rpush/ - */ - parseCommand(parser3, key, element) { - parser3.push("RPUSH"); - parser3.pushKey(key); - parser3.pushVariadic(element); - }, - transformReply: void 0 + transformReply: { + 2: (reply, preserve, typeMapping) => { + if (reply.length === 0) + return null; + return { + value: reply[0], + score: generic_transformers_1.transformDoubleReply[2](reply[1], preserve, typeMapping) + }; + }, + 3: (reply) => { + if (reply.length === 0) + return null; + return { + value: reply[0], + score: reply[1] + }; + } + } }; } }); -var require_RPUSHX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/RPUSHX.js"(exports2) { +var require_ZPOPMIN_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMIN_COUNT.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the RPUSHX command - * - * @param parser - The command parser - * @param key - The list key to push to (only if it exists) - * @param element - One or more elements to push - * @see https://redis.io/commands/rpushx/ + * Removes and returns up to count members with the lowest scores in the sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param count - Number of members to pop. */ - parseCommand(parser3, key, element) { - parser3.push("RPUSHX"); + parseCommand(parser3, key, count) { + parser3.push("ZPOPMIN"); parser3.pushKey(key); - parser3.pushVariadic(element); + parser3.push(count.toString()); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_SADD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SADD.js"(exports2) { +var require_ZPOPMIN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMIN.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var ZPOPMAX_1 = __importDefault(require_ZPOPMAX()); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the SADD command - * - * @param parser - The command parser - * @param key - The set key to add members to - * @param members - One or more members to add to the set - * @see https://redis.io/commands/sadd/ + * Removes and returns the member with the lowest score in the sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. */ - parseCommand(parser3, key, members) { - parser3.push("SADD"); + parseCommand(parser3, key) { + parser3.push("ZPOPMIN"); parser3.pushKey(key); - parser3.pushVariadic(members); }, - transformReply: void 0 + transformReply: ZPOPMAX_1.default.transformReply }; } }); -var require_SCARD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCARD.js"(exports2) { +var require_ZRANDMEMBER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANDMEMBER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SCARD command - * - * @param parser - The command parser - * @param key - The set key to get the cardinality of - * @see https://redis.io/commands/scard/ + * Returns a random member from a sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. */ parseCommand(parser3, key) { - parser3.push("SCARD"); + parser3.push("ZRANDMEMBER"); parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_SCRIPT_DEBUG = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_DEBUG.js"(exports2) { +var require_ZRANDMEMBER_COUNT = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANDMEMBER_COUNT.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var ZRANDMEMBER_1 = __importDefault(require_ZRANDMEMBER()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: ZRANDMEMBER_1.default.IS_READ_ONLY, /** - * Constructs the SCRIPT DEBUG command - * - * @param parser - The command parser - * @param mode - Debug mode: YES, SYNC, or NO - * @see https://redis.io/commands/script-debug/ + * Returns one or more random members from a sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param count - Number of members to return. */ - parseCommand(parser3, mode) { - parser3.push("SCRIPT", "DEBUG", mode); + parseCommand(parser3, key, count) { + ZRANDMEMBER_1.default.parseCommand(parser3, key); + parser3.push(count.toString()); }, transformReply: void 0 }; } }); -var require_SCRIPT_EXISTS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_EXISTS.js"(exports2) { +var require_ZRANDMEMBER_COUNT_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var ZRANDMEMBER_COUNT_1 = __importDefault(require_ZRANDMEMBER_COUNT()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + IS_READ_ONLY: ZRANDMEMBER_COUNT_1.default.IS_READ_ONLY, /** - * Constructs the SCRIPT EXISTS command - * - * @param parser - The command parser - * @param sha1 - One or more SHA1 digests of scripts - * @see https://redis.io/commands/script-exists/ + * Returns one or more random members with their scores from a sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param count - Number of members to return. */ - parseCommand(parser3, sha1) { - parser3.push("SCRIPT", "EXISTS"); - parser3.pushVariadic(sha1); + parseCommand(parser3, key, count) { + ZRANDMEMBER_COUNT_1.default.parseCommand(parser3, key, count); + parser3.push("WITHSCORES"); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_SCRIPT_FLUSH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_FLUSH.js"(exports2) { +var require_ZRANGE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.zRangeArgument = void 0; + var generic_transformers_1 = require_generic_transformers(); + function zRangeArgument(min, max, options2) { + const args = [ + (0, generic_transformers_1.transformStringDoubleArgument)(min), + (0, generic_transformers_1.transformStringDoubleArgument)(max) + ]; + switch (options2?.BY) { + case "SCORE": + args.push("BYSCORE"); + break; + case "LEX": + args.push("BYLEX"); + break; + } + if (options2?.REV) { + args.push("REV"); + } + if (options2?.LIMIT) { + args.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + } + return args; + } + exports2.zRangeArgument = zRangeArgument; exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SCRIPT FLUSH command - * - * @param parser - The command parser - * @param mode - Optional flush mode: ASYNC or SYNC - * @see https://redis.io/commands/script-flush/ + * Returns the specified range of elements in the sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param min - Minimum index, score or lexicographical value. + * @param max - Maximum index, score or lexicographical value. + * @param options - Optional parameters for range retrieval (BY, REV, LIMIT). */ - parseCommand(parser3, mode) { - parser3.push("SCRIPT", "FLUSH"); - if (mode) { - parser3.push(mode); - } + parseCommand(parser3, key, min, max, options2) { + parser3.push("ZRANGE"); + parser3.pushKey(key); + parser3.pushVariadic(zRangeArgument(min, max, options2)); }, transformReply: void 0 }; } }); -var require_SCRIPT_KILL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_KILL.js"(exports2) { +var require_ZRANGE_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGE_WITHSCORES.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var ZRANGE_1 = __importDefault(require_ZRANGE()); exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, + CACHEABLE: ZRANGE_1.default.CACHEABLE, + IS_READ_ONLY: ZRANGE_1.default.IS_READ_ONLY, /** - * Constructs the SCRIPT KILL command - * - * @param parser - The command parser - * @see https://redis.io/commands/script-kill/ + * Returns the specified range of elements in the sorted set with their scores. + * @param args - Same parameters as the ZRANGE command. */ - parseCommand(parser3) { - parser3.push("SCRIPT", "KILL"); + parseCommand(...args) { + const parser3 = args[0]; + ZRANGE_1.default.parseCommand(...args); + parser3.push("WITHSCORES"); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_SCRIPT_LOAD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SCRIPT_LOAD.js"(exports2) { +var require_ZRANGEBYLEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGEBYLEX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - NOT_KEYED_COMMAND: true, + CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SCRIPT LOAD command - * - * @param parser - The command parser - * @param script - The Lua script to load - * @see https://redis.io/commands/script-load/ + * Returns all the elements in the sorted set at key with a lexicographical value between min and max. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param min - Minimum lexicographical value. + * @param max - Maximum lexicographical value. + * @param options - Optional parameters including LIMIT. */ - parseCommand(parser3, script) { - parser3.push("SCRIPT", "LOAD", script); + parseCommand(parser3, key, min, max, options2) { + parser3.push("ZRANGEBYLEX"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); + if (options2?.LIMIT) { + parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + } }, transformReply: void 0 }; } }); -var require_SDIFF = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SDIFF.js"(exports2) { +var require_ZRANGEBYSCORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGEBYSCORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SDIFF command - * - * @param parser - The command parser - * @param keys - One or more set keys to compute the difference from - * @see https://redis.io/commands/sdiff/ + * Returns all the elements in the sorted set with a score between min and max. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param min - Minimum score. + * @param max - Maximum score. + * @param options - Optional parameters including LIMIT. */ - parseCommand(parser3, keys) { - parser3.push("SDIFF"); - parser3.pushKeys(keys); + parseCommand(parser3, key, min, max, options2) { + parser3.push("ZRANGEBYSCORE"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); + if (options2?.LIMIT) { + parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + } }, transformReply: void 0 }; } }); -var require_SDIFFSTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SDIFFSTORE.js"(exports2) { +var require_ZRANGEBYSCORE_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGEBYSCORE_WITHSCORES.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var ZRANGEBYSCORE_1 = __importDefault(require_ZRANGEBYSCORE()); exports2.default = { + CACHEABLE: ZRANGEBYSCORE_1.default.CACHEABLE, + IS_READ_ONLY: ZRANGEBYSCORE_1.default.IS_READ_ONLY, /** - * Constructs the SDIFFSTORE command - * - * @param parser - The command parser - * @param destination - The destination key to store the result - * @param keys - One or more set keys to compute the difference from - * @see https://redis.io/commands/sdiffstore/ + * Returns all the elements in the sorted set with a score between min and max, with their scores. + * @param args - Same parameters as the ZRANGEBYSCORE command. */ - parseCommand(parser3, destination, keys) { - parser3.push("SDIFFSTORE"); - parser3.pushKey(destination); - parser3.pushKeys(keys); + parseCommand(...args) { + const parser3 = args[0]; + ZRANGEBYSCORE_1.default.parseCommand(...args); + parser3.push("WITHSCORES"); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_SET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SET.js"(exports2) { +var require_ZRANGESTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGESTORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the SET command - * - * @param parser - The command parser - * @param key - The key to set - * @param value - The value to set - * @param options - Additional options for the SET command - * @see https://redis.io/commands/set/ + * Stores the result of a range operation on a sorted set into a new sorted set. + * @param parser - The Redis command parser. + * @param destination - Destination key where the result will be stored. + * @param source - Key of the source sorted set. + * @param min - Minimum index, score or lexicographical value. + * @param max - Maximum index, score or lexicographical value. + * @param options - Optional parameters for the range operation (BY, REV, LIMIT). */ - parseCommand(parser3, key, value, options2) { - parser3.push("SET"); - parser3.pushKey(key); - parser3.push(typeof value === "number" ? value.toString() : value); - if (options2?.expiration) { - if (typeof options2.expiration === "string") { - parser3.push(options2.expiration); - } else if (options2.expiration.type === "KEEPTTL") { - parser3.push("KEEPTTL"); - } else { - parser3.push(options2.expiration.type, options2.expiration.value.toString()); - } - } else if (options2?.EX !== void 0) { - parser3.push("EX", options2.EX.toString()); - } else if (options2?.PX !== void 0) { - parser3.push("PX", options2.PX.toString()); - } else if (options2?.EXAT !== void 0) { - parser3.push("EXAT", options2.EXAT.toString()); - } else if (options2?.PXAT !== void 0) { - parser3.push("PXAT", options2.PXAT.toString()); - } else if (options2?.KEEPTTL) { - parser3.push("KEEPTTL"); + parseCommand(parser3, destination, source, min, max, options2) { + parser3.push("ZRANGESTORE"); + parser3.pushKey(destination); + parser3.pushKey(source); + parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); + switch (options2?.BY) { + case "SCORE": + parser3.push("BYSCORE"); + break; + case "LEX": + parser3.push("BYLEX"); + break; } - if (options2?.condition) { - parser3.push(options2.condition); - } else if (options2?.NX) { - parser3.push("NX"); - } else if (options2?.XX) { - parser3.push("XX"); + if (options2?.REV) { + parser3.push("REV"); } - if (options2?.GET) { - parser3.push("GET"); + if (options2?.LIMIT) { + parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); } }, transformReply: void 0 }; } }); -var require_SETBIT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETBIT.js"(exports2) { +var require_ZREMRANGEBYSCORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREMRANGEBYSCORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { IS_READ_ONLY: false, /** - * Constructs the SETBIT command - * - * @param parser - The command parser - * @param key - The key to set the bit on - * @param offset - The bit offset (zero-based) - * @param value - The bit value (0 or 1) - * @see https://redis.io/commands/setbit/ + * Removes all elements in the sorted set with scores between min and max. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param min - Minimum score. + * @param max - Maximum score. */ - parseCommand(parser3, key, offset, value) { - parser3.push("SETBIT"); + parseCommand(parser3, key, min, max) { + parser3.push("ZREMRANGEBYSCORE"); parser3.pushKey(key); - parser3.push(offset.toString(), value.toString()); + parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); }, transformReply: void 0 }; } }); -var require_SETEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETEX.js"(exports2) { +var require_ZRANK = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANK.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + CACHEABLE: true, + IS_READ_ONLY: true, /** - * Constructs the SETEX command - * - * @param parser - The command parser - * @param key - The key to set - * @param seconds - The expiration time in seconds - * @param value - The value to set - * @see https://redis.io/commands/setex/ + * Returns the rank of a member in the sorted set, with scores ordered from low to high. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param member - Member to get the rank for. */ - parseCommand(parser3, key, seconds, value) { - parser3.push("SETEX"); + parseCommand(parser3, key, member) { + parser3.push("ZRANK"); parser3.pushKey(key); - parser3.push(seconds.toString(), value); + parser3.push(member); }, transformReply: void 0 }; } }); -var require_SETNX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETNX.js"(exports2) { +var require_ZRANK_WITHSCORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANK_WITHSCORE.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); + var ZRANK_1 = __importDefault(require_ZRANK()); exports2.default = { + CACHEABLE: ZRANK_1.default.CACHEABLE, + IS_READ_ONLY: ZRANK_1.default.IS_READ_ONLY, /** - * Constructs the SETNX command - * - * @param parser - The command parser - * @param key - The key to set if it doesn't exist - * @param value - The value to set - * @see https://redis.io/commands/setnx/ + * Returns the rank of a member in the sorted set with its score. + * @param args - Same parameters as the ZRANK command. */ - parseCommand(parser3, key, value) { - parser3.push("SETNX"); - parser3.pushKey(key); - parser3.push(value); + parseCommand(...args) { + const parser3 = args[0]; + ZRANK_1.default.parseCommand(...args); + parser3.push("WITHSCORE"); }, - transformReply: void 0 + transformReply: { + 2: (reply) => { + if (reply === null) + return null; + return { + rank: reply[0], + score: Number(reply[1]) + }; + }, + 3: (reply) => { + if (reply === null) + return null; + return { + rank: reply[0], + score: reply[1] + }; + } + } }; } }); -var require_SETRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SETRANGE.js"(exports2) { +var require_ZREM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { + IS_READ_ONLY: false, /** - * Constructs the SETRANGE command - * - * @param parser - The command parser - * @param key - The key to modify - * @param offset - The offset at which to start writing - * @param value - The value to write at the offset - * @see https://redis.io/commands/setrange/ + * Removes the specified members from the sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param member - One or more members to remove. */ - parseCommand(parser3, key, offset, value) { - parser3.push("SETRANGE"); + parseCommand(parser3, key, member) { + parser3.push("ZREM"); parser3.pushKey(key); - parser3.push(offset.toString(), value); + parser3.pushVariadic(member); }, transformReply: void 0 }; } }); -var require_SINTER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SINTER.js"(exports2) { +var require_ZREMRANGEBYLEX = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREMRANGEBYLEX.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + IS_READ_ONLY: false, /** - * Constructs the SINTER command - * - * @param parser - The command parser - * @param keys - One or more set keys to compute the intersection from - * @see https://redis.io/commands/sinter/ + * Removes all elements in the sorted set with lexicographical values between min and max. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param min - Minimum lexicographical value. + * @param max - Maximum lexicographical value. */ - parseCommand(parser3, keys) { - parser3.push("SINTER"); - parser3.pushKeys(keys); - }, - transformReply: void 0 - }; - } -}); -var require_SINTERCARD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SINTERCARD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Constructs the SINTERCARD command - * - * @param parser - The command parser - * @param keys - One or more set keys to compute the intersection cardinality from - * @param options - Options for the SINTERCARD command or a number for LIMIT (backwards compatibility) - * @see https://redis.io/commands/sintercard/ - */ - parseCommand(parser3, keys, options2) { - parser3.push("SINTERCARD"); - parser3.pushKeysLength(keys); - if (typeof options2 === "number") { - parser3.push("LIMIT", options2.toString()); - } else if (options2?.LIMIT !== void 0) { - parser3.push("LIMIT", options2.LIMIT.toString()); - } + parseCommand(parser3, key, min, max) { + parser3.push("ZREMRANGEBYLEX"); + parser3.pushKey(key); + parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); }, transformReply: void 0 }; } }); -var require_SINTERSTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SINTERSTORE.js"(exports2) { +var require_ZREMRANGEBYRANK = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREMRANGEBYRANK.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { IS_READ_ONLY: false, /** - * Constructs the SINTERSTORE command - * - * @param parser - The command parser - * @param destination - The destination key to store the result - * @param keys - One or more set keys to compute the intersection from - * @see https://redis.io/commands/sinterstore/ + * Removes all elements in the sorted set with rank between start and stop. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param start - Minimum rank (starting from 0). + * @param stop - Maximum rank. */ - parseCommand(parser3, destination, keys) { - parser3.push("SINTERSTORE"); - parser3.pushKey(destination); - parser3.pushKeys(keys); + parseCommand(parser3, key, start, stop) { + parser3.push("ZREMRANGEBYRANK"); + parser3.pushKey(key); + parser3.push(start.toString(), stop.toString()); }, transformReply: void 0 }; } }); -var require_SISMEMBER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SISMEMBER.js"(exports2) { +var require_ZREVRANK = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREVRANK.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SISMEMBER command - * - * @param parser - The command parser - * @param key - The set key to check membership in - * @param member - The member to check for existence - * @see https://redis.io/commands/sismember/ + * Returns the rank of a member in the sorted set, with scores ordered from high to low. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param member - Member to get the rank for. */ parseCommand(parser3, key, member) { - parser3.push("SISMEMBER"); + parser3.push("ZREVRANK"); parser3.pushKey(key); parser3.push(member); }, @@ -40921,69924 +35840,39519 @@ var require_SISMEMBER = __commonJS({ }; } }); -var require_SMEMBERS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SMEMBERS.js"(exports2) { +var require_ZSCAN = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZSCAN.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var SCAN_1 = require_SCAN(); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SMEMBERS command - * - * @param parser - The command parser - * @param key - The set key to get all members from - * @see https://redis.io/commands/smembers/ + * Incrementally iterates over a sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param cursor - Cursor position to start the scan from. + * @param options - Optional scan parameters (COUNT, MATCH, TYPE). */ - parseCommand(parser3, key) { - parser3.push("SMEMBERS"); + parseCommand(parser3, key, cursor, options2) { + parser3.push("ZSCAN"); parser3.pushKey(key); + (0, SCAN_1.parseScanArguments)(parser3, cursor, options2); }, - transformReply: { - 2: void 0, - 3: void 0 + transformReply([cursor, rawMembers]) { + return { + cursor, + members: generic_transformers_1.transformSortedSetReply[2](rawMembers) + }; } }; } }); -var require_SMISMEMBER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SMISMEMBER.js"(exports2) { +var require_ZSCORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZSCORE.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SMISMEMBER command - * - * @param parser - The command parser - * @param key - The set key to check membership in - * @param members - The members to check for existence - * @see https://redis.io/commands/smismember/ + * Returns the score of a member in a sorted set. + * @param parser - The Redis command parser. + * @param key - Key of the sorted set. + * @param member - Member to get the score for. */ - parseCommand(parser3, key, members) { - parser3.push("SMISMEMBER"); + parseCommand(parser3, key, member) { + parser3.push("ZSCORE"); parser3.pushKey(key); - parser3.pushVariadic(members); - }, - transformReply: void 0 - }; - } -}); -var require_SMOVE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SMOVE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the SMOVE command - * - * @param parser - The command parser - * @param source - The source set key - * @param destination - The destination set key - * @param member - The member to move - * @see https://redis.io/commands/smove/ - */ - parseCommand(parser3, source, destination, member) { - parser3.push("SMOVE"); - parser3.pushKeys([source, destination]); parser3.push(member); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformNullableDoubleReply }; } }); -var require_SORT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SORT.js"(exports2) { +var require_ZUNION = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZUNION.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseSortArguments = void 0; - function parseSortArguments(parser3, key, options2) { - parser3.pushKey(key); - if (options2?.BY) { - parser3.push("BY", options2.BY); - } - if (options2?.LIMIT) { - parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); - } - if (options2?.GET) { - if (Array.isArray(options2.GET)) { - for (const pattern of options2.GET) { - parser3.push("GET", pattern); - } - } else { - parser3.push("GET", options2.GET); - } - } - if (options2?.DIRECTION) { - parser3.push(options2.DIRECTION); - } - if (options2?.ALPHA) { - parser3.push("ALPHA"); - } - } - exports2.parseSortArguments = parseSortArguments; + var generic_transformers_1 = require_generic_transformers(); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the SORT command - * - * @param parser - The command parser - * @param key - The key to sort (list, set, or sorted set) - * @param options - Sort options - * @see https://redis.io/commands/sort/ + * Returns the union of multiple sorted sets. + * @param parser - The Redis command parser. + * @param keys - Keys of the sorted sets to combine. + * @param options - Optional parameters for the union operation. */ - parseCommand(parser3, key, options2) { - parser3.push("SORT"); - parseSortArguments(parser3, key, options2); + parseCommand(parser3, keys, options2) { + parser3.push("ZUNION"); + (0, generic_transformers_1.parseZKeysArguments)(parser3, keys); + if (options2?.AGGREGATE) { + parser3.push("AGGREGATE", options2.AGGREGATE); + } }, transformReply: void 0 }; } }); -var require_SORT_RO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SORT_RO.js"(exports2) { +var require_ZUNION_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZUNION_WITHSCORES.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var SORT_1 = __importStar(require_SORT()); + var generic_transformers_1 = require_generic_transformers(); + var ZUNION_1 = __importDefault(require_ZUNION()); exports2.default = { - IS_READ_ONLY: true, + IS_READ_ONLY: ZUNION_1.default.IS_READ_ONLY, /** - * Read-only variant of SORT that sorts the elements in a list, set or sorted set. - * @param args - Same parameters as the SORT command. + * Returns the union of multiple sorted sets with their scores. + * @param args - Same parameters as the ZUNION command. */ parseCommand(...args) { const parser3 = args[0]; - parser3.push("SORT_RO"); - (0, SORT_1.parseSortArguments)(...args); + ZUNION_1.default.parseCommand(...args); + parser3.push("WITHSCORES"); }, - transformReply: SORT_1.default.transformReply + transformReply: generic_transformers_1.transformSortedSetReply }; } }); -var require_SORT_STORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SORT_STORE.js"(exports2) { +var require_ZUNIONSTORE = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZUNIONSTORE.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var SORT_1 = __importDefault(require_SORT()); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { IS_READ_ONLY: false, /** - * Sorts the elements in a list, set or sorted set and stores the result in a new list. + * Stores the union of multiple sorted sets in a new sorted set. * @param parser - The Redis command parser. - * @param source - Key of the source list, set or sorted set. * @param destination - Destination key where the result will be stored. - * @param options - Optional sorting parameters. + * @param keys - Keys of the sorted sets to combine. + * @param options - Optional parameters for the union operation. */ - parseCommand(parser3, source, destination, options2) { - SORT_1.default.parseCommand(parser3, source, options2); - parser3.push("STORE", destination); + parseCommand(parser3, destination, keys, options2) { + parser3.push("ZUNIONSTORE"); + parser3.pushKey(destination); + (0, generic_transformers_1.parseZKeysArguments)(parser3, keys); + if (options2?.AGGREGATE) { + parser3.push("AGGREGATE", options2.AGGREGATE); + } }, transformReply: void 0 }; } }); -var require_SPOP_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SPOP_COUNT.js"(exports2) { +var require_VADD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VADD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - IS_READ_ONLY: false, /** - * Constructs the SPOP command to remove and return multiple random members from a set + * Add a new element into the vector set specified by key * * @param parser - The command parser - * @param key - The key of the set to pop from - * @param count - The number of members to pop - * @see https://redis.io/commands/spop/ + * @param key - The name of the key that will hold the vector set data + * @param vector - The vector data as array of numbers + * @param element - The name of the element being added to the vector set + * @param options - Optional parameters for vector addition + * @see https://redis.io/commands/vadd/ */ - parseCommand(parser3, key, count) { - parser3.push("SPOP"); + parseCommand(parser3, key, vector, element, options2) { + parser3.push("VADD"); parser3.pushKey(key); - parser3.push(count.toString()); + if (options2?.REDUCE !== void 0) { + parser3.push("REDUCE", options2.REDUCE.toString()); + } + parser3.push("VALUES", vector.length.toString()); + for (const value of vector) { + parser3.push((0, generic_transformers_1.transformDoubleArgument)(value)); + } + parser3.push(element); + if (options2?.CAS) { + parser3.push("CAS"); + } + options2?.QUANT && parser3.push(options2.QUANT); + if (options2?.EF !== void 0) { + parser3.push("EF", options2.EF.toString()); + } + if (options2?.SETATTR) { + parser3.push("SETATTR", JSON.stringify(options2.SETATTR)); + } + if (options2?.M !== void 0) { + parser3.push("M", options2.M.toString()); + } }, - transformReply: void 0 + transformReply: generic_transformers_1.transformBooleanReply }; } }); -var require_SPOP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SPOP.js"(exports2) { +var require_VCARD = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VCARD.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Constructs the SPOP command to remove and return a random member from a set + * Retrieve the number of elements in a vector set * * @param parser - The command parser - * @param key - The key of the set to pop from - * @see https://redis.io/commands/spop/ + * @param key - The key of the vector set + * @see https://redis.io/commands/vcard/ */ parseCommand(parser3, key) { - parser3.push("SPOP"); + parser3.push("VCARD"); parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_SPUBLISH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SPUBLISH.js"(exports2) { +var require_VDIM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VDIM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the SPUBLISH command to post a message to a Sharded Pub/Sub channel + * Retrieve the dimension of the vectors in a vector set * * @param parser - The command parser - * @param channel - The channel to publish to - * @param message - The message to publish - * @see https://redis.io/commands/spublish/ + * @param key - The key of the vector set + * @see https://redis.io/commands/vdim/ */ - parseCommand(parser3, channel, message) { - parser3.push("SPUBLISH"); - parser3.pushKey(channel); - parser3.push(message); + parseCommand(parser3, key) { + parser3.push("VDIM"); + parser3.pushKey(key); }, transformReply: void 0 }; } }); -var require_SRANDMEMBER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SRANDMEMBER.js"(exports2) { +var require_VEMB = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VEMB.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the SRANDMEMBER command to get a random member from a set + * Retrieve the approximate vector associated with a vector set element * * @param parser - The command parser - * @param key - The key of the set to get random member from - * @see https://redis.io/commands/srandmember/ + * @param key - The key of the vector set + * @param element - The name of the element to retrieve the vector for + * @see https://redis.io/commands/vemb/ */ - parseCommand(parser3, key) { - parser3.push("SRANDMEMBER"); + parseCommand(parser3, key, element) { + parser3.push("VEMB"); parser3.pushKey(key); + parser3.push(element); }, - transformReply: void 0 + transformReply: generic_transformers_1.transformDoubleArrayReply }; } }); -var require_SRANDMEMBER_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SRANDMEMBER_COUNT.js"(exports2) { +var require_VEMB_RAW = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VEMB_RAW.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var SRANDMEMBER_1 = __importDefault(require_SRANDMEMBER()); - exports2.default = { - IS_READ_ONLY: SRANDMEMBER_1.default.IS_READ_ONLY, - /** - * Constructs the SRANDMEMBER command to get multiple random members from a set - * - * @param parser - The command parser - * @param key - The key of the set to get random members from - * @param count - The number of members to return. If negative, may return the same member multiple times - * @see https://redis.io/commands/srandmember/ - */ - parseCommand(parser3, key, count) { - SRANDMEMBER_1.default.parseCommand(parser3, key); - parser3.push(count.toString()); + var generic_transformers_1 = require_generic_transformers(); + var VEMB_1 = __importDefault(require_VEMB()); + var transformRawVembReply = { + 2: (reply) => { + return { + quantization: reply[0], + raw: reply[1], + l2Norm: generic_transformers_1.transformDoubleReply[2](reply[2]), + ...reply[3] !== void 0 && { quantizationRange: generic_transformers_1.transformDoubleReply[2](reply[3]) } + }; }, - transformReply: void 0 + 3: (reply) => { + return { + quantization: reply[0], + raw: reply[1], + l2Norm: reply[2], + quantizationRange: reply[3] + }; + } }; - } -}); -var require_SREM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SREM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Constructs the SREM command to remove one or more members from a set + * Retrieve the RAW approximate vector associated with a vector set element * * @param parser - The command parser - * @param key - The key of the set to remove members from - * @param members - One or more members to remove from the set - * @returns The number of members that were removed from the set - * @see https://redis.io/commands/srem/ + * @param key - The key of the vector set + * @param element - The name of the element to retrieve the vector for + * @see https://redis.io/commands/vemb/ */ - parseCommand(parser3, key, members) { - parser3.push("SREM"); - parser3.pushKey(key); - parser3.pushVariadic(members); + parseCommand(parser3, key, element) { + VEMB_1.default.parseCommand(parser3, key, element); + parser3.push("RAW"); }, - transformReply: void 0 + transformReply: transformRawVembReply }; } }); -var require_SSCAN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SSCAN.js"(exports2) { +var require_VGETATTR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VGETATTR.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var SCAN_1 = require_SCAN(); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the SSCAN command to incrementally iterate over elements in a set + * Retrieve the attributes of a vector set element * * @param parser - The command parser - * @param key - The key of the set to scan - * @param cursor - The cursor position to start scanning from - * @param options - Optional scanning parameters (COUNT and MATCH) - * @returns Iterator containing cursor position and matching members - * @see https://redis.io/commands/sscan/ + * @param key - The key of the vector set + * @param element - The name of the element to retrieve attributes for + * @see https://redis.io/commands/vgetattr/ */ - parseCommand(parser3, key, cursor, options2) { - parser3.push("SSCAN"); + parseCommand(parser3, key, element) { + parser3.push("VGETATTR"); parser3.pushKey(key); - (0, SCAN_1.parseScanArguments)(parser3, cursor, options2); + parser3.push(element); }, - /** - * Transforms the SSCAN reply into a cursor result object - * - * @param cursor - The next cursor position - * @param members - Array of matching set members - * @returns Object containing cursor and members array - */ - transformReply([cursor, members]) { - return { - cursor, - members - }; - } + transformReply: generic_transformers_1.transformRedisJsonNullReply }; } }); -var require_STRLEN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/STRLEN.js"(exports2) { +var require_VINFO = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VINFO.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the STRLEN command to get the length of a string value + * Retrieve metadata and internal details about a vector set, including size, dimensions, quantization type, and graph structure * * @param parser - The command parser - * @param key - The key holding the string value - * @returns The length of the string value, or 0 when key does not exist - * @see https://redis.io/commands/strlen/ + * @param key - The key of the vector set + * @see https://redis.io/commands/vinfo/ */ parseCommand(parser3, key) { - parser3.push("STRLEN"); + parser3.push("VINFO"); parser3.pushKey(key); }, - transformReply: void 0 + transformReply: { + 2: (reply) => { + const ret = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < reply.length; i2 += 2) { + ret[reply[i2].toString()] = reply[i2 + 1]; + } + return ret; + }, + 3: void 0 + } }; } }); -var require_SUNION = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SUNION.js"(exports2) { +var require_VLINKS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VLINKS.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { - CACHEABLE: true, IS_READ_ONLY: true, /** - * Constructs the SUNION command to return the members of the set resulting from the union of all the given sets + * Retrieve the neighbors of a specified element in a vector set; the connections for each layer of the HNSW graph * * @param parser - The command parser - * @param keys - One or more set keys to compute the union from - * @returns Array of all elements that are members of at least one of the given sets - * @see https://redis.io/commands/sunion/ + * @param key - The key of the vector set + * @param element - The name of the element to retrieve neighbors for + * @see https://redis.io/commands/vlinks/ */ - parseCommand(parser3, keys) { - parser3.push("SUNION"); - parser3.pushKeys(keys); + parseCommand(parser3, key, element) { + parser3.push("VLINKS"); + parser3.pushKey(key); + parser3.push(element); }, transformReply: void 0 }; } }); -var require_SUNIONSTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SUNIONSTORE.js"(exports2) { +var require_VLINKS_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VLINKS_WITHSCORES.js"(exports2) { "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the SUNIONSTORE command to store the union of multiple sets into a destination set - * - * @param parser - The command parser - * @param destination - The destination key to store the resulting set - * @param keys - One or more source set keys to compute the union from - * @returns The number of elements in the resulting set - * @see https://redis.io/commands/sunionstore/ - */ - parseCommand(parser3, destination, keys) { - parser3.push("SUNIONSTORE"); - parser3.pushKey(destination); - parser3.pushKeys(keys); - }, - transformReply: void 0 - }; - } -}); -var require_SWAPDB = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/SWAPDB.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, - /** - * Swaps the data of two Redis databases. - * @param parser - The Redis command parser. - * @param index1 - First database index. - * @param index2 - Second database index. - */ - parseCommand(parser3, index1, index2) { - parser3.push("SWAPDB", index1.toString(), index2.toString()); - }, - transformReply: void 0 - }; - } -}); -var require_TIME = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TIME.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Constructs the TIME command to return the server's current time - * - * @param parser - The command parser - * @returns Array containing the Unix timestamp in seconds and microseconds - * @see https://redis.io/commands/time/ - */ - parseCommand(parser3) { - parser3.push("TIME"); - }, - transformReply: void 0 + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - } -}); -var require_TOUCH = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TOUCH.js"(exports2) { - "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var VLINKS_1 = __importDefault(require_VLINKS()); + function transformVLinksWithScoresReply(reply) { + const layers = []; + for (const layer of reply) { + const obj = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < layer.length; i2 += 2) { + const element = layer[i2]; + const score = generic_transformers_1.transformDoubleReply[2](layer[i2 + 1]); + obj[element.toString()] = score; + } + layers.push(obj); + } + return layers; + } exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: VLINKS_1.default.IS_READ_ONLY, /** - * Constructs the TOUCH command to alter the last access time of keys - * - * @param parser - The command parser - * @param key - One or more keys to touch - * @returns The number of keys that were touched - * @see https://redis.io/commands/touch/ + * Get the connections for each layer of the HNSW graph with similarity scores + * @param args - Same parameters as the VLINKS command + * @see https://redis.io/commands/vlinks/ */ - parseCommand(parser3, key) { - parser3.push("TOUCH"); - parser3.pushKeys(key); + parseCommand(...args) { + const parser3 = args[0]; + VLINKS_1.default.parseCommand(...args); + parser3.push("WITHSCORES"); }, - transformReply: void 0 + transformReply: { + 2: transformVLinksWithScoresReply, + 3: void 0 + } }; } }); -var require_TTL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TTL.js"(exports2) { +var require_VRANDMEMBER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VRANDMEMBER.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.default = { IS_READ_ONLY: true, /** - * Constructs the TTL command to get the remaining time to live of a key + * Retrieve random elements of a vector set * * @param parser - The command parser - * @param key - Key to check - * @returns Time to live in seconds, -2 if key does not exist, -1 if has no timeout - * @see https://redis.io/commands/ttl/ + * @param key - The key of the vector set + * @param count - Optional number of elements to return + * @see https://redis.io/commands/vrandmember/ */ - parseCommand(parser3, key) { - parser3.push("TTL"); + parseCommand(parser3, key, count) { + parser3.push("VRANDMEMBER"); parser3.pushKey(key); + if (count !== void 0) { + parser3.push(count.toString()); + } }, transformReply: void 0 }; } }); -var require_TYPE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/TYPE.js"(exports2) { +var require_VREM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VREM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, /** - * Constructs the TYPE command to determine the data type stored at key + * Remove an element from a vector set * * @param parser - The command parser - * @param key - Key to check - * @returns String reply: "none", "string", "list", "set", "zset", "hash", "stream" - * @see https://redis.io/commands/type/ + * @param key - The key of the vector set + * @param element - The name of the element to remove from the vector set + * @see https://redis.io/commands/vrem/ */ - parseCommand(parser3, key) { - parser3.push("TYPE"); + parseCommand(parser3, key, element) { + parser3.push("VREM"); parser3.pushKey(key); + parser3.push(element); }, - transformReply: void 0 - }; - } -}); -var require_UNLINK = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/UNLINK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the UNLINK command to asynchronously delete one or more keys - * - * @param parser - The command parser - * @param keys - One or more keys to unlink - * @returns The number of keys that were unlinked - * @see https://redis.io/commands/unlink/ - */ - parseCommand(parser3, keys) { - parser3.push("UNLINK"); - parser3.pushKeys(keys); - }, - transformReply: void 0 - }; - } -}); -var require_WAIT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/WAIT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Constructs the WAIT command to synchronize with replicas - * - * @param parser - The command parser - * @param numberOfReplicas - Number of replicas that must acknowledge the write - * @param timeout - Maximum time to wait in milliseconds - * @returns The number of replicas that acknowledged the write - * @see https://redis.io/commands/wait/ - */ - parseCommand(parser3, numberOfReplicas, timeout) { - parser3.push("WAIT", numberOfReplicas.toString(), timeout.toString()); - }, - transformReply: void 0 + transformReply: generic_transformers_1.transformBooleanReply }; } }); -var require_XACK = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XACK.js"(exports2) { +var require_VSETATTR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VSETATTR.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - IS_READ_ONLY: false, /** - * Constructs the XACK command to acknowledge the processing of stream messages in a consumer group + * Set or replace attributes on a vector set element * * @param parser - The command parser - * @param key - The stream key - * @param group - The consumer group name - * @param id - One or more message IDs to acknowledge - * @returns The number of messages successfully acknowledged - * @see https://redis.io/commands/xack/ + * @param key - The key of the vector set + * @param element - The name of the element to set attributes for + * @param attributes - The attributes to set (as JSON string or object) + * @see https://redis.io/commands/vsetattr/ */ - parseCommand(parser3, key, group, id) { - parser3.push("XACK"); + parseCommand(parser3, key, element, attributes) { + parser3.push("VSETATTR"); parser3.pushKey(key); - parser3.push(group); - parser3.pushVariadic(id); + parser3.push(element); + if (typeof attributes === "object" && attributes !== null) { + parser3.push(JSON.stringify(attributes)); + } else { + parser3.push(attributes); + } }, - transformReply: void 0 + transformReply: generic_transformers_1.transformBooleanReply }; } }); -var require_XACKDEL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XACKDEL.js"(exports2) { +var require_VSIM = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VSIM.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); exports2.default = { - IS_READ_ONLY: false, + IS_READ_ONLY: true, /** - * Constructs the XACKDEL command to acknowledge and delete one or multiple messages for a stream consumer group + * Retrieve elements similar to a given vector or element with optional filtering * * @param parser - The command parser - * @param key - The stream key - * @param group - The consumer group name - * @param id - One or more message IDs to acknowledge and delete - * @param policy - Policy to apply when deleting entries (optional, defaults to KEEPREF) - * @returns Array of integers: -1 (not found), 1 (acknowledged and deleted), 2 (acknowledged with dangling refs) - * @see https://redis.io/commands/xackdel/ + * @param key - The key of the vector set + * @param query - The query vector (array of numbers) or element name (string) + * @param options - Optional parameters for similarity search + * @see https://redis.io/commands/vsim/ */ - parseCommand(parser3, key, group, id, policy) { - parser3.push("XACKDEL"); + parseCommand(parser3, key, query, options2) { + parser3.push("VSIM"); parser3.pushKey(key); - parser3.push(group); - if (policy) { - parser3.push(policy); + if (Array.isArray(query)) { + parser3.push("VALUES", query.length.toString()); + for (const value of query) { + parser3.push((0, generic_transformers_1.transformDoubleArgument)(value)); + } + } else { + parser3.push("ELE", query); } - parser3.push("IDS"); - parser3.pushVariadicWithLength(id); - }, - transformReply: void 0 - }; - } -}); -var require_XADD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseXAddArguments = void 0; - function parseXAddArguments(optional2, parser3, key, id, message, options2) { - parser3.push("XADD"); - parser3.pushKey(key); - if (optional2) { - parser3.push(optional2); - } - if (options2?.TRIM) { - if (options2.TRIM.strategy) { - parser3.push(options2.TRIM.strategy); + if (options2?.COUNT !== void 0) { + parser3.push("COUNT", options2.COUNT.toString()); } - if (options2.TRIM.strategyModifier) { - parser3.push(options2.TRIM.strategyModifier); + if (options2?.EPSILON !== void 0) { + parser3.push("EPSILON", options2.EPSILON.toString()); } - parser3.push(options2.TRIM.threshold.toString()); - if (options2.TRIM.limit) { - parser3.push("LIMIT", options2.TRIM.limit.toString()); + if (options2?.EF !== void 0) { + parser3.push("EF", options2.EF.toString()); } - if (options2.TRIM.policy) { - parser3.push(options2.TRIM.policy); + if (options2?.FILTER) { + parser3.push("FILTER", options2.FILTER); } - } - parser3.push(id); - for (const [key2, value] of Object.entries(message)) { - parser3.push(key2, value); - } - } - exports2.parseXAddArguments = parseXAddArguments; - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XADD command to append a new entry to a stream - * - * @param parser - The command parser - * @param key - The stream key - * @param id - Message ID (* for auto-generation) - * @param message - Key-value pairs representing the message fields - * @param options - Additional options for stream trimming - * @returns The ID of the added entry - * @see https://redis.io/commands/xadd/ - */ - parseCommand(...args) { - return parseXAddArguments(void 0, ...args); - }, - transformReply: void 0 - }; - } -}); -var require_XADD_NOMKSTREAM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XADD_NOMKSTREAM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var XADD_1 = require_XADD(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XADD command with NOMKSTREAM option to append a new entry to an existing stream - * - * @param args - Arguments tuple containing parser, key, id, message, and options - * @returns The ID of the added entry, or null if the stream doesn't exist - * @see https://redis.io/commands/xadd/ - */ - parseCommand(...args) { - return (0, XADD_1.parseXAddArguments)("NOMKSTREAM", ...args); - }, - transformReply: void 0 - }; - } -}); -var require_XAUTOCLAIM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XAUTOCLAIM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XAUTOCLAIM command to automatically claim pending messages in a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - The consumer group name - * @param consumer - The consumer name that will claim the messages - * @param minIdleTime - Minimum idle time in milliseconds for a message to be claimed - * @param start - Message ID to start scanning from - * @param options - Additional options for the claim operation - * @returns Object containing nextId, claimed messages, and list of deleted message IDs - * @see https://redis.io/commands/xautoclaim/ - */ - parseCommand(parser3, key, group, consumer, minIdleTime, start, options2) { - parser3.push("XAUTOCLAIM"); - parser3.pushKey(key); - parser3.push(group, consumer, minIdleTime.toString(), start); - if (options2?.COUNT) { - parser3.push("COUNT", options2.COUNT.toString()); + if (options2?.["FILTER-EF"] !== void 0) { + parser3.push("FILTER-EF", options2["FILTER-EF"].toString()); + } + if (options2?.TRUTH) { + parser3.push("TRUTH"); + } + if (options2?.NOTHREAD) { + parser3.push("NOTHREAD"); } }, - /** - * Transforms the raw XAUTOCLAIM reply into a structured object - * - * @param reply - Raw reply from Redis - * @param preserve - Preserve options (unused) - * @param typeMapping - Type mapping for message fields - * @returns Structured object containing nextId, messages, and deletedMessages - */ - transformReply(reply, preserve, typeMapping) { - return { - nextId: reply[0], - messages: reply[1].map(generic_transformers_1.transformStreamMessageNullReply.bind(void 0, typeMapping)), - deletedMessages: reply[2] - }; - } + transformReply: void 0 }; } }); -var require_XAUTOCLAIM_JUSTID = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XAUTOCLAIM_JUSTID.js"(exports2) { +var require_VSIM_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VSIM_WITHSCORES.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var XAUTOCLAIM_1 = __importDefault(require_XAUTOCLAIM()); + var generic_transformers_1 = require_generic_transformers(); + var VSIM_1 = __importDefault(require_VSIM()); exports2.default = { - IS_READ_ONLY: XAUTOCLAIM_1.default.IS_READ_ONLY, + IS_READ_ONLY: VSIM_1.default.IS_READ_ONLY, /** - * Constructs the XAUTOCLAIM command with JUSTID option to get only message IDs - * - * @param args - Same parameters as XAUTOCLAIM command - * @returns Object containing nextId and arrays of claimed and deleted message IDs - * @see https://redis.io/commands/xautoclaim/ + * Retrieve elements similar to a given vector or element with similarity scores + * @param args - Same parameters as the VSIM command + * @see https://redis.io/commands/vsim/ */ parseCommand(...args) { const parser3 = args[0]; - XAUTOCLAIM_1.default.parseCommand(...args); - parser3.push("JUSTID"); + VSIM_1.default.parseCommand(...args); + parser3.push("WITHSCORES"); }, - /** - * Transforms the raw XAUTOCLAIM JUSTID reply into a structured object - * - * @param reply - Raw reply from Redis - * @returns Structured object containing nextId, message IDs, and deleted message IDs - */ - transformReply(reply) { - return { - nextId: reply[0], - messages: reply[1], - deletedMessages: reply[2] - }; + transformReply: { + 2: (reply) => { + const inferred = reply; + const members = {}; + for (let i2 = 0; i2 < inferred.length; i2 += 2) { + members[inferred[i2].toString()] = generic_transformers_1.transformDoubleReply[2](inferred[i2 + 1]); + } + return members; + }, + 3: void 0 } }; } }); -var require_XCLAIM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XCLAIM.js"(exports2) { +var require_commands = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/index.js"(exports2) { "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XCLAIM command to claim pending messages in a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - The consumer group name - * @param consumer - The consumer name that will claim the messages - * @param minIdleTime - Minimum idle time in milliseconds for a message to be claimed - * @param id - One or more message IDs to claim - * @param options - Additional options for the claim operation - * @returns Array of claimed messages - * @see https://redis.io/commands/xclaim/ - */ - parseCommand(parser3, key, group, consumer, minIdleTime, id, options2) { - parser3.push("XCLAIM"); - parser3.pushKey(key); - parser3.push(group, consumer, minIdleTime.toString()); - parser3.pushVariadic(id); - if (options2?.IDLE !== void 0) { - parser3.push("IDLE", options2.IDLE.toString()); - } - if (options2?.TIME !== void 0) { - parser3.push("TIME", (options2.TIME instanceof Date ? options2.TIME.getTime() : options2.TIME).toString()); - } - if (options2?.RETRYCOUNT !== void 0) { - parser3.push("RETRYCOUNT", options2.RETRYCOUNT.toString()); - } - if (options2?.FORCE) { - parser3.push("FORCE"); - } - if (options2?.LASTID !== void 0) { - parser3.push("LASTID", options2.LASTID); - } - }, - /** - * Transforms the raw XCLAIM reply into an array of messages - * - * @param reply - Raw reply from Redis - * @param preserve - Preserve options (unused) - * @param typeMapping - Type mapping for message fields - * @returns Array of claimed messages with their fields - */ - transformReply(reply, preserve, typeMapping) { - return reply.map(generic_transformers_1.transformStreamMessageNullReply.bind(void 0, typeMapping)); + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } + __setModuleDefault(result, mod); + return result; }; - } -}); -var require_XCLAIM_JUSTID = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XCLAIM_JUSTID.js"(exports2) { - "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.REDIS_FLUSH_MODES = exports2.COMMAND_LIST_FILTER_BY = exports2.CLUSTER_SLOT_STATES = exports2.FAILOVER_MODES = exports2.CLIENT_KILL_FILTERS = void 0; + var ACL_CAT_1 = __importDefault(require_ACL_CAT()); + var ACL_DELUSER_1 = __importDefault(require_ACL_DELUSER()); + var ACL_DRYRUN_1 = __importDefault(require_ACL_DRYRUN()); + var ACL_GENPASS_1 = __importDefault(require_ACL_GENPASS()); + var ACL_GETUSER_1 = __importDefault(require_ACL_GETUSER()); + var ACL_LIST_1 = __importDefault(require_ACL_LIST()); + var ACL_LOAD_1 = __importDefault(require_ACL_LOAD()); + var ACL_LOG_RESET_1 = __importDefault(require_ACL_LOG_RESET()); + var ACL_LOG_1 = __importDefault(require_ACL_LOG()); + var ACL_SAVE_1 = __importDefault(require_ACL_SAVE()); + var ACL_SETUSER_1 = __importDefault(require_ACL_SETUSER()); + var ACL_USERS_1 = __importDefault(require_ACL_USERS()); + var ACL_WHOAMI_1 = __importDefault(require_ACL_WHOAMI()); + var APPEND_1 = __importDefault(require_APPEND()); + var ASKING_1 = __importDefault(require_ASKING()); + var AUTH_1 = __importDefault(require_AUTH()); + var BGREWRITEAOF_1 = __importDefault(require_BGREWRITEAOF()); + var BGSAVE_1 = __importDefault(require_BGSAVE()); + var BITCOUNT_1 = __importDefault(require_BITCOUNT()); + var BITFIELD_RO_1 = __importDefault(require_BITFIELD_RO()); + var BITFIELD_1 = __importDefault(require_BITFIELD()); + var BITOP_1 = __importDefault(require_BITOP()); + var BITPOS_1 = __importDefault(require_BITPOS()); + var BLMOVE_1 = __importDefault(require_BLMOVE()); + var BLMPOP_1 = __importDefault(require_BLMPOP()); + var BLPOP_1 = __importDefault(require_BLPOP()); + var BRPOP_1 = __importDefault(require_BRPOP()); + var BRPOPLPUSH_1 = __importDefault(require_BRPOPLPUSH()); + var BZMPOP_1 = __importDefault(require_BZMPOP()); + var BZPOPMAX_1 = __importDefault(require_BZPOPMAX()); + var BZPOPMIN_1 = __importDefault(require_BZPOPMIN()); + var CLIENT_CACHING_1 = __importDefault(require_CLIENT_CACHING()); + var CLIENT_GETNAME_1 = __importDefault(require_CLIENT_GETNAME()); + var CLIENT_GETREDIR_1 = __importDefault(require_CLIENT_GETREDIR()); + var CLIENT_ID_1 = __importDefault(require_CLIENT_ID()); + var CLIENT_INFO_1 = __importDefault(require_CLIENT_INFO()); + var CLIENT_KILL_1 = __importStar(require_CLIENT_KILL()); + Object.defineProperty(exports2, "CLIENT_KILL_FILTERS", { enumerable: true, get: function() { + return CLIENT_KILL_1.CLIENT_KILL_FILTERS; + } }); + var CLIENT_LIST_1 = __importDefault(require_CLIENT_LIST()); + var CLIENT_NO_EVICT_1 = __importDefault(require_CLIENT_NO_EVICT()); + var CLIENT_NO_TOUCH_1 = __importDefault(require_CLIENT_NO_TOUCH()); + var CLIENT_PAUSE_1 = __importDefault(require_CLIENT_PAUSE()); + var CLIENT_SETNAME_1 = __importDefault(require_CLIENT_SETNAME()); + var CLIENT_TRACKING_1 = __importDefault(require_CLIENT_TRACKING()); + var CLIENT_TRACKINGINFO_1 = __importDefault(require_CLIENT_TRACKINGINFO()); + var CLIENT_UNPAUSE_1 = __importDefault(require_CLIENT_UNPAUSE()); + var CLUSTER_ADDSLOTS_1 = __importDefault(require_CLUSTER_ADDSLOTS()); + var CLUSTER_ADDSLOTSRANGE_1 = __importDefault(require_CLUSTER_ADDSLOTSRANGE()); + var CLUSTER_BUMPEPOCH_1 = __importDefault(require_CLUSTER_BUMPEPOCH()); + var CLUSTER_COUNT_FAILURE_REPORTS_1 = __importDefault(require_CLUSTER_COUNT_FAILURE_REPORTS()); + var CLUSTER_COUNTKEYSINSLOT_1 = __importDefault(require_CLUSTER_COUNTKEYSINSLOT()); + var CLUSTER_DELSLOTS_1 = __importDefault(require_CLUSTER_DELSLOTS()); + var CLUSTER_DELSLOTSRANGE_1 = __importDefault(require_CLUSTER_DELSLOTSRANGE()); + var CLUSTER_FAILOVER_1 = __importStar(require_CLUSTER_FAILOVER()); + Object.defineProperty(exports2, "FAILOVER_MODES", { enumerable: true, get: function() { + return CLUSTER_FAILOVER_1.FAILOVER_MODES; + } }); + var CLUSTER_FLUSHSLOTS_1 = __importDefault(require_CLUSTER_FLUSHSLOTS()); + var CLUSTER_FORGET_1 = __importDefault(require_CLUSTER_FORGET()); + var CLUSTER_GETKEYSINSLOT_1 = __importDefault(require_CLUSTER_GETKEYSINSLOT()); + var CLUSTER_INFO_1 = __importDefault(require_CLUSTER_INFO()); + var CLUSTER_KEYSLOT_1 = __importDefault(require_CLUSTER_KEYSLOT()); + var CLUSTER_LINKS_1 = __importDefault(require_CLUSTER_LINKS()); + var CLUSTER_MEET_1 = __importDefault(require_CLUSTER_MEET()); + var CLUSTER_MYID_1 = __importDefault(require_CLUSTER_MYID()); + var CLUSTER_MYSHARDID_1 = __importDefault(require_CLUSTER_MYSHARDID()); + var CLUSTER_NODES_1 = __importDefault(require_CLUSTER_NODES()); + var CLUSTER_REPLICAS_1 = __importDefault(require_CLUSTER_REPLICAS()); + var CLUSTER_REPLICATE_1 = __importDefault(require_CLUSTER_REPLICATE()); + var CLUSTER_RESET_1 = __importDefault(require_CLUSTER_RESET()); + var CLUSTER_SAVECONFIG_1 = __importDefault(require_CLUSTER_SAVECONFIG()); + var CLUSTER_SET_CONFIG_EPOCH_1 = __importDefault(require_CLUSTER_SET_CONFIG_EPOCH()); + var CLUSTER_SETSLOT_1 = __importStar(require_CLUSTER_SETSLOT()); + Object.defineProperty(exports2, "CLUSTER_SLOT_STATES", { enumerable: true, get: function() { + return CLUSTER_SETSLOT_1.CLUSTER_SLOT_STATES; + } }); + var CLUSTER_SLOTS_1 = __importDefault(require_CLUSTER_SLOTS()); + var COMMAND_COUNT_1 = __importDefault(require_COMMAND_COUNT()); + var COMMAND_GETKEYS_1 = __importDefault(require_COMMAND_GETKEYS()); + var COMMAND_GETKEYSANDFLAGS_1 = __importDefault(require_COMMAND_GETKEYSANDFLAGS()); + var COMMAND_INFO_1 = __importDefault(require_COMMAND_INFO()); + var COMMAND_LIST_1 = __importStar(require_COMMAND_LIST()); + Object.defineProperty(exports2, "COMMAND_LIST_FILTER_BY", { enumerable: true, get: function() { + return COMMAND_LIST_1.COMMAND_LIST_FILTER_BY; + } }); + var COMMAND_1 = __importDefault(require_COMMAND()); + var CONFIG_GET_1 = __importDefault(require_CONFIG_GET()); + var CONFIG_RESETSTAT_1 = __importDefault(require_CONFIG_RESETSTAT()); + var CONFIG_REWRITE_1 = __importDefault(require_CONFIG_REWRITE()); + var CONFIG_SET_1 = __importDefault(require_CONFIG_SET()); + var COPY_1 = __importDefault(require_COPY()); + var DBSIZE_1 = __importDefault(require_DBSIZE()); + var DECR_1 = __importDefault(require_DECR()); + var DECRBY_1 = __importDefault(require_DECRBY()); + var DEL_1 = __importDefault(require_DEL()); + var DUMP_1 = __importDefault(require_DUMP()); + var ECHO_1 = __importDefault(require_ECHO()); + var EVAL_RO_1 = __importDefault(require_EVAL_RO()); + var EVAL_1 = __importDefault(require_EVAL()); + var EVALSHA_RO_1 = __importDefault(require_EVALSHA_RO()); + var EVALSHA_1 = __importDefault(require_EVALSHA()); + var GEOADD_1 = __importDefault(require_GEOADD()); + var GEODIST_1 = __importDefault(require_GEODIST()); + var GEOHASH_1 = __importDefault(require_GEOHASH()); + var GEOPOS_1 = __importDefault(require_GEOPOS()); + var GEORADIUS_RO_WITH_1 = __importDefault(require_GEORADIUS_RO_WITH()); + var GEORADIUS_RO_1 = __importDefault(require_GEORADIUS_RO()); + var GEORADIUS_STORE_1 = __importDefault(require_GEORADIUS_STORE()); + var GEORADIUS_WITH_1 = __importDefault(require_GEORADIUS_WITH()); + var GEORADIUS_1 = __importDefault(require_GEORADIUS()); + var GEORADIUSBYMEMBER_RO_WITH_1 = __importDefault(require_GEORADIUSBYMEMBER_RO_WITH()); + var GEORADIUSBYMEMBER_RO_1 = __importDefault(require_GEORADIUSBYMEMBER_RO()); + var GEORADIUSBYMEMBER_STORE_1 = __importDefault(require_GEORADIUSBYMEMBER_STORE()); + var GEORADIUSBYMEMBER_WITH_1 = __importDefault(require_GEORADIUSBYMEMBER_WITH()); + var GEORADIUSBYMEMBER_1 = __importDefault(require_GEORADIUSBYMEMBER()); + var GEOSEARCH_WITH_1 = __importDefault(require_GEOSEARCH_WITH()); + var GEOSEARCH_1 = __importDefault(require_GEOSEARCH()); + var GEOSEARCHSTORE_1 = __importDefault(require_GEOSEARCHSTORE()); + var GET_1 = __importDefault(require_GET()); + var GETBIT_1 = __importDefault(require_GETBIT()); + var GETDEL_1 = __importDefault(require_GETDEL()); + var GETEX_1 = __importDefault(require_GETEX()); + var GETRANGE_1 = __importDefault(require_GETRANGE()); + var GETSET_1 = __importDefault(require_GETSET()); + var EXISTS_1 = __importDefault(require_EXISTS()); + var EXPIRE_1 = __importDefault(require_EXPIRE()); + var EXPIREAT_1 = __importDefault(require_EXPIREAT()); + var EXPIRETIME_1 = __importDefault(require_EXPIRETIME()); + var FLUSHALL_1 = __importStar(require_FLUSHALL()); + Object.defineProperty(exports2, "REDIS_FLUSH_MODES", { enumerable: true, get: function() { + return FLUSHALL_1.REDIS_FLUSH_MODES; + } }); + var FLUSHDB_1 = __importDefault(require_FLUSHDB()); + var FCALL_1 = __importDefault(require_FCALL()); + var FCALL_RO_1 = __importDefault(require_FCALL_RO()); + var FUNCTION_DELETE_1 = __importDefault(require_FUNCTION_DELETE()); + var FUNCTION_DUMP_1 = __importDefault(require_FUNCTION_DUMP()); + var FUNCTION_FLUSH_1 = __importDefault(require_FUNCTION_FLUSH()); + var FUNCTION_KILL_1 = __importDefault(require_FUNCTION_KILL()); + var FUNCTION_LIST_WITHCODE_1 = __importDefault(require_FUNCTION_LIST_WITHCODE()); + var FUNCTION_LIST_1 = __importDefault(require_FUNCTION_LIST()); + var FUNCTION_LOAD_1 = __importDefault(require_FUNCTION_LOAD()); + var FUNCTION_RESTORE_1 = __importDefault(require_FUNCTION_RESTORE()); + var FUNCTION_STATS_1 = __importDefault(require_FUNCTION_STATS()); + var HDEL_1 = __importDefault(require_HDEL()); + var HELLO_1 = __importDefault(require_HELLO()); + var HEXISTS_1 = __importDefault(require_HEXISTS()); + var HEXPIRE_1 = __importDefault(require_HEXPIRE()); + var HEXPIREAT_1 = __importDefault(require_HEXPIREAT()); + var HEXPIRETIME_1 = __importDefault(require_HEXPIRETIME()); + var HGET_1 = __importDefault(require_HGET()); + var HGETALL_1 = __importDefault(require_HGETALL()); + var HGETDEL_1 = __importDefault(require_HGETDEL()); + var HGETEX_1 = __importDefault(require_HGETEX()); + var HINCRBY_1 = __importDefault(require_HINCRBY()); + var HINCRBYFLOAT_1 = __importDefault(require_HINCRBYFLOAT()); + var HKEYS_1 = __importDefault(require_HKEYS()); + var HLEN_1 = __importDefault(require_HLEN()); + var HMGET_1 = __importDefault(require_HMGET()); + var HPERSIST_1 = __importDefault(require_HPERSIST()); + var HPEXPIRE_1 = __importDefault(require_HPEXPIRE()); + var HPEXPIREAT_1 = __importDefault(require_HPEXPIREAT()); + var HPEXPIRETIME_1 = __importDefault(require_HPEXPIRETIME()); + var HPTTL_1 = __importDefault(require_HPTTL()); + var HRANDFIELD_COUNT_WITHVALUES_1 = __importDefault(require_HRANDFIELD_COUNT_WITHVALUES()); + var HRANDFIELD_COUNT_1 = __importDefault(require_HRANDFIELD_COUNT()); + var HRANDFIELD_1 = __importDefault(require_HRANDFIELD()); + var HSCAN_1 = __importDefault(require_HSCAN()); + var HSCAN_NOVALUES_1 = __importDefault(require_HSCAN_NOVALUES()); + var HSET_1 = __importDefault(require_HSET()); + var HSETEX_1 = __importDefault(require_HSETEX()); + var HSETNX_1 = __importDefault(require_HSETNX()); + var HSTRLEN_1 = __importDefault(require_HSTRLEN()); + var HTTL_1 = __importDefault(require_HTTL()); + var HVALS_1 = __importDefault(require_HVALS()); + var INCR_1 = __importDefault(require_INCR()); + var INCRBY_1 = __importDefault(require_INCRBY()); + var INCRBYFLOAT_1 = __importDefault(require_INCRBYFLOAT()); + var INFO_1 = __importDefault(require_INFO()); + var KEYS_1 = __importDefault(require_KEYS()); + var LASTSAVE_1 = __importDefault(require_LASTSAVE()); + var LATENCY_DOCTOR_1 = __importDefault(require_LATENCY_DOCTOR()); + var LATENCY_GRAPH_1 = __importDefault(require_LATENCY_GRAPH()); + var LATENCY_HISTORY_1 = __importDefault(require_LATENCY_HISTORY()); + var LATENCY_LATEST_1 = __importDefault(require_LATENCY_LATEST()); + var LATENCY_RESET_1 = __importDefault(require_LATENCY_RESET()); + var LCS_IDX_WITHMATCHLEN_1 = __importDefault(require_LCS_IDX_WITHMATCHLEN()); + var LCS_IDX_1 = __importDefault(require_LCS_IDX()); + var LCS_LEN_1 = __importDefault(require_LCS_LEN()); + var LCS_1 = __importDefault(require_LCS()); + var LINDEX_1 = __importDefault(require_LINDEX()); + var LINSERT_1 = __importDefault(require_LINSERT()); + var LLEN_1 = __importDefault(require_LLEN()); + var LMOVE_1 = __importDefault(require_LMOVE()); + var LMPOP_1 = __importDefault(require_LMPOP()); + var LOLWUT_1 = __importDefault(require_LOLWUT()); + var LPOP_COUNT_1 = __importDefault(require_LPOP_COUNT()); + var LPOP_1 = __importDefault(require_LPOP()); + var LPOS_COUNT_1 = __importDefault(require_LPOS_COUNT()); + var LPOS_1 = __importDefault(require_LPOS()); + var LPUSH_1 = __importDefault(require_LPUSH()); + var LPUSHX_1 = __importDefault(require_LPUSHX()); + var LRANGE_1 = __importDefault(require_LRANGE()); + var LREM_1 = __importDefault(require_LREM()); + var LSET_1 = __importDefault(require_LSET()); + var LTRIM_1 = __importDefault(require_LTRIM()); + var MEMORY_DOCTOR_1 = __importDefault(require_MEMORY_DOCTOR()); + var MEMORY_MALLOC_STATS_1 = __importDefault(require_MEMORY_MALLOC_STATS()); + var MEMORY_PURGE_1 = __importDefault(require_MEMORY_PURGE()); + var MEMORY_STATS_1 = __importDefault(require_MEMORY_STATS()); + var MEMORY_USAGE_1 = __importDefault(require_MEMORY_USAGE()); + var MGET_1 = __importDefault(require_MGET()); + var MIGRATE_1 = __importDefault(require_MIGRATE()); + var MODULE_LIST_1 = __importDefault(require_MODULE_LIST()); + var MODULE_LOAD_1 = __importDefault(require_MODULE_LOAD()); + var MODULE_UNLOAD_1 = __importDefault(require_MODULE_UNLOAD()); + var MOVE_1 = __importDefault(require_MOVE()); + var MSET_1 = __importDefault(require_MSET()); + var MSETNX_1 = __importDefault(require_MSETNX()); + var OBJECT_ENCODING_1 = __importDefault(require_OBJECT_ENCODING()); + var OBJECT_FREQ_1 = __importDefault(require_OBJECT_FREQ()); + var OBJECT_IDLETIME_1 = __importDefault(require_OBJECT_IDLETIME()); + var OBJECT_REFCOUNT_1 = __importDefault(require_OBJECT_REFCOUNT()); + var PERSIST_1 = __importDefault(require_PERSIST()); + var PEXPIRE_1 = __importDefault(require_PEXPIRE()); + var PEXPIREAT_1 = __importDefault(require_PEXPIREAT()); + var PEXPIRETIME_1 = __importDefault(require_PEXPIRETIME()); + var PFADD_1 = __importDefault(require_PFADD()); + var PFCOUNT_1 = __importDefault(require_PFCOUNT()); + var PFMERGE_1 = __importDefault(require_PFMERGE()); + var PING_1 = __importDefault(require_PING()); + var PSETEX_1 = __importDefault(require_PSETEX()); + var PTTL_1 = __importDefault(require_PTTL()); + var PUBLISH_1 = __importDefault(require_PUBLISH()); + var PUBSUB_CHANNELS_1 = __importDefault(require_PUBSUB_CHANNELS()); + var PUBSUB_NUMPAT_1 = __importDefault(require_PUBSUB_NUMPAT()); + var PUBSUB_NUMSUB_1 = __importDefault(require_PUBSUB_NUMSUB()); + var PUBSUB_SHARDNUMSUB_1 = __importDefault(require_PUBSUB_SHARDNUMSUB()); + var PUBSUB_SHARDCHANNELS_1 = __importDefault(require_PUBSUB_SHARDCHANNELS()); + var RANDOMKEY_1 = __importDefault(require_RANDOMKEY()); + var READONLY_1 = __importDefault(require_READONLY()); + var RENAME_1 = __importDefault(require_RENAME()); + var RENAMENX_1 = __importDefault(require_RENAMENX()); + var REPLICAOF_1 = __importDefault(require_REPLICAOF()); + var RESTORE_ASKING_1 = __importDefault(require_RESTORE_ASKING()); + var RESTORE_1 = __importDefault(require_RESTORE()); + var ROLE_1 = __importDefault(require_ROLE()); + var RPOP_COUNT_1 = __importDefault(require_RPOP_COUNT()); + var RPOP_1 = __importDefault(require_RPOP()); + var RPOPLPUSH_1 = __importDefault(require_RPOPLPUSH()); + var RPUSH_1 = __importDefault(require_RPUSH()); + var RPUSHX_1 = __importDefault(require_RPUSHX()); + var SADD_1 = __importDefault(require_SADD()); + var SCAN_1 = __importDefault(require_SCAN()); + var SCARD_1 = __importDefault(require_SCARD()); + var SCRIPT_DEBUG_1 = __importDefault(require_SCRIPT_DEBUG()); + var SCRIPT_EXISTS_1 = __importDefault(require_SCRIPT_EXISTS()); + var SCRIPT_FLUSH_1 = __importDefault(require_SCRIPT_FLUSH()); + var SCRIPT_KILL_1 = __importDefault(require_SCRIPT_KILL()); + var SCRIPT_LOAD_1 = __importDefault(require_SCRIPT_LOAD()); + var SDIFF_1 = __importDefault(require_SDIFF()); + var SDIFFSTORE_1 = __importDefault(require_SDIFFSTORE()); + var SET_1 = __importDefault(require_SET()); + var SETBIT_1 = __importDefault(require_SETBIT()); + var SETEX_1 = __importDefault(require_SETEX()); + var SETNX_1 = __importDefault(require_SETNX()); + var SETRANGE_1 = __importDefault(require_SETRANGE()); + var SINTER_1 = __importDefault(require_SINTER()); + var SINTERCARD_1 = __importDefault(require_SINTERCARD()); + var SINTERSTORE_1 = __importDefault(require_SINTERSTORE()); + var SISMEMBER_1 = __importDefault(require_SISMEMBER()); + var SMEMBERS_1 = __importDefault(require_SMEMBERS()); + var SMISMEMBER_1 = __importDefault(require_SMISMEMBER()); + var SMOVE_1 = __importDefault(require_SMOVE()); + var SORT_RO_1 = __importDefault(require_SORT_RO()); + var SORT_STORE_1 = __importDefault(require_SORT_STORE()); + var SORT_1 = __importDefault(require_SORT()); + var SPOP_COUNT_1 = __importDefault(require_SPOP_COUNT()); + var SPOP_1 = __importDefault(require_SPOP()); + var SPUBLISH_1 = __importDefault(require_SPUBLISH()); + var SRANDMEMBER_COUNT_1 = __importDefault(require_SRANDMEMBER_COUNT()); + var SRANDMEMBER_1 = __importDefault(require_SRANDMEMBER()); + var SREM_1 = __importDefault(require_SREM()); + var SSCAN_1 = __importDefault(require_SSCAN()); + var STRLEN_1 = __importDefault(require_STRLEN()); + var SUNION_1 = __importDefault(require_SUNION()); + var SUNIONSTORE_1 = __importDefault(require_SUNIONSTORE()); + var SWAPDB_1 = __importDefault(require_SWAPDB()); + var TIME_1 = __importDefault(require_TIME()); + var TOUCH_1 = __importDefault(require_TOUCH()); + var TTL_1 = __importDefault(require_TTL()); + var TYPE_1 = __importDefault(require_TYPE()); + var UNLINK_1 = __importDefault(require_UNLINK()); + var WAIT_1 = __importDefault(require_WAIT()); + var XACK_1 = __importDefault(require_XACK()); + var XACKDEL_1 = __importDefault(require_XACKDEL()); + var XADD_NOMKSTREAM_1 = __importDefault(require_XADD_NOMKSTREAM()); + var XADD_1 = __importDefault(require_XADD()); + var XAUTOCLAIM_JUSTID_1 = __importDefault(require_XAUTOCLAIM_JUSTID()); + var XAUTOCLAIM_1 = __importDefault(require_XAUTOCLAIM()); + var XCLAIM_JUSTID_1 = __importDefault(require_XCLAIM_JUSTID()); var XCLAIM_1 = __importDefault(require_XCLAIM()); + var XDEL_1 = __importDefault(require_XDEL()); + var XDELEX_1 = __importDefault(require_XDELEX()); + var XGROUP_CREATE_1 = __importDefault(require_XGROUP_CREATE()); + var XGROUP_CREATECONSUMER_1 = __importDefault(require_XGROUP_CREATECONSUMER()); + var XGROUP_DELCONSUMER_1 = __importDefault(require_XGROUP_DELCONSUMER()); + var XGROUP_DESTROY_1 = __importDefault(require_XGROUP_DESTROY()); + var XGROUP_SETID_1 = __importDefault(require_XGROUP_SETID()); + var XINFO_CONSUMERS_1 = __importDefault(require_XINFO_CONSUMERS()); + var XINFO_GROUPS_1 = __importDefault(require_XINFO_GROUPS()); + var XINFO_STREAM_1 = __importDefault(require_XINFO_STREAM()); + var XLEN_1 = __importDefault(require_XLEN()); + var XPENDING_RANGE_1 = __importDefault(require_XPENDING_RANGE()); + var XPENDING_1 = __importDefault(require_XPENDING()); + var XRANGE_1 = __importDefault(require_XRANGE()); + var XREAD_1 = __importDefault(require_XREAD()); + var XREADGROUP_1 = __importDefault(require_XREADGROUP()); + var XREVRANGE_1 = __importDefault(require_XREVRANGE()); + var XSETID_1 = __importDefault(require_XSETID()); + var XTRIM_1 = __importDefault(require_XTRIM()); + var ZADD_INCR_1 = __importDefault(require_ZADD_INCR()); + var ZADD_1 = __importDefault(require_ZADD()); + var ZCARD_1 = __importDefault(require_ZCARD()); + var ZCOUNT_1 = __importDefault(require_ZCOUNT()); + var ZDIFF_WITHSCORES_1 = __importDefault(require_ZDIFF_WITHSCORES()); + var ZDIFF_1 = __importDefault(require_ZDIFF()); + var ZDIFFSTORE_1 = __importDefault(require_ZDIFFSTORE()); + var ZINCRBY_1 = __importDefault(require_ZINCRBY()); + var ZINTER_WITHSCORES_1 = __importDefault(require_ZINTER_WITHSCORES()); + var ZINTER_1 = __importDefault(require_ZINTER()); + var ZINTERCARD_1 = __importDefault(require_ZINTERCARD()); + var ZINTERSTORE_1 = __importDefault(require_ZINTERSTORE()); + var ZLEXCOUNT_1 = __importDefault(require_ZLEXCOUNT()); + var ZMPOP_1 = __importDefault(require_ZMPOP()); + var ZMSCORE_1 = __importDefault(require_ZMSCORE()); + var ZPOPMAX_COUNT_1 = __importDefault(require_ZPOPMAX_COUNT()); + var ZPOPMAX_1 = __importDefault(require_ZPOPMAX()); + var ZPOPMIN_COUNT_1 = __importDefault(require_ZPOPMIN_COUNT()); + var ZPOPMIN_1 = __importDefault(require_ZPOPMIN()); + var ZRANDMEMBER_COUNT_WITHSCORES_1 = __importDefault(require_ZRANDMEMBER_COUNT_WITHSCORES()); + var ZRANDMEMBER_COUNT_1 = __importDefault(require_ZRANDMEMBER_COUNT()); + var ZRANDMEMBER_1 = __importDefault(require_ZRANDMEMBER()); + var ZRANGE_WITHSCORES_1 = __importDefault(require_ZRANGE_WITHSCORES()); + var ZRANGE_1 = __importDefault(require_ZRANGE()); + var ZRANGEBYLEX_1 = __importDefault(require_ZRANGEBYLEX()); + var ZRANGEBYSCORE_WITHSCORES_1 = __importDefault(require_ZRANGEBYSCORE_WITHSCORES()); + var ZRANGEBYSCORE_1 = __importDefault(require_ZRANGEBYSCORE()); + var ZRANGESTORE_1 = __importDefault(require_ZRANGESTORE()); + var ZREMRANGEBYSCORE_1 = __importDefault(require_ZREMRANGEBYSCORE()); + var ZRANK_WITHSCORE_1 = __importDefault(require_ZRANK_WITHSCORE()); + var ZRANK_1 = __importDefault(require_ZRANK()); + var ZREM_1 = __importDefault(require_ZREM()); + var ZREMRANGEBYLEX_1 = __importDefault(require_ZREMRANGEBYLEX()); + var ZREMRANGEBYRANK_1 = __importDefault(require_ZREMRANGEBYRANK()); + var ZREVRANK_1 = __importDefault(require_ZREVRANK()); + var ZSCAN_1 = __importDefault(require_ZSCAN()); + var ZSCORE_1 = __importDefault(require_ZSCORE()); + var ZUNION_WITHSCORES_1 = __importDefault(require_ZUNION_WITHSCORES()); + var ZUNION_1 = __importDefault(require_ZUNION()); + var ZUNIONSTORE_1 = __importDefault(require_ZUNIONSTORE()); + var VADD_1 = __importDefault(require_VADD()); + var VCARD_1 = __importDefault(require_VCARD()); + var VDIM_1 = __importDefault(require_VDIM()); + var VEMB_1 = __importDefault(require_VEMB()); + var VEMB_RAW_1 = __importDefault(require_VEMB_RAW()); + var VGETATTR_1 = __importDefault(require_VGETATTR()); + var VINFO_1 = __importDefault(require_VINFO()); + var VLINKS_1 = __importDefault(require_VLINKS()); + var VLINKS_WITHSCORES_1 = __importDefault(require_VLINKS_WITHSCORES()); + var VRANDMEMBER_1 = __importDefault(require_VRANDMEMBER()); + var VREM_1 = __importDefault(require_VREM()); + var VSETATTR_1 = __importDefault(require_VSETATTR()); + var VSIM_1 = __importDefault(require_VSIM()); + var VSIM_WITHSCORES_1 = __importDefault(require_VSIM_WITHSCORES()); exports2.default = { - IS_READ_ONLY: XCLAIM_1.default.IS_READ_ONLY, - /** - * Constructs the XCLAIM command with JUSTID option to get only message IDs - * - * @param args - Same parameters as XCLAIM command - * @returns Array of successfully claimed message IDs - * @see https://redis.io/commands/xclaim/ - */ - parseCommand(...args) { - const parser3 = args[0]; - XCLAIM_1.default.parseCommand(...args); - parser3.push("JUSTID"); - }, - /** - * Transforms the XCLAIM JUSTID reply into an array of message IDs - * - * @returns Array of claimed message IDs - */ - transformReply: void 0 - }; - } -}); -var require_XDEL = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XDEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XDEL command to remove one or more messages from a stream - * - * @param parser - The command parser - * @param key - The stream key - * @param id - One or more message IDs to delete - * @returns The number of messages actually deleted - * @see https://redis.io/commands/xdel/ - */ - parseCommand(parser3, key, id) { - parser3.push("XDEL"); - parser3.pushKey(key); - parser3.pushVariadic(id); - }, - transformReply: void 0 - }; - } -}); -var require_XDELEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XDELEX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XDELEX command to delete one or multiple entries from the stream - * - * @param parser - The command parser - * @param key - The stream key - * @param id - One or more message IDs to delete - * @param policy - Policy to apply when deleting entries (optional, defaults to KEEPREF) - * @returns Array of integers: -1 (not found), 1 (deleted), 2 (dangling refs) - * @see https://redis.io/commands/xdelex/ - */ - parseCommand(parser3, key, id, policy) { - parser3.push("XDELEX"); - parser3.pushKey(key); - if (policy) { - parser3.push(policy); - } - parser3.push("IDS"); - parser3.pushVariadicWithLength(id); - }, - transformReply: void 0 - }; - } -}); -var require_XGROUP_CREATE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_CREATE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XGROUP CREATE command to create a consumer group for a stream - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group - * @param id - ID of the last delivered item in the stream ('$' for last item, '0' for all items) - * @param options - Additional options for group creation - * @returns 'OK' if successful - * @see https://redis.io/commands/xgroup-create/ - */ - parseCommand(parser3, key, group, id, options2) { - parser3.push("XGROUP", "CREATE"); - parser3.pushKey(key); - parser3.push(group, id); - if (options2?.MKSTREAM) { - parser3.push("MKSTREAM"); - } - if (options2?.ENTRIESREAD) { - parser3.push("ENTRIESREAD", options2.ENTRIESREAD.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_XGROUP_CREATECONSUMER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_CREATECONSUMER.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XGROUP CREATECONSUMER command to create a new consumer in a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group - * @param consumer - Name of the consumer to create - * @returns 1 if the consumer was created, 0 if it already existed - * @see https://redis.io/commands/xgroup-createconsumer/ - */ - parseCommand(parser3, key, group, consumer) { - parser3.push("XGROUP", "CREATECONSUMER"); - parser3.pushKey(key); - parser3.push(group, consumer); - }, - transformReply: void 0 - }; - } -}); -var require_XGROUP_DELCONSUMER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_DELCONSUMER.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XGROUP DELCONSUMER command to remove a consumer from a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group - * @param consumer - Name of the consumer to remove - * @returns The number of pending messages owned by the deleted consumer - * @see https://redis.io/commands/xgroup-delconsumer/ - */ - parseCommand(parser3, key, group, consumer) { - parser3.push("XGROUP", "DELCONSUMER"); - parser3.pushKey(key); - parser3.push(group, consumer); - }, - transformReply: void 0 - }; - } -}); -var require_XGROUP_DESTROY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_DESTROY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Constructs the XGROUP DESTROY command to remove a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group to destroy - * @returns 1 if the group was destroyed, 0 if it did not exist - * @see https://redis.io/commands/xgroup-destroy/ - */ - parseCommand(parser3, key, group) { - parser3.push("XGROUP", "DESTROY"); - parser3.pushKey(key); - parser3.push(group); - }, - transformReply: void 0 - }; - } -}); -var require_XGROUP_SETID = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XGROUP_SETID.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, + ACL_CAT: ACL_CAT_1.default, + aclCat: ACL_CAT_1.default, + ACL_DELUSER: ACL_DELUSER_1.default, + aclDelUser: ACL_DELUSER_1.default, + ACL_DRYRUN: ACL_DRYRUN_1.default, + aclDryRun: ACL_DRYRUN_1.default, + ACL_GENPASS: ACL_GENPASS_1.default, + aclGenPass: ACL_GENPASS_1.default, + ACL_GETUSER: ACL_GETUSER_1.default, + aclGetUser: ACL_GETUSER_1.default, + ACL_LIST: ACL_LIST_1.default, + aclList: ACL_LIST_1.default, + ACL_LOAD: ACL_LOAD_1.default, + aclLoad: ACL_LOAD_1.default, + ACL_LOG_RESET: ACL_LOG_RESET_1.default, + aclLogReset: ACL_LOG_RESET_1.default, + ACL_LOG: ACL_LOG_1.default, + aclLog: ACL_LOG_1.default, + ACL_SAVE: ACL_SAVE_1.default, + aclSave: ACL_SAVE_1.default, + ACL_SETUSER: ACL_SETUSER_1.default, + aclSetUser: ACL_SETUSER_1.default, + ACL_USERS: ACL_USERS_1.default, + aclUsers: ACL_USERS_1.default, + ACL_WHOAMI: ACL_WHOAMI_1.default, + aclWhoAmI: ACL_WHOAMI_1.default, + APPEND: APPEND_1.default, + append: APPEND_1.default, + ASKING: ASKING_1.default, + asking: ASKING_1.default, + AUTH: AUTH_1.default, + auth: AUTH_1.default, + BGREWRITEAOF: BGREWRITEAOF_1.default, + bgRewriteAof: BGREWRITEAOF_1.default, + BGSAVE: BGSAVE_1.default, + bgSave: BGSAVE_1.default, + BITCOUNT: BITCOUNT_1.default, + bitCount: BITCOUNT_1.default, + BITFIELD_RO: BITFIELD_RO_1.default, + bitFieldRo: BITFIELD_RO_1.default, + BITFIELD: BITFIELD_1.default, + bitField: BITFIELD_1.default, + BITOP: BITOP_1.default, + bitOp: BITOP_1.default, + BITPOS: BITPOS_1.default, + bitPos: BITPOS_1.default, + BLMOVE: BLMOVE_1.default, + blMove: BLMOVE_1.default, + BLMPOP: BLMPOP_1.default, + blmPop: BLMPOP_1.default, + BLPOP: BLPOP_1.default, + blPop: BLPOP_1.default, + BRPOP: BRPOP_1.default, + brPop: BRPOP_1.default, + BRPOPLPUSH: BRPOPLPUSH_1.default, + brPopLPush: BRPOPLPUSH_1.default, + BZMPOP: BZMPOP_1.default, + bzmPop: BZMPOP_1.default, + BZPOPMAX: BZPOPMAX_1.default, + bzPopMax: BZPOPMAX_1.default, + BZPOPMIN: BZPOPMIN_1.default, + bzPopMin: BZPOPMIN_1.default, + CLIENT_CACHING: CLIENT_CACHING_1.default, + clientCaching: CLIENT_CACHING_1.default, + CLIENT_GETNAME: CLIENT_GETNAME_1.default, + clientGetName: CLIENT_GETNAME_1.default, + CLIENT_GETREDIR: CLIENT_GETREDIR_1.default, + clientGetRedir: CLIENT_GETREDIR_1.default, + CLIENT_ID: CLIENT_ID_1.default, + clientId: CLIENT_ID_1.default, + CLIENT_INFO: CLIENT_INFO_1.default, + clientInfo: CLIENT_INFO_1.default, + CLIENT_KILL: CLIENT_KILL_1.default, + clientKill: CLIENT_KILL_1.default, + CLIENT_LIST: CLIENT_LIST_1.default, + clientList: CLIENT_LIST_1.default, + "CLIENT_NO-EVICT": CLIENT_NO_EVICT_1.default, + clientNoEvict: CLIENT_NO_EVICT_1.default, + "CLIENT_NO-TOUCH": CLIENT_NO_TOUCH_1.default, + clientNoTouch: CLIENT_NO_TOUCH_1.default, + CLIENT_PAUSE: CLIENT_PAUSE_1.default, + clientPause: CLIENT_PAUSE_1.default, + CLIENT_SETNAME: CLIENT_SETNAME_1.default, + clientSetName: CLIENT_SETNAME_1.default, + CLIENT_TRACKING: CLIENT_TRACKING_1.default, + clientTracking: CLIENT_TRACKING_1.default, + CLIENT_TRACKINGINFO: CLIENT_TRACKINGINFO_1.default, + clientTrackingInfo: CLIENT_TRACKINGINFO_1.default, + CLIENT_UNPAUSE: CLIENT_UNPAUSE_1.default, + clientUnpause: CLIENT_UNPAUSE_1.default, + CLUSTER_ADDSLOTS: CLUSTER_ADDSLOTS_1.default, + clusterAddSlots: CLUSTER_ADDSLOTS_1.default, + CLUSTER_ADDSLOTSRANGE: CLUSTER_ADDSLOTSRANGE_1.default, + clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE_1.default, + CLUSTER_BUMPEPOCH: CLUSTER_BUMPEPOCH_1.default, + clusterBumpEpoch: CLUSTER_BUMPEPOCH_1.default, + "CLUSTER_COUNT-FAILURE-REPORTS": CLUSTER_COUNT_FAILURE_REPORTS_1.default, + clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS_1.default, + CLUSTER_COUNTKEYSINSLOT: CLUSTER_COUNTKEYSINSLOT_1.default, + clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT_1.default, + CLUSTER_DELSLOTS: CLUSTER_DELSLOTS_1.default, + clusterDelSlots: CLUSTER_DELSLOTS_1.default, + CLUSTER_DELSLOTSRANGE: CLUSTER_DELSLOTSRANGE_1.default, + clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE_1.default, + CLUSTER_FAILOVER: CLUSTER_FAILOVER_1.default, + clusterFailover: CLUSTER_FAILOVER_1.default, + CLUSTER_FLUSHSLOTS: CLUSTER_FLUSHSLOTS_1.default, + clusterFlushSlots: CLUSTER_FLUSHSLOTS_1.default, + CLUSTER_FORGET: CLUSTER_FORGET_1.default, + clusterForget: CLUSTER_FORGET_1.default, + CLUSTER_GETKEYSINSLOT: CLUSTER_GETKEYSINSLOT_1.default, + clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT_1.default, + CLUSTER_INFO: CLUSTER_INFO_1.default, + clusterInfo: CLUSTER_INFO_1.default, + CLUSTER_KEYSLOT: CLUSTER_KEYSLOT_1.default, + clusterKeySlot: CLUSTER_KEYSLOT_1.default, + CLUSTER_LINKS: CLUSTER_LINKS_1.default, + clusterLinks: CLUSTER_LINKS_1.default, + CLUSTER_MEET: CLUSTER_MEET_1.default, + clusterMeet: CLUSTER_MEET_1.default, + CLUSTER_MYID: CLUSTER_MYID_1.default, + clusterMyId: CLUSTER_MYID_1.default, + CLUSTER_MYSHARDID: CLUSTER_MYSHARDID_1.default, + clusterMyShardId: CLUSTER_MYSHARDID_1.default, + CLUSTER_NODES: CLUSTER_NODES_1.default, + clusterNodes: CLUSTER_NODES_1.default, + CLUSTER_REPLICAS: CLUSTER_REPLICAS_1.default, + clusterReplicas: CLUSTER_REPLICAS_1.default, + CLUSTER_REPLICATE: CLUSTER_REPLICATE_1.default, + clusterReplicate: CLUSTER_REPLICATE_1.default, + CLUSTER_RESET: CLUSTER_RESET_1.default, + clusterReset: CLUSTER_RESET_1.default, + CLUSTER_SAVECONFIG: CLUSTER_SAVECONFIG_1.default, + clusterSaveConfig: CLUSTER_SAVECONFIG_1.default, + "CLUSTER_SET-CONFIG-EPOCH": CLUSTER_SET_CONFIG_EPOCH_1.default, + clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH_1.default, + CLUSTER_SETSLOT: CLUSTER_SETSLOT_1.default, + clusterSetSlot: CLUSTER_SETSLOT_1.default, + CLUSTER_SLOTS: CLUSTER_SLOTS_1.default, + clusterSlots: CLUSTER_SLOTS_1.default, + COMMAND_COUNT: COMMAND_COUNT_1.default, + commandCount: COMMAND_COUNT_1.default, + COMMAND_GETKEYS: COMMAND_GETKEYS_1.default, + commandGetKeys: COMMAND_GETKEYS_1.default, + COMMAND_GETKEYSANDFLAGS: COMMAND_GETKEYSANDFLAGS_1.default, + commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS_1.default, + COMMAND_INFO: COMMAND_INFO_1.default, + commandInfo: COMMAND_INFO_1.default, + COMMAND_LIST: COMMAND_LIST_1.default, + commandList: COMMAND_LIST_1.default, + COMMAND: COMMAND_1.default, + command: COMMAND_1.default, + CONFIG_GET: CONFIG_GET_1.default, + configGet: CONFIG_GET_1.default, + CONFIG_RESETASTAT: CONFIG_RESETSTAT_1.default, + configResetStat: CONFIG_RESETSTAT_1.default, + CONFIG_REWRITE: CONFIG_REWRITE_1.default, + configRewrite: CONFIG_REWRITE_1.default, + CONFIG_SET: CONFIG_SET_1.default, + configSet: CONFIG_SET_1.default, + COPY: COPY_1.default, + copy: COPY_1.default, + DBSIZE: DBSIZE_1.default, + dbSize: DBSIZE_1.default, + DECR: DECR_1.default, + decr: DECR_1.default, + DECRBY: DECRBY_1.default, + decrBy: DECRBY_1.default, + DEL: DEL_1.default, + del: DEL_1.default, + DUMP: DUMP_1.default, + dump: DUMP_1.default, + ECHO: ECHO_1.default, + echo: ECHO_1.default, + EVAL_RO: EVAL_RO_1.default, + evalRo: EVAL_RO_1.default, + EVAL: EVAL_1.default, + eval: EVAL_1.default, + EVALSHA_RO: EVALSHA_RO_1.default, + evalShaRo: EVALSHA_RO_1.default, + EVALSHA: EVALSHA_1.default, + evalSha: EVALSHA_1.default, + EXISTS: EXISTS_1.default, + exists: EXISTS_1.default, + EXPIRE: EXPIRE_1.default, + expire: EXPIRE_1.default, + EXPIREAT: EXPIREAT_1.default, + expireAt: EXPIREAT_1.default, + EXPIRETIME: EXPIRETIME_1.default, + expireTime: EXPIRETIME_1.default, + FLUSHALL: FLUSHALL_1.default, + flushAll: FLUSHALL_1.default, + FLUSHDB: FLUSHDB_1.default, + flushDb: FLUSHDB_1.default, + FCALL: FCALL_1.default, + fCall: FCALL_1.default, + FCALL_RO: FCALL_RO_1.default, + fCallRo: FCALL_RO_1.default, + FUNCTION_DELETE: FUNCTION_DELETE_1.default, + functionDelete: FUNCTION_DELETE_1.default, + FUNCTION_DUMP: FUNCTION_DUMP_1.default, + functionDump: FUNCTION_DUMP_1.default, + FUNCTION_FLUSH: FUNCTION_FLUSH_1.default, + functionFlush: FUNCTION_FLUSH_1.default, + FUNCTION_KILL: FUNCTION_KILL_1.default, + functionKill: FUNCTION_KILL_1.default, + FUNCTION_LIST_WITHCODE: FUNCTION_LIST_WITHCODE_1.default, + functionListWithCode: FUNCTION_LIST_WITHCODE_1.default, + FUNCTION_LIST: FUNCTION_LIST_1.default, + functionList: FUNCTION_LIST_1.default, + FUNCTION_LOAD: FUNCTION_LOAD_1.default, + functionLoad: FUNCTION_LOAD_1.default, + FUNCTION_RESTORE: FUNCTION_RESTORE_1.default, + functionRestore: FUNCTION_RESTORE_1.default, + FUNCTION_STATS: FUNCTION_STATS_1.default, + functionStats: FUNCTION_STATS_1.default, + GEOADD: GEOADD_1.default, + geoAdd: GEOADD_1.default, + GEODIST: GEODIST_1.default, + geoDist: GEODIST_1.default, + GEOHASH: GEOHASH_1.default, + geoHash: GEOHASH_1.default, + GEOPOS: GEOPOS_1.default, + geoPos: GEOPOS_1.default, + GEORADIUS_RO_WITH: GEORADIUS_RO_WITH_1.default, + geoRadiusRoWith: GEORADIUS_RO_WITH_1.default, + GEORADIUS_RO: GEORADIUS_RO_1.default, + geoRadiusRo: GEORADIUS_RO_1.default, + GEORADIUS_STORE: GEORADIUS_STORE_1.default, + geoRadiusStore: GEORADIUS_STORE_1.default, + GEORADIUS_WITH: GEORADIUS_WITH_1.default, + geoRadiusWith: GEORADIUS_WITH_1.default, + GEORADIUS: GEORADIUS_1.default, + geoRadius: GEORADIUS_1.default, + GEORADIUSBYMEMBER_RO_WITH: GEORADIUSBYMEMBER_RO_WITH_1.default, + geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH_1.default, + GEORADIUSBYMEMBER_RO: GEORADIUSBYMEMBER_RO_1.default, + geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO_1.default, + GEORADIUSBYMEMBER_STORE: GEORADIUSBYMEMBER_STORE_1.default, + geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE_1.default, + GEORADIUSBYMEMBER_WITH: GEORADIUSBYMEMBER_WITH_1.default, + geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH_1.default, + GEORADIUSBYMEMBER: GEORADIUSBYMEMBER_1.default, + geoRadiusByMember: GEORADIUSBYMEMBER_1.default, + GEOSEARCH_WITH: GEOSEARCH_WITH_1.default, + geoSearchWith: GEOSEARCH_WITH_1.default, + GEOSEARCH: GEOSEARCH_1.default, + geoSearch: GEOSEARCH_1.default, + GEOSEARCHSTORE: GEOSEARCHSTORE_1.default, + geoSearchStore: GEOSEARCHSTORE_1.default, + GET: GET_1.default, + get: GET_1.default, + GETBIT: GETBIT_1.default, + getBit: GETBIT_1.default, + GETDEL: GETDEL_1.default, + getDel: GETDEL_1.default, + GETEX: GETEX_1.default, + getEx: GETEX_1.default, + GETRANGE: GETRANGE_1.default, + getRange: GETRANGE_1.default, + GETSET: GETSET_1.default, + getSet: GETSET_1.default, + HDEL: HDEL_1.default, + hDel: HDEL_1.default, + HELLO: HELLO_1.default, + hello: HELLO_1.default, + HEXISTS: HEXISTS_1.default, + hExists: HEXISTS_1.default, + HEXPIRE: HEXPIRE_1.default, + hExpire: HEXPIRE_1.default, + HEXPIREAT: HEXPIREAT_1.default, + hExpireAt: HEXPIREAT_1.default, + HEXPIRETIME: HEXPIRETIME_1.default, + hExpireTime: HEXPIRETIME_1.default, + HGET: HGET_1.default, + hGet: HGET_1.default, + HGETALL: HGETALL_1.default, + hGetAll: HGETALL_1.default, + HGETDEL: HGETDEL_1.default, + hGetDel: HGETDEL_1.default, + HGETEX: HGETEX_1.default, + hGetEx: HGETEX_1.default, + HINCRBY: HINCRBY_1.default, + hIncrBy: HINCRBY_1.default, + HINCRBYFLOAT: HINCRBYFLOAT_1.default, + hIncrByFloat: HINCRBYFLOAT_1.default, + HKEYS: HKEYS_1.default, + hKeys: HKEYS_1.default, + HLEN: HLEN_1.default, + hLen: HLEN_1.default, + HMGET: HMGET_1.default, + hmGet: HMGET_1.default, + HPERSIST: HPERSIST_1.default, + hPersist: HPERSIST_1.default, + HPEXPIRE: HPEXPIRE_1.default, + hpExpire: HPEXPIRE_1.default, + HPEXPIREAT: HPEXPIREAT_1.default, + hpExpireAt: HPEXPIREAT_1.default, + HPEXPIRETIME: HPEXPIRETIME_1.default, + hpExpireTime: HPEXPIRETIME_1.default, + HPTTL: HPTTL_1.default, + hpTTL: HPTTL_1.default, + HRANDFIELD_COUNT_WITHVALUES: HRANDFIELD_COUNT_WITHVALUES_1.default, + hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES_1.default, + HRANDFIELD_COUNT: HRANDFIELD_COUNT_1.default, + hRandFieldCount: HRANDFIELD_COUNT_1.default, + HRANDFIELD: HRANDFIELD_1.default, + hRandField: HRANDFIELD_1.default, + HSCAN: HSCAN_1.default, + hScan: HSCAN_1.default, + HSCAN_NOVALUES: HSCAN_NOVALUES_1.default, + hScanNoValues: HSCAN_NOVALUES_1.default, + HSET: HSET_1.default, + hSet: HSET_1.default, + HSETEX: HSETEX_1.default, + hSetEx: HSETEX_1.default, + HSETNX: HSETNX_1.default, + hSetNX: HSETNX_1.default, + HSTRLEN: HSTRLEN_1.default, + hStrLen: HSTRLEN_1.default, + HTTL: HTTL_1.default, + hTTL: HTTL_1.default, + HVALS: HVALS_1.default, + hVals: HVALS_1.default, + INCR: INCR_1.default, + incr: INCR_1.default, + INCRBY: INCRBY_1.default, + incrBy: INCRBY_1.default, + INCRBYFLOAT: INCRBYFLOAT_1.default, + incrByFloat: INCRBYFLOAT_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + KEYS: KEYS_1.default, + keys: KEYS_1.default, + LASTSAVE: LASTSAVE_1.default, + lastSave: LASTSAVE_1.default, + LATENCY_DOCTOR: LATENCY_DOCTOR_1.default, + latencyDoctor: LATENCY_DOCTOR_1.default, + LATENCY_GRAPH: LATENCY_GRAPH_1.default, + latencyGraph: LATENCY_GRAPH_1.default, + LATENCY_HISTORY: LATENCY_HISTORY_1.default, + latencyHistory: LATENCY_HISTORY_1.default, + LATENCY_LATEST: LATENCY_LATEST_1.default, + latencyLatest: LATENCY_LATEST_1.default, + LATENCY_RESET: LATENCY_RESET_1.default, + latencyReset: LATENCY_RESET_1.default, + LCS_IDX_WITHMATCHLEN: LCS_IDX_WITHMATCHLEN_1.default, + lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN_1.default, + LCS_IDX: LCS_IDX_1.default, + lcsIdx: LCS_IDX_1.default, + LCS_LEN: LCS_LEN_1.default, + lcsLen: LCS_LEN_1.default, + LCS: LCS_1.default, + lcs: LCS_1.default, + LINDEX: LINDEX_1.default, + lIndex: LINDEX_1.default, + LINSERT: LINSERT_1.default, + lInsert: LINSERT_1.default, + LLEN: LLEN_1.default, + lLen: LLEN_1.default, + LMOVE: LMOVE_1.default, + lMove: LMOVE_1.default, + LMPOP: LMPOP_1.default, + lmPop: LMPOP_1.default, + LOLWUT: LOLWUT_1.default, + LPOP_COUNT: LPOP_COUNT_1.default, + lPopCount: LPOP_COUNT_1.default, + LPOP: LPOP_1.default, + lPop: LPOP_1.default, + LPOS_COUNT: LPOS_COUNT_1.default, + lPosCount: LPOS_COUNT_1.default, + LPOS: LPOS_1.default, + lPos: LPOS_1.default, + LPUSH: LPUSH_1.default, + lPush: LPUSH_1.default, + LPUSHX: LPUSHX_1.default, + lPushX: LPUSHX_1.default, + LRANGE: LRANGE_1.default, + lRange: LRANGE_1.default, + LREM: LREM_1.default, + lRem: LREM_1.default, + LSET: LSET_1.default, + lSet: LSET_1.default, + LTRIM: LTRIM_1.default, + lTrim: LTRIM_1.default, + MEMORY_DOCTOR: MEMORY_DOCTOR_1.default, + memoryDoctor: MEMORY_DOCTOR_1.default, + "MEMORY_MALLOC-STATS": MEMORY_MALLOC_STATS_1.default, + memoryMallocStats: MEMORY_MALLOC_STATS_1.default, + MEMORY_PURGE: MEMORY_PURGE_1.default, + memoryPurge: MEMORY_PURGE_1.default, + MEMORY_STATS: MEMORY_STATS_1.default, + memoryStats: MEMORY_STATS_1.default, + MEMORY_USAGE: MEMORY_USAGE_1.default, + memoryUsage: MEMORY_USAGE_1.default, + MGET: MGET_1.default, + mGet: MGET_1.default, + MIGRATE: MIGRATE_1.default, + migrate: MIGRATE_1.default, + MODULE_LIST: MODULE_LIST_1.default, + moduleList: MODULE_LIST_1.default, + MODULE_LOAD: MODULE_LOAD_1.default, + moduleLoad: MODULE_LOAD_1.default, + MODULE_UNLOAD: MODULE_UNLOAD_1.default, + moduleUnload: MODULE_UNLOAD_1.default, + MOVE: MOVE_1.default, + move: MOVE_1.default, + MSET: MSET_1.default, + mSet: MSET_1.default, + MSETNX: MSETNX_1.default, + mSetNX: MSETNX_1.default, + OBJECT_ENCODING: OBJECT_ENCODING_1.default, + objectEncoding: OBJECT_ENCODING_1.default, + OBJECT_FREQ: OBJECT_FREQ_1.default, + objectFreq: OBJECT_FREQ_1.default, + OBJECT_IDLETIME: OBJECT_IDLETIME_1.default, + objectIdleTime: OBJECT_IDLETIME_1.default, + OBJECT_REFCOUNT: OBJECT_REFCOUNT_1.default, + objectRefCount: OBJECT_REFCOUNT_1.default, + PERSIST: PERSIST_1.default, + persist: PERSIST_1.default, + PEXPIRE: PEXPIRE_1.default, + pExpire: PEXPIRE_1.default, + PEXPIREAT: PEXPIREAT_1.default, + pExpireAt: PEXPIREAT_1.default, + PEXPIRETIME: PEXPIRETIME_1.default, + pExpireTime: PEXPIRETIME_1.default, + PFADD: PFADD_1.default, + pfAdd: PFADD_1.default, + PFCOUNT: PFCOUNT_1.default, + pfCount: PFCOUNT_1.default, + PFMERGE: PFMERGE_1.default, + pfMerge: PFMERGE_1.default, + PING: PING_1.default, /** - * Constructs the XGROUP SETID command to set the last delivered ID for a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group - * @param id - ID to set as last delivered message ('$' for last item, '0' for all items) - * @param options - Additional options for setting the group ID - * @returns 'OK' if successful - * @see https://redis.io/commands/xgroup-setid/ + * ping jsdoc */ - parseCommand(parser3, key, group, id, options2) { - parser3.push("XGROUP", "SETID"); - parser3.pushKey(key); - parser3.push(group, id); - if (options2?.ENTRIESREAD) { - parser3.push("ENTRIESREAD", options2.ENTRIESREAD.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_XINFO_CONSUMERS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XINFO_CONSUMERS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Constructs the XINFO CONSUMERS command to list the consumers in a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group - * @returns Array of consumer information objects - * @see https://redis.io/commands/xinfo-consumers/ - */ - parseCommand(parser3, key, group) { - parser3.push("XINFO", "CONSUMERS"); - parser3.pushKey(key); - parser3.push(group); - }, - transformReply: { - /** - * Transforms RESP2 reply into a structured consumer information array - * - * @param reply - Raw RESP2 reply from Redis - * @returns Array of consumer information objects - */ - 2: (reply) => { - return reply.map((consumer) => { - const unwrapped = consumer; - return { - name: unwrapped[1], - pending: unwrapped[3], - idle: unwrapped[5], - inactive: unwrapped[7] - }; - }); - }, - 3: void 0 - } + ping: PING_1.default, + PSETEX: PSETEX_1.default, + pSetEx: PSETEX_1.default, + PTTL: PTTL_1.default, + pTTL: PTTL_1.default, + PUBLISH: PUBLISH_1.default, + publish: PUBLISH_1.default, + PUBSUB_CHANNELS: PUBSUB_CHANNELS_1.default, + pubSubChannels: PUBSUB_CHANNELS_1.default, + PUBSUB_NUMPAT: PUBSUB_NUMPAT_1.default, + pubSubNumPat: PUBSUB_NUMPAT_1.default, + PUBSUB_NUMSUB: PUBSUB_NUMSUB_1.default, + pubSubNumSub: PUBSUB_NUMSUB_1.default, + PUBSUB_SHARDNUMSUB: PUBSUB_SHARDNUMSUB_1.default, + pubSubShardNumSub: PUBSUB_SHARDNUMSUB_1.default, + PUBSUB_SHARDCHANNELS: PUBSUB_SHARDCHANNELS_1.default, + pubSubShardChannels: PUBSUB_SHARDCHANNELS_1.default, + RANDOMKEY: RANDOMKEY_1.default, + randomKey: RANDOMKEY_1.default, + READONLY: READONLY_1.default, + readonly: READONLY_1.default, + RENAME: RENAME_1.default, + rename: RENAME_1.default, + RENAMENX: RENAMENX_1.default, + renameNX: RENAMENX_1.default, + REPLICAOF: REPLICAOF_1.default, + replicaOf: REPLICAOF_1.default, + "RESTORE-ASKING": RESTORE_ASKING_1.default, + restoreAsking: RESTORE_ASKING_1.default, + RESTORE: RESTORE_1.default, + restore: RESTORE_1.default, + RPOP_COUNT: RPOP_COUNT_1.default, + rPopCount: RPOP_COUNT_1.default, + ROLE: ROLE_1.default, + role: ROLE_1.default, + RPOP: RPOP_1.default, + rPop: RPOP_1.default, + RPOPLPUSH: RPOPLPUSH_1.default, + rPopLPush: RPOPLPUSH_1.default, + RPUSH: RPUSH_1.default, + rPush: RPUSH_1.default, + RPUSHX: RPUSHX_1.default, + rPushX: RPUSHX_1.default, + SADD: SADD_1.default, + sAdd: SADD_1.default, + SCAN: SCAN_1.default, + scan: SCAN_1.default, + SCARD: SCARD_1.default, + sCard: SCARD_1.default, + SCRIPT_DEBUG: SCRIPT_DEBUG_1.default, + scriptDebug: SCRIPT_DEBUG_1.default, + SCRIPT_EXISTS: SCRIPT_EXISTS_1.default, + scriptExists: SCRIPT_EXISTS_1.default, + SCRIPT_FLUSH: SCRIPT_FLUSH_1.default, + scriptFlush: SCRIPT_FLUSH_1.default, + SCRIPT_KILL: SCRIPT_KILL_1.default, + scriptKill: SCRIPT_KILL_1.default, + SCRIPT_LOAD: SCRIPT_LOAD_1.default, + scriptLoad: SCRIPT_LOAD_1.default, + SDIFF: SDIFF_1.default, + sDiff: SDIFF_1.default, + SDIFFSTORE: SDIFFSTORE_1.default, + sDiffStore: SDIFFSTORE_1.default, + SET: SET_1.default, + set: SET_1.default, + SETBIT: SETBIT_1.default, + setBit: SETBIT_1.default, + SETEX: SETEX_1.default, + setEx: SETEX_1.default, + SETNX: SETNX_1.default, + setNX: SETNX_1.default, + SETRANGE: SETRANGE_1.default, + setRange: SETRANGE_1.default, + SINTER: SINTER_1.default, + sInter: SINTER_1.default, + SINTERCARD: SINTERCARD_1.default, + sInterCard: SINTERCARD_1.default, + SINTERSTORE: SINTERSTORE_1.default, + sInterStore: SINTERSTORE_1.default, + SISMEMBER: SISMEMBER_1.default, + sIsMember: SISMEMBER_1.default, + SMEMBERS: SMEMBERS_1.default, + sMembers: SMEMBERS_1.default, + SMISMEMBER: SMISMEMBER_1.default, + smIsMember: SMISMEMBER_1.default, + SMOVE: SMOVE_1.default, + sMove: SMOVE_1.default, + SORT_RO: SORT_RO_1.default, + sortRo: SORT_RO_1.default, + SORT_STORE: SORT_STORE_1.default, + sortStore: SORT_STORE_1.default, + SORT: SORT_1.default, + sort: SORT_1.default, + SPOP_COUNT: SPOP_COUNT_1.default, + sPopCount: SPOP_COUNT_1.default, + SPOP: SPOP_1.default, + sPop: SPOP_1.default, + SPUBLISH: SPUBLISH_1.default, + sPublish: SPUBLISH_1.default, + SRANDMEMBER_COUNT: SRANDMEMBER_COUNT_1.default, + sRandMemberCount: SRANDMEMBER_COUNT_1.default, + SRANDMEMBER: SRANDMEMBER_1.default, + sRandMember: SRANDMEMBER_1.default, + SREM: SREM_1.default, + sRem: SREM_1.default, + SSCAN: SSCAN_1.default, + sScan: SSCAN_1.default, + STRLEN: STRLEN_1.default, + strLen: STRLEN_1.default, + SUNION: SUNION_1.default, + sUnion: SUNION_1.default, + SUNIONSTORE: SUNIONSTORE_1.default, + sUnionStore: SUNIONSTORE_1.default, + SWAPDB: SWAPDB_1.default, + swapDb: SWAPDB_1.default, + TIME: TIME_1.default, + time: TIME_1.default, + TOUCH: TOUCH_1.default, + touch: TOUCH_1.default, + TTL: TTL_1.default, + ttl: TTL_1.default, + TYPE: TYPE_1.default, + type: TYPE_1.default, + UNLINK: UNLINK_1.default, + unlink: UNLINK_1.default, + WAIT: WAIT_1.default, + wait: WAIT_1.default, + XACK: XACK_1.default, + xAck: XACK_1.default, + XACKDEL: XACKDEL_1.default, + xAckDel: XACKDEL_1.default, + XADD_NOMKSTREAM: XADD_NOMKSTREAM_1.default, + xAddNoMkStream: XADD_NOMKSTREAM_1.default, + XADD: XADD_1.default, + xAdd: XADD_1.default, + XAUTOCLAIM_JUSTID: XAUTOCLAIM_JUSTID_1.default, + xAutoClaimJustId: XAUTOCLAIM_JUSTID_1.default, + XAUTOCLAIM: XAUTOCLAIM_1.default, + xAutoClaim: XAUTOCLAIM_1.default, + XCLAIM_JUSTID: XCLAIM_JUSTID_1.default, + xClaimJustId: XCLAIM_JUSTID_1.default, + XCLAIM: XCLAIM_1.default, + xClaim: XCLAIM_1.default, + XDEL: XDEL_1.default, + xDel: XDEL_1.default, + XDELEX: XDELEX_1.default, + xDelEx: XDELEX_1.default, + XGROUP_CREATE: XGROUP_CREATE_1.default, + xGroupCreate: XGROUP_CREATE_1.default, + XGROUP_CREATECONSUMER: XGROUP_CREATECONSUMER_1.default, + xGroupCreateConsumer: XGROUP_CREATECONSUMER_1.default, + XGROUP_DELCONSUMER: XGROUP_DELCONSUMER_1.default, + xGroupDelConsumer: XGROUP_DELCONSUMER_1.default, + XGROUP_DESTROY: XGROUP_DESTROY_1.default, + xGroupDestroy: XGROUP_DESTROY_1.default, + XGROUP_SETID: XGROUP_SETID_1.default, + xGroupSetId: XGROUP_SETID_1.default, + XINFO_CONSUMERS: XINFO_CONSUMERS_1.default, + xInfoConsumers: XINFO_CONSUMERS_1.default, + XINFO_GROUPS: XINFO_GROUPS_1.default, + xInfoGroups: XINFO_GROUPS_1.default, + XINFO_STREAM: XINFO_STREAM_1.default, + xInfoStream: XINFO_STREAM_1.default, + XLEN: XLEN_1.default, + xLen: XLEN_1.default, + XPENDING_RANGE: XPENDING_RANGE_1.default, + xPendingRange: XPENDING_RANGE_1.default, + XPENDING: XPENDING_1.default, + xPending: XPENDING_1.default, + XRANGE: XRANGE_1.default, + xRange: XRANGE_1.default, + XREAD: XREAD_1.default, + xRead: XREAD_1.default, + XREADGROUP: XREADGROUP_1.default, + xReadGroup: XREADGROUP_1.default, + XREVRANGE: XREVRANGE_1.default, + xRevRange: XREVRANGE_1.default, + XSETID: XSETID_1.default, + xSetId: XSETID_1.default, + XTRIM: XTRIM_1.default, + xTrim: XTRIM_1.default, + ZADD_INCR: ZADD_INCR_1.default, + zAddIncr: ZADD_INCR_1.default, + ZADD: ZADD_1.default, + zAdd: ZADD_1.default, + ZCARD: ZCARD_1.default, + zCard: ZCARD_1.default, + ZCOUNT: ZCOUNT_1.default, + zCount: ZCOUNT_1.default, + ZDIFF_WITHSCORES: ZDIFF_WITHSCORES_1.default, + zDiffWithScores: ZDIFF_WITHSCORES_1.default, + ZDIFF: ZDIFF_1.default, + zDiff: ZDIFF_1.default, + ZDIFFSTORE: ZDIFFSTORE_1.default, + zDiffStore: ZDIFFSTORE_1.default, + ZINCRBY: ZINCRBY_1.default, + zIncrBy: ZINCRBY_1.default, + ZINTER_WITHSCORES: ZINTER_WITHSCORES_1.default, + zInterWithScores: ZINTER_WITHSCORES_1.default, + ZINTER: ZINTER_1.default, + zInter: ZINTER_1.default, + ZINTERCARD: ZINTERCARD_1.default, + zInterCard: ZINTERCARD_1.default, + ZINTERSTORE: ZINTERSTORE_1.default, + zInterStore: ZINTERSTORE_1.default, + ZLEXCOUNT: ZLEXCOUNT_1.default, + zLexCount: ZLEXCOUNT_1.default, + ZMPOP: ZMPOP_1.default, + zmPop: ZMPOP_1.default, + ZMSCORE: ZMSCORE_1.default, + zmScore: ZMSCORE_1.default, + ZPOPMAX_COUNT: ZPOPMAX_COUNT_1.default, + zPopMaxCount: ZPOPMAX_COUNT_1.default, + ZPOPMAX: ZPOPMAX_1.default, + zPopMax: ZPOPMAX_1.default, + ZPOPMIN_COUNT: ZPOPMIN_COUNT_1.default, + zPopMinCount: ZPOPMIN_COUNT_1.default, + ZPOPMIN: ZPOPMIN_1.default, + zPopMin: ZPOPMIN_1.default, + ZRANDMEMBER_COUNT_WITHSCORES: ZRANDMEMBER_COUNT_WITHSCORES_1.default, + zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES_1.default, + ZRANDMEMBER_COUNT: ZRANDMEMBER_COUNT_1.default, + zRandMemberCount: ZRANDMEMBER_COUNT_1.default, + ZRANDMEMBER: ZRANDMEMBER_1.default, + zRandMember: ZRANDMEMBER_1.default, + ZRANGE_WITHSCORES: ZRANGE_WITHSCORES_1.default, + zRangeWithScores: ZRANGE_WITHSCORES_1.default, + ZRANGE: ZRANGE_1.default, + zRange: ZRANGE_1.default, + ZRANGEBYLEX: ZRANGEBYLEX_1.default, + zRangeByLex: ZRANGEBYLEX_1.default, + ZRANGEBYSCORE_WITHSCORES: ZRANGEBYSCORE_WITHSCORES_1.default, + zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES_1.default, + ZRANGEBYSCORE: ZRANGEBYSCORE_1.default, + zRangeByScore: ZRANGEBYSCORE_1.default, + ZRANGESTORE: ZRANGESTORE_1.default, + zRangeStore: ZRANGESTORE_1.default, + ZRANK_WITHSCORE: ZRANK_WITHSCORE_1.default, + zRankWithScore: ZRANK_WITHSCORE_1.default, + ZRANK: ZRANK_1.default, + zRank: ZRANK_1.default, + ZREM: ZREM_1.default, + zRem: ZREM_1.default, + ZREMRANGEBYLEX: ZREMRANGEBYLEX_1.default, + zRemRangeByLex: ZREMRANGEBYLEX_1.default, + ZREMRANGEBYRANK: ZREMRANGEBYRANK_1.default, + zRemRangeByRank: ZREMRANGEBYRANK_1.default, + ZREMRANGEBYSCORE: ZREMRANGEBYSCORE_1.default, + zRemRangeByScore: ZREMRANGEBYSCORE_1.default, + ZREVRANK: ZREVRANK_1.default, + zRevRank: ZREVRANK_1.default, + ZSCAN: ZSCAN_1.default, + zScan: ZSCAN_1.default, + ZSCORE: ZSCORE_1.default, + zScore: ZSCORE_1.default, + ZUNION_WITHSCORES: ZUNION_WITHSCORES_1.default, + zUnionWithScores: ZUNION_WITHSCORES_1.default, + ZUNION: ZUNION_1.default, + zUnion: ZUNION_1.default, + ZUNIONSTORE: ZUNIONSTORE_1.default, + zUnionStore: ZUNIONSTORE_1.default, + VADD: VADD_1.default, + vAdd: VADD_1.default, + VCARD: VCARD_1.default, + vCard: VCARD_1.default, + VDIM: VDIM_1.default, + vDim: VDIM_1.default, + VEMB: VEMB_1.default, + vEmb: VEMB_1.default, + VEMB_RAW: VEMB_RAW_1.default, + vEmbRaw: VEMB_RAW_1.default, + VGETATTR: VGETATTR_1.default, + vGetAttr: VGETATTR_1.default, + VINFO: VINFO_1.default, + vInfo: VINFO_1.default, + VLINKS: VLINKS_1.default, + vLinks: VLINKS_1.default, + VLINKS_WITHSCORES: VLINKS_WITHSCORES_1.default, + vLinksWithScores: VLINKS_WITHSCORES_1.default, + VRANDMEMBER: VRANDMEMBER_1.default, + vRandMember: VRANDMEMBER_1.default, + VREM: VREM_1.default, + vRem: VREM_1.default, + VSETATTR: VSETATTR_1.default, + vSetAttr: VSETATTR_1.default, + VSIM: VSIM_1.default, + vSim: VSIM_1.default, + VSIM_WITHSCORES: VSIM_WITHSCORES_1.default, + vSimWithScores: VSIM_WITHSCORES_1.default }; } }); -var require_XINFO_GROUPS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XINFO_GROUPS.js"(exports2) { +var require_enterprise_maintenance_manager = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/enterprise-maintenance-manager.js"(exports2) { "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Constructs the XINFO GROUPS command to list the consumer groups of a stream - * - * @param parser - The command parser - * @param key - The stream key - * @returns Array of consumer group information objects - * @see https://redis.io/commands/xinfo-groups/ - */ - parseCommand(parser3, key) { - parser3.push("XINFO", "GROUPS"); - parser3.pushKey(key); - }, - transformReply: { - /** - * Transforms RESP2 reply into a structured consumer group information array - * - * @param reply - Raw RESP2 reply from Redis - * @returns Array of consumer group information objects containing: - * name - Name of the consumer group - * consumers - Number of consumers in the group - * pending - Number of pending messages for the group - * last-delivered-id - ID of the last delivered message - * entries-read - Number of entries read in the group (Redis 7.0+) - * lag - Number of entries not read by the group (Redis 7.0+) - */ - 2: (reply) => { - return reply.map((group) => { - const unwrapped = group; - return { - name: unwrapped[1], - consumers: unwrapped[3], - pending: unwrapped[5], - "last-delivered-id": unwrapped[7], - "entries-read": unwrapped[9], - lag: unwrapped[11] - }; - }); - }, - 3: void 0 - } + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - } -}); -var require_XINFO_STREAM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XINFO_STREAM.js"(exports2) { - "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Constructs the XINFO STREAM command to get detailed information about a stream - * - * @param parser - The command parser - * @param key - The stream key - * @returns Detailed information about the stream including its length, structure, and entries - * @see https://redis.io/commands/xinfo-stream/ - */ - parseCommand(parser3, key) { - parser3.push("XINFO", "STREAM"); - parser3.pushKey(key); - }, - transformReply: { - // TODO: is there a "type safe" way to do it? - 2(reply) { - const parsedReply = {}; - for (let i2 = 0; i2 < reply.length; i2 += 2) { - switch (reply[i2]) { - case "first-entry": - case "last-entry": - parsedReply[reply[i2]] = transformEntry(reply[i2 + 1]); - break; - default: - parsedReply[reply[i2]] = reply[i2 + 1]; - break; + exports2.emitDiagnostics = exports2.dbgMaintenance = exports2.MAINTENANCE_EVENTS = void 0; + var net_1 = __require2("node:net"); + var promises_1 = __require2("node:dns/promises"); + var node_assert_1 = __importDefault(__require2("node:assert")); + var promises_2 = __require2("node:timers/promises"); + var node_diagnostics_channel_1 = __importDefault(__require2("node:diagnostics_channel")); + exports2.MAINTENANCE_EVENTS = { + PAUSE_WRITING: "pause-writing", + RESUME_WRITING: "resume-writing", + TIMEOUTS_UPDATE: "timeouts-update" + }; + var PN = { + MOVING: "MOVING", + MIGRATING: "MIGRATING", + MIGRATED: "MIGRATED", + FAILING_OVER: "FAILING_OVER", + FAILED_OVER: "FAILED_OVER" + }; + var dbgMaintenance = (...args) => { + if (!process.env.REDIS_DEBUG_MAINTENANCE) + return; + return console.log("[MNT]", ...args); + }; + exports2.dbgMaintenance = dbgMaintenance; + var emitDiagnostics = (event) => { + if (!process.env.REDIS_EMIT_DIAGNOSTICS) + return; + const channel = node_diagnostics_channel_1.default.channel("redis.maintenance"); + channel.publish(event); + }; + exports2.emitDiagnostics = emitDiagnostics; + var EnterpriseMaintenanceManager = class { + #commandsQueue; + #options; + #isMaintenance = 0; + #client; + static setupDefaultMaintOptions(options2) { + if (options2.maintNotifications === void 0) { + options2.maintNotifications = options2?.RESP === 3 ? "auto" : "disabled"; + } + if (options2.maintEndpointType === void 0) { + options2.maintEndpointType = "auto"; + } + if (options2.maintRelaxedSocketTimeout === void 0) { + options2.maintRelaxedSocketTimeout = 1e4; + } + if (options2.maintRelaxedCommandTimeout === void 0) { + options2.maintRelaxedCommandTimeout = 1e4; + } + } + static async getHandshakeCommand(options2) { + if (options2.maintNotifications === "disabled") + return; + const host = options2.url ? new URL(options2.url).hostname : options2.socket?.host; + if (!host) + return; + const tls = options2.socket?.tls ?? false; + const movingEndpointType = await determineEndpoint(tls, host, options2); + return { + cmd: [ + "CLIENT", + "MAINT_NOTIFICATIONS", + "ON", + "moving-endpoint-type", + movingEndpointType + ], + errorHandler: (error2) => { + (0, exports2.dbgMaintenance)("handshake failed:", error2); + if (options2.maintNotifications === "enabled") { + throw error2; } } - return parsedReply; - }, - 3(reply) { - if (reply instanceof Map) { - reply.set("first-entry", transformEntry(reply.get("first-entry"))); - reply.set("last-entry", transformEntry(reply.get("last-entry"))); - } else if (reply instanceof Array) { - reply[17] = transformEntry(reply[17]); - reply[19] = transformEntry(reply[19]); - } else { - reply["first-entry"] = transformEntry(reply["first-entry"]); - reply["last-entry"] = transformEntry(reply["last-entry"]); - } - return reply; - } + }; } - }; - function transformEntry(entry) { - if ((0, generic_transformers_1.isNullReply)(entry)) - return entry; - const [id, message] = entry; - return { - id, - message: (0, generic_transformers_1.transformTuplesReply)(message) - }; - } - } -}); -var require_XLEN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XLEN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Constructs the XLEN command to get the number of entries in a stream - * - * @param parser - The command parser - * @param key - The stream key - * @returns The number of entries inside the stream - * @see https://redis.io/commands/xlen/ - */ - parseCommand(parser3, key) { - parser3.push("XLEN"); - parser3.pushKey(key); - }, - transformReply: void 0 - }; - } -}); -var require_XPENDING_RANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XPENDING_RANGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Constructs the XPENDING command with range parameters to get detailed information about pending messages - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group - * @param start - Start of ID range (use '-' for minimum ID) - * @param end - End of ID range (use '+' for maximum ID) - * @param count - Maximum number of messages to return - * @param options - Additional filtering options - * @returns Array of pending message details - * @see https://redis.io/commands/xpending/ - */ - parseCommand(parser3, key, group, start, end, count, options2) { - parser3.push("XPENDING"); - parser3.pushKey(key); - parser3.push(group); - if (options2?.IDLE !== void 0) { - parser3.push("IDLE", options2.IDLE.toString()); + constructor(commandsQueue, client, options2) { + this.#commandsQueue = commandsQueue; + this.#options = options2; + this.#client = client; + this.#commandsQueue.addPushHandler(this.#onPush); + } + #onPush = (push) => { + (0, exports2.dbgMaintenance)("ONPUSH:", push.map(String)); + if (!Array.isArray(push) || !["MOVING", "MIGRATING", "MIGRATED", "FAILING_OVER", "FAILED_OVER"].includes(String(push[0]))) { + return false; } - parser3.push(start, end, count.toString()); - if (options2?.consumer) { - parser3.push(options2.consumer); + const type = String(push[0]); + (0, exports2.emitDiagnostics)({ + type, + timestamp: Date.now(), + data: { + push: push.map(String) + } + }); + switch (type) { + case PN.MOVING: { + const afterSeconds = push[2]; + const url2 = push[3] ? String(push[3]) : null; + (0, exports2.dbgMaintenance)("Received MOVING:", afterSeconds, url2); + this.#onMoving(afterSeconds, url2); + return true; + } + case PN.MIGRATING: + case PN.FAILING_OVER: { + (0, exports2.dbgMaintenance)("Received MIGRATING|FAILING_OVER"); + this.#onMigrating(); + return true; + } + case PN.MIGRATED: + case PN.FAILED_OVER: { + (0, exports2.dbgMaintenance)("Received MIGRATED|FAILED_OVER"); + this.#onMigrated(); + return true; + } } - }, - /** - * Transforms the raw XPENDING RANGE reply into a structured array of message details - * - * @param reply - Raw reply from Redis - * @returns Array of objects containing message ID, consumer, idle time, and delivery count - */ - transformReply(reply) { - return reply.map((pending) => { - const unwrapped = pending; - return { - id: unwrapped[0], - consumer: unwrapped[1], - millisecondsSinceLastDelivery: unwrapped[2], - deliveriesCounter: unwrapped[3] + return false; + }; + // Queue: + // toWrite [ C D E ] + // waitingForReply [ A B ] - aka In-flight commands + // + // time: ---1-2---3-4-5-6--------------------------- + // + // 1. [EVENT] MOVING PN received + // 2. [ACTION] Pause writing ( we need to wait for new socket to connect and for all in-flight commands to complete ) + // 3. [EVENT] New socket connected + // 4. [EVENT] In-flight commands completed + // 5. [ACTION] Destroy old socket + // 6. [ACTION] Resume writing -> we are going to write to the new socket from now on + #onMoving = async (afterSeconds, url2) => { + this.#onMigrating(); + let host; + let port; + if (url2 === null) { + (0, node_assert_1.default)(this.#options.maintEndpointType === "none"); + (0, node_assert_1.default)(this.#options.socket !== void 0); + (0, node_assert_1.default)("host" in this.#options.socket); + (0, node_assert_1.default)(typeof this.#options.socket.host === "string"); + host = this.#options.socket.host; + (0, node_assert_1.default)(typeof this.#options.socket.port === "number"); + port = this.#options.socket.port; + const waitTime = afterSeconds * 1e3 / 2; + (0, exports2.dbgMaintenance)(`Wait for ${waitTime}ms`); + await (0, promises_2.setTimeout)(waitTime); + } else { + const split = url2.split(":"); + host = split[0]; + port = Number(split[1]); + } + (0, exports2.dbgMaintenance)("Pausing writing of new commands to old socket"); + this.#client._pause(); + (0, exports2.dbgMaintenance)("Creating new tmp client"); + let start = performance.now(); + if (this.#options.url) { + const u2 = new URL(this.#options.url); + u2.hostname = host; + u2.port = String(port); + this.#options.url = u2.toString(); + } else { + this.#options.socket = { + ...this.#options.socket, + host, + port }; + } + const tmpClient = this.#client.duplicate(); + tmpClient.on("error", (error2) => { + (0, exports2.dbgMaintenance)(`[ERR]`, error2); }); - } - }; - } -}); -var require_XPENDING = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XPENDING.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Constructs the XPENDING command to inspect pending messages of a consumer group - * - * @param parser - The command parser - * @param key - The stream key - * @param group - Name of the consumer group - * @returns Summary of pending messages including total count, ID range, and per-consumer stats - * @see https://redis.io/commands/xpending/ - */ - parseCommand(parser3, key, group) { - parser3.push("XPENDING"); - parser3.pushKey(key); - parser3.push(group); - }, - /** - * Transforms the raw XPENDING reply into a structured object - * - * @param reply - Raw reply from Redis - * @returns Object containing pending count, ID range, and consumer statistics - */ - transformReply(reply) { - const consumers = reply[3]; - return { - pending: reply[0], - firstId: reply[1], - lastId: reply[2], - consumers: consumers === null ? null : consumers.map((consumer) => { - const [name, deliveriesCounter] = consumer; - return { - name, - deliveriesCounter: Number(deliveriesCounter) - }; - }) + (0, exports2.dbgMaintenance)(`Tmp client created in ${(performance.now() - start).toFixed(2)}ms`); + (0, exports2.dbgMaintenance)(`Set timeout for tmp client to ${this.#options.maintRelaxedSocketTimeout}`); + tmpClient._maintenanceUpdate({ + relaxedCommandTimeout: this.#options.maintRelaxedCommandTimeout, + relaxedSocketTimeout: this.#options.maintRelaxedSocketTimeout + }); + (0, exports2.dbgMaintenance)(`Connecting tmp client: ${host}:${port}`); + start = performance.now(); + await tmpClient.connect(); + (0, exports2.dbgMaintenance)(`Connected to tmp client in ${(performance.now() - start).toFixed(2)}ms`); + (0, exports2.dbgMaintenance)(`Wait for all in-flight commands to complete`); + await this.#commandsQueue.waitForInflightCommandsToComplete(); + (0, exports2.dbgMaintenance)(`In-flight commands completed`); + (0, exports2.dbgMaintenance)("Swap client sockets..."); + const oldSocket = this.#client._ejectSocket(); + const newSocket = tmpClient._ejectSocket(); + this.#client._insertSocket(newSocket); + tmpClient._insertSocket(oldSocket); + tmpClient.destroy(); + (0, exports2.dbgMaintenance)("Swap client sockets done."); + (0, exports2.dbgMaintenance)("Resume writing"); + this.#client._unpause(); + this.#onMigrated(); + }; + #onMigrating = () => { + this.#isMaintenance++; + if (this.#isMaintenance > 1) { + (0, exports2.dbgMaintenance)(`Timeout relaxation already done`); + return; + } + const update = { + relaxedCommandTimeout: this.#options.maintRelaxedCommandTimeout, + relaxedSocketTimeout: this.#options.maintRelaxedSocketTimeout }; - } + this.#client._maintenanceUpdate(update); + }; + #onMigrated = () => { + this.#isMaintenance = Math.max(this.#isMaintenance - 1, 0); + if (this.#isMaintenance > 0) { + (0, exports2.dbgMaintenance)(`Not ready to unrelax timeouts yet`); + return; + } + const update = { + relaxedCommandTimeout: void 0, + relaxedSocketTimeout: void 0 + }; + this.#client._maintenanceUpdate(update); + }; }; - } -}); -var require_XRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XRANGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.xRangeArguments = void 0; - var generic_transformers_1 = require_generic_transformers(); - function xRangeArguments(start, end, options2) { - const args = [start, end]; - if (options2?.COUNT) { - args.push("COUNT", options2.COUNT.toString()); + exports2.default = EnterpriseMaintenanceManager; + function isPrivateIP(ip) { + const version3 = (0, net_1.isIP)(ip); + if (version3 === 4) { + const octets = ip.split(".").map(Number); + return octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168; } - return args; + if (version3 === 6) { + return ip.startsWith("fc") || // Unique local + ip.startsWith("fd") || // Unique local + ip === "::1" || // Loopback + ip.startsWith("fe80"); + } + return false; } - exports2.xRangeArguments = xRangeArguments; - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Constructs the XRANGE command to read stream entries in a specific range - * - * @param parser - The command parser - * @param key - The stream key - * @param args - Arguments tuple containing start ID, end ID, and options - * @returns Array of messages in the specified range - * @see https://redis.io/commands/xrange/ - */ - parseCommand(parser3, key, ...args) { - parser3.push("XRANGE"); - parser3.pushKey(key); - parser3.pushVariadic(xRangeArguments(args[0], args[1], args[2])); - }, - /** - * Transforms the raw XRANGE reply into structured message objects - * - * @param reply - Raw reply from Redis - * @param preserve - Preserve options (unused) - * @param typeMapping - Type mapping for message fields - * @returns Array of structured message objects - */ - transformReply(reply, preserve, typeMapping) { - return reply.map(generic_transformers_1.transformStreamMessageReply.bind(void 0, typeMapping)); + async function determineEndpoint(tlsEnabled, host, options2) { + (0, node_assert_1.default)(options2.maintEndpointType !== void 0); + if (options2.maintEndpointType !== "auto") { + (0, exports2.dbgMaintenance)(`Determine endpoint type: ${options2.maintEndpointType}`); + return options2.maintEndpointType; } - }; - } -}); -var require_XREAD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XREAD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.pushXReadStreams = void 0; - var generic_transformers_1 = require_generic_transformers(); - function pushXReadStreams(parser3, streams) { - parser3.push("STREAMS"); - if (Array.isArray(streams)) { - for (let i2 = 0; i2 < streams.length; i2++) { - parser3.pushKey(streams[i2].key); - } - for (let i2 = 0; i2 < streams.length; i2++) { - parser3.push(streams[i2].id); - } + const ip = (0, net_1.isIP)(host) ? host : (await (0, promises_1.lookup)(host, { family: 0 })).address; + const isPrivate = isPrivateIP(ip); + let result; + if (tlsEnabled) { + result = isPrivate ? "internal-fqdn" : "external-fqdn"; } else { - parser3.pushKey(streams.key); - parser3.push(streams.id); + result = isPrivate ? "internal-ip" : "external-ip"; } + (0, exports2.dbgMaintenance)(`Determine endpoint type: ${result}`); + return result; } - exports2.pushXReadStreams = pushXReadStreams; - exports2.default = { - IS_READ_ONLY: true, - /** - * Constructs the XREAD command to read messages from one or more streams - * - * @param parser - The command parser - * @param streams - Single stream or array of streams to read from - * @param options - Additional options for reading streams - * @returns Array of stream entries, each containing the stream name and its messages - * @see https://redis.io/commands/xread/ - */ - parseCommand(parser3, streams, options2) { - parser3.push("XREAD"); - if (options2?.COUNT) { - parser3.push("COUNT", options2.COUNT.toString()); - } - if (options2?.BLOCK !== void 0) { - parser3.push("BLOCK", options2.BLOCK.toString()); - } - pushXReadStreams(parser3, streams); - }, - /** - * Transform functions for different RESP versions - */ - transformReply: { - 2: generic_transformers_1.transformStreamsMessagesReplyResp2, - 3: void 0 - }, - unstableResp3: true - }; } }); -var require_XREADGROUP = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XREADGROUP.js"(exports2) { +var require_socket = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/socket.js"(exports2) { "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var XREAD_1 = require_XREAD(); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Constructs the XREADGROUP command to read messages from streams as a consumer group member - * - * @param parser - The command parser - * @param group - Name of the consumer group - * @param consumer - Name of the consumer in the group - * @param streams - Single stream or array of streams to read from - * @param options - Additional options for reading streams - * @returns Array of stream entries, each containing the stream name and its messages - * @see https://redis.io/commands/xreadgroup/ - */ - parseCommand(parser3, group, consumer, streams, options2) { - parser3.push("XREADGROUP", "GROUP", group, consumer); - if (options2?.COUNT !== void 0) { - parser3.push("COUNT", options2.COUNT.toString()); - } - if (options2?.BLOCK !== void 0) { - parser3.push("BLOCK", options2.BLOCK.toString()); - } - if (options2?.NOACK) { - parser3.push("NOACK"); - } - (0, XREAD_1.pushXReadStreams)(parser3, streams); - }, - /** - * Transform functions for different RESP versions - */ - transformReply: { - 2: generic_transformers_1.transformStreamsMessagesReplyResp2, - 3: void 0 - }, - unstableResp3: true + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - } -}); -var require_XREVRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XREVRANGE.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var node_events_1 = __require2("node:events"); + var node_net_1 = __importDefault(__require2("node:net")); + var node_tls_1 = __importDefault(__require2("node:tls")); + var errors_1 = require_errors(); + var promises_1 = __require2("node:timers/promises"); + var enterprise_maintenance_manager_1 = require_enterprise_maintenance_manager(); + var RedisSocket = class extends node_events_1.EventEmitter { + #initiator; + #connectTimeout; + #reconnectStrategy; + #socketFactory; + #socketTimeout; + #maintenanceTimeout; + #socket; + #isOpen = false; + get isOpen() { + return this.#isOpen; } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + #isReady = false; + get isReady() { + return this.#isReady; } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var XRANGE_1 = __importStar(require_XRANGE()); - exports2.default = { - CACHEABLE: XRANGE_1.default.CACHEABLE, - IS_READ_ONLY: XRANGE_1.default.IS_READ_ONLY, - /** - * Constructs the XREVRANGE command to read stream entries in reverse order - * - * @param parser - The command parser - * @param key - The stream key - * @param args - Arguments tuple containing start ID, end ID, and options - * @returns Array of messages in the specified range in reverse order - * @see https://redis.io/commands/xrevrange/ - */ - parseCommand(parser3, key, ...args) { - parser3.push("XREVRANGE"); - parser3.pushKey(key); - parser3.pushVariadic((0, XRANGE_1.xRangeArguments)(args[0], args[1], args[2])); - }, - transformReply: XRANGE_1.default.transformReply - }; - } -}); -var require_XSETID = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XSETID.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - parseCommand(parser3, key, lastId, options2) { - parser3.push("XSETID"); - parser3.pushKey(key); - parser3.push(lastId); - if (options2?.ENTRIESADDED) { - parser3.push("ENTRIESADDED", options2.ENTRIESADDED.toString()); - } - if (options2?.MAXDELETEDID) { - parser3.push("MAXDELETEDID", options2.MAXDELETEDID); + #isSocketUnrefed = false; + #socketEpoch = 0; + get socketEpoch() { + return this.#socketEpoch; + } + constructor(initiator, options2) { + super(); + this.#initiator = initiator; + this.#connectTimeout = options2?.connectTimeout ?? 5e3; + this.#reconnectStrategy = this.#createReconnectStrategy(options2); + this.#socketFactory = this.#createSocketFactory(options2); + this.#socketTimeout = options2?.socketTimeout; + } + #createReconnectStrategy(options2) { + const strategy = options2?.reconnectStrategy; + if (strategy === false || typeof strategy === "number") { + return () => strategy; } - }, - transformReply: void 0 - }; - } + if (strategy) { + return (retries, cause) => { + try { + const retryIn = strategy(retries, cause); + if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== "number") { + throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); + } + return retryIn; + } catch (err) { + this.emit("error", err); + return this.defaultReconnectStrategy(retries, err); + } + }; + } + return this.defaultReconnectStrategy; + } + #createSocketFactory(options2) { + if (options2?.tls === true) { + const withDefaults2 = { + ...options2, + port: options2?.port ?? 6379, + // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" + // @types/node is... incorrect... + // @ts-expect-error + noDelay: options2?.noDelay ?? true, + // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" + // @types/node is... incorrect... + // @ts-expect-error + keepAlive: options2?.keepAlive ?? true, + // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" + // @types/node is... incorrect... + // @ts-expect-error + keepAliveInitialDelay: options2?.keepAliveInitialDelay ?? 5e3, + timeout: void 0, + onread: void 0, + readable: true, + writable: true + }; + return { + create() { + return node_tls_1.default.connect(withDefaults2); + }, + event: "secureConnect" + }; + } + if (options2 && "path" in options2) { + const withDefaults2 = { + ...options2, + timeout: void 0, + onread: void 0, + readable: true, + writable: true + }; + return { + create() { + return node_net_1.default.createConnection(withDefaults2); + }, + event: "connect" + }; + } + const withDefaults = { + ...options2, + port: options2?.port ?? 6379, + noDelay: options2?.noDelay ?? true, + keepAlive: options2?.keepAlive ?? true, + keepAliveInitialDelay: options2?.keepAliveInitialDelay ?? 5e3, + timeout: void 0, + onread: void 0, + readable: true, + writable: true + }; + return { + create() { + return node_net_1.default.createConnection(withDefaults); + }, + event: "connect" + }; + } + #shouldReconnect(retries, cause) { + const retryIn = this.#reconnectStrategy(retries, cause); + if (retryIn === false) { + this.#isOpen = false; + this.emit("error", cause); + return cause; + } else if (retryIn instanceof Error) { + this.#isOpen = false; + this.emit("error", cause); + return new errors_1.ReconnectStrategyError(retryIn, cause); + } + return retryIn; + } + async connect() { + if (this.#isOpen) { + throw new Error("Socket already opened"); + } + this.#isOpen = true; + return this.#connect(); + } + async #connect() { + let retries = 0; + do { + try { + this.#socket = await this.#createSocket(); + this.emit("connect"); + try { + await this.#initiator(); + } catch (err) { + this.#socket.destroy(); + this.#socket = void 0; + throw err; + } + this.#isReady = true; + this.#socketEpoch++; + this.emit("ready"); + } catch (err) { + const retryIn = this.#shouldReconnect(retries++, err); + if (typeof retryIn !== "number") { + throw retryIn; + } + this.emit("error", err); + await (0, promises_1.setTimeout)(retryIn); + this.emit("reconnecting"); + } + } while (this.#isOpen && !this.#isReady); + } + setMaintenanceTimeout(ms) { + (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Set socket timeout to ${ms}`); + if (this.#maintenanceTimeout === ms) { + (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Socket already set maintenanceCommandTimeout to ${ms}, skipping`); + return; + } + ; + this.#maintenanceTimeout = ms; + if (ms !== void 0) { + this.#socket?.setTimeout(ms); + } else { + this.#socket?.setTimeout(this.#socketTimeout ?? 0); + } + } + async #createSocket() { + const socket = this.#socketFactory.create(); + let onTimeout; + if (this.#connectTimeout !== void 0) { + onTimeout = () => socket.destroy(new errors_1.ConnectionTimeoutError()); + socket.once("timeout", onTimeout); + socket.setTimeout(this.#connectTimeout); + } + if (this.#isSocketUnrefed) { + socket.unref(); + } + await (0, node_events_1.once)(socket, this.#socketFactory.event); + if (onTimeout) { + socket.removeListener("timeout", onTimeout); + } + if (this.#socketTimeout) { + socket.once("timeout", () => { + const error2 = this.#maintenanceTimeout ? new errors_1.SocketTimeoutDuringMaintenanceError(this.#maintenanceTimeout) : new errors_1.SocketTimeoutError(this.#socketTimeout); + socket.destroy(error2); + }); + socket.setTimeout(this.#socketTimeout); + } + socket.once("error", (err) => this.#onSocketError(err)).once("close", (hadError) => { + if (hadError || !this.#isOpen || this.#socket !== socket) + return; + this.#onSocketError(new errors_1.SocketClosedUnexpectedlyError()); + }).on("drain", () => this.emit("drain")).on("data", (data) => this.emit("data", data)); + return socket; + } + #onSocketError(err) { + const wasReady = this.#isReady; + this.#isReady = false; + this.emit("error", err); + if (!wasReady || !this.#isOpen || typeof this.#shouldReconnect(0, err) !== "number") + return; + this.emit("reconnecting"); + this.#connect().catch(() => { + }); + } + write(iterable) { + if (!this.#socket) + return; + this.#socket.cork(); + for (const args of iterable) { + for (const toWrite of args) { + this.#socket.write(toWrite); + } + if (this.#socket.writableNeedDrain) + break; + } + this.#socket.uncork(); + } + async quit(fn) { + if (!this.#isOpen) { + throw new errors_1.ClientClosedError(); + } + this.#isOpen = false; + const reply = await fn(); + this.destroySocket(); + return reply; + } + close() { + if (!this.#isOpen) { + throw new errors_1.ClientClosedError(); + } + this.#isOpen = false; + } + destroy() { + if (!this.#isOpen) { + throw new errors_1.ClientClosedError(); + } + this.#isOpen = false; + this.destroySocket(); + } + destroySocket() { + this.#isReady = false; + if (this.#socket) { + this.#socket.destroy(); + this.#socket = void 0; + } + this.emit("end"); + } + ref() { + this.#isSocketUnrefed = false; + this.#socket?.ref(); + } + unref() { + this.#isSocketUnrefed = true; + this.#socket?.unref(); + } + defaultReconnectStrategy(retries, cause) { + if (cause instanceof errors_1.SocketTimeoutError) { + return false; + } + const jitter = Math.floor(Math.random() * 200); + const delay2 = Math.min(Math.pow(2, retries) * 50, 2e3); + return delay2 + jitter; + } + }; + exports2.default = RedisSocket; + } }); -var require_XTRIM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/XTRIM.js"(exports2) { +var require_token = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/token.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, + exports2.Token = void 0; + var Token = class { + value; + expiresAtMs; + receivedAtMs; + constructor(value, expiresAtMs, receivedAtMs) { + this.value = value; + this.expiresAtMs = expiresAtMs; + this.receivedAtMs = receivedAtMs; + } /** - * Constructs the XTRIM command to trim a stream by length or minimum ID - * - * @param parser - The command parser - * @param key - The stream key - * @param strategy - Trim by maximum length (MAXLEN) or minimum ID (MINID) - * @param threshold - Maximum length or minimum ID threshold - * @param options - Additional options for trimming - * @returns Number of entries removed from the stream - * @see https://redis.io/commands/xtrim/ + * Returns the time-to-live of the token in milliseconds. + * @param now The current time in milliseconds since the Unix epoch. */ - parseCommand(parser3, key, strategy, threshold, options2) { - parser3.push("XTRIM"); - parser3.pushKey(key); - parser3.push(strategy); - if (options2?.strategyModifier) { - parser3.push(options2.strategyModifier); - } - parser3.push(threshold.toString()); - if (options2?.LIMIT) { - parser3.push("LIMIT", options2.LIMIT.toString()); - } - if (options2?.policy) { - parser3.push(options2.policy); + getTtlMs(now) { + if (this.expiresAtMs < now) { + return 0; } - }, - transformReply: void 0 + return this.expiresAtMs - now; + } }; + exports2.Token = Token; } }); -var require_ZADD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZADD.js"(exports2) { +var require_token_manager = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/token-manager.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.pushMembers = void 0; - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { + exports2.TokenManager = exports2.IDPError = void 0; + var token_1 = require_token(); + var IDPError = class extends Error { + message; + isRetryable; + constructor(message, isRetryable) { + super(message); + this.message = message; + this.isRetryable = isRetryable; + this.name = "IDPError"; + } + }; + exports2.IDPError = IDPError; + var TokenManager = class { + identityProvider; + config; + currentToken = null; + refreshTimeout = null; + listener = null; + retryAttempt = 0; + constructor(identityProvider, config2) { + this.identityProvider = identityProvider; + this.config = config2; + if (this.config.expirationRefreshRatio > 1) { + throw new Error("expirationRefreshRatio must be less than or equal to 1"); + } + if (this.config.expirationRefreshRatio < 0) { + throw new Error("expirationRefreshRatio must be greater or equal to 0"); + } + } /** - * Constructs the ZADD command to add one or more members to a sorted set + * Starts the token manager and returns a Disposable that can be used to stop the token manager. * - * @param parser - The command parser - * @param key - The sorted set key - * @param members - One or more members to add with their scores - * @param options - Additional options for adding members - * @returns Number of new members added (or changed members if CH is set) - * @see https://redis.io/commands/zadd/ + * @param listener The listener that will receive token updates. + * @param initialDelayMs The initial delay in milliseconds before the first token refresh. */ - parseCommand(parser3, key, members, options2) { - parser3.push("ZADD"); - parser3.pushKey(key); - if (options2?.condition) { - parser3.push(options2.condition); - } else if (options2?.NX) { - parser3.push("NX"); - } else if (options2?.XX) { - parser3.push("XX"); + start(listener, initialDelayMs = 0) { + if (this.listener) { + this.stop(); } - if (options2?.comparison) { - parser3.push(options2.comparison); - } else if (options2?.LT) { - parser3.push("LT"); - } else if (options2?.GT) { - parser3.push("GT"); + this.listener = listener; + this.retryAttempt = 0; + this.scheduleNextRefresh(initialDelayMs); + return { + dispose: () => this.stop() + }; + } + calculateRetryDelay() { + if (!this.config.retry) + return 0; + const { initialDelayMs, maxDelayMs, backoffMultiplier, jitterPercentage } = this.config.retry; + let delay2 = initialDelayMs * Math.pow(backoffMultiplier, this.retryAttempt - 1); + delay2 = Math.min(delay2, maxDelayMs); + if (jitterPercentage) { + const jitterRange = delay2 * (jitterPercentage / 100); + const jitterAmount = Math.random() * jitterRange - jitterRange / 2; + delay2 += jitterAmount; } - if (options2?.CH) { - parser3.push("CH"); + let result = Math.max(0, Math.floor(delay2)); + return result; + } + shouldRetry(error2) { + if (!this.config.retry) + return false; + const { maxAttempts, isRetryable } = this.config.retry; + if (this.retryAttempt >= maxAttempts) { + return false; } - pushMembers(parser3, members); - }, - transformReply: generic_transformers_1.transformDoubleReply - }; - function pushMembers(parser3, members) { - if (Array.isArray(members)) { - for (const member of members) { - pushMember(parser3, member); + if (isRetryable) { + return isRetryable(error2, this.retryAttempt); } - } else { - pushMember(parser3, members); + return false; } - } - exports2.pushMembers = pushMembers; - function pushMember(parser3, member) { - parser3.push((0, generic_transformers_1.transformDoubleArgument)(member.score), member.value); - } - } -}); -var require_ZADD_INCR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZADD_INCR.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ZADD_1 = require_ZADD(); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { + isRunning() { + return this.listener !== null; + } + async refresh() { + if (!this.listener) { + throw new Error("TokenManager is not running, but refresh was called"); + } + try { + await this.identityProvider.requestToken().then(this.handleNewToken); + this.retryAttempt = 0; + } catch (error2) { + if (this.shouldRetry(error2)) { + this.retryAttempt++; + const retryDelay = this.calculateRetryDelay(); + this.notifyError(`Token refresh failed (attempt ${this.retryAttempt}), retrying in ${retryDelay}ms: ${error2}`, true); + this.scheduleNextRefresh(retryDelay); + } else { + this.notifyError(error2, false); + this.stop(); + } + } + } + handleNewToken = async ({ token: nativeToken, ttlMs }) => { + if (!this.listener) { + throw new Error("TokenManager is not running, but a new token was received"); + } + const token = this.wrapAndSetCurrentToken(nativeToken, ttlMs); + this.listener.onNext(token); + this.scheduleNextRefresh(this.calculateRefreshTime(token)); + }; /** - * Constructs the ZADD command with INCR option to increment the score of a member + * Creates a Token object from a native token and sets it as the current token. + * + * @param nativeToken - The raw token received from the identity provider + * @param ttlMs - Time-to-live in milliseconds for the token + * + * @returns A new Token instance containing the wrapped native token and expiration details * - * @param parser - The command parser - * @param key - The sorted set key - * @param members - Member(s) whose score to increment - * @param options - Additional options for the increment operation - * @returns The new score of the member after increment (null if member does not exist with XX option) - * @see https://redis.io/commands/zadd/ */ - parseCommand(parser3, key, members, options2) { - parser3.push("ZADD"); - parser3.pushKey(key); - if (options2?.condition) { - parser3.push(options2.condition); + wrapAndSetCurrentToken(nativeToken, ttlMs) { + const now = Date.now(); + const token = new token_1.Token(nativeToken, now + ttlMs, now); + this.currentToken = token; + return token; + } + scheduleNextRefresh(delayMs) { + if (this.refreshTimeout) { + clearTimeout(this.refreshTimeout); + this.refreshTimeout = null; } - if (options2?.comparison) { - parser3.push(options2.comparison); + if (delayMs === 0) { + this.refresh(); + } else { + this.refreshTimeout = setTimeout(() => this.refresh(), delayMs); } - if (options2?.CH) { - parser3.push("CH"); + } + /** + * Calculates the time in milliseconds when the token should be refreshed + * based on the token's TTL and the expirationRefreshRatio configuration. + * + * @param token The token to calculate the refresh time for. + * @param now The current time in milliseconds. Defaults to Date.now(). + */ + calculateRefreshTime(token, now = Date.now()) { + const ttlMs = token.getTtlMs(now); + return Math.floor(ttlMs * this.config.expirationRefreshRatio); + } + stop() { + if (this.refreshTimeout) { + clearTimeout(this.refreshTimeout); + this.refreshTimeout = null; } - parser3.push("INCR"); - (0, ZADD_1.pushMembers)(parser3, members); - }, - transformReply: generic_transformers_1.transformNullableDoubleReply + this.listener = null; + this.currentToken = null; + this.retryAttempt = 0; + } + /** + * Returns the current token or null if no token is available. + */ + getCurrentToken() { + return this.currentToken; + } + notifyError(error2, isRetryable) { + const errorMessage = error2 instanceof Error ? error2.message : String(error2); + if (!this.listener) { + throw new Error(`TokenManager is not running but received an error: ${errorMessage}`); + } + this.listener.onError(new IDPError(errorMessage, isRetryable)); + } }; + exports2.TokenManager = TokenManager; } }); -var require_ZCARD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZCARD.js"(exports2) { +var require_credentials_provider = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/credentials-provider.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Constructs the ZCARD command to get the cardinality (number of members) of a sorted set - * - * @param parser - The command parser - * @param key - The sorted set key - * @returns Number of members in the sorted set - * @see https://redis.io/commands/zcard/ - */ - parseCommand(parser3, key) { - parser3.push("ZCARD"); - parser3.pushKey(key); - }, - transformReply: void 0 + exports2.UnableToObtainNewCredentialsError = exports2.CredentialsError = void 0; + var CredentialsError = class extends Error { + constructor(message) { + super(`Re-authentication with latest credentials failed: ${message}`); + this.name = "CredentialsError"; + } }; - } -}); -var require_ZCOUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZCOUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Returns the number of elements in the sorted set with a score between min and max. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param min - Minimum score to count from (inclusive). - * @param max - Maximum score to count to (inclusive). - */ - parseCommand(parser3, key, min, max) { - parser3.push("ZCOUNT"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); - }, - transformReply: void 0 + exports2.CredentialsError = CredentialsError; + var UnableToObtainNewCredentialsError = class extends Error { + constructor(message) { + super(`Unable to obtain new credentials : ${message}`); + this.name = "UnableToObtainNewCredentialsError"; + } }; + exports2.UnableToObtainNewCredentialsError = UnableToObtainNewCredentialsError; } }); -var require_ZDIFF = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZDIFF.js"(exports2) { +var require_authx = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/index.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the difference between the first sorted set and all the successive sorted sets. - * @param parser - The Redis command parser. - * @param keys - Keys of the sorted sets. - */ - parseCommand(parser3, keys) { - parser3.push("ZDIFF"); - parser3.pushKeysLength(keys); - }, - transformReply: void 0 - }; + exports2.Token = exports2.CredentialsError = exports2.UnableToObtainNewCredentialsError = exports2.IDPError = exports2.TokenManager = void 0; + var token_manager_1 = require_token_manager(); + Object.defineProperty(exports2, "TokenManager", { enumerable: true, get: function() { + return token_manager_1.TokenManager; + } }); + Object.defineProperty(exports2, "IDPError", { enumerable: true, get: function() { + return token_manager_1.IDPError; + } }); + var credentials_provider_1 = require_credentials_provider(); + Object.defineProperty(exports2, "UnableToObtainNewCredentialsError", { enumerable: true, get: function() { + return credentials_provider_1.UnableToObtainNewCredentialsError; + } }); + Object.defineProperty(exports2, "CredentialsError", { enumerable: true, get: function() { + return credentials_provider_1.CredentialsError; + } }); + var token_1 = require_token(); + Object.defineProperty(exports2, "Token", { enumerable: true, get: function() { + return token_1.Token; + } }); } }); -var require_ZDIFF_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZDIFF_WITHSCORES.js"(exports2) { +var require_linked_list = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/linked-list.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var ZDIFF_1 = __importDefault(require_ZDIFF()); - exports2.default = { - IS_READ_ONLY: ZDIFF_1.default.IS_READ_ONLY, - /** - * Returns the difference between the first sorted set and all successive sorted sets with their scores. - * @param parser - The Redis command parser. - * @param keys - Keys of the sorted sets. - */ - parseCommand(parser3, keys) { - ZDIFF_1.default.parseCommand(parser3, keys); - parser3.push("WITHSCORES"); - }, - transformReply: generic_transformers_1.transformSortedSetReply + exports2.EmptyAwareSinglyLinkedList = exports2.SinglyLinkedList = exports2.DoublyLinkedList = void 0; + var events_1 = __importDefault(__require2("node:events")); + var DoublyLinkedList = class { + #length = 0; + get length() { + return this.#length; + } + #head; + get head() { + return this.#head; + } + #tail; + get tail() { + return this.#tail; + } + push(value) { + ++this.#length; + if (this.#tail === void 0) { + return this.#head = this.#tail = { + previous: this.#head, + next: void 0, + value + }; + } + return this.#tail = this.#tail.next = { + previous: this.#tail, + next: void 0, + value + }; + } + unshift(value) { + ++this.#length; + if (this.#head === void 0) { + return this.#head = this.#tail = { + previous: void 0, + next: void 0, + value + }; + } + return this.#head = this.#head.previous = { + previous: void 0, + next: this.#head, + value + }; + } + add(value, prepend = false) { + return prepend ? this.unshift(value) : this.push(value); + } + shift() { + if (this.#head === void 0) + return void 0; + --this.#length; + const node = this.#head; + if (node.next) { + node.next.previous = void 0; + this.#head = node.next; + node.next = void 0; + } else { + this.#head = this.#tail = void 0; + } + return node.value; + } + remove(node) { + if (this.#length === 0) + return; + --this.#length; + if (this.#tail === node) { + this.#tail = node.previous; + } + if (this.#head === node) { + this.#head = node.next; + } else { + if (node.previous) { + node.previous.next = node.next; + } + if (node.next) { + node.next.previous = node.previous; + } + } + node.previous = void 0; + node.next = void 0; + } + reset() { + this.#length = 0; + this.#head = this.#tail = void 0; + } + *[Symbol.iterator]() { + let node = this.#head; + while (node !== void 0) { + yield node.value; + node = node.next; + } + } + *nodes() { + let node = this.#head; + while (node) { + const next = node.next; + yield node; + node = next; + } + } }; - } -}); -var require_ZDIFFSTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZDIFFSTORE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Computes the difference between the first and all successive sorted sets and stores it in a new key. - * @param parser - The Redis command parser. - * @param destination - Destination key where the result will be stored. - * @param inputKeys - Keys of the sorted sets to find the difference between. - */ - parseCommand(parser3, destination, inputKeys) { - parser3.push("ZDIFFSTORE"); - parser3.pushKey(destination); - parser3.pushKeysLength(inputKeys); - }, - transformReply: void 0 + exports2.DoublyLinkedList = DoublyLinkedList; + var SinglyLinkedList = class { + #length = 0; + get length() { + return this.#length; + } + #head; + get head() { + return this.#head; + } + #tail; + get tail() { + return this.#tail; + } + push(value) { + ++this.#length; + const node = { + value, + next: void 0, + removed: false + }; + if (this.#head === void 0) { + return this.#head = this.#tail = node; + } + return this.#tail.next = this.#tail = node; + } + remove(node, parent) { + if (node.removed) { + throw new Error("node already removed"); + } + --this.#length; + if (this.#head === node) { + if (this.#tail === node) { + this.#head = this.#tail = void 0; + } else { + this.#head = node.next; + } + } else if (this.#tail === node) { + this.#tail = parent; + parent.next = void 0; + } else { + parent.next = node.next; + } + node.removed = true; + } + shift() { + if (this.#head === void 0) + return void 0; + const node = this.#head; + if (--this.#length === 0) { + this.#head = this.#tail = void 0; + } else { + this.#head = node.next; + } + node.removed = true; + return node.value; + } + reset() { + this.#length = 0; + this.#head = this.#tail = void 0; + } + *[Symbol.iterator]() { + let node = this.#head; + while (node !== void 0) { + yield node.value; + node = node.next; + } + } }; - } -}); -var require_ZINCRBY = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINCRBY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - /** - * Increments the score of a member in a sorted set by the specified increment. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param increment - Value to increment the score by. - * @param member - Member whose score should be incremented. - */ - parseCommand(parser3, key, increment2, member) { - parser3.push("ZINCRBY"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformDoubleArgument)(increment2), member); - }, - transformReply: generic_transformers_1.transformDoubleReply + exports2.SinglyLinkedList = SinglyLinkedList; + var EmptyAwareSinglyLinkedList = class extends SinglyLinkedList { + events = new events_1.default(); + reset() { + const old = this.length; + super.reset(); + if (old !== this.length && this.length === 0) { + this.events.emit("empty"); + } + } + shift() { + const old = this.length; + const ret = super.shift(); + if (old !== this.length && this.length === 0) { + this.events.emit("empty"); + } + return ret; + } + remove(node, parent) { + const old = this.length; + super.remove(node, parent); + if (old !== this.length && this.length === 0) { + this.events.emit("empty"); + } + } }; + exports2.EmptyAwareSinglyLinkedList = EmptyAwareSinglyLinkedList; } }); -var require_ZINTER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTER.js"(exports2) { +var require_encoder = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/RESP/encoder.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseZInterArguments = void 0; - var generic_transformers_1 = require_generic_transformers(); - function parseZInterArguments(parser3, keys, options2) { - (0, generic_transformers_1.parseZKeysArguments)(parser3, keys); - if (options2?.AGGREGATE) { - parser3.push("AGGREGATE", options2.AGGREGATE); + var CRLF2 = "\r\n"; + function encodeCommand(args) { + const toWrite = []; + let strings = "*" + args.length + CRLF2; + for (let i2 = 0; i2 < args.length; i2++) { + const arg = args[i2]; + if (typeof arg === "string") { + strings += "$" + Buffer.byteLength(arg) + CRLF2 + arg + CRLF2; + } else if (arg instanceof Buffer) { + toWrite.push(strings + "$" + arg.length.toString() + CRLF2, arg); + strings = CRLF2; + } else { + throw new TypeError(`"arguments[${i2}]" must be of type "string | Buffer", got ${typeof arg} instead.`); + } } + toWrite.push(strings); + return toWrite; } - exports2.parseZInterArguments = parseZInterArguments; - exports2.default = { - IS_READ_ONLY: true, - /** - * Intersects multiple sorted sets and returns the result as a new sorted set. - * @param parser - The Redis command parser. - * @param keys - Keys of the sorted sets to intersect. - * @param options - Optional parameters for the intersection operation. - */ - parseCommand(parser3, keys, options2) { - parser3.push("ZINTER"); - parseZInterArguments(parser3, keys, options2); - }, - transformReply: void 0 - }; - } -}); -var require_ZINTER_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTER_WITHSCORES.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var ZINTER_1 = __importDefault(require_ZINTER()); - exports2.default = { - IS_READ_ONLY: ZINTER_1.default.IS_READ_ONLY, - /** - * Intersects multiple sorted sets and returns the result with scores. - * @param args - Same parameters as ZINTER command. - */ - parseCommand(...args) { - ZINTER_1.default.parseCommand(...args); - args[0].push("WITHSCORES"); - }, - transformReply: generic_transformers_1.transformSortedSetReply - }; + exports2.default = encodeCommand; } }); -var require_ZINTERCARD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTERCARD.js"(exports2) { +var require_pub_sub = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/pub-sub.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the cardinality of the intersection of multiple sorted sets. - * @param parser - The Redis command parser. - * @param keys - Keys of the sorted sets to intersect. - * @param options - Limit option or options object with limit. - */ - parseCommand(parser3, keys, options2) { - parser3.push("ZINTERCARD"); - parser3.pushKeysLength(keys); - if (typeof options2 === "number") { - parser3.push("LIMIT", options2.toString()); - } else if (options2?.LIMIT) { - parser3.push("LIMIT", options2.LIMIT.toString()); - } - }, - transformReply: void 0 + exports2.PubSub = exports2.PUBSUB_TYPE = void 0; + exports2.PUBSUB_TYPE = { + CHANNELS: "CHANNELS", + PATTERNS: "PATTERNS", + SHARDED: "SHARDED" }; - } -}); -var require_ZINTERSTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZINTERSTORE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ZINTER_1 = require_ZINTER(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Stores the result of intersection of multiple sorted sets in a new sorted set. - * @param parser - The Redis command parser. - * @param destination - Destination key where the result will be stored. - * @param keys - Keys of the sorted sets to intersect. - * @param options - Optional parameters for the intersection operation. - */ - parseCommand(parser3, destination, keys, options2) { - parser3.push("ZINTERSTORE"); - parser3.pushKey(destination); - (0, ZINTER_1.parseZInterArguments)(parser3, keys, options2); + var COMMANDS = { + [exports2.PUBSUB_TYPE.CHANNELS]: { + subscribe: Buffer.from("subscribe"), + unsubscribe: Buffer.from("unsubscribe"), + message: Buffer.from("message") }, - transformReply: void 0 - }; - } -}); -var require_ZLEXCOUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZLEXCOUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Returns the number of elements in the sorted set between the lexicographical range specified by min and max. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param min - Minimum lexicographical value (inclusive). - * @param max - Maximum lexicographical value (inclusive). - */ - parseCommand(parser3, key, min, max) { - parser3.push("ZLEXCOUNT"); - parser3.pushKey(key); - parser3.push(min); - parser3.push(max); + [exports2.PUBSUB_TYPE.PATTERNS]: { + subscribe: Buffer.from("psubscribe"), + unsubscribe: Buffer.from("punsubscribe"), + message: Buffer.from("pmessage") }, - transformReply: void 0 + [exports2.PUBSUB_TYPE.SHARDED]: { + subscribe: Buffer.from("ssubscribe"), + unsubscribe: Buffer.from("sunsubscribe"), + message: Buffer.from("smessage") + } }; - } -}); -var require_ZMSCORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZMSCORE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Returns the scores associated with the specified members in the sorted set stored at key. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param member - One or more members to get scores for. - */ - parseCommand(parser3, key, member) { - parser3.push("ZMSCORE"); - parser3.pushKey(key); - parser3.pushVariadic(member); - }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - return reply.map((0, generic_transformers_1.createTransformNullableDoubleReplyResp2Func)(preserve, typeMapping)); - }, - 3: void 0 + var PubSub = class _PubSub { + static isStatusReply(reply) { + return COMMANDS[exports2.PUBSUB_TYPE.CHANNELS].subscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.CHANNELS].unsubscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.PATTERNS].subscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.PATTERNS].unsubscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.SHARDED].subscribe.equals(reply[0]); } - }; - } -}); -var require_ZPOPMAX_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMAX_COUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes and returns up to count members with the highest scores in the sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param count - Number of members to pop. - */ - parseCommand(parser3, key, count) { - parser3.push("ZPOPMAX"); - parser3.pushKey(key); - parser3.push(count.toString()); - }, - transformReply: generic_transformers_1.transformSortedSetReply - }; - } -}); -var require_ZPOPMAX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMAX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes and returns the member with the highest score in the sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - */ - parseCommand(parser3, key) { - parser3.push("ZPOPMAX"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - if (reply.length === 0) - return null; - return { - value: reply[0], - score: generic_transformers_1.transformDoubleReply[2](reply[1], preserve, typeMapping) - }; - }, - 3: (reply) => { - if (reply.length === 0) - return null; - return { - value: reply[0], - score: reply[1] - }; + static isShardedUnsubscribe(reply) { + return COMMANDS[exports2.PUBSUB_TYPE.SHARDED].unsubscribe.equals(reply[0]); + } + static #channelsArray(channels) { + return Array.isArray(channels) ? channels : [channels]; + } + static #listenersSet(listeners, returnBuffers) { + return returnBuffers ? listeners.buffers : listeners.strings; + } + #subscribing = 0; + #isActive = false; + get isActive() { + return this.#isActive; + } + listeners = { + [exports2.PUBSUB_TYPE.CHANNELS]: /* @__PURE__ */ new Map(), + [exports2.PUBSUB_TYPE.PATTERNS]: /* @__PURE__ */ new Map(), + [exports2.PUBSUB_TYPE.SHARDED]: /* @__PURE__ */ new Map() + }; + subscribe(type, channels, listener, returnBuffers) { + const args = [COMMANDS[type].subscribe], channelsArray = _PubSub.#channelsArray(channels); + for (const channel of channelsArray) { + let channelListeners = this.listeners[type].get(channel); + if (!channelListeners || channelListeners.unsubscribing) { + args.push(channel); + } + } + if (args.length === 1) { + for (const channel of channelsArray) { + _PubSub.#listenersSet(this.listeners[type].get(channel), returnBuffers).add(listener); + } + return; } + this.#isActive = true; + this.#subscribing++; + return { + args, + channelsCounter: args.length - 1, + resolve: () => { + this.#subscribing--; + for (const channel of channelsArray) { + let listeners = this.listeners[type].get(channel); + if (!listeners) { + listeners = { + unsubscribing: false, + buffers: /* @__PURE__ */ new Set(), + strings: /* @__PURE__ */ new Set() + }; + this.listeners[type].set(channel, listeners); + } + _PubSub.#listenersSet(listeners, returnBuffers).add(listener); + } + }, + reject: () => { + this.#subscribing--; + this.#updateIsActive(); + } + }; } - }; - } -}); -var require_ZPOPMIN_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMIN_COUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes and returns up to count members with the lowest scores in the sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param count - Number of members to pop. - */ - parseCommand(parser3, key, count) { - parser3.push("ZPOPMIN"); - parser3.pushKey(key); - parser3.push(count.toString()); - }, - transformReply: generic_transformers_1.transformSortedSetReply - }; - } -}); -var require_ZPOPMIN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZPOPMIN.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ZPOPMAX_1 = __importDefault(require_ZPOPMAX()); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes and returns the member with the lowest score in the sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - */ - parseCommand(parser3, key) { - parser3.push("ZPOPMIN"); - parser3.pushKey(key); - }, - transformReply: ZPOPMAX_1.default.transformReply - }; - } -}); -var require_ZRANDMEMBER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANDMEMBER.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns a random member from a sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - */ - parseCommand(parser3, key) { - parser3.push("ZRANDMEMBER"); - parser3.pushKey(key); - }, - transformReply: void 0 - }; - } -}); -var require_ZRANDMEMBER_COUNT = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANDMEMBER_COUNT.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ZRANDMEMBER_1 = __importDefault(require_ZRANDMEMBER()); - exports2.default = { - IS_READ_ONLY: ZRANDMEMBER_1.default.IS_READ_ONLY, - /** - * Returns one or more random members from a sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param count - Number of members to return. - */ - parseCommand(parser3, key, count) { - ZRANDMEMBER_1.default.parseCommand(parser3, key); - parser3.push(count.toString()); - }, - transformReply: void 0 - }; - } -}); -var require_ZRANDMEMBER_COUNT_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANDMEMBER_COUNT_WITHSCORES.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var ZRANDMEMBER_COUNT_1 = __importDefault(require_ZRANDMEMBER_COUNT()); - exports2.default = { - IS_READ_ONLY: ZRANDMEMBER_COUNT_1.default.IS_READ_ONLY, - /** - * Returns one or more random members with their scores from a sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param count - Number of members to return. - */ - parseCommand(parser3, key, count) { - ZRANDMEMBER_COUNT_1.default.parseCommand(parser3, key, count); - parser3.push("WITHSCORES"); - }, - transformReply: generic_transformers_1.transformSortedSetReply - }; - } -}); -var require_ZRANGE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.zRangeArgument = void 0; - var generic_transformers_1 = require_generic_transformers(); - function zRangeArgument(min, max, options2) { - const args = [ - (0, generic_transformers_1.transformStringDoubleArgument)(min), - (0, generic_transformers_1.transformStringDoubleArgument)(max) - ]; - switch (options2?.BY) { - case "SCORE": - args.push("BYSCORE"); - break; - case "LEX": - args.push("BYLEX"); - break; + extendChannelListeners(type, channel, listeners) { + if (!this.#extendChannelListeners(type, channel, listeners)) + return; + this.#isActive = true; + this.#subscribing++; + return { + args: [ + COMMANDS[type].subscribe, + channel + ], + channelsCounter: 1, + resolve: () => this.#subscribing--, + reject: () => { + this.#subscribing--; + this.#updateIsActive(); + } + }; } - if (options2?.REV) { - args.push("REV"); + #extendChannelListeners(type, channel, listeners) { + const existingListeners = this.listeners[type].get(channel); + if (!existingListeners) { + this.listeners[type].set(channel, listeners); + return true; + } + for (const listener of listeners.buffers) { + existingListeners.buffers.add(listener); + } + for (const listener of listeners.strings) { + existingListeners.strings.add(listener); + } + return false; } - if (options2?.LIMIT) { - args.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + extendTypeListeners(type, listeners) { + const args = [COMMANDS[type].subscribe]; + for (const [channel, channelListeners] of listeners) { + if (this.#extendChannelListeners(type, channel, channelListeners)) { + args.push(channel); + } + } + if (args.length === 1) + return; + this.#isActive = true; + this.#subscribing++; + return { + args, + channelsCounter: args.length - 1, + resolve: () => this.#subscribing--, + reject: () => { + this.#subscribing--; + this.#updateIsActive(); + } + }; + } + unsubscribe(type, channels, listener, returnBuffers) { + const listeners = this.listeners[type]; + if (!channels) { + return this.#unsubscribeCommand( + [COMMANDS[type].unsubscribe], + // cannot use `this.#subscribed` because there might be some `SUBSCRIBE` commands in the queue + // cannot use `this.#subscribed + this.#subscribing` because some `SUBSCRIBE` commands might fail + NaN, + () => listeners.clear() + ); + } + const channelsArray = _PubSub.#channelsArray(channels); + if (!listener) { + return this.#unsubscribeCommand([COMMANDS[type].unsubscribe, ...channelsArray], channelsArray.length, () => { + for (const channel of channelsArray) { + listeners.delete(channel); + } + }); + } + const args = [COMMANDS[type].unsubscribe]; + for (const channel of channelsArray) { + const sets = listeners.get(channel); + if (sets) { + let current, other; + if (returnBuffers) { + current = sets.buffers; + other = sets.strings; + } else { + current = sets.strings; + other = sets.buffers; + } + const currentSize = current.has(listener) ? current.size - 1 : current.size; + if (currentSize !== 0 || other.size !== 0) + continue; + sets.unsubscribing = true; + } + args.push(channel); + } + if (args.length === 1) { + for (const channel of channelsArray) { + _PubSub.#listenersSet(listeners.get(channel), returnBuffers).delete(listener); + } + return; + } + return this.#unsubscribeCommand(args, args.length - 1, () => { + for (const channel of channelsArray) { + const sets = listeners.get(channel); + if (!sets) + continue; + (returnBuffers ? sets.buffers : sets.strings).delete(listener); + if (sets.buffers.size === 0 && sets.strings.size === 0) { + listeners.delete(channel); + } + } + }); + } + #unsubscribeCommand(args, channelsCounter, removeListeners) { + return { + args, + channelsCounter, + resolve: () => { + removeListeners(); + this.#updateIsActive(); + }, + reject: void 0 + }; + } + #updateIsActive() { + this.#isActive = this.listeners[exports2.PUBSUB_TYPE.CHANNELS].size !== 0 || this.listeners[exports2.PUBSUB_TYPE.PATTERNS].size !== 0 || this.listeners[exports2.PUBSUB_TYPE.SHARDED].size !== 0 || this.#subscribing !== 0; + } + reset() { + this.#isActive = false; + this.#subscribing = 0; + } + resubscribe() { + const commands = []; + for (const [type, listeners] of Object.entries(this.listeners)) { + if (!listeners.size) + continue; + this.#isActive = true; + if (type === exports2.PUBSUB_TYPE.SHARDED) { + this.#shardedResubscribe(commands, listeners); + } else { + this.#normalResubscribe(commands, type, listeners); + } + } + return commands; + } + #normalResubscribe(commands, type, listeners) { + this.#subscribing++; + const callback = () => this.#subscribing--; + commands.push({ + args: [ + COMMANDS[type].subscribe, + ...listeners.keys() + ], + channelsCounter: listeners.size, + resolve: callback, + reject: callback + }); + } + #shardedResubscribe(commands, listeners) { + const callback = () => this.#subscribing--; + for (const channel of listeners.keys()) { + this.#subscribing++; + commands.push({ + args: [ + COMMANDS[exports2.PUBSUB_TYPE.SHARDED].subscribe, + channel + ], + channelsCounter: 1, + resolve: callback, + reject: callback + }); + } + } + handleMessageReply(reply) { + if (COMMANDS[exports2.PUBSUB_TYPE.CHANNELS].message.equals(reply[0])) { + this.#emitPubSubMessage(exports2.PUBSUB_TYPE.CHANNELS, reply[2], reply[1]); + return true; + } else if (COMMANDS[exports2.PUBSUB_TYPE.PATTERNS].message.equals(reply[0])) { + this.#emitPubSubMessage(exports2.PUBSUB_TYPE.PATTERNS, reply[3], reply[2], reply[1]); + return true; + } else if (COMMANDS[exports2.PUBSUB_TYPE.SHARDED].message.equals(reply[0])) { + this.#emitPubSubMessage(exports2.PUBSUB_TYPE.SHARDED, reply[2], reply[1]); + return true; + } + return false; + } + removeShardedListeners(channel) { + const listeners = this.listeners[exports2.PUBSUB_TYPE.SHARDED].get(channel); + this.listeners[exports2.PUBSUB_TYPE.SHARDED].delete(channel); + this.#updateIsActive(); + return listeners; + } + removeAllListeners() { + const result = { + [exports2.PUBSUB_TYPE.CHANNELS]: this.listeners[exports2.PUBSUB_TYPE.CHANNELS], + [exports2.PUBSUB_TYPE.PATTERNS]: this.listeners[exports2.PUBSUB_TYPE.PATTERNS], + [exports2.PUBSUB_TYPE.SHARDED]: this.listeners[exports2.PUBSUB_TYPE.SHARDED] + }; + this.#updateIsActive(); + this.listeners[exports2.PUBSUB_TYPE.CHANNELS] = /* @__PURE__ */ new Map(); + this.listeners[exports2.PUBSUB_TYPE.PATTERNS] = /* @__PURE__ */ new Map(); + this.listeners[exports2.PUBSUB_TYPE.SHARDED] = /* @__PURE__ */ new Map(); + return result; + } + #emitPubSubMessage(type, message, channel, pattern) { + const keyString = (pattern ?? channel).toString(), listeners = this.listeners[type].get(keyString); + if (!listeners) + return; + for (const listener of listeners.buffers) { + listener(message, channel); + } + if (!listeners.strings.size) + return; + const channelString = pattern ? channel.toString() : keyString, messageString = channelString === "__redis__:invalidate" ? ( + // https://github.com/redis/redis/pull/7469 + // https://github.com/redis/redis/issues/7463 + message === null ? null : message.map((x3) => x3.toString()) + ) : message.toString(); + for (const listener of listeners.strings) { + listener(messageString, channelString); + } } - return args; - } - exports2.zRangeArgument = zRangeArgument; - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Returns the specified range of elements in the sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param min - Minimum index, score or lexicographical value. - * @param max - Maximum index, score or lexicographical value. - * @param options - Optional parameters for range retrieval (BY, REV, LIMIT). - */ - parseCommand(parser3, key, min, max, options2) { - parser3.push("ZRANGE"); - parser3.pushKey(key); - parser3.pushVariadic(zRangeArgument(min, max, options2)); - }, - transformReply: void 0 }; + exports2.PubSub = PubSub; } }); -var require_ZRANGE_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGE_WITHSCORES.js"(exports2) { +var require_commands_queue = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/commands-queue.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var ZRANGE_1 = __importDefault(require_ZRANGE()); - exports2.default = { - CACHEABLE: ZRANGE_1.default.CACHEABLE, - IS_READ_ONLY: ZRANGE_1.default.IS_READ_ONLY, - /** - * Returns the specified range of elements in the sorted set with their scores. - * @param args - Same parameters as the ZRANGE command. - */ - parseCommand(...args) { - const parser3 = args[0]; - ZRANGE_1.default.parseCommand(...args); - parser3.push("WITHSCORES"); - }, - transformReply: generic_transformers_1.transformSortedSetReply + var linked_list_1 = require_linked_list(); + var encoder_1 = __importDefault(require_encoder()); + var decoder_1 = require_decoder(); + var pub_sub_1 = require_pub_sub(); + var errors_1 = require_errors(); + var enterprise_maintenance_manager_1 = require_enterprise_maintenance_manager(); + var PONG2 = Buffer.from("pong"); + var RESET = Buffer.from("RESET"); + var RESP2_PUSH_TYPE_MAPPING = { + ...decoder_1.PUSH_TYPE_MAPPING, + [decoder_1.RESP_TYPES.SIMPLE_STRING]: Buffer }; - } -}); -var require_ZRANGEBYLEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGEBYLEX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Returns all the elements in the sorted set at key with a lexicographical value between min and max. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param min - Minimum lexicographical value. - * @param max - Maximum lexicographical value. - * @param options - Optional parameters including LIMIT. - */ - parseCommand(parser3, key, min, max, options2) { - parser3.push("ZRANGEBYLEX"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); - if (options2?.LIMIT) { - parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + var RedisCommandsQueue = class _RedisCommandsQueue { + #respVersion; + #maxLength; + #toWrite = new linked_list_1.DoublyLinkedList(); + #waitingForReply = new linked_list_1.EmptyAwareSinglyLinkedList(); + #onShardedChannelMoved; + #chainInExecution; + decoder; + #pubSub = new pub_sub_1.PubSub(); + #pushHandlers = [this.#onPush.bind(this)]; + #maintenanceCommandTimeout; + setMaintenanceCommandTimeout(ms) { + if (this.#maintenanceCommandTimeout === ms) { + (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Queue already set maintenanceCommandTimeout to ${ms}, skipping`); + return; } - }, - transformReply: void 0 - }; - } -}); -var require_ZRANGEBYSCORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGEBYSCORE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Returns all the elements in the sorted set with a score between min and max. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param min - Minimum score. - * @param max - Maximum score. - * @param options - Optional parameters including LIMIT. - */ - parseCommand(parser3, key, min, max, options2) { - parser3.push("ZRANGEBYSCORE"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); - if (options2?.LIMIT) { - parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + ; + (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Setting maintenance command timeout to ${ms}`); + this.#maintenanceCommandTimeout = ms; + if (this.#maintenanceCommandTimeout === void 0) { + (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Queue will keep maintenanceCommandTimeout for exisitng commands, just to be on the safe side. New commands will receive normal timeouts`); + return; } - }, - transformReply: void 0 - }; - } -}); -var require_ZRANGEBYSCORE_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGEBYSCORE_WITHSCORES.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var ZRANGEBYSCORE_1 = __importDefault(require_ZRANGEBYSCORE()); - exports2.default = { - CACHEABLE: ZRANGEBYSCORE_1.default.CACHEABLE, - IS_READ_ONLY: ZRANGEBYSCORE_1.default.IS_READ_ONLY, - /** - * Returns all the elements in the sorted set with a score between min and max, with their scores. - * @param args - Same parameters as the ZRANGEBYSCORE command. - */ - parseCommand(...args) { - const parser3 = args[0]; - ZRANGEBYSCORE_1.default.parseCommand(...args); - parser3.push("WITHSCORES"); - }, - transformReply: generic_transformers_1.transformSortedSetReply - }; - } -}); -var require_ZRANGESTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANGESTORE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Stores the result of a range operation on a sorted set into a new sorted set. - * @param parser - The Redis command parser. - * @param destination - Destination key where the result will be stored. - * @param source - Key of the source sorted set. - * @param min - Minimum index, score or lexicographical value. - * @param max - Maximum index, score or lexicographical value. - * @param options - Optional parameters for the range operation (BY, REV, LIMIT). - */ - parseCommand(parser3, destination, source, min, max, options2) { - parser3.push("ZRANGESTORE"); - parser3.pushKey(destination); - parser3.pushKey(source); - parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); - switch (options2?.BY) { - case "SCORE": - parser3.push("BYSCORE"); - break; - case "LEX": - parser3.push("BYLEX"); - break; + let counter = 0; + const total = this.#toWrite.length; + for (const node of this.#toWrite.nodes()) { + const command2 = node.value; + _RedisCommandsQueue.#removeTimeoutListener(command2); + counter++; + const newTimeout = this.#maintenanceCommandTimeout; + const signal = AbortSignal.timeout(newTimeout); + command2.timeout = { + signal, + listener: () => { + this.#toWrite.remove(node); + command2.reject(new errors_1.CommandTimeoutDuringMaintenanceError(newTimeout)); + }, + originalTimeout: command2.timeout?.originalTimeout + }; + signal.addEventListener("abort", command2.timeout.listener, { once: true }); } - if (options2?.REV) { - parser3.push("REV"); + ; + (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Total of ${counter} of ${total} timeouts reset to ${ms}`); + } + get isPubSubActive() { + return this.#pubSub.isActive; + } + constructor(respVersion, maxLength, onShardedChannelMoved) { + this.#respVersion = respVersion; + this.#maxLength = maxLength; + this.#onShardedChannelMoved = onShardedChannelMoved; + this.decoder = this.#initiateDecoder(); + } + #onReply(reply) { + this.#waitingForReply.shift().resolve(reply); + } + #onErrorReply(err) { + this.#waitingForReply.shift().reject(err); + } + #onPush(push) { + if (this.#pubSub.handleMessageReply(push)) + return true; + const isShardedUnsubscribe = pub_sub_1.PubSub.isShardedUnsubscribe(push); + if (isShardedUnsubscribe && !this.#waitingForReply.length) { + const channel = push[1].toString(); + this.#onShardedChannelMoved(channel, this.#pubSub.removeShardedListeners(channel)); + return true; + } else if (isShardedUnsubscribe || pub_sub_1.PubSub.isStatusReply(push)) { + const head = this.#waitingForReply.head.value; + if (Number.isNaN(head.channelsCounter) && push[2] === 0 || --head.channelsCounter === 0) { + this.#waitingForReply.shift().resolve(); + } + return true; } - if (options2?.LIMIT) { - parser3.push("LIMIT", options2.LIMIT.offset.toString(), options2.LIMIT.count.toString()); + return false; + } + #getTypeMapping() { + return this.#waitingForReply.head.value.typeMapping ?? {}; + } + #initiateDecoder() { + return new decoder_1.Decoder({ + onReply: (reply) => this.#onReply(reply), + onErrorReply: (err) => this.#onErrorReply(err), + //TODO: we can shave off a few cycles by not adding onPush handler at all if CSC is not used + onPush: (push) => { + for (const pushHandler of this.#pushHandlers) { + if (pushHandler(push)) + return; + } + }, + getTypeMapping: () => this.#getTypeMapping() + }); + } + addPushHandler(handler) { + this.#pushHandlers.push(handler); + } + async waitForInflightCommandsToComplete() { + if (this.#waitingForReply.length === 0) { + return; } - }, - transformReply: void 0 + ; + return new Promise((resolve82) => { + this.#waitingForReply.events.on("empty", resolve82); + }); + } + addCommand(args, options2) { + if (this.#maxLength && this.#toWrite.length + this.#waitingForReply.length >= this.#maxLength) { + return Promise.reject(new Error("The queue is full")); + } else if (options2?.abortSignal?.aborted) { + return Promise.reject(new errors_1.AbortError()); + } + return new Promise((resolve82, reject) => { + let node; + const value = { + args, + chainId: options2?.chainId, + abort: void 0, + timeout: void 0, + resolve: resolve82, + reject, + channelsCounter: void 0, + typeMapping: options2?.typeMapping + }; + const timeout = this.#maintenanceCommandTimeout ?? options2?.timeout; + const wasInMaintenance = this.#maintenanceCommandTimeout !== void 0; + if (timeout) { + const signal2 = AbortSignal.timeout(timeout); + value.timeout = { + signal: signal2, + listener: () => { + this.#toWrite.remove(node); + value.reject(wasInMaintenance ? new errors_1.CommandTimeoutDuringMaintenanceError(timeout) : new errors_1.TimeoutError()); + }, + originalTimeout: options2?.timeout + }; + signal2.addEventListener("abort", value.timeout.listener, { once: true }); + } + const signal = options2?.abortSignal; + if (signal) { + value.abort = { + signal, + listener: () => { + this.#toWrite.remove(node); + value.reject(new errors_1.AbortError()); + } + }; + signal.addEventListener("abort", value.abort.listener, { once: true }); + } + node = this.#toWrite.add(value, options2?.asap); + }); + } + #addPubSubCommand(command2, asap = false, chainId) { + return new Promise((resolve82, reject) => { + this.#toWrite.add({ + args: command2.args, + chainId, + abort: void 0, + timeout: void 0, + resolve() { + command2.resolve(); + resolve82(); + }, + reject(err) { + command2.reject?.(); + reject(err); + }, + channelsCounter: command2.channelsCounter, + typeMapping: decoder_1.PUSH_TYPE_MAPPING + }, asap); + }); + } + #setupPubSubHandler() { + if (this.#respVersion !== 2) + return; + this.decoder.onReply = (reply) => { + if (Array.isArray(reply)) { + if (this.#onPush(reply)) + return; + if (PONG2.equals(reply[0])) { + const { resolve: resolve82, typeMapping } = this.#waitingForReply.shift(), buffer = reply[1].length === 0 ? reply[0] : reply[1]; + resolve82(typeMapping?.[decoder_1.RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); + return; + } + } + return this.#onReply(reply); + }; + this.decoder.getTypeMapping = () => RESP2_PUSH_TYPE_MAPPING; + } + subscribe(type, channels, listener, returnBuffers) { + const command2 = this.#pubSub.subscribe(type, channels, listener, returnBuffers); + if (!command2) + return; + this.#setupPubSubHandler(); + return this.#addPubSubCommand(command2); + } + #resetDecoderCallbacks() { + this.decoder.onReply = (reply) => this.#onReply(reply); + this.decoder.getTypeMapping = () => this.#getTypeMapping(); + } + unsubscribe(type, channels, listener, returnBuffers) { + const command2 = this.#pubSub.unsubscribe(type, channels, listener, returnBuffers); + if (!command2) + return; + if (command2 && this.#respVersion === 2) { + const { resolve: resolve82 } = command2; + command2.resolve = () => { + if (!this.#pubSub.isActive) { + this.#resetDecoderCallbacks(); + } + resolve82(); + }; + } + return this.#addPubSubCommand(command2); + } + removeAllPubSubListeners() { + return this.#pubSub.removeAllListeners(); + } + resubscribe(chainId) { + const commands = this.#pubSub.resubscribe(); + if (!commands.length) + return; + this.#setupPubSubHandler(); + return Promise.all(commands.map((command2) => this.#addPubSubCommand(command2, true, chainId))); + } + extendPubSubChannelListeners(type, channel, listeners) { + const command2 = this.#pubSub.extendChannelListeners(type, channel, listeners); + if (!command2) + return; + this.#setupPubSubHandler(); + return this.#addPubSubCommand(command2); + } + extendPubSubListeners(type, listeners) { + const command2 = this.#pubSub.extendTypeListeners(type, listeners); + if (!command2) + return; + this.#setupPubSubHandler(); + return this.#addPubSubCommand(command2); + } + getPubSubListeners(type) { + return this.#pubSub.listeners[type]; + } + monitor(callback, options2) { + return new Promise((resolve82, reject) => { + const typeMapping = options2?.typeMapping ?? {}; + this.#toWrite.add({ + args: ["MONITOR"], + chainId: options2?.chainId, + abort: void 0, + timeout: void 0, + // using `resolve` instead of using `.then`/`await` to make sure it'll be called before processing the next reply + resolve: () => { + if (this.#resetFallbackOnReply) { + this.#resetFallbackOnReply = callback; + } else { + this.decoder.onReply = callback; + } + this.decoder.getTypeMapping = () => typeMapping; + resolve82(); + }, + reject, + channelsCounter: void 0, + typeMapping + }, options2?.asap); + }); + } + resetDecoder() { + this.#resetDecoderCallbacks(); + this.decoder.reset(); + } + #resetFallbackOnReply; + async reset(chainId, typeMapping) { + return new Promise((resolve82, reject) => { + this.#resetFallbackOnReply = this.decoder.onReply; + this.decoder.onReply = (reply) => { + if (typeof reply === "string" && reply === "RESET" || reply instanceof Buffer && RESET.equals(reply)) { + this.#resetDecoderCallbacks(); + this.#resetFallbackOnReply = void 0; + this.#pubSub.reset(); + this.#waitingForReply.shift().resolve(reply); + return; + } + this.#resetFallbackOnReply(reply); + }; + this.#toWrite.push({ + args: ["RESET"], + chainId, + abort: void 0, + timeout: void 0, + resolve: resolve82, + reject, + channelsCounter: void 0, + typeMapping + }); + }); + } + isWaitingToWrite() { + return this.#toWrite.length > 0; + } + *commandsToWrite() { + let toSend = this.#toWrite.shift(); + while (toSend) { + let encoded; + try { + encoded = (0, encoder_1.default)(toSend.args); + } catch (err) { + toSend.reject(err); + toSend = this.#toWrite.shift(); + continue; + } + toSend.args = void 0; + if (toSend.abort) { + _RedisCommandsQueue.#removeAbortListener(toSend); + toSend.abort = void 0; + } + if (toSend.timeout) { + _RedisCommandsQueue.#removeTimeoutListener(toSend); + toSend.timeout = void 0; + } + this.#chainInExecution = toSend.chainId; + toSend.chainId = void 0; + this.#waitingForReply.push(toSend); + yield encoded; + toSend = this.#toWrite.shift(); + } + } + #flushWaitingForReply(err) { + for (const node of this.#waitingForReply) { + node.reject(err); + } + this.#waitingForReply.reset(); + } + static #removeAbortListener(command2) { + command2.abort.signal.removeEventListener("abort", command2.abort.listener); + } + static #removeTimeoutListener(command2) { + command2.timeout?.signal.removeEventListener("abort", command2.timeout.listener); + } + static #flushToWrite(toBeSent, err) { + if (toBeSent.abort) { + _RedisCommandsQueue.#removeAbortListener(toBeSent); + } + if (toBeSent.timeout) { + _RedisCommandsQueue.#removeTimeoutListener(toBeSent); + } + toBeSent.reject(err); + } + flushWaitingForReply(err) { + this.resetDecoder(); + this.#pubSub.reset(); + this.#flushWaitingForReply(err); + if (!this.#chainInExecution) + return; + while (this.#toWrite.head?.value.chainId === this.#chainInExecution) { + _RedisCommandsQueue.#flushToWrite(this.#toWrite.shift(), err); + } + this.#chainInExecution = void 0; + } + flushAll(err) { + this.resetDecoder(); + this.#pubSub.reset(); + this.#flushWaitingForReply(err); + for (const node of this.#toWrite) { + _RedisCommandsQueue.#flushToWrite(node, err); + } + this.#toWrite.reset(); + } + isEmpty() { + return this.#toWrite.length === 0 && this.#waitingForReply.length === 0; + } }; + exports2.default = RedisCommandsQueue; } }); -var require_ZREMRANGEBYSCORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREMRANGEBYSCORE.js"(exports2) { +var require_commander = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commander.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes all elements in the sorted set with scores between min and max. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param min - Minimum score. - * @param max - Maximum score. - */ - parseCommand(parser3, key, min, max) { - parser3.push("ZREMRANGEBYSCORE"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); - }, - transformReply: void 0 - }; + exports2.scriptArgumentsPrefix = exports2.functionArgumentsPrefix = exports2.getTransformReply = exports2.attachConfig = void 0; + function throwResp3SearchModuleUnstableError() { + throw new Error("Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance"); + } + function attachConfig({ BaseClass, commands, createCommand, createModuleCommand, createFunctionCommand, createScriptCommand, config: config2 }) { + const RESP = config2?.RESP ?? 2, Class2 = class extends BaseClass { + }; + for (const [name, command2] of Object.entries(commands)) { + if (config2?.RESP == 3 && command2.unstableResp3 && !config2.unstableResp3) { + Class2.prototype[name] = throwResp3SearchModuleUnstableError; + } else { + Class2.prototype[name] = createCommand(command2, RESP); + } + } + if (config2?.modules) { + for (const [moduleName, module15] of Object.entries(config2.modules)) { + const fns = /* @__PURE__ */ Object.create(null); + for (const [name, command2] of Object.entries(module15)) { + if (config2.RESP == 3 && command2.unstableResp3 && !config2.unstableResp3) { + fns[name] = throwResp3SearchModuleUnstableError; + } else { + fns[name] = createModuleCommand(command2, RESP); + } + } + attachNamespace(Class2.prototype, moduleName, fns); + } + } + if (config2?.functions) { + for (const [library, commands2] of Object.entries(config2.functions)) { + const fns = /* @__PURE__ */ Object.create(null); + for (const [name, command2] of Object.entries(commands2)) { + fns[name] = createFunctionCommand(name, command2, RESP); + } + attachNamespace(Class2.prototype, library, fns); + } + } + if (config2?.scripts) { + for (const [name, script] of Object.entries(config2.scripts)) { + Class2.prototype[name] = createScriptCommand(script, RESP); + } + } + return Class2; + } + exports2.attachConfig = attachConfig; + function attachNamespace(prototype, name, fns) { + Object.defineProperty(prototype, name, { + get() { + const value = Object.create(fns); + value._self = this; + Object.defineProperty(this, name, { value }); + return value; + } + }); + } + function getTransformReply(command2, resp) { + switch (typeof command2.transformReply) { + case "function": + return command2.transformReply; + case "object": + return command2.transformReply[resp]; + } + } + exports2.getTransformReply = getTransformReply; + function functionArgumentsPrefix(name, fn) { + const prefix = [ + fn.IS_READ_ONLY ? "FCALL_RO" : "FCALL", + name + ]; + if (fn.NUMBER_OF_KEYS !== void 0) { + prefix.push(fn.NUMBER_OF_KEYS.toString()); + } + return prefix; + } + exports2.functionArgumentsPrefix = functionArgumentsPrefix; + function scriptArgumentsPrefix(script) { + const prefix = [ + script.IS_READ_ONLY ? "EVALSHA_RO" : "EVALSHA", + script.SHA1 + ]; + if (script.NUMBER_OF_KEYS !== void 0) { + prefix.push(script.NUMBER_OF_KEYS.toString()); + } + return prefix; + } + exports2.scriptArgumentsPrefix = scriptArgumentsPrefix; } }); -var require_ZRANK = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANK.js"(exports2) { +var require_multi_command = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/multi-command.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, - /** - * Returns the rank of a member in the sorted set, with scores ordered from low to high. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param member - Member to get the rank for. - */ - parseCommand(parser3, key, member) { - parser3.push("ZRANK"); - parser3.pushKey(key); - parser3.push(member); - }, - transformReply: void 0 + var errors_1 = require_errors(); + var RedisMultiCommand = class { + typeMapping; + constructor(typeMapping) { + this.typeMapping = typeMapping; + } + queue = []; + scriptsInUse = /* @__PURE__ */ new Set(); + addCommand(args, transformReply) { + this.queue.push({ + args, + transformReply + }); + } + addScript(script, args, transformReply) { + const redisArgs = []; + redisArgs.preserve = args.preserve; + if (this.scriptsInUse.has(script.SHA1)) { + redisArgs.push("EVALSHA", script.SHA1); + } else { + this.scriptsInUse.add(script.SHA1); + redisArgs.push("EVAL", script.SCRIPT); + } + if (script.NUMBER_OF_KEYS !== void 0) { + redisArgs.push(script.NUMBER_OF_KEYS.toString()); + } + redisArgs.push(...args); + this.addCommand(redisArgs, transformReply); + } + transformReplies(rawReplies) { + const errorIndexes = [], replies = rawReplies.map((reply, i2) => { + if (reply instanceof errors_1.ErrorReply) { + errorIndexes.push(i2); + return reply; + } + const { transformReply, args } = this.queue[i2]; + return transformReply ? transformReply(reply, args.preserve, this.typeMapping) : reply; + }); + if (errorIndexes.length) + throw new errors_1.MultiErrorReply(replies, errorIndexes); + return replies; + } }; + exports2.default = RedisMultiCommand; } }); -var require_ZRANK_WITHSCORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZRANK_WITHSCORE.js"(exports2) { +var require_multi_command2 = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/multi-command.js"(exports2) { "use strict"; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - var ZRANK_1 = __importDefault(require_ZRANK()); - exports2.default = { - CACHEABLE: ZRANK_1.default.CACHEABLE, - IS_READ_ONLY: ZRANK_1.default.IS_READ_ONLY, - /** - * Returns the rank of a member in the sorted set with its score. - * @param args - Same parameters as the ZRANK command. - */ - parseCommand(...args) { - const parser3 = args[0]; - ZRANK_1.default.parseCommand(...args); - parser3.push("WITHSCORE"); - }, - transformReply: { - 2: (reply) => { - if (reply === null) - return null; - return { - rank: reply[0], - score: Number(reply[1]) - }; - }, - 3: (reply) => { - if (reply === null) - return null; - return { - rank: reply[0], - score: reply[1] - }; - } + var commands_1 = __importDefault(require_commands()); + var multi_command_1 = __importDefault(require_multi_command()); + var commander_1 = require_commander(); + var parser_1 = require_parser(); + var RedisClientMultiCommand = class _RedisClientMultiCommand { + static #createCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + return this.addCommand(redisArgs, transformReply); + }; + } + static #createModuleCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + return this._self.addCommand(redisArgs, transformReply); + }; + } + static #createFunctionCommand(name, fn, resp) { + const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); + const transformReply = (0, commander_1.getTransformReply)(fn, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + fn.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + return this._self.addCommand(redisArgs, transformReply); + }; + } + static #createScriptCommand(script, resp) { + const transformReply = (0, commander_1.getTransformReply)(script, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + script.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + return this.#addScript(script, redisArgs, transformReply); + }; + } + static extend(config2) { + return (0, commander_1.attachConfig)({ + BaseClass: _RedisClientMultiCommand, + commands: commands_1.default, + createCommand: _RedisClientMultiCommand.#createCommand, + createModuleCommand: _RedisClientMultiCommand.#createModuleCommand, + createFunctionCommand: _RedisClientMultiCommand.#createFunctionCommand, + createScriptCommand: _RedisClientMultiCommand.#createScriptCommand, + config: config2 + }); + } + #multi; + #executeMulti; + #executePipeline; + #selectedDB; + constructor(executeMulti, executePipeline, typeMapping) { + this.#multi = new multi_command_1.default(typeMapping); + this.#executeMulti = executeMulti; + this.#executePipeline = executePipeline; + } + SELECT(db2, transformReply) { + this.#selectedDB = db2; + this.#multi.addCommand(["SELECT", db2.toString()], transformReply); + return this; + } + select = this.SELECT; + addCommand(args, transformReply) { + this.#multi.addCommand(args, transformReply); + return this; + } + #addScript(script, args, transformReply) { + this.#multi.addScript(script, args, transformReply); + return this; + } + async exec(execAsPipeline = false) { + if (execAsPipeline) + return this.execAsPipeline(); + return this.#multi.transformReplies(await this.#executeMulti(this.#multi.queue, this.#selectedDB)); + } + EXEC = this.exec; + execTyped(execAsPipeline = false) { + return this.exec(execAsPipeline); + } + async execAsPipeline() { + if (this.#multi.queue.length === 0) + return []; + return this.#multi.transformReplies(await this.#executePipeline(this.#multi.queue, this.#selectedDB)); + } + execAsPipelineTyped() { + return this.execAsPipeline(); } }; + exports2.default = RedisClientMultiCommand; } }); -var require_ZREM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREM.js"(exports2) { +var require_legacy_mode = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/legacy-mode.js"(exports2) { "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes the specified members from the sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param member - One or more members to remove. - */ - parseCommand(parser3, key, member) { - parser3.push("ZREM"); - parser3.pushKey(key); - parser3.pushVariadic(member); - }, - transformReply: void 0 + exports2.RedisLegacyClient = void 0; + var commander_1 = require_commander(); + var commands_1 = __importDefault(require_commands()); + var multi_command_1 = __importDefault(require_multi_command()); + var RedisLegacyClient = class _RedisLegacyClient { + static #transformArguments(redisArgs, args) { + let callback; + if (typeof args[args.length - 1] === "function") { + callback = args.pop(); + } + _RedisLegacyClient.pushArguments(redisArgs, args); + return callback; + } + static pushArguments(redisArgs, args) { + for (let i2 = 0; i2 < args.length; ++i2) { + const arg = args[i2]; + if (Array.isArray(arg)) { + _RedisLegacyClient.pushArguments(redisArgs, arg); + } else { + redisArgs.push(typeof arg === "number" || arg instanceof Date ? arg.toString() : arg); + } + } + } + static getTransformReply(command2, resp) { + return command2.TRANSFORM_LEGACY_REPLY ? (0, commander_1.getTransformReply)(command2, resp) : void 0; + } + static #createCommand(name, command2, resp) { + const transformReply = _RedisLegacyClient.getTransformReply(command2, resp); + return function(...args) { + const redisArgs = [name], callback = _RedisLegacyClient.#transformArguments(redisArgs, args), promise = this.#client.sendCommand(redisArgs); + if (!callback) { + promise.catch((err) => this.#client.emit("error", err)); + return; + } + promise.then((reply) => callback(null, transformReply ? transformReply(reply) : reply)).catch((err) => callback(err)); + }; + } + #client; + #Multi; + constructor(client) { + this.#client = client; + const RESP = client.options?.RESP ?? 2; + for (const [name, command2] of Object.entries(commands_1.default)) { + this[name] = _RedisLegacyClient.#createCommand(name, command2, RESP); + } + this.#Multi = LegacyMultiCommand.factory(RESP); + } + sendCommand(...args) { + const redisArgs = [], callback = _RedisLegacyClient.#transformArguments(redisArgs, args), promise = this.#client.sendCommand(redisArgs); + if (!callback) { + promise.catch((err) => this.#client.emit("error", err)); + return; + } + promise.then((reply) => callback(null, reply)).catch((err) => callback(err)); + } + multi() { + return this.#Multi(this.#client); + } + }; + exports2.RedisLegacyClient = RedisLegacyClient; + var LegacyMultiCommand = class _LegacyMultiCommand { + static #createCommand(name, command2, resp) { + const transformReply = RedisLegacyClient.getTransformReply(command2, resp); + return function(...args) { + const redisArgs = [name]; + RedisLegacyClient.pushArguments(redisArgs, args); + this.#multi.addCommand(redisArgs, transformReply); + return this; + }; + } + static factory(resp) { + const Multi = class extends _LegacyMultiCommand { + }; + for (const [name, command2] of Object.entries(commands_1.default)) { + Multi.prototype[name] = _LegacyMultiCommand.#createCommand(name, command2, resp); + } + return (client) => { + return new Multi(client); + }; + } + #multi = new multi_command_1.default(); + #client; + constructor(client) { + this.#client = client; + } + sendCommand(...args) { + const redisArgs = []; + RedisLegacyClient.pushArguments(redisArgs, args); + this.#multi.addCommand(redisArgs); + return this; + } + exec(cb) { + const promise = this.#client._executeMulti(this.#multi.queue); + if (!cb) { + promise.catch((err) => this.#client.emit("error", err)); + return; + } + promise.then((results) => cb(null, this.#multi.transformReplies(results))).catch((err) => cb?.(err)); + } }; } }); -var require_ZREMRANGEBYLEX = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREMRANGEBYLEX.js"(exports2) { +var require_cache = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/cache.js"(exports2) { "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, + exports2.PooledNoRedirectClientSideCache = exports2.BasicPooledClientSideCache = exports2.PooledClientSideCacheProvider = exports2.BasicClientSideCache = exports2.ClientSideCacheProvider = exports2.CacheStats = void 0; + var stream_1 = __require2("node:stream"); + var CacheStats = class _CacheStats { + hitCount; + missCount; + loadSuccessCount; + loadFailureCount; + totalLoadTime; + evictionCount; /** - * Removes all elements in the sorted set with lexicographical values between min and max. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param min - Minimum lexicographical value. - * @param max - Maximum lexicographical value. + * Creates a new CacheStats instance with the specified statistics. */ - parseCommand(parser3, key, min, max) { - parser3.push("ZREMRANGEBYLEX"); - parser3.pushKey(key); - parser3.push((0, generic_transformers_1.transformStringDoubleArgument)(min), (0, generic_transformers_1.transformStringDoubleArgument)(max)); - }, - transformReply: void 0 - }; - } -}); -var require_ZREMRANGEBYRANK = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREMRANGEBYRANK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, + constructor(hitCount, missCount, loadSuccessCount, loadFailureCount, totalLoadTime, evictionCount) { + this.hitCount = hitCount; + this.missCount = missCount; + this.loadSuccessCount = loadSuccessCount; + this.loadFailureCount = loadFailureCount; + this.totalLoadTime = totalLoadTime; + this.evictionCount = evictionCount; + if (hitCount < 0 || missCount < 0 || loadSuccessCount < 0 || loadFailureCount < 0 || totalLoadTime < 0 || evictionCount < 0) { + throw new Error("All statistics values must be non-negative"); + } + } /** - * Removes all elements in the sorted set with rank between start and stop. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param start - Minimum rank (starting from 0). - * @param stop - Maximum rank. + * Creates a new CacheStats instance with the specified statistics. + * + * @param hitCount - Number of cache hits + * @param missCount - Number of cache misses + * @param loadSuccessCount - Number of successful cache loads + * @param loadFailureCount - Number of failed cache loads + * @param totalLoadTime - Total load time in milliseconds + * @param evictionCount - Number of cache evictions */ - parseCommand(parser3, key, start, stop) { - parser3.push("ZREMRANGEBYRANK"); - parser3.pushKey(key); - parser3.push(start.toString(), stop.toString()); - }, - transformReply: void 0 - }; - } -}); -var require_ZREVRANK = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZREVRANK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + static of(hitCount = 0, missCount = 0, loadSuccessCount = 0, loadFailureCount = 0, totalLoadTime = 0, evictionCount = 0) { + return new _CacheStats(hitCount, missCount, loadSuccessCount, loadFailureCount, totalLoadTime, evictionCount); + } /** - * Returns the rank of a member in the sorted set, with scores ordered from high to low. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param member - Member to get the rank for. + * Returns a statistics instance where no cache events have been recorded. + * + * @returns An empty statistics instance */ - parseCommand(parser3, key, member) { - parser3.push("ZREVRANK"); - parser3.pushKey(key); - parser3.push(member); - }, - transformReply: void 0 - }; - } -}); -var require_ZSCAN = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZSCAN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var SCAN_1 = require_SCAN(); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, + static empty() { + return _CacheStats.EMPTY_STATS; + } /** - * Incrementally iterates over a sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param cursor - Cursor position to start the scan from. - * @param options - Optional scan parameters (COUNT, MATCH, TYPE). + * An empty stats instance with all counters set to zero. */ - parseCommand(parser3, key, cursor, options2) { - parser3.push("ZSCAN"); - parser3.pushKey(key); - (0, SCAN_1.parseScanArguments)(parser3, cursor, options2); - }, - transformReply([cursor, rawMembers]) { - return { - cursor, - members: generic_transformers_1.transformSortedSetReply[2](rawMembers) - }; - } - }; - } -}); -var require_ZSCORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZSCORE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - CACHEABLE: true, - IS_READ_ONLY: true, + static EMPTY_STATS = new _CacheStats(0, 0, 0, 0, 0, 0); /** - * Returns the score of a member in a sorted set. - * @param parser - The Redis command parser. - * @param key - Key of the sorted set. - * @param member - Member to get the score for. - */ - parseCommand(parser3, key, member) { - parser3.push("ZSCORE"); - parser3.pushKey(key); - parser3.push(member); - }, - transformReply: generic_transformers_1.transformNullableDoubleReply - }; - } -}); -var require_ZUNION = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZUNION.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, + * Returns the total number of times cache lookup methods have returned + * either a cached or uncached value. + * + * @returns Total number of requests (hits + misses) + */ + requestCount() { + return this.hitCount + this.missCount; + } /** - * Returns the union of multiple sorted sets. - * @param parser - The Redis command parser. - * @param keys - Keys of the sorted sets to combine. - * @param options - Optional parameters for the union operation. + * Returns the hit rate of the cache. + * This is defined as hitCount / requestCount, or 1.0 when requestCount is 0. + * + * @returns The ratio of cache requests that were hits (between 0.0 and 1.0) */ - parseCommand(parser3, keys, options2) { - parser3.push("ZUNION"); - (0, generic_transformers_1.parseZKeysArguments)(parser3, keys); - if (options2?.AGGREGATE) { - parser3.push("AGGREGATE", options2.AGGREGATE); - } - }, - transformReply: void 0 - }; - } -}); -var require_ZUNION_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZUNION_WITHSCORES.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var ZUNION_1 = __importDefault(require_ZUNION()); - exports2.default = { - IS_READ_ONLY: ZUNION_1.default.IS_READ_ONLY, + hitRate() { + const requestCount = this.requestCount(); + return requestCount === 0 ? 1 : this.hitCount / requestCount; + } /** - * Returns the union of multiple sorted sets with their scores. - * @param args - Same parameters as the ZUNION command. + * Returns the miss rate of the cache. + * This is defined as missCount / requestCount, or 0.0 when requestCount is 0. + * + * @returns The ratio of cache requests that were misses (between 0.0 and 1.0) */ - parseCommand(...args) { - const parser3 = args[0]; - ZUNION_1.default.parseCommand(...args); - parser3.push("WITHSCORES"); - }, - transformReply: generic_transformers_1.transformSortedSetReply - }; - } -}); -var require_ZUNIONSTORE = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/ZUNIONSTORE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, + missRate() { + const requestCount = this.requestCount(); + return requestCount === 0 ? 0 : this.missCount / requestCount; + } /** - * Stores the union of multiple sorted sets in a new sorted set. - * @param parser - The Redis command parser. - * @param destination - Destination key where the result will be stored. - * @param keys - Keys of the sorted sets to combine. - * @param options - Optional parameters for the union operation. - */ - parseCommand(parser3, destination, keys, options2) { - parser3.push("ZUNIONSTORE"); - parser3.pushKey(destination); - (0, generic_transformers_1.parseZKeysArguments)(parser3, keys); - if (options2?.AGGREGATE) { - parser3.push("AGGREGATE", options2.AGGREGATE); - } - }, - transformReply: void 0 - }; - } -}); -var require_VADD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { + * Returns the total number of load operations (successful + failed). + * + * @returns Total number of load operations + */ + loadCount() { + return this.loadSuccessCount + this.loadFailureCount; + } /** - * Add a new element into the vector set specified by key + * Returns the ratio of cache loading attempts that failed. + * This is defined as loadFailureCount / loadCount, or 0.0 when loadCount is 0. * - * @param parser - The command parser - * @param key - The name of the key that will hold the vector set data - * @param vector - The vector data as array of numbers - * @param element - The name of the element being added to the vector set - * @param options - Optional parameters for vector addition - * @see https://redis.io/commands/vadd/ + * @returns Ratio of load operations that failed (between 0.0 and 1.0) */ - parseCommand(parser3, key, vector, element, options2) { - parser3.push("VADD"); - parser3.pushKey(key); - if (options2?.REDUCE !== void 0) { - parser3.push("REDUCE", options2.REDUCE.toString()); - } - parser3.push("VALUES", vector.length.toString()); - for (const value of vector) { - parser3.push((0, generic_transformers_1.transformDoubleArgument)(value)); - } - parser3.push(element); - if (options2?.CAS) { - parser3.push("CAS"); - } - options2?.QUANT && parser3.push(options2.QUANT); - if (options2?.EF !== void 0) { - parser3.push("EF", options2.EF.toString()); - } - if (options2?.SETATTR) { - parser3.push("SETATTR", JSON.stringify(options2.SETATTR)); - } - if (options2?.M !== void 0) { - parser3.push("M", options2.M.toString()); - } - }, - transformReply: generic_transformers_1.transformBooleanReply - }; - } -}); -var require_VCARD = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VCARD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, + loadFailureRate() { + const loadCount = this.loadCount(); + return loadCount === 0 ? 0 : this.loadFailureCount / loadCount; + } /** - * Retrieve the number of elements in a vector set + * Returns the average time spent loading new values, in milliseconds. + * This is defined as totalLoadTime / loadCount, or 0.0 when loadCount is 0. * - * @param parser - The command parser - * @param key - The key of the vector set - * @see https://redis.io/commands/vcard/ + * @returns Average load time in milliseconds */ - parseCommand(parser3, key) { - parser3.push("VCARD"); - parser3.pushKey(key); - }, - transformReply: void 0 - }; - } -}); -var require_VDIM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VDIM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, + averageLoadPenalty() { + const loadCount = this.loadCount(); + return loadCount === 0 ? 0 : this.totalLoadTime / loadCount; + } /** - * Retrieve the dimension of the vectors in a vector set - * - * @param parser - The command parser - * @param key - The key of the vector set - * @see https://redis.io/commands/vdim/ - */ - parseCommand(parser3, key) { - parser3.push("VDIM"); - parser3.pushKey(key); - }, - transformReply: void 0 - }; - } -}); -var require_VEMB = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VEMB.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, + * Returns a new CacheStats representing the difference between this CacheStats + * and another. Negative values are rounded up to zero. + * + * @param other - The statistics to subtract from this instance + * @returns The difference between this instance and other + */ + minus(other) { + return _CacheStats.of(Math.max(0, this.hitCount - other.hitCount), Math.max(0, this.missCount - other.missCount), Math.max(0, this.loadSuccessCount - other.loadSuccessCount), Math.max(0, this.loadFailureCount - other.loadFailureCount), Math.max(0, this.totalLoadTime - other.totalLoadTime), Math.max(0, this.evictionCount - other.evictionCount)); + } /** - * Retrieve the approximate vector associated with a vector set element + * Returns a new CacheStats representing the sum of this CacheStats and another. * - * @param parser - The command parser - * @param key - The key of the vector set - * @param element - The name of the element to retrieve the vector for - * @see https://redis.io/commands/vemb/ + * @param other - The statistics to add to this instance + * @returns The sum of this instance and other */ - parseCommand(parser3, key, element) { - parser3.push("VEMB"); - parser3.pushKey(key); - parser3.push(element); - }, - transformReply: generic_transformers_1.transformDoubleArrayReply - }; - } -}); -var require_VEMB_RAW = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VEMB_RAW.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; + plus(other) { + return _CacheStats.of(this.hitCount + other.hitCount, this.missCount + other.missCount, this.loadSuccessCount + other.loadSuccessCount, this.loadFailureCount + other.loadFailureCount, this.totalLoadTime + other.totalLoadTime, this.evictionCount + other.evictionCount); + } }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var VEMB_1 = __importDefault(require_VEMB()); - var transformRawVembReply = { - 2: (reply) => { - return { - quantization: reply[0], - raw: reply[1], - l2Norm: generic_transformers_1.transformDoubleReply[2](reply[2]), - ...reply[3] !== void 0 && { quantizationRange: generic_transformers_1.transformDoubleReply[2](reply[3]) } - }; - }, - 3: (reply) => { - return { - quantization: reply[0], - raw: reply[1], - l2Norm: reply[2], - quantizationRange: reply[3] - }; + exports2.CacheStats = CacheStats; + var DisabledStatsCounter = class _DisabledStatsCounter { + static INSTANCE = new _DisabledStatsCounter(); + constructor() { + } + recordHits(count) { + } + recordMisses(count) { + } + recordLoadSuccess(loadTime) { + } + recordLoadFailure(loadTime) { + } + recordEvictions(count) { + } + snapshot() { + return CacheStats.empty(); } }; - exports2.default = { - IS_READ_ONLY: true, + function disabledStatsCounter() { + return DisabledStatsCounter.INSTANCE; + } + var DefaultStatsCounter = class _DefaultStatsCounter { + #hitCount = 0; + #missCount = 0; + #loadSuccessCount = 0; + #loadFailureCount = 0; + #totalLoadTime = 0; + #evictionCount = 0; /** - * Retrieve the RAW approximate vector associated with a vector set element + * Records cache hits. * - * @param parser - The command parser - * @param key - The key of the vector set - * @param element - The name of the element to retrieve the vector for - * @see https://redis.io/commands/vemb/ + * @param count - The number of hits to record */ - parseCommand(parser3, key, element) { - VEMB_1.default.parseCommand(parser3, key, element); - parser3.push("RAW"); - }, - transformReply: transformRawVembReply - }; - } -}); -var require_VGETATTR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VGETATTR.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, + recordHits(count) { + this.#hitCount += count; + } /** - * Retrieve the attributes of a vector set element + * Records cache misses. * - * @param parser - The command parser - * @param key - The key of the vector set - * @param element - The name of the element to retrieve attributes for - * @see https://redis.io/commands/vgetattr/ + * @param count - The number of misses to record */ - parseCommand(parser3, key, element) { - parser3.push("VGETATTR"); - parser3.pushKey(key); - parser3.push(element); - }, - transformReply: generic_transformers_1.transformRedisJsonNullReply - }; - } -}); -var require_VINFO = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VINFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, + recordMisses(count) { + this.#missCount += count; + } /** - * Retrieve metadata and internal details about a vector set, including size, dimensions, quantization type, and graph structure + * Records the successful load of a new entry. * - * @param parser - The command parser - * @param key - The key of the vector set - * @see https://redis.io/commands/vinfo/ + * @param loadTime - The number of milliseconds spent loading the entry */ - parseCommand(parser3, key) { - parser3.push("VINFO"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply) => { - const ret = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < reply.length; i2 += 2) { - ret[reply[i2].toString()] = reply[i2 + 1]; - } - return ret; - }, - 3: void 0 + recordLoadSuccess(loadTime) { + this.#loadSuccessCount++; + this.#totalLoadTime += loadTime; } - }; - } -}); -var require_VLINKS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VLINKS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, /** - * Retrieve the neighbors of a specified element in a vector set; the connections for each layer of the HNSW graph + * Records the failed load of a new entry. * - * @param parser - The command parser - * @param key - The key of the vector set - * @param element - The name of the element to retrieve neighbors for - * @see https://redis.io/commands/vlinks/ + * @param loadTime - The number of milliseconds spent attempting to load the entry */ - parseCommand(parser3, key, element) { - parser3.push("VLINKS"); - parser3.pushKey(key); - parser3.push(element); - }, - transformReply: void 0 - }; - } -}); -var require_VLINKS_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VLINKS_WITHSCORES.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var VLINKS_1 = __importDefault(require_VLINKS()); - function transformVLinksWithScoresReply(reply) { - const layers = []; - for (const layer of reply) { - const obj = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < layer.length; i2 += 2) { - const element = layer[i2]; - const score = generic_transformers_1.transformDoubleReply[2](layer[i2 + 1]); - obj[element.toString()] = score; - } - layers.push(obj); + recordLoadFailure(loadTime) { + this.#loadFailureCount++; + this.#totalLoadTime += loadTime; } - return layers; - } - exports2.default = { - IS_READ_ONLY: VLINKS_1.default.IS_READ_ONLY, /** - * Get the connections for each layer of the HNSW graph with similarity scores - * @param args - Same parameters as the VLINKS command - * @see https://redis.io/commands/vlinks/ + * Records cache evictions. + * + * @param count - The number of evictions to record */ - parseCommand(...args) { - const parser3 = args[0]; - VLINKS_1.default.parseCommand(...args); - parser3.push("WITHSCORES"); - }, - transformReply: { - 2: transformVLinksWithScoresReply, - 3: void 0 + recordEvictions(count) { + this.#evictionCount += count; } - }; - } -}); -var require_VRANDMEMBER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VRANDMEMBER.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, /** - * Retrieve random elements of a vector set + * Returns a snapshot of the current statistics. * - * @param parser - The command parser - * @param key - The key of the vector set - * @param count - Optional number of elements to return - * @see https://redis.io/commands/vrandmember/ + * @returns A snapshot of the current statistics */ - parseCommand(parser3, key, count) { - parser3.push("VRANDMEMBER"); - parser3.pushKey(key); - if (count !== void 0) { - parser3.push(count.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_VREM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VREM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { + snapshot() { + return CacheStats.of(this.#hitCount, this.#missCount, this.#loadSuccessCount, this.#loadFailureCount, this.#totalLoadTime, this.#evictionCount); + } /** - * Remove an element from a vector set + * Creates a new DefaultStatsCounter. * - * @param parser - The command parser - * @param key - The key of the vector set - * @param element - The name of the element to remove from the vector set - * @see https://redis.io/commands/vrem/ + * @returns A new DefaultStatsCounter instance */ - parseCommand(parser3, key, element) { - parser3.push("VREM"); - parser3.pushKey(key); - parser3.push(element); - }, - transformReply: generic_transformers_1.transformBooleanReply + static create() { + return new _DefaultStatsCounter(); + } }; - } -}); -var require_VSETATTR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VSETATTR.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - /** - * Set or replace attributes on a vector set element - * - * @param parser - The command parser - * @param key - The key of the vector set - * @param element - The name of the element to set attributes for - * @param attributes - The attributes to set (as JSON string or object) - * @see https://redis.io/commands/vsetattr/ - */ - parseCommand(parser3, key, element, attributes) { - parser3.push("VSETATTR"); - parser3.pushKey(key); - parser3.push(element); - if (typeof attributes === "object" && attributes !== null) { - parser3.push(JSON.stringify(attributes)); + function generateCacheKey(redisArgs) { + const tmp = new Array(redisArgs.length * 2); + for (let i2 = 0; i2 < redisArgs.length; i2++) { + tmp[i2] = redisArgs[i2].length; + tmp[i2 + redisArgs.length] = redisArgs[i2]; + } + return tmp.join("_"); + } + var ClientSideCacheEntryBase = class { + #invalidated = false; + #expireTime; + constructor(ttl) { + if (ttl == 0) { + this.#expireTime = 0; } else { - parser3.push(attributes); + this.#expireTime = Date.now() + ttl; } - }, - transformReply: generic_transformers_1.transformBooleanReply + } + invalidate() { + this.#invalidated = true; + } + validate() { + return !this.#invalidated && (this.#expireTime == 0 || Date.now() < this.#expireTime); + } }; - } -}); -var require_VSIM = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VSIM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Retrieve elements similar to a given vector or element with optional filtering - * - * @param parser - The command parser - * @param key - The key of the vector set - * @param query - The query vector (array of numbers) or element name (string) - * @param options - Optional parameters for similarity search - * @see https://redis.io/commands/vsim/ - */ - parseCommand(parser3, key, query, options2) { - parser3.push("VSIM"); - parser3.pushKey(key); - if (Array.isArray(query)) { - parser3.push("VALUES", query.length.toString()); - for (const value of query) { - parser3.push((0, generic_transformers_1.transformDoubleArgument)(value)); + var ClientSideCacheEntryValue = class extends ClientSideCacheEntryBase { + #value; + get value() { + return this.#value; + } + constructor(ttl, value) { + super(ttl); + this.#value = value; + } + }; + var ClientSideCacheEntryPromise = class extends ClientSideCacheEntryBase { + #sendCommandPromise; + get promise() { + return this.#sendCommandPromise; + } + constructor(ttl, sendCommandPromise) { + super(ttl); + this.#sendCommandPromise = sendCommandPromise; + } + }; + var ClientSideCacheProvider = class extends stream_1.EventEmitter { + }; + exports2.ClientSideCacheProvider = ClientSideCacheProvider; + var BasicClientSideCache = class extends ClientSideCacheProvider { + #cacheKeyToEntryMap; + #keyToCacheKeySetMap; + ttl; + maxEntries; + lru; + #statsCounter; + recordEvictions(count) { + this.#statsCounter.recordEvictions(count); + } + recordHits(count) { + this.#statsCounter.recordHits(count); + } + recordMisses(count) { + this.#statsCounter.recordMisses(count); + } + constructor(config2) { + super(); + this.#cacheKeyToEntryMap = /* @__PURE__ */ new Map(); + this.#keyToCacheKeySetMap = /* @__PURE__ */ new Map(); + this.ttl = config2?.ttl ?? 0; + this.maxEntries = config2?.maxEntries ?? 0; + this.lru = config2?.evictPolicy !== "FIFO"; + const recordStats = config2?.recordStats !== false; + this.#statsCounter = recordStats ? DefaultStatsCounter.create() : disabledStatsCounter(); + } + /* logic of how caching works: + + 1. commands use a CommandParser + it enables us to define/retrieve + cacheKey - a unique key that corresponds to this command and its arguments + redisKeys - an array of redis keys as strings that if the key is modified, will cause redis to invalidate this result when cached + 2. check if cacheKey is in our cache + 2b1. if its a value cacheEntry - return it + 2b2. if it's a promise cache entry - wait on promise and then go to 3c. + 3. if cacheEntry is not in cache + 3a. send the command save the promise into a a cacheEntry and then wait on result + 3b. transform reply (if required) based on transformReply + 3b. check the cacheEntry is still valid - in cache and hasn't been deleted) + 3c. if valid - overwrite with value entry + 4. return previously non cached result + */ + async handleCache(client, parser3, fn, transformReply, typeMapping) { + let reply; + const cacheKey2 = generateCacheKey(parser3.redisArgs); + let cacheEntry = this.get(cacheKey2); + if (cacheEntry) { + if (cacheEntry instanceof ClientSideCacheEntryValue) { + this.#statsCounter.recordHits(1); + return structuredClone(cacheEntry.value); + } else if (cacheEntry instanceof ClientSideCacheEntryPromise) { + this.#statsCounter.recordMisses(1); + reply = await cacheEntry.promise; + } else { + throw new Error("unknown cache entry type"); } } else { - parser3.push("ELE", query); + this.#statsCounter.recordMisses(1); + const startTime = performance.now(); + const promise = fn(); + cacheEntry = this.createPromiseEntry(client, promise); + this.set(cacheKey2, cacheEntry, parser3.keys); + try { + reply = await promise; + const loadTime = performance.now() - startTime; + this.#statsCounter.recordLoadSuccess(loadTime); + } catch (err) { + const loadTime = performance.now() - startTime; + this.#statsCounter.recordLoadFailure(loadTime); + if (cacheEntry.validate()) { + this.delete(cacheKey2); + } + throw err; + } } - if (options2?.COUNT !== void 0) { - parser3.push("COUNT", options2.COUNT.toString()); + let val; + if (transformReply) { + val = transformReply(reply, parser3.preserve, typeMapping); + } else { + val = reply; } - if (options2?.EPSILON !== void 0) { - parser3.push("EPSILON", options2.EPSILON.toString()); + if (cacheEntry.validate()) { + cacheEntry = this.createValueEntry(client, val); + this.set(cacheKey2, cacheEntry, parser3.keys); + this.emit("cached-key", cacheKey2); + } else { } - if (options2?.EF !== void 0) { - parser3.push("EF", options2.EF.toString()); + return structuredClone(val); + } + trackingOn() { + return ["CLIENT", "TRACKING", "ON"]; + } + invalidate(key) { + if (key === null) { + this.clear(false); + this.emit("invalidate", key); + return; } - if (options2?.FILTER) { - parser3.push("FILTER", options2.FILTER); + const keySet = this.#keyToCacheKeySetMap.get(key.toString()); + if (keySet) { + for (const cacheKey2 of keySet) { + const entry = this.#cacheKeyToEntryMap.get(cacheKey2); + if (entry) { + entry.invalidate(); + } + this.#cacheKeyToEntryMap.delete(cacheKey2); + } + this.#keyToCacheKeySetMap.delete(key.toString()); } - if (options2?.["FILTER-EF"] !== void 0) { - parser3.push("FILTER-EF", options2["FILTER-EF"].toString()); + this.emit("invalidate", key); + } + clear(resetStats = true) { + const oldSize = this.#cacheKeyToEntryMap.size; + this.#cacheKeyToEntryMap.clear(); + this.#keyToCacheKeySetMap.clear(); + if (resetStats) { + if (!(this.#statsCounter instanceof DisabledStatsCounter)) { + this.#statsCounter = DefaultStatsCounter.create(); + } + } else { + if (oldSize > 0) { + this.#statsCounter.recordEvictions(oldSize); + } } - if (options2?.TRUTH) { - parser3.push("TRUTH"); + } + get(cacheKey2) { + const val = this.#cacheKeyToEntryMap.get(cacheKey2); + if (val && !val.validate()) { + this.delete(cacheKey2); + this.#statsCounter.recordEvictions(1); + this.emit("cache-evict", cacheKey2); + return void 0; } - if (options2?.NOTHREAD) { - parser3.push("NOTHREAD"); + if (val !== void 0 && this.lru) { + this.#cacheKeyToEntryMap.delete(cacheKey2); + this.#cacheKeyToEntryMap.set(cacheKey2, val); } - }, - transformReply: void 0 + return val; + } + delete(cacheKey2) { + const entry = this.#cacheKeyToEntryMap.get(cacheKey2); + if (entry) { + entry.invalidate(); + this.#cacheKeyToEntryMap.delete(cacheKey2); + } + } + has(cacheKey2) { + return this.#cacheKeyToEntryMap.has(cacheKey2); + } + set(cacheKey2, cacheEntry, keys) { + let count = this.#cacheKeyToEntryMap.size; + const oldEntry = this.#cacheKeyToEntryMap.get(cacheKey2); + if (oldEntry) { + count--; + oldEntry.invalidate(); + } + if (this.maxEntries > 0 && count >= this.maxEntries) { + this.deleteOldest(); + this.#statsCounter.recordEvictions(1); + } + this.#cacheKeyToEntryMap.set(cacheKey2, cacheEntry); + for (const key of keys) { + if (!this.#keyToCacheKeySetMap.has(key.toString())) { + this.#keyToCacheKeySetMap.set(key.toString(), /* @__PURE__ */ new Set()); + } + const cacheKeySet = this.#keyToCacheKeySetMap.get(key.toString()); + cacheKeySet.add(cacheKey2); + } + } + size() { + return this.#cacheKeyToEntryMap.size; + } + createValueEntry(client, value) { + return new ClientSideCacheEntryValue(this.ttl, value); + } + createPromiseEntry(client, sendCommandPromise) { + return new ClientSideCacheEntryPromise(this.ttl, sendCommandPromise); + } + stats() { + return this.#statsCounter.snapshot(); + } + onError() { + this.clear(); + } + onClose() { + this.clear(); + } + /** + * @internal + */ + deleteOldest() { + const it = this.#cacheKeyToEntryMap[Symbol.iterator](); + const n = it.next(); + if (!n.done) { + const key = n.value[0]; + const entry = this.#cacheKeyToEntryMap.get(key); + if (entry) { + entry.invalidate(); + } + this.#cacheKeyToEntryMap.delete(key); + } + } + /** + * Get cache entries for debugging + * @internal + */ + entryEntries() { + return this.#cacheKeyToEntryMap.entries(); + } + /** + * Get key set entries for debugging + * @internal + */ + keySetEntries() { + return this.#keyToCacheKeySetMap.entries(); + } + }; + exports2.BasicClientSideCache = BasicClientSideCache; + var PooledClientSideCacheProvider = class extends BasicClientSideCache { + #disabled = false; + disable() { + this.#disabled = true; + } + enable() { + this.#disabled = false; + } + get(cacheKey2) { + if (this.#disabled) { + return void 0; + } + return super.get(cacheKey2); + } + has(cacheKey2) { + if (this.#disabled) { + return false; + } + return super.has(cacheKey2); + } + onPoolClose() { + this.clear(); + } + }; + exports2.PooledClientSideCacheProvider = PooledClientSideCacheProvider; + var BasicPooledClientSideCache = class extends PooledClientSideCacheProvider { + onError() { + this.clear(false); + } + onClose() { + this.clear(false); + } + }; + exports2.BasicPooledClientSideCache = BasicPooledClientSideCache; + var PooledClientSideCacheEntryValue = class extends ClientSideCacheEntryValue { + #creator; + constructor(ttl, creator, value) { + super(ttl, value); + this.#creator = creator; + } + validate() { + let ret = super.validate(); + if (this.#creator) { + ret = ret && this.#creator.client.isReady && this.#creator.client.socketEpoch == this.#creator.epoch; + } + return ret; + } + }; + var PooledClientSideCacheEntryPromise = class extends ClientSideCacheEntryPromise { + #creator; + constructor(ttl, creator, sendCommandPromise) { + super(ttl, sendCommandPromise); + this.#creator = creator; + } + validate() { + let ret = super.validate(); + return ret && this.#creator.client.isReady && this.#creator.client.socketEpoch == this.#creator.epoch; + } + }; + var PooledNoRedirectClientSideCache = class extends BasicPooledClientSideCache { + createValueEntry(client, value) { + const creator = { + epoch: client.socketEpoch, + client + }; + return new PooledClientSideCacheEntryValue(this.ttl, creator, value); + } + createPromiseEntry(client, sendCommandPromise) { + const creator = { + epoch: client.socketEpoch, + client + }; + return new PooledClientSideCacheEntryPromise(this.ttl, creator, sendCommandPromise); + } + onError() { + } + onClose() { + } }; + exports2.PooledNoRedirectClientSideCache = PooledNoRedirectClientSideCache; } }); -var require_VSIM_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/VSIM_WITHSCORES.js"(exports2) { +var require_single_entry_cache = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/single-entry-cache.js"(exports2) { "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var VSIM_1 = __importDefault(require_VSIM()); - exports2.default = { - IS_READ_ONLY: VSIM_1.default.IS_READ_ONLY, + var SingleEntryCache = class { + #cached; + #serializedKey; /** - * Retrieve elements similar to a given vector or element with similarity scores - * @param args - Same parameters as the VSIM command - * @see https://redis.io/commands/vsim/ + * Retrieves an instance from the cache based on the provided key object. + * + * @param keyObj - The key object to look up in the cache. + * @returns The cached instance if found, undefined otherwise. + * + * @remarks + * This method uses JSON.stringify for comparison, which may not work correctly + * if the properties in the key object are rearranged or reordered. */ - parseCommand(...args) { - const parser3 = args[0]; - VSIM_1.default.parseCommand(...args); - parser3.push("WITHSCORES"); - }, - transformReply: { - 2: (reply) => { - const inferred = reply; - const members = {}; - for (let i2 = 0; i2 < inferred.length; i2 += 2) { - members[inferred[i2].toString()] = generic_transformers_1.transformDoubleReply[2](inferred[i2 + 1]); - } - return members; - }, - 3: void 0 + get(keyObj) { + return JSON.stringify(keyObj, makeCircularReplacer()) === this.#serializedKey ? this.#cached : void 0; + } + set(keyObj, obj) { + this.#cached = obj; + this.#serializedKey = JSON.stringify(keyObj, makeCircularReplacer()); } }; + exports2.default = SingleEntryCache; + function makeCircularReplacer() { + const seen = /* @__PURE__ */ new WeakSet(); + return function serialize2(_, value) { + if (value && typeof value === "object") { + if (seen.has(value)) { + return "circular"; + } + seen.add(value); + return value; + } + return value; + }; + } } }); -var require_commands = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commands/index.js"(exports2) { +var require_pool = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/pool.js"(exports2) { "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; var __importDefault = exports2 && exports2.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { "default": mod }; }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.REDIS_FLUSH_MODES = exports2.COMMAND_LIST_FILTER_BY = exports2.CLUSTER_SLOT_STATES = exports2.FAILOVER_MODES = exports2.CLIENT_KILL_FILTERS = void 0; - var ACL_CAT_1 = __importDefault(require_ACL_CAT()); - var ACL_DELUSER_1 = __importDefault(require_ACL_DELUSER()); - var ACL_DRYRUN_1 = __importDefault(require_ACL_DRYRUN()); - var ACL_GENPASS_1 = __importDefault(require_ACL_GENPASS()); - var ACL_GETUSER_1 = __importDefault(require_ACL_GETUSER()); - var ACL_LIST_1 = __importDefault(require_ACL_LIST()); - var ACL_LOAD_1 = __importDefault(require_ACL_LOAD()); - var ACL_LOG_RESET_1 = __importDefault(require_ACL_LOG_RESET()); - var ACL_LOG_1 = __importDefault(require_ACL_LOG()); - var ACL_SAVE_1 = __importDefault(require_ACL_SAVE()); - var ACL_SETUSER_1 = __importDefault(require_ACL_SETUSER()); - var ACL_USERS_1 = __importDefault(require_ACL_USERS()); - var ACL_WHOAMI_1 = __importDefault(require_ACL_WHOAMI()); - var APPEND_1 = __importDefault(require_APPEND()); - var ASKING_1 = __importDefault(require_ASKING()); - var AUTH_1 = __importDefault(require_AUTH()); - var BGREWRITEAOF_1 = __importDefault(require_BGREWRITEAOF()); - var BGSAVE_1 = __importDefault(require_BGSAVE()); - var BITCOUNT_1 = __importDefault(require_BITCOUNT()); - var BITFIELD_RO_1 = __importDefault(require_BITFIELD_RO()); - var BITFIELD_1 = __importDefault(require_BITFIELD()); - var BITOP_1 = __importDefault(require_BITOP()); - var BITPOS_1 = __importDefault(require_BITPOS()); - var BLMOVE_1 = __importDefault(require_BLMOVE()); - var BLMPOP_1 = __importDefault(require_BLMPOP()); - var BLPOP_1 = __importDefault(require_BLPOP()); - var BRPOP_1 = __importDefault(require_BRPOP()); - var BRPOPLPUSH_1 = __importDefault(require_BRPOPLPUSH()); - var BZMPOP_1 = __importDefault(require_BZMPOP()); - var BZPOPMAX_1 = __importDefault(require_BZPOPMAX()); - var BZPOPMIN_1 = __importDefault(require_BZPOPMIN()); - var CLIENT_CACHING_1 = __importDefault(require_CLIENT_CACHING()); - var CLIENT_GETNAME_1 = __importDefault(require_CLIENT_GETNAME()); - var CLIENT_GETREDIR_1 = __importDefault(require_CLIENT_GETREDIR()); - var CLIENT_ID_1 = __importDefault(require_CLIENT_ID()); - var CLIENT_INFO_1 = __importDefault(require_CLIENT_INFO()); - var CLIENT_KILL_1 = __importStar(require_CLIENT_KILL()); - Object.defineProperty(exports2, "CLIENT_KILL_FILTERS", { enumerable: true, get: function() { - return CLIENT_KILL_1.CLIENT_KILL_FILTERS; - } }); - var CLIENT_LIST_1 = __importDefault(require_CLIENT_LIST()); - var CLIENT_NO_EVICT_1 = __importDefault(require_CLIENT_NO_EVICT()); - var CLIENT_NO_TOUCH_1 = __importDefault(require_CLIENT_NO_TOUCH()); - var CLIENT_PAUSE_1 = __importDefault(require_CLIENT_PAUSE()); - var CLIENT_SETNAME_1 = __importDefault(require_CLIENT_SETNAME()); - var CLIENT_TRACKING_1 = __importDefault(require_CLIENT_TRACKING()); - var CLIENT_TRACKINGINFO_1 = __importDefault(require_CLIENT_TRACKINGINFO()); - var CLIENT_UNPAUSE_1 = __importDefault(require_CLIENT_UNPAUSE()); - var CLUSTER_ADDSLOTS_1 = __importDefault(require_CLUSTER_ADDSLOTS()); - var CLUSTER_ADDSLOTSRANGE_1 = __importDefault(require_CLUSTER_ADDSLOTSRANGE()); - var CLUSTER_BUMPEPOCH_1 = __importDefault(require_CLUSTER_BUMPEPOCH()); - var CLUSTER_COUNT_FAILURE_REPORTS_1 = __importDefault(require_CLUSTER_COUNT_FAILURE_REPORTS()); - var CLUSTER_COUNTKEYSINSLOT_1 = __importDefault(require_CLUSTER_COUNTKEYSINSLOT()); - var CLUSTER_DELSLOTS_1 = __importDefault(require_CLUSTER_DELSLOTS()); - var CLUSTER_DELSLOTSRANGE_1 = __importDefault(require_CLUSTER_DELSLOTSRANGE()); - var CLUSTER_FAILOVER_1 = __importStar(require_CLUSTER_FAILOVER()); - Object.defineProperty(exports2, "FAILOVER_MODES", { enumerable: true, get: function() { - return CLUSTER_FAILOVER_1.FAILOVER_MODES; - } }); - var CLUSTER_FLUSHSLOTS_1 = __importDefault(require_CLUSTER_FLUSHSLOTS()); - var CLUSTER_FORGET_1 = __importDefault(require_CLUSTER_FORGET()); - var CLUSTER_GETKEYSINSLOT_1 = __importDefault(require_CLUSTER_GETKEYSINSLOT()); - var CLUSTER_INFO_1 = __importDefault(require_CLUSTER_INFO()); - var CLUSTER_KEYSLOT_1 = __importDefault(require_CLUSTER_KEYSLOT()); - var CLUSTER_LINKS_1 = __importDefault(require_CLUSTER_LINKS()); - var CLUSTER_MEET_1 = __importDefault(require_CLUSTER_MEET()); - var CLUSTER_MYID_1 = __importDefault(require_CLUSTER_MYID()); - var CLUSTER_MYSHARDID_1 = __importDefault(require_CLUSTER_MYSHARDID()); - var CLUSTER_NODES_1 = __importDefault(require_CLUSTER_NODES()); - var CLUSTER_REPLICAS_1 = __importDefault(require_CLUSTER_REPLICAS()); - var CLUSTER_REPLICATE_1 = __importDefault(require_CLUSTER_REPLICATE()); - var CLUSTER_RESET_1 = __importDefault(require_CLUSTER_RESET()); - var CLUSTER_SAVECONFIG_1 = __importDefault(require_CLUSTER_SAVECONFIG()); - var CLUSTER_SET_CONFIG_EPOCH_1 = __importDefault(require_CLUSTER_SET_CONFIG_EPOCH()); - var CLUSTER_SETSLOT_1 = __importStar(require_CLUSTER_SETSLOT()); - Object.defineProperty(exports2, "CLUSTER_SLOT_STATES", { enumerable: true, get: function() { - return CLUSTER_SETSLOT_1.CLUSTER_SLOT_STATES; - } }); - var CLUSTER_SLOTS_1 = __importDefault(require_CLUSTER_SLOTS()); - var COMMAND_COUNT_1 = __importDefault(require_COMMAND_COUNT()); - var COMMAND_GETKEYS_1 = __importDefault(require_COMMAND_GETKEYS()); - var COMMAND_GETKEYSANDFLAGS_1 = __importDefault(require_COMMAND_GETKEYSANDFLAGS()); - var COMMAND_INFO_1 = __importDefault(require_COMMAND_INFO()); - var COMMAND_LIST_1 = __importStar(require_COMMAND_LIST()); - Object.defineProperty(exports2, "COMMAND_LIST_FILTER_BY", { enumerable: true, get: function() { - return COMMAND_LIST_1.COMMAND_LIST_FILTER_BY; - } }); - var COMMAND_1 = __importDefault(require_COMMAND()); - var CONFIG_GET_1 = __importDefault(require_CONFIG_GET()); - var CONFIG_RESETSTAT_1 = __importDefault(require_CONFIG_RESETSTAT()); - var CONFIG_REWRITE_1 = __importDefault(require_CONFIG_REWRITE()); - var CONFIG_SET_1 = __importDefault(require_CONFIG_SET()); - var COPY_1 = __importDefault(require_COPY()); - var DBSIZE_1 = __importDefault(require_DBSIZE()); - var DECR_1 = __importDefault(require_DECR()); - var DECRBY_1 = __importDefault(require_DECRBY()); - var DEL_1 = __importDefault(require_DEL()); - var DUMP_1 = __importDefault(require_DUMP()); - var ECHO_1 = __importDefault(require_ECHO()); - var EVAL_RO_1 = __importDefault(require_EVAL_RO()); - var EVAL_1 = __importDefault(require_EVAL()); - var EVALSHA_RO_1 = __importDefault(require_EVALSHA_RO()); - var EVALSHA_1 = __importDefault(require_EVALSHA()); - var GEOADD_1 = __importDefault(require_GEOADD()); - var GEODIST_1 = __importDefault(require_GEODIST()); - var GEOHASH_1 = __importDefault(require_GEOHASH()); - var GEOPOS_1 = __importDefault(require_GEOPOS()); - var GEORADIUS_RO_WITH_1 = __importDefault(require_GEORADIUS_RO_WITH()); - var GEORADIUS_RO_1 = __importDefault(require_GEORADIUS_RO()); - var GEORADIUS_STORE_1 = __importDefault(require_GEORADIUS_STORE()); - var GEORADIUS_WITH_1 = __importDefault(require_GEORADIUS_WITH()); - var GEORADIUS_1 = __importDefault(require_GEORADIUS()); - var GEORADIUSBYMEMBER_RO_WITH_1 = __importDefault(require_GEORADIUSBYMEMBER_RO_WITH()); - var GEORADIUSBYMEMBER_RO_1 = __importDefault(require_GEORADIUSBYMEMBER_RO()); - var GEORADIUSBYMEMBER_STORE_1 = __importDefault(require_GEORADIUSBYMEMBER_STORE()); - var GEORADIUSBYMEMBER_WITH_1 = __importDefault(require_GEORADIUSBYMEMBER_WITH()); - var GEORADIUSBYMEMBER_1 = __importDefault(require_GEORADIUSBYMEMBER()); - var GEOSEARCH_WITH_1 = __importDefault(require_GEOSEARCH_WITH()); - var GEOSEARCH_1 = __importDefault(require_GEOSEARCH()); - var GEOSEARCHSTORE_1 = __importDefault(require_GEOSEARCHSTORE()); - var GET_1 = __importDefault(require_GET()); - var GETBIT_1 = __importDefault(require_GETBIT()); - var GETDEL_1 = __importDefault(require_GETDEL()); - var GETEX_1 = __importDefault(require_GETEX()); - var GETRANGE_1 = __importDefault(require_GETRANGE()); - var GETSET_1 = __importDefault(require_GETSET()); - var EXISTS_1 = __importDefault(require_EXISTS()); - var EXPIRE_1 = __importDefault(require_EXPIRE()); - var EXPIREAT_1 = __importDefault(require_EXPIREAT()); - var EXPIRETIME_1 = __importDefault(require_EXPIRETIME()); - var FLUSHALL_1 = __importStar(require_FLUSHALL()); - Object.defineProperty(exports2, "REDIS_FLUSH_MODES", { enumerable: true, get: function() { - return FLUSHALL_1.REDIS_FLUSH_MODES; - } }); - var FLUSHDB_1 = __importDefault(require_FLUSHDB()); - var FCALL_1 = __importDefault(require_FCALL()); - var FCALL_RO_1 = __importDefault(require_FCALL_RO()); - var FUNCTION_DELETE_1 = __importDefault(require_FUNCTION_DELETE()); - var FUNCTION_DUMP_1 = __importDefault(require_FUNCTION_DUMP()); - var FUNCTION_FLUSH_1 = __importDefault(require_FUNCTION_FLUSH()); - var FUNCTION_KILL_1 = __importDefault(require_FUNCTION_KILL()); - var FUNCTION_LIST_WITHCODE_1 = __importDefault(require_FUNCTION_LIST_WITHCODE()); - var FUNCTION_LIST_1 = __importDefault(require_FUNCTION_LIST()); - var FUNCTION_LOAD_1 = __importDefault(require_FUNCTION_LOAD()); - var FUNCTION_RESTORE_1 = __importDefault(require_FUNCTION_RESTORE()); - var FUNCTION_STATS_1 = __importDefault(require_FUNCTION_STATS()); - var HDEL_1 = __importDefault(require_HDEL()); - var HELLO_1 = __importDefault(require_HELLO()); - var HEXISTS_1 = __importDefault(require_HEXISTS()); - var HEXPIRE_1 = __importDefault(require_HEXPIRE()); - var HEXPIREAT_1 = __importDefault(require_HEXPIREAT()); - var HEXPIRETIME_1 = __importDefault(require_HEXPIRETIME()); - var HGET_1 = __importDefault(require_HGET()); - var HGETALL_1 = __importDefault(require_HGETALL()); - var HGETDEL_1 = __importDefault(require_HGETDEL()); - var HGETEX_1 = __importDefault(require_HGETEX()); - var HINCRBY_1 = __importDefault(require_HINCRBY()); - var HINCRBYFLOAT_1 = __importDefault(require_HINCRBYFLOAT()); - var HKEYS_1 = __importDefault(require_HKEYS()); - var HLEN_1 = __importDefault(require_HLEN()); - var HMGET_1 = __importDefault(require_HMGET()); - var HPERSIST_1 = __importDefault(require_HPERSIST()); - var HPEXPIRE_1 = __importDefault(require_HPEXPIRE()); - var HPEXPIREAT_1 = __importDefault(require_HPEXPIREAT()); - var HPEXPIRETIME_1 = __importDefault(require_HPEXPIRETIME()); - var HPTTL_1 = __importDefault(require_HPTTL()); - var HRANDFIELD_COUNT_WITHVALUES_1 = __importDefault(require_HRANDFIELD_COUNT_WITHVALUES()); - var HRANDFIELD_COUNT_1 = __importDefault(require_HRANDFIELD_COUNT()); - var HRANDFIELD_1 = __importDefault(require_HRANDFIELD()); - var HSCAN_1 = __importDefault(require_HSCAN()); - var HSCAN_NOVALUES_1 = __importDefault(require_HSCAN_NOVALUES()); - var HSET_1 = __importDefault(require_HSET()); - var HSETEX_1 = __importDefault(require_HSETEX()); - var HSETNX_1 = __importDefault(require_HSETNX()); - var HSTRLEN_1 = __importDefault(require_HSTRLEN()); - var HTTL_1 = __importDefault(require_HTTL()); - var HVALS_1 = __importDefault(require_HVALS()); - var INCR_1 = __importDefault(require_INCR()); - var INCRBY_1 = __importDefault(require_INCRBY()); - var INCRBYFLOAT_1 = __importDefault(require_INCRBYFLOAT()); - var INFO_1 = __importDefault(require_INFO()); - var KEYS_1 = __importDefault(require_KEYS()); - var LASTSAVE_1 = __importDefault(require_LASTSAVE()); - var LATENCY_DOCTOR_1 = __importDefault(require_LATENCY_DOCTOR()); - var LATENCY_GRAPH_1 = __importDefault(require_LATENCY_GRAPH()); - var LATENCY_HISTORY_1 = __importDefault(require_LATENCY_HISTORY()); - var LATENCY_LATEST_1 = __importDefault(require_LATENCY_LATEST()); - var LATENCY_RESET_1 = __importDefault(require_LATENCY_RESET()); - var LCS_IDX_WITHMATCHLEN_1 = __importDefault(require_LCS_IDX_WITHMATCHLEN()); - var LCS_IDX_1 = __importDefault(require_LCS_IDX()); - var LCS_LEN_1 = __importDefault(require_LCS_LEN()); - var LCS_1 = __importDefault(require_LCS()); - var LINDEX_1 = __importDefault(require_LINDEX()); - var LINSERT_1 = __importDefault(require_LINSERT()); - var LLEN_1 = __importDefault(require_LLEN()); - var LMOVE_1 = __importDefault(require_LMOVE()); - var LMPOP_1 = __importDefault(require_LMPOP()); - var LOLWUT_1 = __importDefault(require_LOLWUT()); - var LPOP_COUNT_1 = __importDefault(require_LPOP_COUNT()); - var LPOP_1 = __importDefault(require_LPOP()); - var LPOS_COUNT_1 = __importDefault(require_LPOS_COUNT()); - var LPOS_1 = __importDefault(require_LPOS()); - var LPUSH_1 = __importDefault(require_LPUSH()); - var LPUSHX_1 = __importDefault(require_LPUSHX()); - var LRANGE_1 = __importDefault(require_LRANGE()); - var LREM_1 = __importDefault(require_LREM()); - var LSET_1 = __importDefault(require_LSET()); - var LTRIM_1 = __importDefault(require_LTRIM()); - var MEMORY_DOCTOR_1 = __importDefault(require_MEMORY_DOCTOR()); - var MEMORY_MALLOC_STATS_1 = __importDefault(require_MEMORY_MALLOC_STATS()); - var MEMORY_PURGE_1 = __importDefault(require_MEMORY_PURGE()); - var MEMORY_STATS_1 = __importDefault(require_MEMORY_STATS()); - var MEMORY_USAGE_1 = __importDefault(require_MEMORY_USAGE()); - var MGET_1 = __importDefault(require_MGET()); - var MIGRATE_1 = __importDefault(require_MIGRATE()); - var MODULE_LIST_1 = __importDefault(require_MODULE_LIST()); - var MODULE_LOAD_1 = __importDefault(require_MODULE_LOAD()); - var MODULE_UNLOAD_1 = __importDefault(require_MODULE_UNLOAD()); - var MOVE_1 = __importDefault(require_MOVE()); - var MSET_1 = __importDefault(require_MSET()); - var MSETNX_1 = __importDefault(require_MSETNX()); - var OBJECT_ENCODING_1 = __importDefault(require_OBJECT_ENCODING()); - var OBJECT_FREQ_1 = __importDefault(require_OBJECT_FREQ()); - var OBJECT_IDLETIME_1 = __importDefault(require_OBJECT_IDLETIME()); - var OBJECT_REFCOUNT_1 = __importDefault(require_OBJECT_REFCOUNT()); - var PERSIST_1 = __importDefault(require_PERSIST()); - var PEXPIRE_1 = __importDefault(require_PEXPIRE()); - var PEXPIREAT_1 = __importDefault(require_PEXPIREAT()); - var PEXPIRETIME_1 = __importDefault(require_PEXPIRETIME()); - var PFADD_1 = __importDefault(require_PFADD()); - var PFCOUNT_1 = __importDefault(require_PFCOUNT()); - var PFMERGE_1 = __importDefault(require_PFMERGE()); - var PING_1 = __importDefault(require_PING()); - var PSETEX_1 = __importDefault(require_PSETEX()); - var PTTL_1 = __importDefault(require_PTTL()); - var PUBLISH_1 = __importDefault(require_PUBLISH()); - var PUBSUB_CHANNELS_1 = __importDefault(require_PUBSUB_CHANNELS()); - var PUBSUB_NUMPAT_1 = __importDefault(require_PUBSUB_NUMPAT()); - var PUBSUB_NUMSUB_1 = __importDefault(require_PUBSUB_NUMSUB()); - var PUBSUB_SHARDNUMSUB_1 = __importDefault(require_PUBSUB_SHARDNUMSUB()); - var PUBSUB_SHARDCHANNELS_1 = __importDefault(require_PUBSUB_SHARDCHANNELS()); - var RANDOMKEY_1 = __importDefault(require_RANDOMKEY()); - var READONLY_1 = __importDefault(require_READONLY()); - var RENAME_1 = __importDefault(require_RENAME()); - var RENAMENX_1 = __importDefault(require_RENAMENX()); - var REPLICAOF_1 = __importDefault(require_REPLICAOF()); - var RESTORE_ASKING_1 = __importDefault(require_RESTORE_ASKING()); - var RESTORE_1 = __importDefault(require_RESTORE()); - var ROLE_1 = __importDefault(require_ROLE()); - var RPOP_COUNT_1 = __importDefault(require_RPOP_COUNT()); - var RPOP_1 = __importDefault(require_RPOP()); - var RPOPLPUSH_1 = __importDefault(require_RPOPLPUSH()); - var RPUSH_1 = __importDefault(require_RPUSH()); - var RPUSHX_1 = __importDefault(require_RPUSHX()); - var SADD_1 = __importDefault(require_SADD()); - var SCAN_1 = __importDefault(require_SCAN()); - var SCARD_1 = __importDefault(require_SCARD()); - var SCRIPT_DEBUG_1 = __importDefault(require_SCRIPT_DEBUG()); - var SCRIPT_EXISTS_1 = __importDefault(require_SCRIPT_EXISTS()); - var SCRIPT_FLUSH_1 = __importDefault(require_SCRIPT_FLUSH()); - var SCRIPT_KILL_1 = __importDefault(require_SCRIPT_KILL()); - var SCRIPT_LOAD_1 = __importDefault(require_SCRIPT_LOAD()); - var SDIFF_1 = __importDefault(require_SDIFF()); - var SDIFFSTORE_1 = __importDefault(require_SDIFFSTORE()); - var SET_1 = __importDefault(require_SET()); - var SETBIT_1 = __importDefault(require_SETBIT()); - var SETEX_1 = __importDefault(require_SETEX()); - var SETNX_1 = __importDefault(require_SETNX()); - var SETRANGE_1 = __importDefault(require_SETRANGE()); - var SINTER_1 = __importDefault(require_SINTER()); - var SINTERCARD_1 = __importDefault(require_SINTERCARD()); - var SINTERSTORE_1 = __importDefault(require_SINTERSTORE()); - var SISMEMBER_1 = __importDefault(require_SISMEMBER()); - var SMEMBERS_1 = __importDefault(require_SMEMBERS()); - var SMISMEMBER_1 = __importDefault(require_SMISMEMBER()); - var SMOVE_1 = __importDefault(require_SMOVE()); - var SORT_RO_1 = __importDefault(require_SORT_RO()); - var SORT_STORE_1 = __importDefault(require_SORT_STORE()); - var SORT_1 = __importDefault(require_SORT()); - var SPOP_COUNT_1 = __importDefault(require_SPOP_COUNT()); - var SPOP_1 = __importDefault(require_SPOP()); - var SPUBLISH_1 = __importDefault(require_SPUBLISH()); - var SRANDMEMBER_COUNT_1 = __importDefault(require_SRANDMEMBER_COUNT()); - var SRANDMEMBER_1 = __importDefault(require_SRANDMEMBER()); - var SREM_1 = __importDefault(require_SREM()); - var SSCAN_1 = __importDefault(require_SSCAN()); - var STRLEN_1 = __importDefault(require_STRLEN()); - var SUNION_1 = __importDefault(require_SUNION()); - var SUNIONSTORE_1 = __importDefault(require_SUNIONSTORE()); - var SWAPDB_1 = __importDefault(require_SWAPDB()); - var TIME_1 = __importDefault(require_TIME()); - var TOUCH_1 = __importDefault(require_TOUCH()); - var TTL_1 = __importDefault(require_TTL()); - var TYPE_1 = __importDefault(require_TYPE()); - var UNLINK_1 = __importDefault(require_UNLINK()); - var WAIT_1 = __importDefault(require_WAIT()); - var XACK_1 = __importDefault(require_XACK()); - var XACKDEL_1 = __importDefault(require_XACKDEL()); - var XADD_NOMKSTREAM_1 = __importDefault(require_XADD_NOMKSTREAM()); - var XADD_1 = __importDefault(require_XADD()); - var XAUTOCLAIM_JUSTID_1 = __importDefault(require_XAUTOCLAIM_JUSTID()); - var XAUTOCLAIM_1 = __importDefault(require_XAUTOCLAIM()); - var XCLAIM_JUSTID_1 = __importDefault(require_XCLAIM_JUSTID()); - var XCLAIM_1 = __importDefault(require_XCLAIM()); - var XDEL_1 = __importDefault(require_XDEL()); - var XDELEX_1 = __importDefault(require_XDELEX()); - var XGROUP_CREATE_1 = __importDefault(require_XGROUP_CREATE()); - var XGROUP_CREATECONSUMER_1 = __importDefault(require_XGROUP_CREATECONSUMER()); - var XGROUP_DELCONSUMER_1 = __importDefault(require_XGROUP_DELCONSUMER()); - var XGROUP_DESTROY_1 = __importDefault(require_XGROUP_DESTROY()); - var XGROUP_SETID_1 = __importDefault(require_XGROUP_SETID()); - var XINFO_CONSUMERS_1 = __importDefault(require_XINFO_CONSUMERS()); - var XINFO_GROUPS_1 = __importDefault(require_XINFO_GROUPS()); - var XINFO_STREAM_1 = __importDefault(require_XINFO_STREAM()); - var XLEN_1 = __importDefault(require_XLEN()); - var XPENDING_RANGE_1 = __importDefault(require_XPENDING_RANGE()); - var XPENDING_1 = __importDefault(require_XPENDING()); - var XRANGE_1 = __importDefault(require_XRANGE()); - var XREAD_1 = __importDefault(require_XREAD()); - var XREADGROUP_1 = __importDefault(require_XREADGROUP()); - var XREVRANGE_1 = __importDefault(require_XREVRANGE()); - var XSETID_1 = __importDefault(require_XSETID()); - var XTRIM_1 = __importDefault(require_XTRIM()); - var ZADD_INCR_1 = __importDefault(require_ZADD_INCR()); - var ZADD_1 = __importDefault(require_ZADD()); - var ZCARD_1 = __importDefault(require_ZCARD()); - var ZCOUNT_1 = __importDefault(require_ZCOUNT()); - var ZDIFF_WITHSCORES_1 = __importDefault(require_ZDIFF_WITHSCORES()); - var ZDIFF_1 = __importDefault(require_ZDIFF()); - var ZDIFFSTORE_1 = __importDefault(require_ZDIFFSTORE()); - var ZINCRBY_1 = __importDefault(require_ZINCRBY()); - var ZINTER_WITHSCORES_1 = __importDefault(require_ZINTER_WITHSCORES()); - var ZINTER_1 = __importDefault(require_ZINTER()); - var ZINTERCARD_1 = __importDefault(require_ZINTERCARD()); - var ZINTERSTORE_1 = __importDefault(require_ZINTERSTORE()); - var ZLEXCOUNT_1 = __importDefault(require_ZLEXCOUNT()); - var ZMPOP_1 = __importDefault(require_ZMPOP()); - var ZMSCORE_1 = __importDefault(require_ZMSCORE()); - var ZPOPMAX_COUNT_1 = __importDefault(require_ZPOPMAX_COUNT()); - var ZPOPMAX_1 = __importDefault(require_ZPOPMAX()); - var ZPOPMIN_COUNT_1 = __importDefault(require_ZPOPMIN_COUNT()); - var ZPOPMIN_1 = __importDefault(require_ZPOPMIN()); - var ZRANDMEMBER_COUNT_WITHSCORES_1 = __importDefault(require_ZRANDMEMBER_COUNT_WITHSCORES()); - var ZRANDMEMBER_COUNT_1 = __importDefault(require_ZRANDMEMBER_COUNT()); - var ZRANDMEMBER_1 = __importDefault(require_ZRANDMEMBER()); - var ZRANGE_WITHSCORES_1 = __importDefault(require_ZRANGE_WITHSCORES()); - var ZRANGE_1 = __importDefault(require_ZRANGE()); - var ZRANGEBYLEX_1 = __importDefault(require_ZRANGEBYLEX()); - var ZRANGEBYSCORE_WITHSCORES_1 = __importDefault(require_ZRANGEBYSCORE_WITHSCORES()); - var ZRANGEBYSCORE_1 = __importDefault(require_ZRANGEBYSCORE()); - var ZRANGESTORE_1 = __importDefault(require_ZRANGESTORE()); - var ZREMRANGEBYSCORE_1 = __importDefault(require_ZREMRANGEBYSCORE()); - var ZRANK_WITHSCORE_1 = __importDefault(require_ZRANK_WITHSCORE()); - var ZRANK_1 = __importDefault(require_ZRANK()); - var ZREM_1 = __importDefault(require_ZREM()); - var ZREMRANGEBYLEX_1 = __importDefault(require_ZREMRANGEBYLEX()); - var ZREMRANGEBYRANK_1 = __importDefault(require_ZREMRANGEBYRANK()); - var ZREVRANK_1 = __importDefault(require_ZREVRANK()); - var ZSCAN_1 = __importDefault(require_ZSCAN()); - var ZSCORE_1 = __importDefault(require_ZSCORE()); - var ZUNION_WITHSCORES_1 = __importDefault(require_ZUNION_WITHSCORES()); - var ZUNION_1 = __importDefault(require_ZUNION()); - var ZUNIONSTORE_1 = __importDefault(require_ZUNIONSTORE()); - var VADD_1 = __importDefault(require_VADD()); - var VCARD_1 = __importDefault(require_VCARD()); - var VDIM_1 = __importDefault(require_VDIM()); - var VEMB_1 = __importDefault(require_VEMB()); - var VEMB_RAW_1 = __importDefault(require_VEMB_RAW()); - var VGETATTR_1 = __importDefault(require_VGETATTR()); - var VINFO_1 = __importDefault(require_VINFO()); - var VLINKS_1 = __importDefault(require_VLINKS()); - var VLINKS_WITHSCORES_1 = __importDefault(require_VLINKS_WITHSCORES()); - var VRANDMEMBER_1 = __importDefault(require_VRANDMEMBER()); - var VREM_1 = __importDefault(require_VREM()); - var VSETATTR_1 = __importDefault(require_VSETATTR()); - var VSIM_1 = __importDefault(require_VSIM()); - var VSIM_WITHSCORES_1 = __importDefault(require_VSIM_WITHSCORES()); - exports2.default = { - ACL_CAT: ACL_CAT_1.default, - aclCat: ACL_CAT_1.default, - ACL_DELUSER: ACL_DELUSER_1.default, - aclDelUser: ACL_DELUSER_1.default, - ACL_DRYRUN: ACL_DRYRUN_1.default, - aclDryRun: ACL_DRYRUN_1.default, - ACL_GENPASS: ACL_GENPASS_1.default, - aclGenPass: ACL_GENPASS_1.default, - ACL_GETUSER: ACL_GETUSER_1.default, - aclGetUser: ACL_GETUSER_1.default, - ACL_LIST: ACL_LIST_1.default, - aclList: ACL_LIST_1.default, - ACL_LOAD: ACL_LOAD_1.default, - aclLoad: ACL_LOAD_1.default, - ACL_LOG_RESET: ACL_LOG_RESET_1.default, - aclLogReset: ACL_LOG_RESET_1.default, - ACL_LOG: ACL_LOG_1.default, - aclLog: ACL_LOG_1.default, - ACL_SAVE: ACL_SAVE_1.default, - aclSave: ACL_SAVE_1.default, - ACL_SETUSER: ACL_SETUSER_1.default, - aclSetUser: ACL_SETUSER_1.default, - ACL_USERS: ACL_USERS_1.default, - aclUsers: ACL_USERS_1.default, - ACL_WHOAMI: ACL_WHOAMI_1.default, - aclWhoAmI: ACL_WHOAMI_1.default, - APPEND: APPEND_1.default, - append: APPEND_1.default, - ASKING: ASKING_1.default, - asking: ASKING_1.default, - AUTH: AUTH_1.default, - auth: AUTH_1.default, - BGREWRITEAOF: BGREWRITEAOF_1.default, - bgRewriteAof: BGREWRITEAOF_1.default, - BGSAVE: BGSAVE_1.default, - bgSave: BGSAVE_1.default, - BITCOUNT: BITCOUNT_1.default, - bitCount: BITCOUNT_1.default, - BITFIELD_RO: BITFIELD_RO_1.default, - bitFieldRo: BITFIELD_RO_1.default, - BITFIELD: BITFIELD_1.default, - bitField: BITFIELD_1.default, - BITOP: BITOP_1.default, - bitOp: BITOP_1.default, - BITPOS: BITPOS_1.default, - bitPos: BITPOS_1.default, - BLMOVE: BLMOVE_1.default, - blMove: BLMOVE_1.default, - BLMPOP: BLMPOP_1.default, - blmPop: BLMPOP_1.default, - BLPOP: BLPOP_1.default, - blPop: BLPOP_1.default, - BRPOP: BRPOP_1.default, - brPop: BRPOP_1.default, - BRPOPLPUSH: BRPOPLPUSH_1.default, - brPopLPush: BRPOPLPUSH_1.default, - BZMPOP: BZMPOP_1.default, - bzmPop: BZMPOP_1.default, - BZPOPMAX: BZPOPMAX_1.default, - bzPopMax: BZPOPMAX_1.default, - BZPOPMIN: BZPOPMIN_1.default, - bzPopMin: BZPOPMIN_1.default, - CLIENT_CACHING: CLIENT_CACHING_1.default, - clientCaching: CLIENT_CACHING_1.default, - CLIENT_GETNAME: CLIENT_GETNAME_1.default, - clientGetName: CLIENT_GETNAME_1.default, - CLIENT_GETREDIR: CLIENT_GETREDIR_1.default, - clientGetRedir: CLIENT_GETREDIR_1.default, - CLIENT_ID: CLIENT_ID_1.default, - clientId: CLIENT_ID_1.default, - CLIENT_INFO: CLIENT_INFO_1.default, - clientInfo: CLIENT_INFO_1.default, - CLIENT_KILL: CLIENT_KILL_1.default, - clientKill: CLIENT_KILL_1.default, - CLIENT_LIST: CLIENT_LIST_1.default, - clientList: CLIENT_LIST_1.default, - "CLIENT_NO-EVICT": CLIENT_NO_EVICT_1.default, - clientNoEvict: CLIENT_NO_EVICT_1.default, - "CLIENT_NO-TOUCH": CLIENT_NO_TOUCH_1.default, - clientNoTouch: CLIENT_NO_TOUCH_1.default, - CLIENT_PAUSE: CLIENT_PAUSE_1.default, - clientPause: CLIENT_PAUSE_1.default, - CLIENT_SETNAME: CLIENT_SETNAME_1.default, - clientSetName: CLIENT_SETNAME_1.default, - CLIENT_TRACKING: CLIENT_TRACKING_1.default, - clientTracking: CLIENT_TRACKING_1.default, - CLIENT_TRACKINGINFO: CLIENT_TRACKINGINFO_1.default, - clientTrackingInfo: CLIENT_TRACKINGINFO_1.default, - CLIENT_UNPAUSE: CLIENT_UNPAUSE_1.default, - clientUnpause: CLIENT_UNPAUSE_1.default, - CLUSTER_ADDSLOTS: CLUSTER_ADDSLOTS_1.default, - clusterAddSlots: CLUSTER_ADDSLOTS_1.default, - CLUSTER_ADDSLOTSRANGE: CLUSTER_ADDSLOTSRANGE_1.default, - clusterAddSlotsRange: CLUSTER_ADDSLOTSRANGE_1.default, - CLUSTER_BUMPEPOCH: CLUSTER_BUMPEPOCH_1.default, - clusterBumpEpoch: CLUSTER_BUMPEPOCH_1.default, - "CLUSTER_COUNT-FAILURE-REPORTS": CLUSTER_COUNT_FAILURE_REPORTS_1.default, - clusterCountFailureReports: CLUSTER_COUNT_FAILURE_REPORTS_1.default, - CLUSTER_COUNTKEYSINSLOT: CLUSTER_COUNTKEYSINSLOT_1.default, - clusterCountKeysInSlot: CLUSTER_COUNTKEYSINSLOT_1.default, - CLUSTER_DELSLOTS: CLUSTER_DELSLOTS_1.default, - clusterDelSlots: CLUSTER_DELSLOTS_1.default, - CLUSTER_DELSLOTSRANGE: CLUSTER_DELSLOTSRANGE_1.default, - clusterDelSlotsRange: CLUSTER_DELSLOTSRANGE_1.default, - CLUSTER_FAILOVER: CLUSTER_FAILOVER_1.default, - clusterFailover: CLUSTER_FAILOVER_1.default, - CLUSTER_FLUSHSLOTS: CLUSTER_FLUSHSLOTS_1.default, - clusterFlushSlots: CLUSTER_FLUSHSLOTS_1.default, - CLUSTER_FORGET: CLUSTER_FORGET_1.default, - clusterForget: CLUSTER_FORGET_1.default, - CLUSTER_GETKEYSINSLOT: CLUSTER_GETKEYSINSLOT_1.default, - clusterGetKeysInSlot: CLUSTER_GETKEYSINSLOT_1.default, - CLUSTER_INFO: CLUSTER_INFO_1.default, - clusterInfo: CLUSTER_INFO_1.default, - CLUSTER_KEYSLOT: CLUSTER_KEYSLOT_1.default, - clusterKeySlot: CLUSTER_KEYSLOT_1.default, - CLUSTER_LINKS: CLUSTER_LINKS_1.default, - clusterLinks: CLUSTER_LINKS_1.default, - CLUSTER_MEET: CLUSTER_MEET_1.default, - clusterMeet: CLUSTER_MEET_1.default, - CLUSTER_MYID: CLUSTER_MYID_1.default, - clusterMyId: CLUSTER_MYID_1.default, - CLUSTER_MYSHARDID: CLUSTER_MYSHARDID_1.default, - clusterMyShardId: CLUSTER_MYSHARDID_1.default, - CLUSTER_NODES: CLUSTER_NODES_1.default, - clusterNodes: CLUSTER_NODES_1.default, - CLUSTER_REPLICAS: CLUSTER_REPLICAS_1.default, - clusterReplicas: CLUSTER_REPLICAS_1.default, - CLUSTER_REPLICATE: CLUSTER_REPLICATE_1.default, - clusterReplicate: CLUSTER_REPLICATE_1.default, - CLUSTER_RESET: CLUSTER_RESET_1.default, - clusterReset: CLUSTER_RESET_1.default, - CLUSTER_SAVECONFIG: CLUSTER_SAVECONFIG_1.default, - clusterSaveConfig: CLUSTER_SAVECONFIG_1.default, - "CLUSTER_SET-CONFIG-EPOCH": CLUSTER_SET_CONFIG_EPOCH_1.default, - clusterSetConfigEpoch: CLUSTER_SET_CONFIG_EPOCH_1.default, - CLUSTER_SETSLOT: CLUSTER_SETSLOT_1.default, - clusterSetSlot: CLUSTER_SETSLOT_1.default, - CLUSTER_SLOTS: CLUSTER_SLOTS_1.default, - clusterSlots: CLUSTER_SLOTS_1.default, - COMMAND_COUNT: COMMAND_COUNT_1.default, - commandCount: COMMAND_COUNT_1.default, - COMMAND_GETKEYS: COMMAND_GETKEYS_1.default, - commandGetKeys: COMMAND_GETKEYS_1.default, - COMMAND_GETKEYSANDFLAGS: COMMAND_GETKEYSANDFLAGS_1.default, - commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS_1.default, - COMMAND_INFO: COMMAND_INFO_1.default, - commandInfo: COMMAND_INFO_1.default, - COMMAND_LIST: COMMAND_LIST_1.default, - commandList: COMMAND_LIST_1.default, - COMMAND: COMMAND_1.default, - command: COMMAND_1.default, - CONFIG_GET: CONFIG_GET_1.default, - configGet: CONFIG_GET_1.default, - CONFIG_RESETASTAT: CONFIG_RESETSTAT_1.default, - configResetStat: CONFIG_RESETSTAT_1.default, - CONFIG_REWRITE: CONFIG_REWRITE_1.default, - configRewrite: CONFIG_REWRITE_1.default, - CONFIG_SET: CONFIG_SET_1.default, - configSet: CONFIG_SET_1.default, - COPY: COPY_1.default, - copy: COPY_1.default, - DBSIZE: DBSIZE_1.default, - dbSize: DBSIZE_1.default, - DECR: DECR_1.default, - decr: DECR_1.default, - DECRBY: DECRBY_1.default, - decrBy: DECRBY_1.default, - DEL: DEL_1.default, - del: DEL_1.default, - DUMP: DUMP_1.default, - dump: DUMP_1.default, - ECHO: ECHO_1.default, - echo: ECHO_1.default, - EVAL_RO: EVAL_RO_1.default, - evalRo: EVAL_RO_1.default, - EVAL: EVAL_1.default, - eval: EVAL_1.default, - EVALSHA_RO: EVALSHA_RO_1.default, - evalShaRo: EVALSHA_RO_1.default, - EVALSHA: EVALSHA_1.default, - evalSha: EVALSHA_1.default, - EXISTS: EXISTS_1.default, - exists: EXISTS_1.default, - EXPIRE: EXPIRE_1.default, - expire: EXPIRE_1.default, - EXPIREAT: EXPIREAT_1.default, - expireAt: EXPIREAT_1.default, - EXPIRETIME: EXPIRETIME_1.default, - expireTime: EXPIRETIME_1.default, - FLUSHALL: FLUSHALL_1.default, - flushAll: FLUSHALL_1.default, - FLUSHDB: FLUSHDB_1.default, - flushDb: FLUSHDB_1.default, - FCALL: FCALL_1.default, - fCall: FCALL_1.default, - FCALL_RO: FCALL_RO_1.default, - fCallRo: FCALL_RO_1.default, - FUNCTION_DELETE: FUNCTION_DELETE_1.default, - functionDelete: FUNCTION_DELETE_1.default, - FUNCTION_DUMP: FUNCTION_DUMP_1.default, - functionDump: FUNCTION_DUMP_1.default, - FUNCTION_FLUSH: FUNCTION_FLUSH_1.default, - functionFlush: FUNCTION_FLUSH_1.default, - FUNCTION_KILL: FUNCTION_KILL_1.default, - functionKill: FUNCTION_KILL_1.default, - FUNCTION_LIST_WITHCODE: FUNCTION_LIST_WITHCODE_1.default, - functionListWithCode: FUNCTION_LIST_WITHCODE_1.default, - FUNCTION_LIST: FUNCTION_LIST_1.default, - functionList: FUNCTION_LIST_1.default, - FUNCTION_LOAD: FUNCTION_LOAD_1.default, - functionLoad: FUNCTION_LOAD_1.default, - FUNCTION_RESTORE: FUNCTION_RESTORE_1.default, - functionRestore: FUNCTION_RESTORE_1.default, - FUNCTION_STATS: FUNCTION_STATS_1.default, - functionStats: FUNCTION_STATS_1.default, - GEOADD: GEOADD_1.default, - geoAdd: GEOADD_1.default, - GEODIST: GEODIST_1.default, - geoDist: GEODIST_1.default, - GEOHASH: GEOHASH_1.default, - geoHash: GEOHASH_1.default, - GEOPOS: GEOPOS_1.default, - geoPos: GEOPOS_1.default, - GEORADIUS_RO_WITH: GEORADIUS_RO_WITH_1.default, - geoRadiusRoWith: GEORADIUS_RO_WITH_1.default, - GEORADIUS_RO: GEORADIUS_RO_1.default, - geoRadiusRo: GEORADIUS_RO_1.default, - GEORADIUS_STORE: GEORADIUS_STORE_1.default, - geoRadiusStore: GEORADIUS_STORE_1.default, - GEORADIUS_WITH: GEORADIUS_WITH_1.default, - geoRadiusWith: GEORADIUS_WITH_1.default, - GEORADIUS: GEORADIUS_1.default, - geoRadius: GEORADIUS_1.default, - GEORADIUSBYMEMBER_RO_WITH: GEORADIUSBYMEMBER_RO_WITH_1.default, - geoRadiusByMemberRoWith: GEORADIUSBYMEMBER_RO_WITH_1.default, - GEORADIUSBYMEMBER_RO: GEORADIUSBYMEMBER_RO_1.default, - geoRadiusByMemberRo: GEORADIUSBYMEMBER_RO_1.default, - GEORADIUSBYMEMBER_STORE: GEORADIUSBYMEMBER_STORE_1.default, - geoRadiusByMemberStore: GEORADIUSBYMEMBER_STORE_1.default, - GEORADIUSBYMEMBER_WITH: GEORADIUSBYMEMBER_WITH_1.default, - geoRadiusByMemberWith: GEORADIUSBYMEMBER_WITH_1.default, - GEORADIUSBYMEMBER: GEORADIUSBYMEMBER_1.default, - geoRadiusByMember: GEORADIUSBYMEMBER_1.default, - GEOSEARCH_WITH: GEOSEARCH_WITH_1.default, - geoSearchWith: GEOSEARCH_WITH_1.default, - GEOSEARCH: GEOSEARCH_1.default, - geoSearch: GEOSEARCH_1.default, - GEOSEARCHSTORE: GEOSEARCHSTORE_1.default, - geoSearchStore: GEOSEARCHSTORE_1.default, - GET: GET_1.default, - get: GET_1.default, - GETBIT: GETBIT_1.default, - getBit: GETBIT_1.default, - GETDEL: GETDEL_1.default, - getDel: GETDEL_1.default, - GETEX: GETEX_1.default, - getEx: GETEX_1.default, - GETRANGE: GETRANGE_1.default, - getRange: GETRANGE_1.default, - GETSET: GETSET_1.default, - getSet: GETSET_1.default, - HDEL: HDEL_1.default, - hDel: HDEL_1.default, - HELLO: HELLO_1.default, - hello: HELLO_1.default, - HEXISTS: HEXISTS_1.default, - hExists: HEXISTS_1.default, - HEXPIRE: HEXPIRE_1.default, - hExpire: HEXPIRE_1.default, - HEXPIREAT: HEXPIREAT_1.default, - hExpireAt: HEXPIREAT_1.default, - HEXPIRETIME: HEXPIRETIME_1.default, - hExpireTime: HEXPIRETIME_1.default, - HGET: HGET_1.default, - hGet: HGET_1.default, - HGETALL: HGETALL_1.default, - hGetAll: HGETALL_1.default, - HGETDEL: HGETDEL_1.default, - hGetDel: HGETDEL_1.default, - HGETEX: HGETEX_1.default, - hGetEx: HGETEX_1.default, - HINCRBY: HINCRBY_1.default, - hIncrBy: HINCRBY_1.default, - HINCRBYFLOAT: HINCRBYFLOAT_1.default, - hIncrByFloat: HINCRBYFLOAT_1.default, - HKEYS: HKEYS_1.default, - hKeys: HKEYS_1.default, - HLEN: HLEN_1.default, - hLen: HLEN_1.default, - HMGET: HMGET_1.default, - hmGet: HMGET_1.default, - HPERSIST: HPERSIST_1.default, - hPersist: HPERSIST_1.default, - HPEXPIRE: HPEXPIRE_1.default, - hpExpire: HPEXPIRE_1.default, - HPEXPIREAT: HPEXPIREAT_1.default, - hpExpireAt: HPEXPIREAT_1.default, - HPEXPIRETIME: HPEXPIRETIME_1.default, - hpExpireTime: HPEXPIRETIME_1.default, - HPTTL: HPTTL_1.default, - hpTTL: HPTTL_1.default, - HRANDFIELD_COUNT_WITHVALUES: HRANDFIELD_COUNT_WITHVALUES_1.default, - hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES_1.default, - HRANDFIELD_COUNT: HRANDFIELD_COUNT_1.default, - hRandFieldCount: HRANDFIELD_COUNT_1.default, - HRANDFIELD: HRANDFIELD_1.default, - hRandField: HRANDFIELD_1.default, - HSCAN: HSCAN_1.default, - hScan: HSCAN_1.default, - HSCAN_NOVALUES: HSCAN_NOVALUES_1.default, - hScanNoValues: HSCAN_NOVALUES_1.default, - HSET: HSET_1.default, - hSet: HSET_1.default, - HSETEX: HSETEX_1.default, - hSetEx: HSETEX_1.default, - HSETNX: HSETNX_1.default, - hSetNX: HSETNX_1.default, - HSTRLEN: HSTRLEN_1.default, - hStrLen: HSTRLEN_1.default, - HTTL: HTTL_1.default, - hTTL: HTTL_1.default, - HVALS: HVALS_1.default, - hVals: HVALS_1.default, - INCR: INCR_1.default, - incr: INCR_1.default, - INCRBY: INCRBY_1.default, - incrBy: INCRBY_1.default, - INCRBYFLOAT: INCRBYFLOAT_1.default, - incrByFloat: INCRBYFLOAT_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - KEYS: KEYS_1.default, - keys: KEYS_1.default, - LASTSAVE: LASTSAVE_1.default, - lastSave: LASTSAVE_1.default, - LATENCY_DOCTOR: LATENCY_DOCTOR_1.default, - latencyDoctor: LATENCY_DOCTOR_1.default, - LATENCY_GRAPH: LATENCY_GRAPH_1.default, - latencyGraph: LATENCY_GRAPH_1.default, - LATENCY_HISTORY: LATENCY_HISTORY_1.default, - latencyHistory: LATENCY_HISTORY_1.default, - LATENCY_LATEST: LATENCY_LATEST_1.default, - latencyLatest: LATENCY_LATEST_1.default, - LATENCY_RESET: LATENCY_RESET_1.default, - latencyReset: LATENCY_RESET_1.default, - LCS_IDX_WITHMATCHLEN: LCS_IDX_WITHMATCHLEN_1.default, - lcsIdxWithMatchLen: LCS_IDX_WITHMATCHLEN_1.default, - LCS_IDX: LCS_IDX_1.default, - lcsIdx: LCS_IDX_1.default, - LCS_LEN: LCS_LEN_1.default, - lcsLen: LCS_LEN_1.default, - LCS: LCS_1.default, - lcs: LCS_1.default, - LINDEX: LINDEX_1.default, - lIndex: LINDEX_1.default, - LINSERT: LINSERT_1.default, - lInsert: LINSERT_1.default, - LLEN: LLEN_1.default, - lLen: LLEN_1.default, - LMOVE: LMOVE_1.default, - lMove: LMOVE_1.default, - LMPOP: LMPOP_1.default, - lmPop: LMPOP_1.default, - LOLWUT: LOLWUT_1.default, - LPOP_COUNT: LPOP_COUNT_1.default, - lPopCount: LPOP_COUNT_1.default, - LPOP: LPOP_1.default, - lPop: LPOP_1.default, - LPOS_COUNT: LPOS_COUNT_1.default, - lPosCount: LPOS_COUNT_1.default, - LPOS: LPOS_1.default, - lPos: LPOS_1.default, - LPUSH: LPUSH_1.default, - lPush: LPUSH_1.default, - LPUSHX: LPUSHX_1.default, - lPushX: LPUSHX_1.default, - LRANGE: LRANGE_1.default, - lRange: LRANGE_1.default, - LREM: LREM_1.default, - lRem: LREM_1.default, - LSET: LSET_1.default, - lSet: LSET_1.default, - LTRIM: LTRIM_1.default, - lTrim: LTRIM_1.default, - MEMORY_DOCTOR: MEMORY_DOCTOR_1.default, - memoryDoctor: MEMORY_DOCTOR_1.default, - "MEMORY_MALLOC-STATS": MEMORY_MALLOC_STATS_1.default, - memoryMallocStats: MEMORY_MALLOC_STATS_1.default, - MEMORY_PURGE: MEMORY_PURGE_1.default, - memoryPurge: MEMORY_PURGE_1.default, - MEMORY_STATS: MEMORY_STATS_1.default, - memoryStats: MEMORY_STATS_1.default, - MEMORY_USAGE: MEMORY_USAGE_1.default, - memoryUsage: MEMORY_USAGE_1.default, - MGET: MGET_1.default, - mGet: MGET_1.default, - MIGRATE: MIGRATE_1.default, - migrate: MIGRATE_1.default, - MODULE_LIST: MODULE_LIST_1.default, - moduleList: MODULE_LIST_1.default, - MODULE_LOAD: MODULE_LOAD_1.default, - moduleLoad: MODULE_LOAD_1.default, - MODULE_UNLOAD: MODULE_UNLOAD_1.default, - moduleUnload: MODULE_UNLOAD_1.default, - MOVE: MOVE_1.default, - move: MOVE_1.default, - MSET: MSET_1.default, - mSet: MSET_1.default, - MSETNX: MSETNX_1.default, - mSetNX: MSETNX_1.default, - OBJECT_ENCODING: OBJECT_ENCODING_1.default, - objectEncoding: OBJECT_ENCODING_1.default, - OBJECT_FREQ: OBJECT_FREQ_1.default, - objectFreq: OBJECT_FREQ_1.default, - OBJECT_IDLETIME: OBJECT_IDLETIME_1.default, - objectIdleTime: OBJECT_IDLETIME_1.default, - OBJECT_REFCOUNT: OBJECT_REFCOUNT_1.default, - objectRefCount: OBJECT_REFCOUNT_1.default, - PERSIST: PERSIST_1.default, - persist: PERSIST_1.default, - PEXPIRE: PEXPIRE_1.default, - pExpire: PEXPIRE_1.default, - PEXPIREAT: PEXPIREAT_1.default, - pExpireAt: PEXPIREAT_1.default, - PEXPIRETIME: PEXPIRETIME_1.default, - pExpireTime: PEXPIRETIME_1.default, - PFADD: PFADD_1.default, - pfAdd: PFADD_1.default, - PFCOUNT: PFCOUNT_1.default, - pfCount: PFCOUNT_1.default, - PFMERGE: PFMERGE_1.default, - pfMerge: PFMERGE_1.default, - PING: PING_1.default, - /** - * ping jsdoc - */ - ping: PING_1.default, - PSETEX: PSETEX_1.default, - pSetEx: PSETEX_1.default, - PTTL: PTTL_1.default, - pTTL: PTTL_1.default, - PUBLISH: PUBLISH_1.default, - publish: PUBLISH_1.default, - PUBSUB_CHANNELS: PUBSUB_CHANNELS_1.default, - pubSubChannels: PUBSUB_CHANNELS_1.default, - PUBSUB_NUMPAT: PUBSUB_NUMPAT_1.default, - pubSubNumPat: PUBSUB_NUMPAT_1.default, - PUBSUB_NUMSUB: PUBSUB_NUMSUB_1.default, - pubSubNumSub: PUBSUB_NUMSUB_1.default, - PUBSUB_SHARDNUMSUB: PUBSUB_SHARDNUMSUB_1.default, - pubSubShardNumSub: PUBSUB_SHARDNUMSUB_1.default, - PUBSUB_SHARDCHANNELS: PUBSUB_SHARDCHANNELS_1.default, - pubSubShardChannels: PUBSUB_SHARDCHANNELS_1.default, - RANDOMKEY: RANDOMKEY_1.default, - randomKey: RANDOMKEY_1.default, - READONLY: READONLY_1.default, - readonly: READONLY_1.default, - RENAME: RENAME_1.default, - rename: RENAME_1.default, - RENAMENX: RENAMENX_1.default, - renameNX: RENAMENX_1.default, - REPLICAOF: REPLICAOF_1.default, - replicaOf: REPLICAOF_1.default, - "RESTORE-ASKING": RESTORE_ASKING_1.default, - restoreAsking: RESTORE_ASKING_1.default, - RESTORE: RESTORE_1.default, - restore: RESTORE_1.default, - RPOP_COUNT: RPOP_COUNT_1.default, - rPopCount: RPOP_COUNT_1.default, - ROLE: ROLE_1.default, - role: ROLE_1.default, - RPOP: RPOP_1.default, - rPop: RPOP_1.default, - RPOPLPUSH: RPOPLPUSH_1.default, - rPopLPush: RPOPLPUSH_1.default, - RPUSH: RPUSH_1.default, - rPush: RPUSH_1.default, - RPUSHX: RPUSHX_1.default, - rPushX: RPUSHX_1.default, - SADD: SADD_1.default, - sAdd: SADD_1.default, - SCAN: SCAN_1.default, - scan: SCAN_1.default, - SCARD: SCARD_1.default, - sCard: SCARD_1.default, - SCRIPT_DEBUG: SCRIPT_DEBUG_1.default, - scriptDebug: SCRIPT_DEBUG_1.default, - SCRIPT_EXISTS: SCRIPT_EXISTS_1.default, - scriptExists: SCRIPT_EXISTS_1.default, - SCRIPT_FLUSH: SCRIPT_FLUSH_1.default, - scriptFlush: SCRIPT_FLUSH_1.default, - SCRIPT_KILL: SCRIPT_KILL_1.default, - scriptKill: SCRIPT_KILL_1.default, - SCRIPT_LOAD: SCRIPT_LOAD_1.default, - scriptLoad: SCRIPT_LOAD_1.default, - SDIFF: SDIFF_1.default, - sDiff: SDIFF_1.default, - SDIFFSTORE: SDIFFSTORE_1.default, - sDiffStore: SDIFFSTORE_1.default, - SET: SET_1.default, - set: SET_1.default, - SETBIT: SETBIT_1.default, - setBit: SETBIT_1.default, - SETEX: SETEX_1.default, - setEx: SETEX_1.default, - SETNX: SETNX_1.default, - setNX: SETNX_1.default, - SETRANGE: SETRANGE_1.default, - setRange: SETRANGE_1.default, - SINTER: SINTER_1.default, - sInter: SINTER_1.default, - SINTERCARD: SINTERCARD_1.default, - sInterCard: SINTERCARD_1.default, - SINTERSTORE: SINTERSTORE_1.default, - sInterStore: SINTERSTORE_1.default, - SISMEMBER: SISMEMBER_1.default, - sIsMember: SISMEMBER_1.default, - SMEMBERS: SMEMBERS_1.default, - sMembers: SMEMBERS_1.default, - SMISMEMBER: SMISMEMBER_1.default, - smIsMember: SMISMEMBER_1.default, - SMOVE: SMOVE_1.default, - sMove: SMOVE_1.default, - SORT_RO: SORT_RO_1.default, - sortRo: SORT_RO_1.default, - SORT_STORE: SORT_STORE_1.default, - sortStore: SORT_STORE_1.default, - SORT: SORT_1.default, - sort: SORT_1.default, - SPOP_COUNT: SPOP_COUNT_1.default, - sPopCount: SPOP_COUNT_1.default, - SPOP: SPOP_1.default, - sPop: SPOP_1.default, - SPUBLISH: SPUBLISH_1.default, - sPublish: SPUBLISH_1.default, - SRANDMEMBER_COUNT: SRANDMEMBER_COUNT_1.default, - sRandMemberCount: SRANDMEMBER_COUNT_1.default, - SRANDMEMBER: SRANDMEMBER_1.default, - sRandMember: SRANDMEMBER_1.default, - SREM: SREM_1.default, - sRem: SREM_1.default, - SSCAN: SSCAN_1.default, - sScan: SSCAN_1.default, - STRLEN: STRLEN_1.default, - strLen: STRLEN_1.default, - SUNION: SUNION_1.default, - sUnion: SUNION_1.default, - SUNIONSTORE: SUNIONSTORE_1.default, - sUnionStore: SUNIONSTORE_1.default, - SWAPDB: SWAPDB_1.default, - swapDb: SWAPDB_1.default, - TIME: TIME_1.default, - time: TIME_1.default, - TOUCH: TOUCH_1.default, - touch: TOUCH_1.default, - TTL: TTL_1.default, - ttl: TTL_1.default, - TYPE: TYPE_1.default, - type: TYPE_1.default, - UNLINK: UNLINK_1.default, - unlink: UNLINK_1.default, - WAIT: WAIT_1.default, - wait: WAIT_1.default, - XACK: XACK_1.default, - xAck: XACK_1.default, - XACKDEL: XACKDEL_1.default, - xAckDel: XACKDEL_1.default, - XADD_NOMKSTREAM: XADD_NOMKSTREAM_1.default, - xAddNoMkStream: XADD_NOMKSTREAM_1.default, - XADD: XADD_1.default, - xAdd: XADD_1.default, - XAUTOCLAIM_JUSTID: XAUTOCLAIM_JUSTID_1.default, - xAutoClaimJustId: XAUTOCLAIM_JUSTID_1.default, - XAUTOCLAIM: XAUTOCLAIM_1.default, - xAutoClaim: XAUTOCLAIM_1.default, - XCLAIM_JUSTID: XCLAIM_JUSTID_1.default, - xClaimJustId: XCLAIM_JUSTID_1.default, - XCLAIM: XCLAIM_1.default, - xClaim: XCLAIM_1.default, - XDEL: XDEL_1.default, - xDel: XDEL_1.default, - XDELEX: XDELEX_1.default, - xDelEx: XDELEX_1.default, - XGROUP_CREATE: XGROUP_CREATE_1.default, - xGroupCreate: XGROUP_CREATE_1.default, - XGROUP_CREATECONSUMER: XGROUP_CREATECONSUMER_1.default, - xGroupCreateConsumer: XGROUP_CREATECONSUMER_1.default, - XGROUP_DELCONSUMER: XGROUP_DELCONSUMER_1.default, - xGroupDelConsumer: XGROUP_DELCONSUMER_1.default, - XGROUP_DESTROY: XGROUP_DESTROY_1.default, - xGroupDestroy: XGROUP_DESTROY_1.default, - XGROUP_SETID: XGROUP_SETID_1.default, - xGroupSetId: XGROUP_SETID_1.default, - XINFO_CONSUMERS: XINFO_CONSUMERS_1.default, - xInfoConsumers: XINFO_CONSUMERS_1.default, - XINFO_GROUPS: XINFO_GROUPS_1.default, - xInfoGroups: XINFO_GROUPS_1.default, - XINFO_STREAM: XINFO_STREAM_1.default, - xInfoStream: XINFO_STREAM_1.default, - XLEN: XLEN_1.default, - xLen: XLEN_1.default, - XPENDING_RANGE: XPENDING_RANGE_1.default, - xPendingRange: XPENDING_RANGE_1.default, - XPENDING: XPENDING_1.default, - xPending: XPENDING_1.default, - XRANGE: XRANGE_1.default, - xRange: XRANGE_1.default, - XREAD: XREAD_1.default, - xRead: XREAD_1.default, - XREADGROUP: XREADGROUP_1.default, - xReadGroup: XREADGROUP_1.default, - XREVRANGE: XREVRANGE_1.default, - xRevRange: XREVRANGE_1.default, - XSETID: XSETID_1.default, - xSetId: XSETID_1.default, - XTRIM: XTRIM_1.default, - xTrim: XTRIM_1.default, - ZADD_INCR: ZADD_INCR_1.default, - zAddIncr: ZADD_INCR_1.default, - ZADD: ZADD_1.default, - zAdd: ZADD_1.default, - ZCARD: ZCARD_1.default, - zCard: ZCARD_1.default, - ZCOUNT: ZCOUNT_1.default, - zCount: ZCOUNT_1.default, - ZDIFF_WITHSCORES: ZDIFF_WITHSCORES_1.default, - zDiffWithScores: ZDIFF_WITHSCORES_1.default, - ZDIFF: ZDIFF_1.default, - zDiff: ZDIFF_1.default, - ZDIFFSTORE: ZDIFFSTORE_1.default, - zDiffStore: ZDIFFSTORE_1.default, - ZINCRBY: ZINCRBY_1.default, - zIncrBy: ZINCRBY_1.default, - ZINTER_WITHSCORES: ZINTER_WITHSCORES_1.default, - zInterWithScores: ZINTER_WITHSCORES_1.default, - ZINTER: ZINTER_1.default, - zInter: ZINTER_1.default, - ZINTERCARD: ZINTERCARD_1.default, - zInterCard: ZINTERCARD_1.default, - ZINTERSTORE: ZINTERSTORE_1.default, - zInterStore: ZINTERSTORE_1.default, - ZLEXCOUNT: ZLEXCOUNT_1.default, - zLexCount: ZLEXCOUNT_1.default, - ZMPOP: ZMPOP_1.default, - zmPop: ZMPOP_1.default, - ZMSCORE: ZMSCORE_1.default, - zmScore: ZMSCORE_1.default, - ZPOPMAX_COUNT: ZPOPMAX_COUNT_1.default, - zPopMaxCount: ZPOPMAX_COUNT_1.default, - ZPOPMAX: ZPOPMAX_1.default, - zPopMax: ZPOPMAX_1.default, - ZPOPMIN_COUNT: ZPOPMIN_COUNT_1.default, - zPopMinCount: ZPOPMIN_COUNT_1.default, - ZPOPMIN: ZPOPMIN_1.default, - zPopMin: ZPOPMIN_1.default, - ZRANDMEMBER_COUNT_WITHSCORES: ZRANDMEMBER_COUNT_WITHSCORES_1.default, - zRandMemberCountWithScores: ZRANDMEMBER_COUNT_WITHSCORES_1.default, - ZRANDMEMBER_COUNT: ZRANDMEMBER_COUNT_1.default, - zRandMemberCount: ZRANDMEMBER_COUNT_1.default, - ZRANDMEMBER: ZRANDMEMBER_1.default, - zRandMember: ZRANDMEMBER_1.default, - ZRANGE_WITHSCORES: ZRANGE_WITHSCORES_1.default, - zRangeWithScores: ZRANGE_WITHSCORES_1.default, - ZRANGE: ZRANGE_1.default, - zRange: ZRANGE_1.default, - ZRANGEBYLEX: ZRANGEBYLEX_1.default, - zRangeByLex: ZRANGEBYLEX_1.default, - ZRANGEBYSCORE_WITHSCORES: ZRANGEBYSCORE_WITHSCORES_1.default, - zRangeByScoreWithScores: ZRANGEBYSCORE_WITHSCORES_1.default, - ZRANGEBYSCORE: ZRANGEBYSCORE_1.default, - zRangeByScore: ZRANGEBYSCORE_1.default, - ZRANGESTORE: ZRANGESTORE_1.default, - zRangeStore: ZRANGESTORE_1.default, - ZRANK_WITHSCORE: ZRANK_WITHSCORE_1.default, - zRankWithScore: ZRANK_WITHSCORE_1.default, - ZRANK: ZRANK_1.default, - zRank: ZRANK_1.default, - ZREM: ZREM_1.default, - zRem: ZREM_1.default, - ZREMRANGEBYLEX: ZREMRANGEBYLEX_1.default, - zRemRangeByLex: ZREMRANGEBYLEX_1.default, - ZREMRANGEBYRANK: ZREMRANGEBYRANK_1.default, - zRemRangeByRank: ZREMRANGEBYRANK_1.default, - ZREMRANGEBYSCORE: ZREMRANGEBYSCORE_1.default, - zRemRangeByScore: ZREMRANGEBYSCORE_1.default, - ZREVRANK: ZREVRANK_1.default, - zRevRank: ZREVRANK_1.default, - ZSCAN: ZSCAN_1.default, - zScan: ZSCAN_1.default, - ZSCORE: ZSCORE_1.default, - zScore: ZSCORE_1.default, - ZUNION_WITHSCORES: ZUNION_WITHSCORES_1.default, - zUnionWithScores: ZUNION_WITHSCORES_1.default, - ZUNION: ZUNION_1.default, - zUnion: ZUNION_1.default, - ZUNIONSTORE: ZUNIONSTORE_1.default, - zUnionStore: ZUNIONSTORE_1.default, - VADD: VADD_1.default, - vAdd: VADD_1.default, - VCARD: VCARD_1.default, - vCard: VCARD_1.default, - VDIM: VDIM_1.default, - vDim: VDIM_1.default, - VEMB: VEMB_1.default, - vEmb: VEMB_1.default, - VEMB_RAW: VEMB_RAW_1.default, - vEmbRaw: VEMB_RAW_1.default, - VGETATTR: VGETATTR_1.default, - vGetAttr: VGETATTR_1.default, - VINFO: VINFO_1.default, - vInfo: VINFO_1.default, - VLINKS: VLINKS_1.default, - vLinks: VLINKS_1.default, - VLINKS_WITHSCORES: VLINKS_WITHSCORES_1.default, - vLinksWithScores: VLINKS_WITHSCORES_1.default, - VRANDMEMBER: VRANDMEMBER_1.default, - vRandMember: VRANDMEMBER_1.default, - VREM: VREM_1.default, - vRem: VREM_1.default, - VSETATTR: VSETATTR_1.default, - vSetAttr: VSETATTR_1.default, - VSIM: VSIM_1.default, - vSim: VSIM_1.default, - VSIM_WITHSCORES: VSIM_WITHSCORES_1.default, - vSimWithScores: VSIM_WITHSCORES_1.default - }; - } -}); -var require_enterprise_maintenance_manager = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/enterprise-maintenance-manager.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.emitDiagnostics = exports2.dbgMaintenance = exports2.MAINTENANCE_EVENTS = void 0; - var net_1 = __require2("net"); - var promises_1 = __require2("dns/promises"); - var node_assert_1 = __importDefault(__require2("node:assert")); - var promises_2 = __require2("node:timers/promises"); - var node_diagnostics_channel_1 = __importDefault(__require2("node:diagnostics_channel")); - exports2.MAINTENANCE_EVENTS = { - PAUSE_WRITING: "pause-writing", - RESUME_WRITING: "resume-writing", - TIMEOUTS_UPDATE: "timeouts-update" - }; - var PN = { - MOVING: "MOVING", - MIGRATING: "MIGRATING", - MIGRATED: "MIGRATED", - FAILING_OVER: "FAILING_OVER", - FAILED_OVER: "FAILED_OVER" - }; - var dbgMaintenance = (...args) => { - if (!process.env.REDIS_DEBUG_MAINTENANCE) - return; - return console.log("[MNT]", ...args); - }; - exports2.dbgMaintenance = dbgMaintenance; - var emitDiagnostics = (event) => { - if (!process.env.REDIS_EMIT_DIAGNOSTICS) - return; - const channel = node_diagnostics_channel_1.default.channel("redis.maintenance"); - channel.publish(event); - }; - exports2.emitDiagnostics = emitDiagnostics; - var EnterpriseMaintenanceManager = class { - #commandsQueue; - #options; - #isMaintenance = 0; - #client; - static setupDefaultMaintOptions(options2) { - if (options2.maintNotifications === void 0) { - options2.maintNotifications = options2?.RESP === 3 ? "auto" : "disabled"; - } - if (options2.maintEndpointType === void 0) { - options2.maintEndpointType = "auto"; - } - if (options2.maintRelaxedSocketTimeout === void 0) { - options2.maintRelaxedSocketTimeout = 1e4; - } - if (options2.maintRelaxedCommandTimeout === void 0) { - options2.maintRelaxedCommandTimeout = 1e4; - } - } - static async getHandshakeCommand(options2) { - if (options2.maintNotifications === "disabled") - return; - const host = options2.url ? new URL(options2.url).hostname : options2.socket?.host; - if (!host) - return; - const tls = options2.socket?.tls ?? false; - const movingEndpointType = await determineEndpoint(tls, host, options2); - return { - cmd: [ - "CLIENT", - "MAINT_NOTIFICATIONS", - "ON", - "moving-endpoint-type", - movingEndpointType - ], - errorHandler: (error2) => { - (0, exports2.dbgMaintenance)("handshake failed:", error2); - if (options2.maintNotifications === "enabled") { - throw error2; - } - } - }; - } - constructor(commandsQueue, client, options2) { - this.#commandsQueue = commandsQueue; - this.#options = options2; - this.#client = client; - this.#commandsQueue.addPushHandler(this.#onPush); - } - #onPush = (push) => { - (0, exports2.dbgMaintenance)("ONPUSH:", push.map(String)); - if (!Array.isArray(push) || !["MOVING", "MIGRATING", "MIGRATED", "FAILING_OVER", "FAILED_OVER"].includes(String(push[0]))) { - return false; - } - const type = String(push[0]); - (0, exports2.emitDiagnostics)({ - type, - timestamp: Date.now(), - data: { - push: push.map(String) - } - }); - switch (type) { - case PN.MOVING: { - const afterSeconds = push[2]; - const url2 = push[3] ? String(push[3]) : null; - (0, exports2.dbgMaintenance)("Received MOVING:", afterSeconds, url2); - this.#onMoving(afterSeconds, url2); - return true; - } - case PN.MIGRATING: - case PN.FAILING_OVER: { - (0, exports2.dbgMaintenance)("Received MIGRATING|FAILING_OVER"); - this.#onMigrating(); - return true; - } - case PN.MIGRATED: - case PN.FAILED_OVER: { - (0, exports2.dbgMaintenance)("Received MIGRATED|FAILED_OVER"); - this.#onMigrated(); - return true; - } - } - return false; - }; - // Queue: - // toWrite [ C D E ] - // waitingForReply [ A B ] - aka In-flight commands - // - // time: ---1-2---3-4-5-6--------------------------- - // - // 1. [EVENT] MOVING PN received - // 2. [ACTION] Pause writing ( we need to wait for new socket to connect and for all in-flight commands to complete ) - // 3. [EVENT] New socket connected - // 4. [EVENT] In-flight commands completed - // 5. [ACTION] Destroy old socket - // 6. [ACTION] Resume writing -> we are going to write to the new socket from now on - #onMoving = async (afterSeconds, url2) => { - this.#onMigrating(); - let host; - let port; - if (url2 === null) { - (0, node_assert_1.default)(this.#options.maintEndpointType === "none"); - (0, node_assert_1.default)(this.#options.socket !== void 0); - (0, node_assert_1.default)("host" in this.#options.socket); - (0, node_assert_1.default)(typeof this.#options.socket.host === "string"); - host = this.#options.socket.host; - (0, node_assert_1.default)(typeof this.#options.socket.port === "number"); - port = this.#options.socket.port; - const waitTime = afterSeconds * 1e3 / 2; - (0, exports2.dbgMaintenance)(`Wait for ${waitTime}ms`); - await (0, promises_2.setTimeout)(waitTime); - } else { - const split = url2.split(":"); - host = split[0]; - port = Number(split[1]); - } - (0, exports2.dbgMaintenance)("Pausing writing of new commands to old socket"); - this.#client._pause(); - (0, exports2.dbgMaintenance)("Creating new tmp client"); - let start = performance.now(); - if (this.#options.url) { - const u2 = new URL(this.#options.url); - u2.hostname = host; - u2.port = String(port); - this.#options.url = u2.toString(); - } else { - this.#options.socket = { - ...this.#options.socket, - host, - port - }; - } - const tmpClient = this.#client.duplicate(); - tmpClient.on("error", (error2) => { - (0, exports2.dbgMaintenance)(`[ERR]`, error2); - }); - (0, exports2.dbgMaintenance)(`Tmp client created in ${(performance.now() - start).toFixed(2)}ms`); - (0, exports2.dbgMaintenance)(`Set timeout for tmp client to ${this.#options.maintRelaxedSocketTimeout}`); - tmpClient._maintenanceUpdate({ - relaxedCommandTimeout: this.#options.maintRelaxedCommandTimeout, - relaxedSocketTimeout: this.#options.maintRelaxedSocketTimeout - }); - (0, exports2.dbgMaintenance)(`Connecting tmp client: ${host}:${port}`); - start = performance.now(); - await tmpClient.connect(); - (0, exports2.dbgMaintenance)(`Connected to tmp client in ${(performance.now() - start).toFixed(2)}ms`); - (0, exports2.dbgMaintenance)(`Wait for all in-flight commands to complete`); - await this.#commandsQueue.waitForInflightCommandsToComplete(); - (0, exports2.dbgMaintenance)(`In-flight commands completed`); - (0, exports2.dbgMaintenance)("Swap client sockets..."); - const oldSocket = this.#client._ejectSocket(); - const newSocket = tmpClient._ejectSocket(); - this.#client._insertSocket(newSocket); - tmpClient._insertSocket(oldSocket); - tmpClient.destroy(); - (0, exports2.dbgMaintenance)("Swap client sockets done."); - (0, exports2.dbgMaintenance)("Resume writing"); - this.#client._unpause(); - this.#onMigrated(); - }; - #onMigrating = () => { - this.#isMaintenance++; - if (this.#isMaintenance > 1) { - (0, exports2.dbgMaintenance)(`Timeout relaxation already done`); - return; - } - const update = { - relaxedCommandTimeout: this.#options.maintRelaxedCommandTimeout, - relaxedSocketTimeout: this.#options.maintRelaxedSocketTimeout - }; - this.#client._maintenanceUpdate(update); - }; - #onMigrated = () => { - this.#isMaintenance = Math.max(this.#isMaintenance - 1, 0); - if (this.#isMaintenance > 0) { - (0, exports2.dbgMaintenance)(`Not ready to unrelax timeouts yet`); - return; - } - const update = { - relaxedCommandTimeout: void 0, - relaxedSocketTimeout: void 0 - }; - this.#client._maintenanceUpdate(update); - }; - }; - exports2.default = EnterpriseMaintenanceManager; - function isPrivateIP(ip) { - const version3 = (0, net_1.isIP)(ip); - if (version3 === 4) { - const octets = ip.split(".").map(Number); - return octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168; - } - if (version3 === 6) { - return ip.startsWith("fc") || // Unique local - ip.startsWith("fd") || // Unique local - ip === "::1" || // Loopback - ip.startsWith("fe80"); - } - return false; - } - async function determineEndpoint(tlsEnabled, host, options2) { - (0, node_assert_1.default)(options2.maintEndpointType !== void 0); - if (options2.maintEndpointType !== "auto") { - (0, exports2.dbgMaintenance)(`Determine endpoint type: ${options2.maintEndpointType}`); - return options2.maintEndpointType; - } - const ip = (0, net_1.isIP)(host) ? host : (await (0, promises_1.lookup)(host, { family: 0 })).address; - const isPrivate = isPrivateIP(ip); - let result; - if (tlsEnabled) { - result = isPrivate ? "internal-fqdn" : "external-fqdn"; - } else { - result = isPrivate ? "internal-ip" : "external-ip"; - } - (0, exports2.dbgMaintenance)(`Determine endpoint type: ${result}`); - return result; - } - } -}); -var require_socket = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/socket.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var node_events_1 = __require2("node:events"); - var node_net_1 = __importDefault(__require2("node:net")); - var node_tls_1 = __importDefault(__require2("node:tls")); - var errors_1 = require_errors(); - var promises_1 = __require2("node:timers/promises"); - var enterprise_maintenance_manager_1 = require_enterprise_maintenance_manager(); - var RedisSocket = class extends node_events_1.EventEmitter { - #initiator; - #connectTimeout; - #reconnectStrategy; - #socketFactory; - #socketTimeout; - #maintenanceTimeout; - #socket; - #isOpen = false; - get isOpen() { - return this.#isOpen; - } - #isReady = false; - get isReady() { - return this.#isReady; - } - #isSocketUnrefed = false; - #socketEpoch = 0; - get socketEpoch() { - return this.#socketEpoch; - } - constructor(initiator, options2) { - super(); - this.#initiator = initiator; - this.#connectTimeout = options2?.connectTimeout ?? 5e3; - this.#reconnectStrategy = this.#createReconnectStrategy(options2); - this.#socketFactory = this.#createSocketFactory(options2); - this.#socketTimeout = options2?.socketTimeout; - } - #createReconnectStrategy(options2) { - const strategy = options2?.reconnectStrategy; - if (strategy === false || typeof strategy === "number") { - return () => strategy; - } - if (strategy) { - return (retries, cause) => { - try { - const retryIn = strategy(retries, cause); - if (retryIn !== false && !(retryIn instanceof Error) && typeof retryIn !== "number") { - throw new TypeError(`Reconnect strategy should return \`false | Error | number\`, got ${retryIn} instead`); - } - return retryIn; - } catch (err) { - this.emit("error", err); - return this.defaultReconnectStrategy(retries, err); - } - }; - } - return this.defaultReconnectStrategy; - } - #createSocketFactory(options2) { - if (options2?.tls === true) { - const withDefaults2 = { - ...options2, - port: options2?.port ?? 6379, - // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" - // @types/node is... incorrect... - // @ts-expect-error - noDelay: options2?.noDelay ?? true, - // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" - // @types/node is... incorrect... - // @ts-expect-error - keepAlive: options2?.keepAlive ?? true, - // https://nodejs.org/api/tls.html#tlsconnectoptions-callback "Any socket.connect() option not already listed" - // @types/node is... incorrect... - // @ts-expect-error - keepAliveInitialDelay: options2?.keepAliveInitialDelay ?? 5e3, - timeout: void 0, - onread: void 0, - readable: true, - writable: true - }; - return { - create() { - return node_tls_1.default.connect(withDefaults2); - }, - event: "secureConnect" - }; - } - if (options2 && "path" in options2) { - const withDefaults2 = { - ...options2, - timeout: void 0, - onread: void 0, - readable: true, - writable: true - }; - return { - create() { - return node_net_1.default.createConnection(withDefaults2); - }, - event: "connect" - }; - } - const withDefaults = { - ...options2, - port: options2?.port ?? 6379, - noDelay: options2?.noDelay ?? true, - keepAlive: options2?.keepAlive ?? true, - keepAliveInitialDelay: options2?.keepAliveInitialDelay ?? 5e3, - timeout: void 0, - onread: void 0, - readable: true, - writable: true - }; - return { - create() { - return node_net_1.default.createConnection(withDefaults); - }, - event: "connect" - }; - } - #shouldReconnect(retries, cause) { - const retryIn = this.#reconnectStrategy(retries, cause); - if (retryIn === false) { - this.#isOpen = false; - this.emit("error", cause); - return cause; - } else if (retryIn instanceof Error) { - this.#isOpen = false; - this.emit("error", cause); - return new errors_1.ReconnectStrategyError(retryIn, cause); - } - return retryIn; - } - async connect() { - if (this.#isOpen) { - throw new Error("Socket already opened"); - } - this.#isOpen = true; - return this.#connect(); - } - async #connect() { - let retries = 0; - do { - try { - this.#socket = await this.#createSocket(); - this.emit("connect"); - try { - await this.#initiator(); - } catch (err) { - this.#socket.destroy(); - this.#socket = void 0; - throw err; - } - this.#isReady = true; - this.#socketEpoch++; - this.emit("ready"); - } catch (err) { - const retryIn = this.#shouldReconnect(retries++, err); - if (typeof retryIn !== "number") { - throw retryIn; - } - this.emit("error", err); - await (0, promises_1.setTimeout)(retryIn); - this.emit("reconnecting"); - } - } while (this.#isOpen && !this.#isReady); - } - setMaintenanceTimeout(ms) { - (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Set socket timeout to ${ms}`); - if (this.#maintenanceTimeout === ms) { - (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Socket already set maintenanceCommandTimeout to ${ms}, skipping`); - return; - } - ; - this.#maintenanceTimeout = ms; - if (ms !== void 0) { - this.#socket?.setTimeout(ms); - } else { - this.#socket?.setTimeout(this.#socketTimeout ?? 0); - } - } - async #createSocket() { - const socket = this.#socketFactory.create(); - let onTimeout; - if (this.#connectTimeout !== void 0) { - onTimeout = () => socket.destroy(new errors_1.ConnectionTimeoutError()); - socket.once("timeout", onTimeout); - socket.setTimeout(this.#connectTimeout); - } - if (this.#isSocketUnrefed) { - socket.unref(); - } - await (0, node_events_1.once)(socket, this.#socketFactory.event); - if (onTimeout) { - socket.removeListener("timeout", onTimeout); - } - if (this.#socketTimeout) { - socket.once("timeout", () => { - const error2 = this.#maintenanceTimeout ? new errors_1.SocketTimeoutDuringMaintenanceError(this.#maintenanceTimeout) : new errors_1.SocketTimeoutError(this.#socketTimeout); - socket.destroy(error2); - }); - socket.setTimeout(this.#socketTimeout); - } - socket.once("error", (err) => this.#onSocketError(err)).once("close", (hadError) => { - if (hadError || !this.#isOpen || this.#socket !== socket) - return; - this.#onSocketError(new errors_1.SocketClosedUnexpectedlyError()); - }).on("drain", () => this.emit("drain")).on("data", (data) => this.emit("data", data)); - return socket; - } - #onSocketError(err) { - const wasReady = this.#isReady; - this.#isReady = false; - this.emit("error", err); - if (!wasReady || !this.#isOpen || typeof this.#shouldReconnect(0, err) !== "number") - return; - this.emit("reconnecting"); - this.#connect().catch(() => { - }); - } - write(iterable) { - if (!this.#socket) - return; - this.#socket.cork(); - for (const args of iterable) { - for (const toWrite of args) { - this.#socket.write(toWrite); - } - if (this.#socket.writableNeedDrain) - break; - } - this.#socket.uncork(); - } - async quit(fn) { - if (!this.#isOpen) { - throw new errors_1.ClientClosedError(); - } - this.#isOpen = false; - const reply = await fn(); - this.destroySocket(); - return reply; - } - close() { - if (!this.#isOpen) { - throw new errors_1.ClientClosedError(); - } - this.#isOpen = false; - } - destroy() { - if (!this.#isOpen) { - throw new errors_1.ClientClosedError(); - } - this.#isOpen = false; - this.destroySocket(); - } - destroySocket() { - this.#isReady = false; - if (this.#socket) { - this.#socket.destroy(); - this.#socket = void 0; - } - this.emit("end"); - } - ref() { - this.#isSocketUnrefed = false; - this.#socket?.ref(); - } - unref() { - this.#isSocketUnrefed = true; - this.#socket?.unref(); - } - defaultReconnectStrategy(retries, cause) { - if (cause instanceof errors_1.SocketTimeoutError) { - return false; - } - const jitter = Math.floor(Math.random() * 200); - const delay2 = Math.min(Math.pow(2, retries) * 50, 2e3); - return delay2 + jitter; - } - }; - exports2.default = RedisSocket; - } -}); -var require_token = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/token.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.Token = void 0; - var Token = class { - value; - expiresAtMs; - receivedAtMs; - constructor(value, expiresAtMs, receivedAtMs) { - this.value = value; - this.expiresAtMs = expiresAtMs; - this.receivedAtMs = receivedAtMs; - } - /** - * Returns the time-to-live of the token in milliseconds. - * @param now The current time in milliseconds since the Unix epoch. - */ - getTtlMs(now) { - if (this.expiresAtMs < now) { - return 0; - } - return this.expiresAtMs - now; - } - }; - exports2.Token = Token; - } -}); -var require_token_manager = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/token-manager.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.TokenManager = exports2.IDPError = void 0; - var token_1 = require_token(); - var IDPError = class extends Error { - message; - isRetryable; - constructor(message, isRetryable) { - super(message); - this.message = message; - this.isRetryable = isRetryable; - this.name = "IDPError"; - } - }; - exports2.IDPError = IDPError; - var TokenManager = class { - identityProvider; - config; - currentToken = null; - refreshTimeout = null; - listener = null; - retryAttempt = 0; - constructor(identityProvider, config2) { - this.identityProvider = identityProvider; - this.config = config2; - if (this.config.expirationRefreshRatio > 1) { - throw new Error("expirationRefreshRatio must be less than or equal to 1"); - } - if (this.config.expirationRefreshRatio < 0) { - throw new Error("expirationRefreshRatio must be greater or equal to 0"); - } - } - /** - * Starts the token manager and returns a Disposable that can be used to stop the token manager. - * - * @param listener The listener that will receive token updates. - * @param initialDelayMs The initial delay in milliseconds before the first token refresh. - */ - start(listener, initialDelayMs = 0) { - if (this.listener) { - this.stop(); - } - this.listener = listener; - this.retryAttempt = 0; - this.scheduleNextRefresh(initialDelayMs); - return { - dispose: () => this.stop() - }; - } - calculateRetryDelay() { - if (!this.config.retry) - return 0; - const { initialDelayMs, maxDelayMs, backoffMultiplier, jitterPercentage } = this.config.retry; - let delay2 = initialDelayMs * Math.pow(backoffMultiplier, this.retryAttempt - 1); - delay2 = Math.min(delay2, maxDelayMs); - if (jitterPercentage) { - const jitterRange = delay2 * (jitterPercentage / 100); - const jitterAmount = Math.random() * jitterRange - jitterRange / 2; - delay2 += jitterAmount; - } - let result = Math.max(0, Math.floor(delay2)); - return result; - } - shouldRetry(error2) { - if (!this.config.retry) - return false; - const { maxAttempts, isRetryable } = this.config.retry; - if (this.retryAttempt >= maxAttempts) { - return false; - } - if (isRetryable) { - return isRetryable(error2, this.retryAttempt); - } - return false; - } - isRunning() { - return this.listener !== null; - } - async refresh() { - if (!this.listener) { - throw new Error("TokenManager is not running, but refresh was called"); - } - try { - await this.identityProvider.requestToken().then(this.handleNewToken); - this.retryAttempt = 0; - } catch (error2) { - if (this.shouldRetry(error2)) { - this.retryAttempt++; - const retryDelay = this.calculateRetryDelay(); - this.notifyError(`Token refresh failed (attempt ${this.retryAttempt}), retrying in ${retryDelay}ms: ${error2}`, true); - this.scheduleNextRefresh(retryDelay); - } else { - this.notifyError(error2, false); - this.stop(); - } - } - } - handleNewToken = async ({ token: nativeToken, ttlMs }) => { - if (!this.listener) { - throw new Error("TokenManager is not running, but a new token was received"); - } - const token = this.wrapAndSetCurrentToken(nativeToken, ttlMs); - this.listener.onNext(token); - this.scheduleNextRefresh(this.calculateRefreshTime(token)); - }; - /** - * Creates a Token object from a native token and sets it as the current token. - * - * @param nativeToken - The raw token received from the identity provider - * @param ttlMs - Time-to-live in milliseconds for the token - * - * @returns A new Token instance containing the wrapped native token and expiration details - * - */ - wrapAndSetCurrentToken(nativeToken, ttlMs) { - const now = Date.now(); - const token = new token_1.Token(nativeToken, now + ttlMs, now); - this.currentToken = token; - return token; - } - scheduleNextRefresh(delayMs) { - if (this.refreshTimeout) { - clearTimeout(this.refreshTimeout); - this.refreshTimeout = null; - } - if (delayMs === 0) { - this.refresh(); - } else { - this.refreshTimeout = setTimeout(() => this.refresh(), delayMs); - } - } - /** - * Calculates the time in milliseconds when the token should be refreshed - * based on the token's TTL and the expirationRefreshRatio configuration. - * - * @param token The token to calculate the refresh time for. - * @param now The current time in milliseconds. Defaults to Date.now(). - */ - calculateRefreshTime(token, now = Date.now()) { - const ttlMs = token.getTtlMs(now); - return Math.floor(ttlMs * this.config.expirationRefreshRatio); - } - stop() { - if (this.refreshTimeout) { - clearTimeout(this.refreshTimeout); - this.refreshTimeout = null; - } - this.listener = null; - this.currentToken = null; - this.retryAttempt = 0; - } - /** - * Returns the current token or null if no token is available. - */ - getCurrentToken() { - return this.currentToken; - } - notifyError(error2, isRetryable) { - const errorMessage = error2 instanceof Error ? error2.message : String(error2); - if (!this.listener) { - throw new Error(`TokenManager is not running but received an error: ${errorMessage}`); - } - this.listener.onError(new IDPError(errorMessage, isRetryable)); - } - }; - exports2.TokenManager = TokenManager; - } -}); -var require_credentials_provider = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/credentials-provider.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.UnableToObtainNewCredentialsError = exports2.CredentialsError = void 0; - var CredentialsError = class extends Error { - constructor(message) { - super(`Re-authentication with latest credentials failed: ${message}`); - this.name = "CredentialsError"; - } - }; - exports2.CredentialsError = CredentialsError; - var UnableToObtainNewCredentialsError = class extends Error { - constructor(message) { - super(`Unable to obtain new credentials : ${message}`); - this.name = "UnableToObtainNewCredentialsError"; - } - }; - exports2.UnableToObtainNewCredentialsError = UnableToObtainNewCredentialsError; - } -}); -var require_authx = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/authx/index.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.Token = exports2.CredentialsError = exports2.UnableToObtainNewCredentialsError = exports2.IDPError = exports2.TokenManager = void 0; - var token_manager_1 = require_token_manager(); - Object.defineProperty(exports2, "TokenManager", { enumerable: true, get: function() { - return token_manager_1.TokenManager; - } }); - Object.defineProperty(exports2, "IDPError", { enumerable: true, get: function() { - return token_manager_1.IDPError; - } }); - var credentials_provider_1 = require_credentials_provider(); - Object.defineProperty(exports2, "UnableToObtainNewCredentialsError", { enumerable: true, get: function() { - return credentials_provider_1.UnableToObtainNewCredentialsError; - } }); - Object.defineProperty(exports2, "CredentialsError", { enumerable: true, get: function() { - return credentials_provider_1.CredentialsError; - } }); - var token_1 = require_token(); - Object.defineProperty(exports2, "Token", { enumerable: true, get: function() { - return token_1.Token; - } }); - } -}); -var require_linked_list = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/linked-list.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.EmptyAwareSinglyLinkedList = exports2.SinglyLinkedList = exports2.DoublyLinkedList = void 0; - var events_1 = __importDefault(__require2("events")); - var DoublyLinkedList = class { - #length = 0; - get length() { - return this.#length; - } - #head; - get head() { - return this.#head; - } - #tail; - get tail() { - return this.#tail; - } - push(value) { - ++this.#length; - if (this.#tail === void 0) { - return this.#head = this.#tail = { - previous: this.#head, - next: void 0, - value - }; - } - return this.#tail = this.#tail.next = { - previous: this.#tail, - next: void 0, - value - }; - } - unshift(value) { - ++this.#length; - if (this.#head === void 0) { - return this.#head = this.#tail = { - previous: void 0, - next: void 0, - value - }; - } - return this.#head = this.#head.previous = { - previous: void 0, - next: this.#head, - value - }; - } - add(value, prepend = false) { - return prepend ? this.unshift(value) : this.push(value); - } - shift() { - if (this.#head === void 0) - return void 0; - --this.#length; - const node = this.#head; - if (node.next) { - node.next.previous = void 0; - this.#head = node.next; - node.next = void 0; - } else { - this.#head = this.#tail = void 0; - } - return node.value; - } - remove(node) { - if (this.#length === 0) - return; - --this.#length; - if (this.#tail === node) { - this.#tail = node.previous; - } - if (this.#head === node) { - this.#head = node.next; - } else { - if (node.previous) { - node.previous.next = node.next; - } - if (node.next) { - node.next.previous = node.previous; - } - } - node.previous = void 0; - node.next = void 0; - } - reset() { - this.#length = 0; - this.#head = this.#tail = void 0; - } - *[Symbol.iterator]() { - let node = this.#head; - while (node !== void 0) { - yield node.value; - node = node.next; - } - } - *nodes() { - let node = this.#head; - while (node) { - const next = node.next; - yield node; - node = next; - } - } - }; - exports2.DoublyLinkedList = DoublyLinkedList; - var SinglyLinkedList = class { - #length = 0; - get length() { - return this.#length; - } - #head; - get head() { - return this.#head; - } - #tail; - get tail() { - return this.#tail; - } - push(value) { - ++this.#length; - const node = { - value, - next: void 0, - removed: false - }; - if (this.#head === void 0) { - return this.#head = this.#tail = node; - } - return this.#tail.next = this.#tail = node; - } - remove(node, parent) { - if (node.removed) { - throw new Error("node already removed"); - } - --this.#length; - if (this.#head === node) { - if (this.#tail === node) { - this.#head = this.#tail = void 0; - } else { - this.#head = node.next; - } - } else if (this.#tail === node) { - this.#tail = parent; - parent.next = void 0; - } else { - parent.next = node.next; - } - node.removed = true; - } - shift() { - if (this.#head === void 0) - return void 0; - const node = this.#head; - if (--this.#length === 0) { - this.#head = this.#tail = void 0; - } else { - this.#head = node.next; - } - node.removed = true; - return node.value; - } - reset() { - this.#length = 0; - this.#head = this.#tail = void 0; - } - *[Symbol.iterator]() { - let node = this.#head; - while (node !== void 0) { - yield node.value; - node = node.next; - } - } - }; - exports2.SinglyLinkedList = SinglyLinkedList; - var EmptyAwareSinglyLinkedList = class extends SinglyLinkedList { - events = new events_1.default(); - reset() { - const old = this.length; - super.reset(); - if (old !== this.length && this.length === 0) { - this.events.emit("empty"); - } - } - shift() { - const old = this.length; - const ret = super.shift(); - if (old !== this.length && this.length === 0) { - this.events.emit("empty"); - } - return ret; - } - remove(node, parent) { - const old = this.length; - super.remove(node, parent); - if (old !== this.length && this.length === 0) { - this.events.emit("empty"); - } - } - }; - exports2.EmptyAwareSinglyLinkedList = EmptyAwareSinglyLinkedList; - } -}); -var require_encoder = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/RESP/encoder.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var CRLF2 = "\r\n"; - function encodeCommand(args) { - const toWrite = []; - let strings = "*" + args.length + CRLF2; - for (let i2 = 0; i2 < args.length; i2++) { - const arg = args[i2]; - if (typeof arg === "string") { - strings += "$" + Buffer.byteLength(arg) + CRLF2 + arg + CRLF2; - } else if (arg instanceof Buffer) { - toWrite.push(strings + "$" + arg.length.toString() + CRLF2, arg); - strings = CRLF2; - } else { - throw new TypeError(`"arguments[${i2}]" must be of type "string | Buffer", got ${typeof arg} instead.`); - } - } - toWrite.push(strings); - return toWrite; - } - exports2.default = encodeCommand; - } -}); -var require_pub_sub = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/pub-sub.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.PubSub = exports2.PUBSUB_TYPE = void 0; - exports2.PUBSUB_TYPE = { - CHANNELS: "CHANNELS", - PATTERNS: "PATTERNS", - SHARDED: "SHARDED" - }; - var COMMANDS = { - [exports2.PUBSUB_TYPE.CHANNELS]: { - subscribe: Buffer.from("subscribe"), - unsubscribe: Buffer.from("unsubscribe"), - message: Buffer.from("message") - }, - [exports2.PUBSUB_TYPE.PATTERNS]: { - subscribe: Buffer.from("psubscribe"), - unsubscribe: Buffer.from("punsubscribe"), - message: Buffer.from("pmessage") - }, - [exports2.PUBSUB_TYPE.SHARDED]: { - subscribe: Buffer.from("ssubscribe"), - unsubscribe: Buffer.from("sunsubscribe"), - message: Buffer.from("smessage") - } - }; - var PubSub = class _PubSub { - static isStatusReply(reply) { - return COMMANDS[exports2.PUBSUB_TYPE.CHANNELS].subscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.CHANNELS].unsubscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.PATTERNS].subscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.PATTERNS].unsubscribe.equals(reply[0]) || COMMANDS[exports2.PUBSUB_TYPE.SHARDED].subscribe.equals(reply[0]); - } - static isShardedUnsubscribe(reply) { - return COMMANDS[exports2.PUBSUB_TYPE.SHARDED].unsubscribe.equals(reply[0]); - } - static #channelsArray(channels) { - return Array.isArray(channels) ? channels : [channels]; - } - static #listenersSet(listeners, returnBuffers) { - return returnBuffers ? listeners.buffers : listeners.strings; - } - #subscribing = 0; - #isActive = false; - get isActive() { - return this.#isActive; - } - listeners = { - [exports2.PUBSUB_TYPE.CHANNELS]: /* @__PURE__ */ new Map(), - [exports2.PUBSUB_TYPE.PATTERNS]: /* @__PURE__ */ new Map(), - [exports2.PUBSUB_TYPE.SHARDED]: /* @__PURE__ */ new Map() - }; - subscribe(type, channels, listener, returnBuffers) { - const args = [COMMANDS[type].subscribe], channelsArray = _PubSub.#channelsArray(channels); - for (const channel of channelsArray) { - let channelListeners = this.listeners[type].get(channel); - if (!channelListeners || channelListeners.unsubscribing) { - args.push(channel); - } - } - if (args.length === 1) { - for (const channel of channelsArray) { - _PubSub.#listenersSet(this.listeners[type].get(channel), returnBuffers).add(listener); - } - return; - } - this.#isActive = true; - this.#subscribing++; - return { - args, - channelsCounter: args.length - 1, - resolve: () => { - this.#subscribing--; - for (const channel of channelsArray) { - let listeners = this.listeners[type].get(channel); - if (!listeners) { - listeners = { - unsubscribing: false, - buffers: /* @__PURE__ */ new Set(), - strings: /* @__PURE__ */ new Set() - }; - this.listeners[type].set(channel, listeners); - } - _PubSub.#listenersSet(listeners, returnBuffers).add(listener); - } - }, - reject: () => { - this.#subscribing--; - this.#updateIsActive(); - } - }; - } - extendChannelListeners(type, channel, listeners) { - if (!this.#extendChannelListeners(type, channel, listeners)) - return; - this.#isActive = true; - this.#subscribing++; - return { - args: [ - COMMANDS[type].subscribe, - channel - ], - channelsCounter: 1, - resolve: () => this.#subscribing--, - reject: () => { - this.#subscribing--; - this.#updateIsActive(); - } - }; - } - #extendChannelListeners(type, channel, listeners) { - const existingListeners = this.listeners[type].get(channel); - if (!existingListeners) { - this.listeners[type].set(channel, listeners); - return true; - } - for (const listener of listeners.buffers) { - existingListeners.buffers.add(listener); - } - for (const listener of listeners.strings) { - existingListeners.strings.add(listener); - } - return false; - } - extendTypeListeners(type, listeners) { - const args = [COMMANDS[type].subscribe]; - for (const [channel, channelListeners] of listeners) { - if (this.#extendChannelListeners(type, channel, channelListeners)) { - args.push(channel); - } - } - if (args.length === 1) - return; - this.#isActive = true; - this.#subscribing++; - return { - args, - channelsCounter: args.length - 1, - resolve: () => this.#subscribing--, - reject: () => { - this.#subscribing--; - this.#updateIsActive(); - } - }; - } - unsubscribe(type, channels, listener, returnBuffers) { - const listeners = this.listeners[type]; - if (!channels) { - return this.#unsubscribeCommand( - [COMMANDS[type].unsubscribe], - // cannot use `this.#subscribed` because there might be some `SUBSCRIBE` commands in the queue - // cannot use `this.#subscribed + this.#subscribing` because some `SUBSCRIBE` commands might fail - NaN, - () => listeners.clear() - ); - } - const channelsArray = _PubSub.#channelsArray(channels); - if (!listener) { - return this.#unsubscribeCommand([COMMANDS[type].unsubscribe, ...channelsArray], channelsArray.length, () => { - for (const channel of channelsArray) { - listeners.delete(channel); - } - }); - } - const args = [COMMANDS[type].unsubscribe]; - for (const channel of channelsArray) { - const sets = listeners.get(channel); - if (sets) { - let current, other; - if (returnBuffers) { - current = sets.buffers; - other = sets.strings; - } else { - current = sets.strings; - other = sets.buffers; - } - const currentSize = current.has(listener) ? current.size - 1 : current.size; - if (currentSize !== 0 || other.size !== 0) - continue; - sets.unsubscribing = true; - } - args.push(channel); - } - if (args.length === 1) { - for (const channel of channelsArray) { - _PubSub.#listenersSet(listeners.get(channel), returnBuffers).delete(listener); - } - return; - } - return this.#unsubscribeCommand(args, args.length - 1, () => { - for (const channel of channelsArray) { - const sets = listeners.get(channel); - if (!sets) - continue; - (returnBuffers ? sets.buffers : sets.strings).delete(listener); - if (sets.buffers.size === 0 && sets.strings.size === 0) { - listeners.delete(channel); - } - } - }); - } - #unsubscribeCommand(args, channelsCounter, removeListeners) { - return { - args, - channelsCounter, - resolve: () => { - removeListeners(); - this.#updateIsActive(); - }, - reject: void 0 - }; - } - #updateIsActive() { - this.#isActive = this.listeners[exports2.PUBSUB_TYPE.CHANNELS].size !== 0 || this.listeners[exports2.PUBSUB_TYPE.PATTERNS].size !== 0 || this.listeners[exports2.PUBSUB_TYPE.SHARDED].size !== 0 || this.#subscribing !== 0; - } - reset() { - this.#isActive = false; - this.#subscribing = 0; - } - resubscribe() { - const commands = []; - for (const [type, listeners] of Object.entries(this.listeners)) { - if (!listeners.size) - continue; - this.#isActive = true; - if (type === exports2.PUBSUB_TYPE.SHARDED) { - this.#shardedResubscribe(commands, listeners); - } else { - this.#normalResubscribe(commands, type, listeners); - } - } - return commands; - } - #normalResubscribe(commands, type, listeners) { - this.#subscribing++; - const callback = () => this.#subscribing--; - commands.push({ - args: [ - COMMANDS[type].subscribe, - ...listeners.keys() - ], - channelsCounter: listeners.size, - resolve: callback, - reject: callback - }); - } - #shardedResubscribe(commands, listeners) { - const callback = () => this.#subscribing--; - for (const channel of listeners.keys()) { - this.#subscribing++; - commands.push({ - args: [ - COMMANDS[exports2.PUBSUB_TYPE.SHARDED].subscribe, - channel - ], - channelsCounter: 1, - resolve: callback, - reject: callback - }); - } - } - handleMessageReply(reply) { - if (COMMANDS[exports2.PUBSUB_TYPE.CHANNELS].message.equals(reply[0])) { - this.#emitPubSubMessage(exports2.PUBSUB_TYPE.CHANNELS, reply[2], reply[1]); - return true; - } else if (COMMANDS[exports2.PUBSUB_TYPE.PATTERNS].message.equals(reply[0])) { - this.#emitPubSubMessage(exports2.PUBSUB_TYPE.PATTERNS, reply[3], reply[2], reply[1]); - return true; - } else if (COMMANDS[exports2.PUBSUB_TYPE.SHARDED].message.equals(reply[0])) { - this.#emitPubSubMessage(exports2.PUBSUB_TYPE.SHARDED, reply[2], reply[1]); - return true; - } - return false; - } - removeShardedListeners(channel) { - const listeners = this.listeners[exports2.PUBSUB_TYPE.SHARDED].get(channel); - this.listeners[exports2.PUBSUB_TYPE.SHARDED].delete(channel); - this.#updateIsActive(); - return listeners; - } - removeAllListeners() { - const result = { - [exports2.PUBSUB_TYPE.CHANNELS]: this.listeners[exports2.PUBSUB_TYPE.CHANNELS], - [exports2.PUBSUB_TYPE.PATTERNS]: this.listeners[exports2.PUBSUB_TYPE.PATTERNS], - [exports2.PUBSUB_TYPE.SHARDED]: this.listeners[exports2.PUBSUB_TYPE.SHARDED] - }; - this.#updateIsActive(); - this.listeners[exports2.PUBSUB_TYPE.CHANNELS] = /* @__PURE__ */ new Map(); - this.listeners[exports2.PUBSUB_TYPE.PATTERNS] = /* @__PURE__ */ new Map(); - this.listeners[exports2.PUBSUB_TYPE.SHARDED] = /* @__PURE__ */ new Map(); - return result; - } - #emitPubSubMessage(type, message, channel, pattern) { - const keyString = (pattern ?? channel).toString(), listeners = this.listeners[type].get(keyString); - if (!listeners) - return; - for (const listener of listeners.buffers) { - listener(message, channel); - } - if (!listeners.strings.size) - return; - const channelString = pattern ? channel.toString() : keyString, messageString = channelString === "__redis__:invalidate" ? ( - // https://github.com/redis/redis/pull/7469 - // https://github.com/redis/redis/issues/7463 - message === null ? null : message.map((x3) => x3.toString()) - ) : message.toString(); - for (const listener of listeners.strings) { - listener(messageString, channelString); - } - } - }; - exports2.PubSub = PubSub; - } -}); -var require_commands_queue = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/commands-queue.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var linked_list_1 = require_linked_list(); - var encoder_1 = __importDefault(require_encoder()); - var decoder_1 = require_decoder(); - var pub_sub_1 = require_pub_sub(); - var errors_1 = require_errors(); - var enterprise_maintenance_manager_1 = require_enterprise_maintenance_manager(); - var PONG2 = Buffer.from("pong"); - var RESET = Buffer.from("RESET"); - var RESP2_PUSH_TYPE_MAPPING = { - ...decoder_1.PUSH_TYPE_MAPPING, - [decoder_1.RESP_TYPES.SIMPLE_STRING]: Buffer - }; - var RedisCommandsQueue = class _RedisCommandsQueue { - #respVersion; - #maxLength; - #toWrite = new linked_list_1.DoublyLinkedList(); - #waitingForReply = new linked_list_1.EmptyAwareSinglyLinkedList(); - #onShardedChannelMoved; - #chainInExecution; - decoder; - #pubSub = new pub_sub_1.PubSub(); - #pushHandlers = [this.#onPush.bind(this)]; - #maintenanceCommandTimeout; - setMaintenanceCommandTimeout(ms) { - if (this.#maintenanceCommandTimeout === ms) { - (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Queue already set maintenanceCommandTimeout to ${ms}, skipping`); - return; - } - ; - (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Setting maintenance command timeout to ${ms}`); - this.#maintenanceCommandTimeout = ms; - if (this.#maintenanceCommandTimeout === void 0) { - (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Queue will keep maintenanceCommandTimeout for exisitng commands, just to be on the safe side. New commands will receive normal timeouts`); - return; - } - let counter = 0; - const total = this.#toWrite.length; - for (const node of this.#toWrite.nodes()) { - const command2 = node.value; - _RedisCommandsQueue.#removeTimeoutListener(command2); - counter++; - const newTimeout = this.#maintenanceCommandTimeout; - const signal = AbortSignal.timeout(newTimeout); - command2.timeout = { - signal, - listener: () => { - this.#toWrite.remove(node); - command2.reject(new errors_1.CommandTimeoutDuringMaintenanceError(newTimeout)); - }, - originalTimeout: command2.timeout?.originalTimeout - }; - signal.addEventListener("abort", command2.timeout.listener, { once: true }); - } - ; - (0, enterprise_maintenance_manager_1.dbgMaintenance)(`Total of ${counter} of ${total} timeouts reset to ${ms}`); - } - get isPubSubActive() { - return this.#pubSub.isActive; - } - constructor(respVersion, maxLength, onShardedChannelMoved) { - this.#respVersion = respVersion; - this.#maxLength = maxLength; - this.#onShardedChannelMoved = onShardedChannelMoved; - this.decoder = this.#initiateDecoder(); - } - #onReply(reply) { - this.#waitingForReply.shift().resolve(reply); - } - #onErrorReply(err) { - this.#waitingForReply.shift().reject(err); - } - #onPush(push) { - if (this.#pubSub.handleMessageReply(push)) - return true; - const isShardedUnsubscribe = pub_sub_1.PubSub.isShardedUnsubscribe(push); - if (isShardedUnsubscribe && !this.#waitingForReply.length) { - const channel = push[1].toString(); - this.#onShardedChannelMoved(channel, this.#pubSub.removeShardedListeners(channel)); - return true; - } else if (isShardedUnsubscribe || pub_sub_1.PubSub.isStatusReply(push)) { - const head = this.#waitingForReply.head.value; - if (Number.isNaN(head.channelsCounter) && push[2] === 0 || --head.channelsCounter === 0) { - this.#waitingForReply.shift().resolve(); - } - return true; - } - return false; - } - #getTypeMapping() { - return this.#waitingForReply.head.value.typeMapping ?? {}; - } - #initiateDecoder() { - return new decoder_1.Decoder({ - onReply: (reply) => this.#onReply(reply), - onErrorReply: (err) => this.#onErrorReply(err), - //TODO: we can shave off a few cycles by not adding onPush handler at all if CSC is not used - onPush: (push) => { - for (const pushHandler of this.#pushHandlers) { - if (pushHandler(push)) - return; - } - }, - getTypeMapping: () => this.#getTypeMapping() - }); - } - addPushHandler(handler) { - this.#pushHandlers.push(handler); - } - async waitForInflightCommandsToComplete() { - if (this.#waitingForReply.length === 0) { - return; - } - ; - return new Promise((resolve82) => { - this.#waitingForReply.events.on("empty", resolve82); - }); - } - addCommand(args, options2) { - if (this.#maxLength && this.#toWrite.length + this.#waitingForReply.length >= this.#maxLength) { - return Promise.reject(new Error("The queue is full")); - } else if (options2?.abortSignal?.aborted) { - return Promise.reject(new errors_1.AbortError()); - } - return new Promise((resolve82, reject) => { - let node; - const value = { - args, - chainId: options2?.chainId, - abort: void 0, - timeout: void 0, - resolve: resolve82, - reject, - channelsCounter: void 0, - typeMapping: options2?.typeMapping - }; - const timeout = this.#maintenanceCommandTimeout ?? options2?.timeout; - const wasInMaintenance = this.#maintenanceCommandTimeout !== void 0; - if (timeout) { - const signal2 = AbortSignal.timeout(timeout); - value.timeout = { - signal: signal2, - listener: () => { - this.#toWrite.remove(node); - value.reject(wasInMaintenance ? new errors_1.CommandTimeoutDuringMaintenanceError(timeout) : new errors_1.TimeoutError()); - }, - originalTimeout: options2?.timeout - }; - signal2.addEventListener("abort", value.timeout.listener, { once: true }); - } - const signal = options2?.abortSignal; - if (signal) { - value.abort = { - signal, - listener: () => { - this.#toWrite.remove(node); - value.reject(new errors_1.AbortError()); - } - }; - signal.addEventListener("abort", value.abort.listener, { once: true }); - } - node = this.#toWrite.add(value, options2?.asap); - }); - } - #addPubSubCommand(command2, asap = false, chainId) { - return new Promise((resolve82, reject) => { - this.#toWrite.add({ - args: command2.args, - chainId, - abort: void 0, - timeout: void 0, - resolve() { - command2.resolve(); - resolve82(); - }, - reject(err) { - command2.reject?.(); - reject(err); - }, - channelsCounter: command2.channelsCounter, - typeMapping: decoder_1.PUSH_TYPE_MAPPING - }, asap); - }); - } - #setupPubSubHandler() { - if (this.#respVersion !== 2) - return; - this.decoder.onReply = (reply) => { - if (Array.isArray(reply)) { - if (this.#onPush(reply)) - return; - if (PONG2.equals(reply[0])) { - const { resolve: resolve82, typeMapping } = this.#waitingForReply.shift(), buffer = reply[1].length === 0 ? reply[0] : reply[1]; - resolve82(typeMapping?.[decoder_1.RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); - return; - } - } - return this.#onReply(reply); - }; - this.decoder.getTypeMapping = () => RESP2_PUSH_TYPE_MAPPING; - } - subscribe(type, channels, listener, returnBuffers) { - const command2 = this.#pubSub.subscribe(type, channels, listener, returnBuffers); - if (!command2) - return; - this.#setupPubSubHandler(); - return this.#addPubSubCommand(command2); - } - #resetDecoderCallbacks() { - this.decoder.onReply = (reply) => this.#onReply(reply); - this.decoder.getTypeMapping = () => this.#getTypeMapping(); - } - unsubscribe(type, channels, listener, returnBuffers) { - const command2 = this.#pubSub.unsubscribe(type, channels, listener, returnBuffers); - if (!command2) - return; - if (command2 && this.#respVersion === 2) { - const { resolve: resolve82 } = command2; - command2.resolve = () => { - if (!this.#pubSub.isActive) { - this.#resetDecoderCallbacks(); - } - resolve82(); - }; - } - return this.#addPubSubCommand(command2); - } - removeAllPubSubListeners() { - return this.#pubSub.removeAllListeners(); - } - resubscribe(chainId) { - const commands = this.#pubSub.resubscribe(); - if (!commands.length) - return; - this.#setupPubSubHandler(); - return Promise.all(commands.map((command2) => this.#addPubSubCommand(command2, true, chainId))); - } - extendPubSubChannelListeners(type, channel, listeners) { - const command2 = this.#pubSub.extendChannelListeners(type, channel, listeners); - if (!command2) - return; - this.#setupPubSubHandler(); - return this.#addPubSubCommand(command2); - } - extendPubSubListeners(type, listeners) { - const command2 = this.#pubSub.extendTypeListeners(type, listeners); - if (!command2) - return; - this.#setupPubSubHandler(); - return this.#addPubSubCommand(command2); - } - getPubSubListeners(type) { - return this.#pubSub.listeners[type]; - } - monitor(callback, options2) { - return new Promise((resolve82, reject) => { - const typeMapping = options2?.typeMapping ?? {}; - this.#toWrite.add({ - args: ["MONITOR"], - chainId: options2?.chainId, - abort: void 0, - timeout: void 0, - // using `resolve` instead of using `.then`/`await` to make sure it'll be called before processing the next reply - resolve: () => { - if (this.#resetFallbackOnReply) { - this.#resetFallbackOnReply = callback; - } else { - this.decoder.onReply = callback; - } - this.decoder.getTypeMapping = () => typeMapping; - resolve82(); - }, - reject, - channelsCounter: void 0, - typeMapping - }, options2?.asap); - }); - } - resetDecoder() { - this.#resetDecoderCallbacks(); - this.decoder.reset(); - } - #resetFallbackOnReply; - async reset(chainId, typeMapping) { - return new Promise((resolve82, reject) => { - this.#resetFallbackOnReply = this.decoder.onReply; - this.decoder.onReply = (reply) => { - if (typeof reply === "string" && reply === "RESET" || reply instanceof Buffer && RESET.equals(reply)) { - this.#resetDecoderCallbacks(); - this.#resetFallbackOnReply = void 0; - this.#pubSub.reset(); - this.#waitingForReply.shift().resolve(reply); - return; - } - this.#resetFallbackOnReply(reply); - }; - this.#toWrite.push({ - args: ["RESET"], - chainId, - abort: void 0, - timeout: void 0, - resolve: resolve82, - reject, - channelsCounter: void 0, - typeMapping - }); - }); - } - isWaitingToWrite() { - return this.#toWrite.length > 0; - } - *commandsToWrite() { - let toSend = this.#toWrite.shift(); - while (toSend) { - let encoded; - try { - encoded = (0, encoder_1.default)(toSend.args); - } catch (err) { - toSend.reject(err); - toSend = this.#toWrite.shift(); - continue; - } - toSend.args = void 0; - if (toSend.abort) { - _RedisCommandsQueue.#removeAbortListener(toSend); - toSend.abort = void 0; - } - if (toSend.timeout) { - _RedisCommandsQueue.#removeTimeoutListener(toSend); - toSend.timeout = void 0; - } - this.#chainInExecution = toSend.chainId; - toSend.chainId = void 0; - this.#waitingForReply.push(toSend); - yield encoded; - toSend = this.#toWrite.shift(); - } - } - #flushWaitingForReply(err) { - for (const node of this.#waitingForReply) { - node.reject(err); - } - this.#waitingForReply.reset(); - } - static #removeAbortListener(command2) { - command2.abort.signal.removeEventListener("abort", command2.abort.listener); - } - static #removeTimeoutListener(command2) { - command2.timeout?.signal.removeEventListener("abort", command2.timeout.listener); - } - static #flushToWrite(toBeSent, err) { - if (toBeSent.abort) { - _RedisCommandsQueue.#removeAbortListener(toBeSent); - } - if (toBeSent.timeout) { - _RedisCommandsQueue.#removeTimeoutListener(toBeSent); - } - toBeSent.reject(err); - } - flushWaitingForReply(err) { - this.resetDecoder(); - this.#pubSub.reset(); - this.#flushWaitingForReply(err); - if (!this.#chainInExecution) - return; - while (this.#toWrite.head?.value.chainId === this.#chainInExecution) { - _RedisCommandsQueue.#flushToWrite(this.#toWrite.shift(), err); - } - this.#chainInExecution = void 0; - } - flushAll(err) { - this.resetDecoder(); - this.#pubSub.reset(); - this.#flushWaitingForReply(err); - for (const node of this.#toWrite) { - _RedisCommandsQueue.#flushToWrite(node, err); - } - this.#toWrite.reset(); - } - isEmpty() { - return this.#toWrite.length === 0 && this.#waitingForReply.length === 0; - } - }; - exports2.default = RedisCommandsQueue; - } -}); -var require_commander = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/commander.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.scriptArgumentsPrefix = exports2.functionArgumentsPrefix = exports2.getTransformReply = exports2.attachConfig = void 0; - function throwResp3SearchModuleUnstableError() { - throw new Error("Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance"); - } - function attachConfig({ BaseClass, commands, createCommand, createModuleCommand, createFunctionCommand, createScriptCommand, config: config2 }) { - const RESP = config2?.RESP ?? 2, Class2 = class extends BaseClass { - }; - for (const [name, command2] of Object.entries(commands)) { - if (config2?.RESP == 3 && command2.unstableResp3 && !config2.unstableResp3) { - Class2.prototype[name] = throwResp3SearchModuleUnstableError; - } else { - Class2.prototype[name] = createCommand(command2, RESP); - } - } - if (config2?.modules) { - for (const [moduleName, module15] of Object.entries(config2.modules)) { - const fns = /* @__PURE__ */ Object.create(null); - for (const [name, command2] of Object.entries(module15)) { - if (config2.RESP == 3 && command2.unstableResp3 && !config2.unstableResp3) { - fns[name] = throwResp3SearchModuleUnstableError; - } else { - fns[name] = createModuleCommand(command2, RESP); - } - } - attachNamespace(Class2.prototype, moduleName, fns); - } - } - if (config2?.functions) { - for (const [library, commands2] of Object.entries(config2.functions)) { - const fns = /* @__PURE__ */ Object.create(null); - for (const [name, command2] of Object.entries(commands2)) { - fns[name] = createFunctionCommand(name, command2, RESP); - } - attachNamespace(Class2.prototype, library, fns); - } - } - if (config2?.scripts) { - for (const [name, script] of Object.entries(config2.scripts)) { - Class2.prototype[name] = createScriptCommand(script, RESP); - } - } - return Class2; - } - exports2.attachConfig = attachConfig; - function attachNamespace(prototype, name, fns) { - Object.defineProperty(prototype, name, { - get() { - const value = Object.create(fns); - value._self = this; - Object.defineProperty(this, name, { value }); - return value; - } - }); - } - function getTransformReply(command2, resp) { - switch (typeof command2.transformReply) { - case "function": - return command2.transformReply; - case "object": - return command2.transformReply[resp]; - } - } - exports2.getTransformReply = getTransformReply; - function functionArgumentsPrefix(name, fn) { - const prefix = [ - fn.IS_READ_ONLY ? "FCALL_RO" : "FCALL", - name - ]; - if (fn.NUMBER_OF_KEYS !== void 0) { - prefix.push(fn.NUMBER_OF_KEYS.toString()); - } - return prefix; - } - exports2.functionArgumentsPrefix = functionArgumentsPrefix; - function scriptArgumentsPrefix(script) { - const prefix = [ - script.IS_READ_ONLY ? "EVALSHA_RO" : "EVALSHA", - script.SHA1 - ]; - if (script.NUMBER_OF_KEYS !== void 0) { - prefix.push(script.NUMBER_OF_KEYS.toString()); - } - return prefix; - } - exports2.scriptArgumentsPrefix = scriptArgumentsPrefix; - } -}); -var require_multi_command = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/multi-command.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var errors_1 = require_errors(); - var RedisMultiCommand = class { - typeMapping; - constructor(typeMapping) { - this.typeMapping = typeMapping; - } - queue = []; - scriptsInUse = /* @__PURE__ */ new Set(); - addCommand(args, transformReply) { - this.queue.push({ - args, - transformReply - }); - } - addScript(script, args, transformReply) { - const redisArgs = []; - redisArgs.preserve = args.preserve; - if (this.scriptsInUse.has(script.SHA1)) { - redisArgs.push("EVALSHA", script.SHA1); - } else { - this.scriptsInUse.add(script.SHA1); - redisArgs.push("EVAL", script.SCRIPT); - } - if (script.NUMBER_OF_KEYS !== void 0) { - redisArgs.push(script.NUMBER_OF_KEYS.toString()); - } - redisArgs.push(...args); - this.addCommand(redisArgs, transformReply); - } - transformReplies(rawReplies) { - const errorIndexes = [], replies = rawReplies.map((reply, i2) => { - if (reply instanceof errors_1.ErrorReply) { - errorIndexes.push(i2); - return reply; - } - const { transformReply, args } = this.queue[i2]; - return transformReply ? transformReply(reply, args.preserve, this.typeMapping) : reply; - }); - if (errorIndexes.length) - throw new errors_1.MultiErrorReply(replies, errorIndexes); - return replies; - } - }; - exports2.default = RedisMultiCommand; - } -}); -var require_multi_command2 = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/multi-command.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var commands_1 = __importDefault(require_commands()); - var multi_command_1 = __importDefault(require_multi_command()); - var commander_1 = require_commander(); - var parser_1 = require_parser(); - var RedisClientMultiCommand = class _RedisClientMultiCommand { - static #createCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - return this.addCommand(redisArgs, transformReply); - }; - } - static #createModuleCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - return this._self.addCommand(redisArgs, transformReply); - }; - } - static #createFunctionCommand(name, fn, resp) { - const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); - const transformReply = (0, commander_1.getTransformReply)(fn, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - fn.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - return this._self.addCommand(redisArgs, transformReply); - }; - } - static #createScriptCommand(script, resp) { - const transformReply = (0, commander_1.getTransformReply)(script, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - script.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - return this.#addScript(script, redisArgs, transformReply); - }; - } - static extend(config2) { - return (0, commander_1.attachConfig)({ - BaseClass: _RedisClientMultiCommand, - commands: commands_1.default, - createCommand: _RedisClientMultiCommand.#createCommand, - createModuleCommand: _RedisClientMultiCommand.#createModuleCommand, - createFunctionCommand: _RedisClientMultiCommand.#createFunctionCommand, - createScriptCommand: _RedisClientMultiCommand.#createScriptCommand, - config: config2 - }); - } - #multi; - #executeMulti; - #executePipeline; - #selectedDB; - constructor(executeMulti, executePipeline, typeMapping) { - this.#multi = new multi_command_1.default(typeMapping); - this.#executeMulti = executeMulti; - this.#executePipeline = executePipeline; - } - SELECT(db2, transformReply) { - this.#selectedDB = db2; - this.#multi.addCommand(["SELECT", db2.toString()], transformReply); - return this; - } - select = this.SELECT; - addCommand(args, transformReply) { - this.#multi.addCommand(args, transformReply); - return this; - } - #addScript(script, args, transformReply) { - this.#multi.addScript(script, args, transformReply); - return this; - } - async exec(execAsPipeline = false) { - if (execAsPipeline) - return this.execAsPipeline(); - return this.#multi.transformReplies(await this.#executeMulti(this.#multi.queue, this.#selectedDB)); - } - EXEC = this.exec; - execTyped(execAsPipeline = false) { - return this.exec(execAsPipeline); - } - async execAsPipeline() { - if (this.#multi.queue.length === 0) - return []; - return this.#multi.transformReplies(await this.#executePipeline(this.#multi.queue, this.#selectedDB)); - } - execAsPipelineTyped() { - return this.execAsPipeline(); - } - }; - exports2.default = RedisClientMultiCommand; - } -}); -var require_legacy_mode = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/legacy-mode.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.RedisLegacyClient = void 0; - var commander_1 = require_commander(); - var commands_1 = __importDefault(require_commands()); - var multi_command_1 = __importDefault(require_multi_command()); - var RedisLegacyClient = class _RedisLegacyClient { - static #transformArguments(redisArgs, args) { - let callback; - if (typeof args[args.length - 1] === "function") { - callback = args.pop(); - } - _RedisLegacyClient.pushArguments(redisArgs, args); - return callback; - } - static pushArguments(redisArgs, args) { - for (let i2 = 0; i2 < args.length; ++i2) { - const arg = args[i2]; - if (Array.isArray(arg)) { - _RedisLegacyClient.pushArguments(redisArgs, arg); - } else { - redisArgs.push(typeof arg === "number" || arg instanceof Date ? arg.toString() : arg); - } - } - } - static getTransformReply(command2, resp) { - return command2.TRANSFORM_LEGACY_REPLY ? (0, commander_1.getTransformReply)(command2, resp) : void 0; - } - static #createCommand(name, command2, resp) { - const transformReply = _RedisLegacyClient.getTransformReply(command2, resp); - return function(...args) { - const redisArgs = [name], callback = _RedisLegacyClient.#transformArguments(redisArgs, args), promise = this.#client.sendCommand(redisArgs); - if (!callback) { - promise.catch((err) => this.#client.emit("error", err)); - return; - } - promise.then((reply) => callback(null, transformReply ? transformReply(reply) : reply)).catch((err) => callback(err)); - }; - } - #client; - #Multi; - constructor(client) { - this.#client = client; - const RESP = client.options?.RESP ?? 2; - for (const [name, command2] of Object.entries(commands_1.default)) { - this[name] = _RedisLegacyClient.#createCommand(name, command2, RESP); - } - this.#Multi = LegacyMultiCommand.factory(RESP); - } - sendCommand(...args) { - const redisArgs = [], callback = _RedisLegacyClient.#transformArguments(redisArgs, args), promise = this.#client.sendCommand(redisArgs); - if (!callback) { - promise.catch((err) => this.#client.emit("error", err)); - return; - } - promise.then((reply) => callback(null, reply)).catch((err) => callback(err)); - } - multi() { - return this.#Multi(this.#client); - } - }; - exports2.RedisLegacyClient = RedisLegacyClient; - var LegacyMultiCommand = class _LegacyMultiCommand { - static #createCommand(name, command2, resp) { - const transformReply = RedisLegacyClient.getTransformReply(command2, resp); - return function(...args) { - const redisArgs = [name]; - RedisLegacyClient.pushArguments(redisArgs, args); - this.#multi.addCommand(redisArgs, transformReply); - return this; - }; - } - static factory(resp) { - const Multi = class extends _LegacyMultiCommand { - }; - for (const [name, command2] of Object.entries(commands_1.default)) { - Multi.prototype[name] = _LegacyMultiCommand.#createCommand(name, command2, resp); - } - return (client) => { - return new Multi(client); - }; - } - #multi = new multi_command_1.default(); - #client; - constructor(client) { - this.#client = client; - } - sendCommand(...args) { - const redisArgs = []; - RedisLegacyClient.pushArguments(redisArgs, args); - this.#multi.addCommand(redisArgs); - return this; - } - exec(cb) { - const promise = this.#client._executeMulti(this.#multi.queue); - if (!cb) { - promise.catch((err) => this.#client.emit("error", err)); - return; - } - promise.then((results) => cb(null, this.#multi.transformReplies(results))).catch((err) => cb?.(err)); - } - }; - } -}); -var require_cache = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/cache.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.PooledNoRedirectClientSideCache = exports2.BasicPooledClientSideCache = exports2.PooledClientSideCacheProvider = exports2.BasicClientSideCache = exports2.ClientSideCacheProvider = exports2.CacheStats = void 0; - var stream_1 = __require2("stream"); - var CacheStats = class _CacheStats { - hitCount; - missCount; - loadSuccessCount; - loadFailureCount; - totalLoadTime; - evictionCount; - /** - * Creates a new CacheStats instance with the specified statistics. - */ - constructor(hitCount, missCount, loadSuccessCount, loadFailureCount, totalLoadTime, evictionCount) { - this.hitCount = hitCount; - this.missCount = missCount; - this.loadSuccessCount = loadSuccessCount; - this.loadFailureCount = loadFailureCount; - this.totalLoadTime = totalLoadTime; - this.evictionCount = evictionCount; - if (hitCount < 0 || missCount < 0 || loadSuccessCount < 0 || loadFailureCount < 0 || totalLoadTime < 0 || evictionCount < 0) { - throw new Error("All statistics values must be non-negative"); - } - } - /** - * Creates a new CacheStats instance with the specified statistics. - * - * @param hitCount - Number of cache hits - * @param missCount - Number of cache misses - * @param loadSuccessCount - Number of successful cache loads - * @param loadFailureCount - Number of failed cache loads - * @param totalLoadTime - Total load time in milliseconds - * @param evictionCount - Number of cache evictions - */ - static of(hitCount = 0, missCount = 0, loadSuccessCount = 0, loadFailureCount = 0, totalLoadTime = 0, evictionCount = 0) { - return new _CacheStats(hitCount, missCount, loadSuccessCount, loadFailureCount, totalLoadTime, evictionCount); - } - /** - * Returns a statistics instance where no cache events have been recorded. - * - * @returns An empty statistics instance - */ - static empty() { - return _CacheStats.EMPTY_STATS; - } - /** - * An empty stats instance with all counters set to zero. - */ - static EMPTY_STATS = new _CacheStats(0, 0, 0, 0, 0, 0); - /** - * Returns the total number of times cache lookup methods have returned - * either a cached or uncached value. - * - * @returns Total number of requests (hits + misses) - */ - requestCount() { - return this.hitCount + this.missCount; - } - /** - * Returns the hit rate of the cache. - * This is defined as hitCount / requestCount, or 1.0 when requestCount is 0. - * - * @returns The ratio of cache requests that were hits (between 0.0 and 1.0) - */ - hitRate() { - const requestCount = this.requestCount(); - return requestCount === 0 ? 1 : this.hitCount / requestCount; - } - /** - * Returns the miss rate of the cache. - * This is defined as missCount / requestCount, or 0.0 when requestCount is 0. - * - * @returns The ratio of cache requests that were misses (between 0.0 and 1.0) - */ - missRate() { - const requestCount = this.requestCount(); - return requestCount === 0 ? 0 : this.missCount / requestCount; - } - /** - * Returns the total number of load operations (successful + failed). - * - * @returns Total number of load operations - */ - loadCount() { - return this.loadSuccessCount + this.loadFailureCount; - } - /** - * Returns the ratio of cache loading attempts that failed. - * This is defined as loadFailureCount / loadCount, or 0.0 when loadCount is 0. - * - * @returns Ratio of load operations that failed (between 0.0 and 1.0) - */ - loadFailureRate() { - const loadCount = this.loadCount(); - return loadCount === 0 ? 0 : this.loadFailureCount / loadCount; - } - /** - * Returns the average time spent loading new values, in milliseconds. - * This is defined as totalLoadTime / loadCount, or 0.0 when loadCount is 0. - * - * @returns Average load time in milliseconds - */ - averageLoadPenalty() { - const loadCount = this.loadCount(); - return loadCount === 0 ? 0 : this.totalLoadTime / loadCount; - } - /** - * Returns a new CacheStats representing the difference between this CacheStats - * and another. Negative values are rounded up to zero. - * - * @param other - The statistics to subtract from this instance - * @returns The difference between this instance and other - */ - minus(other) { - return _CacheStats.of(Math.max(0, this.hitCount - other.hitCount), Math.max(0, this.missCount - other.missCount), Math.max(0, this.loadSuccessCount - other.loadSuccessCount), Math.max(0, this.loadFailureCount - other.loadFailureCount), Math.max(0, this.totalLoadTime - other.totalLoadTime), Math.max(0, this.evictionCount - other.evictionCount)); - } - /** - * Returns a new CacheStats representing the sum of this CacheStats and another. - * - * @param other - The statistics to add to this instance - * @returns The sum of this instance and other - */ - plus(other) { - return _CacheStats.of(this.hitCount + other.hitCount, this.missCount + other.missCount, this.loadSuccessCount + other.loadSuccessCount, this.loadFailureCount + other.loadFailureCount, this.totalLoadTime + other.totalLoadTime, this.evictionCount + other.evictionCount); - } - }; - exports2.CacheStats = CacheStats; - var DisabledStatsCounter = class _DisabledStatsCounter { - static INSTANCE = new _DisabledStatsCounter(); - constructor() { - } - recordHits(count) { - } - recordMisses(count) { - } - recordLoadSuccess(loadTime) { - } - recordLoadFailure(loadTime) { - } - recordEvictions(count) { - } - snapshot() { - return CacheStats.empty(); - } - }; - function disabledStatsCounter() { - return DisabledStatsCounter.INSTANCE; - } - var DefaultStatsCounter = class _DefaultStatsCounter { - #hitCount = 0; - #missCount = 0; - #loadSuccessCount = 0; - #loadFailureCount = 0; - #totalLoadTime = 0; - #evictionCount = 0; - /** - * Records cache hits. - * - * @param count - The number of hits to record - */ - recordHits(count) { - this.#hitCount += count; - } - /** - * Records cache misses. - * - * @param count - The number of misses to record - */ - recordMisses(count) { - this.#missCount += count; - } - /** - * Records the successful load of a new entry. - * - * @param loadTime - The number of milliseconds spent loading the entry - */ - recordLoadSuccess(loadTime) { - this.#loadSuccessCount++; - this.#totalLoadTime += loadTime; - } - /** - * Records the failed load of a new entry. - * - * @param loadTime - The number of milliseconds spent attempting to load the entry - */ - recordLoadFailure(loadTime) { - this.#loadFailureCount++; - this.#totalLoadTime += loadTime; - } - /** - * Records cache evictions. - * - * @param count - The number of evictions to record - */ - recordEvictions(count) { - this.#evictionCount += count; - } - /** - * Returns a snapshot of the current statistics. - * - * @returns A snapshot of the current statistics - */ - snapshot() { - return CacheStats.of(this.#hitCount, this.#missCount, this.#loadSuccessCount, this.#loadFailureCount, this.#totalLoadTime, this.#evictionCount); - } - /** - * Creates a new DefaultStatsCounter. - * - * @returns A new DefaultStatsCounter instance - */ - static create() { - return new _DefaultStatsCounter(); - } - }; - function generateCacheKey(redisArgs) { - const tmp = new Array(redisArgs.length * 2); - for (let i2 = 0; i2 < redisArgs.length; i2++) { - tmp[i2] = redisArgs[i2].length; - tmp[i2 + redisArgs.length] = redisArgs[i2]; - } - return tmp.join("_"); - } - var ClientSideCacheEntryBase = class { - #invalidated = false; - #expireTime; - constructor(ttl) { - if (ttl == 0) { - this.#expireTime = 0; - } else { - this.#expireTime = Date.now() + ttl; - } - } - invalidate() { - this.#invalidated = true; - } - validate() { - return !this.#invalidated && (this.#expireTime == 0 || Date.now() < this.#expireTime); - } - }; - var ClientSideCacheEntryValue = class extends ClientSideCacheEntryBase { - #value; - get value() { - return this.#value; - } - constructor(ttl, value) { - super(ttl); - this.#value = value; - } - }; - var ClientSideCacheEntryPromise = class extends ClientSideCacheEntryBase { - #sendCommandPromise; - get promise() { - return this.#sendCommandPromise; - } - constructor(ttl, sendCommandPromise) { - super(ttl); - this.#sendCommandPromise = sendCommandPromise; - } - }; - var ClientSideCacheProvider = class extends stream_1.EventEmitter { - }; - exports2.ClientSideCacheProvider = ClientSideCacheProvider; - var BasicClientSideCache = class extends ClientSideCacheProvider { - #cacheKeyToEntryMap; - #keyToCacheKeySetMap; - ttl; - maxEntries; - lru; - #statsCounter; - recordEvictions(count) { - this.#statsCounter.recordEvictions(count); - } - recordHits(count) { - this.#statsCounter.recordHits(count); - } - recordMisses(count) { - this.#statsCounter.recordMisses(count); - } - constructor(config2) { - super(); - this.#cacheKeyToEntryMap = /* @__PURE__ */ new Map(); - this.#keyToCacheKeySetMap = /* @__PURE__ */ new Map(); - this.ttl = config2?.ttl ?? 0; - this.maxEntries = config2?.maxEntries ?? 0; - this.lru = config2?.evictPolicy !== "FIFO"; - const recordStats = config2?.recordStats !== false; - this.#statsCounter = recordStats ? DefaultStatsCounter.create() : disabledStatsCounter(); - } - /* logic of how caching works: - - 1. commands use a CommandParser - it enables us to define/retrieve - cacheKey - a unique key that corresponds to this command and its arguments - redisKeys - an array of redis keys as strings that if the key is modified, will cause redis to invalidate this result when cached - 2. check if cacheKey is in our cache - 2b1. if its a value cacheEntry - return it - 2b2. if it's a promise cache entry - wait on promise and then go to 3c. - 3. if cacheEntry is not in cache - 3a. send the command save the promise into a a cacheEntry and then wait on result - 3b. transform reply (if required) based on transformReply - 3b. check the cacheEntry is still valid - in cache and hasn't been deleted) - 3c. if valid - overwrite with value entry - 4. return previously non cached result - */ - async handleCache(client, parser3, fn, transformReply, typeMapping) { - let reply; - const cacheKey = generateCacheKey(parser3.redisArgs); - let cacheEntry = this.get(cacheKey); - if (cacheEntry) { - if (cacheEntry instanceof ClientSideCacheEntryValue) { - this.#statsCounter.recordHits(1); - return structuredClone(cacheEntry.value); - } else if (cacheEntry instanceof ClientSideCacheEntryPromise) { - this.#statsCounter.recordMisses(1); - reply = await cacheEntry.promise; - } else { - throw new Error("unknown cache entry type"); - } - } else { - this.#statsCounter.recordMisses(1); - const startTime = performance.now(); - const promise = fn(); - cacheEntry = this.createPromiseEntry(client, promise); - this.set(cacheKey, cacheEntry, parser3.keys); - try { - reply = await promise; - const loadTime = performance.now() - startTime; - this.#statsCounter.recordLoadSuccess(loadTime); - } catch (err) { - const loadTime = performance.now() - startTime; - this.#statsCounter.recordLoadFailure(loadTime); - if (cacheEntry.validate()) { - this.delete(cacheKey); - } - throw err; - } - } - let val; - if (transformReply) { - val = transformReply(reply, parser3.preserve, typeMapping); - } else { - val = reply; - } - if (cacheEntry.validate()) { - cacheEntry = this.createValueEntry(client, val); - this.set(cacheKey, cacheEntry, parser3.keys); - this.emit("cached-key", cacheKey); - } else { - } - return structuredClone(val); - } - trackingOn() { - return ["CLIENT", "TRACKING", "ON"]; - } - invalidate(key) { - if (key === null) { - this.clear(false); - this.emit("invalidate", key); - return; - } - const keySet = this.#keyToCacheKeySetMap.get(key.toString()); - if (keySet) { - for (const cacheKey of keySet) { - const entry = this.#cacheKeyToEntryMap.get(cacheKey); - if (entry) { - entry.invalidate(); - } - this.#cacheKeyToEntryMap.delete(cacheKey); - } - this.#keyToCacheKeySetMap.delete(key.toString()); - } - this.emit("invalidate", key); - } - clear(resetStats = true) { - const oldSize = this.#cacheKeyToEntryMap.size; - this.#cacheKeyToEntryMap.clear(); - this.#keyToCacheKeySetMap.clear(); - if (resetStats) { - if (!(this.#statsCounter instanceof DisabledStatsCounter)) { - this.#statsCounter = DefaultStatsCounter.create(); - } - } else { - if (oldSize > 0) { - this.#statsCounter.recordEvictions(oldSize); - } - } - } - get(cacheKey) { - const val = this.#cacheKeyToEntryMap.get(cacheKey); - if (val && !val.validate()) { - this.delete(cacheKey); - this.#statsCounter.recordEvictions(1); - this.emit("cache-evict", cacheKey); - return void 0; - } - if (val !== void 0 && this.lru) { - this.#cacheKeyToEntryMap.delete(cacheKey); - this.#cacheKeyToEntryMap.set(cacheKey, val); - } - return val; - } - delete(cacheKey) { - const entry = this.#cacheKeyToEntryMap.get(cacheKey); - if (entry) { - entry.invalidate(); - this.#cacheKeyToEntryMap.delete(cacheKey); - } - } - has(cacheKey) { - return this.#cacheKeyToEntryMap.has(cacheKey); - } - set(cacheKey, cacheEntry, keys) { - let count = this.#cacheKeyToEntryMap.size; - const oldEntry = this.#cacheKeyToEntryMap.get(cacheKey); - if (oldEntry) { - count--; - oldEntry.invalidate(); - } - if (this.maxEntries > 0 && count >= this.maxEntries) { - this.deleteOldest(); - this.#statsCounter.recordEvictions(1); - } - this.#cacheKeyToEntryMap.set(cacheKey, cacheEntry); - for (const key of keys) { - if (!this.#keyToCacheKeySetMap.has(key.toString())) { - this.#keyToCacheKeySetMap.set(key.toString(), /* @__PURE__ */ new Set()); - } - const cacheKeySet = this.#keyToCacheKeySetMap.get(key.toString()); - cacheKeySet.add(cacheKey); - } - } - size() { - return this.#cacheKeyToEntryMap.size; - } - createValueEntry(client, value) { - return new ClientSideCacheEntryValue(this.ttl, value); - } - createPromiseEntry(client, sendCommandPromise) { - return new ClientSideCacheEntryPromise(this.ttl, sendCommandPromise); - } - stats() { - return this.#statsCounter.snapshot(); - } - onError() { - this.clear(); - } - onClose() { - this.clear(); - } - /** - * @internal - */ - deleteOldest() { - const it = this.#cacheKeyToEntryMap[Symbol.iterator](); - const n = it.next(); - if (!n.done) { - const key = n.value[0]; - const entry = this.#cacheKeyToEntryMap.get(key); - if (entry) { - entry.invalidate(); - } - this.#cacheKeyToEntryMap.delete(key); - } - } - /** - * Get cache entries for debugging - * @internal - */ - entryEntries() { - return this.#cacheKeyToEntryMap.entries(); - } - /** - * Get key set entries for debugging - * @internal - */ - keySetEntries() { - return this.#keyToCacheKeySetMap.entries(); - } - }; - exports2.BasicClientSideCache = BasicClientSideCache; - var PooledClientSideCacheProvider = class extends BasicClientSideCache { - #disabled = false; - disable() { - this.#disabled = true; - } - enable() { - this.#disabled = false; - } - get(cacheKey) { - if (this.#disabled) { - return void 0; - } - return super.get(cacheKey); - } - has(cacheKey) { - if (this.#disabled) { - return false; - } - return super.has(cacheKey); - } - onPoolClose() { - this.clear(); - } - }; - exports2.PooledClientSideCacheProvider = PooledClientSideCacheProvider; - var BasicPooledClientSideCache = class extends PooledClientSideCacheProvider { - onError() { - this.clear(false); - } - onClose() { - this.clear(false); - } - }; - exports2.BasicPooledClientSideCache = BasicPooledClientSideCache; - var PooledClientSideCacheEntryValue = class extends ClientSideCacheEntryValue { - #creator; - constructor(ttl, creator, value) { - super(ttl, value); - this.#creator = creator; - } - validate() { - let ret = super.validate(); - if (this.#creator) { - ret = ret && this.#creator.client.isReady && this.#creator.client.socketEpoch == this.#creator.epoch; - } - return ret; - } - }; - var PooledClientSideCacheEntryPromise = class extends ClientSideCacheEntryPromise { - #creator; - constructor(ttl, creator, sendCommandPromise) { - super(ttl, sendCommandPromise); - this.#creator = creator; - } - validate() { - let ret = super.validate(); - return ret && this.#creator.client.isReady && this.#creator.client.socketEpoch == this.#creator.epoch; - } - }; - var PooledNoRedirectClientSideCache = class extends BasicPooledClientSideCache { - createValueEntry(client, value) { - const creator = { - epoch: client.socketEpoch, - client - }; - return new PooledClientSideCacheEntryValue(this.ttl, creator, value); - } - createPromiseEntry(client, sendCommandPromise) { - const creator = { - epoch: client.socketEpoch, - client - }; - return new PooledClientSideCacheEntryPromise(this.ttl, creator, sendCommandPromise); - } - onError() { - } - onClose() { - } - }; - exports2.PooledNoRedirectClientSideCache = PooledNoRedirectClientSideCache; - } -}); -var require_single_entry_cache = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/single-entry-cache.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var SingleEntryCache = class { - #cached; - #serializedKey; - /** - * Retrieves an instance from the cache based on the provided key object. - * - * @param keyObj - The key object to look up in the cache. - * @returns The cached instance if found, undefined otherwise. - * - * @remarks - * This method uses JSON.stringify for comparison, which may not work correctly - * if the properties in the key object are rearranged or reordered. - */ - get(keyObj) { - return JSON.stringify(keyObj, makeCircularReplacer()) === this.#serializedKey ? this.#cached : void 0; - } - set(keyObj, obj) { - this.#cached = obj; - this.#serializedKey = JSON.stringify(keyObj, makeCircularReplacer()); - } - }; - exports2.default = SingleEntryCache; - function makeCircularReplacer() { - const seen = /* @__PURE__ */ new WeakSet(); - return function serialize(_, value) { - if (value && typeof value === "object") { - if (seen.has(value)) { - return "circular"; - } - seen.add(value); - return value; - } - return value; - }; - } - } -}); -var require_pool = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/pool.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.RedisClientPool = void 0; - var commands_1 = __importDefault(require_commands()); - var _1 = __importDefault(require_client()); - var node_events_1 = __require2("node:events"); - var linked_list_1 = require_linked_list(); - var errors_1 = require_errors(); - var commander_1 = require_commander(); - var multi_command_1 = __importDefault(require_multi_command2()); - var cache_1 = require_cache(); - var parser_1 = require_parser(); - var single_entry_cache_1 = __importDefault(require_single_entry_cache()); - var RedisClientPool = class _RedisClientPool extends node_events_1.EventEmitter { - static #createCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this.execute((client) => client._executeCommand(command2, parser3, this._commandOptions, transformReply)); - }; - } - static #createModuleCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this._self.execute((client) => client._executeCommand(command2, parser3, this._self._commandOptions, transformReply)); - }; - } - static #createFunctionCommand(name, fn, resp) { - const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); - const transformReply = (0, commander_1.getTransformReply)(fn, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - fn.parseCommand(parser3, ...args); - return this._self.execute((client) => client._executeCommand(fn, parser3, this._self._commandOptions, transformReply)); - }; - } - static #createScriptCommand(script, resp) { - const prefix = (0, commander_1.scriptArgumentsPrefix)(script); - const transformReply = (0, commander_1.getTransformReply)(script, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.pushVariadic(prefix); - script.parseCommand(parser3, ...args); - return this.execute((client) => client._executeScript(script, parser3, this._commandOptions, transformReply)); - }; - } - static #SingleEntryCache = new single_entry_cache_1.default(); - static create(clientOptions, options2) { - let Pool = _RedisClientPool.#SingleEntryCache.get(clientOptions); - if (!Pool) { - Pool = (0, commander_1.attachConfig)({ - BaseClass: _RedisClientPool, - commands: commands_1.default, - createCommand: _RedisClientPool.#createCommand, - createModuleCommand: _RedisClientPool.#createModuleCommand, - createFunctionCommand: _RedisClientPool.#createFunctionCommand, - createScriptCommand: _RedisClientPool.#createScriptCommand, - config: clientOptions - }); - Pool.prototype.Multi = multi_command_1.default.extend(clientOptions); - _RedisClientPool.#SingleEntryCache.set(clientOptions, Pool); - } - return Object.create(new Pool(clientOptions, options2)); - } - // TODO: defaults - static #DEFAULTS = { - minimum: 1, - maximum: 100, - acquireTimeout: 3e3, - cleanupDelay: 3e3 - }; - #clientFactory; - #options; - #idleClients = new linked_list_1.SinglyLinkedList(); - /** - * The number of idle clients. - */ - get idleClients() { - return this._self.#idleClients.length; - } - #clientsInUse = new linked_list_1.DoublyLinkedList(); - /** - * The number of clients in use. - */ - get clientsInUse() { - return this._self.#clientsInUse.length; - } - /** - * The total number of clients in the pool (including connecting, idle, and in use). - */ - get totalClients() { - return this._self.#idleClients.length + this._self.#clientsInUse.length; - } - #tasksQueue = new linked_list_1.SinglyLinkedList(); - /** - * The number of tasks waiting for a client to become available. - */ - get tasksQueueLength() { - return this._self.#tasksQueue.length; - } - #isOpen = false; - /** - * Whether the pool is open (either connecting or connected). - */ - get isOpen() { - return this._self.#isOpen; - } - #isClosing = false; - /** - * Whether the pool is closing (*not* closed). - */ - get isClosing() { - return this._self.#isClosing; - } - #clientSideCache; - get clientSideCache() { - return this._self.#clientSideCache; - } - /** - * You are probably looking for {@link RedisClient.createPool `RedisClient.createPool`}, - * {@link RedisClientPool.fromClient `RedisClientPool.fromClient`}, - * or {@link RedisClientPool.fromOptions `RedisClientPool.fromOptions`}... - */ - constructor(clientOptions, options2) { - super(); - this.#options = { - ..._RedisClientPool.#DEFAULTS, - ...options2 - }; - if (options2?.clientSideCache) { - if (clientOptions === void 0) { - clientOptions = {}; - } - if (options2.clientSideCache instanceof cache_1.PooledClientSideCacheProvider) { - this.#clientSideCache = clientOptions.clientSideCache = options2.clientSideCache; - } else { - const cscConfig = options2.clientSideCache; - this.#clientSideCache = clientOptions.clientSideCache = new cache_1.BasicPooledClientSideCache(cscConfig); - } - } - this.#clientFactory = _1.default.factory(clientOptions).bind(void 0, clientOptions); - } - _self = this; - _commandOptions; - withCommandOptions(options2) { - const proxy = Object.create(this._self); - proxy._commandOptions = options2; - return proxy; - } - #commandOptionsProxy(key, value) { - const proxy = Object.create(this._self); - proxy._commandOptions = Object.create(this._commandOptions ?? null); - proxy._commandOptions[key] = value; - return proxy; - } - /** - * Override the `typeMapping` command option - */ - withTypeMapping(typeMapping) { - return this._self.#commandOptionsProxy("typeMapping", typeMapping); - } - /** - * Override the `abortSignal` command option - */ - withAbortSignal(abortSignal) { - return this._self.#commandOptionsProxy("abortSignal", abortSignal); - } - /** - * Override the `asap` command option to `true` - * TODO: remove? - */ - asap() { - return this._self.#commandOptionsProxy("asap", true); - } - async connect() { - if (this._self.#isOpen) - return; - this._self.#isOpen = true; - const promises = []; - while (promises.length < this._self.#options.minimum) { - promises.push(this._self.#create()); - } - try { - await Promise.all(promises); - } catch (err) { - this.destroy(); - throw err; - } - return this; - } - async #create() { - const node = this._self.#clientsInUse.push(this._self.#clientFactory().on("error", (err) => this.emit("error", err))); - try { - const client = node.value; - await client.connect(); - } catch (err) { - this._self.#clientsInUse.remove(node); - throw err; - } - this._self.#returnClient(node); - } - execute(fn) { - return new Promise((resolve82, reject) => { - const client = this._self.#idleClients.shift(), { tail } = this._self.#tasksQueue; - if (!client) { - let timeout; - if (this._self.#options.acquireTimeout > 0) { - timeout = setTimeout(() => { - this._self.#tasksQueue.remove(task, tail); - reject(new errors_1.TimeoutError("Timeout waiting for a client")); - }, this._self.#options.acquireTimeout); - } - const task = this._self.#tasksQueue.push({ - timeout, - // @ts-ignore - resolve: resolve82, - reject, - fn - }); - if (this.totalClients < this._self.#options.maximum) { - this._self.#create(); - } - return; - } - const node = this._self.#clientsInUse.push(client); - this._self.#executeTask(node, resolve82, reject, fn); - }); - } - #executeTask(node, resolve82, reject, fn) { - const result = fn(node.value); - if (result instanceof Promise) { - result.then(resolve82, reject).finally(() => this.#returnClient(node)); - } else { - resolve82(result); - this.#returnClient(node); - } - } - #returnClient(node) { - const task = this.#tasksQueue.shift(); - if (task) { - clearTimeout(task.timeout); - this.#executeTask(node, task.resolve, task.reject, task.fn); - return; - } - this.#clientsInUse.remove(node); - this.#idleClients.push(node.value); - this.#scheduleCleanup(); - } - cleanupTimeout; - #scheduleCleanup() { - if (this.totalClients <= this.#options.minimum) - return; - clearTimeout(this.cleanupTimeout); - this.cleanupTimeout = setTimeout(() => this.#cleanup(), this.#options.cleanupDelay); - } - #cleanup() { - const toDestroy = Math.min(this.#idleClients.length, this.totalClients - this.#options.minimum); - for (let i2 = 0; i2 < toDestroy; i2++) { - const client = this.#idleClients.shift(); - client.destroy(); - } - } - sendCommand(args, options2) { - return this.execute((client) => client.sendCommand(args, options2)); - } - MULTI() { - return new this.Multi((commands, selectedDB) => this.execute((client) => client._executeMulti(commands, selectedDB)), (commands) => this.execute((client) => client._executePipeline(commands)), this._commandOptions?.typeMapping); - } - multi = this.MULTI; - async close() { - if (this._self.#isClosing) - return; - if (!this._self.#isOpen) - return; - this._self.#isClosing = true; - try { - const promises = []; - for (const client of this._self.#idleClients) { - promises.push(client.close()); - } - for (const client of this._self.#clientsInUse) { - promises.push(client.close()); - } - await Promise.all(promises); - this.#clientSideCache?.onPoolClose(); - this._self.#idleClients.reset(); - this._self.#clientsInUse.reset(); - } catch (err) { - } finally { - this._self.#isClosing = false; - } - } - destroy() { - for (const client of this._self.#idleClients) { - client.destroy(); - } - this._self.#idleClients.reset(); - for (const client of this._self.#clientsInUse) { - client.destroy(); - } - this._self.#clientSideCache?.onPoolClose(); - this._self.#clientsInUse.reset(); - this._self.#isOpen = false; - } - }; - exports2.RedisClientPool = RedisClientPool; - } -}); -var require_package2 = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/package.json"(exports2, module14) { - module14.exports = { - name: "@redis/client", - version: "5.9.0-beta.3", - license: "MIT", - main: "./dist/index.js", - types: "./dist/index.d.ts", - files: [ - "dist/", - "!dist/tsconfig.tsbuildinfo" - ], - scripts: { - test: "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'", - release: "release-it" - }, - dependencies: { - "cluster-key-slot": "1.1.2" - }, - devDependencies: { - "@redis/test-utils": "*", - "@types/sinon": "^17.0.3", - sinon: "^17.0.1" - }, - engines: { - node: ">= 18" - }, - repository: { - type: "git", - url: "git://github.com/redis/node-redis.git" - }, - bugs: { - url: "https://github.com/redis/node-redis/issues" - }, - homepage: "https://github.com/redis/node-redis/tree/master/packages/client", - keywords: [ - "redis" - ] - }; - } -}); -var require_client = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - var _a2; - Object.defineProperty(exports2, "__esModule", { value: true }); - var commands_1 = __importDefault(require_commands()); - var socket_1 = __importDefault(require_socket()); - var authx_1 = require_authx(); - var commands_queue_1 = __importDefault(require_commands_queue()); - var node_events_1 = __require2("node:events"); - var commander_1 = require_commander(); - var errors_1 = require_errors(); - var node_url_1 = __require2("node:url"); - var pub_sub_1 = require_pub_sub(); - var multi_command_1 = __importDefault(require_multi_command2()); - var HELLO_1 = __importDefault(require_HELLO()); - var legacy_mode_1 = require_legacy_mode(); - var pool_1 = require_pool(); - var generic_transformers_1 = require_generic_transformers(); - var cache_1 = require_cache(); - var parser_1 = require_parser(); - var single_entry_cache_1 = __importDefault(require_single_entry_cache()); - var package_json_1 = require_package2(); - var enterprise_maintenance_manager_1 = __importDefault(require_enterprise_maintenance_manager()); - var RedisClient = class extends node_events_1.EventEmitter { - static #createCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this._self._executeCommand(command2, parser3, this._commandOptions, transformReply); - }; - } - static #createModuleCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this._self._executeCommand(command2, parser3, this._self._commandOptions, transformReply); - }; - } - static #createFunctionCommand(name, fn, resp) { - const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); - const transformReply = (0, commander_1.getTransformReply)(fn, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - fn.parseCommand(parser3, ...args); - return this._self._executeCommand(fn, parser3, this._self._commandOptions, transformReply); - }; - } - static #createScriptCommand(script, resp) { - const prefix = (0, commander_1.scriptArgumentsPrefix)(script); - const transformReply = (0, commander_1.getTransformReply)(script, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - script.parseCommand(parser3, ...args); - return this._executeScript(script, parser3, this._commandOptions, transformReply); - }; - } - static #SingleEntryCache = new single_entry_cache_1.default(); - static factory(config2) { - let Client = _a2.#SingleEntryCache.get(config2); - if (!Client) { - Client = (0, commander_1.attachConfig)({ - BaseClass: _a2, - commands: commands_1.default, - createCommand: _a2.#createCommand, - createModuleCommand: _a2.#createModuleCommand, - createFunctionCommand: _a2.#createFunctionCommand, - createScriptCommand: _a2.#createScriptCommand, - config: config2 - }); - Client.prototype.Multi = multi_command_1.default.extend(config2); - _a2.#SingleEntryCache.set(config2, Client); - } - return (options2) => { - return Object.create(new Client(options2)); - }; - } - static create(options2) { - return _a2.factory(options2)(options2); - } - static parseOptions(options2) { - if (options2?.url) { - const parsed = _a2.parseURL(options2.url); - if (options2.socket) { - if (options2.socket.tls !== void 0 && options2.socket.tls !== parsed.socket.tls) { - throw new TypeError(`tls socket option is set to ${options2.socket.tls} which is mismatch with protocol or the URL ${options2.url} passed`); - } - parsed.socket = Object.assign(options2.socket, parsed.socket); - } - Object.assign(options2, parsed); - } - return options2; - } - static parseURL(url2) { - const { hostname: hostname2, port, protocol, username, password, pathname } = new node_url_1.URL(url2), parsed = { - socket: { - host: hostname2, - tls: false - } - }; - if (protocol !== "redis:" && protocol !== "rediss:") { - throw new TypeError("Invalid protocol"); - } - parsed.socket.tls = protocol === "rediss:"; - if (port) { - parsed.socket.port = Number(port); - } - if (username) { - parsed.username = decodeURIComponent(username); - } - if (password) { - parsed.password = decodeURIComponent(password); - } - if (username || password) { - parsed.credentialsProvider = { - type: "async-credentials-provider", - credentials: async () => ({ - username: username ? decodeURIComponent(username) : void 0, - password: password ? decodeURIComponent(password) : void 0 - }) - }; - } - if (pathname.length > 1) { - const database = Number(pathname.substring(1)); - if (isNaN(database)) { - throw new TypeError("Invalid pathname"); - } - parsed.database = database; - } - return parsed; - } - #options; - #socket; - #queue; - #selectedDB = 0; - #monitorCallback; - _self = this; - _commandOptions; - // flag used to annotate that the client - // was in a watch transaction when - // a topology change occured - #dirtyWatch; - #watchEpoch; - #clientSideCache; - #credentialsSubscription = null; - // Flag used to pause writing to the socket during maintenance windows. - // When true, prevents new commands from being written while waiting for: - // 1. New socket to be ready after maintenance redirect - // 2. In-flight commands on the old socket to complete - #paused = false; - get clientSideCache() { - return this._self.#clientSideCache; - } - get options() { - return this._self.#options; - } - get isOpen() { - return this._self.#socket.isOpen; - } - get isReady() { - return this._self.#socket.isReady; - } - get isPubSubActive() { - return this._self.#queue.isPubSubActive; - } - get socketEpoch() { - return this._self.#socket.socketEpoch; - } - get isWatching() { - return this._self.#watchEpoch !== void 0; - } - /** - * Indicates whether the client's WATCH command has been invalidated by a topology change. - * When this returns true, any transaction using WATCH will fail with a WatchError. - * @returns true if the watched keys have been modified, false otherwise - */ - get isDirtyWatch() { - return this._self.#dirtyWatch !== void 0; - } - /** - * Marks the client's WATCH command as invalidated due to a topology change. - * This will cause any subsequent EXEC in a transaction to fail with a WatchError. - * @param msg - The error message explaining why the WATCH is dirty - */ - setDirtyWatch(msg) { - this._self.#dirtyWatch = msg; - } - constructor(options2) { - super(); - this.#validateOptions(options2); - this.#options = this.#initiateOptions(options2); - this.#queue = this.#initiateQueue(); - this.#socket = this.#initiateSocket(); - if (this.#options.maintNotifications !== "disabled") { - new enterprise_maintenance_manager_1.default(this.#queue, this, this.#options); - } - ; - if (this.#options.clientSideCache) { - if (this.#options.clientSideCache instanceof cache_1.ClientSideCacheProvider) { - this.#clientSideCache = this.#options.clientSideCache; - } else { - const cscConfig = this.#options.clientSideCache; - this.#clientSideCache = new cache_1.BasicClientSideCache(cscConfig); - } - this.#queue.addPushHandler((push) => { - if (push[0].toString() !== "invalidate") - return false; - if (push[1] !== null) { - for (const key of push[1]) { - this.#clientSideCache?.invalidate(key); - } - } else { - this.#clientSideCache?.invalidate(null); - } - return true; - }); - } else if (options2?.emitInvalidate) { - this.#queue.addPushHandler((push) => { - if (push[0].toString() !== "invalidate") - return false; - if (push[1] !== null) { - for (const key of push[1]) { - this.emit("invalidate", key); - } - } else { - this.emit("invalidate", null); - } - return true; - }); - } - } - #validateOptions(options2) { - if (options2?.clientSideCache && options2?.RESP !== 3) { - throw new Error("Client Side Caching is only supported with RESP3"); - } - if (options2?.emitInvalidate && options2?.RESP !== 3) { - throw new Error("emitInvalidate is only supported with RESP3"); - } - if (options2?.clientSideCache && options2?.emitInvalidate) { - throw new Error("emitInvalidate is not supported (or necessary) when clientSideCache is enabled"); - } - if (options2?.maintNotifications && options2?.maintNotifications !== "disabled" && options2?.RESP !== 3) { - throw new Error("Graceful Maintenance is only supported with RESP3"); - } - } - #initiateOptions(options2 = {}) { - if (!options2.credentialsProvider && (options2.username || options2.password)) { - options2.credentialsProvider = { - type: "async-credentials-provider", - credentials: async () => ({ - username: options2.username, - password: options2.password - }) - }; - } - if (options2.database) { - this._self.#selectedDB = options2.database; - } - if (options2.commandOptions) { - this._commandOptions = options2.commandOptions; - } - if (options2.maintNotifications !== "disabled") { - enterprise_maintenance_manager_1.default.setupDefaultMaintOptions(options2); - } - if (options2.url) { - const parsedOptions = _a2.parseOptions(options2); - if (parsedOptions?.database) { - this._self.#selectedDB = parsedOptions.database; - } - return parsedOptions; - } - return options2; - } - #initiateQueue() { - return new commands_queue_1.default(this.#options.RESP ?? 2, this.#options.commandsQueueMaxLength, (channel, listeners) => this.emit("sharded-channel-moved", channel, listeners)); - } - /** - * @param credentials - */ - reAuthenticate = async (credentials) => { - if (!(this.isPubSubActive && !this.#options.RESP)) { - await this.sendCommand((0, generic_transformers_1.parseArgs)(commands_1.default.AUTH, { - username: credentials.username, - password: credentials.password ?? "" - })); - } - }; - #subscribeForStreamingCredentials(cp) { - return cp.subscribe({ - onNext: (credentials) => { - this.reAuthenticate(credentials).catch((error2) => { - const errorMessage = error2 instanceof Error ? error2.message : String(error2); - cp.onReAuthenticationError(new authx_1.CredentialsError(errorMessage)); - }); - }, - onError: (e2) => { - const errorMessage = `Error from streaming credentials provider: ${e2.message}`; - cp.onReAuthenticationError(new authx_1.UnableToObtainNewCredentialsError(errorMessage)); - } - }); - } - async #handshake(chainId, asap) { - const promises = []; - const commandsWithErrorHandlers = await this.#getHandshakeCommands(); - if (asap) - commandsWithErrorHandlers.reverse(); - for (const { cmd, errorHandler } of commandsWithErrorHandlers) { - promises.push(this.#queue.addCommand(cmd, { - chainId, - asap - }).catch(errorHandler)); - } - return promises; - } - async #getHandshakeCommands() { - const commands = []; - const cp = this.#options.credentialsProvider; - if (this.#options.RESP) { - const hello = {}; - if (cp && cp.type === "async-credentials-provider") { - const credentials = await cp.credentials(); - if (credentials.password) { - hello.AUTH = { - username: credentials.username ?? "default", - password: credentials.password - }; - } - } - if (cp && cp.type === "streaming-credentials-provider") { - const [credentials, disposable] = await this.#subscribeForStreamingCredentials(cp); - this.#credentialsSubscription = disposable; - if (credentials.password) { - hello.AUTH = { - username: credentials.username ?? "default", - password: credentials.password - }; - } - } - if (this.#options.name) { - hello.SETNAME = this.#options.name; - } - commands.push({ cmd: (0, generic_transformers_1.parseArgs)(HELLO_1.default, this.#options.RESP, hello) }); - } else { - if (cp && cp.type === "async-credentials-provider") { - const credentials = await cp.credentials(); - if (credentials.username || credentials.password) { - commands.push({ - cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.AUTH, { - username: credentials.username, - password: credentials.password ?? "" - }) - }); - } - } - if (cp && cp.type === "streaming-credentials-provider") { - const [credentials, disposable] = await this.#subscribeForStreamingCredentials(cp); - this.#credentialsSubscription = disposable; - if (credentials.username || credentials.password) { - commands.push({ - cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.AUTH, { - username: credentials.username, - password: credentials.password ?? "" - }) - }); - } - } - if (this.#options.name) { - commands.push({ - cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.CLIENT_SETNAME, this.#options.name) - }); - } - } - if (this.#selectedDB !== 0) { - commands.push({ cmd: ["SELECT", this.#selectedDB.toString()] }); - } - if (this.#options.readonly) { - commands.push({ cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.READONLY) }); - } - if (!this.#options.disableClientInfo) { - commands.push({ - cmd: ["CLIENT", "SETINFO", "LIB-VER", package_json_1.version], - errorHandler: () => { - } - }); - commands.push({ - cmd: [ - "CLIENT", - "SETINFO", - "LIB-NAME", - this.#options.clientInfoTag ? `node-redis(${this.#options.clientInfoTag})` : "node-redis" - ], - errorHandler: () => { - } - }); - } - if (this.#clientSideCache) { - commands.push({ cmd: this.#clientSideCache.trackingOn() }); - } - if (this.#options?.emitInvalidate) { - commands.push({ cmd: ["CLIENT", "TRACKING", "ON"] }); - } - const maintenanceHandshakeCmd = await enterprise_maintenance_manager_1.default.getHandshakeCommand(this.#options); - if (maintenanceHandshakeCmd) { - commands.push(maintenanceHandshakeCmd); - } - ; - return commands; - } - #attachListeners(socket) { - socket.on("data", (chunk) => { - try { - this.#queue.decoder.write(chunk); - } catch (err) { - this.#queue.resetDecoder(); - this.emit("error", err); - } - }).on("error", (err) => { - this.emit("error", err); - this.#clientSideCache?.onError(); - if (this.#socket.isOpen && !this.#options.disableOfflineQueue) { - this.#queue.flushWaitingForReply(err); - } else { - this.#queue.flushAll(err); - } - }).on("connect", () => this.emit("connect")).on("ready", () => { - this.emit("ready"); - this.#setPingTimer(); - this.#maybeScheduleWrite(); - }).on("reconnecting", () => this.emit("reconnecting")).on("drain", () => this.#maybeScheduleWrite()).on("end", () => this.emit("end")); - } - #initiateSocket() { - const socketInitiator = async () => { - const promises = [], chainId = Symbol("Socket Initiator"); - const resubscribePromise = this.#queue.resubscribe(chainId); - resubscribePromise?.catch((error2) => { - if (error2.message && error2.message.startsWith("MOVED")) { - this.emit("__MOVED", this._self.#queue.removeAllPubSubListeners()); - } - }); - if (resubscribePromise) { - promises.push(resubscribePromise); - } - if (this.#monitorCallback) { - promises.push(this.#queue.monitor(this.#monitorCallback, { - typeMapping: this._commandOptions?.typeMapping, - chainId, - asap: true - })); - } - promises.push(...await this.#handshake(chainId, true)); - if (promises.length) { - this.#write(); - return Promise.all(promises); - } - }; - const socket = new socket_1.default(socketInitiator, this.#options.socket); - this.#attachListeners(socket); - return socket; - } - #pingTimer; - #setPingTimer() { - if (!this.#options.pingInterval || !this.#socket.isReady) - return; - clearTimeout(this.#pingTimer); - this.#pingTimer = setTimeout(() => { - if (!this.#socket.isReady) - return; - this.sendCommand(["PING"]).then((reply) => this.emit("ping-interval", reply)).catch((err) => this.emit("error", err)).finally(() => this.#setPingTimer()); - }, this.#options.pingInterval); - } - withCommandOptions(options2) { - const proxy = Object.create(this._self); - proxy._commandOptions = options2; - return proxy; - } - _commandOptionsProxy(key, value) { - const proxy = Object.create(this._self); - proxy._commandOptions = Object.create(this._commandOptions ?? null); - proxy._commandOptions[key] = value; - return proxy; - } - /** - * Override the `typeMapping` command option - */ - withTypeMapping(typeMapping) { - return this._commandOptionsProxy("typeMapping", typeMapping); - } - /** - * Override the `abortSignal` command option - */ - withAbortSignal(abortSignal) { - return this._commandOptionsProxy("abortSignal", abortSignal); - } - /** - * Override the `asap` command option to `true` - */ - asap() { - return this._commandOptionsProxy("asap", true); - } - /** - * Create the "legacy" (v3/callback) interface - */ - legacy() { - return new legacy_mode_1.RedisLegacyClient(this); - } - /** - * Create {@link RedisClientPool `RedisClientPool`} using this client as a prototype - */ - createPool(options2) { - return pool_1.RedisClientPool.create(this._self.#options, options2); - } - duplicate(overrides) { - return new (Object.getPrototypeOf(this)).constructor({ - ...this._self.#options, - commandOptions: this._commandOptions, - ...overrides - }); - } - async connect() { - await this._self.#socket.connect(); - return this; - } - /** - * @internal - */ - _ejectSocket() { - const socket = this._self.#socket; - this._self.#socket = null; - socket.removeAllListeners(); - return socket; - } - /** - * @internal - */ - _insertSocket(socket) { - if (this._self.#socket) { - this._self._ejectSocket().destroy(); - } - this._self.#socket = socket; - this._self.#attachListeners(this._self.#socket); - } - /** - * @internal - */ - _maintenanceUpdate(update) { - this._self.#socket.setMaintenanceTimeout(update.relaxedSocketTimeout); - this._self.#queue.setMaintenanceCommandTimeout(update.relaxedCommandTimeout); - } - /** - * @internal - */ - _pause() { - this._self.#paused = true; - } - /** - * @internal - */ - _unpause() { - this._self.#paused = false; - this._self.#maybeScheduleWrite(); - } - /** - * @internal - */ - async _executeCommand(command2, parser3, commandOptions, transformReply) { - const csc = this._self.#clientSideCache; - const defaultTypeMapping = this._self.#options.commandOptions === commandOptions; - const fn = () => { - return this.sendCommand(parser3.redisArgs, commandOptions); - }; - if (csc && command2.CACHEABLE && defaultTypeMapping) { - return await csc.handleCache(this._self, parser3, fn, transformReply, commandOptions?.typeMapping); - } else { - const reply = await fn(); - if (transformReply) { - return transformReply(reply, parser3.preserve, commandOptions?.typeMapping); - } - return reply; - } - } - /** - * @internal - */ - async _executeScript(script, parser3, options2, transformReply) { - const args = parser3.redisArgs; - let reply; - try { - reply = await this.sendCommand(args, options2); - } catch (err) { - if (!err?.message?.startsWith?.("NOSCRIPT")) - throw err; - args[0] = "EVAL"; - args[1] = script.SCRIPT; - reply = await this.sendCommand(args, options2); - } - return transformReply ? transformReply(reply, parser3.preserve, options2?.typeMapping) : reply; - } - sendCommand(args, options2) { - if (!this._self.#socket.isOpen) { - return Promise.reject(new errors_1.ClientClosedError()); - } else if (!this._self.#socket.isReady && this._self.#options.disableOfflineQueue) { - return Promise.reject(new errors_1.ClientOfflineError()); - } - const opts = { - ...this._self._commandOptions, - ...options2 - }; - const promise = this._self.#queue.addCommand(args, opts); - this._self.#scheduleWrite(); - return promise; - } - async SELECT(db2) { - await this.sendCommand(["SELECT", db2.toString()]); - this._self.#selectedDB = db2; - } - select = this.SELECT; - #pubSubCommand(promise) { - if (promise === void 0) - return Promise.resolve(); - this.#scheduleWrite(); - return promise; - } - SUBSCRIBE(channels, listener, bufferMode) { - return this._self.#pubSubCommand(this._self.#queue.subscribe(pub_sub_1.PUBSUB_TYPE.CHANNELS, channels, listener, bufferMode)); - } - subscribe = this.SUBSCRIBE; - UNSUBSCRIBE(channels, listener, bufferMode) { - return this._self.#pubSubCommand(this._self.#queue.unsubscribe(pub_sub_1.PUBSUB_TYPE.CHANNELS, channels, listener, bufferMode)); - } - unsubscribe = this.UNSUBSCRIBE; - PSUBSCRIBE(patterns, listener, bufferMode) { - return this._self.#pubSubCommand(this._self.#queue.subscribe(pub_sub_1.PUBSUB_TYPE.PATTERNS, patterns, listener, bufferMode)); - } - pSubscribe = this.PSUBSCRIBE; - PUNSUBSCRIBE(patterns, listener, bufferMode) { - return this._self.#pubSubCommand(this._self.#queue.unsubscribe(pub_sub_1.PUBSUB_TYPE.PATTERNS, patterns, listener, bufferMode)); - } - pUnsubscribe = this.PUNSUBSCRIBE; - SSUBSCRIBE(channels, listener, bufferMode) { - return this._self.#pubSubCommand(this._self.#queue.subscribe(pub_sub_1.PUBSUB_TYPE.SHARDED, channels, listener, bufferMode)); - } - sSubscribe = this.SSUBSCRIBE; - SUNSUBSCRIBE(channels, listener, bufferMode) { - return this._self.#pubSubCommand(this._self.#queue.unsubscribe(pub_sub_1.PUBSUB_TYPE.SHARDED, channels, listener, bufferMode)); - } - sUnsubscribe = this.SUNSUBSCRIBE; - async WATCH(key) { - const reply = await this._self.sendCommand((0, generic_transformers_1.pushVariadicArguments)(["WATCH"], key)); - this._self.#watchEpoch ??= this._self.socketEpoch; - return reply; - } - watch = this.WATCH; - async UNWATCH() { - const reply = await this._self.sendCommand(["UNWATCH"]); - this._self.#watchEpoch = void 0; - return reply; - } - unwatch = this.UNWATCH; - getPubSubListeners(type) { - return this._self.#queue.getPubSubListeners(type); - } - extendPubSubChannelListeners(type, channel, listeners) { - return this._self.#pubSubCommand(this._self.#queue.extendPubSubChannelListeners(type, channel, listeners)); - } - extendPubSubListeners(type, listeners) { - return this._self.#pubSubCommand(this._self.#queue.extendPubSubListeners(type, listeners)); - } - #write() { - if (this.#paused) { - return; - } - this.#socket.write(this.#queue.commandsToWrite()); - } - #scheduledWrite; - #scheduleWrite() { - if (!this.#socket.isReady || this.#scheduledWrite) - return; - this.#scheduledWrite = setImmediate(() => { - this.#write(); - this.#scheduledWrite = void 0; - }); - } - #maybeScheduleWrite() { - if (!this.#queue.isWaitingToWrite()) - return; - this.#scheduleWrite(); - } - /** - * @internal - */ - async _executePipeline(commands, selectedDB) { - if (!this._self.#socket.isOpen) { - return Promise.reject(new errors_1.ClientClosedError()); - } - const chainId = Symbol("Pipeline Chain"), promise = Promise.all(commands.map(({ args }) => this._self.#queue.addCommand(args, { - chainId, - typeMapping: this._commandOptions?.typeMapping - }))); - this._self.#scheduleWrite(); - const result = await promise; - if (selectedDB !== void 0) { - this._self.#selectedDB = selectedDB; - } - return result; - } - /** - * @internal - */ - async _executeMulti(commands, selectedDB) { - const dirtyWatch = this._self.#dirtyWatch; - this._self.#dirtyWatch = void 0; - const watchEpoch = this._self.#watchEpoch; - this._self.#watchEpoch = void 0; - if (!this._self.#socket.isOpen) { - throw new errors_1.ClientClosedError(); - } - if (dirtyWatch) { - throw new errors_1.WatchError(dirtyWatch); - } - if (watchEpoch && watchEpoch !== this._self.socketEpoch) { - throw new errors_1.WatchError("Client reconnected after WATCH"); - } - const typeMapping = this._commandOptions?.typeMapping; - const chainId = Symbol("MULTI Chain"); - const promises = [ - this._self.#queue.addCommand(["MULTI"], { chainId }) - ]; - for (const { args } of commands) { - promises.push(this._self.#queue.addCommand(args, { - chainId, - typeMapping - })); - } - promises.push(this._self.#queue.addCommand(["EXEC"], { chainId })); - this._self.#scheduleWrite(); - const results = await Promise.all(promises), execResult = results[results.length - 1]; - if (execResult === null) { - throw new errors_1.WatchError(); - } - if (selectedDB !== void 0) { - this._self.#selectedDB = selectedDB; - } - return execResult; - } - MULTI() { - return new this.Multi(this._executeMulti.bind(this), this._executePipeline.bind(this), this._commandOptions?.typeMapping); - } - multi = this.MULTI; - async *scanIterator(options2) { - let cursor = options2?.cursor ?? "0"; - do { - const reply = await this.scan(cursor, options2); - cursor = reply.cursor; - yield reply.keys; - } while (cursor !== "0"); - } - async *hScanIterator(key, options2) { - let cursor = options2?.cursor ?? "0"; - do { - const reply = await this.hScan(key, cursor, options2); - cursor = reply.cursor; - yield reply.entries; - } while (cursor !== "0"); - } - async *hScanValuesIterator(key, options2) { - let cursor = options2?.cursor ?? "0"; - do { - const reply = await this.hScanNoValues(key, cursor, options2); - cursor = reply.cursor; - yield reply.fields; - } while (cursor !== "0"); - } - async *hScanNoValuesIterator(key, options2) { - let cursor = options2?.cursor ?? "0"; - do { - const reply = await this.hScanNoValues(key, cursor, options2); - cursor = reply.cursor; - yield reply.fields; - } while (cursor !== "0"); - } - async *sScanIterator(key, options2) { - let cursor = options2?.cursor ?? "0"; - do { - const reply = await this.sScan(key, cursor, options2); - cursor = reply.cursor; - yield reply.members; - } while (cursor !== "0"); - } - async *zScanIterator(key, options2) { - let cursor = options2?.cursor ?? "0"; - do { - const reply = await this.zScan(key, cursor, options2); - cursor = reply.cursor; - yield reply.members; - } while (cursor !== "0"); - } - async MONITOR(callback) { - const promise = this._self.#queue.monitor(callback, { - typeMapping: this._commandOptions?.typeMapping - }); - this._self.#scheduleWrite(); - await promise; - this._self.#monitorCallback = callback; - } - monitor = this.MONITOR; - /** - * Reset the client to its default state (i.e. stop PubSub, stop monitoring, select default DB, etc.) - */ - async reset() { - const chainId = Symbol("Reset Chain"), promises = [this._self.#queue.reset(chainId)], selectedDB = this._self.#options?.database ?? 0; - this._self.#credentialsSubscription?.dispose(); - this._self.#credentialsSubscription = null; - promises.push(...await this._self.#handshake(chainId, false)); - this._self.#scheduleWrite(); - await Promise.all(promises); - this._self.#selectedDB = selectedDB; - this._self.#monitorCallback = void 0; - this._self.#dirtyWatch = void 0; - this._self.#watchEpoch = void 0; - } - /** - * If the client has state, reset it. - * An internal function to be used by wrapper class such as `RedisClientPool`. - * @internal - */ - resetIfDirty() { - let shouldReset = false; - if (this._self.#selectedDB !== (this._self.#options?.database ?? 0)) { - console.warn("Returning a client with a different selected DB"); - shouldReset = true; - } - if (this._self.#monitorCallback) { - console.warn("Returning a client with active MONITOR"); - shouldReset = true; - } - if (this._self.#queue.isPubSubActive) { - console.warn("Returning a client with active PubSub"); - shouldReset = true; - } - if (this._self.#dirtyWatch || this._self.#watchEpoch) { - console.warn("Returning a client with active WATCH"); - shouldReset = true; - } - if (shouldReset) { - return this.reset(); - } - } - /** - * @deprecated use .close instead - */ - QUIT() { - this._self.#credentialsSubscription?.dispose(); - this._self.#credentialsSubscription = null; - return this._self.#socket.quit(async () => { - clearTimeout(this._self.#pingTimer); - const quitPromise = this._self.#queue.addCommand(["QUIT"]); - this._self.#scheduleWrite(); - return quitPromise; - }); - } - quit = this.QUIT; - /** - * @deprecated use .destroy instead - */ - disconnect() { - return Promise.resolve(this.destroy()); - } - /** - * Close the client. Wait for pending commands. - */ - close() { - return new Promise((resolve82) => { - clearTimeout(this._self.#pingTimer); - this._self.#socket.close(); - this._self.#clientSideCache?.onClose(); - if (this._self.#queue.isEmpty()) { - this._self.#socket.destroySocket(); - return resolve82(); - } - const maybeClose = () => { - if (!this._self.#queue.isEmpty()) - return; - this._self.#socket.off("data", maybeClose); - this._self.#socket.destroySocket(); - resolve82(); - }; - this._self.#socket.on("data", maybeClose); - this._self.#credentialsSubscription?.dispose(); - this._self.#credentialsSubscription = null; - }); - } - /** - * Destroy the client. Rejects all commands immediately. - */ - destroy() { - clearTimeout(this._self.#pingTimer); - this._self.#queue.flushAll(new errors_1.DisconnectsClientError()); - this._self.#socket.destroy(); - this._self.#clientSideCache?.onClose(); - this._self.#credentialsSubscription?.dispose(); - this._self.#credentialsSubscription = null; - } - ref() { - this._self.#socket.ref(); - } - unref() { - this._self.#socket.unref(); - } - }; - _a2 = RedisClient; - exports2.default = RedisClient; - } -}); -var require_lib3 = __commonJS({ - "node_modules/.deno/cluster-key-slot@1.1.2/node_modules/cluster-key-slot/lib/index.js"(exports2, module14) { - var lookup = [ - 0, - 4129, - 8258, - 12387, - 16516, - 20645, - 24774, - 28903, - 33032, - 37161, - 41290, - 45419, - 49548, - 53677, - 57806, - 61935, - 4657, - 528, - 12915, - 8786, - 21173, - 17044, - 29431, - 25302, - 37689, - 33560, - 45947, - 41818, - 54205, - 50076, - 62463, - 58334, - 9314, - 13379, - 1056, - 5121, - 25830, - 29895, - 17572, - 21637, - 42346, - 46411, - 34088, - 38153, - 58862, - 62927, - 50604, - 54669, - 13907, - 9842, - 5649, - 1584, - 30423, - 26358, - 22165, - 18100, - 46939, - 42874, - 38681, - 34616, - 63455, - 59390, - 55197, - 51132, - 18628, - 22757, - 26758, - 30887, - 2112, - 6241, - 10242, - 14371, - 51660, - 55789, - 59790, - 63919, - 35144, - 39273, - 43274, - 47403, - 23285, - 19156, - 31415, - 27286, - 6769, - 2640, - 14899, - 10770, - 56317, - 52188, - 64447, - 60318, - 39801, - 35672, - 47931, - 43802, - 27814, - 31879, - 19684, - 23749, - 11298, - 15363, - 3168, - 7233, - 60846, - 64911, - 52716, - 56781, - 44330, - 48395, - 36200, - 40265, - 32407, - 28342, - 24277, - 20212, - 15891, - 11826, - 7761, - 3696, - 65439, - 61374, - 57309, - 53244, - 48923, - 44858, - 40793, - 36728, - 37256, - 33193, - 45514, - 41451, - 53516, - 49453, - 61774, - 57711, - 4224, - 161, - 12482, - 8419, - 20484, - 16421, - 28742, - 24679, - 33721, - 37784, - 41979, - 46042, - 49981, - 54044, - 58239, - 62302, - 689, - 4752, - 8947, - 13010, - 16949, - 21012, - 25207, - 29270, - 46570, - 42443, - 38312, - 34185, - 62830, - 58703, - 54572, - 50445, - 13538, - 9411, - 5280, - 1153, - 29798, - 25671, - 21540, - 17413, - 42971, - 47098, - 34713, - 38840, - 59231, - 63358, - 50973, - 55100, - 9939, - 14066, - 1681, - 5808, - 26199, - 30326, - 17941, - 22068, - 55628, - 51565, - 63758, - 59695, - 39368, - 35305, - 47498, - 43435, - 22596, - 18533, - 30726, - 26663, - 6336, - 2273, - 14466, - 10403, - 52093, - 56156, - 60223, - 64286, - 35833, - 39896, - 43963, - 48026, - 19061, - 23124, - 27191, - 31254, - 2801, - 6864, - 10931, - 14994, - 64814, - 60687, - 56684, - 52557, - 48554, - 44427, - 40424, - 36297, - 31782, - 27655, - 23652, - 19525, - 15522, - 11395, - 7392, - 3265, - 61215, - 65342, - 53085, - 57212, - 44955, - 49082, - 36825, - 40952, - 28183, - 32310, - 20053, - 24180, - 11923, - 16050, - 3793, - 7920 - ]; - var toUTF8Array = function toUTF8Array2(str) { - var char; - var i2 = 0; - var p = 0; - var utf8 = []; - var len = str.length; - for (; i2 < len; i2++) { - char = str.charCodeAt(i2); - if (char < 128) { - utf8[p++] = char; - } else if (char < 2048) { - utf8[p++] = char >> 6 | 192; - utf8[p++] = char & 63 | 128; - } else if ((char & 64512) === 55296 && i2 + 1 < str.length && (str.charCodeAt(i2 + 1) & 64512) === 56320) { - char = 65536 + ((char & 1023) << 10) + (str.charCodeAt(++i2) & 1023); - utf8[p++] = char >> 18 | 240; - utf8[p++] = char >> 12 & 63 | 128; - utf8[p++] = char >> 6 & 63 | 128; - utf8[p++] = char & 63 | 128; - } else { - utf8[p++] = char >> 12 | 224; - utf8[p++] = char >> 6 & 63 | 128; - utf8[p++] = char & 63 | 128; - } - } - return utf8; - }; - var generate = module14.exports = function generate2(str) { - var char; - var i2 = 0; - var start = -1; - var result = 0; - var resultHash = 0; - var utf8 = typeof str === "string" ? toUTF8Array(str) : str; - var len = utf8.length; - while (i2 < len) { - char = utf8[i2++]; - if (start === -1) { - if (char === 123) { - start = i2; - } - } else if (char !== 125) { - resultHash = lookup[(char ^ resultHash >> 8) & 255] ^ resultHash << 8; - } else if (i2 - 1 !== start) { - return resultHash & 16383; - } - result = lookup[(char ^ result >> 8) & 255] ^ result << 8; - } - return result & 16383; - }; - module14.exports.generateMulti = function generateMulti(keys) { - var i2 = 1; - var len = keys.length; - var base2 = generate(keys[0]); - while (i2 < len) { - if (generate(keys[i2++]) !== base2) return -1; - } - return base2; - }; - } -}); -var require_cluster_slots = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/cluster/cluster-slots.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - var _a2; - Object.defineProperty(exports2, "__esModule", { value: true }); - var errors_1 = require_errors(); - var client_1 = __importDefault(require_client()); - var pub_sub_1 = require_pub_sub(); - var cluster_key_slot_1 = __importDefault(require_lib3()); - var cache_1 = require_cache(); - var RedisClusterSlots = class { - static #SLOTS = 16384; - #options; - #clientFactory; - #emit; - slots = new Array(_a2.#SLOTS); - masters = new Array(); - replicas = new Array(); - nodeByAddress = /* @__PURE__ */ new Map(); - pubSubNode; - clientSideCache; - #isOpen = false; - get isOpen() { - return this.#isOpen; - } - #validateOptions(options2) { - if (options2?.clientSideCache && options2?.RESP !== 3) { - throw new Error("Client Side Caching is only supported with RESP3"); - } - } - constructor(options2, emit) { - this.#validateOptions(options2); - this.#options = options2; - if (options2?.clientSideCache) { - if (options2.clientSideCache instanceof cache_1.PooledClientSideCacheProvider) { - this.clientSideCache = options2.clientSideCache; - } else { - this.clientSideCache = new cache_1.BasicPooledClientSideCache(options2.clientSideCache); - } - } - this.#clientFactory = client_1.default.factory(this.#options); - this.#emit = emit; - } - async connect() { - if (this.#isOpen) { - throw new Error("Cluster already open"); - } - this.#isOpen = true; - try { - await this.#discoverWithRootNodes(); - this.#emit("connect"); - } catch (err) { - this.#isOpen = false; - throw err; - } - } - async #discoverWithRootNodes() { - let start = Math.floor(Math.random() * this.#options.rootNodes.length); - for (let i2 = start; i2 < this.#options.rootNodes.length; i2++) { - if (!this.#isOpen) - throw new Error("Cluster closed"); - if (await this.#discover(this.#options.rootNodes[i2])) - return; - } - for (let i2 = 0; i2 < start; i2++) { - if (!this.#isOpen) - throw new Error("Cluster closed"); - if (await this.#discover(this.#options.rootNodes[i2])) - return; - } - throw new errors_1.RootNodesUnavailableError(); - } - #resetSlots() { - this.slots = new Array(_a2.#SLOTS); - this.masters = []; - this.replicas = []; - this._randomNodeIterator = void 0; - } - async #discover(rootNode) { - this.clientSideCache?.clear(); - this.clientSideCache?.disable(); - try { - const addressesInUse = /* @__PURE__ */ new Set(), promises = [], eagerConnect = this.#options.minimizeConnections !== true; - const shards = await this.#getShards(rootNode); - this.#resetSlots(); - for (const { from: from3, to, master, replicas } of shards) { - const shard = { - master: this.#initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) - }; - if (this.#options.useReplicas) { - shard.replicas = replicas.map((replica) => this.#initiateSlotNode(replica, true, eagerConnect, addressesInUse, promises)); - } - for (let i2 = from3; i2 <= to; i2++) { - this.slots[i2] = shard; - } - } - if (this.pubSubNode && !addressesInUse.has(this.pubSubNode.address)) { - const channelsListeners = this.pubSubNode.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS), patternsListeners = this.pubSubNode.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS); - this.pubSubNode.client.destroy(); - if (channelsListeners.size || patternsListeners.size) { - promises.push(this.#initiatePubSubClient({ - [pub_sub_1.PUBSUB_TYPE.CHANNELS]: channelsListeners, - [pub_sub_1.PUBSUB_TYPE.PATTERNS]: patternsListeners - })); - } - } - for (const [address, node] of this.nodeByAddress.entries()) { - if (addressesInUse.has(address)) - continue; - if (node.client) { - node.client.destroy(); - } - const { pubSub } = node; - if (pubSub) { - pubSub.client.destroy(); - } - this.nodeByAddress.delete(address); - } - await Promise.all(promises); - this.clientSideCache?.enable(); - return true; - } catch (err) { - this.#emit("error", err); - return false; - } - } - async #getShards(rootNode) { - const options2 = this.#clientOptionsDefaults(rootNode); - options2.socket ??= {}; - options2.socket.reconnectStrategy = false; - options2.RESP = this.#options.RESP; - options2.commandOptions = void 0; - const client = await this.#clientFactory(options2).on("error", (err) => this.#emit("error", err)).connect(); - try { - return await client.clusterSlots(); - } finally { - client.destroy(); - } - } - #getNodeAddress(address) { - switch (typeof this.#options.nodeAddressMap) { - case "object": - return this.#options.nodeAddressMap[address]; - case "function": - return this.#options.nodeAddressMap(address); - } - } - #clientOptionsDefaults(options2) { - if (!this.#options.defaults) - return options2; - let socket; - if (this.#options.defaults.socket) { - socket = { - ...this.#options.defaults.socket, - ...options2?.socket - }; - } else { - socket = options2?.socket; - } - return { - ...this.#options.defaults, - ...options2, - socket - }; - } - #initiateSlotNode(shard, readonly2, eagerConnent, addressesInUse, promises) { - const address = `${shard.host}:${shard.port}`; - let node = this.nodeByAddress.get(address); - if (!node) { - node = { - ...shard, - address, - readonly: readonly2, - client: void 0, - connectPromise: void 0 - }; - if (eagerConnent) { - promises.push(this.#createNodeClient(node)); - } - this.nodeByAddress.set(address, node); - } - if (!addressesInUse.has(address)) { - addressesInUse.add(address); - (readonly2 ? this.replicas : this.masters).push(node); - } - return node; - } - #createClient(node, readonly2 = node.readonly) { - const socket = this.#getNodeAddress(node.address) ?? { host: node.host, port: node.port }; - const clientInfo = Object.freeze({ - host: socket.host, - port: socket.port - }); - const emit = this.#emit; - const client = this.#clientFactory(this.#clientOptionsDefaults({ - clientSideCache: this.clientSideCache, - RESP: this.#options.RESP, - socket, - readonly: readonly2 - })).on("error", (error2) => emit("node-error", error2, clientInfo)).on("reconnecting", () => emit("node-reconnecting", clientInfo)).once("ready", () => emit("node-ready", clientInfo)).once("connect", () => emit("node-connect", clientInfo)).once("end", () => emit("node-disconnect", clientInfo)).on("__MOVED", async (allPubSubListeners) => { - await this.rediscover(client); - this.#emit("__resubscribeAllPubSubListeners", allPubSubListeners); - }); - return client; - } - #createNodeClient(node, readonly2) { - const client = node.client = this.#createClient(node, readonly2); - return node.connectPromise = client.connect().finally(() => node.connectPromise = void 0); - } - nodeClient(node) { - return node.connectPromise ?? // if the node is connecting - node.client ?? // if the node is connected - this.#createNodeClient(node); - } - #runningRediscoverPromise; - async rediscover(startWith) { - this.#runningRediscoverPromise ??= this.#rediscover(startWith).finally(() => { - this.#runningRediscoverPromise = void 0; - }); - return this.#runningRediscoverPromise; - } - async #rediscover(startWith) { - if (await this.#discover(startWith.options)) - return; - return this.#discoverWithRootNodes(); - } - /** - * @deprecated Use `close` instead. - */ - quit() { - return this.#destroy((client) => client.quit()); - } - /** - * @deprecated Use `destroy` instead. - */ - disconnect() { - return this.#destroy((client) => client.disconnect()); - } - close() { - return this.#destroy((client) => client.close()); - } - destroy() { - this.#isOpen = false; - for (const client of this.#clients()) { - client.destroy(); - } - if (this.pubSubNode) { - this.pubSubNode.client.destroy(); - this.pubSubNode = void 0; - } - this.#resetSlots(); - this.nodeByAddress.clear(); - this.#emit("disconnect"); - } - *#clients() { - for (const master of this.masters) { - if (master.client) { - yield master.client; - } - if (master.pubSub) { - yield master.pubSub.client; - } - } - for (const replica of this.replicas) { - if (replica.client) { - yield replica.client; - } - } - } - async #destroy(fn) { - this.#isOpen = false; - const promises = []; - for (const client of this.#clients()) { - promises.push(fn(client)); - } - if (this.pubSubNode) { - promises.push(fn(this.pubSubNode.client)); - this.pubSubNode = void 0; - } - this.#resetSlots(); - this.nodeByAddress.clear(); - await Promise.allSettled(promises); - this.#emit("disconnect"); - } - getClient(firstKey, isReadonly) { - if (!firstKey) { - return this.nodeClient(this.getRandomNode()); - } - const slotNumber = (0, cluster_key_slot_1.default)(firstKey); - if (!isReadonly) { - return this.nodeClient(this.slots[slotNumber].master); - } - return this.nodeClient(this.getSlotRandomNode(slotNumber)); - } - *#iterateAllNodes() { - if (this.masters.length + this.replicas.length === 0) - return; - let i2 = Math.floor(Math.random() * (this.masters.length + this.replicas.length)); - if (i2 < this.masters.length) { - do { - yield this.masters[i2]; - } while (++i2 < this.masters.length); - for (const replica of this.replicas) { - yield replica; - } - } else { - i2 -= this.masters.length; - do { - yield this.replicas[i2]; - } while (++i2 < this.replicas.length); - } - while (true) { - for (const master of this.masters) { - yield master; - } - for (const replica of this.replicas) { - yield replica; - } - } - } - _randomNodeIterator; - getRandomNode() { - this._randomNodeIterator ??= this.#iterateAllNodes(); - return this._randomNodeIterator.next().value; - } - *#slotNodesIterator(slot) { - let i2 = Math.floor(Math.random() * (1 + slot.replicas.length)); - if (i2 < slot.replicas.length) { - do { - yield slot.replicas[i2]; - } while (++i2 < slot.replicas.length); - } - while (true) { - yield slot.master; - for (const replica of slot.replicas) { - yield replica; - } - } - } - getSlotRandomNode(slotNumber) { - const slot = this.slots[slotNumber]; - if (!slot.replicas?.length) { - return slot.master; - } - slot.nodesIterator ??= this.#slotNodesIterator(slot); - return slot.nodesIterator.next().value; - } - getMasterByAddress(address) { - const master = this.nodeByAddress.get(address); - if (!master) - return; - return this.nodeClient(master); - } - getPubSubClient() { - if (!this.pubSubNode) - return this.#initiatePubSubClient(); - return this.pubSubNode.connectPromise ?? this.pubSubNode.client; - } - async #initiatePubSubClient(toResubscribe) { - const index = Math.floor(Math.random() * (this.masters.length + this.replicas.length)), node = index < this.masters.length ? this.masters[index] : this.replicas[index - this.masters.length], client = this.#createClient(node, false); - this.pubSubNode = { - address: node.address, - client, - connectPromise: client.connect().then(async (client2) => { - if (toResubscribe) { - await Promise.all([ - client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS, toResubscribe[pub_sub_1.PUBSUB_TYPE.CHANNELS]), - client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS, toResubscribe[pub_sub_1.PUBSUB_TYPE.PATTERNS]) - ]); - } - this.pubSubNode.connectPromise = void 0; - return client2; - }).catch((err) => { - this.pubSubNode = void 0; - throw err; - }) - }; - return this.pubSubNode.connectPromise; - } - async executeUnsubscribeCommand(unsubscribe) { - const client = await this.getPubSubClient(); - await unsubscribe(client); - if (!client.isPubSubActive) { - client.destroy(); - this.pubSubNode = void 0; - } - } - getShardedPubSubClient(channel) { - const { master } = this.slots[(0, cluster_key_slot_1.default)(channel)]; - if (!master.pubSub) - return this.#initiateShardedPubSubClient(master); - return master.pubSub.connectPromise ?? master.pubSub.client; - } - async #initiateShardedPubSubClient(master) { - const client = this.#createClient(master, false).on("server-sunsubscribe", async (channel, listeners) => { - try { - await this.rediscover(client); - const redirectTo = await this.getShardedPubSubClient(channel); - await redirectTo.extendPubSubChannelListeners(pub_sub_1.PUBSUB_TYPE.SHARDED, channel, listeners); - } catch (err) { - this.#emit("sharded-shannel-moved-error", err, channel, listeners); - } - }); - master.pubSub = { - client, - connectPromise: client.connect().then((client2) => { - master.pubSub.connectPromise = void 0; - return client2; - }).catch((err) => { - master.pubSub = void 0; - throw err; - }) - }; - return master.pubSub.connectPromise; - } - async executeShardedUnsubscribeCommand(channel, unsubscribe) { - const { master } = this.slots[(0, cluster_key_slot_1.default)(channel)]; - if (!master.pubSub) - return; - const client = master.pubSub.connectPromise ? await master.pubSub.connectPromise : master.pubSub.client; - await unsubscribe(client); - if (!client.isPubSubActive) { - client.destroy(); - master.pubSub = void 0; - } - } - }; - _a2 = RedisClusterSlots; - exports2.default = RedisClusterSlots; - } -}); -var require_multi_command3 = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/cluster/multi-command.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var commands_1 = __importDefault(require_commands()); - var multi_command_1 = __importDefault(require_multi_command()); - var commander_1 = require_commander(); - var parser_1 = require_parser(); - var RedisClusterMultiCommand = class _RedisClusterMultiCommand { - static #createCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - const firstKey = parser3.firstKey; - return this.addCommand(firstKey, command2.IS_READ_ONLY, redisArgs, transformReply); - }; - } - static #createModuleCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - const firstKey = parser3.firstKey; - return this._self.addCommand(firstKey, command2.IS_READ_ONLY, redisArgs, transformReply); - }; - } - static #createFunctionCommand(name, fn, resp) { - const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); - const transformReply = (0, commander_1.getTransformReply)(fn, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - fn.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - const firstKey = parser3.firstKey; - return this._self.addCommand(firstKey, fn.IS_READ_ONLY, redisArgs, transformReply); - }; - } - static #createScriptCommand(script, resp) { - const transformReply = (0, commander_1.getTransformReply)(script, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - script.parseCommand(parser3, ...args); - const scriptArgs = parser3.redisArgs; - scriptArgs.preserve = parser3.preserve; - const firstKey = parser3.firstKey; - return this.#addScript(firstKey, script.IS_READ_ONLY, script, scriptArgs, transformReply); - }; - } - static extend(config2) { - return (0, commander_1.attachConfig)({ - BaseClass: _RedisClusterMultiCommand, - commands: commands_1.default, - createCommand: _RedisClusterMultiCommand.#createCommand, - createModuleCommand: _RedisClusterMultiCommand.#createModuleCommand, - createFunctionCommand: _RedisClusterMultiCommand.#createFunctionCommand, - createScriptCommand: _RedisClusterMultiCommand.#createScriptCommand, - config: config2 - }); - } - #multi; - #executeMulti; - #executePipeline; - #firstKey; - #isReadonly = true; - constructor(executeMulti, executePipeline, routing, typeMapping) { - this.#multi = new multi_command_1.default(typeMapping); - this.#executeMulti = executeMulti; - this.#executePipeline = executePipeline; - this.#firstKey = routing; - } - #setState(firstKey, isReadonly) { - this.#firstKey ??= firstKey; - this.#isReadonly &&= isReadonly; - } - addCommand(firstKey, isReadonly, args, transformReply) { - this.#setState(firstKey, isReadonly); - this.#multi.addCommand(args, transformReply); - return this; - } - #addScript(firstKey, isReadonly, script, args, transformReply) { - this.#setState(firstKey, isReadonly); - this.#multi.addScript(script, args, transformReply); - return this; - } - async exec(execAsPipeline = false) { - if (execAsPipeline) - return this.execAsPipeline(); - return this.#multi.transformReplies(await this.#executeMulti(this.#firstKey, this.#isReadonly, this.#multi.queue)); - } - EXEC = this.exec; - execTyped(execAsPipeline = false) { - return this.exec(execAsPipeline); - } - async execAsPipeline() { - if (this.#multi.queue.length === 0) - return []; - return this.#multi.transformReplies(await this.#executePipeline(this.#firstKey, this.#isReadonly, this.#multi.queue)); - } - execAsPipelineTyped() { - return this.execAsPipeline(); - } - }; - exports2.default = RedisClusterMultiCommand; - } -}); -var require_cluster = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/cluster/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var commands_1 = __importDefault(require_commands()); - var node_events_1 = __require2("node:events"); - var commander_1 = require_commander(); - var cluster_slots_1 = __importDefault(require_cluster_slots()); - var multi_command_1 = __importDefault(require_multi_command3()); - var errors_1 = require_errors(); - var parser_1 = require_parser(); - var ASKING_1 = require_ASKING(); - var single_entry_cache_1 = __importDefault(require_single_entry_cache()); - var RedisCluster = class _RedisCluster extends node_events_1.EventEmitter { - static #createCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this._self._execute(parser3.firstKey, command2.IS_READ_ONLY, this._commandOptions, (client, opts) => client._executeCommand(command2, parser3, opts, transformReply)); - }; - } - static #createModuleCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this._self._execute(parser3.firstKey, command2.IS_READ_ONLY, this._self._commandOptions, (client, opts) => client._executeCommand(command2, parser3, opts, transformReply)); - }; - } - static #createFunctionCommand(name, fn, resp) { - const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); - const transformReply = (0, commander_1.getTransformReply)(fn, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - fn.parseCommand(parser3, ...args); - return this._self._execute(parser3.firstKey, fn.IS_READ_ONLY, this._self._commandOptions, (client, opts) => client._executeCommand(fn, parser3, opts, transformReply)); - }; - } - static #createScriptCommand(script, resp) { - const prefix = (0, commander_1.scriptArgumentsPrefix)(script); - const transformReply = (0, commander_1.getTransformReply)(script, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - script.parseCommand(parser3, ...args); - return this._self._execute(parser3.firstKey, script.IS_READ_ONLY, this._commandOptions, (client, opts) => client._executeScript(script, parser3, opts, transformReply)); - }; - } - static #SingleEntryCache = new single_entry_cache_1.default(); - static factory(config2) { - let Cluster = _RedisCluster.#SingleEntryCache.get(config2); - if (!Cluster) { - Cluster = (0, commander_1.attachConfig)({ - BaseClass: _RedisCluster, - commands: commands_1.default, - createCommand: _RedisCluster.#createCommand, - createModuleCommand: _RedisCluster.#createModuleCommand, - createFunctionCommand: _RedisCluster.#createFunctionCommand, - createScriptCommand: _RedisCluster.#createScriptCommand, - config: config2 - }); - Cluster.prototype.Multi = multi_command_1.default.extend(config2); - _RedisCluster.#SingleEntryCache.set(config2, Cluster); - } - return (options2) => { - return Object.create(new Cluster(options2)); - }; - } - static create(options2) { - return _RedisCluster.factory(options2)(options2); - } - _options; - _slots; - _self = this; - _commandOptions; - /** - * An array of the cluster slots, each slot contain its `master` and `replicas`. - * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). - */ - get slots() { - return this._self._slots.slots; - } - get clientSideCache() { - return this._self._slots.clientSideCache; - } - /** - * An array of the cluster masters. - * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific master node. - */ - get masters() { - return this._self._slots.masters; - } - /** - * An array of the cluster replicas. - * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific replica node. - */ - get replicas() { - return this._self._slots.replicas; - } - /** - * A map form a node address (`:`) to its shard, each shard contain its `master` and `replicas`. - * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). - */ - get nodeByAddress() { - return this._self._slots.nodeByAddress; - } - /** - * The current pub/sub node. - */ - get pubSubNode() { - return this._self._slots.pubSubNode; - } - get isOpen() { - return this._self._slots.isOpen; - } - constructor(options2) { - super(); - this._options = options2; - this._slots = new cluster_slots_1.default(options2, this.emit.bind(this)); - this.on("__resubscribeAllPubSubListeners", this.resubscribeAllPubSubListeners.bind(this)); - if (options2?.commandOptions) { - this._commandOptions = options2.commandOptions; - } - } - duplicate(overrides) { - return new (Object.getPrototypeOf(this)).constructor({ - ...this._self._options, - commandOptions: this._commandOptions, - ...overrides - }); - } - async connect() { - await this._self._slots.connect(); - return this; - } - withCommandOptions(options2) { - const proxy = Object.create(this); - proxy._commandOptions = options2; - return proxy; - } - _commandOptionsProxy(key, value) { - const proxy = Object.create(this); - proxy._commandOptions = Object.create(this._commandOptions ?? null); - proxy._commandOptions[key] = value; - return proxy; - } - /** - * Override the `typeMapping` command option - */ - withTypeMapping(typeMapping) { - return this._commandOptionsProxy("typeMapping", typeMapping); - } - // /** - // * Override the `policies` command option - // * TODO - // */ - // withPolicies (policies: POLICIES) { - // return this._commandOptionsProxy('policies', policies); - // } - _handleAsk(fn) { - return async (client, options2) => { - const chainId = Symbol("asking chain"); - const opts = options2 ? { ...options2 } : {}; - opts.chainId = chainId; - const ret = await Promise.all([ - client.sendCommand([ASKING_1.ASKING_CMD], { chainId }), - fn(client, opts) - ]); - return ret[1]; - }; - } - async _execute(firstKey, isReadonly, options2, fn) { - const maxCommandRedirections = this._options.maxCommandRedirections ?? 16; - let client = await this._slots.getClient(firstKey, isReadonly); - let i2 = 0; - let myFn = fn; - while (true) { - try { - return await myFn(client, options2); - } catch (err) { - myFn = fn; - if (++i2 > maxCommandRedirections || !(err instanceof Error)) { - throw err; - } - if (err.message.startsWith("ASK")) { - const address = err.message.substring(err.message.lastIndexOf(" ") + 1); - let redirectTo = await this._slots.getMasterByAddress(address); - if (!redirectTo) { - await this._slots.rediscover(client); - redirectTo = await this._slots.getMasterByAddress(address); - } - if (!redirectTo) { - throw new Error(`Cannot find node ${address}`); - } - client = redirectTo; - myFn = this._handleAsk(fn); - continue; - } - if (err.message.startsWith("MOVED")) { - await this._slots.rediscover(client); - client = await this._slots.getClient(firstKey, isReadonly); - continue; - } - throw err; - } - } - } - async sendCommand(firstKey, isReadonly, args, options2) { - const opts = { - ...this._self._commandOptions, - ...options2 - }; - return this._self._execute(firstKey, isReadonly, opts, (client, opts2) => client.sendCommand(args, opts2)); - } - MULTI(routing) { - return new this.Multi(async (firstKey, isReadonly, commands) => { - const client = await this._self._slots.getClient(firstKey, isReadonly); - return client._executeMulti(commands); - }, async (firstKey, isReadonly, commands) => { - const client = await this._self._slots.getClient(firstKey, isReadonly); - return client._executePipeline(commands); - }, routing, this._commandOptions?.typeMapping); - } - multi = this.MULTI; - async SUBSCRIBE(channels, listener, bufferMode) { - return (await this._self._slots.getPubSubClient()).SUBSCRIBE(channels, listener, bufferMode); - } - subscribe = this.SUBSCRIBE; - async UNSUBSCRIBE(channels, listener, bufferMode) { - return this._self._slots.executeUnsubscribeCommand((client) => client.UNSUBSCRIBE(channels, listener, bufferMode)); - } - unsubscribe = this.UNSUBSCRIBE; - async PSUBSCRIBE(patterns, listener, bufferMode) { - return (await this._self._slots.getPubSubClient()).PSUBSCRIBE(patterns, listener, bufferMode); - } - pSubscribe = this.PSUBSCRIBE; - async PUNSUBSCRIBE(patterns, listener, bufferMode) { - return this._self._slots.executeUnsubscribeCommand((client) => client.PUNSUBSCRIBE(patterns, listener, bufferMode)); - } - pUnsubscribe = this.PUNSUBSCRIBE; - async SSUBSCRIBE(channels, listener, bufferMode) { - const maxCommandRedirections = this._self._options.maxCommandRedirections ?? 16, firstChannel = Array.isArray(channels) ? channels[0] : channels; - let client = await this._self._slots.getShardedPubSubClient(firstChannel); - for (let i2 = 0; ; i2++) { - try { - return await client.SSUBSCRIBE(channels, listener, bufferMode); - } catch (err) { - if (++i2 > maxCommandRedirections || !(err instanceof errors_1.ErrorReply)) { - throw err; - } - if (err.message.startsWith("MOVED")) { - await this._self._slots.rediscover(client); - client = await this._self._slots.getShardedPubSubClient(firstChannel); - continue; - } - throw err; - } - } - } - sSubscribe = this.SSUBSCRIBE; - SUNSUBSCRIBE(channels, listener, bufferMode) { - return this._self._slots.executeShardedUnsubscribeCommand(Array.isArray(channels) ? channels[0] : channels, (client) => client.SUNSUBSCRIBE(channels, listener, bufferMode)); - } - resubscribeAllPubSubListeners(allListeners) { - for (const [channel, listeners] of allListeners.CHANNELS) { - listeners.buffers.forEach((bufListener) => { - this.subscribe(channel, bufListener, true); - }); - listeners.strings.forEach((strListener) => { - this.subscribe(channel, strListener); - }); - } - ; - for (const [channel, listeners] of allListeners.PATTERNS) { - listeners.buffers.forEach((bufListener) => { - this.pSubscribe(channel, bufListener, true); - }); - listeners.strings.forEach((strListener) => { - this.pSubscribe(channel, strListener); - }); - } - ; - for (const [channel, listeners] of allListeners.SHARDED) { - listeners.buffers.forEach((bufListener) => { - this.sSubscribe(channel, bufListener, true); - }); - listeners.strings.forEach((strListener) => { - this.sSubscribe(channel, strListener); - }); - } - ; - } - sUnsubscribe = this.SUNSUBSCRIBE; - /** - * @deprecated Use `close` instead. - */ - quit() { - return this._self._slots.quit(); - } - /** - * @deprecated Use `destroy` instead. - */ - disconnect() { - return this._self._slots.disconnect(); - } - close() { - this._self._slots.clientSideCache?.onPoolClose(); - return this._self._slots.close(); - } - destroy() { - this._self._slots.clientSideCache?.onPoolClose(); - return this._self._slots.destroy(); - } - nodeClient(node) { - return this._self._slots.nodeClient(node); - } - /** - * Returns a random node from the cluster. - * Userful for running "forward" commands (like PUBLISH) on a random node. - */ - getRandomNode() { - return this._self._slots.getRandomNode(); - } - /** - * Get a random node from a slot. - * Useful for running readonly commands on a slot. - */ - getSlotRandomNode(slot) { - return this._self._slots.getSlotRandomNode(slot); - } - /** - * @deprecated use `.masters` instead - * TODO - */ - getMasters() { - return this.masters; - } - /** - * @deprecated use `.slots[]` instead - * TODO - */ - getSlotMaster(slot) { - return this.slots[slot].master; - } - }; - exports2.default = RedisCluster; - } -}); -var require_utils2 = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/utils.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createScriptCommand = exports2.createModuleCommand = exports2.createFunctionCommand = exports2.createCommand = exports2.clientSocketToNode = exports2.createNodeList = exports2.parseNode = void 0; - var parser_1 = require_parser(); - var commander_1 = require_commander(); - function parseNode(node) { - if (node.flags.includes("s_down") || node.flags.includes("disconnected") || node.flags.includes("failover_in_progress")) { - return void 0; - } - return { host: node.ip, port: Number(node.port) }; - } - exports2.parseNode = parseNode; - function createNodeList(nodes) { - var nodeList = []; - for (const nodeData of nodes) { - const node = parseNode(nodeData); - if (node === void 0) { - continue; - } - nodeList.push(node); - } - return nodeList; - } - exports2.createNodeList = createNodeList; - function clientSocketToNode(socket) { - const s = socket; - return { - host: s.host, - port: s.port - }; - } - exports2.clientSocketToNode = clientSocketToNode; - function createCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this._self._execute(command2.IS_READ_ONLY, (client) => client._executeCommand(command2, parser3, this.commandOptions, transformReply)); - }; - } - exports2.createCommand = createCommand; - function createFunctionCommand(name, fn, resp) { - const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); - const transformReply = (0, commander_1.getTransformReply)(fn, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - fn.parseCommand(parser3, ...args); - return this._self._execute(fn.IS_READ_ONLY, (client) => client._executeCommand(fn, parser3, this._self.commandOptions, transformReply)); - }; - } - exports2.createFunctionCommand = createFunctionCommand; - function createModuleCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - return this._self._execute(command2.IS_READ_ONLY, (client) => client._executeCommand(command2, parser3, this._self.commandOptions, transformReply)); - }; - } - exports2.createModuleCommand = createModuleCommand; - function createScriptCommand(script, resp) { - const prefix = (0, commander_1.scriptArgumentsPrefix)(script); - const transformReply = (0, commander_1.getTransformReply)(script, resp); - return async function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - script.parseCommand(parser3, ...args); - return this._self._execute(script.IS_READ_ONLY, (client) => client._executeScript(script, parser3, this.commandOptions, transformReply)); - }; - } - exports2.createScriptCommand = createScriptCommand; - } -}); -var require_multi_commands = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/multi-commands.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var commands_1 = __importDefault(require_commands()); - var multi_command_1 = __importDefault(require_multi_command()); - var commander_1 = require_commander(); - var parser_1 = require_parser(); - var RedisSentinelMultiCommand = class _RedisSentinelMultiCommand { - static _createCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - return this.addCommand(command2.IS_READ_ONLY, redisArgs, transformReply); - }; - } - static _createModuleCommand(command2, resp) { - const transformReply = (0, commander_1.getTransformReply)(command2, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - command2.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - return this._self.addCommand(command2.IS_READ_ONLY, redisArgs, transformReply); - }; - } - static _createFunctionCommand(name, fn, resp) { - const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); - const transformReply = (0, commander_1.getTransformReply)(fn, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - parser3.push(...prefix); - fn.parseCommand(parser3, ...args); - const redisArgs = parser3.redisArgs; - redisArgs.preserve = parser3.preserve; - return this._self.addCommand(fn.IS_READ_ONLY, redisArgs, transformReply); - }; - } - static _createScriptCommand(script, resp) { - const transformReply = (0, commander_1.getTransformReply)(script, resp); - return function(...args) { - const parser3 = new parser_1.BasicCommandParser(); - script.parseCommand(parser3, ...args); - const scriptArgs = parser3.redisArgs; - scriptArgs.preserve = parser3.preserve; - return this.#addScript(script.IS_READ_ONLY, script, scriptArgs, transformReply); - }; - } - static extend(config2) { - return (0, commander_1.attachConfig)({ - BaseClass: _RedisSentinelMultiCommand, - commands: commands_1.default, - createCommand: _RedisSentinelMultiCommand._createCommand, - createModuleCommand: _RedisSentinelMultiCommand._createModuleCommand, - createFunctionCommand: _RedisSentinelMultiCommand._createFunctionCommand, - createScriptCommand: _RedisSentinelMultiCommand._createScriptCommand, - config: config2 - }); - } - #multi = new multi_command_1.default(); - #sentinel; - #isReadonly = true; - constructor(sentinel, typeMapping) { - this.#multi = new multi_command_1.default(typeMapping); - this.#sentinel = sentinel; - } - #setState(isReadonly) { - this.#isReadonly &&= isReadonly; - } - addCommand(isReadonly, args, transformReply) { - this.#setState(isReadonly); - this.#multi.addCommand(args, transformReply); - return this; - } - #addScript(isReadonly, script, args, transformReply) { - this.#setState(isReadonly); - this.#multi.addScript(script, args, transformReply); - return this; - } - async exec(execAsPipeline = false) { - if (execAsPipeline) - return this.execAsPipeline(); - return this.#multi.transformReplies(await this.#sentinel._executeMulti(this.#isReadonly, this.#multi.queue)); - } - EXEC = this.exec; - execTyped(execAsPipeline = false) { - return this.exec(execAsPipeline); - } - async execAsPipeline() { - if (this.#multi.queue.length === 0) - return []; - return this.#multi.transformReplies(await this.#sentinel._executePipeline(this.#isReadonly, this.#multi.queue)); - } - execAsPipelineTyped() { - return this.execAsPipeline(); - } - }; - exports2.default = RedisSentinelMultiCommand; - } -}); -var require_pub_sub_proxy = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/pub-sub-proxy.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.PubSubProxy = void 0; - var node_events_1 = __importDefault(__require2("node:events")); - var pub_sub_1 = require_pub_sub(); - var client_1 = __importDefault(require_client()); - var PubSubProxy = class extends node_events_1.default { - #clientOptions; - #onError; - #node; - #state; - #subscriptions; - constructor(clientOptions, onError) { - super(); - this.#clientOptions = clientOptions; - this.#onError = onError; - } - #createClient() { - if (this.#node === void 0) { - throw new Error("pubSubProxy: didn't define node to do pubsub against"); - } - return new client_1.default({ - ...this.#clientOptions, - socket: { - ...this.#clientOptions.socket, - host: this.#node.host, - port: this.#node.port - } - }); - } - async #initiatePubSubClient(withSubscriptions = false) { - const client = this.#createClient().on("error", this.#onError); - const connectPromise = client.connect().then(async (client2) => { - if (this.#state?.client !== client2) { - client2.destroy(); - return this.#state?.connectPromise; - } - if (withSubscriptions && this.#subscriptions) { - await Promise.all([ - client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS, this.#subscriptions[pub_sub_1.PUBSUB_TYPE.CHANNELS]), - client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS, this.#subscriptions[pub_sub_1.PUBSUB_TYPE.PATTERNS]) - ]); - } - if (this.#state.client !== client2) { - client2.destroy(); - return this.#state?.connectPromise; - } - this.#state.connectPromise = void 0; - return client2; - }).catch((err) => { - this.#state = void 0; - throw err; - }); - this.#state = { - client, - connectPromise - }; - return connectPromise; - } - #getPubSubClient() { - if (!this.#state) - return this.#initiatePubSubClient(); - return this.#state.connectPromise ?? this.#state.client; - } - async changeNode(node) { - this.#node = node; - if (!this.#state) - return; - if (this.#state.connectPromise === void 0) { - this.#subscriptions = { - [pub_sub_1.PUBSUB_TYPE.CHANNELS]: this.#state.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS), - [pub_sub_1.PUBSUB_TYPE.PATTERNS]: this.#state.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS) - }; - this.#state.client.destroy(); - } - await this.#initiatePubSubClient(true); - } - #executeCommand(fn) { - const client = this.#getPubSubClient(); - if (client instanceof client_1.default) { - return fn(client); - } - return client.then((client2) => { - if (client2 === void 0) - return; - return fn(client2); - }).catch((err) => { - if (this.#state?.client.isPubSubActive) { - this.#state.client.destroy(); - this.#state = void 0; - } - throw err; - }); - } - subscribe(channels, listener, bufferMode) { - return this.#executeCommand((client) => client.SUBSCRIBE(channels, listener, bufferMode)); - } - #unsubscribe(fn) { - return this.#executeCommand(async (client) => { - const reply = await fn(client); - if (!client.isPubSubActive) { - client.destroy(); - this.#state = void 0; - } - return reply; - }); - } - async unsubscribe(channels, listener, bufferMode) { - return this.#unsubscribe((client) => client.UNSUBSCRIBE(channels, listener, bufferMode)); - } - async pSubscribe(patterns, listener, bufferMode) { - return this.#executeCommand((client) => client.PSUBSCRIBE(patterns, listener, bufferMode)); - } - async pUnsubscribe(patterns, listener, bufferMode) { - return this.#unsubscribe((client) => client.PUNSUBSCRIBE(patterns, listener, bufferMode)); - } - destroy() { - this.#subscriptions = void 0; - if (this.#state === void 0) - return; - if (!this.#state.connectPromise) { - this.#state.client.destroy(); - } - this.#state = void 0; - } - }; - exports2.PubSubProxy = PubSubProxy; - } -}); -var require_SENTINEL_MASTER = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_MASTER.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - /** - * Returns information about the specified master. - * @param parser - The Redis command parser. - * @param dbname - Name of the master. - */ - parseCommand(parser3, dbname) { - parser3.push("SENTINEL", "MASTER", dbname); - }, - transformReply: { - 2: generic_transformers_1.transformTuplesReply, - 3: void 0 - } - }; - } -}); -var require_SENTINEL_MONITOR = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_MONITOR.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - /** - * Instructs a Sentinel to monitor a new master with the specified parameters. - * @param parser - The Redis command parser. - * @param dbname - Name that identifies the master. - * @param host - Host of the master. - * @param port - Port of the master. - * @param quorum - Number of Sentinels that need to agree to trigger a failover. - */ - parseCommand(parser3, dbname, host, port, quorum) { - parser3.push("SENTINEL", "MONITOR", dbname, host, port, quorum); - }, - transformReply: void 0 - }; - } -}); -var require_SENTINEL_REPLICAS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_REPLICAS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - /** - * Returns a list of replicas for the specified master. - * @param parser - The Redis command parser. - * @param dbname - Name of the master. - */ - parseCommand(parser3, dbname) { - parser3.push("SENTINEL", "REPLICAS", dbname); - }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - const inferred = reply; - const initial = []; - return inferred.reduce((sentinels, x3) => { - sentinels.push((0, generic_transformers_1.transformTuplesReply)(x3, void 0, typeMapping)); - return sentinels; - }, initial); - }, - 3: void 0 - } - }; - } -}); -var require_SENTINEL_SENTINELS = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_SENTINELS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - /** - * Returns a list of Sentinel instances for the specified master. - * @param parser - The Redis command parser. - * @param dbname - Name of the master. - */ - parseCommand(parser3, dbname) { - parser3.push("SENTINEL", "SENTINELS", dbname); - }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - const inferred = reply; - const initial = []; - return inferred.reduce((sentinels, x3) => { - sentinels.push((0, generic_transformers_1.transformTuplesReply)(x3, void 0, typeMapping)); - return sentinels; - }, initial); - }, - 3: void 0 - } - }; - } -}); -var require_SENTINEL_SET = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_SET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - /** - * Sets configuration parameters for a specific master. - * @param parser - The Redis command parser. - * @param dbname - Name of the master. - * @param options - Configuration options to set as option-value pairs. - */ - parseCommand(parser3, dbname, options2) { - parser3.push("SENTINEL", "SET", dbname); - for (const option of options2) { - parser3.push(option.option, option.value); - } - }, - transformReply: void 0 - }; - } -}); -var require_commands2 = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var SENTINEL_MASTER_1 = __importDefault(require_SENTINEL_MASTER()); - var SENTINEL_MONITOR_1 = __importDefault(require_SENTINEL_MONITOR()); - var SENTINEL_REPLICAS_1 = __importDefault(require_SENTINEL_REPLICAS()); - var SENTINEL_SENTINELS_1 = __importDefault(require_SENTINEL_SENTINELS()); - var SENTINEL_SET_1 = __importDefault(require_SENTINEL_SET()); - exports2.default = { - SENTINEL_SENTINELS: SENTINEL_SENTINELS_1.default, - sentinelSentinels: SENTINEL_SENTINELS_1.default, - SENTINEL_MASTER: SENTINEL_MASTER_1.default, - sentinelMaster: SENTINEL_MASTER_1.default, - SENTINEL_REPLICAS: SENTINEL_REPLICAS_1.default, - sentinelReplicas: SENTINEL_REPLICAS_1.default, - SENTINEL_MONITOR: SENTINEL_MONITOR_1.default, - sentinelMonitor: SENTINEL_MONITOR_1.default, - SENTINEL_SET: SENTINEL_SET_1.default, - sentinelSet: SENTINEL_SET_1.default - }; - } -}); -var require_module = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/module.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var commands_1 = __importDefault(require_commands2()); - exports2.default = { - sentinel: commands_1.default - }; - } -}); -var require_wait_queue = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/wait-queue.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.WaitQueue = void 0; - var linked_list_1 = require_linked_list(); - var WaitQueue = class { - #list = new linked_list_1.SinglyLinkedList(); - #queue = new linked_list_1.SinglyLinkedList(); - push(value) { - const resolve82 = this.#queue.shift(); - if (resolve82 !== void 0) { - resolve82(value); - return; - } - this.#list.push(value); - } - shift() { - return this.#list.shift(); - } - wait() { - return new Promise((resolve82) => this.#queue.push(resolve82)); - } - }; - exports2.WaitQueue = WaitQueue; - } -}); -var require_sentinel = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.RedisSentinelFactory = exports2.RedisSentinelClient = void 0; - var node_events_1 = __require2("node:events"); - var client_1 = __importDefault(require_client()); - var commander_1 = require_commander(); - var commands_1 = __importDefault(require_commands()); - var utils_1 = require_utils2(); - var multi_commands_1 = __importDefault(require_multi_commands()); - var pub_sub_proxy_1 = require_pub_sub_proxy(); - var promises_1 = __require2("node:timers/promises"); - var module_1 = __importDefault(require_module()); - var wait_queue_1 = require_wait_queue(); - var cache_1 = require_cache(); - var RedisSentinelClient = class _RedisSentinelClient { - #clientInfo; - #internal; - _self; - /** - * Indicates if the client connection is open - * - * @returns `true` if the client connection is open, `false` otherwise - */ - get isOpen() { - return this._self.#internal.isOpen; - } - /** - * Indicates if the client connection is ready to accept commands - * - * @returns `true` if the client connection is ready, `false` otherwise - */ - get isReady() { - return this._self.#internal.isReady; - } - /** - * Gets the command options configured for this client - * - * @returns The command options for this client or `undefined` if none were set - */ - get commandOptions() { - return this._self.#commandOptions; - } - #commandOptions; - constructor(internal, clientInfo, commandOptions) { - this._self = this; - this.#internal = internal; - this.#clientInfo = clientInfo; - this.#commandOptions = commandOptions; - } - static factory(config2) { - const SentinelClient = (0, commander_1.attachConfig)({ - BaseClass: _RedisSentinelClient, - commands: commands_1.default, - createCommand: utils_1.createCommand, - createModuleCommand: utils_1.createModuleCommand, - createFunctionCommand: utils_1.createFunctionCommand, - createScriptCommand: utils_1.createScriptCommand, - config: config2 - }); - SentinelClient.prototype.Multi = multi_commands_1.default.extend(config2); - return (internal, clientInfo, commandOptions) => { - return Object.create(new SentinelClient(internal, clientInfo, commandOptions)); - }; - } - static create(options2, internal, clientInfo, commandOptions) { - return _RedisSentinelClient.factory(options2)(internal, clientInfo, commandOptions); - } - withCommandOptions(options2) { - const proxy = Object.create(this); - proxy._commandOptions = options2; - return proxy; - } - _commandOptionsProxy(key, value) { - const proxy = Object.create(this); - proxy._commandOptions = Object.create(this._self.#commandOptions ?? null); - proxy._commandOptions[key] = value; - return proxy; - } - /** - * Override the `typeMapping` command option - */ - withTypeMapping(typeMapping) { - return this._commandOptionsProxy("typeMapping", typeMapping); - } - async _execute(isReadonly, fn) { - if (this._self.#clientInfo === void 0) { - throw new Error("Attempted execution on released RedisSentinelClient lease"); - } - return await this._self.#internal.execute(fn, this._self.#clientInfo); - } - async sendCommand(isReadonly, args, options2) { - return this._execute(isReadonly, (client) => client.sendCommand(args, options2)); - } - /** - * @internal - */ - async _executePipeline(isReadonly, commands) { - return this._execute(isReadonly, (client) => client._executePipeline(commands)); - } - /**f - * @internal - */ - async _executeMulti(isReadonly, commands) { - return this._execute(isReadonly, (client) => client._executeMulti(commands)); - } - MULTI() { - return new this.Multi(this); - } - multi = this.MULTI; - WATCH(key) { - if (this._self.#clientInfo === void 0) { - throw new Error("Attempted execution on released RedisSentinelClient lease"); - } - return this._execute(false, (client) => client.watch(key)); - } - watch = this.WATCH; - UNWATCH() { - if (this._self.#clientInfo === void 0) { - throw new Error("Attempted execution on released RedisSentinelClient lease"); - } - return this._execute(false, (client) => client.unwatch()); - } - unwatch = this.UNWATCH; - /** - * Releases the client lease back to the pool - * - * After calling this method, the client instance should no longer be used as it - * will be returned to the client pool and may be given to other operations. - * - * @returns A promise that resolves when the client is ready to be reused, or undefined - * if the client was immediately ready - * @throws Error if the lease has already been released - */ - release() { - if (this._self.#clientInfo === void 0) { - throw new Error("RedisSentinelClient lease already released"); - } - const result = this._self.#internal.releaseClientLease(this._self.#clientInfo); - this._self.#clientInfo = void 0; - return result; - } - }; - exports2.RedisSentinelClient = RedisSentinelClient; - var RedisSentinel = class _RedisSentinel extends node_events_1.EventEmitter { - _self; - #internal; - #options; - /** - * Indicates if the sentinel connection is open - * - * @returns `true` if the sentinel connection is open, `false` otherwise - */ - get isOpen() { - return this._self.#internal.isOpen; - } - /** - * Indicates if the sentinel connection is ready to accept commands - * - * @returns `true` if the sentinel connection is ready, `false` otherwise - */ - get isReady() { - return this._self.#internal.isReady; - } - get commandOptions() { - return this._self.#commandOptions; - } - #commandOptions; - #trace = () => { - }; - #reservedClientInfo; - #masterClientCount = 0; - #masterClientInfo; - get clientSideCache() { - return this._self.#internal.clientSideCache; - } - constructor(options2) { - super(); - this._self = this; - this.#options = options2; - if (options2.commandOptions) { - this.#commandOptions = options2.commandOptions; - } - this.#internal = new RedisSentinelInternal(options2); - this.#internal.on("error", (err) => this.emit("error", err)); - this.#internal.on("topology-change", (event) => { - if (!this.emit("topology-change", event)) { - this._self.#trace(`RedisSentinel: re-emit for topology-change for ${event.type} event returned false`); - } - }); - } - static factory(config2) { - const Sentinel = (0, commander_1.attachConfig)({ - BaseClass: _RedisSentinel, - commands: commands_1.default, - createCommand: utils_1.createCommand, - createModuleCommand: utils_1.createModuleCommand, - createFunctionCommand: utils_1.createFunctionCommand, - createScriptCommand: utils_1.createScriptCommand, - config: config2 - }); - Sentinel.prototype.Multi = multi_commands_1.default.extend(config2); - return (options2) => { - return Object.create(new Sentinel(options2)); - }; - } - static create(options2) { - return _RedisSentinel.factory(options2)(options2); - } - withCommandOptions(options2) { - const proxy = Object.create(this); - proxy._commandOptions = options2; - return proxy; - } - _commandOptionsProxy(key, value) { - const proxy = Object.create(this); - proxy._self.#commandOptions = { - ...this._self.#commandOptions || {}, - [key]: value - }; - return proxy; - } - /** - * Override the `typeMapping` command option - */ - withTypeMapping(typeMapping) { - return this._commandOptionsProxy("typeMapping", typeMapping); - } - async connect() { - await this._self.#internal.connect(); - if (this._self.#options.reserveClient) { - this._self.#reservedClientInfo = await this._self.#internal.getClientLease(); - } - return this; - } - async _execute(isReadonly, fn) { - let clientInfo; - if (!isReadonly || !this._self.#internal.useReplicas) { - if (this._self.#reservedClientInfo) { - clientInfo = this._self.#reservedClientInfo; - } else { - this._self.#masterClientInfo ??= await this._self.#internal.getClientLease(); - clientInfo = this._self.#masterClientInfo; - this._self.#masterClientCount++; - } - } - try { - return await this._self.#internal.execute(fn, clientInfo); - } finally { - if (clientInfo !== void 0 && clientInfo === this._self.#masterClientInfo && --this._self.#masterClientCount === 0) { - const promise = this._self.#internal.releaseClientLease(clientInfo); - this._self.#masterClientInfo = void 0; - if (promise) - await promise; - } - } - } - async use(fn) { - const clientInfo = await this._self.#internal.getClientLease(); - try { - return await fn(RedisSentinelClient.create(this._self.#options, this._self.#internal, clientInfo, this._self.#commandOptions)); - } finally { - const promise = this._self.#internal.releaseClientLease(clientInfo); - if (promise) - await promise; - } - } - async sendCommand(isReadonly, args, options2) { - return this._execute(isReadonly, (client) => client.sendCommand(args, options2)); - } - /** - * @internal - */ - async _executePipeline(isReadonly, commands) { - return this._execute(isReadonly, (client) => client._executePipeline(commands)); - } - /**f - * @internal - */ - async _executeMulti(isReadonly, commands) { - return this._execute(isReadonly, (client) => client._executeMulti(commands)); - } - MULTI() { - return new this.Multi(this); - } - multi = this.MULTI; - async close() { - return this._self.#internal.close(); - } - destroy() { - return this._self.#internal.destroy(); - } - async SUBSCRIBE(channels, listener, bufferMode) { - return this._self.#internal.subscribe(channels, listener, bufferMode); - } - subscribe = this.SUBSCRIBE; - async UNSUBSCRIBE(channels, listener, bufferMode) { - return this._self.#internal.unsubscribe(channels, listener, bufferMode); - } - unsubscribe = this.UNSUBSCRIBE; - async PSUBSCRIBE(patterns, listener, bufferMode) { - return this._self.#internal.pSubscribe(patterns, listener, bufferMode); - } - pSubscribe = this.PSUBSCRIBE; - async PUNSUBSCRIBE(patterns, listener, bufferMode) { - return this._self.#internal.pUnsubscribe(patterns, listener, bufferMode); - } - pUnsubscribe = this.PUNSUBSCRIBE; - /** - * Acquires a master client lease for exclusive operations - * - * Used when multiple commands need to run on an exclusive client (for example, using `WATCH/MULTI/EXEC`). - * The returned client must be released after use with the `release()` method. - * - * @returns A promise that resolves to a Redis client connected to the master node - * @example - * ```javascript - * const clientLease = await sentinel.acquire(); - * - * try { - * await clientLease.watch('key'); - * const resp = await clientLease.multi() - * .get('key') - * .exec(); - * } finally { - * clientLease.release(); - * } - * ``` - */ - async acquire() { - const clientInfo = await this._self.#internal.getClientLease(); - return RedisSentinelClient.create(this._self.#options, this._self.#internal, clientInfo, this._self.#commandOptions); - } - getSentinelNode() { - return this._self.#internal.getSentinelNode(); - } - getMasterNode() { - return this._self.#internal.getMasterNode(); - } - getReplicaNodes() { - return this._self.#internal.getReplicaNodes(); - } - setTracer(tracer) { - if (tracer) { - this._self.#trace = (msg) => { - tracer.push(msg); - }; - } else { - this._self.#trace = () => { - }; - } - this._self.#internal.setTracer(tracer); - } - }; - exports2.default = RedisSentinel; - var RedisSentinelInternal = class extends node_events_1.EventEmitter { - #isOpen = false; - get isOpen() { - return this.#isOpen; - } - #isReady = false; - get isReady() { - return this.#isReady; - } - #name; - #nodeClientOptions; - #sentinelClientOptions; - #scanInterval; - #passthroughClientErrorEvents; - #RESP; - #anotherReset = false; - #configEpoch = 0; - #sentinelRootNodes; - #sentinelClient; - #masterClients = []; - #masterClientQueue; - #masterPoolSize; - #replicaClients = []; - #replicaClientsIdx = 0; - #replicaPoolSize; - get useReplicas() { - return this.#replicaPoolSize > 0; - } - #connectPromise; - #maxCommandRediscovers; - #pubSubProxy; - #scanTimer; - #destroy = false; - #trace = () => { - }; - #clientSideCache; - get clientSideCache() { - return this.#clientSideCache; - } - #validateOptions(options2) { - if (options2?.clientSideCache && options2?.RESP !== 3) { - throw new Error("Client Side Caching is only supported with RESP3"); - } - } - constructor(options2) { - super(); - this.#validateOptions(options2); - this.#name = options2.name; - this.#RESP = options2.RESP; - this.#sentinelRootNodes = Array.from(options2.sentinelRootNodes); - this.#maxCommandRediscovers = options2.maxCommandRediscovers ?? 16; - this.#masterPoolSize = options2.masterPoolSize ?? 1; - this.#replicaPoolSize = options2.replicaPoolSize ?? 0; - this.#scanInterval = options2.scanInterval ?? 0; - this.#passthroughClientErrorEvents = options2.passthroughClientErrorEvents ?? false; - this.#nodeClientOptions = options2.nodeClientOptions ? { ...options2.nodeClientOptions } : {}; - if (this.#nodeClientOptions.url !== void 0) { - throw new Error("invalid nodeClientOptions for Sentinel"); - } - if (options2.clientSideCache) { - if (options2.clientSideCache instanceof cache_1.PooledClientSideCacheProvider) { - this.#clientSideCache = this.#nodeClientOptions.clientSideCache = options2.clientSideCache; - } else { - const cscConfig = options2.clientSideCache; - this.#clientSideCache = this.#nodeClientOptions.clientSideCache = new cache_1.BasicPooledClientSideCache(cscConfig); - } - } - this.#sentinelClientOptions = options2.sentinelClientOptions ? Object.assign({}, options2.sentinelClientOptions) : {}; - this.#sentinelClientOptions.modules = module_1.default; - if (this.#sentinelClientOptions.url !== void 0) { - throw new Error("invalid sentinelClientOptions for Sentinel"); - } - this.#masterClientQueue = new wait_queue_1.WaitQueue(); - for (let i2 = 0; i2 < this.#masterPoolSize; i2++) { - this.#masterClientQueue.push(i2); - } - this.#pubSubProxy = new pub_sub_proxy_1.PubSubProxy(this.#nodeClientOptions, (err) => this.emit("error", err)); - } - #createClient(node, clientOptions, reconnectStrategy) { - return client_1.default.create({ - //first take the globally set RESP - RESP: this.#RESP, - //then take the client options, which can in theory overwrite it - ...clientOptions, - socket: { - ...clientOptions.socket, - host: node.host, - port: node.port, - ...reconnectStrategy !== void 0 && { reconnectStrategy } - } - }); - } - /** - * Gets a client lease from the master client pool - * - * @returns A client info object or a promise that resolves to a client info object - * when a client becomes available - */ - getClientLease() { - const id = this.#masterClientQueue.shift(); - if (id !== void 0) { - return { id }; - } - return this.#masterClientQueue.wait().then((id2) => ({ id: id2 })); - } - /** - * Releases a client lease back to the pool - * - * If the client was used for a transaction that might have left it in a dirty state, - * it will be reset before being returned to the pool. - * - * @param clientInfo The client info object representing the client to release - * @returns A promise that resolves when the client is ready to be reused, or undefined - * if the client was immediately ready or no longer exists - */ - releaseClientLease(clientInfo) { - const client = this.#masterClients[clientInfo.id]; - if (client !== void 0) { - const dirtyPromise = client.resetIfDirty(); - if (dirtyPromise) { - return dirtyPromise.then(() => this.#masterClientQueue.push(clientInfo.id)); - } - } - this.#masterClientQueue.push(clientInfo.id); - } - async connect() { - if (this.#isOpen) { - throw new Error("already attempting to open"); - } - try { - this.#isOpen = true; - this.#connectPromise = this.#connect(); - await this.#connectPromise; - this.#isReady = true; - } finally { - this.#connectPromise = void 0; - if (this.#scanInterval > 0) { - this.#scanTimer = setInterval(this.#reset.bind(this), this.#scanInterval); - } - } - } - async #connect() { - let count = 0; - while (true) { - this.#trace("starting connect loop"); - count += 1; - if (this.#destroy) { - this.#trace("in #connect and want to destroy"); - return; - } - try { - this.#anotherReset = false; - await this.transform(this.analyze(await this.observe())); - if (this.#anotherReset) { - this.#trace("#connect: anotherReset is true, so continuing"); - continue; - } - this.#trace("#connect: returning"); - return; - } catch (e2) { - this.#trace(`#connect: exception ${e2.message}`); - if (!this.#isReady && count > this.#maxCommandRediscovers) { - throw e2; - } - if (e2.message !== "no valid master node") { - console.log(e2); - } - await (0, promises_1.setTimeout)(1e3); - } finally { - this.#trace("finished connect"); - } - } - } - async execute(fn, clientInfo) { - let iter = 0; - while (true) { - if (this.#connectPromise !== void 0) { - await this.#connectPromise; - } - const client = this.#getClient(clientInfo); - if (!client.isReady) { - await this.#reset(); - continue; - } - const sockOpts = client.options?.socket; - this.#trace("attemping to send command to " + sockOpts?.host + ":" + sockOpts?.port); - try { - return await fn(client); - } catch (err) { - if (++iter > this.#maxCommandRediscovers || !(err instanceof Error)) { - throw err; - } - if (clientInfo !== void 0 && (err.message.startsWith("READONLY") || !client.isReady)) { - await this.#reset(); - continue; - } - throw err; - } - } - } - async #createPubSub(client) { - await client.pSubscribe(["switch-master", "[-+]sdown", "+slave", "+sentinel", "[-+]odown", "+slave-reconf-done"], (message, channel) => { - this.#handlePubSubControlChannel(channel, message); - }, true); - return client; - } - async #handlePubSubControlChannel(channel, message) { - this.#trace("pubsub control channel message on " + channel); - this.#reset(); - } - // if clientInfo is defined, it corresponds to a master client in the #masterClients array, otherwise loop around replicaClients - #getClient(clientInfo) { - if (clientInfo !== void 0) { - return this.#masterClients[clientInfo.id]; - } - if (this.#replicaClientsIdx >= this.#replicaClients.length) { - this.#replicaClientsIdx = 0; - } - if (this.#replicaClients.length == 0) { - throw new Error("no replicas available for read"); - } - return this.#replicaClients[this.#replicaClientsIdx++]; - } - async #reset() { - if (this.#isReady == false || this.#destroy == true) { - return; - } - if (this.#connectPromise !== void 0) { - this.#anotherReset = true; - return await this.#connectPromise; - } - try { - this.#connectPromise = this.#connect(); - return await this.#connectPromise; - } finally { - this.#trace("finished reconfgure"); - this.#connectPromise = void 0; - } - } - #handleSentinelFailure(node) { - const found = this.#sentinelRootNodes.findIndex((rootNode) => rootNode.host === node.host && rootNode.port === node.port); - if (found !== -1) { - this.#sentinelRootNodes.splice(found, 1); - } - this.#reset(); - } - async close() { - this.#destroy = true; - if (this.#connectPromise != void 0) { - await this.#connectPromise; - } - this.#isReady = false; - this.#clientSideCache?.onPoolClose(); - if (this.#scanTimer) { - clearInterval(this.#scanTimer); - this.#scanTimer = void 0; - } - const promises = []; - if (this.#sentinelClient !== void 0) { - if (this.#sentinelClient.isOpen) { - promises.push(this.#sentinelClient.close()); - } - this.#sentinelClient = void 0; - } - for (const client of this.#masterClients) { - if (client.isOpen) { - promises.push(client.close()); - } - } - this.#masterClients = []; - for (const client of this.#replicaClients) { - if (client.isOpen) { - promises.push(client.close()); - } - } - this.#replicaClients = []; - await Promise.all(promises); - this.#pubSubProxy.destroy(); - this.#isOpen = false; - } - // destroy has to be async because its stopping others async events, timers and the like - // and shouldn't return until its finished. - async destroy() { - this.#destroy = true; - if (this.#connectPromise != void 0) { - await this.#connectPromise; - } - this.#isReady = false; - this.#clientSideCache?.onPoolClose(); - if (this.#scanTimer) { - clearInterval(this.#scanTimer); - this.#scanTimer = void 0; - } - if (this.#sentinelClient !== void 0) { - if (this.#sentinelClient.isOpen) { - this.#sentinelClient.destroy(); - } - this.#sentinelClient = void 0; - } - for (const client of this.#masterClients) { - if (client.isOpen) { - client.destroy(); - } - } - this.#masterClients = []; - for (const client of this.#replicaClients) { - if (client.isOpen) { - client.destroy(); - } - } - this.#replicaClients = []; - this.#pubSubProxy.destroy(); - this.#isOpen = false; - this.#destroy = false; - } - async subscribe(channels, listener, bufferMode) { - return this.#pubSubProxy.subscribe(channels, listener, bufferMode); - } - async unsubscribe(channels, listener, bufferMode) { - return this.#pubSubProxy.unsubscribe(channels, listener, bufferMode); - } - async pSubscribe(patterns, listener, bufferMode) { - return this.#pubSubProxy.pSubscribe(patterns, listener, bufferMode); - } - async pUnsubscribe(patterns, listener, bufferMode) { - return this.#pubSubProxy.pUnsubscribe(patterns, listener, bufferMode); - } - // observe/analyze/transform remediation functions - async observe() { - for (const node of this.#sentinelRootNodes) { - let client; - try { - this.#trace(`observe: trying to connect to sentinel: ${node.host}:${node.port}`); - client = this.#createClient(node, this.#sentinelClientOptions, false); - client.on("error", (err) => this.emit("error", `obseve client error: ${err}`)); - await client.connect(); - this.#trace(`observe: connected to sentinel`); - const [sentinelData, masterData, replicaData] = await Promise.all([ - client.sentinel.sentinelSentinels(this.#name), - client.sentinel.sentinelMaster(this.#name), - client.sentinel.sentinelReplicas(this.#name) - ]); - this.#trace("observe: got all sentinel data"); - const ret = { - sentinelConnected: node, - sentinelData, - masterData, - replicaData, - currentMaster: this.getMasterNode(), - currentReplicas: this.getReplicaNodes(), - currentSentinel: this.getSentinelNode(), - replicaPoolSize: this.#replicaPoolSize, - useReplicas: this.useReplicas - }; - return ret; - } catch (err) { - this.#trace(`observe: error ${err}`); - this.emit("error", err); - } finally { - if (client !== void 0 && client.isOpen) { - this.#trace(`observe: destroying sentinel client`); - client.destroy(); - } - } - } - this.#trace(`observe: none of the sentinels are available`); - throw new Error("None of the sentinels are available"); - } - analyze(observed) { - let master = (0, utils_1.parseNode)(observed.masterData); - if (master === void 0) { - this.#trace(`analyze: no valid master node because ${observed.masterData.flags}`); - throw new Error("no valid master node"); - } - if (master.host === observed.currentMaster?.host && master.port === observed.currentMaster?.port) { - this.#trace(`analyze: master node hasn't changed from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`); - master = void 0; - } else { - this.#trace(`analyze: master node has changed to ${master.host}:${master.port} from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`); - } - let sentinel = observed.sentinelConnected; - if (sentinel.host === observed.currentSentinel?.host && sentinel.port === observed.currentSentinel.port) { - this.#trace(`analyze: sentinel node hasn't changed`); - sentinel = void 0; - } else { - this.#trace(`analyze: sentinel node has changed to ${sentinel.host}:${sentinel.port}`); - } - const replicasToClose = []; - const replicasToOpen = /* @__PURE__ */ new Map(); - const desiredSet = /* @__PURE__ */ new Set(); - const seen = /* @__PURE__ */ new Set(); - if (observed.useReplicas) { - const replicaList = (0, utils_1.createNodeList)(observed.replicaData); - for (const node of replicaList) { - desiredSet.add(JSON.stringify(node)); - } - for (const [node, value] of observed.currentReplicas) { - if (!desiredSet.has(JSON.stringify(node))) { - replicasToClose.push(node); - this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToClose`); - } else { - seen.add(JSON.stringify(node)); - if (value != observed.replicaPoolSize) { - replicasToOpen.set(node, observed.replicaPoolSize - value); - this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToOpen`); - } - } - } - for (const node of replicaList) { - if (!seen.has(JSON.stringify(node))) { - replicasToOpen.set(node, observed.replicaPoolSize); - this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToOpen`); - } - } - } - const ret = { - sentinelList: [observed.sentinelConnected].concat((0, utils_1.createNodeList)(observed.sentinelData)), - epoch: Number(observed.masterData["config-epoch"]), - sentinelToOpen: sentinel, - masterToOpen: master, - replicasToClose, - replicasToOpen - }; - return ret; - } - async transform(analyzed) { - this.#trace("transform: enter"); - let promises = []; - if (analyzed.sentinelToOpen) { - this.#trace(`transform: opening a new sentinel`); - if (this.#sentinelClient !== void 0 && this.#sentinelClient.isOpen) { - this.#trace(`transform: destroying old sentinel as open`); - this.#sentinelClient.destroy(); - this.#sentinelClient = void 0; - } else { - this.#trace(`transform: not destroying old sentinel as not open`); - } - this.#trace(`transform: creating new sentinel to ${analyzed.sentinelToOpen.host}:${analyzed.sentinelToOpen.port}`); - const node = analyzed.sentinelToOpen; - const client = this.#createClient(analyzed.sentinelToOpen, this.#sentinelClientOptions, false); - client.on("error", (err) => { - if (this.#passthroughClientErrorEvents) { - this.emit("error", new Error(`Sentinel Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); - } - const event2 = { - type: "SENTINEL", - node: (0, utils_1.clientSocketToNode)(client.options.socket), - error: err - }; - this.emit("client-error", event2); - this.#handleSentinelFailure(node); - }).on("end", () => this.#handleSentinelFailure(node)); - this.#sentinelClient = client; - this.#trace(`transform: adding sentinel client connect() to promise list`); - const promise = this.#sentinelClient.connect().then((client2) => { - return this.#createPubSub(client2); - }); - promises.push(promise); - this.#trace(`created sentinel client to ${analyzed.sentinelToOpen.host}:${analyzed.sentinelToOpen.port}`); - const event = { - type: "SENTINEL_CHANGE", - node: analyzed.sentinelToOpen - }; - this.#trace(`transform: emiting topology-change event for sentinel_change`); - if (!this.emit("topology-change", event)) { - this.#trace(`transform: emit for topology-change for sentinel_change returned false`); - } - } - if (analyzed.masterToOpen) { - this.#trace(`transform: opening a new master`); - const masterPromises = []; - const masterWatches = []; - this.#trace(`transform: destroying old masters if open`); - for (const client of this.#masterClients) { - masterWatches.push(client.isWatching || client.isDirtyWatch); - if (client.isOpen) { - client.destroy(); - } - } - this.#masterClients = []; - this.#trace(`transform: creating all master clients and adding connect promises`); - for (let i2 = 0; i2 < this.#masterPoolSize; i2++) { - const node = analyzed.masterToOpen; - const client = this.#createClient(analyzed.masterToOpen, this.#nodeClientOptions); - client.on("error", (err) => { - if (this.#passthroughClientErrorEvents) { - this.emit("error", new Error(`Master Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); - } - const event2 = { - type: "MASTER", - node: (0, utils_1.clientSocketToNode)(client.options.socket), - error: err - }; - this.emit("client-error", event2); - }); - if (masterWatches[i2]) { - client.setDirtyWatch("sentinel config changed in middle of a WATCH Transaction"); - } - this.#masterClients.push(client); - masterPromises.push(client.connect()); - this.#trace(`created master client to ${analyzed.masterToOpen.host}:${analyzed.masterToOpen.port}`); - } - this.#trace(`transform: adding promise to change #pubSubProxy node`); - masterPromises.push(this.#pubSubProxy.changeNode(analyzed.masterToOpen)); - promises.push(...masterPromises); - const event = { - type: "MASTER_CHANGE", - node: analyzed.masterToOpen - }; - this.#trace(`transform: emiting topology-change event for master_change`); - if (!this.emit("topology-change", event)) { - this.#trace(`transform: emit for topology-change for master_change returned false`); - } - this.#configEpoch++; - } - const replicaCloseSet = /* @__PURE__ */ new Set(); - for (const node of analyzed.replicasToClose) { - const str = JSON.stringify(node); - replicaCloseSet.add(str); - } - const newClientList = []; - const removedSet = /* @__PURE__ */ new Set(); - for (const replica of this.#replicaClients) { - const node = (0, utils_1.clientSocketToNode)(replica.options.socket); - const str = JSON.stringify(node); - if (replicaCloseSet.has(str) || !replica.isOpen) { - if (replica.isOpen) { - const sockOpts = replica.options?.socket; - this.#trace(`destroying replica client to ${sockOpts?.host}:${sockOpts?.port}`); - replica.destroy(); - } - if (!removedSet.has(str)) { - const event = { - type: "REPLICA_REMOVE", - node - }; - this.emit("topology-change", event); - removedSet.add(str); - } - } else { - newClientList.push(replica); - } - } - this.#replicaClients = newClientList; - if (analyzed.replicasToOpen.size != 0) { - for (const [node, size] of analyzed.replicasToOpen) { - for (let i2 = 0; i2 < size; i2++) { - const client = this.#createClient(node, this.#nodeClientOptions); - client.on("error", (err) => { - if (this.#passthroughClientErrorEvents) { - this.emit("error", new Error(`Replica Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); - } - const event2 = { - type: "REPLICA", - node: (0, utils_1.clientSocketToNode)(client.options.socket), - error: err - }; - this.emit("client-error", event2); - }); - this.#replicaClients.push(client); - promises.push(client.connect()); - this.#trace(`created replica client to ${node.host}:${node.port}`); - } - const event = { - type: "REPLICA_ADD", - node - }; - this.emit("topology-change", event); - } - } - if (analyzed.sentinelList.length != this.#sentinelRootNodes.length) { - this.#sentinelRootNodes = analyzed.sentinelList; - const event = { - type: "SENTINE_LIST_CHANGE", - size: analyzed.sentinelList.length - }; - this.emit("topology-change", event); - } - await Promise.all(promises); - this.#trace("transform: exit"); - } - // introspection functions - getMasterNode() { - if (this.#masterClients.length == 0) { - return void 0; - } - for (const master of this.#masterClients) { - if (master.isReady) { - return (0, utils_1.clientSocketToNode)(master.options.socket); - } - } - return void 0; - } - getSentinelNode() { - if (this.#sentinelClient === void 0) { - return void 0; - } - return (0, utils_1.clientSocketToNode)(this.#sentinelClient.options.socket); - } - getReplicaNodes() { - const ret = /* @__PURE__ */ new Map(); - const initialMap = /* @__PURE__ */ new Map(); - for (const replica of this.#replicaClients) { - const node = (0, utils_1.clientSocketToNode)(replica.options.socket); - const hash3 = JSON.stringify(node); - if (replica.isReady) { - initialMap.set(hash3, (initialMap.get(hash3) ?? 0) + 1); - } else { - if (!initialMap.has(hash3)) { - initialMap.set(hash3, 0); - } - } - } - for (const [key, value] of initialMap) { - ret.set(JSON.parse(key), value); - } - return ret; - } - setTracer(tracer) { - if (tracer) { - this.#trace = (msg) => { - tracer.push(msg); - }; - } else { - this.#trace = () => { - }; - } - } - }; - var RedisSentinelFactory = class extends node_events_1.EventEmitter { - options; - #sentinelRootNodes; - #replicaIdx = -1; - constructor(options2) { - super(); - this.options = options2; - this.#sentinelRootNodes = options2.sentinelRootNodes; - } - async updateSentinelRootNodes() { - for (const node of this.#sentinelRootNodes) { - const client = client_1.default.create({ - ...this.options.sentinelClientOptions, - socket: { - ...this.options.sentinelClientOptions?.socket, - host: node.host, - port: node.port, - reconnectStrategy: false - }, - modules: module_1.default - }).on("error", (err) => this.emit(`updateSentinelRootNodes: ${err}`)); - try { - await client.connect(); - } catch { - if (client.isOpen) { - client.destroy(); - } - continue; - } - try { - const sentinelData = await client.sentinel.sentinelSentinels(this.options.name); - this.#sentinelRootNodes = [node].concat((0, utils_1.createNodeList)(sentinelData)); - return; - } finally { - client.destroy(); - } - } - throw new Error("Couldn't connect to any sentinel node"); - } - async getMasterNode() { - let connected = false; - for (const node of this.#sentinelRootNodes) { - const client = client_1.default.create({ - ...this.options.sentinelClientOptions, - socket: { - ...this.options.sentinelClientOptions?.socket, - host: node.host, - port: node.port, - reconnectStrategy: false - }, - modules: module_1.default - }).on("error", (err) => this.emit(`getMasterNode: ${err}`)); - try { - await client.connect(); - } catch { - if (client.isOpen) { - client.destroy(); - } - continue; - } - connected = true; - try { - const masterData = await client.sentinel.sentinelMaster(this.options.name); - let master = (0, utils_1.parseNode)(masterData); - if (master === void 0) { - continue; - } - return master; - } finally { - client.destroy(); - } - } - if (connected) { - throw new Error("Master Node Not Enumerated"); - } - throw new Error("couldn't connect to any sentinels"); - } - async getMasterClient() { - const master = await this.getMasterNode(); - return client_1.default.create({ - ...this.options.nodeClientOptions, - socket: { - ...this.options.nodeClientOptions?.socket, - host: master.host, - port: master.port - } - }); - } - async getReplicaNodes() { - let connected = false; - for (const node of this.#sentinelRootNodes) { - const client = client_1.default.create({ - ...this.options.sentinelClientOptions, - socket: { - ...this.options.sentinelClientOptions?.socket, - host: node.host, - port: node.port, - reconnectStrategy: false - }, - modules: module_1.default - }).on("error", (err) => this.emit(`getReplicaNodes: ${err}`)); - try { - await client.connect(); - } catch { - if (client.isOpen) { - client.destroy(); - } - continue; - } - connected = true; - try { - const replicaData = await client.sentinel.sentinelReplicas(this.options.name); - const replicas = (0, utils_1.createNodeList)(replicaData); - if (replicas.length == 0) { - continue; - } - return replicas; - } finally { - client.destroy(); - } - } - if (connected) { - throw new Error("No Replicas Nodes Enumerated"); - } - throw new Error("couldn't connect to any sentinels"); - } - async getReplicaClient() { - const replicas = await this.getReplicaNodes(); - if (replicas.length == 0) { - throw new Error("no available replicas"); - } - this.#replicaIdx++; - if (this.#replicaIdx >= replicas.length) { - this.#replicaIdx = 0; - } - return client_1.default.create({ - ...this.options.nodeClientOptions, - socket: { - ...this.options.nodeClientOptions?.socket, - host: replicas[this.#replicaIdx].host, - port: replicas[this.#replicaIdx].port - } - }); - } - }; - exports2.RedisSentinelFactory = RedisSentinelFactory; - } -}); -var require_dist = __commonJS({ - "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/index.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { - for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); - }; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.BasicPooledClientSideCache = exports2.BasicClientSideCache = exports2.REDIS_FLUSH_MODES = exports2.COMMAND_LIST_FILTER_BY = exports2.CLUSTER_SLOT_STATES = exports2.FAILOVER_MODES = exports2.CLIENT_KILL_FILTERS = exports2.GEO_REPLY_WITH = exports2.createSentinel = exports2.createCluster = exports2.createClientPool = exports2.createClient = exports2.defineScript = exports2.VerbatimString = exports2.RESP_TYPES = void 0; - var decoder_1 = require_decoder(); - Object.defineProperty(exports2, "RESP_TYPES", { enumerable: true, get: function() { - return decoder_1.RESP_TYPES; - } }); - var verbatim_string_1 = require_verbatim_string(); - Object.defineProperty(exports2, "VerbatimString", { enumerable: true, get: function() { - return verbatim_string_1.VerbatimString; - } }); - var lua_script_1 = require_lua_script(); - Object.defineProperty(exports2, "defineScript", { enumerable: true, get: function() { - return lua_script_1.defineScript; - } }); - __exportStar(require_errors(), exports2); - var client_1 = __importDefault(require_client()); - exports2.createClient = client_1.default.create; - var pool_1 = require_pool(); - exports2.createClientPool = pool_1.RedisClientPool.create; - var cluster_1 = __importDefault(require_cluster()); - exports2.createCluster = cluster_1.default.create; - var sentinel_1 = __importDefault(require_sentinel()); - exports2.createSentinel = sentinel_1.default.create; - var GEOSEARCH_WITH_1 = require_GEOSEARCH_WITH(); - Object.defineProperty(exports2, "GEO_REPLY_WITH", { enumerable: true, get: function() { - return GEOSEARCH_WITH_1.GEO_REPLY_WITH; - } }); - var commands_1 = require_commands(); - Object.defineProperty(exports2, "CLIENT_KILL_FILTERS", { enumerable: true, get: function() { - return commands_1.CLIENT_KILL_FILTERS; - } }); - Object.defineProperty(exports2, "FAILOVER_MODES", { enumerable: true, get: function() { - return commands_1.FAILOVER_MODES; - } }); - Object.defineProperty(exports2, "CLUSTER_SLOT_STATES", { enumerable: true, get: function() { - return commands_1.CLUSTER_SLOT_STATES; - } }); - Object.defineProperty(exports2, "COMMAND_LIST_FILTER_BY", { enumerable: true, get: function() { - return commands_1.COMMAND_LIST_FILTER_BY; - } }); - Object.defineProperty(exports2, "REDIS_FLUSH_MODES", { enumerable: true, get: function() { - return commands_1.REDIS_FLUSH_MODES; - } }); - var cache_1 = require_cache(); - Object.defineProperty(exports2, "BasicClientSideCache", { enumerable: true, get: function() { - return cache_1.BasicClientSideCache; - } }); - Object.defineProperty(exports2, "BasicPooledClientSideCache", { enumerable: true, get: function() { - return cache_1.BasicPooledClientSideCache; - } }); - } -}); -var require_ADD = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/ADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds an item to a Bloom Filter - * @param parser - The command parser - * @param key - The name of the Bloom filter - * @param item - The item to add to the filter - */ - parseCommand(parser3, key, item) { - parser3.push("BF.ADD"); - parser3.pushKey(key); - parser3.push(item); - }, - transformReply: generic_transformers_1.transformBooleanReply - }; - } -}); -var require_CARD = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/CARD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the cardinality (number of items) in a Bloom Filter - * @param parser - The command parser - * @param key - The name of the Bloom filter to query - */ - parseCommand(parser3, key) { - parser3.push("BF.CARD"); - parser3.pushKey(key); - }, - transformReply: void 0 - }; - } -}); -var require_EXISTS2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/EXISTS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Checks if an item exists in a Bloom Filter - * @param parser - The command parser - * @param key - The name of the Bloom filter - * @param item - The item to check for existence - */ - parseCommand(parser3, key, item) { - parser3.push("BF.EXISTS"); - parser3.pushKey(key); - parser3.push(item); - }, - transformReply: generic_transformers_1.transformBooleanReply - }; - } -}); -var require_helpers = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/helpers.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.transformInfoV2Reply = void 0; - var client_1 = require_dist(); - function transformInfoV2Reply(reply, typeMapping) { - const mapType = typeMapping ? typeMapping[client_1.RESP_TYPES.MAP] : void 0; - switch (mapType) { - case Array: { - return reply; - } - case Map: { - const ret = /* @__PURE__ */ new Map(); - for (let i2 = 0; i2 < reply.length; i2 += 2) { - ret.set(reply[i2].toString(), reply[i2 + 1]); - } - return ret; - } - default: { - const ret = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < reply.length; i2 += 2) { - ret[reply[i2].toString()] = reply[i2 + 1]; - } - return ret; - } - } - } - exports2.transformInfoV2Reply = transformInfoV2Reply; - } -}); -var require_INFO2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/INFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var helpers_1 = require_helpers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns information about a Bloom Filter, including capacity, size, number of filters, items inserted, and expansion rate - * @param parser - The command parser - * @param key - The name of the Bloom filter to get information about - */ - parseCommand(parser3, key) { - parser3.push("BF.INFO"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply, _, typeMapping) => { - return (0, helpers_1.transformInfoV2Reply)(reply, typeMapping); - }, - 3: void 0 - } - }; - } -}); -var require_INSERT = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/INSERT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds one or more items to a Bloom Filter, creating it if it does not exist - * @param parser - The command parser - * @param key - The name of the Bloom filter - * @param items - One or more items to add to the filter - * @param options - Optional parameters for filter creation - * @param options.CAPACITY - Desired capacity for a new filter - * @param options.ERROR - Desired error rate for a new filter - * @param options.EXPANSION - Expansion rate for a new filter - * @param options.NOCREATE - If true, prevents automatic filter creation - * @param options.NONSCALING - Prevents the filter from creating additional sub-filters - */ - parseCommand(parser3, key, items, options2) { - parser3.push("BF.INSERT"); - parser3.pushKey(key); - if (options2?.CAPACITY !== void 0) { - parser3.push("CAPACITY", options2.CAPACITY.toString()); - } - if (options2?.ERROR !== void 0) { - parser3.push("ERROR", options2.ERROR.toString()); - } - if (options2?.EXPANSION !== void 0) { - parser3.push("EXPANSION", options2.EXPANSION.toString()); - } - if (options2?.NOCREATE) { - parser3.push("NOCREATE"); - } - if (options2?.NONSCALING) { - parser3.push("NONSCALING"); - } - parser3.push("ITEMS"); - parser3.pushVariadic(items); - }, - transformReply: generic_transformers_1.transformBooleanArrayReply - }; - } -}); -var require_LOADCHUNK = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/LOADCHUNK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Restores a Bloom Filter chunk previously saved using SCANDUMP - * @param parser - The command parser - * @param key - The name of the Bloom filter to restore - * @param iterator - Iterator value from the SCANDUMP command - * @param chunk - Data chunk from the SCANDUMP command - */ - parseCommand(parser3, key, iterator, chunk) { - parser3.push("BF.LOADCHUNK"); - parser3.pushKey(key); - parser3.push(iterator.toString(), chunk); - }, - transformReply: void 0 - }; - } -}); -var require_MADD = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/MADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds multiple items to a Bloom Filter in a single call - * @param parser - The command parser - * @param key - The name of the Bloom filter - * @param items - One or more items to add to the filter - */ - parseCommand(parser3, key, items) { - parser3.push("BF.MADD"); - parser3.pushKey(key); - parser3.pushVariadic(items); - }, - transformReply: generic_transformers_1.transformBooleanArrayReply - }; - } -}); -var require_MEXISTS = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/MEXISTS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Checks if multiple items exist in a Bloom Filter in a single call - * @param parser - The command parser - * @param key - The name of the Bloom filter - * @param items - One or more items to check for existence - */ - parseCommand(parser3, key, items) { - parser3.push("BF.MEXISTS"); - parser3.pushKey(key); - parser3.pushVariadic(items); - }, - transformReply: generic_transformers_1.transformBooleanArrayReply - }; - } -}); -var require_RESERVE = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/RESERVE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Creates an empty Bloom Filter with a given desired error ratio and initial capacity - * @param parser - The command parser - * @param key - The name of the Bloom filter to create - * @param errorRate - The desired probability for false positives (between 0 and 1) - * @param capacity - The number of entries intended to be added to the filter - * @param options - Optional parameters to tune the filter - * @param options.EXPANSION - Expansion rate for the filter - * @param options.NONSCALING - Prevents the filter from creating additional sub-filters - */ - parseCommand(parser3, key, errorRate, capacity, options2) { - parser3.push("BF.RESERVE"); - parser3.pushKey(key); - parser3.push(errorRate.toString(), capacity.toString()); - if (options2?.EXPANSION) { - parser3.push("EXPANSION", options2.EXPANSION.toString()); - } - if (options2?.NONSCALING) { - parser3.push("NONSCALING"); - } - }, - transformReply: void 0 - }; - } -}); -var require_SCANDUMP = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/SCANDUMP.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Begins an incremental save of a Bloom Filter. This is useful for large filters that can't be saved at once - * @param parser - The command parser - * @param key - The name of the Bloom filter to save - * @param iterator - Iterator value; Start at 0, and use the iterator from the response for the next chunk - */ - parseCommand(parser3, key, iterator) { - parser3.push("BF.SCANDUMP"); - parser3.pushKey(key); - parser3.push(iterator.toString()); - }, - transformReply(reply) { - return { - iterator: reply[0], - chunk: reply[1] - }; - } - }; - } -}); -var require_bloom = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/index.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { - for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); - }; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ADD_1 = __importDefault(require_ADD()); - var CARD_1 = __importDefault(require_CARD()); - var EXISTS_1 = __importDefault(require_EXISTS2()); - var INFO_1 = __importDefault(require_INFO2()); - var INSERT_1 = __importDefault(require_INSERT()); - var LOADCHUNK_1 = __importDefault(require_LOADCHUNK()); - var MADD_1 = __importDefault(require_MADD()); - var MEXISTS_1 = __importDefault(require_MEXISTS()); - var RESERVE_1 = __importDefault(require_RESERVE()); - var SCANDUMP_1 = __importDefault(require_SCANDUMP()); - __exportStar(require_helpers(), exports2); - exports2.default = { - ADD: ADD_1.default, - add: ADD_1.default, - CARD: CARD_1.default, - card: CARD_1.default, - EXISTS: EXISTS_1.default, - exists: EXISTS_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - INSERT: INSERT_1.default, - insert: INSERT_1.default, - LOADCHUNK: LOADCHUNK_1.default, - loadChunk: LOADCHUNK_1.default, - MADD: MADD_1.default, - mAdd: MADD_1.default, - MEXISTS: MEXISTS_1.default, - mExists: MEXISTS_1.default, - RESERVE: RESERVE_1.default, - reserve: RESERVE_1.default, - SCANDUMP: SCANDUMP_1.default, - scanDump: SCANDUMP_1.default - }; - } -}); -var require_INCRBY2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INCRBY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Increases the count of one or more items in a Count-Min Sketch - * @param parser - The command parser - * @param key - The name of the sketch - * @param items - A single item or array of items to increment, each with an item and increment value - */ - parseCommand(parser3, key, items) { - parser3.push("CMS.INCRBY"); - parser3.pushKey(key); - if (Array.isArray(items)) { - for (const item of items) { - pushIncrByItem(parser3, item); - } - } else { - pushIncrByItem(parser3, items); - } - }, - transformReply: void 0 - }; - function pushIncrByItem(parser3, { item, incrementBy }) { - parser3.push(item, incrementBy.toString()); - } - } -}); -var require_INFO3 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var bloom_1 = require_bloom(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns width, depth, and total count of items in a Count-Min Sketch - * @param parser - The command parser - * @param key - The name of the sketch to get information about - */ - parseCommand(parser3, key) { - parser3.push("CMS.INFO"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply, _, typeMapping) => { - return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); - }, - 3: void 0 - } - }; - } -}); -var require_INITBYDIM = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INITBYDIM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Initialize a Count-Min Sketch using width and depth parameters - * @param parser - The command parser - * @param key - The name of the sketch - * @param width - Number of counters in each array (must be a multiple of 2) - * @param depth - Number of counter arrays (determines accuracy of estimates) - */ - parseCommand(parser3, key, width, depth) { - parser3.push("CMS.INITBYDIM"); - parser3.pushKey(key); - parser3.push(width.toString(), depth.toString()); - }, - transformReply: void 0 - }; - } -}); -var require_INITBYPROB = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INITBYPROB.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Initialize a Count-Min Sketch using error rate and probability parameters - * @param parser - The command parser - * @param key - The name of the sketch - * @param error - Estimate error, as a decimal between 0 and 1 - * @param probability - The desired probability for inflated count, as a decimal between 0 and 1 - */ - parseCommand(parser3, key, error2, probability) { - parser3.push("CMS.INITBYPROB"); - parser3.pushKey(key); - parser3.push(error2.toString(), probability.toString()); - }, - transformReply: void 0 - }; - } -}); -var require_MERGE = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/MERGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Merges multiple Count-Min Sketches into a single sketch, with optional weights - * @param parser - The command parser - * @param destination - The name of the destination sketch - * @param source - Array of sketch names or array of sketches with weights - */ - parseCommand(parser3, destination, source) { - parser3.push("CMS.MERGE"); - parser3.pushKey(destination); - parser3.push(source.length.toString()); - if (isPlainSketches(source)) { - parser3.pushVariadic(source); - } else { - for (let i2 = 0; i2 < source.length; i2++) { - parser3.push(source[i2].name); - } - parser3.push("WEIGHTS"); - for (let i2 = 0; i2 < source.length; i2++) { - parser3.push(source[i2].weight.toString()); - } - } - }, - transformReply: void 0 - }; - function isPlainSketches(src2) { - return typeof src2[0] === "string" || src2[0] instanceof Buffer; - } - } -}); -var require_QUERY = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/QUERY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the count for one or more items in a Count-Min Sketch - * @param parser - The command parser - * @param key - The name of the sketch - * @param items - One or more items to get counts for - */ - parseCommand(parser3, key, items) { - parser3.push("CMS.QUERY"); - parser3.pushKey(key); - parser3.pushVariadic(items); - }, - transformReply: void 0 - }; - } -}); -var require_count_min_sketch = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var INCRBY_1 = __importDefault(require_INCRBY2()); - var INFO_1 = __importDefault(require_INFO3()); - var INITBYDIM_1 = __importDefault(require_INITBYDIM()); - var INITBYPROB_1 = __importDefault(require_INITBYPROB()); - var MERGE_1 = __importDefault(require_MERGE()); - var QUERY_1 = __importDefault(require_QUERY()); - exports2.default = { - INCRBY: INCRBY_1.default, - incrBy: INCRBY_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - INITBYDIM: INITBYDIM_1.default, - initByDim: INITBYDIM_1.default, - INITBYPROB: INITBYPROB_1.default, - initByProb: INITBYPROB_1.default, - MERGE: MERGE_1.default, - merge: MERGE_1.default, - QUERY: QUERY_1.default, - query: QUERY_1.default - }; - } -}); -var require_ADD2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/ADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds an item to a Cuckoo Filter, creating the filter if it does not exist - * @param parser - The command parser - * @param key - The name of the Cuckoo filter - * @param item - The item to add to the filter - */ - parseCommand(parser3, key, item) { - parser3.push("CF.ADD"); - parser3.pushKey(key); - parser3.push(item); - }, - transformReply: generic_transformers_1.transformBooleanReply - }; - } -}); -var require_ADDNX = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/ADDNX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds an item to a Cuckoo Filter only if it does not exist - * @param parser - The command parser - * @param key - The name of the Cuckoo filter - * @param item - The item to add to the filter if it doesn't exist - */ - parseCommand(parser3, key, item) { - parser3.push("CF.ADDNX"); - parser3.pushKey(key); - parser3.push(item); - }, - transformReply: generic_transformers_1.transformBooleanReply - }; - } -}); -var require_COUNT = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/COUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the number of times an item appears in a Cuckoo Filter - * @param parser - The command parser - * @param key - The name of the Cuckoo filter - * @param item - The item to count occurrences of - */ - parseCommand(parser3, key, item) { - parser3.push("CF.COUNT"); - parser3.pushKey(key); - parser3.push(item); - }, - transformReply: void 0 - }; - } -}); -var require_DEL2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/DEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes an item from a Cuckoo Filter if it exists - * @param parser - The command parser - * @param key - The name of the Cuckoo filter - * @param item - The item to remove from the filter - */ - parseCommand(parser3, key, item) { - parser3.push("CF.DEL"); - parser3.pushKey(key); - parser3.push(item); - }, - transformReply: generic_transformers_1.transformBooleanReply - }; - } -}); -var require_EXISTS3 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/EXISTS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Checks if an item exists in a Cuckoo Filter - * @param parser - The command parser - * @param key - The name of the Cuckoo filter - * @param item - The item to check for existence - */ - parseCommand(parser3, key, item) { - parser3.push("CF.EXISTS"); - parser3.pushKey(key); - parser3.push(item); - }, - transformReply: generic_transformers_1.transformBooleanReply - }; - } -}); -var require_INFO4 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/INFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var bloom_1 = require_bloom(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns detailed information about a Cuckoo Filter including size, buckets, filters count, items statistics and configuration - * @param parser - The command parser - * @param key - The name of the Cuckoo filter to get information about - */ - parseCommand(parser3, key) { - parser3.push("CF.INFO"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply, _, typeMapping) => { - return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); - }, - 3: void 0 - } - }; - } -}); -var require_INSERT2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/INSERT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseCfInsertArguments = void 0; - var generic_transformers_1 = require_generic_transformers(); - function parseCfInsertArguments(parser3, key, items, options2) { - parser3.pushKey(key); - if (options2?.CAPACITY !== void 0) { - parser3.push("CAPACITY", options2.CAPACITY.toString()); - } - if (options2?.NOCREATE) { - parser3.push("NOCREATE"); - } - parser3.push("ITEMS"); - parser3.pushVariadic(items); - } - exports2.parseCfInsertArguments = parseCfInsertArguments; - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds one or more items to a Cuckoo Filter, creating it if it does not exist - * @param parser - The command parser - * @param key - The name of the Cuckoo filter - * @param items - One or more items to add to the filter - * @param options - Optional parameters for filter creation - * @param options.CAPACITY - The number of entries intended to be added to the filter - * @param options.NOCREATE - If true, prevents automatic filter creation - */ - parseCommand(...args) { - args[0].push("CF.INSERT"); - parseCfInsertArguments(...args); - }, - transformReply: generic_transformers_1.transformBooleanArrayReply - }; - } -}); -var require_INSERTNX = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/INSERTNX.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var INSERT_1 = __importStar(require_INSERT2()); - exports2.default = { - IS_READ_ONLY: INSERT_1.default.IS_READ_ONLY, - parseCommand(...args) { - args[0].push("CF.INSERTNX"); - (0, INSERT_1.parseCfInsertArguments)(...args); - }, - transformReply: INSERT_1.default.transformReply - }; - } -}); -var require_LOADCHUNK2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/LOADCHUNK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Restores a Cuckoo Filter chunk previously saved using SCANDUMP - * @param parser - The command parser - * @param key - The name of the Cuckoo filter to restore - * @param iterator - Iterator value from the SCANDUMP command - * @param chunk - Data chunk from the SCANDUMP command - */ - parseCommand(parser3, key, iterator, chunk) { - parser3.push("CF.LOADCHUNK"); - parser3.pushKey(key); - parser3.push(iterator.toString(), chunk); - }, - transformReply: void 0 - }; - } -}); -var require_RESERVE2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/RESERVE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Creates an empty Cuckoo Filter with specified capacity and parameters - * @param parser - The command parser - * @param key - The name of the Cuckoo filter to create - * @param capacity - The number of entries intended to be added to the filter - * @param options - Optional parameters to tune the filter - * @param options.BUCKETSIZE - Number of items in each bucket - * @param options.MAXITERATIONS - Maximum number of iterations before declaring filter full - * @param options.EXPANSION - Number of additional buckets per expansion - */ - parseCommand(parser3, key, capacity, options2) { - parser3.push("CF.RESERVE"); - parser3.pushKey(key); - parser3.push(capacity.toString()); - if (options2?.BUCKETSIZE !== void 0) { - parser3.push("BUCKETSIZE", options2.BUCKETSIZE.toString()); - } - if (options2?.MAXITERATIONS !== void 0) { - parser3.push("MAXITERATIONS", options2.MAXITERATIONS.toString()); - } - if (options2?.EXPANSION !== void 0) { - parser3.push("EXPANSION", options2.EXPANSION.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_SCANDUMP2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/SCANDUMP.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Begins an incremental save of a Cuckoo Filter. This is useful for large filters that can't be saved at once - * @param parser - The command parser - * @param key - The name of the Cuckoo filter to save - * @param iterator - Iterator value; Start at 0, and use the iterator from the response for the next chunk - */ - parseCommand(parser3, key, iterator) { - parser3.push("CF.SCANDUMP"); - parser3.pushKey(key); - parser3.push(iterator.toString()); - }, - transformReply(reply) { - return { - iterator: reply[0], - chunk: reply[1] - }; - } - }; - } -}); -var require_cuckoo = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ADD_1 = __importDefault(require_ADD2()); - var ADDNX_1 = __importDefault(require_ADDNX()); - var COUNT_1 = __importDefault(require_COUNT()); - var DEL_1 = __importDefault(require_DEL2()); - var EXISTS_1 = __importDefault(require_EXISTS3()); - var INFO_1 = __importDefault(require_INFO4()); - var INSERT_1 = __importDefault(require_INSERT2()); - var INSERTNX_1 = __importDefault(require_INSERTNX()); - var LOADCHUNK_1 = __importDefault(require_LOADCHUNK2()); - var RESERVE_1 = __importDefault(require_RESERVE2()); - var SCANDUMP_1 = __importDefault(require_SCANDUMP2()); - exports2.default = { - ADD: ADD_1.default, - add: ADD_1.default, - ADDNX: ADDNX_1.default, - addNX: ADDNX_1.default, - COUNT: COUNT_1.default, - count: COUNT_1.default, - DEL: DEL_1.default, - del: DEL_1.default, - EXISTS: EXISTS_1.default, - exists: EXISTS_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - INSERT: INSERT_1.default, - insert: INSERT_1.default, - INSERTNX: INSERTNX_1.default, - insertNX: INSERTNX_1.default, - LOADCHUNK: LOADCHUNK_1.default, - loadChunk: LOADCHUNK_1.default, - RESERVE: RESERVE_1.default, - reserve: RESERVE_1.default, - SCANDUMP: SCANDUMP_1.default, - scanDump: SCANDUMP_1.default - }; - } -}); -var require_ADD3 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/ADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds one or more observations to a t-digest sketch - * @param parser - The command parser - * @param key - The name of the t-digest sketch - * @param values - Array of numeric values to add to the sketch - */ - parseCommand(parser3, key, values) { - parser3.push("TDIGEST.ADD"); - parser3.pushKey(key); - for (const value of values) { - parser3.push(value.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_BYRANK = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/BYRANK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.transformByRankArguments = void 0; - var generic_transformers_1 = require_generic_transformers(); - function transformByRankArguments(parser3, key, ranks) { - parser3.pushKey(key); - for (const rank of ranks) { - parser3.push(rank.toString()); - } - } - exports2.transformByRankArguments = transformByRankArguments; - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns value estimates for one or more ranks in a t-digest sketch - * @param parser - The command parser - * @param key - The name of the t-digest sketch - * @param ranks - Array of ranks to get value estimates for (ascending order) - */ - parseCommand(...args) { - args[0].push("TDIGEST.BYRANK"); - transformByRankArguments(...args); - }, - transformReply: generic_transformers_1.transformDoubleArrayReply - }; - } -}); -var require_BYREVRANK = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/BYREVRANK.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var BYRANK_1 = __importStar(require_BYRANK()); - exports2.default = { - IS_READ_ONLY: BYRANK_1.default.IS_READ_ONLY, - parseCommand(...args) { - args[0].push("TDIGEST.BYREVRANK"); - (0, BYRANK_1.transformByRankArguments)(...args); - }, - transformReply: BYRANK_1.default.transformReply - }; - } -}); -var require_CDF = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/CDF.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Estimates the cumulative distribution function for values in a t-digest sketch - * @param parser - The command parser - * @param key - The name of the t-digest sketch - * @param values - Array of values to get CDF estimates for - */ - parseCommand(parser3, key, values) { - parser3.push("TDIGEST.CDF"); - parser3.pushKey(key); - for (const item of values) { - parser3.push(item.toString()); - } - }, - transformReply: generic_transformers_1.transformDoubleArrayReply - }; - } -}); -var require_CREATE = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/CREATE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Creates a new t-digest sketch for storing distributions - * @param parser - The command parser - * @param key - The name of the t-digest sketch - * @param options - Optional parameters for sketch creation - * @param options.COMPRESSION - Compression parameter that affects performance and accuracy - */ - parseCommand(parser3, key, options2) { - parser3.push("TDIGEST.CREATE"); - parser3.pushKey(key); - if (options2?.COMPRESSION !== void 0) { - parser3.push("COMPRESSION", options2.COMPRESSION.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_INFO5 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/INFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var bloom_1 = require_bloom(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns information about a t-digest sketch including compression, capacity, nodes, weights, observations and memory usage - * @param parser - The command parser - * @param key - The name of the t-digest sketch to get information about - */ - parseCommand(parser3, key) { - parser3.push("TDIGEST.INFO"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply, _, typeMapping) => { - return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); - }, - 3: void 0 - } - }; - } -}); -var require_MAX = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/MAX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the maximum value from a t-digest sketch - * @param parser - The command parser - * @param key - The name of the t-digest sketch - */ - parseCommand(parser3, key) { - parser3.push("TDIGEST.MAX"); - parser3.pushKey(key); - }, - transformReply: generic_transformers_1.transformDoubleReply - }; - } -}); -var require_MERGE2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/MERGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Merges multiple t-digest sketches into one, with optional compression and override settings - * @param parser - The command parser - * @param destination - The name of the destination t-digest sketch - * @param source - One or more source sketch names to merge from - * @param options - Optional parameters for merge operation - * @param options.COMPRESSION - New compression value for merged sketch - * @param options.OVERRIDE - If true, override destination sketch if it exists - */ - parseCommand(parser3, destination, source, options2) { - parser3.push("TDIGEST.MERGE"); - parser3.pushKey(destination); - parser3.pushKeysLength(source); - if (options2?.COMPRESSION !== void 0) { - parser3.push("COMPRESSION", options2.COMPRESSION.toString()); - } - if (options2?.OVERRIDE) { - parser3.push("OVERRIDE"); - } - }, - transformReply: void 0 - }; - } -}); -var require_MIN = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/MIN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the minimum value from a t-digest sketch - * @param parser - The command parser - * @param key - The name of the t-digest sketch - */ - parseCommand(parser3, key) { - parser3.push("TDIGEST.MIN"); - parser3.pushKey(key); - }, - transformReply: generic_transformers_1.transformDoubleReply - }; - } -}); -var require_QUANTILE = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/QUANTILE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns value estimates at requested quantiles from a t-digest sketch - * @param parser - The command parser - * @param key - The name of the t-digest sketch - * @param quantiles - Array of quantiles (between 0 and 1) to get value estimates for - */ - parseCommand(parser3, key, quantiles) { - parser3.push("TDIGEST.QUANTILE"); - parser3.pushKey(key); - for (const quantile of quantiles) { - parser3.push(quantile.toString()); - } - }, - transformReply: generic_transformers_1.transformDoubleArrayReply - }; - } -}); -var require_RANK = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/RANK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.transformRankArguments = void 0; - function transformRankArguments(parser3, key, values) { - parser3.pushKey(key); - for (const value of values) { - parser3.push(value.toString()); - } - } - exports2.transformRankArguments = transformRankArguments; - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the rank of one or more values in a t-digest sketch (number of values that are lower than each value) - * @param parser - The command parser - * @param key - The name of the t-digest sketch - * @param values - Array of values to get ranks for - */ - parseCommand(...args) { - args[0].push("TDIGEST.RANK"); - transformRankArguments(...args); - }, - transformReply: void 0 - }; - } -}); -var require_RESET = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/RESET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Resets a t-digest sketch, clearing all previously added observations - * @param parser - The command parser - * @param key - The name of the t-digest sketch to reset - */ - parseCommand(parser3, key) { - parser3.push("TDIGEST.RESET"); - parser3.pushKey(key); - }, - transformReply: void 0 - }; - } -}); -var require_REVRANK = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/REVRANK.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var RANK_1 = __importStar(require_RANK()); - exports2.default = { - IS_READ_ONLY: RANK_1.default.IS_READ_ONLY, - parseCommand(...args) { - args[0].push("TDIGEST.REVRANK"); - (0, RANK_1.transformRankArguments)(...args); - }, - transformReply: RANK_1.default.transformReply - }; - } -}); -var require_TRIMMED_MEAN = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/TRIMMED_MEAN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the mean value from a t-digest sketch after trimming values at specified percentiles - * @param parser - The command parser - * @param key - The name of the t-digest sketch - * @param lowCutPercentile - Lower percentile cutoff (between 0 and 100) - * @param highCutPercentile - Higher percentile cutoff (between 0 and 100) - */ - parseCommand(parser3, key, lowCutPercentile, highCutPercentile) { - parser3.push("TDIGEST.TRIMMED_MEAN"); - parser3.pushKey(key); - parser3.push(lowCutPercentile.toString(), highCutPercentile.toString()); - }, - transformReply: generic_transformers_1.transformDoubleReply - }; - } -}); -var require_t_digest = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ADD_1 = __importDefault(require_ADD3()); - var BYRANK_1 = __importDefault(require_BYRANK()); - var BYREVRANK_1 = __importDefault(require_BYREVRANK()); - var CDF_1 = __importDefault(require_CDF()); - var CREATE_1 = __importDefault(require_CREATE()); - var INFO_1 = __importDefault(require_INFO5()); - var MAX_1 = __importDefault(require_MAX()); - var MERGE_1 = __importDefault(require_MERGE2()); - var MIN_1 = __importDefault(require_MIN()); - var QUANTILE_1 = __importDefault(require_QUANTILE()); - var RANK_1 = __importDefault(require_RANK()); - var RESET_1 = __importDefault(require_RESET()); - var REVRANK_1 = __importDefault(require_REVRANK()); - var TRIMMED_MEAN_1 = __importDefault(require_TRIMMED_MEAN()); - exports2.default = { - ADD: ADD_1.default, - add: ADD_1.default, - BYRANK: BYRANK_1.default, - byRank: BYRANK_1.default, - BYREVRANK: BYREVRANK_1.default, - byRevRank: BYREVRANK_1.default, - CDF: CDF_1.default, - cdf: CDF_1.default, - CREATE: CREATE_1.default, - create: CREATE_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - MAX: MAX_1.default, - max: MAX_1.default, - MERGE: MERGE_1.default, - merge: MERGE_1.default, - MIN: MIN_1.default, - min: MIN_1.default, - QUANTILE: QUANTILE_1.default, - quantile: QUANTILE_1.default, - RANK: RANK_1.default, - rank: RANK_1.default, - RESET: RESET_1.default, - reset: RESET_1.default, - REVRANK: REVRANK_1.default, - revRank: REVRANK_1.default, - TRIMMED_MEAN: TRIMMED_MEAN_1.default, - trimmedMean: TRIMMED_MEAN_1.default - }; - } -}); -var require_ADD4 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/ADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds one or more items to a Top-K filter and returns items dropped from the top-K list - * @param parser - The command parser - * @param key - The name of the Top-K filter - * @param items - One or more items to add to the filter - */ - parseCommand(parser3, key, items) { - parser3.push("TOPK.ADD"); - parser3.pushKey(key); - parser3.pushVariadic(items); - }, - transformReply: void 0 - }; - } -}); -var require_COUNT2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/COUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the count of occurrences for one or more items in a Top-K filter - * @param parser - The command parser - * @param key - The name of the Top-K filter - * @param items - One or more items to get counts for - */ - parseCommand(parser3, key, items) { - parser3.push("TOPK.COUNT"); - parser3.pushKey(key); - parser3.pushVariadic(items); - }, - transformReply: void 0 - }; - } -}); -var require_INCRBY3 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/INCRBY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - function pushIncrByItem(parser3, { item, incrementBy }) { - parser3.push(item, incrementBy.toString()); - } - exports2.default = { - IS_READ_ONLY: false, - /** - * Increases the score of one or more items in a Top-K filter by specified increments - * @param parser - The command parser - * @param key - The name of the Top-K filter - * @param items - A single item or array of items to increment, each with an item name and increment value - */ - parseCommand(parser3, key, items) { - parser3.push("TOPK.INCRBY"); - parser3.pushKey(key); - if (Array.isArray(items)) { - for (const item of items) { - pushIncrByItem(parser3, item); - } - } else { - pushIncrByItem(parser3, items); - } - }, - transformReply: void 0 - }; - } -}); -var require_INFO6 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/INFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var bloom_1 = require_bloom(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns configuration and statistics of a Top-K filter, including k, width, depth, and decay parameters - * @param parser - The command parser - * @param key - The name of the Top-K filter to get information about - */ - parseCommand(parser3, key) { - parser3.push("TOPK.INFO"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - reply[7] = generic_transformers_1.transformDoubleReply[2](reply[7], preserve, typeMapping); - return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); - }, - 3: void 0 - } - }; - } -}); -var require_LIST_WITHCOUNT = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/LIST_WITHCOUNT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns all items in a Top-K filter with their respective counts - * @param parser - The command parser - * @param key - The name of the Top-K filter - */ - parseCommand(parser3, key) { - parser3.push("TOPK.LIST"); - parser3.pushKey(key); - parser3.push("WITHCOUNT"); - }, - transformReply(rawReply) { - const reply = []; - for (let i2 = 0; i2 < rawReply.length; i2++) { - reply.push({ - item: rawReply[i2], - count: rawReply[++i2] - }); - } - return reply; - } - }; - } -}); -var require_LIST = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/LIST.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns all items in a Top-K filter - * @param parser - The command parser - * @param key - The name of the Top-K filter - */ - parseCommand(parser3, key) { - parser3.push("TOPK.LIST"); - parser3.pushKey(key); - }, - transformReply: void 0 - }; - } -}); -var require_QUERY2 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/QUERY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Checks if one or more items are in the Top-K list - * @param parser - The command parser - * @param key - The name of the Top-K filter - * @param items - One or more items to check in the filter - */ - parseCommand(parser3, key, items) { - parser3.push("TOPK.QUERY"); - parser3.pushKey(key); - parser3.pushVariadic(items); - }, - transformReply: generic_transformers_1.transformBooleanArrayReply - }; - } -}); -var require_RESERVE3 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/RESERVE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Creates a new Top-K filter with specified parameters - * @param parser - The command parser - * @param key - The name of the Top-K filter - * @param topK - Number of top occurring items to keep - * @param options - Optional parameters for filter configuration - * @param options.width - Number of counters in each array - * @param options.depth - Number of counter-arrays - * @param options.decay - Counter decay factor - */ - parseCommand(parser3, key, topK, options2) { - parser3.push("TOPK.RESERVE"); - parser3.pushKey(key); - parser3.push(topK.toString()); - if (options2) { - parser3.push(options2.width.toString(), options2.depth.toString(), options2.decay.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_top_k = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ADD_1 = __importDefault(require_ADD4()); - var COUNT_1 = __importDefault(require_COUNT2()); - var INCRBY_1 = __importDefault(require_INCRBY3()); - var INFO_1 = __importDefault(require_INFO6()); - var LIST_WITHCOUNT_1 = __importDefault(require_LIST_WITHCOUNT()); - var LIST_1 = __importDefault(require_LIST()); - var QUERY_1 = __importDefault(require_QUERY2()); - var RESERVE_1 = __importDefault(require_RESERVE3()); - exports2.default = { - ADD: ADD_1.default, - add: ADD_1.default, - COUNT: COUNT_1.default, - count: COUNT_1.default, - INCRBY: INCRBY_1.default, - incrBy: INCRBY_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - LIST_WITHCOUNT: LIST_WITHCOUNT_1.default, - listWithCount: LIST_WITHCOUNT_1.default, - LIST: LIST_1.default, - list: LIST_1.default, - QUERY: QUERY_1.default, - query: QUERY_1.default, - RESERVE: RESERVE_1.default, - reserve: RESERVE_1.default - }; - } -}); -var require_commands3 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var bloom_1 = __importDefault(require_bloom()); - var count_min_sketch_1 = __importDefault(require_count_min_sketch()); - var cuckoo_1 = __importDefault(require_cuckoo()); - var t_digest_1 = __importDefault(require_t_digest()); - var top_k_1 = __importDefault(require_top_k()); - exports2.default = { - bf: bloom_1.default, - cms: count_min_sketch_1.default, - cf: cuckoo_1.default, - tDigest: t_digest_1.default, - topK: top_k_1.default - }; - } -}); -var require_lib4 = __commonJS({ - "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = void 0; - var commands_1 = require_commands3(); - Object.defineProperty(exports2, "default", { enumerable: true, get: function() { - return __importDefault(commands_1).default; - } }); - } -}); -var require_ARRAPPEND = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRAPPEND.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Appends one or more values to the end of an array in a JSON document. - * Returns the new array length after append, or null if the path does not exist. - * - * @param parser - The Redis command parser - * @param key - The key to append to - * @param path - Path to the array in the JSON document - * @param json - The first value to append - * @param jsons - Additional values to append - */ - parseCommand(parser3, key, path8, json, ...jsons) { - parser3.push("JSON.ARRAPPEND"); - parser3.pushKey(key); - parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(json)); - for (let i2 = 0; i2 < jsons.length; i2++) { - parser3.push((0, generic_transformers_1.transformRedisJsonArgument)(jsons[i2])); - } - }, - transformReply: void 0 - }; - } -}); -var require_ARRINDEX = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRINDEX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the index of the first occurrence of a value in a JSON array. - * If the specified value is not found, it returns -1, or null if the path does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the array - * @param path - Path to the array in the JSON document - * @param json - The value to search for - * @param options - Optional range parameters for the search - * @param options.range.start - Starting index for the search - * @param options.range.stop - Optional ending index for the search - */ - parseCommand(parser3, key, path8, json, options2) { - parser3.push("JSON.ARRINDEX"); - parser3.pushKey(key); - parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(json)); - if (options2?.range) { - parser3.push(options2.range.start.toString()); - if (options2.range.stop !== void 0) { - parser3.push(options2.range.stop.toString()); - } - } - }, - transformReply: void 0 - }; - } -}); -var require_ARRINSERT = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRINSERT.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Inserts one or more values into an array at the specified index. - * Returns the new array length after insert, or null if the path does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the array - * @param path - Path to the array in the JSON document - * @param index - The position where to insert the values - * @param json - The first value to insert - * @param jsons - Additional values to insert - */ - parseCommand(parser3, key, path8, index, json, ...jsons) { - parser3.push("JSON.ARRINSERT"); - parser3.pushKey(key); - parser3.push(path8, index.toString(), (0, generic_transformers_1.transformRedisJsonArgument)(json)); - for (let i2 = 0; i2 < jsons.length; i2++) { - parser3.push((0, generic_transformers_1.transformRedisJsonArgument)(jsons[i2])); - } - }, - transformReply: void 0 - }; - } -}); -var require_ARRLEN = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRLEN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the length of an array in a JSON document. - * Returns null if the path does not exist or the value is not an array. - * - * @param parser - The Redis command parser - * @param key - The key containing the array - * @param options - Optional parameters - * @param options.path - Path to the array in the JSON document - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.ARRLEN"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_ARRPOP = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRPOP.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Removes and returns an element from an array in a JSON document. - * Returns null if the path does not exist or the value is not an array. - * - * @param parser - The Redis command parser - * @param key - The key containing the array - * @param options - Optional parameters - * @param options.path - Path to the array in the JSON document - * @param options.index - Optional index to pop from. Default is -1 (last element) - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.ARRPOP"); - parser3.pushKey(key); - if (options2) { - parser3.push(options2.path); - if (options2.index !== void 0) { - parser3.push(options2.index.toString()); - } - } - }, - transformReply(reply) { - return (0, generic_transformers_1.isArrayReply)(reply) ? reply.map((item) => (0, generic_transformers_1.transformRedisJsonNullReply)(item)) : (0, generic_transformers_1.transformRedisJsonNullReply)(reply); - } - }; - } -}); -var require_ARRTRIM = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRTRIM.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Trims an array in a JSON document to include only elements within the specified range. - * Returns the new array length after trimming, or null if the path does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the array - * @param path - Path to the array in the JSON document - * @param start - Starting index (inclusive) - * @param stop - Ending index (inclusive) - */ - parseCommand(parser3, key, path8, start, stop) { - parser3.push("JSON.ARRTRIM"); - parser3.pushKey(key); - parser3.push(path8, start.toString(), stop.toString()); - }, - transformReply: void 0 - }; - } -}); -var require_CLEAR = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/CLEAR.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Clears container values (arrays/objects) in a JSON document. - * Returns the number of values cleared (0 or 1), or null if the path does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to the container to clear - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.CLEAR"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_DEBUG_MEMORY = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/DEBUG_MEMORY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Reports memory usage details for a JSON document value. - * Returns size in bytes of the value, or null if the key or path does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to the value to examine - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.DEBUG", "MEMORY"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_DEL3 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/DEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Deletes a value from a JSON document. - * Returns the number of paths deleted (0 or 1), or null if the key does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to the value to delete - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.DEL"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_FORGET = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/FORGET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Alias for JSON.DEL - Deletes a value from a JSON document. - * Returns the number of paths deleted (0 or 1), or null if the key does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to the value to delete - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.FORGET"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_GET2 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/GET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Gets values from a JSON document. - * Returns the value at the specified path, or null if the key or path does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path(s) to the value(s) to retrieve - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.GET"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.pushVariadic(options2.path); - } - }, - transformReply: generic_transformers_1.transformRedisJsonNullReply - }; - } -}); -var require_MERGE3 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/MERGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Merges a given JSON value into a JSON document. - * Returns OK on success, or null if the key does not exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param path - Path to merge into - * @param value - JSON value to merge - */ - parseCommand(parser3, key, path8, value) { - parser3.push("JSON.MERGE"); - parser3.pushKey(key); - parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(value)); - }, - transformReply: void 0 - }; - } -}); -var require_MGET2 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/MGET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets values at a specific path from multiple JSON documents. - * Returns an array of values at the path from each key, null for missing keys/paths. - * - * @param parser - The Redis command parser - * @param keys - Array of keys containing JSON documents - * @param path - Path to retrieve from each document - */ - parseCommand(parser3, keys, path8) { - parser3.push("JSON.MGET"); - parser3.pushKeys(keys); - parser3.push(path8); - }, - transformReply(reply) { - return reply.map((json) => (0, generic_transformers_1.transformRedisJsonNullReply)(json)); - } - }; - } -}); -var require_MSET2 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/MSET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Sets multiple JSON values in multiple documents. - * Returns OK on success. - * - * @param parser - The Redis command parser - * @param items - Array of objects containing key, path, and value to set - * @param items[].key - The key containing the JSON document - * @param items[].path - Path in the document to set - * @param items[].value - JSON value to set at the path - */ - parseCommand(parser3, items) { - parser3.push("JSON.MSET"); - for (let i2 = 0; i2 < items.length; i2++) { - parser3.pushKey(items[i2].key); - parser3.push(items[i2].path, (0, generic_transformers_1.transformRedisJsonArgument)(items[i2].value)); - } - }, - transformReply: void 0 - }; - } -}); -var require_NUMINCRBY = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/NUMINCRBY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Increments a numeric value stored in a JSON document by a given number. - * Returns the value after increment, or null if the key/path doesn't exist or value is not numeric. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param path - Path to the numeric value - * @param by - Amount to increment by - */ - parseCommand(parser3, key, path8, by) { - parser3.push("JSON.NUMINCRBY"); - parser3.pushKey(key); - parser3.push(path8, by.toString()); - }, - transformReply: { - 2: (reply) => { - return JSON.parse(reply.toString()); - }, - 3: void 0 - } - }; - } -}); -var require_NUMMULTBY = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/NUMMULTBY.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var NUMINCRBY_1 = __importDefault(require_NUMINCRBY()); - exports2.default = { - IS_READ_ONLY: false, - /** - * Multiplies a numeric value stored in a JSON document by a given number. - * Returns the value after multiplication, or null if the key/path doesn't exist or value is not numeric. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param path - Path to the numeric value - * @param by - Amount to multiply by - */ - parseCommand(parser3, key, path8, by) { - parser3.push("JSON.NUMMULTBY"); - parser3.pushKey(key); - parser3.push(path8, by.toString()); - }, - transformReply: NUMINCRBY_1.default.transformReply - }; - } -}); -var require_OBJKEYS = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/OBJKEYS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Returns the keys in the object stored in a JSON document. - * Returns array of keys, array of arrays for multiple paths, or null if path doesn't exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to the object to examine - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.OBJKEYS"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_OBJLEN = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/OBJLEN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the number of keys in the object stored in a JSON document. - * Returns length of object, array of lengths for multiple paths, or null if path doesn't exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to the object to examine - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.OBJLEN"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_SET2 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/SET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Sets a JSON value at a specific path in a JSON document. - * Returns OK on success, or null if condition (NX/XX) is not met. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param path - Path in the document to set - * @param json - JSON value to set at the path - * @param options - Optional parameters - * @param options.condition - Set condition: NX (only if doesn't exist) or XX (only if exists) - * @deprecated options.NX - Use options.condition instead - * @deprecated options.XX - Use options.condition instead - */ - parseCommand(parser3, key, path8, json, options2) { - parser3.push("JSON.SET"); - parser3.pushKey(key); - parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(json)); - if (options2?.condition) { - parser3.push(options2?.condition); - } else if (options2?.NX) { - parser3.push("NX"); - } else if (options2?.XX) { - parser3.push("XX"); - } - }, - transformReply: void 0 - }; - } -}); -var require_STRAPPEND = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/STRAPPEND.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Appends a string to a string value stored in a JSON document. - * Returns new string length after append, or null if the path doesn't exist or value is not a string. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param append - String to append - * @param options - Optional parameters - * @param options.path - Path to the string value - */ - parseCommand(parser3, key, append, options2) { - parser3.push("JSON.STRAPPEND"); - parser3.pushKey(key); - if (options2?.path !== void 0) { - parser3.push(options2.path); - } - parser3.push((0, generic_transformers_1.transformRedisJsonArgument)(append)); - }, - transformReply: void 0 - }; - } -}); -var require_STRLEN2 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/STRLEN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the length of a string value stored in a JSON document. - * Returns string length, array of lengths for multiple paths, or null if path doesn't exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to the string value - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.STRLEN"); - parser3.pushKey(key); - if (options2?.path) { - parser3.push(options2.path); - } - }, - transformReply: void 0 - }; - } -}); -var require_TOGGLE = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/TOGGLE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Toggles a boolean value stored in a JSON document. - * Returns 1 if value was toggled to true, 0 if toggled to false, or null if path doesn't exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param path - Path to the boolean value - */ - parseCommand(parser3, key, path8) { - parser3.push("JSON.TOGGLE"); - parser3.pushKey(key); - parser3.push(path8); - }, - transformReply: void 0 - }; - } -}); -var require_TYPE2 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/TYPE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Returns the type of JSON value at a specific path in a JSON document. - * Returns the type as a string, array of types for multiple paths, or null if path doesn't exist. - * - * @param parser - The Redis command parser - * @param key - The key containing the JSON document - * @param options - Optional parameters - * @param options.path - Path to examine - */ - parseCommand(parser3, key, options2) { - parser3.push("JSON.TYPE"); - parser3.pushKey(key); - if (options2?.path) { - parser3.push(options2.path); - } - }, - transformReply: { - 2: void 0, - // TODO: RESP3 wraps the response in another array, but only returns 1 - 3: (reply) => { - return reply[0]; - } - } - }; - } -}); -var require_commands4 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.transformRedisJsonNullReply = exports2.transformRedisJsonReply = exports2.transformRedisJsonArgument = void 0; - var ARRAPPEND_1 = __importDefault(require_ARRAPPEND()); - var ARRINDEX_1 = __importDefault(require_ARRINDEX()); - var ARRINSERT_1 = __importDefault(require_ARRINSERT()); - var ARRLEN_1 = __importDefault(require_ARRLEN()); - var ARRPOP_1 = __importDefault(require_ARRPOP()); - var ARRTRIM_1 = __importDefault(require_ARRTRIM()); - var CLEAR_1 = __importDefault(require_CLEAR()); - var DEBUG_MEMORY_1 = __importDefault(require_DEBUG_MEMORY()); - var DEL_1 = __importDefault(require_DEL3()); - var FORGET_1 = __importDefault(require_FORGET()); - var GET_1 = __importDefault(require_GET2()); - var MERGE_1 = __importDefault(require_MERGE3()); - var MGET_1 = __importDefault(require_MGET2()); - var MSET_1 = __importDefault(require_MSET2()); - var NUMINCRBY_1 = __importDefault(require_NUMINCRBY()); - var NUMMULTBY_1 = __importDefault(require_NUMMULTBY()); - var OBJKEYS_1 = __importDefault(require_OBJKEYS()); - var OBJLEN_1 = __importDefault(require_OBJLEN()); - var SET_1 = __importDefault(require_SET2()); - var STRAPPEND_1 = __importDefault(require_STRAPPEND()); - var STRLEN_1 = __importDefault(require_STRLEN2()); - var TOGGLE_1 = __importDefault(require_TOGGLE()); - var TYPE_1 = __importDefault(require_TYPE2()); - var generic_transformers_1 = require_generic_transformers(); - Object.defineProperty(exports2, "transformRedisJsonArgument", { enumerable: true, get: function() { - return generic_transformers_1.transformRedisJsonArgument; - } }); - Object.defineProperty(exports2, "transformRedisJsonReply", { enumerable: true, get: function() { - return generic_transformers_1.transformRedisJsonReply; - } }); - Object.defineProperty(exports2, "transformRedisJsonNullReply", { enumerable: true, get: function() { - return generic_transformers_1.transformRedisJsonNullReply; - } }); - exports2.default = { - ARRAPPEND: ARRAPPEND_1.default, - arrAppend: ARRAPPEND_1.default, - ARRINDEX: ARRINDEX_1.default, - arrIndex: ARRINDEX_1.default, - ARRINSERT: ARRINSERT_1.default, - arrInsert: ARRINSERT_1.default, - ARRLEN: ARRLEN_1.default, - arrLen: ARRLEN_1.default, - ARRPOP: ARRPOP_1.default, - arrPop: ARRPOP_1.default, - ARRTRIM: ARRTRIM_1.default, - arrTrim: ARRTRIM_1.default, - CLEAR: CLEAR_1.default, - clear: CLEAR_1.default, - DEBUG_MEMORY: DEBUG_MEMORY_1.default, - debugMemory: DEBUG_MEMORY_1.default, - DEL: DEL_1.default, - del: DEL_1.default, - FORGET: FORGET_1.default, - forget: FORGET_1.default, - GET: GET_1.default, - get: GET_1.default, - MERGE: MERGE_1.default, - merge: MERGE_1.default, - MGET: MGET_1.default, - mGet: MGET_1.default, - MSET: MSET_1.default, - mSet: MSET_1.default, - NUMINCRBY: NUMINCRBY_1.default, - numIncrBy: NUMINCRBY_1.default, - /** - * @deprecated since JSON version 2.0 - */ - NUMMULTBY: NUMMULTBY_1.default, - /** - * @deprecated since JSON version 2.0 - */ - numMultBy: NUMMULTBY_1.default, - OBJKEYS: OBJKEYS_1.default, - objKeys: OBJKEYS_1.default, - OBJLEN: OBJLEN_1.default, - objLen: OBJLEN_1.default, - // RESP, - // resp: RESP, - SET: SET_1.default, - set: SET_1.default, - STRAPPEND: STRAPPEND_1.default, - strAppend: STRAPPEND_1.default, - STRLEN: STRLEN_1.default, - strLen: STRLEN_1.default, - TOGGLE: TOGGLE_1.default, - toggle: TOGGLE_1.default, - TYPE: TYPE_1.default, - type: TYPE_1.default - }; - } -}); -var require_lib5 = __commonJS({ - "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = void 0; - var commands_1 = require_commands4(); - Object.defineProperty(exports2, "default", { enumerable: true, get: function() { - return __importDefault(commands_1).default; - } }); - } -}); -var require_LIST2 = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/_LIST.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Lists all existing indexes in the database. - * @param parser - The command parser - */ - parseCommand(parser3) { - parser3.push("FT._LIST"); - }, - transformReply: { - 2: void 0, - 3: void 0 - } - }; - } -}); -var require_CREATE2 = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CREATE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.REDISEARCH_LANGUAGE = exports2.parseSchema = exports2.SCHEMA_GEO_SHAPE_COORD_SYSTEM = exports2.VAMANA_COMPRESSION_ALGORITHM = exports2.SCHEMA_VECTOR_FIELD_ALGORITHM = exports2.SCHEMA_TEXT_FIELD_PHONETIC = exports2.SCHEMA_FIELD_TYPE = void 0; - var generic_transformers_1 = require_generic_transformers(); - exports2.SCHEMA_FIELD_TYPE = { - TEXT: "TEXT", - NUMERIC: "NUMERIC", - GEO: "GEO", - TAG: "TAG", - VECTOR: "VECTOR", - GEOSHAPE: "GEOSHAPE" - }; - exports2.SCHEMA_TEXT_FIELD_PHONETIC = { - DM_EN: "dm:en", - DM_FR: "dm:fr", - FM_PT: "dm:pt", - DM_ES: "dm:es" - }; - exports2.SCHEMA_VECTOR_FIELD_ALGORITHM = { - FLAT: "FLAT", - HNSW: "HNSW", - /** - * available since 8.2 - */ - VAMANA: "SVS-VAMANA" - }; - exports2.VAMANA_COMPRESSION_ALGORITHM = { - LVQ4: "LVQ4", - LVQ8: "LVQ8", - LVQ4x4: "LVQ4x4", - LVQ4x8: "LVQ4x8", - LeanVec4x8: "LeanVec4x8", - LeanVec8x8: "LeanVec8x8" - }; - exports2.SCHEMA_GEO_SHAPE_COORD_SYSTEM = { - SPHERICAL: "SPHERICAL", - FLAT: "FLAT" - }; - function parseCommonSchemaFieldOptions(parser3, fieldOptions) { - if (fieldOptions.SORTABLE) { - parser3.push("SORTABLE"); - if (fieldOptions.SORTABLE === "UNF") { - parser3.push("UNF"); - } - } - if (fieldOptions.NOINDEX) { - parser3.push("NOINDEX"); - } - } - function parseSchema(parser3, schema) { - for (const [field, fieldOptions] of Object.entries(schema)) { - parser3.push(field); - if (typeof fieldOptions === "string") { - parser3.push(fieldOptions); - continue; - } - if (fieldOptions.AS) { - parser3.push("AS", fieldOptions.AS); - } - parser3.push(fieldOptions.type); - if (fieldOptions.INDEXMISSING) { - parser3.push("INDEXMISSING"); - } - switch (fieldOptions.type) { - case exports2.SCHEMA_FIELD_TYPE.TEXT: - if (fieldOptions.NOSTEM) { - parser3.push("NOSTEM"); - } - if (fieldOptions.WEIGHT !== void 0) { - parser3.push("WEIGHT", fieldOptions.WEIGHT.toString()); - } - if (fieldOptions.PHONETIC) { - parser3.push("PHONETIC", fieldOptions.PHONETIC); - } - if (fieldOptions.WITHSUFFIXTRIE) { - parser3.push("WITHSUFFIXTRIE"); - } - if (fieldOptions.INDEXEMPTY) { - parser3.push("INDEXEMPTY"); - } - parseCommonSchemaFieldOptions(parser3, fieldOptions); - break; - case exports2.SCHEMA_FIELD_TYPE.NUMERIC: - case exports2.SCHEMA_FIELD_TYPE.GEO: - parseCommonSchemaFieldOptions(parser3, fieldOptions); - break; - case exports2.SCHEMA_FIELD_TYPE.TAG: - if (fieldOptions.SEPARATOR) { - parser3.push("SEPARATOR", fieldOptions.SEPARATOR); - } - if (fieldOptions.CASESENSITIVE) { - parser3.push("CASESENSITIVE"); - } - if (fieldOptions.WITHSUFFIXTRIE) { - parser3.push("WITHSUFFIXTRIE"); - } - if (fieldOptions.INDEXEMPTY) { - parser3.push("INDEXEMPTY"); - } - parseCommonSchemaFieldOptions(parser3, fieldOptions); - break; - case exports2.SCHEMA_FIELD_TYPE.VECTOR: - parser3.push(fieldOptions.ALGORITHM); - const args = []; - args.push("TYPE", fieldOptions.TYPE, "DIM", fieldOptions.DIM.toString(), "DISTANCE_METRIC", fieldOptions.DISTANCE_METRIC); - if (fieldOptions.INITIAL_CAP !== void 0) { - args.push("INITIAL_CAP", fieldOptions.INITIAL_CAP.toString()); - } - switch (fieldOptions.ALGORITHM) { - case exports2.SCHEMA_VECTOR_FIELD_ALGORITHM.FLAT: - if (fieldOptions.BLOCK_SIZE !== void 0) { - args.push("BLOCK_SIZE", fieldOptions.BLOCK_SIZE.toString()); - } - break; - case exports2.SCHEMA_VECTOR_FIELD_ALGORITHM.HNSW: - if (fieldOptions.M !== void 0) { - args.push("M", fieldOptions.M.toString()); - } - if (fieldOptions.EF_CONSTRUCTION !== void 0) { - args.push("EF_CONSTRUCTION", fieldOptions.EF_CONSTRUCTION.toString()); - } - if (fieldOptions.EF_RUNTIME !== void 0) { - args.push("EF_RUNTIME", fieldOptions.EF_RUNTIME.toString()); - } - break; - case exports2.SCHEMA_VECTOR_FIELD_ALGORITHM["VAMANA"]: - if (fieldOptions.COMPRESSION) { - args.push("COMPRESSION", fieldOptions.COMPRESSION); - } - if (fieldOptions.CONSTRUCTION_WINDOW_SIZE !== void 0) { - args.push("CONSTRUCTION_WINDOW_SIZE", fieldOptions.CONSTRUCTION_WINDOW_SIZE.toString()); - } - if (fieldOptions.GRAPH_MAX_DEGREE !== void 0) { - args.push("GRAPH_MAX_DEGREE", fieldOptions.GRAPH_MAX_DEGREE.toString()); - } - if (fieldOptions.SEARCH_WINDOW_SIZE !== void 0) { - args.push("SEARCH_WINDOW_SIZE", fieldOptions.SEARCH_WINDOW_SIZE.toString()); - } - if (fieldOptions.EPSILON !== void 0) { - args.push("EPSILON", fieldOptions.EPSILON.toString()); - } - if (fieldOptions.TRAINING_THRESHOLD !== void 0) { - args.push("TRAINING_THRESHOLD", fieldOptions.TRAINING_THRESHOLD.toString()); - } - if (fieldOptions.REDUCE !== void 0) { - args.push("REDUCE", fieldOptions.REDUCE.toString()); - } - break; - } - parser3.pushVariadicWithLength(args); - break; - case exports2.SCHEMA_FIELD_TYPE.GEOSHAPE: - if (fieldOptions.COORD_SYSTEM !== void 0) { - parser3.push("COORD_SYSTEM", fieldOptions.COORD_SYSTEM); - } - break; - } - } - } - exports2.parseSchema = parseSchema; - exports2.REDISEARCH_LANGUAGE = { - ARABIC: "Arabic", - BASQUE: "Basque", - CATALANA: "Catalan", - DANISH: "Danish", - DUTCH: "Dutch", - ENGLISH: "English", - FINNISH: "Finnish", - FRENCH: "French", - GERMAN: "German", - GREEK: "Greek", - HUNGARIAN: "Hungarian", - INDONESAIN: "Indonesian", - IRISH: "Irish", - ITALIAN: "Italian", - LITHUANIAN: "Lithuanian", - NEPALI: "Nepali", - NORWEIGAN: "Norwegian", - PORTUGUESE: "Portuguese", - ROMANIAN: "Romanian", - RUSSIAN: "Russian", - SPANISH: "Spanish", - SWEDISH: "Swedish", - TAMIL: "Tamil", - TURKISH: "Turkish", - CHINESE: "Chinese" - }; - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Creates a new search index with the given schema and options. - * @param parser - The command parser - * @param index - Name of the index to create - * @param schema - Index schema defining field names and types (TEXT, NUMERIC, GEO, TAG, VECTOR, GEOSHAPE) - * @param options - Optional parameters: - * - ON: Type of container to index (HASH or JSON) - * - PREFIX: Prefixes for document keys to index - * - FILTER: Expression that filters indexed documents - * - LANGUAGE/LANGUAGE_FIELD: Default language for indexing - * - SCORE/SCORE_FIELD: Document ranking parameters - * - MAXTEXTFIELDS: Index all text fields without specifying them - * - TEMPORARY: Create a temporary index - * - NOOFFSETS/NOHL/NOFIELDS/NOFREQS: Index optimization flags - * - STOPWORDS: Custom stopword list - */ - parseCommand(parser3, index, schema, options2) { - parser3.push("FT.CREATE", index); - if (options2?.ON) { - parser3.push("ON", options2.ON); - } - (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "PREFIX", options2?.PREFIX); - if (options2?.FILTER) { - parser3.push("FILTER", options2.FILTER); - } - if (options2?.LANGUAGE) { - parser3.push("LANGUAGE", options2.LANGUAGE); - } - if (options2?.LANGUAGE_FIELD) { - parser3.push("LANGUAGE_FIELD", options2.LANGUAGE_FIELD); - } - if (options2?.SCORE) { - parser3.push("SCORE", options2.SCORE.toString()); - } - if (options2?.SCORE_FIELD) { - parser3.push("SCORE_FIELD", options2.SCORE_FIELD); - } - if (options2?.MAXTEXTFIELDS) { - parser3.push("MAXTEXTFIELDS"); - } - if (options2?.TEMPORARY) { - parser3.push("TEMPORARY", options2.TEMPORARY.toString()); - } - if (options2?.NOOFFSETS) { - parser3.push("NOOFFSETS"); - } - if (options2?.NOHL) { - parser3.push("NOHL"); - } - if (options2?.NOFIELDS) { - parser3.push("NOFIELDS"); - } - if (options2?.NOFREQS) { - parser3.push("NOFREQS"); - } - if (options2?.SKIPINITIALSCAN) { - parser3.push("SKIPINITIALSCAN"); - } - (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "STOPWORDS", options2?.STOPWORDS); - parser3.push("SCHEMA"); - parseSchema(parser3, schema); - }, - transformReply: void 0 - }; - } -}); -var require_ALTER = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALTER.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var CREATE_1 = require_CREATE2(); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Alters an existing RediSearch index schema by adding new fields. - * @param parser - The command parser - * @param index - The index to alter - * @param schema - The schema definition containing new fields to add - */ - parseCommand(parser3, index, schema) { - parser3.push("FT.ALTER", index, "SCHEMA", "ADD"); - (0, CREATE_1.parseSchema)(parser3, schema); - }, - transformReply: void 0 - }; - } -}); -var require_default = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/dialect/default.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.DEFAULT_DIALECT = void 0; - exports2.DEFAULT_DIALECT = "2"; - } -}); -var require_SEARCH = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SEARCH.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseSearchOptions = exports2.parseParamsArgument = void 0; - var generic_transformers_1 = require_generic_transformers(); - var default_1 = require_default(); - function parseParamsArgument(parser3, params) { - if (params) { - parser3.push("PARAMS"); - const args = []; - for (const key in params) { - if (!Object.hasOwn(params, key)) - continue; - const value = params[key]; - args.push(key, typeof value === "number" ? value.toString() : value); - } - parser3.pushVariadicWithLength(args); - } - } - exports2.parseParamsArgument = parseParamsArgument; - function parseSearchOptions(parser3, options2) { - if (options2?.VERBATIM) { - parser3.push("VERBATIM"); - } - if (options2?.NOSTOPWORDS) { - parser3.push("NOSTOPWORDS"); - } - (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "INKEYS", options2?.INKEYS); - (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "INFIELDS", options2?.INFIELDS); - (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "RETURN", options2?.RETURN); - if (options2?.SUMMARIZE) { - parser3.push("SUMMARIZE"); - if (typeof options2.SUMMARIZE === "object") { - (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "FIELDS", options2.SUMMARIZE.FIELDS); - if (options2.SUMMARIZE.FRAGS !== void 0) { - parser3.push("FRAGS", options2.SUMMARIZE.FRAGS.toString()); - } - if (options2.SUMMARIZE.LEN !== void 0) { - parser3.push("LEN", options2.SUMMARIZE.LEN.toString()); - } - if (options2.SUMMARIZE.SEPARATOR !== void 0) { - parser3.push("SEPARATOR", options2.SUMMARIZE.SEPARATOR); - } - } - } - if (options2?.HIGHLIGHT) { - parser3.push("HIGHLIGHT"); - if (typeof options2.HIGHLIGHT === "object") { - (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "FIELDS", options2.HIGHLIGHT.FIELDS); - if (options2.HIGHLIGHT.TAGS) { - parser3.push("TAGS", options2.HIGHLIGHT.TAGS.open, options2.HIGHLIGHT.TAGS.close); - } - } - } - if (options2?.SLOP !== void 0) { - parser3.push("SLOP", options2.SLOP.toString()); - } - if (options2?.TIMEOUT !== void 0) { - parser3.push("TIMEOUT", options2.TIMEOUT.toString()); - } - if (options2?.INORDER) { - parser3.push("INORDER"); - } - if (options2?.LANGUAGE) { - parser3.push("LANGUAGE", options2.LANGUAGE); - } - if (options2?.EXPANDER) { - parser3.push("EXPANDER", options2.EXPANDER); - } - if (options2?.SCORER) { - parser3.push("SCORER", options2.SCORER); - } - if (options2?.SORTBY) { - parser3.push("SORTBY"); - if (typeof options2.SORTBY === "string" || options2.SORTBY instanceof Buffer) { - parser3.push(options2.SORTBY); - } else { - parser3.push(options2.SORTBY.BY); - if (options2.SORTBY.DIRECTION) { - parser3.push(options2.SORTBY.DIRECTION); - } - } - } - if (options2?.LIMIT) { - parser3.push("LIMIT", options2.LIMIT.from.toString(), options2.LIMIT.size.toString()); - } - parseParamsArgument(parser3, options2?.PARAMS); - if (options2?.DIALECT) { - parser3.push("DIALECT", options2.DIALECT.toString()); - } else { - parser3.push("DIALECT", default_1.DEFAULT_DIALECT); - } - } - exports2.parseSearchOptions = parseSearchOptions; - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Searches a RediSearch index with the given query. - * @param parser - The command parser - * @param index - The index name to search - * @param query - The text query to search. For syntax, see https://redis.io/docs/stack/search/reference/query_syntax - * @param options - Optional search parameters including: - * - VERBATIM: do not try to use stemming for query expansion - * - NOSTOPWORDS: do not filter stopwords from the query - * - INKEYS/INFIELDS: restrict the search to specific keys/fields - * - RETURN: limit which fields are returned - * - SUMMARIZE/HIGHLIGHT: create search result highlights - * - LIMIT: pagination control - * - SORTBY: sort results by a specific field - * - PARAMS: bind parameters to the query - */ - parseCommand(parser3, index, query, options2) { - parser3.push("FT.SEARCH", index, query); - parseSearchOptions(parser3, options2); - }, - transformReply: { - 2: (reply) => { - const withoutDocuments = reply.length > 2 && !Array.isArray(reply[2]); - const documents = []; - let i2 = 1; - while (i2 < reply.length) { - documents.push({ - id: reply[i2++], - value: withoutDocuments ? /* @__PURE__ */ Object.create(null) : documentValue(reply[i2++]) - }); - } - return { - total: reply[0], - documents - }; - }, - 3: void 0 - }, - unstableResp3: true - }; - function documentValue(tuples) { - const message = /* @__PURE__ */ Object.create(null); - if (!tuples) { - return message; - } - let i2 = 0; - while (i2 < tuples.length) { - const key = tuples[i2++], value = tuples[i2++]; - if (key === "$") { - try { - Object.assign(message, JSON.parse(value)); - continue; - } catch { - } - } - message[key] = value; - } - return message; - } - } -}); -var require_AGGREGATE = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/AGGREGATE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseAggregateOptions = exports2.FT_AGGREGATE_GROUP_BY_REDUCERS = exports2.FT_AGGREGATE_STEPS = void 0; - var SEARCH_1 = require_SEARCH(); - var generic_transformers_1 = require_generic_transformers(); - var default_1 = require_default(); - exports2.FT_AGGREGATE_STEPS = { - GROUPBY: "GROUPBY", - SORTBY: "SORTBY", - APPLY: "APPLY", - LIMIT: "LIMIT", - FILTER: "FILTER" - }; - exports2.FT_AGGREGATE_GROUP_BY_REDUCERS = { - COUNT: "COUNT", - COUNT_DISTINCT: "COUNT_DISTINCT", - COUNT_DISTINCTISH: "COUNT_DISTINCTISH", - SUM: "SUM", - MIN: "MIN", - MAX: "MAX", - AVG: "AVG", - STDDEV: "STDDEV", - QUANTILE: "QUANTILE", - TOLIST: "TOLIST", - FIRST_VALUE: "FIRST_VALUE", - RANDOM_SAMPLE: "RANDOM_SAMPLE" - }; - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: false, - /** - * Performs an aggregation query on a RediSearch index. - * @param parser - The command parser - * @param index - The index name to query - * @param query - The text query to use as filter, use * to indicate no filtering - * @param options - Optional parameters for aggregation: - * - VERBATIM: disable stemming in query evaluation - * - LOAD: specify fields to load from documents - * - STEPS: sequence of aggregation steps (GROUPBY, SORTBY, APPLY, LIMIT, FILTER) - * - PARAMS: bind parameters for query evaluation - * - TIMEOUT: maximum time to run the query - */ - parseCommand(parser3, index, query, options2) { - parser3.push("FT.AGGREGATE", index, query); - return parseAggregateOptions(parser3, options2); - }, - transformReply: { - 2: (rawReply, preserve, typeMapping) => { - const results = []; - for (let i2 = 1; i2 < rawReply.length; i2++) { - results.push((0, generic_transformers_1.transformTuplesReply)(rawReply[i2], preserve, typeMapping)); - } - return { - // https://redis.io/docs/latest/commands/ft.aggregate/#return - // FT.AGGREGATE returns an array reply where each row is an array reply and represents a single aggregate result. - // The integer reply at position 1 does not represent a valid value. - total: Number(rawReply[0]), - results - }; - }, - 3: void 0 - }, - unstableResp3: true - }; - function parseAggregateOptions(parser3, options2) { - if (options2?.VERBATIM) { - parser3.push("VERBATIM"); - } - if (options2?.ADDSCORES) { - parser3.push("ADDSCORES"); - } - if (options2?.LOAD) { - const args = []; - if (Array.isArray(options2.LOAD)) { - for (const load of options2.LOAD) { - pushLoadField(args, load); - } - } else { - pushLoadField(args, options2.LOAD); - } - parser3.push("LOAD"); - parser3.pushVariadicWithLength(args); - } - if (options2?.TIMEOUT !== void 0) { - parser3.push("TIMEOUT", options2.TIMEOUT.toString()); - } - if (options2?.STEPS) { - for (const step of options2.STEPS) { - parser3.push(step.type); - switch (step.type) { - case exports2.FT_AGGREGATE_STEPS.GROUPBY: - if (!step.properties) { - parser3.push("0"); - } else { - parser3.pushVariadicWithLength(step.properties); - } - if (Array.isArray(step.REDUCE)) { - for (const reducer of step.REDUCE) { - parseGroupByReducer(parser3, reducer); - } - } else { - parseGroupByReducer(parser3, step.REDUCE); - } - break; - case exports2.FT_AGGREGATE_STEPS.SORTBY: - const args = []; - if (Array.isArray(step.BY)) { - for (const by of step.BY) { - pushSortByProperty(args, by); - } - } else { - pushSortByProperty(args, step.BY); - } - if (step.MAX) { - args.push("MAX", step.MAX.toString()); - } - parser3.pushVariadicWithLength(args); - break; - case exports2.FT_AGGREGATE_STEPS.APPLY: - parser3.push(step.expression, "AS", step.AS); - break; - case exports2.FT_AGGREGATE_STEPS.LIMIT: - parser3.push(step.from.toString(), step.size.toString()); - break; - case exports2.FT_AGGREGATE_STEPS.FILTER: - parser3.push(step.expression); - break; - } - } - } - (0, SEARCH_1.parseParamsArgument)(parser3, options2?.PARAMS); - if (options2?.DIALECT) { - parser3.push("DIALECT", options2.DIALECT.toString()); - } else { - parser3.push("DIALECT", default_1.DEFAULT_DIALECT); - } - } - exports2.parseAggregateOptions = parseAggregateOptions; - function pushLoadField(args, toLoad) { - if (typeof toLoad === "string" || toLoad instanceof Buffer) { - args.push(toLoad); - } else { - args.push(toLoad.identifier); - if (toLoad.AS) { - args.push("AS", toLoad.AS); - } - } - } - function parseGroupByReducer(parser3, reducer) { - parser3.push("REDUCE", reducer.type); - switch (reducer.type) { - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT: - parser3.push("0"); - break; - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCT: - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCTISH: - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.SUM: - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.MIN: - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.MAX: - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.AVG: - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.STDDEV: - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.TOLIST: - parser3.push("1", reducer.property); - break; - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.QUANTILE: - parser3.push("2", reducer.property, reducer.quantile.toString()); - break; - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.FIRST_VALUE: { - const args = [reducer.property]; - if (reducer.BY) { - args.push("BY"); - if (typeof reducer.BY === "string" || reducer.BY instanceof Buffer) { - args.push(reducer.BY); - } else { - args.push(reducer.BY.property); - if (reducer.BY.direction) { - args.push(reducer.BY.direction); - } - } - } - parser3.pushVariadicWithLength(args); - break; - } - case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.RANDOM_SAMPLE: - parser3.push("2", reducer.property, reducer.sampleSize.toString()); - break; - } - if (reducer.AS) { - parser3.push("AS", reducer.AS); - } - } - function pushSortByProperty(args, sortBy) { - if (typeof sortBy === "string" || sortBy instanceof Buffer) { - args.push(sortBy); - } else { - args.push(sortBy.BY); - if (sortBy.DIRECTION) { - args.push(sortBy.DIRECTION); - } - } - } - } -}); -var require_AGGREGATE_WITHCURSOR = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/AGGREGATE_WITHCURSOR.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var AGGREGATE_1 = __importDefault(require_AGGREGATE()); - exports2.default = { - IS_READ_ONLY: AGGREGATE_1.default.IS_READ_ONLY, - /** - * Performs an aggregation with a cursor for retrieving large result sets. - * @param parser - The command parser - * @param index - Name of the index to query - * @param query - The aggregation query - * @param options - Optional parameters: - * - All options supported by FT.AGGREGATE - * - COUNT: Number of results to return per cursor fetch - * - MAXIDLE: Maximum idle time for cursor in milliseconds - */ - parseCommand(parser3, index, query, options2) { - AGGREGATE_1.default.parseCommand(parser3, index, query, options2); - parser3.push("WITHCURSOR"); - if (options2?.COUNT !== void 0) { - parser3.push("COUNT", options2.COUNT.toString()); - } - if (options2?.MAXIDLE !== void 0) { - parser3.push("MAXIDLE", options2.MAXIDLE.toString()); - } - }, - transformReply: { - 2: (reply) => { - return { - ...AGGREGATE_1.default.transformReply[2](reply[0]), - cursor: reply[1] - }; - }, - 3: void 0 - }, - unstableResp3: true - }; - } -}); -var require_ALIASADD = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALIASADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Adds an alias to a RediSearch index. - * @param parser - The command parser - * @param alias - The alias to add - * @param index - The index name to alias - */ - parseCommand(parser3, alias, index) { - parser3.push("FT.ALIASADD", alias, index); - }, - transformReply: void 0 - }; - } -}); -var require_ALIASDEL = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALIASDEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Removes an existing alias from a RediSearch index. - * @param parser - The command parser - * @param alias - The alias to remove - */ - parseCommand(parser3, alias) { - parser3.push("FT.ALIASDEL", alias); - }, - transformReply: void 0 - }; - } -}); -var require_ALIASUPDATE = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALIASUPDATE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Updates the index pointed to by an existing alias. - * @param parser - The command parser - * @param alias - The existing alias to update - * @param index - The new index name that the alias should point to - */ - parseCommand(parser3, alias, index) { - parser3.push("FT.ALIASUPDATE", alias, index); - }, - transformReply: void 0 - }; - } -}); -var require_CONFIG_GET2 = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CONFIG_GET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Gets a RediSearch configuration option value. - * @param parser - The command parser - * @param option - The name of the configuration option to retrieve - */ - parseCommand(parser3, option) { - parser3.push("FT.CONFIG", "GET", option); - }, - transformReply(reply) { - const transformedReply = /* @__PURE__ */ Object.create(null); - for (const item of reply) { - const [key, value] = item; - transformedReply[key.toString()] = value; - } - return transformedReply; - } - }; - } -}); -var require_CONFIG_SET2 = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CONFIG_SET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Sets a RediSearch configuration option value. - * @param parser - The command parser - * @param property - The name of the configuration option to set - * @param value - The value to set for the configuration option - */ - parseCommand(parser3, property, value) { - parser3.push("FT.CONFIG", "SET", property, value); - }, - transformReply: void 0 - }; - } -}); -var require_CURSOR_DEL = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CURSOR_DEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Deletes a cursor from an index. - * @param parser - The command parser - * @param index - The index name that contains the cursor - * @param cursorId - The cursor ID to delete - */ - parseCommand(parser3, index, cursorId) { - parser3.push("FT.CURSOR", "DEL", index, cursorId.toString()); - }, - transformReply: void 0 - }; - } -}); -var require_CURSOR_READ = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CURSOR_READ.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var AGGREGATE_WITHCURSOR_1 = __importDefault(require_AGGREGATE_WITHCURSOR()); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Reads from an existing cursor to get more results from an index. - * @param parser - The command parser - * @param index - The index name that contains the cursor - * @param cursor - The cursor ID to read from - * @param options - Optional parameters: - * - COUNT: Maximum number of results to return - */ - parseCommand(parser3, index, cursor, options2) { - parser3.push("FT.CURSOR", "READ", index, cursor.toString()); - if (options2?.COUNT !== void 0) { - parser3.push("COUNT", options2.COUNT.toString()); - } - }, - transformReply: AGGREGATE_WITHCURSOR_1.default.transformReply, - unstableResp3: true - }; - } -}); -var require_DICTADD = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DICTADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Adds terms to a dictionary. - * @param parser - The command parser - * @param dictionary - Name of the dictionary to add terms to - * @param term - One or more terms to add to the dictionary - */ - parseCommand(parser3, dictionary, term) { - parser3.push("FT.DICTADD", dictionary); - parser3.pushVariadic(term); - }, - transformReply: void 0 - }; - } -}); -var require_DICTDEL = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DICTDEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Deletes terms from a dictionary. - * @param parser - The command parser - * @param dictionary - Name of the dictionary to remove terms from - * @param term - One or more terms to delete from the dictionary - */ - parseCommand(parser3, dictionary, term) { - parser3.push("FT.DICTDEL", dictionary); - parser3.pushVariadic(term); - }, - transformReply: void 0 - }; - } -}); -var require_DICTDUMP = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DICTDUMP.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Returns all terms in a dictionary. - * @param parser - The command parser - * @param dictionary - Name of the dictionary to dump - */ - parseCommand(parser3, dictionary) { - parser3.push("FT.DICTDUMP", dictionary); - }, - transformReply: { - 2: void 0, - 3: void 0 - } - }; - } -}); -var require_DROPINDEX = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DROPINDEX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Deletes an index and all associated documents. - * @param parser - The command parser - * @param index - Name of the index to delete - * @param options - Optional parameters: - * - DD: Also delete the indexed documents themselves - */ - parseCommand(parser3, index, options2) { - parser3.push("FT.DROPINDEX", index); - if (options2?.DD) { - parser3.push("DD"); - } - }, - transformReply: { - 2: void 0, - 3: void 0 - } - }; - } -}); -var require_EXPLAIN = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/EXPLAIN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var SEARCH_1 = require_SEARCH(); - var default_1 = require_default(); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Returns the execution plan for a complex query. - * @param parser - The command parser - * @param index - Name of the index to explain query against - * @param query - The query string to explain - * @param options - Optional parameters: - * - PARAMS: Named parameters to use in the query - * - DIALECT: Version of query dialect to use (defaults to 1) - */ - parseCommand(parser3, index, query, options2) { - parser3.push("FT.EXPLAIN", index, query); - (0, SEARCH_1.parseParamsArgument)(parser3, options2?.PARAMS); - if (options2?.DIALECT) { - parser3.push("DIALECT", options2.DIALECT.toString()); - } else { - parser3.push("DIALECT", default_1.DEFAULT_DIALECT); - } - }, - transformReply: void 0 - }; - } -}); -var require_EXPLAINCLI = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/EXPLAINCLI.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var default_1 = require_default(); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Returns the execution plan for a complex query in a more verbose format than FT.EXPLAIN. - * @param parser - The command parser - * @param index - Name of the index to explain query against - * @param query - The query string to explain - * @param options - Optional parameters: - * - DIALECT: Version of query dialect to use (defaults to 1) - */ - parseCommand(parser3, index, query, options2) { - parser3.push("FT.EXPLAINCLI", index, query); - if (options2?.DIALECT) { - parser3.push("DIALECT", options2.DIALECT.toString()); - } else { - parser3.push("DIALECT", default_1.DEFAULT_DIALECT); - } - }, - transformReply: void 0 - }; - } -}); -var require_INFO7 = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/INFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Returns information and statistics about an index. - * @param parser - The command parser - * @param index - Name of the index to get information about - */ - parseCommand(parser3, index) { - parser3.push("FT.INFO", index); - }, - transformReply: { - 2: transformV2Reply, - 3: void 0 - }, - unstableResp3: true - }; - function transformV2Reply(reply, preserve, typeMapping) { - const myTransformFunc = (0, generic_transformers_1.createTransformTuplesReplyFunc)(preserve, typeMapping); - const ret = {}; - for (let i2 = 0; i2 < reply.length; i2 += 2) { - const key = reply[i2].toString(); - switch (key) { - case "index_name": - case "index_options": - case "num_docs": - case "max_doc_id": - case "num_terms": - case "num_records": - case "total_inverted_index_blocks": - case "hash_indexing_failures": - case "indexing": - case "number_of_uses": - case "cleaning": - case "stopwords_list": - ret[key] = reply[i2 + 1]; - break; - case "inverted_sz_mb": - case "vector_index_sz_mb": - case "offset_vectors_sz_mb": - case "doc_table_size_mb": - case "sortable_values_size_mb": - case "key_table_size_mb": - case "text_overhead_sz_mb": - case "tag_overhead_sz_mb": - case "total_index_memory_sz_mb": - case "geoshapes_sz_mb": - case "records_per_doc_avg": - case "bytes_per_record_avg": - case "offsets_per_term_avg": - case "offset_bits_per_record_avg": - case "total_indexing_time": - case "percent_indexed": - ret[key] = generic_transformers_1.transformDoubleReply[2](reply[i2 + 1], void 0, typeMapping); - break; - case "index_definition": - ret[key] = myTransformFunc(reply[i2 + 1]); - break; - case "attributes": - ret[key] = reply[i2 + 1].map((attribute) => myTransformFunc(attribute)); - break; - case "gc_stats": { - const innerRet = {}; - const array2 = reply[i2 + 1]; - for (let i3 = 0; i3 < array2.length; i3 += 2) { - const innerKey = array2[i3].toString(); - switch (innerKey) { - case "bytes_collected": - case "total_ms_run": - case "total_cycles": - case "average_cycle_time_ms": - case "last_run_time_ms": - case "gc_numeric_trees_missed": - case "gc_blocks_denied": - innerRet[innerKey] = generic_transformers_1.transformDoubleReply[2](array2[i3 + 1], void 0, typeMapping); - break; - } - } - ret[key] = innerRet; - break; - } - case "cursor_stats": { - const innerRet = {}; - const array2 = reply[i2 + 1]; - for (let i3 = 0; i3 < array2.length; i3 += 2) { - const innerKey = array2[i3].toString(); - switch (innerKey) { - case "global_idle": - case "global_total": - case "index_capacity": - case "index_total": - innerRet[innerKey] = array2[i3 + 1]; - break; - } - } - ret[key] = innerRet; - break; - } - } - } - return ret; - } - } -}); -var require_PROFILE_SEARCH = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/PROFILE_SEARCH.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var SEARCH_1 = __importStar(require_SEARCH()); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Profiles the execution of a search query for performance analysis. - * @param parser - The command parser - * @param index - Name of the index to profile query against - * @param query - The search query to profile - * @param options - Optional parameters: - * - LIMITED: Collect limited timing information only - * - All options supported by FT.SEARCH command - */ - parseCommand(parser3, index, query, options2) { - parser3.push("FT.PROFILE", index, "SEARCH"); - if (options2?.LIMITED) { - parser3.push("LIMITED"); - } - parser3.push("QUERY", query); - (0, SEARCH_1.parseSearchOptions)(parser3, options2); - }, - transformReply: { - 2: (reply) => { - return { - results: SEARCH_1.default.transformReply[2](reply[0]), - profile: reply[1] - }; - }, - 3: (reply) => reply - }, - unstableResp3: true - }; - } -}); -var require_PROFILE_AGGREGATE = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/PROFILE_AGGREGATE.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var AGGREGATE_1 = __importStar(require_AGGREGATE()); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Profiles the execution of an aggregation query for performance analysis. - * @param parser - The command parser - * @param index - Name of the index to profile query against - * @param query - The aggregation query to profile - * @param options - Optional parameters: - * - LIMITED: Collect limited timing information only - * - All options supported by FT.AGGREGATE command - */ - parseCommand(parser3, index, query, options2) { - parser3.push("FT.PROFILE", index, "AGGREGATE"); - if (options2?.LIMITED) { - parser3.push("LIMITED"); - } - parser3.push("QUERY", query); - (0, AGGREGATE_1.parseAggregateOptions)(parser3, options2); - }, - transformReply: { - 2: (reply) => { - return { - results: AGGREGATE_1.default.transformReply[2](reply[0]), - profile: reply[1] - }; - }, - 3: (reply) => reply - }, - unstableResp3: true - }; - } -}); -var require_SEARCH_NOCONTENT = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SEARCH_NOCONTENT.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var SEARCH_1 = __importDefault(require_SEARCH()); - exports2.default = { - NOT_KEYED_COMMAND: SEARCH_1.default.NOT_KEYED_COMMAND, - IS_READ_ONLY: SEARCH_1.default.IS_READ_ONLY, - /** - * Performs a search query but returns only document ids without their contents. - * @param args - Same parameters as FT.SEARCH: - * - parser: The command parser - * - index: Name of the index to search - * - query: The text query to search - * - options: Optional search parameters - */ - parseCommand(...args) { - SEARCH_1.default.parseCommand(...args); - args[0].push("NOCONTENT"); - }, - transformReply: { - 2: (reply) => { - return { - total: reply[0], - documents: reply.slice(1) - }; - }, - 3: void 0 - }, - unstableResp3: true - }; - } -}); -var require_SPELLCHECK = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SPELLCHECK.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var default_1 = require_default(); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Performs spelling correction on a search query. - * @param parser - The command parser - * @param index - Name of the index to use for spelling corrections - * @param query - The search query to check for spelling - * @param options - Optional parameters: - * - DISTANCE: Maximum Levenshtein distance for spelling suggestions - * - TERMS: Custom dictionary terms to include/exclude - * - DIALECT: Version of query dialect to use (defaults to 1) - */ - parseCommand(parser3, index, query, options2) { - parser3.push("FT.SPELLCHECK", index, query); - if (options2?.DISTANCE) { - parser3.push("DISTANCE", options2.DISTANCE.toString()); - } - if (options2?.TERMS) { - if (Array.isArray(options2.TERMS)) { - for (const term of options2.TERMS) { - parseTerms(parser3, term); - } - } else { - parseTerms(parser3, options2.TERMS); - } - } - if (options2?.DIALECT) { - parser3.push("DIALECT", options2.DIALECT.toString()); - } else { - parser3.push("DIALECT", default_1.DEFAULT_DIALECT); - } - }, - transformReply: { - 2: (rawReply) => { - return rawReply.map(([, term, suggestions]) => ({ - term, - suggestions: suggestions.map(([score, suggestion]) => ({ - score: Number(score), - suggestion - })) - })); - }, - 3: void 0 - }, - unstableResp3: true - }; - function parseTerms(parser3, { mode, dictionary }) { - parser3.push("TERMS", mode, dictionary); - } - } -}); -var require_SUGADD = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Adds a suggestion string to an auto-complete suggestion dictionary. - * @param parser - The command parser - * @param key - The suggestion dictionary key - * @param string - The suggestion string to add - * @param score - The suggestion score used for sorting - * @param options - Optional parameters: - * - INCR: If true, increment the existing entry's score - * - PAYLOAD: Optional payload to associate with the suggestion - */ - parseCommand(parser3, key, string3, score, options2) { - parser3.push("FT.SUGADD"); - parser3.pushKey(key); - parser3.push(string3, score.toString()); - if (options2?.INCR) { - parser3.push("INCR"); - } - if (options2?.PAYLOAD) { - parser3.push("PAYLOAD", options2.PAYLOAD); - } - }, - transformReply: void 0 - }; - } -}); -var require_SUGDEL = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGDEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Deletes a string from a suggestion dictionary. - * @param parser - The command parser - * @param key - The suggestion dictionary key - * @param string - The suggestion string to delete - */ - parseCommand(parser3, key, string3) { - parser3.push("FT.SUGDEL"); - parser3.pushKey(key); - parser3.push(string3); - }, - transformReply: void 0 - }; - } -}); -var require_SUGGET = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets completion suggestions for a prefix from a suggestion dictionary. - * @param parser - The command parser - * @param key - The suggestion dictionary key - * @param prefix - The prefix to get completion suggestions for - * @param options - Optional parameters: - * - FUZZY: Enable fuzzy prefix matching - * - MAX: Maximum number of results to return - */ - parseCommand(parser3, key, prefix, options2) { - parser3.push("FT.SUGGET"); - parser3.pushKey(key); - parser3.push(prefix); - if (options2?.FUZZY) { - parser3.push("FUZZY"); - } - if (options2?.MAX !== void 0) { - parser3.push("MAX", options2.MAX.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_SUGGET_WITHPAYLOADS = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET_WITHPAYLOADS.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var SUGGET_1 = __importDefault(require_SUGGET()); - exports2.default = { - IS_READ_ONLY: SUGGET_1.default.IS_READ_ONLY, - /** - * Gets completion suggestions with their payloads from a suggestion dictionary. - * @param args - Same parameters as FT.SUGGET: - * - parser: The command parser - * - key: The suggestion dictionary key - * - prefix: The prefix to get completion suggestions for - * - options: Optional parameters for fuzzy matching and max results - */ - parseCommand(...args) { - SUGGET_1.default.parseCommand(...args); - args[0].push("WITHPAYLOADS"); - }, - transformReply(reply) { - if ((0, generic_transformers_1.isNullReply)(reply)) - return null; - const transformedReply = new Array(reply.length / 2); - let replyIndex = 0, arrIndex = 0; - while (replyIndex < reply.length) { - transformedReply[arrIndex++] = { - suggestion: reply[replyIndex++], - payload: reply[replyIndex++] - }; - } - return transformedReply; - } - }; - } -}); -var require_SUGGET_WITHSCORES_WITHPAYLOADS = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var SUGGET_1 = __importDefault(require_SUGGET()); - exports2.default = { - IS_READ_ONLY: SUGGET_1.default.IS_READ_ONLY, - /** - * Gets completion suggestions with their scores and payloads from a suggestion dictionary. - * @param args - Same parameters as FT.SUGGET: - * - parser: The command parser - * - key: The suggestion dictionary key - * - prefix: The prefix to get completion suggestions for - * - options: Optional parameters for fuzzy matching and max results - */ - parseCommand(...args) { - SUGGET_1.default.parseCommand(...args); - args[0].push("WITHSCORES", "WITHPAYLOADS"); - }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - if ((0, generic_transformers_1.isNullReply)(reply)) - return null; - const transformedReply = new Array(reply.length / 3); - let replyIndex = 0, arrIndex = 0; - while (replyIndex < reply.length) { - transformedReply[arrIndex++] = { - suggestion: reply[replyIndex++], - score: generic_transformers_1.transformDoubleReply[2](reply[replyIndex++], preserve, typeMapping), - payload: reply[replyIndex++] - }; - } - return transformedReply; - }, - 3: (reply) => { - if ((0, generic_transformers_1.isNullReply)(reply)) - return null; - const transformedReply = new Array(reply.length / 3); - let replyIndex = 0, arrIndex = 0; - while (replyIndex < reply.length) { - transformedReply[arrIndex++] = { - suggestion: reply[replyIndex++], - score: reply[replyIndex++], - payload: reply[replyIndex++] - }; - } - return transformedReply; - } - } - }; - } -}); -var require_SUGGET_WITHSCORES = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET_WITHSCORES.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - var SUGGET_1 = __importDefault(require_SUGGET()); - exports2.default = { - IS_READ_ONLY: SUGGET_1.default.IS_READ_ONLY, - /** - * Gets completion suggestions with their scores from a suggestion dictionary. - * @param args - Same parameters as FT.SUGGET: - * - parser: The command parser - * - key: The suggestion dictionary key - * - prefix: The prefix to get completion suggestions for - * - options: Optional parameters for fuzzy matching and max results - */ - parseCommand(...args) { - SUGGET_1.default.parseCommand(...args); - args[0].push("WITHSCORES"); - }, - transformReply: { - 2: (reply, preserve, typeMapping) => { - if ((0, generic_transformers_1.isNullReply)(reply)) - return null; - const transformedReply = new Array(reply.length / 2); - let replyIndex = 0, arrIndex = 0; - while (replyIndex < reply.length) { - transformedReply[arrIndex++] = { - suggestion: reply[replyIndex++], - score: generic_transformers_1.transformDoubleReply[2](reply[replyIndex++], preserve, typeMapping) - }; - } - return transformedReply; - }, - 3: (reply) => { - if ((0, generic_transformers_1.isNullReply)(reply)) - return null; - const transformedReply = new Array(reply.length / 2); - let replyIndex = 0, arrIndex = 0; - while (replyIndex < reply.length) { - transformedReply[arrIndex++] = { - suggestion: reply[replyIndex++], - score: reply[replyIndex++] - }; - } - return transformedReply; - } - } - }; - } -}); -var require_SUGLEN = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGLEN.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets the size of a suggestion dictionary. - * @param parser - The command parser - * @param key - The suggestion dictionary key - */ - parseCommand(parser3, key) { - parser3.push("FT.SUGLEN", key); - }, - transformReply: void 0 - }; - } -}); -var require_SYNDUMP = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SYNDUMP.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Dumps the contents of a synonym group. - * @param parser - The command parser - * @param index - Name of the index that contains the synonym group - */ - parseCommand(parser3, index) { - parser3.push("FT.SYNDUMP", index); - }, - transformReply: { - 2: (reply) => { - const result = {}; - let i2 = 0; - while (i2 < reply.length) { - const key = reply[i2++].toString(), value = reply[i2++]; - result[key] = value; - } - return result; - }, - 3: void 0 - } - }; - } -}); -var require_SYNUPDATE = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SYNUPDATE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Updates a synonym group with new terms. - * @param parser - The command parser - * @param index - Name of the index that contains the synonym group - * @param groupId - ID of the synonym group to update - * @param terms - One or more synonym terms to add to the group - * @param options - Optional parameters: - * - SKIPINITIALSCAN: Skip the initial scan for existing documents - */ - parseCommand(parser3, index, groupId, terms, options2) { - parser3.push("FT.SYNUPDATE", index, groupId); - if (options2?.SKIPINITIALSCAN) { - parser3.push("SKIPINITIALSCAN"); - } - parser3.pushVariadic(terms); - }, - transformReply: void 0 - }; - } -}); -var require_TAGVALS = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/TAGVALS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Returns the distinct values in a TAG field. - * @param parser - The command parser - * @param index - Name of the index - * @param fieldName - Name of the TAG field to get values from - */ - parseCommand(parser3, index, fieldName) { - parser3.push("FT.TAGVALS", index, fieldName); - }, - transformReply: { - 2: void 0, - 3: void 0 - } - }; - } -}); -var require_commands5 = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var _LIST_1 = __importDefault(require_LIST2()); - var ALTER_1 = __importDefault(require_ALTER()); - var AGGREGATE_WITHCURSOR_1 = __importDefault(require_AGGREGATE_WITHCURSOR()); - var AGGREGATE_1 = __importDefault(require_AGGREGATE()); - var ALIASADD_1 = __importDefault(require_ALIASADD()); - var ALIASDEL_1 = __importDefault(require_ALIASDEL()); - var ALIASUPDATE_1 = __importDefault(require_ALIASUPDATE()); - var CONFIG_GET_1 = __importDefault(require_CONFIG_GET2()); - var CONFIG_SET_1 = __importDefault(require_CONFIG_SET2()); - var CREATE_1 = __importDefault(require_CREATE2()); - var CURSOR_DEL_1 = __importDefault(require_CURSOR_DEL()); - var CURSOR_READ_1 = __importDefault(require_CURSOR_READ()); - var DICTADD_1 = __importDefault(require_DICTADD()); - var DICTDEL_1 = __importDefault(require_DICTDEL()); - var DICTDUMP_1 = __importDefault(require_DICTDUMP()); - var DROPINDEX_1 = __importDefault(require_DROPINDEX()); - var EXPLAIN_1 = __importDefault(require_EXPLAIN()); - var EXPLAINCLI_1 = __importDefault(require_EXPLAINCLI()); - var INFO_1 = __importDefault(require_INFO7()); - var PROFILE_SEARCH_1 = __importDefault(require_PROFILE_SEARCH()); - var PROFILE_AGGREGATE_1 = __importDefault(require_PROFILE_AGGREGATE()); - var SEARCH_NOCONTENT_1 = __importDefault(require_SEARCH_NOCONTENT()); - var SEARCH_1 = __importDefault(require_SEARCH()); - var SPELLCHECK_1 = __importDefault(require_SPELLCHECK()); - var SUGADD_1 = __importDefault(require_SUGADD()); - var SUGDEL_1 = __importDefault(require_SUGDEL()); - var SUGGET_WITHPAYLOADS_1 = __importDefault(require_SUGGET_WITHPAYLOADS()); - var SUGGET_WITHSCORES_WITHPAYLOADS_1 = __importDefault(require_SUGGET_WITHSCORES_WITHPAYLOADS()); - var SUGGET_WITHSCORES_1 = __importDefault(require_SUGGET_WITHSCORES()); - var SUGGET_1 = __importDefault(require_SUGGET()); - var SUGLEN_1 = __importDefault(require_SUGLEN()); - var SYNDUMP_1 = __importDefault(require_SYNDUMP()); - var SYNUPDATE_1 = __importDefault(require_SYNUPDATE()); - var TAGVALS_1 = __importDefault(require_TAGVALS()); - exports2.default = { - _LIST: _LIST_1.default, - _list: _LIST_1.default, - ALTER: ALTER_1.default, - alter: ALTER_1.default, - AGGREGATE_WITHCURSOR: AGGREGATE_WITHCURSOR_1.default, - aggregateWithCursor: AGGREGATE_WITHCURSOR_1.default, - AGGREGATE: AGGREGATE_1.default, - aggregate: AGGREGATE_1.default, - ALIASADD: ALIASADD_1.default, - aliasAdd: ALIASADD_1.default, - ALIASDEL: ALIASDEL_1.default, - aliasDel: ALIASDEL_1.default, - ALIASUPDATE: ALIASUPDATE_1.default, - aliasUpdate: ALIASUPDATE_1.default, - /** - * @deprecated Redis >=8 uses the standard CONFIG command - */ - CONFIG_GET: CONFIG_GET_1.default, - /** - * @deprecated Redis >=8 uses the standard CONFIG command - */ - configGet: CONFIG_GET_1.default, - /** - * @deprecated Redis >=8 uses the standard CONFIG command - */ - CONFIG_SET: CONFIG_SET_1.default, - /** - * @deprecated Redis >=8 uses the standard CONFIG command - */ - configSet: CONFIG_SET_1.default, - CREATE: CREATE_1.default, - create: CREATE_1.default, - CURSOR_DEL: CURSOR_DEL_1.default, - cursorDel: CURSOR_DEL_1.default, - CURSOR_READ: CURSOR_READ_1.default, - cursorRead: CURSOR_READ_1.default, - DICTADD: DICTADD_1.default, - dictAdd: DICTADD_1.default, - DICTDEL: DICTDEL_1.default, - dictDel: DICTDEL_1.default, - DICTDUMP: DICTDUMP_1.default, - dictDump: DICTDUMP_1.default, - DROPINDEX: DROPINDEX_1.default, - dropIndex: DROPINDEX_1.default, - EXPLAIN: EXPLAIN_1.default, - explain: EXPLAIN_1.default, - EXPLAINCLI: EXPLAINCLI_1.default, - explainCli: EXPLAINCLI_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - PROFILESEARCH: PROFILE_SEARCH_1.default, - profileSearch: PROFILE_SEARCH_1.default, - PROFILEAGGREGATE: PROFILE_AGGREGATE_1.default, - profileAggregate: PROFILE_AGGREGATE_1.default, - SEARCH_NOCONTENT: SEARCH_NOCONTENT_1.default, - searchNoContent: SEARCH_NOCONTENT_1.default, - SEARCH: SEARCH_1.default, - search: SEARCH_1.default, - SPELLCHECK: SPELLCHECK_1.default, - spellCheck: SPELLCHECK_1.default, - SUGADD: SUGADD_1.default, - sugAdd: SUGADD_1.default, - SUGDEL: SUGDEL_1.default, - sugDel: SUGDEL_1.default, - SUGGET_WITHPAYLOADS: SUGGET_WITHPAYLOADS_1.default, - sugGetWithPayloads: SUGGET_WITHPAYLOADS_1.default, - SUGGET_WITHSCORES_WITHPAYLOADS: SUGGET_WITHSCORES_WITHPAYLOADS_1.default, - sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS_1.default, - SUGGET_WITHSCORES: SUGGET_WITHSCORES_1.default, - sugGetWithScores: SUGGET_WITHSCORES_1.default, - SUGGET: SUGGET_1.default, - sugGet: SUGGET_1.default, - SUGLEN: SUGLEN_1.default, - sugLen: SUGLEN_1.default, - SYNDUMP: SYNDUMP_1.default, - synDump: SYNDUMP_1.default, - SYNUPDATE: SYNUPDATE_1.default, - synUpdate: SYNUPDATE_1.default, - TAGVALS: TAGVALS_1.default, - tagVals: TAGVALS_1.default - }; - } -}); -var require_lib6 = __commonJS({ - "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.FT_AGGREGATE_STEPS = exports2.FT_AGGREGATE_GROUP_BY_REDUCERS = exports2.SCHEMA_VECTOR_FIELD_ALGORITHM = exports2.SCHEMA_TEXT_FIELD_PHONETIC = exports2.SCHEMA_FIELD_TYPE = exports2.REDISEARCH_LANGUAGE = exports2.default = void 0; - var commands_1 = require_commands5(); - Object.defineProperty(exports2, "default", { enumerable: true, get: function() { - return __importDefault(commands_1).default; - } }); - var CREATE_1 = require_CREATE2(); - Object.defineProperty(exports2, "REDISEARCH_LANGUAGE", { enumerable: true, get: function() { - return CREATE_1.REDISEARCH_LANGUAGE; - } }); - Object.defineProperty(exports2, "SCHEMA_FIELD_TYPE", { enumerable: true, get: function() { - return CREATE_1.SCHEMA_FIELD_TYPE; - } }); - Object.defineProperty(exports2, "SCHEMA_TEXT_FIELD_PHONETIC", { enumerable: true, get: function() { - return CREATE_1.SCHEMA_TEXT_FIELD_PHONETIC; - } }); - Object.defineProperty(exports2, "SCHEMA_VECTOR_FIELD_ALGORITHM", { enumerable: true, get: function() { - return CREATE_1.SCHEMA_VECTOR_FIELD_ALGORITHM; - } }); - var AGGREGATE_1 = require_AGGREGATE(); - Object.defineProperty(exports2, "FT_AGGREGATE_GROUP_BY_REDUCERS", { enumerable: true, get: function() { - return AGGREGATE_1.FT_AGGREGATE_GROUP_BY_REDUCERS; - } }); - Object.defineProperty(exports2, "FT_AGGREGATE_STEPS", { enumerable: true, get: function() { - return AGGREGATE_1.FT_AGGREGATE_STEPS; - } }); - } -}); -var require_helpers2 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/helpers.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.transformRESP2LabelsWithSources = exports2.transformRESP2Labels = exports2.parseSelectedLabelsArguments = exports2.resp3MapToValue = exports2.resp2MapToValue = exports2.transformSamplesReply = exports2.transformSampleReply = exports2.parseLabelsArgument = exports2.transformTimestampArgument = exports2.parseDuplicatePolicy = exports2.TIME_SERIES_DUPLICATE_POLICIES = exports2.parseChunkSizeArgument = exports2.parseEncodingArgument = exports2.TIME_SERIES_ENCODING = exports2.parseRetentionArgument = exports2.parseIgnoreArgument = void 0; - var client_1 = require_dist(); - function parseIgnoreArgument(parser3, ignore) { - if (ignore !== void 0) { - parser3.push("IGNORE", ignore.maxTimeDiff.toString(), ignore.maxValDiff.toString()); - } - } - exports2.parseIgnoreArgument = parseIgnoreArgument; - function parseRetentionArgument(parser3, retention) { - if (retention !== void 0) { - parser3.push("RETENTION", retention.toString()); - } - } - exports2.parseRetentionArgument = parseRetentionArgument; - exports2.TIME_SERIES_ENCODING = { - COMPRESSED: "COMPRESSED", - UNCOMPRESSED: "UNCOMPRESSED" - }; - function parseEncodingArgument(parser3, encoding) { - if (encoding !== void 0) { - parser3.push("ENCODING", encoding); - } - } - exports2.parseEncodingArgument = parseEncodingArgument; - function parseChunkSizeArgument(parser3, chunkSize) { - if (chunkSize !== void 0) { - parser3.push("CHUNK_SIZE", chunkSize.toString()); - } - } - exports2.parseChunkSizeArgument = parseChunkSizeArgument; - exports2.TIME_SERIES_DUPLICATE_POLICIES = { - BLOCK: "BLOCK", - FIRST: "FIRST", - LAST: "LAST", - MIN: "MIN", - MAX: "MAX", - SUM: "SUM" - }; - function parseDuplicatePolicy(parser3, duplicatePolicy) { - if (duplicatePolicy !== void 0) { - parser3.push("DUPLICATE_POLICY", duplicatePolicy); - } - } - exports2.parseDuplicatePolicy = parseDuplicatePolicy; - function transformTimestampArgument(timestamp) { - if (typeof timestamp === "string") - return timestamp; - return (typeof timestamp === "number" ? timestamp : timestamp.getTime()).toString(); - } - exports2.transformTimestampArgument = transformTimestampArgument; - function parseLabelsArgument(parser3, labels) { - if (labels) { - parser3.push("LABELS"); - for (const [label, value] of Object.entries(labels)) { - parser3.push(label, value); - } - } - } - exports2.parseLabelsArgument = parseLabelsArgument; - exports2.transformSampleReply = { - 2(reply) { - const [timestamp, value] = reply; - return { - timestamp, - value: Number(value) - // TODO: use double type mapping instead - }; - }, - 3(reply) { - const [timestamp, value] = reply; - return { - timestamp, - value - }; - } - }; - exports2.transformSamplesReply = { - 2(reply) { - return reply.map((sample) => exports2.transformSampleReply[2](sample)); - }, - 3(reply) { - return reply.map((sample) => exports2.transformSampleReply[3](sample)); - } - }; - function resp2MapToValue(wrappedReply, parseFunc, typeMapping) { - const reply = wrappedReply; - switch (typeMapping?.[client_1.RESP_TYPES.MAP]) { - case Map: { - const ret = /* @__PURE__ */ new Map(); - for (const wrappedTuple of reply) { - const tuple = wrappedTuple; - const key = tuple[0]; - ret.set(key.toString(), parseFunc(tuple)); - } - return ret; - } - case Array: { - for (const wrappedTuple of reply) { - const tuple = wrappedTuple; - tuple[1] = parseFunc(tuple); - } - return reply; - } - default: { - const ret = /* @__PURE__ */ Object.create(null); - for (const wrappedTuple of reply) { - const tuple = wrappedTuple; - const key = tuple[0]; - ret[key.toString()] = parseFunc(tuple); - } - return ret; - } - } - } - exports2.resp2MapToValue = resp2MapToValue; - function resp3MapToValue(wrappedReply, parseFunc) { - const reply = wrappedReply; - if (reply instanceof Array) { - for (let i2 = 1; i2 < reply.length; i2 += 2) { - reply[i2] = parseFunc(reply[i2]); - } - } else if (reply instanceof Map) { - for (const [key, value] of reply.entries()) { - reply.set(key, parseFunc(value)); - } - } else { - for (const [key, value] of Object.entries(reply)) { - reply[key] = parseFunc(value); - } - } - return reply; - } - exports2.resp3MapToValue = resp3MapToValue; - function parseSelectedLabelsArguments(parser3, selectedLabels) { - parser3.push("SELECTED_LABELS"); - parser3.pushVariadic(selectedLabels); - } - exports2.parseSelectedLabelsArguments = parseSelectedLabelsArguments; - function transformRESP2Labels(labels, typeMapping) { - const unwrappedLabels = labels; - switch (typeMapping?.[client_1.RESP_TYPES.MAP]) { - case Map: - const map = /* @__PURE__ */ new Map(); - for (const tuple of unwrappedLabels) { - const [key, value] = tuple; - const unwrappedKey = key; - map.set(unwrappedKey.toString(), value); - } - return map; - case Array: - return unwrappedLabels.flat(); - case Object: - default: - const labelsObject = /* @__PURE__ */ Object.create(null); - for (const tuple of unwrappedLabels) { - const [key, value] = tuple; - const unwrappedKey = key; - labelsObject[unwrappedKey.toString()] = value; - } - return labelsObject; - } - } - exports2.transformRESP2Labels = transformRESP2Labels; - function transformRESP2LabelsWithSources(labels, typeMapping) { - const unwrappedLabels = labels; - const to = unwrappedLabels.length - 2; - let transformedLabels; - switch (typeMapping?.[client_1.RESP_TYPES.MAP]) { - case Map: - const map = /* @__PURE__ */ new Map(); - for (let i2 = 0; i2 < to; i2++) { - const [key, value] = unwrappedLabels[i2]; - const unwrappedKey = key; - map.set(unwrappedKey.toString(), value); - } - transformedLabels = map; - break; - case Array: - transformedLabels = unwrappedLabels.slice(0, to).flat(); - break; - case Object: - default: - const labelsObject = /* @__PURE__ */ Object.create(null); - for (let i2 = 0; i2 < to; i2++) { - const [key, value] = unwrappedLabels[i2]; - const unwrappedKey = key; - labelsObject[unwrappedKey.toString()] = value; - } - transformedLabels = labelsObject; - break; - } - const sourcesTuple = unwrappedLabels[unwrappedLabels.length - 1]; - const unwrappedSourcesTuple = sourcesTuple; - const transformedSources = transformRESP2Sources(unwrappedSourcesTuple[1]); - return { - labels: transformedLabels, - sources: transformedSources - }; - } - exports2.transformRESP2LabelsWithSources = transformRESP2LabelsWithSources; - function transformRESP2Sources(sourcesRaw) { - const unwrappedSources = sourcesRaw; - if (typeof unwrappedSources === "string") { - return unwrappedSources.split(","); - } - const indexOfComma = unwrappedSources.indexOf(","); - if (indexOfComma === -1) { - return [unwrappedSources]; - } - const sourcesArray = [ - unwrappedSources.subarray(0, indexOfComma) - ]; - let previousComma = indexOfComma + 1; - while (true) { - const indexOf = unwrappedSources.indexOf(",", previousComma); - if (indexOf === -1) { - sourcesArray.push(unwrappedSources.subarray(previousComma)); - break; - } - const source = unwrappedSources.subarray(previousComma, indexOf); - sourcesArray.push(source); - previousComma = indexOf + 1; - } - return sourcesArray; - } - } -}); -var require_ADD5 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/ADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var helpers_1 = require_helpers2(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Creates or appends a sample to a time series - * @param parser - The command parser - * @param key - The key name for the time series - * @param timestamp - The timestamp of the sample - * @param value - The value of the sample - * @param options - Optional configuration parameters - */ - parseCommand(parser3, key, timestamp, value, options2) { - parser3.push("TS.ADD"); - parser3.pushKey(key); - parser3.push((0, helpers_1.transformTimestampArgument)(timestamp), value.toString()); - (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); - (0, helpers_1.parseEncodingArgument)(parser3, options2?.ENCODING); - (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); - if (options2?.ON_DUPLICATE) { - parser3.push("ON_DUPLICATE", options2.ON_DUPLICATE); - } - (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); - (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); - }, - transformReply: void 0 - }; - } -}); -var require_ALTER2 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/ALTER.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var helpers_1 = require_helpers2(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Alters the configuration of an existing time series - * @param parser - The command parser - * @param key - The key name for the time series - * @param options - Configuration parameters to alter - */ - parseCommand(parser3, key, options2) { - parser3.push("TS.ALTER"); - parser3.pushKey(key); - (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); - (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); - (0, helpers_1.parseDuplicatePolicy)(parser3, options2?.DUPLICATE_POLICY); - (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); - (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); - }, - transformReply: void 0 - }; - } -}); -var require_CREATE3 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/CREATE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var helpers_1 = require_helpers2(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Creates a new time series - * @param parser - The command parser - * @param key - The key name for the new time series - * @param options - Optional configuration parameters - */ - parseCommand(parser3, key, options2) { - parser3.push("TS.CREATE"); - parser3.pushKey(key); - (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); - (0, helpers_1.parseEncodingArgument)(parser3, options2?.ENCODING); - (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); - (0, helpers_1.parseDuplicatePolicy)(parser3, options2?.DUPLICATE_POLICY); - (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); - (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); - }, - transformReply: void 0 - }; - } -}); -var require_CREATERULE = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/CREATERULE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.TIME_SERIES_AGGREGATION_TYPE = void 0; - exports2.TIME_SERIES_AGGREGATION_TYPE = { - AVG: "AVG", - FIRST: "FIRST", - LAST: "LAST", - MIN: "MIN", - MAX: "MAX", - SUM: "SUM", - RANGE: "RANGE", - COUNT: "COUNT", - STD_P: "STD.P", - STD_S: "STD.S", - VAR_P: "VAR.P", - VAR_S: "VAR.S", - TWA: "TWA" - }; - exports2.default = { - IS_READ_ONLY: false, - /** - * Creates a compaction rule from source time series to destination time series - * @param parser - The command parser - * @param sourceKey - The source time series key - * @param destinationKey - The destination time series key - * @param aggregationType - The aggregation type to use - * @param bucketDuration - The duration of each bucket in milliseconds - * @param alignTimestamp - Optional timestamp for alignment - */ - parseCommand(parser3, sourceKey, destinationKey, aggregationType, bucketDuration, alignTimestamp) { - parser3.push("TS.CREATERULE"); - parser3.pushKeys([sourceKey, destinationKey]); - parser3.push("AGGREGATION", aggregationType, bucketDuration.toString()); - if (alignTimestamp !== void 0) { - parser3.push(alignTimestamp.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_INCRBY4 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/INCRBY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseIncrByArguments = void 0; - var helpers_1 = require_helpers2(); - function parseIncrByArguments(parser3, key, value, options2) { - parser3.pushKey(key); - parser3.push(value.toString()); - if (options2?.TIMESTAMP !== void 0 && options2?.TIMESTAMP !== null) { - parser3.push("TIMESTAMP", (0, helpers_1.transformTimestampArgument)(options2.TIMESTAMP)); - } - (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); - if (options2?.UNCOMPRESSED) { - parser3.push("UNCOMPRESSED"); - } - (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); - (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); - (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); - } - exports2.parseIncrByArguments = parseIncrByArguments; - exports2.default = { - IS_READ_ONLY: false, - /** - * Increases the value of a time series by a given amount - * @param args - Arguments passed to the {@link parseIncrByArguments} function - */ - parseCommand(...args) { - const parser3 = args[0]; - parser3.push("TS.INCRBY"); - parseIncrByArguments(...args); - }, - transformReply: void 0 - }; - } -}); -var require_DECRBY2 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/DECRBY.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var INCRBY_1 = __importStar(require_INCRBY4()); - exports2.default = { - IS_READ_ONLY: INCRBY_1.default.IS_READ_ONLY, - /** - * Decreases the value of a time series by a given amount - * @param args - Arguments passed to the parseIncrByArguments function - */ - parseCommand(...args) { - const parser3 = args[0]; - parser3.push("TS.DECRBY"); - (0, INCRBY_1.parseIncrByArguments)(...args); - }, - transformReply: INCRBY_1.default.transformReply - }; - } -}); -var require_DEL4 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/DEL.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var helpers_1 = require_helpers2(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Deletes samples between two timestamps from a time series - * @param parser - The command parser - * @param key - The key name of the time series - * @param fromTimestamp - Start timestamp to delete from - * @param toTimestamp - End timestamp to delete until - */ - parseCommand(parser3, key, fromTimestamp, toTimestamp) { - parser3.push("TS.DEL"); - parser3.pushKey(key); - parser3.push((0, helpers_1.transformTimestampArgument)(fromTimestamp), (0, helpers_1.transformTimestampArgument)(toTimestamp)); - }, - transformReply: void 0 - }; - } -}); -var require_DELETERULE = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/DELETERULE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: false, - /** - * Deletes a compaction rule between source and destination time series - * @param parser - The command parser - * @param sourceKey - The source time series key - * @param destinationKey - The destination time series key - */ - parseCommand(parser3, sourceKey, destinationKey) { - parser3.push("TS.DELETERULE"); - parser3.pushKeys([sourceKey, destinationKey]); - }, - transformReply: void 0 - }; - } -}); -var require_GET3 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/GET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets the last sample of a time series - * @param parser - The command parser - * @param key - The key name of the time series - * @param options - Optional parameters for the command - */ - parseCommand(parser3, key, options2) { - parser3.push("TS.GET"); - parser3.pushKey(key); - if (options2?.LATEST) { - parser3.push("LATEST"); - } - }, - transformReply: { - 2(reply) { - return reply.length === 0 ? null : { - timestamp: reply[0], - value: Number(reply[1]) - }; - }, - 3(reply) { - return reply.length === 0 ? null : { - timestamp: reply[0], - value: reply[1] - }; - } - } - }; - } -}); -var require_INFO8 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/INFO.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var generic_transformers_1 = require_generic_transformers(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets information about a time series - * @param parser - The command parser - * @param key - The key name of the time series - */ - parseCommand(parser3, key) { - parser3.push("TS.INFO"); - parser3.pushKey(key); - }, - transformReply: { - 2: (reply, _, typeMapping) => { - const ret = {}; - for (let i2 = 0; i2 < reply.length; i2 += 2) { - const key = reply[i2].toString(); - switch (key) { - case "totalSamples": - case "memoryUsage": - case "firstTimestamp": - case "lastTimestamp": - case "retentionTime": - case "chunkCount": - case "chunkSize": - case "chunkType": - case "duplicatePolicy": - case "sourceKey": - case "ignoreMaxTimeDiff": - ret[key] = reply[i2 + 1]; - break; - case "labels": - ret[key] = reply[i2 + 1].map(([name, value]) => ({ - name, - value - })); - break; - case "rules": - ret[key] = reply[i2 + 1].map(([key2, timeBucket, aggregationType]) => ({ - key: key2, - timeBucket, - aggregationType - })); - break; - case "ignoreMaxValDiff": - ret[key] = generic_transformers_1.transformDoubleReply[2](reply[27], void 0, typeMapping); - break; - } - } - return ret; - }, - 3: void 0 - }, - unstableResp3: true - }; - } -}); -var require_INFO_DEBUG = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/INFO_DEBUG.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var INFO_1 = __importDefault(require_INFO8()); - exports2.default = { - IS_READ_ONLY: INFO_1.default.IS_READ_ONLY, - /** - * Gets debug information about a time series - * @param parser - The command parser - * @param key - The key name of the time series - */ - parseCommand(parser3, key) { - INFO_1.default.parseCommand(parser3, key); - parser3.push("DEBUG"); - }, - transformReply: { - 2: (reply, _, typeMapping) => { - const ret = INFO_1.default.transformReply[2](reply, _, typeMapping); - for (let i2 = 0; i2 < reply.length; i2 += 2) { - const key = reply[i2].toString(); - switch (key) { - case "keySelfName": { - ret[key] = reply[i2 + 1]; - break; - } - case "Chunks": { - ret["chunks"] = reply[i2 + 1].map((chunk) => ({ - startTimestamp: chunk[1], - endTimestamp: chunk[3], - samples: chunk[5], - size: chunk[7], - bytesPerSample: chunk[9] - })); - break; - } - } - } - return ret; - }, - 3: void 0 - }, - unstableResp3: true - }; - } -}); -var require_MADD2 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MADD.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var helpers_1 = require_helpers2(); - exports2.default = { - IS_READ_ONLY: false, - /** - * Adds multiple samples to multiple time series - * @param parser - The command parser - * @param toAdd - Array of samples to add to different time series - */ - parseCommand(parser3, toAdd) { - parser3.push("TS.MADD"); - for (const { key, timestamp, value } of toAdd) { - parser3.pushKey(key); - parser3.push((0, helpers_1.transformTimestampArgument)(timestamp), value.toString()); - } - }, - transformReply: void 0 - }; - } -}); -var require_MGET3 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MGET.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.parseFilterArgument = exports2.parseLatestArgument = void 0; - var helpers_1 = require_helpers2(); - function parseLatestArgument(parser3, latest) { - if (latest) { - parser3.push("LATEST"); - } - } - exports2.parseLatestArgument = parseLatestArgument; - function parseFilterArgument(parser3, filter) { - parser3.push("FILTER"); - parser3.pushVariadic(filter); - } - exports2.parseFilterArgument = parseFilterArgument; - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Gets the last samples matching a specific filter from multiple time series - * @param parser - The command parser - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand(parser3, filter, options2) { - parser3.push("TS.MGET"); - parseLatestArgument(parser3, options2?.LATEST); - parseFilterArgument(parser3, filter); - }, - transformReply: { - 2(reply, _, typeMapping) { - return (0, helpers_1.resp2MapToValue)(reply, ([, , sample]) => { - return { - sample: helpers_1.transformSampleReply[2](sample) - }; - }, typeMapping); - }, - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([, sample]) => { - return { - sample: helpers_1.transformSampleReply[3](sample) - }; - }); - } - } - }; - } -}); -var require_MGET_WITHLABELS = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MGET_WITHLABELS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createTransformMGetLabelsReply = void 0; - var MGET_1 = require_MGET3(); - var helpers_1 = require_helpers2(); - function createTransformMGetLabelsReply() { - return { - 2(reply, _, typeMapping) { - return (0, helpers_1.resp2MapToValue)(reply, ([, labels, sample]) => { - return { - labels: (0, helpers_1.transformRESP2Labels)(labels), - sample: helpers_1.transformSampleReply[2](sample) - }; - }, typeMapping); - }, - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([labels, sample]) => { - return { - labels, - sample: helpers_1.transformSampleReply[3](sample) - }; - }); - } - }; - } - exports2.createTransformMGetLabelsReply = createTransformMGetLabelsReply; - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets the last samples matching a specific filter with labels - * @param parser - The command parser - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand(parser3, filter, options2) { - parser3.push("TS.MGET"); - (0, MGET_1.parseLatestArgument)(parser3, options2?.LATEST); - parser3.push("WITHLABELS"); - (0, MGET_1.parseFilterArgument)(parser3, filter); - }, - transformReply: createTransformMGetLabelsReply() - }; - } -}); -var require_MGET_SELECTED_LABELS = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MGET_SELECTED_LABELS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - var MGET_1 = require_MGET3(); - var helpers_1 = require_helpers2(); - var MGET_WITHLABELS_1 = require_MGET_WITHLABELS(); - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets the last samples matching a specific filter with selected labels - * @param parser - The command parser - * @param filter - Filter to match time series keys - * @param selectedLabels - Labels to include in the output - * @param options - Optional parameters for the command - */ - parseCommand(parser3, filter, selectedLabels, options2) { - parser3.push("TS.MGET"); - (0, MGET_1.parseLatestArgument)(parser3, options2?.LATEST); - (0, helpers_1.parseSelectedLabelsArguments)(parser3, selectedLabels); - (0, MGET_1.parseFilterArgument)(parser3, filter); - }, - transformReply: (0, MGET_WITHLABELS_1.createTransformMGetLabelsReply)() - }; - } -}); -var require_RANGE = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/RANGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.transformRangeArguments = exports2.parseRangeArguments = exports2.TIME_SERIES_BUCKET_TIMESTAMP = void 0; - var helpers_1 = require_helpers2(); - exports2.TIME_SERIES_BUCKET_TIMESTAMP = { - LOW: "-", - MIDDLE: "~", - END: "+" - }; - function parseRangeArguments(parser3, fromTimestamp, toTimestamp, options2) { - parser3.push((0, helpers_1.transformTimestampArgument)(fromTimestamp), (0, helpers_1.transformTimestampArgument)(toTimestamp)); - if (options2?.LATEST) { - parser3.push("LATEST"); - } - if (options2?.FILTER_BY_TS) { - parser3.push("FILTER_BY_TS"); - for (const timestamp of options2.FILTER_BY_TS) { - parser3.push((0, helpers_1.transformTimestampArgument)(timestamp)); - } - } - if (options2?.FILTER_BY_VALUE) { - parser3.push("FILTER_BY_VALUE", options2.FILTER_BY_VALUE.min.toString(), options2.FILTER_BY_VALUE.max.toString()); - } - if (options2?.COUNT !== void 0) { - parser3.push("COUNT", options2.COUNT.toString()); - } - if (options2?.AGGREGATION) { - if (options2?.ALIGN !== void 0) { - parser3.push("ALIGN", (0, helpers_1.transformTimestampArgument)(options2.ALIGN)); - } - parser3.push("AGGREGATION", options2.AGGREGATION.type, (0, helpers_1.transformTimestampArgument)(options2.AGGREGATION.timeBucket)); - if (options2.AGGREGATION.BUCKETTIMESTAMP) { - parser3.push("BUCKETTIMESTAMP", options2.AGGREGATION.BUCKETTIMESTAMP); - } - if (options2.AGGREGATION.EMPTY) { - parser3.push("EMPTY"); - } - } - } - exports2.parseRangeArguments = parseRangeArguments; - function transformRangeArguments(parser3, key, fromTimestamp, toTimestamp, options2) { - parser3.pushKey(key); - parseRangeArguments(parser3, fromTimestamp, toTimestamp, options2); - } - exports2.transformRangeArguments = transformRangeArguments; - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets samples from a time series within a time range - * @param args - Arguments passed to the {@link transformRangeArguments} function - */ - parseCommand(...args) { - const parser3 = args[0]; - parser3.push("TS.RANGE"); - transformRangeArguments(...args); - }, - transformReply: { - 2(reply) { - return helpers_1.transformSamplesReply[2](reply); - }, - 3(reply) { - return helpers_1.transformSamplesReply[3](reply); - } - } - }; - } -}); -var require_MRANGE_GROUPBY = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_GROUPBY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.extractResp3MRangeSources = exports2.createTransformMRangeGroupByArguments = exports2.parseGroupByArguments = exports2.TIME_SERIES_REDUCERS = void 0; - var helpers_1 = require_helpers2(); - var RANGE_1 = require_RANGE(); - var MGET_1 = require_MGET3(); - exports2.TIME_SERIES_REDUCERS = { - AVG: "AVG", - SUM: "SUM", - MIN: "MIN", - MAX: "MAX", - RANGE: "RANGE", - COUNT: "COUNT", - STD_P: "STD.P", - STD_S: "STD.S", - VAR_P: "VAR.P", - VAR_S: "VAR.S" - }; - function parseGroupByArguments(parser3, groupBy) { - parser3.push("GROUPBY", groupBy.label, "REDUCE", groupBy.REDUCE); - } - exports2.parseGroupByArguments = parseGroupByArguments; - function createTransformMRangeGroupByArguments(command2) { - return (parser3, fromTimestamp, toTimestamp, filter, groupBy, options2) => { - parser3.push(command2); - (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); - (0, MGET_1.parseFilterArgument)(parser3, filter); - parseGroupByArguments(parser3, groupBy); - }; - } - exports2.createTransformMRangeGroupByArguments = createTransformMRangeGroupByArguments; - function extractResp3MRangeSources(raw) { - const unwrappedMetadata2 = raw; - if (unwrappedMetadata2 instanceof Map) { - return unwrappedMetadata2.get("sources"); - } else if (unwrappedMetadata2 instanceof Array) { - return unwrappedMetadata2[1]; - } else { - return unwrappedMetadata2.sources; - } - } - exports2.extractResp3MRangeSources = extractResp3MRangeSources; - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets samples for time series matching a filter within a time range with grouping - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param groupBy - Group by parameters - * @param options - Optional parameters for the command - */ - parseCommand: createTransformMRangeGroupByArguments("TS.MRANGE"), - transformReply: { - 2(reply, _, typeMapping) { - return (0, helpers_1.resp2MapToValue)(reply, ([_key, _labels, samples]) => { - return { - samples: helpers_1.transformSamplesReply[2](samples) - }; - }, typeMapping); - }, - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([_labels, _metadata1, metadata2, samples]) => { - return { - sources: extractResp3MRangeSources(metadata2), - samples: helpers_1.transformSamplesReply[3](samples) - }; - }); - } - } - }; - } -}); -var require_MRANGE_SELECTED_LABELS = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_SELECTED_LABELS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createTransformMRangeSelectedLabelsArguments = void 0; - var helpers_1 = require_helpers2(); - var RANGE_1 = require_RANGE(); - var MGET_1 = require_MGET3(); - function createTransformMRangeSelectedLabelsArguments(command2) { - return (parser3, fromTimestamp, toTimestamp, selectedLabels, filter, options2) => { - parser3.push(command2); - (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); - (0, helpers_1.parseSelectedLabelsArguments)(parser3, selectedLabels); - (0, MGET_1.parseFilterArgument)(parser3, filter); - }; - } - exports2.createTransformMRangeSelectedLabelsArguments = createTransformMRangeSelectedLabelsArguments; - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets samples for time series matching a filter with selected labels - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param selectedLabels - Labels to include in the output - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand: createTransformMRangeSelectedLabelsArguments("TS.MRANGE"), - transformReply: { - 2(reply, _, typeMapping) { - return (0, helpers_1.resp2MapToValue)(reply, ([_key, labels, samples]) => { - return { - labels: (0, helpers_1.transformRESP2Labels)(labels, typeMapping), - samples: helpers_1.transformSamplesReply[2](samples) - }; - }, typeMapping); - }, - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([_key, labels, samples]) => { - return { - labels, - samples: helpers_1.transformSamplesReply[3](samples) - }; - }); - } - } - }; - } -}); -var require_MRANGE_SELECTED_LABELS_GROUPBY = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_SELECTED_LABELS_GROUPBY.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createMRangeSelectedLabelsGroupByTransformArguments = void 0; - var helpers_1 = require_helpers2(); - var RANGE_1 = require_RANGE(); - var MRANGE_GROUPBY_1 = require_MRANGE_GROUPBY(); - var MGET_1 = require_MGET3(); - var MRANGE_SELECTED_LABELS_1 = __importDefault(require_MRANGE_SELECTED_LABELS()); - function createMRangeSelectedLabelsGroupByTransformArguments(command2) { - return (parser3, fromTimestamp, toTimestamp, selectedLabels, filter, groupBy, options2) => { - parser3.push(command2); - (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); - (0, helpers_1.parseSelectedLabelsArguments)(parser3, selectedLabels); - (0, MGET_1.parseFilterArgument)(parser3, filter); - (0, MRANGE_GROUPBY_1.parseGroupByArguments)(parser3, groupBy); - }; - } - exports2.createMRangeSelectedLabelsGroupByTransformArguments = createMRangeSelectedLabelsGroupByTransformArguments; - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets samples for time series matching a filter with selected labels and grouping - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param selectedLabels - Labels to include in the output - * @param filter - Filter to match time series keys - * @param groupBy - Group by parameters - * @param options - Optional parameters for the command - */ - parseCommand: createMRangeSelectedLabelsGroupByTransformArguments("TS.MRANGE"), - transformReply: { - 2: MRANGE_SELECTED_LABELS_1.default.transformReply[2], - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([labels, _metadata, metadata2, samples]) => { - return { - labels, - sources: (0, MRANGE_GROUPBY_1.extractResp3MRangeSources)(metadata2), - samples: helpers_1.transformSamplesReply[3](samples) - }; - }); - } - } - }; - } -}); -var require_MRANGE_WITHLABELS_GROUPBY = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_WITHLABELS_GROUPBY.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createMRangeWithLabelsGroupByTransformArguments = void 0; - var helpers_1 = require_helpers2(); - var RANGE_1 = require_RANGE(); - var MRANGE_GROUPBY_1 = require_MRANGE_GROUPBY(); - var MGET_1 = require_MGET3(); - function createMRangeWithLabelsGroupByTransformArguments(command2) { - return (parser3, fromTimestamp, toTimestamp, filter, groupBy, options2) => { - parser3.push(command2); - (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); - parser3.push("WITHLABELS"); - (0, MGET_1.parseFilterArgument)(parser3, filter); - (0, MRANGE_GROUPBY_1.parseGroupByArguments)(parser3, groupBy); - }; - } - exports2.createMRangeWithLabelsGroupByTransformArguments = createMRangeWithLabelsGroupByTransformArguments; - exports2.default = { - IS_READ_ONLY: true, - /** - * Gets samples for time series matching a filter with labels and grouping - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param groupBy - Group by parameters - * @param options - Optional parameters for the command - */ - parseCommand: createMRangeWithLabelsGroupByTransformArguments("TS.MRANGE"), - transformReply: { - 2(reply, _, typeMapping) { - return (0, helpers_1.resp2MapToValue)(reply, ([_key, labels, samples]) => { - const transformed = (0, helpers_1.transformRESP2LabelsWithSources)(labels); - return { - labels: transformed.labels, - sources: transformed.sources, - samples: helpers_1.transformSamplesReply[2](samples) - }; - }, typeMapping); - }, - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([labels, _metadata, metadata2, samples]) => { - return { - labels, - sources: (0, MRANGE_GROUPBY_1.extractResp3MRangeSources)(metadata2), - samples: helpers_1.transformSamplesReply[3](samples) - }; - }); - } - } - }; - } -}); -var require_MRANGE_WITHLABELS = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_WITHLABELS.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createTransformMRangeWithLabelsArguments = void 0; - var helpers_1 = require_helpers2(); - var RANGE_1 = require_RANGE(); - var MGET_1 = require_MGET3(); - function createTransformMRangeWithLabelsArguments(command2) { - return (parser3, fromTimestamp, toTimestamp, filter, options2) => { - parser3.push(command2); - (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); - parser3.push("WITHLABELS"); - (0, MGET_1.parseFilterArgument)(parser3, filter); - }; - } - exports2.createTransformMRangeWithLabelsArguments = createTransformMRangeWithLabelsArguments; - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Gets samples for time series matching a filter with labels - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand: createTransformMRangeWithLabelsArguments("TS.MRANGE"), - transformReply: { - 2(reply, _, typeMapping) { - return (0, helpers_1.resp2MapToValue)(reply, ([_key, labels, samples]) => { - const unwrappedLabels = labels; - const labelsObject = /* @__PURE__ */ Object.create(null); - for (const tuple of unwrappedLabels) { - const [key, value] = tuple; - const unwrappedKey = key; - labelsObject[unwrappedKey.toString()] = value; - } - return { - labels: labelsObject, - samples: helpers_1.transformSamplesReply[2](samples) - }; - }, typeMapping); - }, - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([labels, _metadata, samples]) => { - return { - labels, - samples: helpers_1.transformSamplesReply[3](samples) - }; - }); - } - } - }; - } -}); -var require_MRANGE = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createTransformMRangeArguments = void 0; - var helpers_1 = require_helpers2(); - var RANGE_1 = require_RANGE(); - var MGET_1 = require_MGET3(); - function createTransformMRangeArguments(command2) { - return (parser3, fromTimestamp, toTimestamp, filter, options2) => { - parser3.push(command2); - (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); - (0, MGET_1.parseFilterArgument)(parser3, filter); - }; - } - exports2.createTransformMRangeArguments = createTransformMRangeArguments; - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Gets samples for time series matching a specific filter within a time range - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand: createTransformMRangeArguments("TS.MRANGE"), - transformReply: { - 2(reply, _, typeMapping) { - return (0, helpers_1.resp2MapToValue)(reply, ([_key, _labels, samples]) => { - return helpers_1.transformSamplesReply[2](samples); - }, typeMapping); - }, - 3(reply) { - return (0, helpers_1.resp3MapToValue)(reply, ([_labels, _metadata, samples]) => { - return helpers_1.transformSamplesReply[3](samples); - }); - } - } - }; - } -}); -var require_MREVRANGE_GROUPBY = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_GROUPBY.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var MRANGE_GROUPBY_1 = __importStar(require_MRANGE_GROUPBY()); - exports2.default = { - IS_READ_ONLY: MRANGE_GROUPBY_1.default.IS_READ_ONLY, - /** - * Gets samples for time series matching a filter within a time range with grouping (in reverse order) - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param groupBy - Group by parameters - * @param options - Optional parameters for the command - */ - parseCommand: (0, MRANGE_GROUPBY_1.createTransformMRangeGroupByArguments)("TS.MREVRANGE"), - transformReply: MRANGE_GROUPBY_1.default.transformReply - }; - } -}); -var require_MREVRANGE_SELECTED_LABELS_GROUPBY = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_SELECTED_LABELS_GROUPBY.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var MRANGE_SELECTED_LABELS_GROUPBY_1 = __importStar(require_MRANGE_SELECTED_LABELS_GROUPBY()); - exports2.default = { - IS_READ_ONLY: MRANGE_SELECTED_LABELS_GROUPBY_1.default.IS_READ_ONLY, - /** - * Gets samples for time series matching a filter with selected labels and grouping (in reverse order) - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param selectedLabels - Labels to include in the output - * @param filter - Filter to match time series keys - * @param groupBy - Group by parameters - * @param options - Optional parameters for the command - */ - parseCommand: (0, MRANGE_SELECTED_LABELS_GROUPBY_1.createMRangeSelectedLabelsGroupByTransformArguments)("TS.MREVRANGE"), - transformReply: MRANGE_SELECTED_LABELS_GROUPBY_1.default.transformReply - }; - } -}); -var require_MREVRANGE_SELECTED_LABELS = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_SELECTED_LABELS.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var MRANGE_SELECTED_LABELS_1 = __importStar(require_MRANGE_SELECTED_LABELS()); - exports2.default = { - IS_READ_ONLY: MRANGE_SELECTED_LABELS_1.default.IS_READ_ONLY, - /** - * Gets samples for time series matching a filter with selected labels (in reverse order) - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param selectedLabels - Labels to include in the output - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand: (0, MRANGE_SELECTED_LABELS_1.createTransformMRangeSelectedLabelsArguments)("TS.MREVRANGE"), - transformReply: MRANGE_SELECTED_LABELS_1.default.transformReply - }; - } -}); -var require_MREVRANGE_WITHLABELS_GROUPBY = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_WITHLABELS_GROUPBY.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var MRANGE_WITHLABELS_GROUPBY_1 = __importStar(require_MRANGE_WITHLABELS_GROUPBY()); - exports2.default = { - IS_READ_ONLY: MRANGE_WITHLABELS_GROUPBY_1.default.IS_READ_ONLY, - /** - * Gets samples for time series matching a filter with labels and grouping (in reverse order) - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param groupBy - Group by parameters - * @param options - Optional parameters for the command - */ - parseCommand: (0, MRANGE_WITHLABELS_GROUPBY_1.createMRangeWithLabelsGroupByTransformArguments)("TS.MREVRANGE"), - transformReply: MRANGE_WITHLABELS_GROUPBY_1.default.transformReply - }; - } -}); -var require_MREVRANGE_WITHLABELS = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_WITHLABELS.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var MRANGE_WITHLABELS_1 = __importStar(require_MRANGE_WITHLABELS()); - exports2.default = { - NOT_KEYED_COMMAND: MRANGE_WITHLABELS_1.default.NOT_KEYED_COMMAND, - IS_READ_ONLY: MRANGE_WITHLABELS_1.default.IS_READ_ONLY, - /** - * Gets samples for time series matching a filter with labels (in reverse order) - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand: (0, MRANGE_WITHLABELS_1.createTransformMRangeWithLabelsArguments)("TS.MREVRANGE"), - transformReply: MRANGE_WITHLABELS_1.default.transformReply - }; - } -}); -var require_MREVRANGE = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var MRANGE_1 = __importStar(require_MRANGE()); - exports2.default = { - NOT_KEYED_COMMAND: MRANGE_1.default.NOT_KEYED_COMMAND, - IS_READ_ONLY: MRANGE_1.default.IS_READ_ONLY, - /** - * Gets samples for time series matching a specific filter within a time range (in reverse order) - * @param parser - The command parser - * @param fromTimestamp - Start timestamp for range - * @param toTimestamp - End timestamp for range - * @param filter - Filter to match time series keys - * @param options - Optional parameters for the command - */ - parseCommand: (0, MRANGE_1.createTransformMRangeArguments)("TS.MREVRANGE"), - transformReply: MRANGE_1.default.transformReply - }; - } -}); -var require_QUERYINDEX = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/QUERYINDEX.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.default = { - NOT_KEYED_COMMAND: true, - IS_READ_ONLY: true, - /** - * Queries the index for time series matching a specific filter - * @param parser - The command parser - * @param filter - Filter to match time series labels - */ - parseCommand(parser3, filter) { - parser3.push("TS.QUERYINDEX"); - parser3.pushVariadic(filter); - }, - transformReply: { - 2: void 0, - 3: void 0 - } - }; - } -}); -var require_REVRANGE = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/REVRANGE.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { - Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); - } : function(o2, v2) { - o2["default"] = v2; - }); - var __importStar = exports2 && exports2.__importStar || function(mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) { - for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - } - __setModuleDefault(result, mod); - return result; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var RANGE_1 = __importStar(require_RANGE()); - exports2.default = { - IS_READ_ONLY: RANGE_1.default.IS_READ_ONLY, - /** - * Gets samples from a time series within a time range (in reverse order) - * @param args - Arguments passed to the {@link transformRangeArguments} function - */ - parseCommand(...args) { - const parser3 = args[0]; - parser3.push("TS.REVRANGE"); - (0, RANGE_1.transformRangeArguments)(...args); - }, - transformReply: RANGE_1.default.transformReply - }; - } -}); -var require_commands6 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/index.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { - for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); - }; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - var ADD_1 = __importDefault(require_ADD5()); - var ALTER_1 = __importDefault(require_ALTER2()); - var CREATE_1 = __importDefault(require_CREATE3()); - var CREATERULE_1 = __importDefault(require_CREATERULE()); - var DECRBY_1 = __importDefault(require_DECRBY2()); - var DEL_1 = __importDefault(require_DEL4()); - var DELETERULE_1 = __importDefault(require_DELETERULE()); - var GET_1 = __importDefault(require_GET3()); - var INCRBY_1 = __importDefault(require_INCRBY4()); - var INFO_DEBUG_1 = __importDefault(require_INFO_DEBUG()); - var INFO_1 = __importDefault(require_INFO8()); - var MADD_1 = __importDefault(require_MADD2()); - var MGET_SELECTED_LABELS_1 = __importDefault(require_MGET_SELECTED_LABELS()); - var MGET_WITHLABELS_1 = __importDefault(require_MGET_WITHLABELS()); - var MGET_1 = __importDefault(require_MGET3()); - var MRANGE_GROUPBY_1 = __importDefault(require_MRANGE_GROUPBY()); - var MRANGE_SELECTED_LABELS_GROUPBY_1 = __importDefault(require_MRANGE_SELECTED_LABELS_GROUPBY()); - var MRANGE_SELECTED_LABELS_1 = __importDefault(require_MRANGE_SELECTED_LABELS()); - var MRANGE_WITHLABELS_GROUPBY_1 = __importDefault(require_MRANGE_WITHLABELS_GROUPBY()); - var MRANGE_WITHLABELS_1 = __importDefault(require_MRANGE_WITHLABELS()); - var MRANGE_1 = __importDefault(require_MRANGE()); - var MREVRANGE_GROUPBY_1 = __importDefault(require_MREVRANGE_GROUPBY()); - var MREVRANGE_SELECTED_LABELS_GROUPBY_1 = __importDefault(require_MREVRANGE_SELECTED_LABELS_GROUPBY()); - var MREVRANGE_SELECTED_LABELS_1 = __importDefault(require_MREVRANGE_SELECTED_LABELS()); - var MREVRANGE_WITHLABELS_GROUPBY_1 = __importDefault(require_MREVRANGE_WITHLABELS_GROUPBY()); - var MREVRANGE_WITHLABELS_1 = __importDefault(require_MREVRANGE_WITHLABELS()); - var MREVRANGE_1 = __importDefault(require_MREVRANGE()); - var QUERYINDEX_1 = __importDefault(require_QUERYINDEX()); - var RANGE_1 = __importDefault(require_RANGE()); - var REVRANGE_1 = __importDefault(require_REVRANGE()); - __exportStar(require_helpers2(), exports2); - exports2.default = { - ADD: ADD_1.default, - add: ADD_1.default, - ALTER: ALTER_1.default, - alter: ALTER_1.default, - CREATE: CREATE_1.default, - create: CREATE_1.default, - CREATERULE: CREATERULE_1.default, - createRule: CREATERULE_1.default, - DECRBY: DECRBY_1.default, - decrBy: DECRBY_1.default, - DEL: DEL_1.default, - del: DEL_1.default, - DELETERULE: DELETERULE_1.default, - deleteRule: DELETERULE_1.default, - GET: GET_1.default, - get: GET_1.default, - INCRBY: INCRBY_1.default, - incrBy: INCRBY_1.default, - INFO_DEBUG: INFO_DEBUG_1.default, - infoDebug: INFO_DEBUG_1.default, - INFO: INFO_1.default, - info: INFO_1.default, - MADD: MADD_1.default, - mAdd: MADD_1.default, - MGET_SELECTED_LABELS: MGET_SELECTED_LABELS_1.default, - mGetSelectedLabels: MGET_SELECTED_LABELS_1.default, - MGET_WITHLABELS: MGET_WITHLABELS_1.default, - mGetWithLabels: MGET_WITHLABELS_1.default, - MGET: MGET_1.default, - mGet: MGET_1.default, - MRANGE_GROUPBY: MRANGE_GROUPBY_1.default, - mRangeGroupBy: MRANGE_GROUPBY_1.default, - MRANGE_SELECTED_LABELS_GROUPBY: MRANGE_SELECTED_LABELS_GROUPBY_1.default, - mRangeSelectedLabelsGroupBy: MRANGE_SELECTED_LABELS_GROUPBY_1.default, - MRANGE_SELECTED_LABELS: MRANGE_SELECTED_LABELS_1.default, - mRangeSelectedLabels: MRANGE_SELECTED_LABELS_1.default, - MRANGE_WITHLABELS_GROUPBY: MRANGE_WITHLABELS_GROUPBY_1.default, - mRangeWithLabelsGroupBy: MRANGE_WITHLABELS_GROUPBY_1.default, - MRANGE_WITHLABELS: MRANGE_WITHLABELS_1.default, - mRangeWithLabels: MRANGE_WITHLABELS_1.default, - MRANGE: MRANGE_1.default, - mRange: MRANGE_1.default, - MREVRANGE_GROUPBY: MREVRANGE_GROUPBY_1.default, - mRevRangeGroupBy: MREVRANGE_GROUPBY_1.default, - MREVRANGE_SELECTED_LABELS_GROUPBY: MREVRANGE_SELECTED_LABELS_GROUPBY_1.default, - mRevRangeSelectedLabelsGroupBy: MREVRANGE_SELECTED_LABELS_GROUPBY_1.default, - MREVRANGE_SELECTED_LABELS: MREVRANGE_SELECTED_LABELS_1.default, - mRevRangeSelectedLabels: MREVRANGE_SELECTED_LABELS_1.default, - MREVRANGE_WITHLABELS_GROUPBY: MREVRANGE_WITHLABELS_GROUPBY_1.default, - mRevRangeWithLabelsGroupBy: MREVRANGE_WITHLABELS_GROUPBY_1.default, - MREVRANGE_WITHLABELS: MREVRANGE_WITHLABELS_1.default, - mRevRangeWithLabels: MREVRANGE_WITHLABELS_1.default, - MREVRANGE: MREVRANGE_1.default, - mRevRange: MREVRANGE_1.default, - QUERYINDEX: QUERYINDEX_1.default, - queryIndex: QUERYINDEX_1.default, - RANGE: RANGE_1.default, - range: RANGE_1.default, - REVRANGE: REVRANGE_1.default, - revRange: REVRANGE_1.default - }; - } -}); -var require_lib7 = __commonJS({ - "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/index.js"(exports2) { - "use strict"; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.TIME_SERIES_REDUCERS = exports2.TIME_SERIES_BUCKET_TIMESTAMP = exports2.TIME_SERIES_AGGREGATION_TYPE = exports2.TIME_SERIES_DUPLICATE_POLICIES = exports2.TIME_SERIES_ENCODING = exports2.default = void 0; - var commands_1 = require_commands6(); - Object.defineProperty(exports2, "default", { enumerable: true, get: function() { - return __importDefault(commands_1).default; - } }); - Object.defineProperty(exports2, "TIME_SERIES_ENCODING", { enumerable: true, get: function() { - return commands_1.TIME_SERIES_ENCODING; - } }); - Object.defineProperty(exports2, "TIME_SERIES_DUPLICATE_POLICIES", { enumerable: true, get: function() { - return commands_1.TIME_SERIES_DUPLICATE_POLICIES; - } }); - var CREATERULE_1 = require_CREATERULE(); - Object.defineProperty(exports2, "TIME_SERIES_AGGREGATION_TYPE", { enumerable: true, get: function() { - return CREATERULE_1.TIME_SERIES_AGGREGATION_TYPE; - } }); - var RANGE_1 = require_RANGE(); - Object.defineProperty(exports2, "TIME_SERIES_BUCKET_TIMESTAMP", { enumerable: true, get: function() { - return RANGE_1.TIME_SERIES_BUCKET_TIMESTAMP; - } }); - var MRANGE_GROUPBY_1 = require_MRANGE_GROUPBY(); - Object.defineProperty(exports2, "TIME_SERIES_REDUCERS", { enumerable: true, get: function() { - return MRANGE_GROUPBY_1.TIME_SERIES_REDUCERS; - } }); - } -}); -var require_dist2 = __commonJS({ - "node_modules/.deno/redis@5.9.0/node_modules/redis/dist/index.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { - for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); - }; - var __importDefault = exports2 && exports2.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.createSentinel = exports2.createCluster = exports2.createClientPool = exports2.createClient = void 0; - var client_1 = require_dist(); - var bloom_1 = __importDefault(require_lib4()); - var json_1 = __importDefault(require_lib5()); - var search_1 = __importDefault(require_lib6()); - var time_series_1 = __importDefault(require_lib7()); - __exportStar(require_dist(), exports2); - __exportStar(require_lib4(), exports2); - __exportStar(require_lib5(), exports2); - __exportStar(require_lib6(), exports2); - __exportStar(require_lib7(), exports2); - var modules = { - ...bloom_1.default, - json: json_1.default, - ft: search_1.default, - ts: time_series_1.default - }; - function createClient3(options2) { - return (0, client_1.createClient)({ - ...options2, - modules: { - ...modules, - ...options2?.modules - } - }); - } - exports2.createClient = createClient3; - function createClientPool(clientOptions, options2) { - return (0, client_1.createClientPool)({ - ...clientOptions, - modules: { - ...modules, - ...clientOptions?.modules - } - }, options2); - } - exports2.createClientPool = createClientPool; - function createCluster(options2) { - return (0, client_1.createCluster)({ - ...options2, - modules: { - ...modules, - ...options2?.modules - } - }); - } - exports2.createCluster = createCluster; - function createSentinel(options2) { - return (0, client_1.createSentinel)({ - ...options2, - modules: { - ...modules, - ...options2?.modules - } - }); - } - exports2.createSentinel = createSentinel; - } -}); -var database_redis_exports = {}; -__export(database_redis_exports, { - default: () => RedisBackend -}); -var import_npm_redis; -var ConfigSchema2; -var RedisBackend; -var init_database_redis = __esm({ - "src/serve/database-redis.ts"() { - "use strict"; - import_npm_redis = __toESM(require_dist2()); - init_zod(); - init_DatabaseBackend(); - ConfigSchema2 = strictObject({ - url: optional(url({ protocol: /^rediss?$/ })) - }); - RedisBackend = class extends DatabaseBackend { - db = null; - url; - constructor(options2 = {}) { - super(); - ConfigSchema2.parse(options2); - this.url = options2.url; - } - async init() { - const db2 = (0, import_npm_redis.createClient)({ - RESP: 3, - url: this.url - }).withTypeMapping({ - [import_npm_redis.RESP_TYPES.BLOB_STRING]: Buffer10 - }); - await db2.connect(); - this.db = db2; - } - // Useful in test hooks. - async clear() { - await this.db.flushAll(); - } - async readData(key) { - return await this.db.get(key) ?? void 0; - } - async writeData(key, value) { - await this.db.set(key, value); - } - async deleteData(key) { - await this.db.del(key); - } - close() { - this.db.destroy(); - } - async *iterKeys() { - const iterator = this.db.withTypeMapping({}).scanIterator({ MATCH: "*" }); - for await (const keys of iterator) { - yield* keys; - } - } - keyCount() { - return this.db.dbSize(); - } - }; - } -}); -var database_sqlite_exports = {}; -__export(database_sqlite_exports, { - default: () => SqliteBackend -}); -var ConfigSchema3; -var SqliteBackend; -var init_database_sqlite = __esm({ - "src/serve/database-sqlite.ts"() { - "use strict"; - init_zod(); - init_DatabaseBackend(); - ConfigSchema3 = strictObject({ - filepath: optional(string2()) - }); - SqliteBackend = class extends DatabaseBackend { - dataFolder = "data"; - db = null; - filename = "chelonia.db"; - readStatement = null; - writeStatement = null; - deleteStatement = null; - iterKeysStatement = null; - keyCountStatement = null; - constructor(options2 = {}) { - super(); - ConfigSchema3.parse(options2); - const { filepath } = options2; - if (!filepath) return; - const resolvedPath = resolve22(filepath); - this.dataFolder = dirname22(resolvedPath); - this.filename = basename22(resolvedPath); - } - run(sql) { - this.db.prepare(sql).run(); - } - async init() { - const { dataFolder, filename } = this; - await mkdir2(dataFolder, { mode: 488, recursive: true }); - if (this.db) { - throw new Error(`The ${filename} SQLite database is already open.`); - } - this.db = new Database(join22(dataFolder, filename)); - this.run("CREATE TABLE IF NOT EXISTS Data(key TEXT NOT NULL PRIMARY KEY, value TEXT NOT NULL)"); - console.info(`Connected to the ${filename} SQLite database.`); - this.readStatement = this.db.prepare("SELECT CAST(value AS BLOB) value FROM Data WHERE key = ?"); - this.writeStatement = this.db.prepare("REPLACE INTO Data(key, value) VALUES(?, ?)"); - this.deleteStatement = this.db.prepare("DELETE FROM Data WHERE key = ?"); - this.iterKeysStatement = this.db.prepare("SELECT key FROM Data"); - this.keyCountStatement = this.db.prepare("SELECT COUNT(*) count FROM Data"); - } - // Useful in test hooks. - // deno-lint-ignore require-await - async clear() { - this.run("DELETE FROM Data"); - } - // deno-lint-ignore require-await - async readData(key) { - const row = this.readStatement.get(key); - const value = row?.value; - if (ArrayBuffer.isView(value) && !Buffer11.isBuffer(value)) { - return Buffer11.from(value); - } else { - return value; - } - } - async writeData(key, value) { - await this.writeStatement.run(key, value); - } - async deleteData(key) { - await this.deleteStatement.run(key); - } - close() { - this.db.close(); - } - async *iterKeys() { - for (const row of this.iterKeysStatement.iter()) { - yield row.key; - } - } - async keyCount() { - const result = await this.keyCountStatement.get(); - return result?.count ?? 0; - } - }; - } -}); -var globImport_database_ts; -var init_ = __esm({ - 'import("./database-*.ts") in src/serve/database-router.ts'() { - globImport_database_ts = __glob({ - "./database-fs.ts": () => Promise.resolve().then(() => (init_database_fs(), database_fs_exports)), - "./database-redis.ts": () => Promise.resolve().then(() => (init_database_redis(), database_redis_exports)), - "./database-router.test.ts": () => Promise.resolve().then(() => (init_database_router_test(), database_router_test_exports)), - "./database-router.ts": () => Promise.resolve().then(() => (init_database_router(), database_router_exports)), - "./database-sqlite.ts": () => Promise.resolve().then(() => (init_database_sqlite(), database_sqlite_exports)) - }); - } -}); -var database_router_exports = {}; -__export(database_router_exports, { - default: () => RouterBackend -}); -var ConfigEntrySchema; -var ConfigSchema4; -var RouterBackend; -var init_database_router = __esm({ - "src/serve/database-router.ts"() { - "use strict"; - init_zod(); - init_DatabaseBackend(); - init_(); - ConfigEntrySchema = strictObject({ - name: string2(), - options: object() - }); - ConfigSchema4 = intersection( - object({ "*": ConfigEntrySchema }), - record(string2(), ConfigEntrySchema) - ); - RouterBackend = class extends DatabaseBackend { - backends; - config; - constructor(config2 = {}) { - super(); - ConfigSchema4.parse(config2); - const configCopy = Object.fromEntries(Object.entries(config2).sort((a, b) => b[0].length - a[0].length)); - const errors = this.validateConfig(configCopy); - if (errors.length) { - throw new Error(`[${this.constructor.name}] ${errors.length} error(s) found in your config.`, { cause: errors }); - } - this.config = configCopy; - } - lookupBackend(key) { - const { backends, config: config2 } = this; - const keyPrefixes = Object.keys(config2); - for (let i2 = 0; i2 < keyPrefixes.length; i2++) { - if (key.startsWith(keyPrefixes[i2])) { - return backends[keyPrefixes[i2]]; - } - } - return backends["*"]; - } - validateConfig(config2) { - const errors = []; - if (!config2["*"]) { - errors.push({ msg: 'Missing key: "*" (fallback storage is required)' }); - } - for (const entry of Object.entries(config2)) { - const value = entry[1]; - if (typeof value?.name !== "string" || typeof value?.options !== "object") { - errors.push({ msg: "entry value must be of type { name: string, options: Object }", entry }); - continue; - } - if (value.name === "router") { - errors.push({ msg: "Router backends cannot be nested.", entry }); - continue; - } - } - return errors; - } - async init() { - this.backends = /* @__PURE__ */ Object.create(null); - const entries = Object.entries(this.config); - await Promise.all(entries.map(async (entry) => { - const [keyPrefix, { name, options: options2 }] = entry; - const Ctor = (await globImport_database_ts(`./database-${name}.ts`)).default; - const backend = new Ctor(options2); - await backend.init(); - this.backends[keyPrefix] = backend; - })); - } - async readData(key) { - return await this.lookupBackend(key).readData(key); - } - async writeData(key, value) { - return await this.lookupBackend(key).writeData(key, value); - } - async deleteData(key) { - return await this.lookupBackend(key).deleteData(key); - } - async clear() { - for (const backend of new Set(Object.values(this.backends))) { - try { - await backend.clear(); - } catch (e2) { - const prefix = Object.entries(this.backends).find(([, b]) => b === backend)[0]; - console.error(e2, `Error clearing DB for prefix ${prefix}`); - } - } - } - async close() { - for (const backend of new Set(Object.values(this.backends))) { - try { - await backend.close(); - } catch (e2) { - const prefix = Object.entries(this.backends).find(([, b]) => b === backend)[0]; - console.error(e2, `Error closing DB for prefix ${prefix}`); - } - } - } - async *iterKeys() { - for (const backend of new Set(Object.values(this.backends))) { - yield* backend.iterKeys(); - } - } - async keyCount() { - let count = 0; - for (const backend of new Set(Object.values(this.backends))) { - count += await backend.keyCount(); - } - return count; - } - }; - } -}); -var database_router_test_exports = {}; -var CID2; -var randomKeyWithPrefix; -var validConfig; -var db; -var init_database_router_test = __esm({ - "src/serve/database-router.test.ts"() { - "use strict"; - init_esm5(); - init_database_router(); - CID2 = "Q"; - randomKeyWithPrefix = (prefix) => `${prefix}${globalThis.crypto.randomUUID().replaceAll("-", "")}`; - validConfig = { - [CID2]: { - name: "sqlite", - options: { - filepath: "./test/temp/sqlite.db" - } - }, - "*": { - name: "fs", - options: { - dirname: "./test/temp", - skipFsCaseSensitivityCheck: true - } - } - }; - db = new RouterBackend(validConfig); - Deno.test({ - name: "DatabaseRouter::validateConfig", - async fn(t) { - await t.step("should accept a valid config", () => { - const errors = db.validateConfig(validConfig); - if (errors.length !== 0) throw new Error(`Expected 0 errors but got ${errors.length}`); - }); - await t.step("should reject configs missing a * key", () => { - const config2 = omit2(validConfig, ["*"]); - const errors = db.validateConfig(config2); - if (errors.length !== 1) throw new Error(`Expected 1 error but got ${errors.length}`); - }); - await t.step("should reject config entries missing a name", () => { - const config2 = cloneDeep(validConfig); - delete config2["*"].name; - const errors = db.validateConfig(config2); - if (errors.length !== 1) throw new Error(`Expected 1 error but got ${errors.length}`); - }); - } - }); - Deno.test({ - name: "DatabaseRouter::lookupBackend", - async fn(t) { - await db.init(); - try { - await t.step("should find the right backend for keys starting with configured prefixes", () => { - for (const keyPrefix of Object.keys(db.config)) { - if (keyPrefix === "*") continue; - const key = randomKeyWithPrefix(keyPrefix); - const actual = db.lookupBackend(key); - const expected = db.backends[keyPrefix]; - if (actual !== expected) throw new Error(`Expected ${expected} but got ${actual}`); - } - }); - await t.step("should find the right backend for keys equal to configured prefixes", () => { - for (const keyPrefix of Object.keys(db.config)) { - const key = keyPrefix; - const actual = db.lookupBackend(key); - const expected = db.backends[keyPrefix]; - if (actual !== expected) throw new Error(`Expected ${expected} but got ${actual}`); - } - }); - await t.step("should return the fallback backend for keys not matching any configured prefix", () => { - const key = "foo"; - const actual = db.lookupBackend(key); - const expected = db.backends["*"]; - if (actual !== expected) throw new Error(`Expected ${expected} but got ${actual}`); - }); - } finally { - await db.clear(); - } - } - }); - } -}); -var globImport_database_ts2; -var init_2 = __esm({ - 'import("./database-*.ts") in src/serve/database.ts'() { - globImport_database_ts2 = __glob({ - "./database-fs.ts": () => Promise.resolve().then(() => (init_database_fs(), database_fs_exports)), - "./database-redis.ts": () => Promise.resolve().then(() => (init_database_redis(), database_redis_exports)), - "./database-router.test.ts": () => Promise.resolve().then(() => (init_database_router_test(), database_router_test_exports)), - "./database-router.ts": () => Promise.resolve().then(() => (init_database_router(), database_router_exports)), - "./database-sqlite.ts": () => Promise.resolve().then(() => (init_database_sqlite(), database_sqlite_exports)) - }); - } -}); -var import_boom; -var import_npm_lru_cache; -var import_npm_nconf2; -var production; -var database_default; -var initedDB; -var initDB; -var init_database = __esm({ - "src/serve/database.ts"() { - "use strict"; - init_chelonia(); - init_db(); - init_db(); - init_functions(); - import_boom = __toESM(require_lib2()); - init_esm(); - import_npm_lru_cache = __toESM(require_lru_cache()); - init_events2(); - init_vapid(); - init_zkppSalt(); - import_npm_nconf2 = __toESM(require_nconf()); - init_db_utils(); - init_db_utils(); - init_2(); - production = process2.env.NODE_ENV === "production"; - database_default = esm_default("sbp/selectors/register", { - "backend/db/streamEntriesAfter": async function(contractID, height, requestedLimit, options2 = {}) { - const batchMaxSize = import_npm_nconf2.default.get("server:maxEventsBatchSize") ?? 500; - const limit = Math.min(requestedLimit ?? Number.POSITIVE_INFINITY, batchMaxSize); - const latestHEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); - if (latestHEADinfo === "") { - throw import_boom.default.resourceGone(`contractID ${contractID} has been deleted!`); - } - if (!latestHEADinfo) { - throw import_boom.default.notFound(`contractID ${contractID} doesn't exist!`); - } - let counter = 0; - let currentHeight = height; - let currentHash, serverMeta; - let prefix = ""; - const nextKeyOp = /* @__PURE__ */ (() => { - let index; - return async () => { - if (!index) { - index = (await esm_default("chelonia.db/get", `_private_keyop_idx_${contractID}_${currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH}`))?.split("\0"); - } - const value = index?.find((h2, i2) => { - if (Number(h2) >= currentHeight) { - index = index.slice(i2 + 1); - return true; - } else { - return false; - } - }); - if (value != null) { - const newHeight = Number(value); - currentHeight = newHeight; - } else { - currentHeight = currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH + KEYOP_SEGMENT_LENGTH; - index = void 0; - if (currentHeight > latestHEADinfo.height) { - return false; - } else { - return null; - } - } - return true; - }; - })(); - const fetchMeta = async () => { - if (currentHeight > latestHEADinfo.height) { - return false; - } - const meta = await esm_default("chelonia/db/getEntryMeta", contractID, currentHeight); - if (!meta) { - return false; - } - const { hash: newCurrentHash, ...newServerMeta } = meta; - currentHash = newCurrentHash; - serverMeta = newServerMeta; - return true; - }; - const stream = Readable.from(async function* () { - yield "["; - await fetchMeta(); - while (serverMeta && counter < limit) { - try { - const entry = await esm_default("chelonia/db/getEntry", currentHash); - if (!entry) break; - const currentPrefix = prefix; - prefix = ","; - counter++; - yield `${currentPrefix}"${strToB64( - JSON.stringify({ serverMeta, message: entry.serialize() }) - )}"`; - currentHeight++; - currentHash = void 0; - serverMeta = void 0; - if (options2.keyOps) { - while (await nextKeyOp() === null) ; - } - await fetchMeta(); - } catch (e2) { - console.error(e2, "[backend] streamEntriesAfter: read()"); - break; - } - } - yield "]"; - }(), { encoding: "utf-8", objectMode: false }); - stream.headers = { - "shelter-headinfo-head": latestHEADinfo.HEAD, - "shelter-headinfo-height": latestHEADinfo.height - }; - return stream; - }, - // ======================= - // wrapper methods to add / lookup names - // ======================= - "backend/db/registerName": async function(name, value) { - const exists = await esm_default("backend/db/lookupName", name); - if (exists) { - throw import_boom.default.conflict("exists"); - } - await esm_default("chelonia.db/set", namespaceKey(name), value); - await esm_default("chelonia.db/set", `_private_cid2name_${value}`, name); - await appendToNamesIndex(name); - return { name, value }; - }, - "backend/db/lookupName": async function(name) { - const value = await esm_default("chelonia.db/get", namespaceKey(name)); - return value; - } - }); - initedDB = false; - initDB = async ({ skipDbPreloading } = {}) => { - if (!initedDB) { - const backend = import_npm_nconf2.default.get("database:backend"); - const persistence = backend || (production ? "fs" : void 0); - const options2 = import_npm_nconf2.default.get("database:backendOptions"); - const ARCHIVE_MODE3 = import_npm_nconf2.default.get("server:archiveMode"); - if (persistence && persistence !== "mem") { - const Ctor = (await globImport_database_ts2(`./database-${persistence}.ts`)).default; - const { init: init2, readData, writeData, deleteData, iterKeys, keyCount, close } = new Ctor(options2[persistence]); - await init2(); - esm_default("okTurtles.events/once", SERVER_EXITING, () => { - esm_default("okTurtles.eventQueue/queueEvent", SERVER_EXITING, async () => { - try { - await close(); - } catch (e2) { - console.error(e2, `Error closing DB ${persistence}`); - } - }); - }); - const cache2 = new import_npm_lru_cache.default({ - max: import_npm_nconf2.default.get("database:lruNumItems") ?? 1e4 - }); - const prefixes = Object.keys(prefixHandlers); - esm_default("sbp/selectors/overwrite", { - "chelonia.db/get": async function(prefixableKey, { bypassCache } = {}) { - if (!bypassCache) { - const lookupValue = cache2.get(prefixableKey); - if (lookupValue !== void 0) { - return lookupValue; - } - } - const [prefix, key] = parsePrefixableKey(prefixableKey); - let value = await readData(key); - if (value === void 0) { - return; - } - value = prefixHandlers[prefix](value); - cache2.set(prefixableKey, value); - return value; - }, - "chelonia.db/set": async function(key, value) { - if (ARCHIVE_MODE3) throw new Error("Unable to write in archive mode"); - checkKey(key); - if (key.startsWith("_private_immutable")) { - const existingValue = await readData(key); - if (existingValue !== void 0) { - throw new Error("Cannot set already set immutable key"); - } - } - await writeData(key, value); - prefixes.forEach((prefix) => { - cache2.delete(prefix + key); - }); - }, - "chelonia.db/delete": async function(key) { - if (ARCHIVE_MODE3) throw new Error("Unable to write in archive mode"); - checkKey(key); - if (key.startsWith("_private_immutable")) { - throw new Error("Cannot delete immutable key"); - } - await deleteData(key); - prefixes.forEach((prefix) => { - cache2.delete(prefix + key); - }); - }, - "chelonia.db/iterKeys": () => { - return iterKeys(); - }, - "chelonia.db/keyCount": () => { - return keyCount(); - } - }); - esm_default("sbp/selectors/lock", ["chelonia.db/get", "chelonia.db/set", "chelonia.db/delete", "chelonia.db/iterKeys"]); - } - initedDB = true; - } - if (skipDbPreloading || initedDB === "preloaded") return; - await Promise.all([initVapid(), initZkpp()]); - initedDB = "preloaded"; - }; - } -}); -var require_package3 = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/package.json"(exports2, module14) { - module14.exports = { - name: "@hapi/validate", - description: "Object schema validation", - version: "2.0.1", - repository: "git://github.com/hapijs/validate", - main: "lib/index.js", - files: [ - "lib/**/*" - ], - eslintConfig: { - extends: [ - "plugin:@hapi/module" - ] - }, - dependencies: { - "@hapi/hoek": "^11.0.2", - "@hapi/topo": "^6.0.1" - }, - devDependencies: { - "@hapi/bourne": "^3.0.0", - "@hapi/code": "^9.0.3", - "@hapi/eslint-plugin": "*", - "@hapi/lab": "^25.1.2" - }, - scripts: { - test: "lab -t 100 -a @hapi/code -L", - "test-cov-html": "lab -r html -o coverage.html -a @hapi/code" - }, - license: "BSD-3-Clause" - }; - } -}); -var require_schemas = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/schemas.js"(exports2) { - "use strict"; - var Joi2 = require_lib9(); - var internals = {}; - internals.wrap = Joi2.string().min(1).max(2).allow(false); - exports2.preferences = Joi2.object({ - allowUnknown: Joi2.boolean(), - abortEarly: Joi2.boolean(), - context: Joi2.object(), - convert: Joi2.boolean(), - dateFormat: Joi2.valid("date", "iso", "string", "time", "utc"), - errors: { - escapeHtml: Joi2.boolean(), - label: Joi2.valid("path", "key", false), - language: [ - Joi2.string(), - Joi2.object().ref() - ], - render: Joi2.boolean(), - stack: Joi2.boolean(), - wrap: { - label: internals.wrap, - array: internals.wrap - } - }, - messages: Joi2.object(), - noDefaults: Joi2.boolean(), - nonEnumerables: Joi2.boolean(), - presence: Joi2.valid("required", "optional", "forbidden"), - skipFunctions: Joi2.boolean(), - stripUnknown: Joi2.object({ - arrays: Joi2.boolean(), - objects: Joi2.boolean() - }).or("arrays", "objects").allow(true, false) - }).strict(); - } -}); -var require_ref = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/ref.js"(exports2) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var Reach = require_reach(); - var Common = require_common2(); - var internals = { - symbol: Symbol("ref"), - // Used to internally identify references (shared with other joi versions) - defaults: { - adjust: null, - in: false, - iterables: null, - map: null, - separator: ".", - type: "value" - } - }; - exports2.create = function(key, options2 = {}) { - Assert(typeof key === "string", "Invalid reference key:", key); - Common.assertOptions(options2, ["adjust", "ancestor", "in", "iterables", "map", "prefix", "separator"]); - Assert(!options2.prefix || typeof options2.prefix === "object", "options.prefix must be of type object"); - const ref = Object.assign({}, internals.defaults, options2); - delete ref.prefix; - const separator = ref.separator; - const context = internals.context(key, separator, options2.prefix); - ref.type = context.type; - key = context.key; - if (ref.type === "value") { - if (context.root) { - Assert(!separator || key[0] !== separator, "Cannot specify relative path with root prefix"); - ref.ancestor = "root"; - if (!key) { - key = null; - } - } - if (separator && separator === key) { - key = null; - ref.ancestor = 0; - } else { - if (ref.ancestor !== void 0) { - Assert(!separator || !key || key[0] !== separator, "Cannot combine prefix with ancestor option"); - } else { - const [ancestor, slice] = internals.ancestor(key, separator); - if (slice) { - key = key.slice(slice); - if (key === "") { - key = null; - } - } - ref.ancestor = ancestor; - } - } - } - ref.path = separator ? key === null ? [] : key.split(separator) : [key]; - return new internals.Ref(ref); - }; - exports2.in = function(key, options2 = {}) { - return exports2.create(key, Object.assign({}, options2, { in: true })); - }; - exports2.isRef = function(ref) { - return ref ? !!ref[Common.symbols.ref] : false; - }; - internals.Ref = class { - constructor(options2) { - Assert(typeof options2 === "object", "Invalid reference construction"); - Common.assertOptions(options2, [ - "adjust", - "ancestor", - "in", - "iterables", - "map", - "path", - "separator", - "type", - // Copied - "depth", - "key", - "root", - "display" - // Overridden - ]); - Assert([false, void 0].includes(options2.separator) || typeof options2.separator === "string" && options2.separator.length === 1, "Invalid separator"); - Assert(!options2.adjust || typeof options2.adjust === "function", "options.adjust must be a function"); - Assert(!options2.map || Array.isArray(options2.map), "options.map must be an array"); - Assert(!options2.map || !options2.adjust, "Cannot set both map and adjust options"); - Object.assign(this, internals.defaults, options2); - Assert(this.type === "value" || this.ancestor === void 0, "Non-value references cannot reference ancestors"); - if (Array.isArray(this.map)) { - this.map = new Map(this.map); - } - this.depth = this.path.length; - this.key = this.path.length ? this.path.join(this.separator) : null; - this.root = this.path[0]; - this.updateDisplay(); - } - resolve(value, state, prefs, local, options2 = {}) { - Assert(!this.in || options2.in, "Invalid in() reference usage"); - if (this.type === "global") { - return this._resolve(prefs.context, state, options2); - } - if (this.type === "local") { - return this._resolve(local, state, options2); - } - if (!this.ancestor) { - return this._resolve(value, state, options2); - } - if (this.ancestor === "root") { - return this._resolve(state.ancestors[state.ancestors.length - 1], state, options2); - } - Assert(this.ancestor <= state.ancestors.length, "Invalid reference exceeds the schema root:", this.display); - return this._resolve(state.ancestors[this.ancestor - 1], state, options2); - } - _resolve(target, state, options2) { - let resolved; - if (this.type === "value" && state.mainstay.shadow && options2.shadow !== false) { - resolved = state.mainstay.shadow.get(this.absolute(state)); - } - if (resolved === void 0) { - resolved = Reach(target, this.path, { iterables: this.iterables, functions: true }); - } - if (this.adjust) { - resolved = this.adjust(resolved); - } - if (this.map) { - const mapped = this.map.get(resolved); - if (mapped !== void 0) { - resolved = mapped; - } - } - return resolved; - } - toString() { - return this.display; - } - absolute(state) { - return [...state.path.slice(0, -this.ancestor), ...this.path]; - } - clone() { - return new internals.Ref(this); - } - updateDisplay() { - const key = this.key !== null ? this.key : ""; - if (this.type !== "value") { - this.display = `ref:${this.type}:${key}`; - return; - } - if (!this.separator) { - this.display = `ref:${key}`; - return; - } - if (!this.ancestor) { - this.display = `ref:${this.separator}${key}`; - return; - } - if (this.ancestor === "root") { - this.display = `ref:root:${key}`; - return; - } - if (this.ancestor === 1) { - this.display = `ref:${key || ".."}`; - return; - } - const lead = new Array(this.ancestor + 1).fill(this.separator).join(""); - this.display = `ref:${lead}${key || ""}`; - } - }; - internals.Ref.prototype[Common.symbols.ref] = true; - internals.context = function(key, separator, prefix = {}) { - key = key.trim(); - if (prefix) { - const globalp = prefix.global === void 0 ? "$" : prefix.global; - if (globalp !== separator && key.startsWith(globalp)) { - return { key: key.slice(globalp.length), type: "global" }; - } - const local = prefix.local === void 0 ? "#" : prefix.local; - if (local !== separator && key.startsWith(local)) { - return { key: key.slice(local.length), type: "local" }; - } - const root = prefix.root === void 0 ? "/" : prefix.root; - if (root !== separator && key.startsWith(root)) { - return { key: key.slice(root.length), type: "value", root: true }; - } - } - return { key, type: "value" }; - }; - internals.ancestor = function(key, separator) { - if (!separator) { - return [1, 0]; - } - if (key[0] !== separator) { - return [1, 0]; - } - if (key[1] !== separator) { - return [0, 1]; - } - let i2 = 2; - while (key[i2] === separator) { - ++i2; - } - return [i2 - 1, i2]; - }; - exports2.toSibling = 0; - exports2.toParent = 1; - exports2.Manager = class { - constructor() { - this.refs = []; - } - register(source, target) { - if (!source) { - return; - } - target = target === void 0 ? exports2.toParent : target; - if (Array.isArray(source)) { - for (const ref of source) { - this.register(ref, target); - } - return; - } - if (Common.isSchema(source)) { - for (const item of source._refs.refs) { - if (item.ancestor - target >= 0) { - this.refs.push({ ancestor: item.ancestor - target, root: item.root }); - } - } - return; - } - if (exports2.isRef(source) && source.type === "value" && source.ancestor - target >= 0) { - this.refs.push({ ancestor: source.ancestor - target, root: source.root }); - } - } - clone() { - const copy2 = new exports2.Manager(); - copy2.refs = Clone(this.refs); - return copy2; - } - reset() { - this.refs = []; - } - roots() { - return this.refs.filter((ref) => !ref.ancestor).map((ref) => ref.root); - } - }; - } -}); -var require_template = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/template.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var EscapeHtml = require_escapeHtml(); - var Common = require_common2(); - var Ref = require_ref(); - var internals = { - symbol: Symbol("template"), - opens: new Array(1e3).join("\0"), - closes: new Array(1e3).join(""), - dateFormat: { - date: Date.prototype.toDateString, - iso: Date.prototype.toISOString, - string: Date.prototype.toString, - time: Date.prototype.toTimeString, - utc: Date.prototype.toUTCString - } - }; - module14.exports = exports2 = internals.Template = class { - constructor(source, options2) { - Assert(typeof source === "string", "Template source must be a string"); - Assert(!source.includes("\0") && !source.includes(""), "Template source cannot contain reserved control characters"); - this.source = source; - this.rendered = source; - this._template = null; - this._settings = Clone(options2); - this._parse(); - } - _parse() { - if (!this.source.includes("{")) { - return; - } - const encoded = internals.encode(this.source); - const parts = internals.split(encoded); - const processed = []; - const head = parts.shift(); - if (head) { - processed.push(head); - } - for (const part of parts) { - const raw = part[0] !== "{"; - const ender = raw ? "}" : "}}"; - const end = part.indexOf(ender); - let variable = part.slice(raw ? 0 : 1, end); - const wrapped = variable[0] === ":"; - if (wrapped) { - variable = variable.slice(1); - } - const dynamic = this._ref(internals.decode(variable), { raw, wrapped }); - processed.push(dynamic); - const rest = part.slice(end + ender.length); - if (rest) { - processed.push(internals.decode(rest)); - } - } - this._template = processed; - } - static date(date3, prefs) { - return internals.dateFormat[prefs.dateFormat].call(date3); - } - isDynamic() { - return !!this._template; - } - static isTemplate(template) { - return template ? !!template[Common.symbols.template] : false; - } - render(value, state, prefs, local, options2 = {}) { - if (!this.isDynamic()) { - return this.rendered; - } - const parts = []; - for (const part of this._template) { - if (typeof part === "string") { - parts.push(part); - } else { - const rendered = part.ref.resolve(value, state, prefs, local, options2); - const string3 = internals.stringify(rendered, prefs, options2.errors); - const result = part.raw || options2.errors?.escapeHtml === false ? string3 : EscapeHtml(string3); - parts.push(internals.wrap(result, part.wrapped && prefs.errors.wrap.label)); - } - } - return parts.join(""); - } - _ref(content, { raw, wrapped }) { - const ref = Ref.create(content, this._settings); - return { ref, raw, wrapped: wrapped || ref.type === "local" && ref.key === "label" }; - } - toString() { - return this.source; - } - }; - internals.Template.prototype[Common.symbols.template] = true; - internals.Template.prototype.isImmutable = true; - internals.encode = function(string3) { - return string3.replace(/\\(\{+)/g, ($0, $1) => { - return internals.opens.slice(0, $1.length); - }).replace(/\\(\}+)/g, ($0, $1) => { - return internals.closes.slice(0, $1.length); - }); - }; - internals.decode = function(string3) { - return string3.replace(/\u0000/g, "{").replace(/\u0001/g, "}"); - }; - internals.split = function(string3) { - const parts = []; - let current = ""; - for (let i2 = 0; i2 < string3.length; ++i2) { - const char = string3[i2]; - if (char === "{") { - let next = ""; - while (i2 + 1 < string3.length && string3[i2 + 1] === "{") { - next += "{"; - ++i2; - } - parts.push(current); - current = next; - } else { - current += char; - } - } - parts.push(current); - return parts; - }; - internals.wrap = function(value, ends) { - if (!ends) { - return value; - } - if (ends.length === 1) { - return `${ends}${value}${ends}`; - } - return `${ends[0]}${value}${ends[1]}`; - }; - internals.stringify = function(value, prefs, options2) { - const type = typeof value; - if (value === null) { - return "null"; - } - if (value === void 0) { - return ""; - } - if (type === "string") { - return value; - } - if (type === "number" || type === "function" || type === "symbol") { - return value.toString(); - } - if (type !== "object") { - return JSON.stringify(value); - } - if (value instanceof Date) { - return internals.Template.date(value, prefs); - } - if (value instanceof Map) { - const pairs = []; - for (const [key, sym] of value.entries()) { - pairs.push(`${key.toString()} -> ${sym.toString()}`); - } - value = pairs; - } - if (!Array.isArray(value)) { - return value.toString(); - } - let partial2 = ""; - for (const item of value) { - partial2 = partial2 + (partial2.length ? ", " : "") + internals.stringify(item, prefs, options2); - } - return internals.wrap(partial2, prefs.errors.wrap.array); - }; - } -}); -var require_messages = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/messages.js"(exports2) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var Template = require_template(); - exports2.compile = function(messages, target) { - if (typeof messages === "string") { - Assert(!target, "Cannot set single message string"); - return new Template(messages); - } - if (Template.isTemplate(messages)) { - Assert(!target, "Cannot set single message template"); - return messages; - } - Assert(typeof messages === "object" && !Array.isArray(messages), "Invalid message options"); - target = target ? Clone(target) : {}; - for (let code2 in messages) { - const message = messages[code2]; - if (code2 === "root" || Template.isTemplate(message)) { - target[code2] = message; - continue; - } - if (typeof message === "string") { - target[code2] = new Template(message); - continue; - } - Assert(typeof message === "object" && !Array.isArray(message), "Invalid message for", code2); - const language = code2; - target[language] = target[language] || {}; - for (code2 in message) { - const localized = message[code2]; - if (code2 === "root" || Template.isTemplate(localized)) { - target[language][code2] = localized; - continue; - } - Assert(typeof localized === "string", "Invalid message for", code2, "in", language); - target[language][code2] = new Template(localized); - } - } - return target; - }; - exports2.merge = function(base2, extended) { - if (!base2) { - return exports2.compile(extended); - } - if (!extended) { - return base2; - } - if (typeof extended === "string") { - return new Template(extended); - } - if (Template.isTemplate(extended)) { - return extended; - } - const target = Clone(base2); - for (let code2 in extended) { - const message = extended[code2]; - if (code2 === "root" || Template.isTemplate(message)) { - target[code2] = message; - continue; - } - if (typeof message === "string") { - target[code2] = new Template(message); - continue; - } - Assert(typeof message === "object" && !Array.isArray(message), "Invalid message for", code2); - const language = code2; - target[language] = target[language] || {}; - for (code2 in message) { - const localized = message[code2]; - if (code2 === "root" || Template.isTemplate(localized)) { - target[language][code2] = localized; - continue; - } - Assert(typeof localized === "string", "Invalid message for", code2, "in", language); - target[language][code2] = new Template(localized); - } - } - return target; - }; - } -}); -var require_common2 = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/common.js"(exports2) { - "use strict"; - var Assert = require_assert(); - var AssertError = require_assertError(); - var Pkg = require_package3(); - var Messages; - var Schemas; - var internals = { - isoDate: /^(?:[-+]\d{2})?(?:\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?![T]$|[T][\d]+Z$)(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24\:?00)(?:[.,]\d+(?!:))?)(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[Z]|(?:[+-])(?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?)?$/ - }; - exports2.version = Pkg.version; - exports2.defaults = { - abortEarly: true, - allowUnknown: false, - context: null, - convert: true, - dateFormat: "iso", - errors: { - escapeHtml: false, - label: "path", - language: null, - render: true, - stack: false, - wrap: { - label: '"', - array: "[]" - } - }, - messages: {}, - nonEnumerables: false, - noDefaults: false, - presence: "optional", - skipFunctions: false, - stripUnknown: false - }; - exports2.symbols = { - any: Symbol.for("@hapi/joi/schema"), - // Used to internally identify any-based types (shared with other joi versions) - arraySingle: Symbol("arraySingle"), - deepDefault: Symbol("deepDefault"), - errors: Symbol("errors"), - literal: Symbol("literal"), - override: Symbol("override"), - parent: Symbol("parent"), - prefs: Symbol("prefs"), - ref: Symbol("ref"), - template: Symbol("template"), - values: Symbol("values") - }; - exports2.assertOptions = function(options2, keys, name = "Options") { - Assert(options2 && typeof options2 === "object" && !Array.isArray(options2), "Options must be of type object"); - const unknownKeys = Object.keys(options2).filter((k) => !keys.includes(k)); - Assert(unknownKeys.length === 0, `${name} contain unknown keys: ${unknownKeys}`); - }; - exports2.checkPreferences = function(prefs) { - Schemas = Schemas || require_schemas(); - const result = Schemas.preferences.validate(prefs); - if (result.error) { - throw new AssertError([result.error.details[0].message]); - } - }; - exports2.compare = function(a, b, operator) { - switch (operator) { - case "=": - return a === b; - case ">": - return a > b; - case "<": - return a < b; - case ">=": - return a >= b; - case "<=": - return a <= b; - } - }; - exports2.default = function(value, defaultValue) { - return value === void 0 ? defaultValue : value; - }; - exports2.isIsoDate = function(date3) { - return internals.isoDate.test(date3); - }; - exports2.isNumber = function(value) { - return typeof value === "number" && !isNaN(value); - }; - exports2.isResolvable = function(obj) { - if (!obj) { - return false; - } - return obj[exports2.symbols.ref] || obj[exports2.symbols.template]; - }; - exports2.isSchema = function(schema, options2 = {}) { - const any = schema && schema[exports2.symbols.any]; - if (!any) { - return false; - } - return true; - }; - exports2.limit = function(value) { - return Number.isSafeInteger(value) && value >= 0; - }; - exports2.preferences = function(target, source) { - Messages = Messages || require_messages(); - target = target || {}; - source = source || {}; - const merged = Object.assign({}, target, source); - if (source.errors && target.errors) { - merged.errors = Object.assign({}, target.errors, source.errors); - merged.errors.wrap = Object.assign({}, target.errors.wrap, source.errors.wrap); - } - if (source.messages) { - merged.messages = Messages.compile(source.messages, target.messages); - } - delete merged[exports2.symbols.prefs]; - return merged; - }; - exports2.tryWithPath = function(fn, key, options2 = {}) { - try { - return fn(); - } catch (err) { - if (err.path !== void 0) { - err.path = key + "." + err.path; - } else { - err.path = key; - } - if (options2.append) { - err.message = `${err.message} (${err.path})`; - } - throw err; - } - }; - exports2.validateArg = function(value, label, { assert: assert2, message }) { - if (exports2.isSchema(assert2)) { - const result = assert2.validate(value); - if (!result.error) { - return; - } - return result.error.message; - } else if (!assert2(value)) { - return label ? `${label} ${message}` : message; - } - }; - exports2.verifyFlat = function(args, method) { - for (const arg of args) { - Assert(!Array.isArray(arg), "Method no longer accepts array arguments:", method); - } - }; - } -}); -var require_compile = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/compile.js"(exports2) { - "use strict"; - var Assert = require_assert(); - var Common = require_common2(); - var Ref = require_ref(); - var internals = {}; - exports2.schema = function(Joi2, config2, options2 = {}) { - Common.assertOptions(options2, ["appendPath", "override"]); - try { - return internals.schema(Joi2, config2, options2); - } catch (err) { - if (options2.appendPath && err.path !== void 0) { - err.message = `${err.message} (${err.path})`; - } - throw err; - } - }; - internals.schema = function(Joi2, config2, options2) { - Assert(config2 !== void 0, "Invalid undefined schema"); - if (Array.isArray(config2)) { - Assert(config2.length, "Invalid empty array schema"); - if (config2.length === 1) { - config2 = config2[0]; - } - } - const valid = (base2, ...values) => { - if (options2.override !== false) { - return base2.valid(Joi2.override, ...values); - } - return base2.valid(...values); - }; - if (internals.simple(config2)) { - return valid(Joi2, config2); - } - if (typeof config2 === "function") { - return Joi2.custom(config2); - } - Assert(typeof config2 === "object", "Invalid schema content:", typeof config2); - if (Common.isResolvable(config2)) { - return valid(Joi2, config2); - } - if (Common.isSchema(config2)) { - return config2; - } - if (Array.isArray(config2)) { - for (const item of config2) { - if (!internals.simple(item)) { - return Joi2.alternatives().try(...config2); - } - } - return valid(Joi2, ...config2); - } - if (config2 instanceof RegExp) { - return Joi2.string().regex(config2); - } - if (config2 instanceof Date) { - return valid(Joi2.date(), config2); - } - Assert(Object.getPrototypeOf(config2) === Object.getPrototypeOf({}), "Schema can only contain plain objects"); - return Joi2.object().keys(config2); - }; - exports2.ref = function(id, options2) { - return Ref.isRef(id) ? id : Ref.create(id, options2); - }; - exports2.compile = function(root, schema) { - const any = schema && schema[Common.symbols.any]; - if (any) { - Assert(any.version === Common.version, "Cannot mix different versions of joi schemas:", any.version, Common.version); - return schema; - } - return exports2.schema(root, schema, { appendPath: true }); - }; - internals.simple = function(value) { - return value === null || ["boolean", "string", "number"].includes(typeof value); - }; - exports2.when = function(schema, condition, options2) { - if (options2 === void 0) { - Assert(condition && typeof condition === "object", "Missing options"); - options2 = condition; - condition = Ref.create("."); - } - if (Array.isArray(options2)) { - options2 = { switch: options2 }; - } - Common.assertOptions(options2, ["is", "not", "then", "otherwise", "switch", "break"]); - if (Common.isSchema(condition)) { - Assert(options2.is === void 0, '"is" can not be used with a schema condition'); - Assert(options2.not === void 0, '"not" can not be used with a schema condition'); - Assert(options2.switch === void 0, '"switch" can not be used with a schema condition'); - return internals.condition(schema, { is: condition, then: options2.then, otherwise: options2.otherwise, break: options2.break }); - } - Assert(Ref.isRef(condition) || typeof condition === "string", "Invalid condition:", condition); - Assert(options2.not === void 0 || options2.is === void 0, 'Cannot combine "is" with "not"'); - if (options2.switch === void 0) { - let rule2 = options2; - if (options2.not !== void 0) { - rule2 = { is: options2.not, then: options2.otherwise, otherwise: options2.then, break: options2.break }; - } - let is = rule2.is !== void 0 ? schema.$_compile(rule2.is) : schema.$_root.invalid(null, false, 0, "").required(); - Assert(rule2.then !== void 0 || rule2.otherwise !== void 0, 'options must have at least one of "then", "otherwise", or "switch"'); - Assert(rule2.break === void 0 || rule2.then === void 0 || rule2.otherwise === void 0, "Cannot specify then, otherwise, and break all together"); - if (options2.is !== void 0 && !Ref.isRef(options2.is) && !Common.isSchema(options2.is)) { - is = is.required(); - } - return internals.condition(schema, { ref: exports2.ref(condition), is, then: rule2.then, otherwise: rule2.otherwise, break: rule2.break }); - } - Assert(Array.isArray(options2.switch), '"switch" must be an array'); - Assert(options2.is === void 0, 'Cannot combine "switch" with "is"'); - Assert(options2.not === void 0, 'Cannot combine "switch" with "not"'); - Assert(options2.then === void 0, 'Cannot combine "switch" with "then"'); - const rule = { - ref: exports2.ref(condition), - switch: [], - break: options2.break - }; - for (let i2 = 0; i2 < options2.switch.length; ++i2) { - const test = options2.switch[i2]; - const last = i2 === options2.switch.length - 1; - Common.assertOptions(test, last ? ["is", "then", "otherwise"] : ["is", "then"]); - Assert(test.is !== void 0, 'Switch statement missing "is"'); - Assert(test.then !== void 0, 'Switch statement missing "then"'); - const item = { - is: schema.$_compile(test.is), - then: schema.$_compile(test.then) - }; - if (!Ref.isRef(test.is) && !Common.isSchema(test.is)) { - item.is = item.is.required(); - } - if (last) { - Assert(options2.otherwise === void 0 || test.otherwise === void 0, 'Cannot specify "otherwise" inside and outside a "switch"'); - const otherwise = options2.otherwise !== void 0 ? options2.otherwise : test.otherwise; - if (otherwise !== void 0) { - Assert(rule.break === void 0, "Cannot specify both otherwise and break"); - item.otherwise = schema.$_compile(otherwise); - } - } - rule.switch.push(item); - } - return rule; - }; - internals.condition = function(schema, condition) { - for (const key of ["then", "otherwise"]) { - if (condition[key] === void 0) { - delete condition[key]; - } else { - condition[key] = schema.$_compile(condition[key]); - } - } - return condition; - }; - } -}); -var require_annotate = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/annotate.js"(exports2) { - "use strict"; - var Clone = require_clone(); - var Common = require_common2(); - var internals = { - annotations: Symbol("annotations") - }; - exports2.error = function(stripColorCodes) { - if (!this._original || typeof this._original !== "object") { - return this.details[0].message; - } - const redFgEscape = stripColorCodes ? "" : "\x1B[31m"; - const redBgEscape = stripColorCodes ? "" : "\x1B[41m"; - const endColor = stripColorCodes ? "" : "\x1B[0m"; - const obj = Clone(this._original); - for (let i2 = this.details.length - 1; i2 >= 0; --i2) { - const pos = i2 + 1; - const error2 = this.details[i2]; - const path8 = error2.path; - let node = obj; - for (let j = 0; ; ++j) { - const seg = path8[j]; - if (Common.isSchema(node)) { - node = node.clone(); - } - if (j + 1 < path8.length && typeof node[seg] !== "string") { - node = node[seg]; - } else { - const refAnnotations = node[internals.annotations] || { errors: {}, missing: {} }; - node[internals.annotations] = refAnnotations; - const cacheKey = seg || error2.context.key; - if (node[seg] !== void 0) { - refAnnotations.errors[cacheKey] = refAnnotations.errors[cacheKey] || []; - refAnnotations.errors[cacheKey].push(pos); - } else { - refAnnotations.missing[cacheKey] = pos; - } - break; - } - } - } - const replacers = { - key: /_\$key\$_([, \d]+)_\$end\$_"/g, - missing: /"_\$miss\$_([^|]+)\|(\d+)_\$end\$_": "__missing__"/g, - arrayIndex: /\s*"_\$idx\$_([, \d]+)_\$end\$_",?\n(.*)/g, - specials: /"\[(NaN|Symbol.*|-?Infinity|function.*|\(.*)]"/g - }; - let message = internals.safeStringify(obj, 2).replace(replacers.key, ($0, $1) => `" ${redFgEscape}[${$1}]${endColor}`).replace(replacers.missing, ($0, $1, $2) => `${redBgEscape}"${$1}"${endColor}${redFgEscape} [${$2}]: -- missing --${endColor}`).replace(replacers.arrayIndex, ($0, $1, $2) => ` -${$2} ${redFgEscape}[${$1}]${endColor}`).replace(replacers.specials, ($0, $1) => $1); - message = `${message} -${redFgEscape}`; - for (let i2 = 0; i2 < this.details.length; ++i2) { - const pos = i2 + 1; - message = `${message} -[${pos}] ${this.details[i2].message}`; - } - message = message + endColor; - return message; - }; - internals.safeStringify = function(obj, spaces) { - return JSON.stringify(obj, internals.serializer(), spaces); - }; - internals.serializer = function() { - const keys = []; - const stack = []; - const cycleReplacer = (key, value) => { - if (stack[0] === value) { - return "[Circular ~]"; - } - return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"; - }; - return function(key, value) { - if (stack.length > 0) { - const thisPos = stack.indexOf(this); - if (~thisPos) { - stack.length = thisPos + 1; - keys.length = thisPos + 1; - keys[thisPos] = key; - } else { - stack.push(this); - keys.push(key); - } - if (~stack.indexOf(value)) { - value = cycleReplacer.call(this, key, value); - } - } else { - stack.push(value); - } - if (value) { - const annotations = value[internals.annotations]; - if (annotations) { - if (Array.isArray(value)) { - const annotated = []; - for (let i2 = 0; i2 < value.length; ++i2) { - if (annotations.errors[i2]) { - annotated.push(`_$idx$_${annotations.errors[i2].sort().join(", ")}_$end$_`); - } - annotated.push(value[i2]); - } - value = annotated; - } else { - for (const errorKey in annotations.errors) { - value[`${errorKey}_$key$_${annotations.errors[errorKey].sort().join(", ")}_$end$_`] = value[errorKey]; - value[errorKey] = void 0; - } - for (const missingKey in annotations.missing) { - value[`_$miss$_${missingKey}|${annotations.missing[missingKey]}_$end$_`] = "__missing__"; - } - } - return value; - } - } - if (value === Infinity || value === -Infinity || Number.isNaN(value) || typeof value === "function" || typeof value === "symbol") { - return "[" + value.toString() + "]"; - } - return value; - }; - }; - } -}); -var require_errors2 = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/errors.js"(exports2) { - "use strict"; - var Annotate = require_annotate(); - var Common = require_common2(); - var Template = require_template(); - exports2.Report = class { - constructor(code2, value, local, flags, messages, state, prefs) { - this.code = code2; - this.flags = flags; - this.messages = messages; - this.path = state.path; - this.prefs = prefs; - this.state = state; - this.value = value; - this.message = null; - this.local = local || {}; - this.local.label = exports2.label(this.flags, this.state, this.prefs, this.messages); - if (this.value !== void 0 && !this.local.hasOwnProperty("value")) { - this.local.value = this.value; - } - if (this.path.length) { - const key = this.path[this.path.length - 1]; - if (typeof key !== "object") { - this.local.key = key; - } - } - } - toString() { - if (this.message) { - return this.message; - } - const code2 = this.code; - if (!this.prefs.errors.render) { - return this.code; - } - const template = this._template(this.prefs.messages) || this._template(this.messages); - if (template === void 0) { - return `Error code "${code2}" is not defined, your custom type is missing the correct messages definition`; - } - this.message = template.render(this.value, this.state, this.prefs, this.local, { errors: this.prefs.errors, messages: [this.prefs.messages, this.messages] }); - if (!this.prefs.errors.label) { - this.message = this.message.replace(/^"" /, "").trim(); - } - return this.message; - } - _template(messages) { - return exports2.template(this.value, messages, this.code, this.state, this.prefs); - } - }; - exports2.path = function(path8) { - let label = ""; - for (const segment of path8) { - if (typeof segment === "object") { - continue; - } - if (typeof segment === "string") { - if (label) { - label += "."; - } - label += segment; - } else { - label += `[${segment}]`; - } - } - return label; - }; - exports2.template = function(value, messages, code2, state, prefs) { - if (Template.isTemplate(messages)) { - return code2 !== "root" ? messages : null; - } - let lang = prefs.errors.language; - if (Common.isResolvable(lang)) { - lang = lang.resolve(value, state, prefs); - } - if (lang && messages[lang] && messages[lang][code2] !== void 0) { - return messages[lang][code2]; - } - return messages[code2]; - }; - exports2.label = function(flags, state, prefs, messages) { - if (!prefs.errors.label) { - return ""; - } - let path8 = state.path; - if (prefs.errors.label === "key" && state.path.length > 1) { - path8 = state.path.slice(-1); - } - const normalized = exports2.path(path8); - if (normalized) { - return normalized; - } - return exports2.template(null, prefs.messages, "root", state, prefs) || exports2.template(null, messages, "root", state, prefs) || "value"; - }; - exports2.process = function(errors, original, prefs) { - if (!errors) { - return null; - } - const { override, message, details } = exports2.details(errors); - if (override) { - return override; - } - if (prefs.errors.stack) { - return new exports2.ValidationError(message, details, original); - } - const limit = Error.stackTraceLimit; - Error.stackTraceLimit = 0; - const validationError = new exports2.ValidationError(message, details, original); - Error.stackTraceLimit = limit; - return validationError; - }; - exports2.details = function(errors, options2 = {}) { - let messages = []; - const details = []; - for (const item of errors) { - if (item instanceof Error) { - if (options2.override !== false) { - return { override: item }; - } - const message2 = item.toString(); - messages.push(message2); - details.push({ - message: message2, - type: "override", - context: { error: item } - }); - continue; - } - const message = item.toString(); - messages.push(message); - details.push({ - message, - path: item.path.filter((v2) => typeof v2 !== "object"), - type: item.code, - context: item.local - }); - } - if (messages.length > 1) { - messages = [...new Set(messages)]; - } - return { message: messages.join(". "), details }; - }; - exports2.ValidationError = class extends Error { - constructor(message, details, original) { - super(message); - this._original = original; - this.details = details; - } - static isError(err) { - return err instanceof exports2.ValidationError; - } - }; - exports2.ValidationError.prototype.isJoi = true; - exports2.ValidationError.prototype.name = "ValidationError"; - exports2.ValidationError.prototype.annotate = Annotate.error; - } -}); -var require_extend = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/extend.js"(exports2) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var Common = require_common2(); - var Messages = require_messages(); - exports2.type = function(from3, options2) { - const base2 = Object.getPrototypeOf(from3); - const prototype = Clone(base2); - const schema = from3._assign(Object.create(prototype)); - const def = Object.assign({}, options2); - delete def.base; - prototype._definition = def; - const parent = base2._definition || {}; - def.messages = Messages.merge(parent.messages, def.messages); - def.properties = Object.assign({}, parent.properties, def.properties); - schema.type = def.type; - def.flags = Object.assign({}, parent.flags, def.flags); - const terms = Object.assign({}, parent.terms); - if (def.terms) { - for (const name in def.terms) { - const term = def.terms[name]; - Assert(schema.$_terms[name] === void 0, "Invalid term override for", def.type, name); - schema.$_terms[name] = term.init; - terms[name] = term; - } - } - def.terms = terms; - if (!def.args) { - def.args = parent.args; - } - if (def.coerce) { - if (typeof def.coerce === "function") { - def.coerce = { method: def.coerce }; - } - if (def.coerce.from && !Array.isArray(def.coerce.from)) { - def.coerce = { method: def.coerce.method, from: [].concat(def.coerce.from) }; - } - } - def.coerce = def.coerce || parent.coerce; - def.validate = def.validate || parent.validate; - const rules = Object.assign({}, parent.rules); - if (def.rules) { - for (const name in def.rules) { - const rule = def.rules[name]; - Assert(typeof rule === "object", "Invalid rule definition for", def.type, name); - const method = rule.method; - if (method) { - Assert(!prototype[name], "Rule conflict in", def.type, name); - prototype[name] = method; - } - Assert(!rules[name], "Rule conflict in", def.type, name); - rules[name] = rule; - if (rule.alias) { - const aliases = [].concat(rule.alias); - for (const alias of aliases) { - prototype[alias] = rule.method; - } - } - if (rule.args) { - rule.argsByName = /* @__PURE__ */ new Map(); - rule.args = rule.args.map((arg) => { - if (typeof arg === "string") { - arg = { name: arg }; - } - Assert(!rule.argsByName.has(arg.name), "Duplicated argument name", arg.name); - rule.argsByName.set(arg.name, arg); - return arg; - }); - } - } - } - def.rules = rules; - if (def.overrides) { - prototype._super = base2; - schema.$_super = {}; - for (const override in def.overrides) { - Assert(base2[override], "Cannot override missing", override); - def.overrides[override][Common.symbols.parent] = base2[override]; - schema.$_super[override] = base2[override].bind(schema); - } - Object.assign(prototype, def.overrides); - } - def.cast = Object.assign({}, parent.cast, def.cast); - def.rebuild = def.rebuild || parent.rebuild; - return schema; - }; - } -}); -var require_modify = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/modify.js"(exports2) { - "use strict"; - var Assert = require_assert(); - var Common = require_common2(); - var Ref = require_ref(); - var internals = {}; - exports2.Ids = internals.Ids = class { - constructor() { - this._byId = /* @__PURE__ */ new Map(); - this._byKey = /* @__PURE__ */ new Map(); - this._schemaChain = false; - } - clone() { - const clone2 = new internals.Ids(); - clone2._byId = new Map(this._byId); - clone2._byKey = new Map(this._byKey); - clone2._schemaChain = this._schemaChain; - return clone2; - } - concat(source) { - if (source._schemaChain) { - this._schemaChain = true; - } - for (const [id, value] of source._byId.entries()) { - Assert(!this._byKey.has(id), "Schema id conflicts with existing key:", id); - this._byId.set(id, value); - } - for (const [key, value] of source._byKey.entries()) { - Assert(!this._byId.has(key), "Schema key conflicts with existing id:", key); - this._byKey.set(key, value); - } - } - reach(path8, behind = []) { - const current = path8[0]; - const node = this._get(current); - Assert(node, "Schema does not contain path", [...behind, ...path8].join(".")); - const forward = path8.slice(1); - if (!forward.length) { - return node.schema; - } - return node.schema._ids.reach(forward, [...behind, current]); - } - register(schema, { key } = {}) { - if (!schema || !Common.isSchema(schema)) { - return; - } - if (schema.$_property("schemaChain") || schema._ids._schemaChain) { - this._schemaChain = true; - } - const id = schema._flags.id; - if (id) { - const existing = this._byId.get(id); - Assert(!existing || existing.schema === schema, "Cannot add different schemas with the same id:", id); - Assert(!this._byKey.has(id), "Schema id conflicts with existing key:", id); - this._byId.set(id, { schema, id }); - } - if (key) { - Assert(!this._byKey.has(key), "Schema already contains key:", key); - Assert(!this._byId.has(key), "Schema key conflicts with existing id:", key); - this._byKey.set(key, { schema, id: key }); - } - } - reset() { - this._byId = /* @__PURE__ */ new Map(); - this._byKey = /* @__PURE__ */ new Map(); - this._schemaChain = false; - } - _get(id) { - return this._byId.get(id) || this._byKey.get(id); - } - }; - exports2.schema = function(schema, options2) { - let obj; - for (const name in schema._flags) { - if (name[0] === "_") { - continue; - } - const result = internals.scan(schema._flags[name], { source: "flags", name }, options2); - if (result !== void 0) { - obj = obj || schema.clone(); - obj._flags[name] = result; - } - } - for (let i2 = 0; i2 < schema._rules.length; ++i2) { - const rule = schema._rules[i2]; - const result = internals.scan(rule.args, { source: "rules", name: rule.name }, options2); - if (result !== void 0) { - obj = obj || schema.clone(); - const clone2 = Object.assign({}, rule); - clone2.args = result; - obj._rules[i2] = clone2; - const existingUnique = obj._singleRules.get(rule.name); - if (existingUnique === rule) { - obj._singleRules.set(rule.name, clone2); - } - } - } - for (const name in schema.$_terms) { - if (name[0] === "_") { - continue; - } - const result = internals.scan(schema.$_terms[name], { source: "terms", name }, options2); - if (result !== void 0) { - obj = obj || schema.clone(); - obj.$_terms[name] = result; - } - } - return obj; - }; - internals.scan = function(item, source, options2, _path, _key) { - const path8 = _path || []; - if (item === null || typeof item !== "object") { - return; - } - let clone2; - if (Array.isArray(item)) { - for (let i2 = 0; i2 < item.length; ++i2) { - const key = source.name === "keys" && item[i2].key; - const result = internals.scan(item[i2], source, options2, [i2, ...path8], key); - if (result !== void 0) { - clone2 = clone2 || item.slice(); - clone2[i2] = result; - } - } - return clone2; - } - if (options2.schema !== false && Common.isSchema(item) || options2.ref !== false && Ref.isRef(item)) { - const result = options2.each(item, { ...source, path: path8, key: _key }); - return result; - } - for (const key in item) { - if (key[0] === "_") { - continue; - } - const result = internals.scan(item[key], source, options2, [key, ...path8], _key); - if (result !== void 0) { - clone2 = clone2 || Object.assign({}, item); - clone2[key] = result; - } - } - return clone2; - }; - } -}); -var require_state = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/state.js"(exports2, module14) { - "use strict"; - var Clone = require_clone(); - var Reach = require_reach(); - var Common = require_common2(); - var internals = { - value: Symbol("value") - }; - module14.exports = internals.State = class { - constructor(path8, ancestors, state) { - this.path = path8; - this.ancestors = ancestors; - this.mainstay = state.mainstay; - this.schemas = state.schemas; - } - localize(path8, ancestors = null, schema = null) { - const state = new internals.State(path8, ancestors, this); - if (schema && state.schemas) { - state.schemas = [internals.schemas(schema), ...state.schemas]; - } - return state; - } - nest(schema) { - const state = new internals.State(this.path, this.ancestors, this); - state.schemas = state.schemas && [internals.schemas(schema), ...state.schemas]; - return state; - } - shadow(value, reason) { - this.mainstay.shadow = this.mainstay.shadow || new internals.Shadow(); - this.mainstay.shadow.set(this.path, value, reason); - } - snapshot() { - if (this.mainstay.shadow) { - this._snapshot = Clone(this.mainstay.shadow.node(this.path)); - } - } - restore() { - if (this.mainstay.shadow) { - this.mainstay.shadow.override(this.path, this._snapshot); - this._snapshot = void 0; - } - } - }; - internals.schemas = function(schema) { - if (Common.isSchema(schema)) { - return { schema }; - } - return schema; - }; - internals.Shadow = class { - constructor() { - this._values = null; - } - set(path8, value, reason) { - if (!path8.length) { - return; - } - if (reason === "strip" && typeof path8[path8.length - 1] === "number") { - return; - } - this._values = this._values || /* @__PURE__ */ new Map(); - let node = this._values; - for (let i2 = 0; i2 < path8.length; ++i2) { - const segment = path8[i2]; - let next = node.get(segment); - if (!next) { - next = /* @__PURE__ */ new Map(); - node.set(segment, next); - } - node = next; - } - node[internals.value] = value; - } - get(path8) { - const node = this.node(path8); - if (node) { - return node[internals.value]; - } - } - node(path8) { - if (!this._values) { - return; - } - return Reach(this._values, path8, { iterables: true }); - } - override(path8, node) { - if (!this._values) { - return; - } - const parents = path8.slice(0, -1); - const own = path8[path8.length - 1]; - const parent = Reach(this._values, parents, { iterables: true }); - if (node) { - parent.set(own, node); - return; - } - if (parent) { - parent.delete(own); - } - } - }; - } -}); -var require_validator = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/validator.js"(exports2) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var Common = require_common2(); - var Errors = require_errors2(); - var State = require_state(); - var internals = { - result: Symbol("result") - }; - exports2.entry = function(value, schema, prefs) { - let settings = Common.defaults; - if (prefs) { - settings = Common.preferences(Common.defaults, prefs); - } - const result = internals.entry(value, schema, settings); - const outcome = { value: result.value }; - if (result.error) { - outcome.error = result.error; - } - return outcome; - }; - internals.entry = function(value, schema, prefs) { - const links = schema._ids._schemaChain ? /* @__PURE__ */ new Map() : null; - const mainstay = { links }; - const schemas = schema._ids._schemaChain ? [{ schema }] : null; - const state = new State([], [], { mainstay, schemas }); - const result = exports2.validate(value, schema, state, prefs); - const error2 = Errors.process(result.errors, value, prefs); - return { value: result.value, error: error2, mainstay }; - }; - exports2.validate = function(value, schema, state, prefs, overrides = {}) { - if (schema.$_terms.whens) { - schema = schema._generate(value, state, prefs).schema; - } - if (schema._preferences) { - prefs = internals.prefs(schema, prefs); - } - const createError = (code2, local, localState) => schema.$_createError(code2, value, local, localState || state, prefs); - const helpers = { - original: value, - prefs, - schema, - state, - error: createError, - errorsArray: internals.errorsArray, - message: (messages, local) => schema.$_createError("custom", value, local, state, prefs, { messages }) - }; - const def = schema._definition; - if (def.coerce && value !== void 0 && prefs.convert && (!def.coerce.from || def.coerce.from.includes(typeof value))) { - const coerced = def.coerce.method(value, helpers); - if (coerced) { - if (coerced.errors) { - return internals.finalize(coerced.value, [].concat(coerced.errors), helpers); - } - value = coerced.value; - } - } - const empty2 = schema._flags.empty; - if (empty2 && empty2.$_match(internals.trim(value, schema), state.nest(empty2), Common.defaults)) { - value = void 0; - } - const presence = overrides.presence || schema._flags.presence || (schema._flags._endedSwitch ? null : prefs.presence); - if (value === void 0) { - if (presence === "forbidden") { - return internals.finalize(value, null, helpers); - } - if (presence === "required") { - return internals.finalize(value, [schema.$_createError("any.required", value, null, state, prefs)], helpers); - } - if (presence === "optional") { - if (schema._flags.default !== Common.symbols.deepDefault) { - return internals.finalize(value, null, helpers); - } - value = {}; - } - } else if (presence === "forbidden") { - return internals.finalize(value, [schema.$_createError("any.unknown", value, null, state, prefs)], helpers); - } - const errors = []; - if (schema._valids) { - const match = schema._valids.get(value, state, prefs, schema._flags.insensitive); - if (match) { - if (prefs.convert) { - value = match.value; - } - return internals.finalize(value, null, helpers); - } - if (schema._flags.only) { - const report = schema.$_createError("any.only", value, { valids: schema._valids.values({ display: true }) }, state, prefs); - if (prefs.abortEarly) { - return internals.finalize(value, [report], helpers); - } - errors.push(report); - } - } - if (schema._invalids) { - const match = schema._invalids.get(value, state, prefs, schema._flags.insensitive); - if (match) { - const report = schema.$_createError("any.invalid", value, { invalids: schema._invalids.values({ display: true }) }, state, prefs); - if (prefs.abortEarly) { - return internals.finalize(value, [report], helpers); - } - errors.push(report); - } - } - if (def.validate) { - const base2 = def.validate(value, helpers); - if (base2) { - value = base2.value; - if (base2.errors) { - if (!Array.isArray(base2.errors)) { - errors.push(base2.errors); - return internals.finalize(value, errors, helpers); - } - if (base2.errors.length) { - errors.push(...base2.errors); - return internals.finalize(value, errors, helpers); - } - } - } - } - if (!schema._rules.length) { - return internals.finalize(value, errors, helpers); - } - return internals.rules(value, errors, helpers); - }; - internals.rules = function(value, errors, helpers) { - const { schema, state, prefs } = helpers; - for (const rule of schema._rules) { - const definition = schema._definition.rules[rule.method]; - if (definition.convert && prefs.convert) { - continue; - } - let ret; - let args = rule.args; - if (rule._resolve.length) { - args = Object.assign({}, args); - for (const key of rule._resolve) { - const resolver = definition.argsByName.get(key); - const resolved = args[key].resolve(value, state, prefs); - const normalized = resolver.normalize ? resolver.normalize(resolved) : resolved; - const invalid = Common.validateArg(normalized, null, resolver); - if (invalid) { - ret = schema.$_createError("any.ref", resolved, { arg: key, ref: args[key], reason: invalid }, state, prefs); - break; - } - args[key] = normalized; - } - } - ret = ret || definition.validate(value, helpers, args, rule); - const result = internals.rule(ret, rule); - if (result.errors) { - if (prefs.abortEarly) { - return internals.finalize(value, result.errors, helpers); - } - errors.push(...result.errors); - } else { - value = result.value; - } - } - return internals.finalize(value, errors, helpers); - }; - internals.rule = function(ret, rule) { - if (ret instanceof Errors.Report) { - return { errors: [ret], value: null }; - } - if (Array.isArray(ret) && ret[Common.symbols.errors]) { - return { errors: ret, value: null }; - } - return { errors: null, value: ret }; - }; - internals.finalize = function(value, errors, helpers) { - errors = errors || []; - const { schema, state } = helpers; - if (errors.length) { - const failover = internals.default("failover", void 0, errors, helpers); - if (failover !== void 0) { - value = failover; - errors = []; - } - } - if (errors.length && schema._flags.error) { - if (typeof schema._flags.error === "function") { - errors = schema._flags.error(errors); - if (!Array.isArray(errors)) { - errors = [errors]; - } - for (const error2 of errors) { - Assert(error2 instanceof Error || error2 instanceof Errors.Report, "error() must return an Error object"); - } - } else { - errors = [schema._flags.error]; - } - } - if (value === void 0) { - const defaulted = internals.default("default", value, errors, helpers); - value = defaulted; - } - if (schema._flags.cast && value !== void 0) { - const caster = schema._definition.cast[schema._flags.cast]; - if (caster.from(value)) { - const casted = caster.to(value, helpers); - value = casted; - } - } - const result = { value, errors: errors.length ? errors : null }; - if (schema._flags.result) { - result.value = schema._flags.result === "strip" ? void 0 : ( - /* raw */ - helpers.original - ); - state.shadow(value, schema._flags.result); - } - return result; - }; - internals.prefs = function(schema, prefs) { - const isDefaultOptions = prefs === Common.defaults; - if (isDefaultOptions && schema._preferences[Common.symbols.prefs]) { - return schema._preferences[Common.symbols.prefs]; - } - prefs = Common.preferences(prefs, schema._preferences); - if (isDefaultOptions) { - schema._preferences[Common.symbols.prefs] = prefs; - } - return prefs; - }; - internals.default = function(flag, value, errors, helpers) { - const { schema, state, prefs } = helpers; - const source = schema._flags[flag]; - if (prefs.noDefaults || source === void 0) { - return value; - } - if (!source) { - return source; - } - if (typeof source === "function") { - const args = source.length ? [Clone(state.ancestors[0]), helpers] : []; - try { - return source(...args); - } catch (err) { - errors.push(schema.$_createError(`any.${flag}`, null, { error: err }, state, prefs)); - return; - } - } - if (typeof source !== "object") { - return source; - } - if (source[Common.symbols.literal]) { - return source.literal; - } - if (Common.isResolvable(source)) { - return source.resolve(value, state, prefs); - } - return Clone(source); - }; - internals.trim = function(value, schema) { - if (typeof value !== "string") { - return value; - } - const trim = schema.$_getRule("trim"); - if (!trim || !trim.args.enabled) { - return value; - } - return value.trim(); - }; - internals.errorsArray = function() { - const errors = []; - errors[Common.symbols.errors] = true; - return errors; - }; - } -}); -var require_values = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/values.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var DeepEqual = require_deepEqual(); - var Common = require_common2(); - var internals = {}; - module14.exports = internals.Values = class { - constructor(values, refs) { - this._values = new Set(values); - this._refs = new Set(refs); - this._lowercase = internals.lowercases(values); - this._override = false; - } - get length() { - return this._values.size + this._refs.size; - } - add(value, refs) { - if (Common.isResolvable(value)) { - if (!this._refs.has(value)) { - this._refs.add(value); - if (refs) { - refs.register(value); - } - } - return; - } - if (!this.has(value, null, null, false)) { - this._values.add(value); - if (typeof value === "string") { - this._lowercase.set(value.toLowerCase(), value); - } - } - } - static merge(target, source, remove) { - target = target || new internals.Values(); - if (source) { - if (source._override) { - return source.clone(); - } - for (const item of [...source._values, ...source._refs]) { - target.add(item); - } - } - if (remove) { - for (const item of [...remove._values, ...remove._refs]) { - target.remove(item); - } - } - return target.length ? target : null; - } - remove(value) { - if (Common.isResolvable(value)) { - this._refs.delete(value); - return; - } - this._values.delete(value); - if (typeof value === "string") { - this._lowercase.delete(value.toLowerCase()); - } - } - has(value, state, prefs, insensitive) { - return !!this.get(value, state, prefs, insensitive); - } - get(value, state, prefs, insensitive) { - if (!this.length) { - return false; - } - if (this._values.has(value)) { - return { value }; - } - if (typeof value === "string" && value && insensitive) { - const found = this._lowercase.get(value.toLowerCase()); - if (found) { - return { value: found }; - } - } - if (!this._refs.size && typeof value !== "object") { - return false; - } - if (typeof value === "object") { - for (const item of this._values) { - if (DeepEqual(item, value)) { - return { value: item }; - } - } - } - if (state) { - for (const ref of this._refs) { - const resolved = ref.resolve(value, state, prefs, null, { in: true }); - if (resolved === void 0) { - continue; - } - const items = !ref.in || typeof resolved !== "object" ? [resolved] : Array.isArray(resolved) ? resolved : Object.keys(resolved); - for (const item of items) { - if (typeof item !== typeof value) { - continue; - } - if (insensitive && value && typeof value === "string") { - if (item.toLowerCase() === value.toLowerCase()) { - return { value: item, ref }; - } - } else { - if (DeepEqual(item, value)) { - return { value: item, ref }; - } - } - } - } - } - return false; - } - override() { - this._override = true; - } - values(options2) { - if (options2 && options2.display) { - const values = []; - for (const item of [...this._values, ...this._refs]) { - if (item !== void 0) { - values.push(item); - } - } - return values; - } - return Array.from([...this._values, ...this._refs]); - } - clone() { - const set = new internals.Values(this._values, this._refs); - set._override = this._override; - return set; - } - concat(source) { - Assert(!source._override, "Cannot concat override set of values"); - const set = new internals.Values([...this._values, ...source._values], [...this._refs, ...source._refs]); - set._override = this._override; - return set; - } - }; - internals.Values.prototype[Common.symbols.values] = true; - internals.Values.prototype.slice = internals.Values.prototype.clone; - internals.lowercases = function(from3) { - const map = /* @__PURE__ */ new Map(); - if (from3) { - for (const value of from3) { - if (typeof value === "string") { - map.set(value.toLowerCase(), value); - } - } - } - return map; - }; - } -}); -var require_base = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/base.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var DeepEqual = require_deepEqual(); - var Merge = require_merge(); - var Common = require_common2(); - var Compile = require_compile(); - var Errors = require_errors2(); - var Extend = require_extend(); - var Messages = require_messages(); - var Modify = require_modify(); - var Ref = require_ref(); - var Validator = require_validator(); - var Values = require_values(); - var internals = {}; - internals.Base = class { - constructor(type) { - this.type = type; - this.$_root = null; - this._definition = {}; - this._ids = new Modify.Ids(); - this._preferences = null; - this._refs = new Ref.Manager(); - this._cache = null; - this._valids = null; - this._invalids = null; - this._flags = {}; - this._rules = []; - this._singleRules = /* @__PURE__ */ new Map(); - this.$_terms = {}; - this.$_temp = { - // Runtime state (not cloned) - whens: {} - // Runtime cache of generated whens - }; - } - // Rules - allow(...values) { - Common.verifyFlat(values, "allow"); - return this._values(values, "_valids"); - } - cast(to) { - Assert(to === false || typeof to === "string", "Invalid to value"); - Assert(to === false || this._definition.cast[to], "Type", this.type, "does not support casting to", to); - return this.$_setFlag("cast", to === false ? void 0 : to); - } - default(value, options2) { - return this._default("default", value, options2); - } - empty(schema) { - const obj = this.clone(); - if (schema !== void 0) { - schema = obj.$_compile(schema, { override: false }); - } - return obj.$_setFlag("empty", schema, { clone: false }); - } - error(err) { - Assert(err, "Missing error"); - Assert(err instanceof Error || typeof err === "function", "Must provide a valid Error object or a function"); - return this.$_setFlag("error", err); - } - failover(value, options2) { - return this._default("failover", value, options2); - } - forbidden() { - return this.presence("forbidden"); - } - id(id) { - if (!id) { - return this.$_setFlag("id", void 0); - } - Assert(typeof id === "string", "id must be a non-empty string"); - Assert(/^[^\.]+$/.test(id), "id cannot contain period character"); - return this.$_setFlag("id", id); - } - invalid(...values) { - return this._values(values, "_invalids"); - } - only(mode = true) { - Assert(typeof mode === "boolean", "Invalid mode:", mode); - return this.$_setFlag("only", mode); - } - optional() { - return this.presence("optional"); - } - prefs(prefs) { - Assert(prefs, "Missing preferences"); - Assert(prefs.context === void 0, "Cannot override context"); - Common.checkPreferences(prefs); - const obj = this.clone(); - obj._preferences = Common.preferences(obj._preferences, prefs); - return obj; - } - presence(mode) { - Assert(["optional", "required", "forbidden"].includes(mode), "Unknown presence mode", mode); - return this.$_setFlag("presence", mode); - } - raw(enabled2 = true) { - return this.$_setFlag("result", enabled2 ? "raw" : void 0); - } - required() { - return this.presence("required"); - } - strict(enabled2) { - const obj = this.clone(); - const convert = enabled2 === void 0 ? false : !enabled2; - obj._preferences = Common.preferences(obj._preferences, { convert }); - return obj; - } - strip(enabled2 = true) { - return this.$_setFlag("result", enabled2 ? "strip" : void 0); - } - valid(...values) { - Common.verifyFlat(values, "valid"); - const obj = this.allow(...values); - obj.$_setFlag("only", !!obj._valids, { clone: false }); - return obj; - } - when(condition, options2) { - const obj = this.clone(); - if (!obj.$_terms.whens) { - obj.$_terms.whens = []; - } - const when = Compile.when(obj, condition, options2); - if (!["any", "link"].includes(obj.type)) { - const conditions = when.is ? [when] : when.switch; - for (const item of conditions) { - Assert(!item.then || item.then.type === "any" || item.then.type === obj.type, "Cannot combine", obj.type, "with", item.then?.type); - Assert(!item.otherwise || item.otherwise.type === "any" || item.otherwise.type === obj.type, "Cannot combine", obj.type, "with", item.otherwise?.type); - } - } - obj.$_terms.whens.push(when); - return obj.$_mutateRebuild(); - } - // Helpers - clone() { - const obj = Object.create(Object.getPrototypeOf(this)); - return this._assign(obj); - } - concat(source) { - Assert(Common.isSchema(source), "Invalid schema object"); - Assert(this.type === "any" || source.type === "any" || source.type === this.type, "Cannot merge type", this.type, "with another type:", source.type); - let obj = this.clone(); - if (this.type === "any" && source.type !== "any") { - const tmpObj = source.clone(); - for (const key of Object.keys(obj)) { - if (key !== "type") { - tmpObj[key] = obj[key]; - } - } - obj = tmpObj; - } - obj._ids.concat(source._ids); - obj._refs.register(source, Ref.toSibling); - obj._preferences = obj._preferences ? Common.preferences(obj._preferences, source._preferences) : source._preferences; - obj._valids = Values.merge(obj._valids, source._valids, source._invalids); - obj._invalids = Values.merge(obj._invalids, source._invalids, source._valids); - for (const name of source._singleRules.keys()) { - if (obj._singleRules.has(name)) { - obj._rules = obj._rules.filter((target) => target.name !== name); - obj._singleRules.delete(name); - } - } - for (const test of source._rules) { - if (!source._definition.rules[test.method].multi) { - obj._singleRules.set(test.name, test); - } - obj._rules.push(test); - } - if (obj._flags.empty && source._flags.empty) { - obj._flags.empty = obj._flags.empty.concat(source._flags.empty); - const flags = Object.assign({}, source._flags); - delete flags.empty; - Merge(obj._flags, flags); - } else if (source._flags.empty) { - obj._flags.empty = source._flags.empty; - const flags = Object.assign({}, source._flags); - delete flags.empty; - Merge(obj._flags, flags); - } else { - Merge(obj._flags, source._flags); - } - for (const key in source.$_terms) { - const terms = source.$_terms[key]; - if (!terms) { - if (!obj.$_terms[key]) { - obj.$_terms[key] = terms; - } - continue; - } - if (!obj.$_terms[key]) { - obj.$_terms[key] = terms.slice(); - continue; - } - obj.$_terms[key] = obj.$_terms[key].concat(terms); - } - return obj.$_mutateRebuild(); - } - validate(value, options2) { - return Validator.entry(value, this, options2); - } - validateAsync(value, options2) { - const result = this.validate(value, options2); - if (result.error) { - throw result.error; - } - return result.value; - } - // Extensions - $_addRule(options2) { - if (typeof options2 === "string") { - options2 = { name: options2 }; - } - Assert(options2 && typeof options2 === "object", "Invalid options"); - Assert(options2.name && typeof options2.name === "string", "Invalid rule name"); - for (const key in options2) { - Assert(key[0] !== "_", "Cannot set private rule properties"); - } - const rule = Object.assign({}, options2); - rule._resolve = []; - rule.method = rule.method || rule.name; - const definition = this._definition.rules[rule.method]; - const args = rule.args; - Assert(definition, "Unknown rule", rule.method); - const obj = this.clone(); - if (args) { - Assert(Object.keys(args).length === 1 || Object.keys(args).length === this._definition.rules[rule.name].args.length, "Invalid rule definition for", this.type, rule.name); - for (const key in args) { - let arg = args[key]; - if (arg === void 0) { - delete args[key]; - continue; - } - if (definition.argsByName) { - const resolver = definition.argsByName.get(key); - if (resolver.ref && Common.isResolvable(arg)) { - rule._resolve.push(key); - obj.$_mutateRegister(arg); - } else { - if (resolver.normalize) { - arg = resolver.normalize(arg); - args[key] = arg; - } - if (resolver.assert) { - const error2 = Common.validateArg(arg, key, resolver); - Assert(!error2, error2, "or reference"); - } - } - } - args[key] = arg; - } - } - if (!definition.multi) { - obj._ruleRemove(rule.name); - obj._singleRules.set(rule.name, rule); - } - if (definition.priority) { - obj._rules.unshift(rule); - } else { - obj._rules.push(rule); - } - return obj; - } - $_compile(schema, options2) { - return Compile.schema(this.$_root, schema, options2); - } - $_createError(code2, value, local, state, prefs, options2 = {}) { - const flags = options2.flags !== false ? this._flags : {}; - const messages = options2.messages ? Messages.merge(this._definition.messages, options2.messages) : this._definition.messages; - return new Errors.Report(code2, value, local, flags, messages, state, prefs); - } - $_getRule(name) { - return this._singleRules.get(name); - } - $_match(value, state, prefs, overrides) { - prefs = Object.assign({}, prefs); - prefs.abortEarly = true; - prefs._externals = false; - state.snapshot(); - const result = !Validator.validate(value, this, state, prefs, overrides).errors; - state.restore(); - return result; - } - $_modify(options2) { - Common.assertOptions(options2, ["each", "once", "ref", "schema"]); - return Modify.schema(this, options2) || this; - } - $_mutateRebuild() { - this._refs.reset(); - this._ids.reset(); - const each = (item, { source, name, path: path8, key }) => { - const family = this._definition[source][name]?.register; - if (family !== false) { - this.$_mutateRegister(item, { family, key }); - } - }; - this.$_modify({ each }); - if (this._definition.rebuild) { - this._definition.rebuild(this); - } - return this; - } - $_mutateRegister(schema, { family, key } = {}) { - this._refs.register(schema, family); - this._ids.register(schema, { key }); - } - $_property(name) { - return this._definition.properties[name]; - } - $_reach(path8) { - return this._ids.reach(path8); - } - $_rootReferences() { - return this._refs.roots(); - } - $_setFlag(name, value, options2 = {}) { - const flag = this._definition.flags[name] || {}; - if (DeepEqual(value, flag.default)) { - value = void 0; - } - if (DeepEqual(value, this._flags[name])) { - return this; - } - const obj = options2.clone !== false ? this.clone() : this; - if (value !== void 0) { - obj._flags[name] = value; - obj.$_mutateRegister(value); - } else { - delete obj._flags[name]; - } - return obj; - } - $_parent(method, ...args) { - return this[method][Common.symbols.parent].call(this, ...args); - } - $_validate(value, state, prefs) { - return Validator.validate(value, this, state, prefs); - } - // Internals - _assign(target) { - target.type = this.type; - target.$_root = this.$_root; - target.$_temp = Object.assign({}, this.$_temp); - target.$_temp.whens = {}; - target._ids = this._ids.clone(); - target._preferences = this._preferences; - target._valids = this._valids?.clone(); - target._invalids = this._invalids?.clone(); - target._rules = this._rules.slice(); - target._singleRules = Clone(this._singleRules, { shallow: true }); - target._refs = this._refs.clone(); - target._flags = Object.assign({}, this._flags); - target._cache = null; - target.$_terms = {}; - for (const key in this.$_terms) { - target.$_terms[key] = this.$_terms[key] ? this.$_terms[key].slice() : null; - } - target.$_super = {}; - for (const override in this.$_super) { - target.$_super[override] = this._super[override].bind(target); - } - return target; - } - _default(flag, value, options2 = {}) { - Common.assertOptions(options2, "literal"); - Assert(value !== void 0, "Missing", flag, "value"); - Assert(typeof value === "function" || !options2.literal, "Only function value supports literal option"); - if (typeof value === "function" && options2.literal) { - value = { - [Common.symbols.literal]: true, - literal: value - }; - } - const obj = this.$_setFlag(flag, value); - return obj; - } - _extend(options2) { - Assert(!options2.base, "Cannot extend type with another base"); - return Extend.type(this, options2); - } - _generate(value, state, prefs) { - if (!this.$_terms.whens) { - return { schema: this }; - } - const whens = []; - const ids = []; - for (let i2 = 0; i2 < this.$_terms.whens.length; ++i2) { - const when = this.$_terms.whens[i2]; - if (when.concat) { - whens.push(when.concat); - ids.push(`${i2}.concat`); - continue; - } - const input = when.ref ? when.ref.resolve(value, state, prefs) : value; - const tests = when.is ? [when] : when.switch; - const before = ids.length; - for (let j = 0; j < tests.length; ++j) { - const { is, then, otherwise } = tests[j]; - const baseId = `${i2}${when.switch ? "." + j : ""}`; - if (is.$_match(input, state.nest(is, `${baseId}.is`), prefs)) { - if (then) { - const localState = state.localize([...state.path, `${baseId}.then`], state.ancestors, state.schemas); - const { schema: generated, id: id2 } = then._generate(value, localState, prefs); - whens.push(generated); - ids.push(`${baseId}.then${id2 ? `(${id2})` : ""}`); - break; - } - } else if (otherwise) { - const localState = state.localize([...state.path, `${baseId}.otherwise`], state.ancestors, state.schemas); - const { schema: generated, id: id2 } = otherwise._generate(value, localState, prefs); - whens.push(generated); - ids.push(`${baseId}.otherwise${id2 ? `(${id2})` : ""}`); - break; - } - } - if (when.break && ids.length > before) { - break; - } - } - const id = ids.join(", "); - if (!id) { - return { schema: this }; - } - if (this.$_temp.whens[id]) { - return { schema: this.$_temp.whens[id], id }; - } - let obj = this; - if (this._definition.generate) { - obj = this._definition.generate(this, value, state, prefs); - } - for (const when of whens) { - obj = obj.concat(when); - } - this.$_temp.whens[id] = obj; - return { schema: obj, id }; - } - _ruleRemove(name) { - if (!this._singleRules.has(name)) { - return this; - } - this._singleRules.delete(name); - const filtered = []; - for (let i2 = 0; i2 < this._rules.length; ++i2) { - const test = this._rules[i2]; - if (test.name === name) { - continue; - } - filtered.push(test); - } - this._rules = filtered; - } - _values(values, key) { - Common.verifyFlat(values, key.slice(1, -1)); - const obj = this.clone(); - const override = values[0] === Common.symbols.override; - if (override) { - values = values.slice(1); - } - if (!obj[key] && values.length) { - obj[key] = new Values(); - } else if (override) { - obj[key] = values.length ? new Values() : null; - obj.$_mutateRebuild(); - } - if (!obj[key]) { - return obj; - } - if (override) { - obj[key].override(); - } - for (const value of values) { - Assert(value !== void 0, "Cannot call allow/valid/invalid with undefined"); - Assert(value !== Common.symbols.override, "Override must be the first value"); - const other = key === "_invalids" ? "_valids" : "_invalids"; - if (obj[other]) { - obj[other].remove(value); - if (!obj[other].length) { - Assert(key === "_valids" || !obj._flags.only, "Setting invalid value", value, "leaves schema rejecting all values due to previous valid rule"); - obj[other] = null; - } - } - obj[key].add(value, obj._refs); - } - return obj; - } - }; - internals.Base.prototype[Common.symbols.any] = { - version: Common.version, - compile: Compile.compile, - root: "$_root" - }; - internals.Base.prototype.isImmutable = true; - internals.Base.prototype.deny = internals.Base.prototype.invalid; - internals.Base.prototype.disallow = internals.Base.prototype.invalid; - internals.Base.prototype.equal = internals.Base.prototype.valid; - internals.Base.prototype.exist = internals.Base.prototype.required; - internals.Base.prototype.not = internals.Base.prototype.invalid; - internals.Base.prototype.options = internals.Base.prototype.prefs; - internals.Base.prototype.preferences = internals.Base.prototype.prefs; - module14.exports = new internals.Base(); - } -}); -var require_any = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/any.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Base = require_base(); - var Common = require_common2(); - module14.exports = Base._extend({ - type: "any", - flags: { - only: { default: false } - }, - terms: { - alterations: { init: null }, - examples: { init: null }, - metas: { init: [] }, - notes: { init: [] }, - shared: { init: null }, - tags: { init: [] }, - whens: { init: null } - }, - rules: { - custom: { - method(method, description) { - Assert(typeof method === "function", "Method must be a function"); - Assert(description === void 0 || description && typeof description === "string", "Description must be a non-empty string"); - return this.$_addRule({ name: "custom", args: { method, description } }); - }, - validate(value, helpers, { method }) { - try { - return method(value, helpers); - } catch (err) { - return helpers.error("any.custom", { error: err }); - } - }, - args: ["method", "description"], - multi: true - }, - messages: { - method(messages) { - return this.prefs({ messages }); - } - }, - shared: { - method(schema) { - Assert(Common.isSchema(schema) && schema._flags.id, "Schema must be a schema with an id"); - const obj = this.clone(); - obj.$_terms.shared = obj.$_terms.shared || []; - obj.$_terms.shared.push(schema); - obj.$_mutateRegister(schema); - return obj; - } - } - }, - messages: { - "any.custom": "{{#label}} failed custom validation because {{#error.message}}", - "any.default": "{{#label}} threw an error when running default method", - "any.failover": "{{#label}} threw an error when running failover method", - "any.invalid": "{{#label}} contains an invalid value", - "any.only": "{{#label}} must be one of {{#valids}}", - "any.ref": "{{#label}} {{#arg}} references {{:#ref}} which {{#reason}}", - "any.required": "{{#label}} is required", - "any.unknown": "{{#label}} is not allowed" - } - }); - } -}); -var require_alternatives = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/alternatives.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Any = require_any(); - var Common = require_common2(); - var Compile = require_compile(); - var Errors = require_errors2(); - var Ref = require_ref(); - var internals = {}; - module14.exports = Any._extend({ - type: "alternatives", - flags: { - match: { default: "any" } - // 'any', 'one', 'all' - }, - terms: { - matches: { init: [], register: Ref.toSibling } - }, - args(schema, ...schemas) { - if (schemas.length === 1) { - if (Array.isArray(schemas[0])) { - return schema.try(...schemas[0]); - } - } - return schema.try(...schemas); - }, - validate(value, helpers) { - const { schema, error: error2, state, prefs } = helpers; - if (schema._flags.match) { - let hits = 0; - let matched; - for (let i2 = 0; i2 < schema.$_terms.matches.length; ++i2) { - const item = schema.$_terms.matches[i2]; - const localState = state.nest(item.schema, `match.${i2}`); - localState.snapshot(); - const result = item.schema.$_validate(value, localState, prefs); - if (!result.errors) { - ++hits; - matched = result.value; - } else { - localState.restore(); - } - } - if (!hits) { - return { errors: error2("alternatives.any") }; - } - if (schema._flags.match === "one") { - return hits === 1 ? { value: matched } : { errors: error2("alternatives.one") }; - } - return hits === schema.$_terms.matches.length ? { value } : { errors: error2("alternatives.all") }; - } - const errors = []; - for (let i2 = 0; i2 < schema.$_terms.matches.length; ++i2) { - const item = schema.$_terms.matches[i2]; - if (item.schema) { - const localState = state.nest(item.schema, `match.${i2}`); - localState.snapshot(); - const result = item.schema.$_validate(value, localState, prefs); - if (!result.errors) { - return result; - } - localState.restore(); - errors.push({ schema: item.schema, reports: result.errors }); - continue; - } - const input = item.ref ? item.ref.resolve(value, state, prefs) : value; - const tests = item.is ? [item] : item.switch; - for (let j = 0; j < tests.length; ++j) { - const test = tests[j]; - const { is, then, otherwise } = test; - const id = `match.${i2}${item.switch ? "." + j : ""}`; - if (!is.$_match(input, state.nest(is, `${id}.is`), prefs)) { - if (otherwise) { - return otherwise.$_validate(value, state.nest(otherwise, `${id}.otherwise`), prefs); - } - } else if (then) { - return then.$_validate(value, state.nest(then, `${id}.then`), prefs); - } - } - } - return internals.errors(errors, helpers); - }, - rules: { - conditional: { - method(condition, options2) { - Assert(!this._flags._endedSwitch, "Unreachable condition"); - Assert(!this._flags.match, "Cannot combine match mode", this._flags.match, "with conditional rule"); - Assert(options2.break === void 0, "Cannot use break option with alternatives conditional"); - const obj = this.clone(); - const match = Compile.when(obj, condition, options2); - const conditions = match.is ? [match] : match.switch; - for (const item of conditions) { - if (item.then && item.otherwise) { - obj.$_setFlag("_endedSwitch", true, { clone: false }); - break; - } - } - obj.$_terms.matches.push(match); - return obj.$_mutateRebuild(); - } - }, - match: { - method(mode) { - Assert(["any", "one", "all"].includes(mode), "Invalid alternatives match mode", mode); - if (mode !== "any") { - for (const match of this.$_terms.matches) { - Assert(match.schema, "Cannot combine match mode", mode, "with conditional rules"); - } - } - return this.$_setFlag("match", mode); - } - }, - try: { - method(...schemas) { - Assert(schemas.length, "Missing alternative schemas"); - Common.verifyFlat(schemas, "try"); - Assert(!this._flags._endedSwitch, "Unreachable condition"); - const obj = this.clone(); - for (const schema of schemas) { - obj.$_terms.matches.push({ schema: obj.$_compile(schema) }); - } - return obj.$_mutateRebuild(); - } - } - }, - rebuild(schema) { - const each = (item) => { - if (Common.isSchema(item) && item.type === "array") { - schema.$_setFlag("_arrayItems", true, { clone: false }); - } - }; - schema.$_modify({ each }); - }, - messages: { - "alternatives.all": "{{#label}} does not match all of the required types", - "alternatives.any": "{{#label}} does not match any of the allowed types", - "alternatives.match": "{{#label}} does not match any of the allowed types", - "alternatives.one": "{{#label}} matches more than one allowed type", - "alternatives.types": "{{#label}} must be one of {{#types}}" - } - }); - internals.errors = function(failures, { error: error2, state }) { - if (!failures.length) { - return { errors: error2("alternatives.any") }; - } - if (failures.length === 1) { - return { errors: failures[0].reports }; - } - const valids = /* @__PURE__ */ new Set(); - const complex = []; - for (const { reports, schema } of failures) { - if (reports.length > 1) { - return internals.unmatched(failures, error2); - } - const report = reports[0]; - if (report instanceof Errors.Report === false) { - return internals.unmatched(failures, error2); - } - if (report.state.path.length !== state.path.length) { - complex.push({ type: schema.type, report }); - continue; - } - if (report.code === "any.only") { - for (const valid of report.local.valids) { - valids.add(valid); - } - continue; - } - const [type, code2] = report.code.split("."); - if (code2 !== "base") { - complex.push({ type: schema.type, report }); - continue; - } - valids.add(type); - } - if (!complex.length) { - return { errors: error2("alternatives.types", { types: [...valids] }) }; - } - if (complex.length === 1) { - return { errors: complex[0].report }; - } - return internals.unmatched(failures, error2); - }; - internals.unmatched = function(failures, error2) { - const errors = []; - for (const failure of failures) { - errors.push(...failure.reports); - } - return { errors: error2("alternatives.match", Errors.details(errors, { override: false })) }; - }; - } -}); -var require_array = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/array.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var DeepEqual = require_deepEqual(); - var Reach = require_reach(); - var Any = require_any(); - var Common = require_common2(); - var Compile = require_compile(); - var internals = {}; - module14.exports = Any._extend({ - type: "array", - flags: { - single: { default: false }, - sparse: { default: false } - }, - terms: { - items: { init: [] }, - ordered: { init: [] }, - _exclusions: { init: [] }, - _inclusions: { init: [] }, - _requireds: { init: [] } - }, - coerce: { - from: "object", - method(value, { schema, state, prefs }) { - if (!Array.isArray(value)) { - return; - } - const sort = schema.$_getRule("sort"); - if (!sort) { - return; - } - return internals.sort(schema, value, sort.args.options, state, prefs); - } - }, - validate(value, { schema, error: error2 }) { - if (!Array.isArray(value)) { - if (schema._flags.single) { - const single = [value]; - single[Common.symbols.arraySingle] = true; - return { value: single }; - } - return { errors: error2("array.base") }; - } - if (!schema.$_getRule("items")) { - return; - } - return { value: value.slice() }; - }, - rules: { - has: { - method(schema) { - schema = this.$_compile(schema, { appendPath: true }); - const obj = this.$_addRule({ name: "has", args: { schema } }); - obj.$_mutateRegister(schema); - return obj; - }, - validate(value, { state, prefs, error: error2 }, { schema: has2 }) { - const ancestors = [value, ...state.ancestors]; - for (let i2 = 0; i2 < value.length; ++i2) { - const localState = state.localize([...state.path, i2], ancestors, has2); - if (has2.$_match(value[i2], localState, prefs)) { - return value; - } - } - return error2("array.hasUnknown", null); - }, - multi: true - }, - items: { - method(...schemas) { - Common.verifyFlat(schemas, "items"); - const obj = this.$_addRule("items"); - for (let i2 = 0; i2 < schemas.length; ++i2) { - const type = Common.tryWithPath(() => this.$_compile(schemas[i2]), i2, { append: true }); - obj.$_terms.items.push(type); - } - return obj.$_mutateRebuild(); - }, - validate(value, { schema, error: error2, state, prefs, errorsArray }) { - const requireds = schema.$_terms._requireds.slice(); - const ordereds = schema.$_terms.ordered.slice(); - const inclusions = [...schema.$_terms._inclusions, ...requireds]; - const wasArray = !value[Common.symbols.arraySingle]; - delete value[Common.symbols.arraySingle]; - const errors = errorsArray(); - let il = value.length; - for (let i2 = 0; i2 < il; ++i2) { - const item = value[i2]; - let errored = false; - let isValid = false; - const key = wasArray ? i2 : new Number(i2); - const path8 = [...state.path, key]; - if (!schema._flags.sparse && item === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - ordereds.shift(); - continue; - } - const ancestors = [value, ...state.ancestors]; - for (const exclusion of schema.$_terms._exclusions) { - if (!exclusion.$_match(item, state.localize(path8, ancestors, exclusion), prefs, { presence: "ignore" })) { - continue; - } - errors.push(error2("array.excludes", { pos: i2, value: item }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - errored = true; - ordereds.shift(); - break; - } - if (errored) { - continue; - } - if (schema.$_terms.ordered.length) { - if (ordereds.length) { - const ordered = ordereds.shift(); - const res = ordered.$_validate(item, state.localize(path8, ancestors, ordered), prefs); - if (!res.errors) { - if (ordered._flags.result === "strip") { - internals.fastSplice(value, i2); - --i2; - --il; - } else if (!schema._flags.sparse && res.value === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - continue; - } else { - value[i2] = res.value; - } - } else { - errors.push(...res.errors); - if (prefs.abortEarly) { - return errors; - } - } - continue; - } else if (!schema.$_terms.items.length) { - errors.push(error2("array.orderedLength", { pos: i2, limit: schema.$_terms.ordered.length })); - if (prefs.abortEarly) { - return errors; - } - break; - } - } - const requiredChecks = []; - let jl = requireds.length; - for (let j = 0; j < jl; ++j) { - const localState = state.localize(path8, ancestors, requireds[j]); - localState.snapshot(); - const res = requireds[j].$_validate(item, localState, prefs); - requiredChecks[j] = res; - if (!res.errors) { - value[i2] = res.value; - isValid = true; - internals.fastSplice(requireds, j); - --j; - --jl; - if (!schema._flags.sparse && res.value === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - } - break; - } - localState.restore(); - } - if (isValid) { - continue; - } - const stripUnknown = prefs.stripUnknown && !!prefs.stripUnknown.arrays || false; - jl = inclusions.length; - for (const inclusion of inclusions) { - let res; - const previousCheck = requireds.indexOf(inclusion); - if (previousCheck !== -1) { - res = requiredChecks[previousCheck]; - } else { - const localState = state.localize(path8, ancestors, inclusion); - localState.snapshot(); - res = inclusion.$_validate(item, localState, prefs); - if (!res.errors) { - if (inclusion._flags.result === "strip") { - internals.fastSplice(value, i2); - --i2; - --il; - } else if (!schema._flags.sparse && res.value === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - errored = true; - } else { - value[i2] = res.value; - } - isValid = true; - break; - } - localState.restore(); - } - if (jl === 1) { - if (stripUnknown) { - internals.fastSplice(value, i2); - --i2; - --il; - isValid = true; - break; - } - errors.push(...res.errors); - if (prefs.abortEarly) { - return errors; - } - errored = true; - break; - } - } - if (errored) { - continue; - } - if (schema.$_terms._inclusions.length && !isValid) { - if (stripUnknown) { - internals.fastSplice(value, i2); - --i2; - --il; - continue; - } - errors.push(error2("array.includes", { pos: i2, value: item }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - } - } - if (requireds.length) { - internals.fillMissedErrors(schema, errors, requireds, value, state, prefs); - } - if (ordereds.length) { - internals.fillOrderedErrors(schema, errors, ordereds, value, state, prefs); - } - return errors.length ? errors : value; - }, - priority: true - }, - length: { - method(limit) { - return this.$_addRule({ name: "length", args: { limit }, operator: "=" }); - }, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(value.length, limit, operator)) { - return value; - } - return helpers.error("array." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - } - ] - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "length", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "length", args: { limit }, operator: ">=" }); - } - }, - ordered: { - method(...schemas) { - Common.verifyFlat(schemas, "ordered"); - const obj = this.$_addRule("items"); - for (let i2 = 0; i2 < schemas.length; ++i2) { - const type = Common.tryWithPath(() => this.$_compile(schemas[i2]), i2, { append: true }); - internals.validateSingle(type, obj); - obj.$_mutateRegister(type); - obj.$_terms.ordered.push(type); - } - return obj.$_mutateRebuild(); - } - }, - single: { - method(enabled2) { - const value = enabled2 === void 0 ? true : !!enabled2; - Assert(!value || !this._flags._arrayItems, "Cannot specify single rule when array has array items"); - return this.$_setFlag("single", value); - } - }, - sort: { - method(options2 = {}) { - Common.assertOptions(options2, ["by", "order"]); - const settings = { - order: options2.order || "ascending" - }; - if (options2.by) { - settings.by = Compile.ref(options2.by, { ancestor: 0 }); - Assert(!settings.by.ancestor, "Cannot sort by ancestor"); - } - return this.$_addRule({ name: "sort", args: { options: settings } }); - }, - validate(value, { error: error2, state, prefs, schema }, { options: options2 }) { - const { value: sorted, errors } = internals.sort(schema, value, options2, state, prefs); - if (errors) { - return errors; - } - for (let i2 = 0; i2 < value.length; ++i2) { - if (value[i2] !== sorted[i2]) { - return error2("array.sort", { order: options2.order, by: options2.by ? options2.by.key : "value" }); - } - } - return value; - }, - convert: true - }, - sparse: { - method(enabled2) { - const value = enabled2 === void 0 ? true : !!enabled2; - if (this._flags.sparse === value) { - return this; - } - const obj = value ? this.clone() : this.$_addRule("items"); - return obj.$_setFlag("sparse", value, { clone: false }); - } - }, - unique: { - method(comparator, options2 = {}) { - Assert(!comparator || typeof comparator === "function" || typeof comparator === "string", "comparator must be a function or a string"); - Common.assertOptions(options2, ["ignoreUndefined", "separator"]); - const rule = { name: "unique", args: { options: options2, comparator } }; - if (comparator) { - if (typeof comparator === "string") { - const separator = Common.default(options2.separator, "."); - rule.path = separator ? comparator.split(separator) : [comparator]; - } else { - rule.comparator = comparator; - } - } - return this.$_addRule(rule); - }, - validate(value, { state, error: error2, schema }, { comparator: raw, options: options2 }, { comparator, path: path8 }) { - const found = { - string: /* @__PURE__ */ Object.create(null), - number: /* @__PURE__ */ Object.create(null), - undefined: /* @__PURE__ */ Object.create(null), - boolean: /* @__PURE__ */ Object.create(null), - object: /* @__PURE__ */ new Map(), - function: /* @__PURE__ */ new Map(), - custom: /* @__PURE__ */ new Map() - }; - const compare = comparator || DeepEqual; - const ignoreUndefined = options2.ignoreUndefined; - for (let i2 = 0; i2 < value.length; ++i2) { - const item = path8 ? Reach(value[i2], path8) : value[i2]; - const records = comparator ? found.custom : found[typeof item]; - Assert(records, "Failed to find unique map container for type", typeof item); - if (records instanceof Map) { - const entries = records.entries(); - let current; - while (!(current = entries.next()).done) { - if (compare(current.value[0], item)) { - const localState = state.localize([...state.path, i2], [value, ...state.ancestors]); - const context = { - pos: i2, - value: value[i2], - dupePos: current.value[1], - dupeValue: value[current.value[1]] - }; - if (path8) { - context.path = raw; - } - return error2("array.unique", context, localState); - } - } - records.set(item, i2); - } else { - if ((!ignoreUndefined || item !== void 0) && records[item] !== void 0) { - const context = { - pos: i2, - value: value[i2], - dupePos: records[item], - dupeValue: value[records[item]] - }; - if (path8) { - context.path = raw; - } - const localState = state.localize([...state.path, i2], [value, ...state.ancestors]); - return error2("array.unique", context, localState); - } - records[item] = i2; - } - } - return value; - }, - args: ["comparator", "options"], - multi: true - } - }, - cast: { - set: { - from: Array.isArray, - to(value, helpers) { - return new Set(value); - } - } - }, - rebuild(schema) { - schema.$_terms._inclusions = []; - schema.$_terms._exclusions = []; - schema.$_terms._requireds = []; - for (const type of schema.$_terms.items) { - internals.validateSingle(type, schema); - if (type._flags.presence === "required") { - schema.$_terms._requireds.push(type); - } else if (type._flags.presence === "forbidden") { - schema.$_terms._exclusions.push(type); - } else { - schema.$_terms._inclusions.push(type); - } - } - for (const type of schema.$_terms.ordered) { - internals.validateSingle(type, schema); - } - }, - messages: { - "array.base": "{{#label}} must be an array", - "array.excludes": "{{#label}} contains an excluded value", - "array.hasUnknown": "{{#label}} does not contain at least one required match", - "array.includes": "{{#label}} does not match any of the allowed types", - "array.includesRequiredBoth": "{{#label}} does not contain {{#knownMisses}} and {{#unknownMisses}} other required value(s)", - "array.includesRequiredKnowns": "{{#label}} does not contain {{#knownMisses}}", - "array.includesRequiredUnknowns": "{{#label}} does not contain {{#unknownMisses}} required value(s)", - "array.length": "{{#label}} must contain {{#limit}} items", - "array.max": "{{#label}} must contain less than or equal to {{#limit}} items", - "array.min": "{{#label}} must contain at least {{#limit}} items", - "array.orderedLength": "{{#label}} must contain at most {{#limit}} items", - "array.sort": "{{#label}} must be sorted in {#order} order by {{#by}}", - "array.sort.mismatching": "{{#label}} cannot be sorted due to mismatching types", - "array.sort.unsupported": "{{#label}} cannot be sorted due to unsupported type {#type}", - "array.sparse": "{{#label}} must not be a sparse array item", - "array.unique": "{{#label}} contains a duplicate value" - } - }); - internals.fillMissedErrors = function(schema, errors, requireds, value, state, prefs) { - let unknownMisses = 0; - for (let i2 = 0; i2 < requireds.length; ++i2) { - ++unknownMisses; - } - errors.push(schema.$_createError("array.includesRequiredUnknowns", value, { unknownMisses }, state, prefs)); - }; - internals.fillOrderedErrors = function(schema, errors, ordereds, value, state, prefs) { - const requiredOrdereds = []; - for (const ordered of ordereds) { - if (ordered._flags.presence === "required") { - requiredOrdereds.push(ordered); - } - } - if (requiredOrdereds.length) { - internals.fillMissedErrors(schema, errors, requiredOrdereds, value, state, prefs); - } - }; - internals.fastSplice = function(arr, i2) { - let pos = i2; - while (pos < arr.length) { - arr[pos++] = arr[pos]; - } - --arr.length; - }; - internals.validateSingle = function(type, obj) { - if (type.type === "array" || type._flags._arrayItems) { - Assert(!obj._flags.single, "Cannot specify array item with single rule enabled"); - obj.$_setFlag("_arrayItems", true, { clone: false }); - } - }; - internals.sort = function(schema, value, settings, state, prefs) { - const order = settings.order === "ascending" ? 1 : -1; - const aFirst = -1 * order; - const bFirst = order; - const sort = (a, b) => { - let compare = internals.compare(a, b, aFirst, bFirst); - if (compare !== null) { - return compare; - } - if (settings.by) { - a = settings.by.resolve(a, state, prefs); - b = settings.by.resolve(b, state, prefs); - } - compare = internals.compare(a, b, aFirst, bFirst); - if (compare !== null) { - return compare; - } - const type = typeof a; - if (type !== typeof b) { - throw schema.$_createError("array.sort.mismatching", value, null, state, prefs); - } - if (type !== "number" && type !== "string") { - throw schema.$_createError("array.sort.unsupported", value, { type }, state, prefs); - } - if (type === "number") { - return (a - b) * order; - } - return a < b ? aFirst : bFirst; - }; - try { - return { value: value.slice().sort(sort) }; - } catch (err) { - return { errors: err }; - } - }; - internals.compare = function(a, b, aFirst, bFirst) { - if (a === b) { - return 0; - } - if (a === void 0) { - return 1; - } - if (b === void 0) { - return -1; - } - if (a === null) { - return bFirst; - } - if (b === null) { - return aFirst; - } - return null; - }; - } -}); -var require_boolean = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/boolean.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Any = require_any(); - var Common = require_common2(); - var Values = require_values(); - var internals = {}; - internals.isBool = function(value) { - return typeof value === "boolean"; - }; - module14.exports = Any._extend({ - type: "boolean", - flags: { - sensitive: { default: false } - }, - terms: { - falsy: { - init: null - }, - truthy: { - init: null - } - }, - coerce(value, { schema }) { - if (typeof value === "boolean") { - return; - } - if (typeof value === "string") { - const normalized = schema._flags.sensitive ? value : value.toLowerCase(); - value = normalized === "true" ? true : normalized === "false" ? false : value; - } - if (typeof value !== "boolean") { - value = schema.$_terms.truthy?.has(value, null, null, !schema._flags.sensitive) || (schema.$_terms.falsy?.has(value, null, null, !schema._flags.sensitive) ? false : value); - } - return { value }; - }, - validate(value, { error: error2 }) { - if (typeof value !== "boolean") { - return { value, errors: error2("boolean.base") }; - } - }, - rules: { - truthy: { - method(...values) { - Common.verifyFlat(values, "truthy"); - const obj = this.clone(); - obj.$_terms.truthy = obj.$_terms.truthy || new Values(); - for (let i2 = 0; i2 < values.length; ++i2) { - const value = values[i2]; - Assert(value !== void 0, "Cannot call truthy with undefined"); - obj.$_terms.truthy.add(value); - } - return obj; - } - }, - falsy: { - method(...values) { - Common.verifyFlat(values, "falsy"); - const obj = this.clone(); - obj.$_terms.falsy = obj.$_terms.falsy || new Values(); - for (let i2 = 0; i2 < values.length; ++i2) { - const value = values[i2]; - Assert(value !== void 0, "Cannot call falsy with undefined"); - obj.$_terms.falsy.add(value); - } - return obj; - } - }, - sensitive: { - method(enabled2 = true) { - return this.$_setFlag("sensitive", enabled2); - } - } - }, - cast: { - number: { - from: internals.isBool, - to(value, helpers) { - return value ? 1 : 0; - } - }, - string: { - from: internals.isBool, - to(value, helpers) { - return value ? "true" : "false"; - } - } - }, - messages: { - "boolean.base": "{{#label}} must be a boolean" - } - }); - } -}); -var require_date = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/date.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Any = require_any(); - var Common = require_common2(); - var Template = require_template(); - var internals = {}; - internals.isDate = function(value) { - return value instanceof Date; - }; - module14.exports = Any._extend({ - type: "date", - coerce: { - from: ["number", "string"], - method(value, { schema }) { - return { value: internals.parse(value, schema._flags.format) || value }; - } - }, - validate(value, { schema, error: error2, prefs }) { - if (value instanceof Date && !isNaN(value.getTime())) { - return; - } - const format52 = schema._flags.format; - if (!prefs.convert || !format52 || typeof value !== "string") { - return { value, errors: error2("date.base") }; - } - return { value, errors: error2("date.format", { format: format52 }) }; - }, - rules: { - compare: { - method: false, - validate(value, helpers, { date: date3 }, { name, operator, args }) { - const to = date3 === "now" ? Date.now() : date3.getTime(); - if (Common.compare(value.getTime(), to, operator)) { - return value; - } - return helpers.error("date." + name, { limit: args.date, value }); - }, - args: [ - { - name: "date", - ref: true, - normalize: (date3) => { - return date3 === "now" ? date3 : internals.parse(date3); - }, - assert: (date3) => date3 !== null, - message: "must have a valid date format" - } - ] - }, - format: { - method(format52) { - Assert(["iso", "javascript", "unix"].includes(format52), "Unknown date format", format52); - return this.$_setFlag("format", format52); - } - }, - greater: { - method(date3) { - return this.$_addRule({ name: "greater", method: "compare", args: { date: date3 }, operator: ">" }); - } - }, - iso: { - method() { - return this.format("iso"); - } - }, - less: { - method(date3) { - return this.$_addRule({ name: "less", method: "compare", args: { date: date3 }, operator: "<" }); - } - }, - max: { - method(date3) { - return this.$_addRule({ name: "max", method: "compare", args: { date: date3 }, operator: "<=" }); - } - }, - min: { - method(date3) { - return this.$_addRule({ name: "min", method: "compare", args: { date: date3 }, operator: ">=" }); - } - }, - timestamp: { - method(type = "javascript") { - Assert(["javascript", "unix"].includes(type), '"type" must be one of "javascript, unix"'); - return this.format(type); - } - } - }, - cast: { - number: { - from: internals.isDate, - to(value, helpers) { - return value.getTime(); - } - }, - string: { - from: internals.isDate, - to(value, { prefs }) { - return Template.date(value, prefs); - } - } - }, - messages: { - "date.base": "{{#label}} must be a valid date", - "date.format": "{{#label}} must be in {{#format}} format", - "date.greater": "{{#label}} must be greater than {{:#limit}}", - "date.less": "{{#label}} must be less than {{:#limit}}", - "date.max": "{{#label}} must be less than or equal to {{:#limit}}", - "date.min": "{{#label}} must be greater than or equal to {{:#limit}}" - } - }); - internals.parse = function(value, format52) { - if (value instanceof Date) { - return value; - } - if (typeof value !== "string" && (isNaN(value) || !isFinite(value))) { - return null; - } - if (/^\s*$/.test(value)) { - return null; - } - if (format52 === "iso") { - if (!Common.isIsoDate(value)) { - return null; - } - return internals.date(value.toString()); - } - const original = value; - if (typeof value === "string" && /^[+-]?\d+(\.\d+)?$/.test(value)) { - value = parseFloat(value); - } - if (format52) { - if (format52 === "javascript") { - return internals.date(1 * value); - } - if (format52 === "unix") { - return internals.date(1e3 * value); - } - if (typeof original === "string") { - return null; - } - } - return internals.date(value); - }; - internals.date = function(value) { - const date3 = new Date(value); - if (!isNaN(date3.getTime())) { - return date3; - } - return null; - }; - } -}); -var require_lib8 = __commonJS({ - "node_modules/.deno/@hapi+topo@6.0.2/node_modules/@hapi/topo/lib/index.js"(exports2) { - "use strict"; - var { assert: assert2 } = require_lib(); - var internals = {}; - exports2.Sorter = class { - constructor() { - this._items = []; - this.nodes = []; - } - add(nodes, options2) { - options2 = options2 ?? {}; - const before = [].concat(options2.before ?? []); - const after = [].concat(options2.after ?? []); - const group = options2.group ?? "?"; - const sort = options2.sort ?? 0; - assert2(!before.includes(group), `Item cannot come before itself: ${group}`); - assert2(!before.includes("?"), "Item cannot come before unassociated items"); - assert2(!after.includes(group), `Item cannot come after itself: ${group}`); - assert2(!after.includes("?"), "Item cannot come after unassociated items"); - if (!Array.isArray(nodes)) { - nodes = [nodes]; - } - for (const node of nodes) { - const item = { - seq: this._items.length, - sort, - before, - after, - group, - node - }; - this._items.push(item); - } - if (!options2.manual) { - const valid = this._sort(); - assert2(valid, "item", group !== "?" ? `added into group ${group}` : "", "created a dependencies error"); - } - return this.nodes; - } - merge(others) { - if (!Array.isArray(others)) { - others = [others]; - } - for (const other of others) { - if (other) { - for (const item of other._items) { - this._items.push(Object.assign({}, item)); - } - } - } - this._items.sort(internals.mergeSort); - for (let i2 = 0; i2 < this._items.length; ++i2) { - this._items[i2].seq = i2; - } - const valid = this._sort(); - assert2(valid, "merge created a dependencies error"); - return this.nodes; - } - sort() { - const valid = this._sort(); - assert2(valid, "sort created a dependencies error"); - return this.nodes; - } - _sort() { - const graph = {}; - const graphAfters = /* @__PURE__ */ Object.create(null); - const groups = /* @__PURE__ */ Object.create(null); - for (const item of this._items) { - const seq = item.seq; - const group = item.group; - groups[group] = groups[group] ?? []; - groups[group].push(seq); - graph[seq] = item.before; - for (const after of item.after) { - graphAfters[after] = graphAfters[after] ?? []; - graphAfters[after].push(seq); - } - } - for (const node in graph) { - const expandedGroups = []; - for (const graphNodeItem in graph[node]) { - const group = graph[node][graphNodeItem]; - groups[group] = groups[group] ?? []; - expandedGroups.push(...groups[group]); - } - graph[node] = expandedGroups; - } - for (const group in graphAfters) { - if (groups[group]) { - for (const node of groups[group]) { - graph[node].push(...graphAfters[group]); - } - } - } - const ancestors = {}; - for (const node in graph) { - const children = graph[node]; - for (const child of children) { - ancestors[child] = ancestors[child] ?? []; - ancestors[child].push(node); - } - } - const visited = {}; - const sorted = []; - for (let i2 = 0; i2 < this._items.length; ++i2) { - let next = i2; - if (ancestors[i2]) { - next = null; - for (let j = 0; j < this._items.length; ++j) { - if (visited[j] === true) { - continue; - } - if (!ancestors[j]) { - ancestors[j] = []; - } - const shouldSeeCount = ancestors[j].length; - let seenCount = 0; - for (let k = 0; k < shouldSeeCount; ++k) { - if (visited[ancestors[j][k]]) { - ++seenCount; - } - } - if (seenCount === shouldSeeCount) { - next = j; - break; - } - } - } - if (next !== null) { - visited[next] = true; - sorted.push(next); - } - } - if (sorted.length !== this._items.length) { - return false; - } - const seqIndex = {}; - for (const item of this._items) { - seqIndex[item.seq] = item; - } - this._items = []; - this.nodes = []; - for (const value of sorted) { - const sortedItem = seqIndex[value]; - this.nodes.push(sortedItem.node); - this._items.push(sortedItem); - } - return true; - } - }; - internals.mergeSort = (a, b) => { - return a.sort === b.sort ? 0 : a.sort < b.sort ? -1 : 1; - }; - } -}); -var require_keys = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/keys.js"(exports2, module14) { - "use strict"; - var ApplyToDefaults = require_applyToDefaults(); - var Assert = require_assert(); - var Clone = require_clone(); - var Topo = require_lib8(); - var Any = require_any(); - var Common = require_common2(); - var Compile = require_compile(); - var Errors = require_errors2(); - var Ref = require_ref(); - var internals = { - renameDefaults: { - alias: false, - // Keep old value in place - multiple: false, - // Allow renaming multiple keys into the same target - override: false - // Overrides an existing key - } - }; - module14.exports = Any._extend({ - type: "_keys", - properties: { - typeof: "object" - }, - flags: { - unknown: { default: false } - }, - terms: { - dependencies: { init: null }, - keys: { init: null }, - patterns: { init: null }, - renames: { init: null } - }, - args(schema, keys) { - return schema.keys(keys); - }, - validate(value, { schema, error: error2, state, prefs }) { - if (!value || typeof value !== schema.$_property("typeof") || Array.isArray(value)) { - return { value, errors: error2("object.base", { type: schema.$_property("typeof") }) }; - } - if (!schema.$_terms.renames && !schema.$_terms.dependencies && !schema.$_terms.keys && // null allows any keys - !schema.$_terms.patterns) { - return; - } - value = internals.clone(value, prefs); - const errors = []; - if (schema.$_terms.renames && !internals.rename(schema, value, state, prefs, errors)) { - return { value, errors }; - } - if (!schema.$_terms.keys && // null allows any keys - !schema.$_terms.patterns && !schema.$_terms.dependencies) { - return { value, errors }; - } - const unprocessed = new Set(Object.keys(value)); - if (schema.$_terms.keys) { - const ancestors = [value, ...state.ancestors]; - for (const child of schema.$_terms.keys) { - const key = child.key; - const item = value[key]; - unprocessed.delete(key); - const localState = state.localize([...state.path, key], ancestors, child); - const result = child.schema.$_validate(item, localState, prefs); - if (result.errors) { - if (prefs.abortEarly) { - return { value, errors: result.errors }; - } - errors.push(...result.errors); - } else if (child.schema._flags.result === "strip" || result.value === void 0 && item !== void 0) { - delete value[key]; - } else if (result.value !== void 0) { - value[key] = result.value; - } - } - } - if (unprocessed.size || schema._flags._hasPatternMatch) { - const early = internals.unknown(schema, value, unprocessed, errors, state, prefs); - if (early) { - return early; - } - } - if (schema.$_terms.dependencies) { - for (const dep of schema.$_terms.dependencies) { - if (dep.key && dep.key.resolve(value, state, prefs, null, { shadow: false }) === void 0) { - continue; - } - const failed = internals.dependencies[dep.rel](schema, dep, value, state, prefs); - if (failed) { - const report = schema.$_createError(failed.code, value, failed.context, state, prefs); - if (prefs.abortEarly) { - return { value, errors: report }; - } - errors.push(report); - } - } - } - return { value, errors }; - }, - rules: { - and: { - method(...peers) { - Common.verifyFlat(peers, "and"); - return internals.dependency(this, "and", null, peers); - } - }, - append: { - method(schema) { - if (schema === null || schema === void 0 || Object.keys(schema).length === 0) { - return this; - } - return this.keys(schema); - } - }, - assert: { - method(subject, schema, message) { - subject = Compile.ref(subject); - Assert(message === void 0 || typeof message === "string", "Message must be a string"); - schema = this.$_compile(schema, { appendPath: true }); - const obj = this.$_addRule({ name: "assert", args: { subject, schema, message } }); - obj.$_mutateRegister(subject); - obj.$_mutateRegister(schema); - return obj; - }, - validate(value, { error: error2, prefs, state }, { subject, schema, message }) { - const about = subject.resolve(value, state, prefs); - const path8 = subject.absolute(state); - if (schema.$_match(about, state.localize(path8, [value, ...state.ancestors], schema), prefs)) { - return value; - } - return error2("object.assert", { subject, message }); - }, - args: ["subject", "schema", "message"], - multi: true - }, - instance: { - method(constructor, name) { - Assert(typeof constructor === "function", "constructor must be a function"); - name = name || constructor.name; - return this.$_addRule({ name: "instance", args: { constructor, name } }); - }, - validate(value, helpers, { constructor, name }) { - if (value instanceof constructor) { - return value; - } - return helpers.error("object.instance", { type: name, value }); - }, - args: ["constructor", "name"] - }, - keys: { - method(schema) { - Assert(schema === void 0 || typeof schema === "object", "Object schema must be a valid object"); - Assert(!Common.isSchema(schema), "Object schema cannot be a joi schema"); - const obj = this.clone(); - if (!schema) { - obj.$_terms.keys = null; - } else if (!Object.keys(schema).length) { - obj.$_terms.keys = new internals.Keys(); - } else { - obj.$_terms.keys = obj.$_terms.keys ? obj.$_terms.keys.filter((child) => !schema.hasOwnProperty(child.key)) : new internals.Keys(); - for (const key in schema) { - Common.tryWithPath(() => obj.$_terms.keys.push({ key, schema: this.$_compile(schema[key]) }), key); - } - } - return obj.$_mutateRebuild(); - } - }, - length: { - method(limit) { - return this.$_addRule({ name: "length", args: { limit }, operator: "=" }); - }, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(Object.keys(value).length, limit, operator)) { - return value; - } - return helpers.error("object." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - } - ] - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "length", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "length", args: { limit }, operator: ">=" }); - } - }, - nand: { - method(...peers) { - Common.verifyFlat(peers, "nand"); - return internals.dependency(this, "nand", null, peers); - } - }, - or: { - method(...peers) { - Common.verifyFlat(peers, "or"); - return internals.dependency(this, "or", null, peers); - } - }, - oxor: { - method(...peers) { - return internals.dependency(this, "oxor", null, peers); - } - }, - pattern: { - method(pattern, schema, options2 = {}) { - const isRegExp = pattern instanceof RegExp; - if (!isRegExp) { - pattern = this.$_compile(pattern, { appendPath: true }); - } - Assert(schema !== void 0, "Invalid rule"); - Common.assertOptions(options2, ["fallthrough", "matches"]); - if (isRegExp) { - Assert(!pattern.flags.includes("g") && !pattern.flags.includes("y"), "pattern should not use global or sticky mode"); - } - schema = this.$_compile(schema, { appendPath: true }); - const obj = this.clone(); - obj.$_terms.patterns = obj.$_terms.patterns || []; - const config2 = { [isRegExp ? "regex" : "schema"]: pattern, rule: schema }; - if (options2.matches) { - config2.matches = this.$_compile(options2.matches); - if (config2.matches.type !== "array") { - config2.matches = config2.matches.$_root.array().items(config2.matches); - } - obj.$_mutateRegister(config2.matches); - obj.$_setFlag("_hasPatternMatch", true, { clone: false }); - } - if (options2.fallthrough) { - config2.fallthrough = true; - } - obj.$_terms.patterns.push(config2); - obj.$_mutateRegister(schema); - return obj; - } - }, - ref: { - method() { - return this.$_addRule("ref"); - }, - validate(value, helpers) { - if (Ref.isRef(value)) { - return value; - } - return helpers.error("object.refType", { value }); - } - }, - regex: { - method() { - return this.$_addRule("regex"); - }, - validate(value, helpers) { - if (value instanceof RegExp) { - return value; - } - return helpers.error("object.regex", { value }); - } - }, - rename: { - method(from3, to, options2 = {}) { - Assert(typeof from3 === "string" || from3 instanceof RegExp, "Rename missing the from argument"); - Assert(typeof to === "string", "Invalid rename to argument"); - Assert(to !== from3, "Cannot rename key to same name:", from3); - Common.assertOptions(options2, ["alias", "ignoreUndefined", "override", "multiple"]); - const obj = this.clone(); - obj.$_terms.renames = obj.$_terms.renames || []; - for (const rename of obj.$_terms.renames) { - Assert(rename.from !== from3, "Cannot rename the same key multiple times"); - } - obj.$_terms.renames.push({ - from: from3, - to, - options: ApplyToDefaults(internals.renameDefaults, options2) - }); - return obj; - } - }, - schema: { - method(type = "any") { - return this.$_addRule({ name: "schema", args: { type } }); - }, - validate(value, helpers, { type }) { - if (Common.isSchema(value) && (type === "any" || value.type === type)) { - return value; - } - return helpers.error("object.schema", { type }); - } - }, - unknown: { - method(allow) { - return this.$_setFlag("unknown", allow !== false); - } - }, - with: { - method(key, peers, options2 = {}) { - return internals.dependency(this, "with", key, peers, options2); - } - }, - without: { - method(key, peers, options2 = {}) { - return internals.dependency(this, "without", key, peers, options2); - } - }, - xor: { - method(...peers) { - Common.verifyFlat(peers, "xor"); - return internals.dependency(this, "xor", null, peers); - } - } - }, - overrides: { - default(value, options2) { - if (value === void 0) { - value = Common.symbols.deepDefault; - } - return this.$_parent("default", value, options2); - } - }, - rebuild(schema) { - if (schema.$_terms.keys) { - const topo = new Topo.Sorter(); - for (const child of schema.$_terms.keys) { - Common.tryWithPath(() => topo.add(child, { after: child.schema.$_rootReferences(), group: child.key }), child.key); - } - schema.$_terms.keys = new internals.Keys(...topo.nodes); - } - }, - messages: { - "object.and": "{{#label}} contains {{#present}} without its required peers {{#missing}}", - "object.assert": "{{#label}} is invalid because it failed to pass the assertion test", - "object.base": "{{#label}} must be of type {{#type}}", - "object.instance": "{{#label}} must be an instance of {{:#type}}", - "object.length": "{{#label}} must have {{#limit}} keys", - "object.max": "{{#label}} must have less than or equal to {{#limit}} keys", - "object.min": "{{#label}} must have at least {{#limit}} keys", - "object.missing": "{{#label}} must contain at least one of {{#peers}}", - "object.nand": "{{:#main}} must not exist simultaneously with {{#peers}}", - "object.oxor": "{{#label}} contains a conflict between optional exclusive peers {{#peers}}", - "object.pattern.match": "{{#label}} keys failed to match pattern requirements", - "object.refType": "{{#label}} must be a Joi reference", - "object.regex": "{{#label}} must be a RegExp object", - "object.rename.multiple": "{{#label}} cannot rename {{:#from}} because multiple renames are disabled and another key was already renamed to {{:#to}}", - "object.rename.override": "{{#label}} cannot rename {{:#from}} because override is disabled and target {{:#to}} exists", - "object.schema": "{{#label}} must be a Joi schema of {{#type}} type", - "object.unknown": "{{#label}} is not allowed", - "object.with": "{{:#main}} missing required peer {{:#peer}}", - "object.without": "{{:#main}} conflict with forbidden peer {{:#peer}}", - "object.xor": "{{#label}} contains a conflict between exclusive peers {{#peers}}" - } - }); - internals.clone = function(value, prefs) { - if (typeof value === "object") { - if (prefs.nonEnumerables) { - return Clone(value, { shallow: true }); - } - const clone3 = Object.create(Object.getPrototypeOf(value)); - Object.assign(clone3, value); - return clone3; - } - const clone2 = function(...args) { - return value.apply(this, args); - }; - clone2.prototype = Clone(value.prototype); - Object.defineProperty(clone2, "name", { value: value.name, writable: false }); - Object.defineProperty(clone2, "length", { value: value.length, writable: false }); - Object.assign(clone2, value); - return clone2; - }; - internals.dependency = function(schema, rel, key, peers, options2) { - Assert(key === null || typeof key === "string", rel, "key must be a strings"); - if (!options2) { - options2 = peers.length > 1 && typeof peers[peers.length - 1] === "object" ? peers.pop() : {}; - } - Common.assertOptions(options2, ["separator"]); - peers = [].concat(peers); - const separator = Common.default(options2.separator, "."); - const paths = []; - for (const peer of peers) { - Assert(typeof peer === "string", rel, "peers must be a string or a reference"); - paths.push(Compile.ref(peer, { separator, ancestor: 0, prefix: false })); - } - if (key !== null) { - key = Compile.ref(key, { separator, ancestor: 0, prefix: false }); - } - const obj = schema.clone(); - obj.$_terms.dependencies = obj.$_terms.dependencies || []; - obj.$_terms.dependencies.push(new internals.Dependency(rel, key, paths, peers)); - return obj; - }; - internals.dependencies = { - and(schema, dep, value, state, prefs) { - const missing = []; - const present = []; - const count = dep.peers.length; - for (const peer of dep.peers) { - if (peer.resolve(value, state, prefs, null, { shadow: false }) === void 0) { - missing.push(peer.key); - } else { - present.push(peer.key); - } - } - if (missing.length !== count && present.length !== count) { - return { - code: "object.and", - context: { - present, - missing - } - }; - } - }, - nand(schema, dep, value, state, prefs) { - const present = []; - for (const peer of dep.peers) { - if (peer.resolve(value, state, prefs, null, { shadow: false }) !== void 0) { - present.push(peer.key); - } - } - if (present.length !== dep.peers.length) { - return; - } - const main = dep.paths[0]; - const values = dep.paths.slice(1); - return { - code: "object.nand", - context: { - main, - peers: values - } - }; - }, - or(schema, dep, value, state, prefs) { - for (const peer of dep.peers) { - if (peer.resolve(value, state, prefs, null, { shadow: false }) !== void 0) { - return; - } - } - return { - code: "object.missing", - context: { - peers: dep.paths - } - }; - }, - oxor(schema, dep, value, state, prefs) { - const present = []; - for (const peer of dep.peers) { - if (peer.resolve(value, state, prefs, null, { shadow: false }) !== void 0) { - present.push(peer.key); - } - } - if (!present.length || present.length === 1) { - return; - } - const context = { peers: dep.paths }; - context.present = present; - return { code: "object.oxor", context }; - }, - with(schema, dep, value, state, prefs) { - for (const peer of dep.peers) { - if (peer.resolve(value, state, prefs, null, { shadow: false }) === void 0) { - return { - code: "object.with", - context: { - main: dep.key.key, - peer: peer.key - } - }; - } - } - }, - without(schema, dep, value, state, prefs) { - for (const peer of dep.peers) { - if (peer.resolve(value, state, prefs, null, { shadow: false }) !== void 0) { - return { - code: "object.without", - context: { - main: dep.key.key, - peer: peer.key - } - }; - } - } - }, - xor(schema, dep, value, state, prefs) { - const present = []; - for (const peer of dep.peers) { - if (peer.resolve(value, state, prefs, null, { shadow: false }) !== void 0) { - present.push(peer.key); - } - } - if (present.length === 1) { - return; - } - const context = { peers: dep.paths }; - if (present.length === 0) { - return { code: "object.missing", context }; - } - context.present = present; - return { code: "object.xor", context }; - } - }; - internals.rename = function(schema, value, state, prefs, errors) { - const renamed = {}; - for (const rename of schema.$_terms.renames) { - const matches = []; - const pattern = typeof rename.from !== "string"; - if (!pattern) { - if (Object.prototype.hasOwnProperty.call(value, rename.from) && (value[rename.from] !== void 0 || !rename.options.ignoreUndefined)) { - matches.push(rename); - } - } else { - for (const from3 in value) { - if (value[from3] === void 0 && rename.options.ignoreUndefined) { - continue; - } - if (from3 === rename.to) { - continue; - } - const match = rename.from.exec(from3); - if (!match) { - continue; - } - matches.push({ from: from3, to: rename.to, match }); - } - } - for (const match of matches) { - const from3 = match.from; - const to = match.to; - if (!rename.options.multiple && renamed[to]) { - errors.push(schema.$_createError("object.rename.multiple", value, { from: from3, to, pattern }, state, prefs)); - if (prefs.abortEarly) { - return false; - } - } - if (Object.prototype.hasOwnProperty.call(value, to) && !rename.options.override && !renamed[to]) { - errors.push(schema.$_createError("object.rename.override", value, { from: from3, to, pattern }, state, prefs)); - if (prefs.abortEarly) { - return false; - } - } - if (value[from3] === void 0) { - delete value[to]; - } else { - value[to] = value[from3]; - } - renamed[to] = true; - if (!rename.options.alias) { - delete value[from3]; - } - } - } - return true; - }; - internals.unknown = function(schema, value, unprocessed, errors, state, prefs) { - if (schema.$_terms.patterns) { - let hasMatches = false; - const matches = schema.$_terms.patterns.map((pattern) => { - if (pattern.matches) { - hasMatches = true; - return []; - } - }); - const ancestors = [value, ...state.ancestors]; - for (const key of unprocessed) { - const item = value[key]; - const path8 = [...state.path, key]; - for (let i2 = 0; i2 < schema.$_terms.patterns.length; ++i2) { - const pattern = schema.$_terms.patterns[i2]; - if (pattern.regex) { - const match = pattern.regex.test(key); - if (!match) { - continue; - } - } else { - if (!pattern.schema.$_match(key, state.nest(pattern.schema, `pattern.${i2}`), prefs)) { - continue; - } - } - unprocessed.delete(key); - const localState = state.localize(path8, ancestors, { schema: pattern.rule, key }); - const result = pattern.rule.$_validate(item, localState, prefs); - if (result.errors) { - if (prefs.abortEarly) { - return { value, errors: result.errors }; - } - errors.push(...result.errors); - } - if (pattern.matches) { - matches[i2].push(key); - } - value[key] = result.value; - if (!pattern.fallthrough) { - break; - } - } - } - if (hasMatches) { - for (let i2 = 0; i2 < matches.length; ++i2) { - const match = matches[i2]; - if (!match) { - continue; - } - const stpm = schema.$_terms.patterns[i2].matches; - const localState = state.localize(state.path, ancestors, stpm); - const result = stpm.$_validate(match, localState, prefs); - if (result.errors) { - const details = Errors.details(result.errors, { override: false }); - details.matches = match; - const report = schema.$_createError("object.pattern.match", value, details, state, prefs); - if (prefs.abortEarly) { - return { value, errors: report }; - } - errors.push(report); - } - } - } - } - if (!unprocessed.size || !schema.$_terms.keys && !schema.$_terms.patterns) { - return; - } - if (prefs.stripUnknown && !schema._flags.unknown || prefs.skipFunctions) { - const stripUnknown = prefs.stripUnknown ? prefs.stripUnknown === true ? true : !!prefs.stripUnknown.objects : false; - for (const key of unprocessed) { - if (stripUnknown) { - delete value[key]; - unprocessed.delete(key); - } else if (typeof value[key] === "function") { - unprocessed.delete(key); - } - } - } - const forbidUnknown = !Common.default(schema._flags.unknown, prefs.allowUnknown); - if (forbidUnknown) { - for (const unprocessedKey of unprocessed) { - const localState = state.localize([...state.path, unprocessedKey], []); - const report = schema.$_createError("object.unknown", value[unprocessedKey], { child: unprocessedKey }, localState, prefs, { flags: false }); - if (prefs.abortEarly) { - return { value, errors: report }; - } - errors.push(report); - } - } - }; - internals.Dependency = class { - constructor(rel, key, peers, paths) { - this.rel = rel; - this.key = key; - this.peers = peers; - this.paths = paths; - } - }; - internals.Keys = class extends Array { - concat(source) { - const result = this.slice(); - const keys = /* @__PURE__ */ new Map(); - for (let i2 = 0; i2 < result.length; ++i2) { - keys.set(result[i2].key, i2); - } - for (const item of source) { - const key = item.key; - const pos = keys.get(key); - if (pos !== void 0) { - result[pos] = { key, schema: result[pos].schema.concat(item.schema) }; - } else { - result.push(item); - } - } - return result; - } - }; - } -}); -var require_function = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/function.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Keys = require_keys(); - module14.exports = Keys._extend({ - type: "function", - properties: { - typeof: "function" - }, - rules: { - arity: { - method(n) { - Assert(Number.isSafeInteger(n) && n >= 0, "n must be a positive integer"); - return this.$_addRule({ name: "arity", args: { n } }); - }, - validate(value, helpers, { n }) { - if (value.length === n) { - return value; - } - return helpers.error("function.arity", { n }); - } - }, - class: { - method() { - return this.$_addRule("class"); - }, - validate(value, helpers) { - if (/^\s*class\s/.test(value.toString())) { - return value; - } - return helpers.error("function.class", { value }); - } - }, - minArity: { - method(n) { - Assert(Number.isSafeInteger(n) && n > 0, "n must be a strict positive integer"); - return this.$_addRule({ name: "minArity", args: { n } }); - }, - validate(value, helpers, { n }) { - if (value.length >= n) { - return value; - } - return helpers.error("function.minArity", { n }); - } - }, - maxArity: { - method(n) { - Assert(Number.isSafeInteger(n) && n >= 0, "n must be a positive integer"); - return this.$_addRule({ name: "maxArity", args: { n } }); - }, - validate(value, helpers, { n }) { - if (value.length <= n) { - return value; - } - return helpers.error("function.maxArity", { n }); - } - } - }, - messages: { - "function.arity": "{{#label}} must have an arity of {{#n}}", - "function.class": "{{#label}} must be a class", - "function.maxArity": "{{#label}} must have an arity lesser or equal to {{#n}}", - "function.minArity": "{{#label}} must have an arity greater or equal to {{#n}}" - } - }); - } -}); -var require_link = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/link.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Any = require_any(); - var Common = require_common2(); - var Compile = require_compile(); - var Errors = require_errors2(); - var internals = {}; - module14.exports = Any._extend({ - type: "link", - properties: { - schemaChain: true - }, - terms: { - link: { init: null, register: false } - }, - args(schema, ref) { - return schema.ref(ref); - }, - validate(value, { schema, state, prefs }) { - Assert(schema.$_terms.link, "Uninitialized link schema"); - const linked = internals.generate(schema, value, state, prefs); - const ref = schema.$_terms.link[0].ref; - return linked.$_validate(value, state.nest(linked, `link:${ref.display}:${linked.type}`), prefs); - }, - generate(schema, value, state, prefs) { - return internals.generate(schema, value, state, prefs); - }, - rules: { - ref: { - method(ref) { - Assert(!this.$_terms.link, "Cannot reinitialize schema"); - ref = Compile.ref(ref); - Assert(ref.type === "value" || ref.type === "local", "Invalid reference type:", ref.type); - Assert(ref.type === "local" || ref.ancestor === "root" || ref.ancestor > 0, "Link cannot reference itself"); - const obj = this.clone(); - obj.$_terms.link = [{ ref }]; - return obj; - } - }, - relative: { - method(enabled2 = true) { - return this.$_setFlag("relative", enabled2); - } - } - }, - overrides: { - concat(source) { - Assert(this.$_terms.link, "Uninitialized link schema"); - Assert(Common.isSchema(source), "Invalid schema object"); - Assert(source.type !== "link", "Cannot merge type link with another link"); - const obj = this.clone(); - if (!obj.$_terms.whens) { - obj.$_terms.whens = []; - } - obj.$_terms.whens.push({ concat: source }); - return obj.$_mutateRebuild(); - } - } - }); - internals.generate = function(schema, value, state, prefs) { - let linked = state.mainstay.links.get(schema); - if (linked) { - return linked._generate(value, state, prefs).schema; - } - const ref = schema.$_terms.link[0].ref; - const { perspective, path: path8 } = internals.perspective(ref, state); - internals.assert(perspective, "which is outside of schema boundaries", ref, schema, state, prefs); - try { - linked = path8.length ? perspective.$_reach(path8) : perspective; - } catch (ignoreErr) { - internals.assert(false, "to non-existing schema", ref, schema, state, prefs); - } - internals.assert(linked.type !== "link", "which is another link", ref, schema, state, prefs); - if (!schema._flags.relative) { - state.mainstay.links.set(schema, linked); - } - return linked._generate(value, state, prefs).schema; - }; - internals.perspective = function(ref, state) { - if (ref.type === "local") { - for (const { schema, key } of state.schemas) { - const id = schema._flags.id || key; - if (id === ref.path[0]) { - return { perspective: schema, path: ref.path.slice(1) }; - } - if (schema.$_terms.shared) { - for (const shared of schema.$_terms.shared) { - if (shared._flags.id === ref.path[0]) { - return { perspective: shared, path: ref.path.slice(1) }; - } - } - } - } - return { perspective: null, path: null }; - } - if (ref.ancestor === "root") { - return { perspective: state.schemas[state.schemas.length - 1].schema, path: ref.path }; - } - return { perspective: state.schemas[ref.ancestor]?.schema, path: ref.path }; - }; - internals.assert = function(condition, message, ref, schema, state, prefs) { - if (condition) { - return; - } - Assert(false, `"${Errors.label(schema._flags, state, prefs)}" contains link reference "${ref.display}" ${message}`); - }; - } -}); -var require_number = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/number.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Any = require_any(); - var Common = require_common2(); - var internals = { - numberRx: /^\s*[+-]?(?:(?:\d+(?:\.\d*)?)|(?:\.\d+))(?:e([+-]?\d+))?\s*$/i, - precisionRx: /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/ - }; - module14.exports = Any._extend({ - type: "number", - flags: { - unsafe: { default: false } - }, - coerce: { - from: "string", - method(value, { schema, error: error2 }) { - const matches = value.match(internals.numberRx); - if (!matches) { - return; - } - value = value.trim(); - const result = { value: parseFloat(value) }; - if (result.value === 0) { - result.value = 0; - } - if (!schema._flags.unsafe) { - if (value.match(/e/i)) { - const constructed = internals.normalizeExponent(`${result.value / Math.pow(10, matches[1])}e${matches[1]}`); - if (constructed !== internals.normalizeExponent(value)) { - result.errors = error2("number.unsafe"); - return result; - } - } else { - const string3 = result.value.toString(); - if (string3.match(/e/i)) { - return result; - } - if (string3 !== internals.normalizeDecimal(value)) { - result.errors = error2("number.unsafe"); - return result; - } - } - } - return result; - } - }, - validate(value, { schema, error: error2, prefs }) { - if (value === Infinity || value === -Infinity) { - return { value, errors: error2("number.infinity") }; - } - if (!Common.isNumber(value)) { - return { value, errors: error2("number.base") }; - } - const result = { value }; - if (prefs.convert) { - const rule = schema.$_getRule("precision"); - if (rule) { - const precision = Math.pow(10, rule.args.limit); - result.value = Math.round(result.value * precision) / precision; - } - } - if (result.value === 0) { - result.value = 0; - } - if (!schema._flags.unsafe && (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER)) { - result.errors = error2("number.unsafe"); - } - return result; - }, - rules: { - compare: { - method: false, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(value, limit, operator)) { - return value; - } - return helpers.error("number." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.isNumber, - message: "must be a number" - } - ] - }, - greater: { - method(limit) { - return this.$_addRule({ name: "greater", method: "compare", args: { limit }, operator: ">" }); - } - }, - integer: { - method() { - return this.$_addRule("integer"); - }, - validate(value, helpers) { - if (Math.trunc(value) - value === 0) { - return value; - } - return helpers.error("number.integer"); - } - }, - less: { - method(limit) { - return this.$_addRule({ name: "less", method: "compare", args: { limit }, operator: "<" }); - } - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "compare", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "compare", args: { limit }, operator: ">=" }); - } - }, - multiple: { - method(base2) { - return this.$_addRule({ name: "multiple", args: { base: base2 } }); - }, - validate(value, helpers, { base: base2 }, options2) { - if (value % base2 === 0) { - return value; - } - return helpers.error("number.multiple", { multiple: options2.args.base, value }); - }, - args: [ - { - name: "base", - ref: true, - assert: (value) => typeof value === "number" && isFinite(value) && value > 0, - message: "must be a positive number" - } - ], - multi: true - }, - negative: { - method() { - return this.sign("negative"); - } - }, - port: { - method() { - return this.$_addRule("port"); - }, - validate(value, helpers) { - if (Number.isSafeInteger(value) && value >= 0 && value <= 65535) { - return value; - } - return helpers.error("number.port"); - } - }, - positive: { - method() { - return this.sign("positive"); - } - }, - precision: { - method(limit) { - Assert(Number.isSafeInteger(limit), "limit must be an integer"); - return this.$_addRule({ name: "precision", args: { limit } }); - }, - validate(value, helpers, { limit }) { - const places = value.toString().match(internals.precisionRx); - const decimals = Math.max((places[1] ? places[1].length : 0) - (places[2] ? parseInt(places[2], 10) : 0), 0); - if (decimals <= limit) { - return value; - } - return helpers.error("number.precision", { limit, value }); - }, - convert: true - }, - sign: { - method(sign2) { - Assert(["negative", "positive"].includes(sign2), "Invalid sign", sign2); - return this.$_addRule({ name: "sign", args: { sign: sign2 } }); - }, - validate(value, helpers, { sign: sign2 }) { - if (sign2 === "negative" && value < 0 || sign2 === "positive" && value > 0) { - return value; - } - return helpers.error(`number.${sign2}`); - } - }, - unsafe: { - method(enabled2 = true) { - Assert(typeof enabled2 === "boolean", "enabled must be a boolean"); - return this.$_setFlag("unsafe", enabled2); - } - } - }, - cast: { - string: { - from: (value) => typeof value === "number", - to(value, helpers) { - return value.toString(); - } - } - }, - messages: { - "number.base": "{{#label}} must be a number", - "number.greater": "{{#label}} must be greater than {{#limit}}", - "number.infinity": "{{#label}} cannot be infinity", - "number.integer": "{{#label}} must be an integer", - "number.less": "{{#label}} must be less than {{#limit}}", - "number.max": "{{#label}} must be less than or equal to {{#limit}}", - "number.min": "{{#label}} must be greater than or equal to {{#limit}}", - "number.multiple": "{{#label}} must be a multiple of {{#multiple}}", - "number.negative": "{{#label}} must be a negative number", - "number.port": "{{#label}} must be a valid port", - "number.positive": "{{#label}} must be a positive number", - "number.precision": "{{#label}} must have no more than {{#limit}} decimal places", - "number.unsafe": "{{#label}} must be a safe number" - } - }); - internals.normalizeExponent = function(str) { - return str.replace(/E/, "e").replace(/\.(\d*[1-9])?0+e/, ".$1e").replace(/\.e/, "e").replace(/e\+/, "e").replace(/^\+/, "").replace(/^(-?)0+([1-9])/, "$1$2"); - }; - internals.normalizeDecimal = function(str) { - str = str.replace(/^\+/, "").replace(/\.0+$/, "").replace(/^(-?)\.([^\.]*)$/, "$10.$2").replace(/^(-?)0+([1-9])/, "$1$2"); - if (str.includes(".") && str.endsWith("0")) { - str = str.replace(/0+$/, ""); - } - if (str === "-0") { - return "0"; - } - return str; - }; - } -}); -var require_object = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/object.js"(exports2, module14) { - "use strict"; - var Keys = require_keys(); - module14.exports = Keys._extend({ - type: "object", - cast: { - map: { - from: (value) => value && typeof value === "object", - to(value, helpers) { - return new Map(Object.entries(value)); - } - } - } - }); - } -}); -var require_string = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/string.js"(exports2, module14) { - "use strict"; - var Url = __require2("url"); - var Assert = require_assert(); - var EscapeRegex = require_escapeRegex(); - var Any = require_any(); - var Common = require_common2(); - var internals = { - base64Regex: { - // paddingRequired - true: { - // urlSafe - true: /^(?:[\w\-]{2}[\w\-]{2})*(?:[\w\-]{2}==|[\w\-]{3}=)?$/, - false: /^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/ - }, - false: { - true: /^(?:[\w\-]{2}[\w\-]{2})*(?:[\w\-]{2}(==)?|[\w\-]{3}=?)?$/, - false: /^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}(==)?|[A-Za-z0-9+\/]{3}=?)?$/ - } - }, - dataUriRegex: /^data:[\w+.-]+\/[\w+.-]+;((charset=[\w-]+|base64),)?(.*)$/, - hexRegex: /^[a-f0-9]+$/i, - isoDurationRegex: /^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/, - guidBrackets: { - "{": "}", - "[": "]", - "(": ")", - "": "" - }, - guidVersions: { - uuidv1: "1", - uuidv2: "2", - uuidv3: "3", - uuidv4: "4", - uuidv5: "5" - }, - guidSeparators: /* @__PURE__ */ new Set([void 0, true, false, "-", ":"]), - normalizationForms: ["NFC", "NFD", "NFKC", "NFKD"], - domainControlRx: /[\x00-\x20@\:\/]/, - // Control + space + separators - domainSegmentRx: /^[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$/, - finalSegmentAdditionalRx: /[^0-9]/ - // Domain segment which is additionally not all-numeric - }; - module14.exports = Any._extend({ - type: "string", - flags: { - insensitive: { default: false }, - truncate: { default: false } - }, - terms: { - replacements: { init: null } - }, - coerce: { - from: "string", - method(value, { schema, state, prefs }) { - const normalize32 = schema.$_getRule("normalize"); - if (normalize32) { - value = value.normalize(normalize32.args.form); - } - const casing = schema.$_getRule("case"); - if (casing) { - value = casing.args.direction === "upper" ? value.toLocaleUpperCase() : value.toLocaleLowerCase(); - } - const trim = schema.$_getRule("trim"); - if (trim && trim.args.enabled) { - value = value.trim(); - } - if (schema.$_terms.replacements) { - for (const replacement of schema.$_terms.replacements) { - value = value.replace(replacement.pattern, replacement.replacement); - } - } - const hex = schema.$_getRule("hex"); - if (hex && hex.args.options.byteAligned && value.length % 2 !== 0) { - value = `0${value}`; - } - if (schema.$_getRule("isoDate")) { - const iso = internals.isoDate(value); - if (iso) { - value = iso; - } - } - if (schema._flags.truncate) { - const rule = schema.$_getRule("max"); - if (rule) { - let limit = rule.args.limit; - if (Common.isResolvable(limit)) { - limit = limit.resolve(value, state, prefs); - if (!Common.limit(limit)) { - return { value, errors: schema.$_createError("any.ref", limit, { ref: rule.args.limit, arg: "limit", reason: "must be a positive integer" }, state, prefs) }; - } - } - value = value.slice(0, limit); - } - } - return { value }; - } - }, - validate(value, { error: error2 }) { - if (typeof value !== "string") { - return { value, errors: error2("string.base") }; - } - if (value === "") { - return { value, errors: error2("string.empty") }; - } - }, - rules: { - alphanum: { - method() { - return this.$_addRule("alphanum"); - }, - validate(value, helpers) { - if (/^[a-zA-Z0-9]+$/.test(value)) { - return value; - } - return helpers.error("string.alphanum"); - } - }, - base64: { - method(options2 = {}) { - Common.assertOptions(options2, ["paddingRequired", "urlSafe"]); - options2 = { urlSafe: false, paddingRequired: true, ...options2 }; - Assert(typeof options2.paddingRequired === "boolean", "paddingRequired must be boolean"); - Assert(typeof options2.urlSafe === "boolean", "urlSafe must be boolean"); - return this.$_addRule({ name: "base64", args: { options: options2 } }); - }, - validate(value, helpers, { options: options2 }) { - const regex = internals.base64Regex[options2.paddingRequired][options2.urlSafe]; - if (regex.test(value)) { - return value; - } - return helpers.error("string.base64"); - } - }, - case: { - method(direction) { - Assert(["lower", "upper"].includes(direction), "Invalid case:", direction); - return this.$_addRule({ name: "case", args: { direction } }); - }, - validate(value, helpers, { direction }) { - if (direction === "lower" && value === value.toLocaleLowerCase() || direction === "upper" && value === value.toLocaleUpperCase()) { - return value; - } - return helpers.error(`string.${direction}case`); - }, - convert: true - }, - creditCard: { - method() { - return this.$_addRule("creditCard"); - }, - validate(value, helpers) { - let i2 = value.length; - let sum = 0; - let mul = 1; - while (i2--) { - const char = value.charAt(i2) * mul; - sum = sum + (char - (char > 9) * 9); - mul = mul ^ 3; - } - if (sum > 0 && sum % 10 === 0) { - return value; - } - return helpers.error("string.creditCard"); - } - }, - dataUri: { - method(options2 = {}) { - Common.assertOptions(options2, ["paddingRequired"]); - options2 = { paddingRequired: true, ...options2 }; - Assert(typeof options2.paddingRequired === "boolean", "paddingRequired must be boolean"); - return this.$_addRule({ name: "dataUri", args: { options: options2 } }); - }, - validate(value, helpers, { options: options2 }) { - const matches = value.match(internals.dataUriRegex); - if (matches) { - if (!matches[2]) { - return value; - } - if (matches[2] !== "base64") { - return value; - } - const base64regex = internals.base64Regex[options2.paddingRequired].false; - if (base64regex.test(matches[3])) { - return value; - } - } - return helpers.error("string.dataUri"); - } - }, - guid: { - alias: "uuid", - method(options2 = {}) { - Common.assertOptions(options2, ["version", "separator"]); - let versionNumbers = ""; - if (options2.version) { - const versions = [].concat(options2.version); - Assert(versions.length >= 1, "version must have at least 1 valid version specified"); - const set = /* @__PURE__ */ new Set(); - for (let i2 = 0; i2 < versions.length; ++i2) { - const version3 = versions[i2]; - Assert(typeof version3 === "string", "version at position " + i2 + " must be a string"); - const versionNumber = internals.guidVersions[version3.toLowerCase()]; - Assert(versionNumber, "version at position " + i2 + " must be one of " + Object.keys(internals.guidVersions).join(", ")); - Assert(!set.has(versionNumber), "version at position " + i2 + " must not be a duplicate"); - versionNumbers += versionNumber; - set.add(versionNumber); - } - } - Assert(internals.guidSeparators.has(options2.separator), 'separator must be one of true, false, "-", or ":"'); - const separator = options2.separator === void 0 ? "[:-]?" : options2.separator === true ? "[:-]" : options2.separator === false ? "[]?" : `\\${options2.separator}`; - const regex = new RegExp(`^([\\[{\\(]?)[0-9A-F]{8}(${separator})[0-9A-F]{4}\\2?[${versionNumbers || "0-9A-F"}][0-9A-F]{3}\\2?[${versionNumbers ? "89AB" : "0-9A-F"}][0-9A-F]{3}\\2?[0-9A-F]{12}([\\]}\\)]?)$`, "i"); - return this.$_addRule({ name: "guid", args: { options: options2 }, regex }); - }, - validate(value, helpers, args, { regex }) { - const results = regex.exec(value); - if (!results) { - return helpers.error("string.guid"); - } - if (internals.guidBrackets[results[1]] !== results[results.length - 1]) { - return helpers.error("string.guid"); - } - return value; - } - }, - hex: { - method(options2 = {}) { - Common.assertOptions(options2, ["byteAligned"]); - options2 = { byteAligned: false, ...options2 }; - Assert(typeof options2.byteAligned === "boolean", "byteAligned must be boolean"); - return this.$_addRule({ name: "hex", args: { options: options2 } }); - }, - validate(value, helpers, { options: options2 }) { - if (!internals.hexRegex.test(value)) { - return helpers.error("string.hex"); - } - if (options2.byteAligned && value.length % 2 !== 0) { - return helpers.error("string.hexAlign"); - } - return value; - } - }, - hostname: { - method() { - return this.$_addRule("hostname"); - }, - validate(value, helpers) { - if (internals.isDomainValid(value) || internals.ipRegex.test(value)) { - return value; - } - return helpers.error("string.hostname"); - } - }, - insensitive: { - method() { - return this.$_setFlag("insensitive", true); - } - }, - isoDate: { - method() { - return this.$_addRule("isoDate"); - }, - validate(value, { error: error2 }) { - if (internals.isoDate(value)) { - return value; - } - return error2("string.isoDate"); - } - }, - isoDuration: { - method() { - return this.$_addRule("isoDuration"); - }, - validate(value, helpers) { - if (internals.isoDurationRegex.test(value)) { - return value; - } - return helpers.error("string.isoDuration"); - } - }, - length: { - method(limit, encoding) { - return internals.length(this, "length", limit, "=", encoding); - }, - validate(value, helpers, { limit, encoding }, { name, operator, args }) { - const length2 = encoding ? Buffer.byteLength(value, encoding) : value.length; - if (Common.compare(length2, limit, operator)) { - return value; - } - return helpers.error("string." + name, { limit: args.limit, value, encoding }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - }, - "encoding" - ] - }, - lowercase: { - method() { - return this.case("lower"); - } - }, - max: { - method(limit, encoding) { - return internals.length(this, "max", limit, "<=", encoding); - }, - args: ["limit", "encoding"] - }, - min: { - method(limit, encoding) { - return internals.length(this, "min", limit, ">=", encoding); - }, - args: ["limit", "encoding"] - }, - normalize: { - method(form = "NFC") { - Assert(internals.normalizationForms.includes(form), "normalization form must be one of " + internals.normalizationForms.join(", ")); - return this.$_addRule({ name: "normalize", args: { form } }); - }, - validate(value, { error: error2 }, { form }) { - if (value === value.normalize(form)) { - return value; - } - return error2("string.normalize", { value, form }); - }, - convert: true - }, - pattern: { - alias: "regex", - method(regex, options2 = {}) { - Assert(regex instanceof RegExp, "regex must be a RegExp"); - Assert(!regex.flags.includes("g") && !regex.flags.includes("y"), "regex should not use global or sticky mode"); - if (typeof options2 === "string") { - options2 = { name: options2 }; - } - Common.assertOptions(options2, ["invert", "name"]); - const errorCode = ["string.pattern", options2.invert ? ".invert" : "", options2.name ? ".name" : ".base"].join(""); - return this.$_addRule({ name: "pattern", args: { regex, options: options2 }, errorCode }); - }, - validate(value, helpers, { regex, options: options2 }, { errorCode }) { - const patternMatch = regex.test(value); - if (patternMatch ^ options2.invert) { - return value; - } - return helpers.error(errorCode, { name: options2.name, regex, value }); - }, - args: ["regex", "options"], - multi: true - }, - replace: { - method(pattern, replacement) { - if (typeof pattern === "string") { - pattern = new RegExp(EscapeRegex(pattern), "g"); - } - Assert(pattern instanceof RegExp, "pattern must be a RegExp"); - Assert(typeof replacement === "string", "replacement must be a String"); - const obj = this.clone(); - if (!obj.$_terms.replacements) { - obj.$_terms.replacements = []; - } - obj.$_terms.replacements.push({ pattern, replacement }); - return obj; - } - }, - token: { - method() { - return this.$_addRule("token"); - }, - validate(value, helpers) { - if (/^\w+$/.test(value)) { - return value; - } - return helpers.error("string.token"); - } - }, - trim: { - method(enabled2 = true) { - Assert(typeof enabled2 === "boolean", "enabled must be a boolean"); - return this.$_addRule({ name: "trim", args: { enabled: enabled2 } }); - }, - validate(value, helpers, { enabled: enabled2 }) { - if (!enabled2 || value === value.trim()) { - return value; - } - return helpers.error("string.trim"); - }, - convert: true - }, - truncate: { - method(enabled2 = true) { - Assert(typeof enabled2 === "boolean", "enabled must be a boolean"); - return this.$_setFlag("truncate", enabled2); - } - }, - uppercase: { - method() { - return this.case("upper"); - } - } - }, - messages: { - "string.alphanum": "{{#label}} must only contain alpha-numeric characters", - "string.base": "{{#label}} must be a string", - "string.base64": "{{#label}} must be a valid base64 string", - "string.creditCard": "{{#label}} must be a credit card", - "string.dataUri": "{{#label}} must be a valid dataUri string", - "string.empty": "{{#label}} is not allowed to be empty", - "string.guid": "{{#label}} must be a valid GUID", - "string.hex": "{{#label}} must only contain hexadecimal characters", - "string.hexAlign": "{{#label}} hex decoded representation must be byte aligned", - "string.hostname": "{{#label}} must be a valid hostname", - "string.isoDate": "{{#label}} must be in iso format", - "string.isoDuration": "{{#label}} must be a valid ISO 8601 duration", - "string.length": "{{#label}} length must be {{#limit}} characters long", - "string.lowercase": "{{#label}} must only contain lowercase characters", - "string.max": "{{#label}} length must be less than or equal to {{#limit}} characters long", - "string.min": "{{#label}} length must be at least {{#limit}} characters long", - "string.normalize": "{{#label}} must be unicode normalized in the {{#form}} form", - "string.token": "{{#label}} must only contain alpha-numeric and underscore characters", - "string.pattern.base": "{{#label}} with value {:.} fails to match the required pattern: {{#regex}}", - "string.pattern.name": "{{#label}} with value {:.} fails to match the {{#name}} pattern", - "string.pattern.invert.base": "{{#label}} with value {:.} matches the inverted pattern: {{#regex}}", - "string.pattern.invert.name": "{{#label}} with value {:.} matches the inverted {{#name}} pattern", - "string.trim": "{{#label}} must not have leading or trailing whitespace", - "string.uppercase": "{{#label}} must only contain uppercase characters" - } - }); - internals.isoDate = function(value) { - if (!Common.isIsoDate(value)) { - return null; - } - const date3 = new Date(value); - if (isNaN(date3.getTime())) { - return null; - } - return date3.toISOString(); - }; - internals.length = function(schema, name, limit, operator, encoding) { - Assert(!encoding || Buffer.isEncoding(encoding), "Invalid encoding:", encoding); - return schema.$_addRule({ name, method: "length", args: { limit, encoding }, operator }); - }; - internals.rfc3986 = function() { - const rfc3986 = {}; - const hexDigit = "\\dA-Fa-f"; - const hexDigitOnly = "[" + hexDigit + "]"; - const unreserved = "\\w-\\.~"; - const subDelims = "!\\$&'\\(\\)\\*\\+,;="; - const decOctect = "(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])"; - rfc3986.ipv4 = "(?:" + decOctect + "\\.){3}" + decOctect; - const h16 = hexDigitOnly + "{1,4}"; - const ls32 = "(?:" + h16 + ":" + h16 + "|" + rfc3986.ipv4 + ")"; - const IPv6SixHex = "(?:" + h16 + ":){6}" + ls32; - const IPv6FiveHex = "::(?:" + h16 + ":){5}" + ls32; - const IPv6FourHex = "(?:" + h16 + ")?::(?:" + h16 + ":){4}" + ls32; - const IPv6ThreeHex = "(?:(?:" + h16 + ":){0,1}" + h16 + ")?::(?:" + h16 + ":){3}" + ls32; - const IPv6TwoHex = "(?:(?:" + h16 + ":){0,2}" + h16 + ")?::(?:" + h16 + ":){2}" + ls32; - const IPv6OneHex = "(?:(?:" + h16 + ":){0,3}" + h16 + ")?::" + h16 + ":" + ls32; - const IPv6NoneHex = "(?:(?:" + h16 + ":){0,4}" + h16 + ")?::" + ls32; - const IPv6NoneHex2 = "(?:(?:" + h16 + ":){0,5}" + h16 + ")?::" + h16; - const IPv6NoneHex3 = "(?:(?:" + h16 + ":){0,6}" + h16 + ")?::"; - rfc3986.v4Cidr = "(?:\\d|[1-2]\\d|3[0-2])"; - rfc3986.v6Cidr = "(?:0{0,2}\\d|0?[1-9]\\d|1[01]\\d|12[0-8])"; - rfc3986.ipv6 = "(?:" + IPv6SixHex + "|" + IPv6FiveHex + "|" + IPv6FourHex + "|" + IPv6ThreeHex + "|" + IPv6TwoHex + "|" + IPv6OneHex + "|" + IPv6NoneHex + "|" + IPv6NoneHex2 + "|" + IPv6NoneHex3 + ")"; - rfc3986.ipvfuture = "v" + hexDigitOnly + "+\\.[" + unreserved + subDelims + ":]+"; - return rfc3986; - }; - internals.ipRegex = function() { - const versions = ["ipv4", "ipv6", "ipvfuture"]; - const rfc3986 = internals.rfc3986(); - const parts = versions.map((version3) => { - const cidrpart = `\\/${version3 === "ipv4" ? rfc3986.v4Cidr : rfc3986.v6Cidr}`; - return `${rfc3986[version3]}(?:${cidrpart})?`; - }); - const raw = `(?:${parts.join("|")})`; - return new RegExp(`^${raw}$`); - }(); - internals.isDomainValid = function(domain) { - if (domain.length > 256) { - return false; - } - domain = domain.normalize("NFC"); - if (internals.domainControlRx.test(domain)) { - return false; - } - domain = internals.punycode(domain); - const segments = domain.split("."); - for (let i2 = 0; i2 < segments.length; ++i2) { - const segment = segments[i2]; - if (!segment.length) { - return false; - } - if (segment.length > 63) { - return false; - } - if (!internals.domainSegmentRx.test(segment)) { - return false; - } - const isFinalSegment = i2 === segments.length - 1; - if (isFinalSegment && !internals.finalSegmentAdditionalRx.test(segment)) { - return false; - } - } - return true; - }; - internals.punycode = function(domain) { - try { - return new Url.URL(`http://${domain}`).host; - } catch (err) { - return domain; - } - }; - } -}); -var require_symbol = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/symbol.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Any = require_any(); - var internals = {}; - internals.Map = class extends Map { - slice() { - return new internals.Map(this); - } - }; - module14.exports = Any._extend({ - type: "symbol", - terms: { - map: { init: new internals.Map() } - }, - coerce: { - method(value, { schema, error: error2 }) { - const lookup = schema.$_terms.map.get(value); - if (lookup) { - value = lookup; - } - if (!schema._flags.only || typeof value === "symbol") { - return { value }; - } - return { value, errors: error2("symbol.map", { map: schema.$_terms.map }) }; - } - }, - validate(value, { error: error2 }) { - if (typeof value !== "symbol") { - return { value, errors: error2("symbol.base") }; - } - }, - rules: { - map: { - method(iterable) { - if (iterable && !iterable[Symbol.iterator] && typeof iterable === "object") { - iterable = Object.entries(iterable); - } - Assert(iterable && iterable[Symbol.iterator], "Iterable must be an iterable or object"); - const obj = this.clone(); - const symbols2 = []; - for (const entry of iterable) { - Assert(entry && entry[Symbol.iterator], "Entry must be an iterable"); - const [key, value] = entry; - Assert(typeof key !== "object" && typeof key !== "function" && typeof key !== "symbol", "Key must not be of type object, function, or Symbol"); - Assert(typeof value === "symbol", "Value must be a Symbol"); - obj.$_terms.map.set(key, value); - symbols2.push(value); - } - return obj.valid(...symbols2); - } - } - }, - messages: { - "symbol.base": "{{#label}} must be a symbol", - "symbol.map": "{{#label}} must be one of {{#map}}" - } - }); - } -}); -var require_binary = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/types/binary.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Any = require_any(); - var Common = require_common2(); - module14.exports = Any._extend({ - type: "binary", - coerce: { - from: "string", - method(value, { schema }) { - try { - return { value: Buffer.from(value, schema._flags.encoding) }; - } catch (ignoreErr) { - } - } - }, - validate(value, { error: error2 }) { - if (!Buffer.isBuffer(value)) { - return { value, errors: error2("binary.base") }; - } - }, - rules: { - encoding: { - method(encoding) { - Assert(Buffer.isEncoding(encoding), "Invalid encoding:", encoding); - return this.$_setFlag("encoding", encoding); - } - }, - length: { - method(limit) { - return this.$_addRule({ name: "length", method: "length", args: { limit }, operator: "=" }); - }, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(value.length, limit, operator)) { - return value; - } - return helpers.error("binary." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - } - ] - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "length", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "length", args: { limit }, operator: ">=" }); - } - } - }, - cast: { - string: { - from: (value) => Buffer.isBuffer(value), - to(value, helpers) { - return value.toString(); - } - } - }, - messages: { - "binary.base": "{{#label}} must be a buffer or a string", - "binary.length": "{{#label}} must be {{#limit}} bytes", - "binary.max": "{{#label}} must be less than or equal to {{#limit}} bytes", - "binary.min": "{{#label}} must be at least {{#limit}} bytes" - } - }); - } -}); -var require_lib9 = __commonJS({ - "node_modules/.deno/@hapi+validate@2.0.1/node_modules/@hapi/validate/lib/index.js"(exports2, module14) { - "use strict"; - var Assert = require_assert(); - var Clone = require_clone(); - var Common = require_common2(); - var Compile = require_compile(); - var Errors = require_errors2(); - var Ref = require_ref(); - var internals = { - types: { - alternatives: require_alternatives(), - any: require_any(), - array: require_array(), - boolean: require_boolean(), - date: require_date(), - function: require_function(), - link: require_link(), - number: require_number(), - object: require_object(), - string: require_string(), - symbol: require_symbol() - }, - aliases: { - alt: "alternatives", - bool: "boolean", - func: "function" - } - }; - if (Buffer) { - internals.types.binary = require_binary(); - } - internals.root = function() { - const root = { - _types: new Set(Object.keys(internals.types)) - }; - for (const type of root._types) { - root[type] = function(...args) { - Assert(!args.length || ["alternatives", "link", "object"].includes(type), "The", type, "type does not allow arguments"); - return internals.generate(this, internals.types[type], args); - }; - } - for (const method of ["allow", "custom", "disallow", "equal", "exist", "forbidden", "invalid", "not", "only", "optional", "options", "prefs", "preferences", "required", "strip", "valid", "when"]) { - root[method] = function(...args) { - return this.any()[method](...args); - }; - } - Object.assign(root, internals.methods); - for (const alias in internals.aliases) { - const target = internals.aliases[alias]; - root[alias] = root[target]; - } - return root; - }; - internals.methods = { - ValidationError: Errors.ValidationError, - version: Common.version, - assert(value, schema, ...args) { - internals.assert(value, schema, true, args); - }, - attempt(value, schema, ...args) { - return internals.assert(value, schema, false, args); - }, - checkPreferences(prefs) { - Common.checkPreferences(prefs); - }, - compile(schema, options2) { - return Compile.compile(this, schema, options2); - }, - isError: Errors.ValidationError.isError, - isRef: Ref.isRef, - isSchema: Common.isSchema, - in(...args) { - return Ref.in(...args); - }, - override: Common.symbols.override, - ref(...args) { - return Ref.create(...args); - } - }; - internals.assert = function(value, schema, annotate, args) { - const message = args[0] instanceof Error || typeof args[0] === "string" ? args[0] : null; - const options2 = message ? args[1] : args[0]; - const result = schema.validate(value, Common.preferences({ errors: { stack: true } }, options2 || {})); - let error2 = result.error; - if (!error2) { - return result.value; - } - if (message instanceof Error) { - throw message; - } - const display = annotate && typeof error2.annotate === "function" ? error2.annotate() : error2.message; - if (error2 instanceof Errors.ValidationError === false) { - error2 = Clone(error2); - } - error2.message = message ? `${message} ${display}` : display; - throw error2; - }; - internals.generate = function(root, schema, args) { - Assert(root, "Must be invoked on a Joi instance."); - schema.$_root = root; - if (!schema._definition.args || !args.length) { - return schema; - } - return schema._definition.args(schema, ...args); - }; - module14.exports = internals.root(); - } -}); -var require_symbols = __commonJS({ - "node_modules/.deno/@hapi+shot@6.0.2/node_modules/@hapi/shot/lib/symbols.js"(exports2) { - "use strict"; - exports2.injection = Symbol("injection"); - } -}); -var require_request = __commonJS({ - "node_modules/.deno/@hapi+shot@6.0.2/node_modules/@hapi/shot/lib/request.js"(exports2, module14) { - "use strict"; - var Events2 = __require2("events"); - var Stream = __require2("stream"); - var Url = __require2("url"); - var Symbols = require_symbols(); - var internals = {}; - exports2 = module14.exports = internals.Request = class extends Stream.Readable { - constructor(options2) { - super({ - emitClose: !!options2.simulate?.close, - autoDestroy: true - // This is the default in node 14+ - }); - let url2 = options2.url; - if (typeof url2 === "object") { - url2 = Url.format(url2); - } - const uri = Url.parse(url2); - this.url = uri.path; - this.httpVersion = "1.1"; - this.method = options2.method ? options2.method.toUpperCase() : "GET"; - this.headers = {}; - const headers = options2.headers ?? {}; - const fields = Object.keys(headers); - fields.forEach((field) => { - this.headers[field.toLowerCase()] = headers[field]; - }); - this.headers["user-agent"] = this.headers["user-agent"] ?? "shot"; - const hostHeaderFromUri = function() { - if (uri.port) { - return uri.host; - } - if (uri.protocol) { - return uri.hostname + (uri.protocol === "https:" ? ":443" : ":80"); - } - return null; - }; - this.headers.host = this.headers.host ?? hostHeaderFromUri() ?? options2.authority ?? "localhost:80"; - this.socket = this.connection = new internals.MockSocket(options2); - let payload = options2.payload ?? null; - if (payload && typeof payload !== "string" && !(payload instanceof Stream) && !Buffer.isBuffer(payload)) { - payload = JSON.stringify(payload); - this.headers["content-type"] = this.headers["content-type"] || "application/json"; - } - if (payload && !(payload instanceof Stream) && !this.headers.hasOwnProperty("content-length")) { - this.headers["content-length"] = (Buffer.isBuffer(payload) ? payload.length : Buffer.byteLength(payload)).toString(); - } - this._shot = { - payload, - isDone: false, - simulate: options2.simulate ?? {} - }; - return this; - } - prepare(next) { - if (this._shot.payload instanceof Stream === false) { - return next(); - } - const chunks = []; - this._shot.payload.on("data", (chunk) => chunks.push(Buffer.from(chunk))); - this._shot.payload.on("end", () => { - const payload = Buffer.concat(chunks); - this.headers["content-length"] = this.headers["content-length"] || payload.length; - this._shot.payload = payload; - return next(); - }); - } - _read(size) { - setImmediate(() => { - if (this._shot.isDone) { - if (this._shot.simulate.end !== false) { - this.push(null); - } - return; - } - this._shot.isDone = true; - if (this._shot.payload) { - if (this._shot.simulate.split) { - this.push(this._shot.payload.slice(0, 1)); - this.push(this._shot.payload.slice(1)); - } else { - this.push(this._shot.payload); - } - } - if (this._shot.simulate.error) { - this.destroy(new Error("Simulated")); - } else if (this._shot.simulate.end !== false) { - this.push(null); - } else if (this._shot.simulate.close) { - this.emit("close"); - } - }); - } - }; - internals.Request.prototype[Symbols.injection] = true; - internals.MockSocket = class MockSocket extends Events2.EventEmitter { - constructor({ remoteAddress }) { - super(); - this.remoteAddress = remoteAddress ?? "127.0.0.1"; - } - // Net.Socket APIs used by hapi - end() { - } - setTimeout() { - } - }; - } -}); -var require_response = __commonJS({ - "node_modules/.deno/@hapi+shot@6.0.2/node_modules/@hapi/shot/lib/response.js"(exports2, module14) { - "use strict"; - var Http = __require2("http"); - var Stream = __require2("stream"); - var Hoek = require_lib(); - var Symbols = require_symbols(); - var internals = {}; - exports2 = module14.exports = internals.Response = class extends Http.ServerResponse { - constructor(req, onEnd) { - super({ method: req.method, httpVersionMajor: 1, httpVersionMinor: 1 }); - this._shot = { headers: null, trailers: {}, payloadChunks: [] }; - this.assignSocket(internals.nullSocket()); - this.socket.on("error", Hoek.ignore); - if (req._shot.simulate.close) { - req.once("close", () => { - process.nextTick(() => this.destroy()); - }); - } - const finalize = (aborted2) => { - const res = internals.payload(this); - res.raw.req = req; - if (aborted2) { - res.aborted = aborted2; - if (!this.headersSent) { - res.statusCode = 499; - } - } - this.removeListener("close", abort); - process.nextTick(() => onEnd(res)); - }; - const abort = () => finalize(true); - this.once("finish", finalize); - this.on("close", abort); - } - writeHead(...args) { - const headers = args[args.length - 1]; - if (typeof headers === "object" && headers !== null) { - const headerNames = Object.keys(headers); - for (let i2 = 0; i2 < headerNames.length; ++i2) { - const name = headerNames[i2]; - try { - this.setHeader(name, headers[name]); - break; - } catch (ignoreErr) { - } - } - } - const result = super.writeHead(...args); - this._shot.headers = this.getHeaders(); - ["Date", "Connection", "Transfer-Encoding"].forEach((name) => { - const regex = new RegExp("\\r\\n" + name + ": ([^\\r]*)\\r\\n"); - const field = this._header.match(regex); - if (field) { - this._shot.headers[name.toLowerCase()] = field[1]; - } - }); - return result; - } - write(data, encoding, callback) { - super.write(data, encoding, callback); - this._shot.payloadChunks.push(Buffer.from(data, encoding)); - return true; - } - end(data, encoding, callback) { - if (data) { - this.write(data, encoding); - } - super.end(callback); - this.emit("finish"); - } - addTrailers(trailers) { - for (const key in trailers) { - this._shot.trailers[key.toLowerCase().trim()] = trailers[key].toString().trim(); - } - } - }; - internals.Response.prototype[Symbols.injection] = true; - internals.payload = function(response) { - const res = { - raw: { - res: response - }, - headers: response._shot.headers, - statusCode: response.statusCode, - statusMessage: response.statusMessage, - trailers: {} - }; - const rawBuffer = Buffer.concat(response._shot.payloadChunks); - res.rawPayload = rawBuffer; - res.payload = rawBuffer.toString(); - res.trailers = response._shot.trailers; - return res; - }; - internals.nullSocket = function() { - return new Stream.Writable({ - write(chunk, encoding, callback) { - setImmediate(callback); - } - }); - }; - } -}); -var require_lib10 = __commonJS({ - "node_modules/.deno/@hapi+shot@6.0.2/node_modules/@hapi/shot/lib/index.js"(exports2) { - "use strict"; - var Hoek = require_lib(); - var Validate = require_lib9(); - var Request2 = require_request(); - var Response2 = require_response(); - var Symbols = require_symbols(); - var internals = {}; - internals.options = Validate.object().keys({ - url: Validate.alternatives([ - Validate.string(), - Validate.object().keys({ - protocol: Validate.string(), - hostname: Validate.string(), - port: Validate.any(), - pathname: Validate.string().required(), - query: Validate.any() - }) - ]).required(), - headers: Validate.object(), - payload: Validate.any(), - simulate: { - end: Validate.boolean(), - split: Validate.boolean(), - error: Validate.boolean(), - close: Validate.boolean() - }, - authority: Validate.string(), - remoteAddress: Validate.string(), - method: Validate.string(), - validate: Validate.boolean() - }); - exports2.inject = async function(dispatchFunc, options2) { - options2 = typeof options2 === "string" ? { url: options2 } : options2; - if (options2?.validate !== false) { - Hoek.assert(typeof dispatchFunc === "function", "Invalid or missing dispatch function"); - Validate.assert(options2 ?? null, internals.options, "Invalid options:"); - } - return new Promise((resolve82) => { - const req = new Request2(options2); - const res = new Response2(req, resolve82); - req.prepare(() => dispatchFunc(req, res)); - }); - }; - exports2.isInjection = function(obj) { - return !!obj[Symbols.injection]; - }; - } -}); -var require_lib11 = __commonJS({ - "node_modules/.deno/@hapi+teamwork@6.0.1/node_modules/@hapi/teamwork/lib/index.js"(exports2) { - "use strict"; - var internals = {}; - exports2.Team = class { - #meetings = null; - #count = null; - #notes = null; - #done = false; - #strict = false; - constructor(options2) { - this._init(options2); - } - static _notes(instance) { - return instance.#notes; - } - _init(options2 = {}) { - this.work = new Promise((resolve82, reject) => { - this._resolve = resolve82; - this._reject = reject; - }); - const meetings = options2.meetings ?? 1; - const strict = !!options2.strict; - if (!Number.isInteger(meetings) || meetings <= 0) { - if (meetings === 0 && !strict) { - return this._finalize(null, null); - } - throw new Error("Invalid meetings value"); - } - this.#meetings = meetings; - this.#count = meetings; - this.#notes = []; - this.#done = false; - this.#strict = strict; - } - _finalize(err, note) { - this.#done = true; - this.#notes = null; - if (err) { - this._reject(err); - } else { - this._resolve(note); - } - } - attend(note) { - if (this.#done) { - if (this.#strict) { - throw new Error("Unscheduled meeting"); - } - return; - } - if (note instanceof Error) { - return this._finalize(note); - } - this.#notes.push(note); - if (--this.#count) { - return; - } - this._finalize(null, this.#meetings === 1 ? this.#notes[0] : this.#notes); - } - async regroup(options2) { - try { - await this.work; - } catch { - } - this._init(options2); - } - }; - exports2.Events = class { - #iterators = /* @__PURE__ */ new Set(); - static _iterators(instance) { - return instance.#iterators; - } - static isIterator(iterator) { - return iterator instanceof internals.EventsIterator; - } - iterator() { - const iterator = new internals.EventsIterator(this); - this.#iterators.add(iterator); - return iterator; - } - emit(value) { - for (const iterator of this.#iterators) { - iterator._queue({ value, done: false }); - } - } - end() { - for (const iterator of this.#iterators) { - iterator._queue({ done: true }); - } - } - _remove(iterator) { - this.#iterators.delete(iterator); - } - }; - internals.EventsIterator = class { - #events; - #pending = null; - #queue = []; - constructor(events) { - this.#events = events; - } - [Symbol.asyncIterator]() { - return this; - } - next() { - if (this.#queue.length) { - return Promise.resolve(this.#queue.shift()); - } - if (!this.#events) { - return { done: true }; - } - this.#pending = new exports2.Team(); - return this.#pending.work; - } - return() { - this._cleanup(); - return { done: true }; - } - _cleanup() { - this.#events?._remove(this); - this.#events = null; - } - _queue(item) { - if (item.done) { - this._cleanup(); - } - if (this.#pending) { - this.#pending.attend(item); - this.#pending = null; - } else { - this.#queue.push(item); - } - } - }; - } -}); -var require_lib12 = __commonJS({ - "node_modules/.deno/@hapi+bounce@3.0.2/node_modules/@hapi/bounce/lib/index.js"(exports2) { - "use strict"; - var Assert = __require2("assert"); - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var internals = { - system: [ - // JavaScript - EvalError, - RangeError, - ReferenceError, - SyntaxError, - TypeError, - URIError, - // Node - Assert.AssertionError, - // Hoek - Hoek.AssertError - ] - }; - exports2.rethrow = function(err, types, options2 = {}) { - return internals.catch(err, types, options2, true); - }; - exports2.ignore = function(err, types, options2 = {}) { - return internals.catch(err, types, options2, false); - }; - internals.catch = function(err, types, options2, match) { - if (internals.match(err, types) !== match) { - return; - } - if (options2.override) { - err = options2.override; - } - if (options2.decorate) { - Object.assign(err, options2.decorate); - } - if (options2.return) { - return err; - } - throw err; - }; - exports2.background = async function(operation, action = "rethrow", types = "system", options2 = {}) { - try { - if (typeof operation === "function") { - await operation(); - } else { - await operation; - } - } catch (err) { - return exports2[action](err, types, options2); - } - }; - exports2.isBoom = function(err) { - return Boom5.isBoom(err); - }; - exports2.isError = function(err) { - return err instanceof Error; - }; - exports2.isSystem = function(err) { - if (!err) { - return false; - } - if (err.isBoom) { - return false; - } - for (const system of internals.system) { - if (err instanceof system) { - return true; - } - } - return false; - }; - internals.rules = { - system: exports2.isSystem, - boom: exports2.isBoom - }; - internals.match = function(err, types) { - if (!types) { - return true; - } - types = Array.isArray(types) ? types : [types]; - for (const type of types) { - if (typeof type === "string") { - if (internals.rules[type](err)) { - return true; - } - } else if (typeof type === "object") { - if (Hoek.contain(err, type, { deep: true, part: true })) { - return true; - } - } else if (err instanceof type) { - return true; - } - } - return false; - }; - } -}); -var require_lib13 = __commonJS({ - "node_modules/.deno/@hapi+somever@4.1.1/node_modules/@hapi/somever/lib/index.js"(exports2) { - "use strict"; - var Bounce = require_lib12(); - var Hoek = require_lib(); - var internals = { - maxLength: 256, - wildcards: ["x", "X", "*"], - any: Symbol("any") - }; - internals.versionRx = /^\s*[vV]?(\d+|[xX*])(?:\.(\d+|[xX*])(?:\.(\d+|[xX*])(?:\-?([^+]+))?(?:\+(.+))?)?)?\s*$/; - internals.strict = { - tokenRx: /^[-\dA-Za-z]+(?:\.[-\dA-Za-z]+)*$/, - numberRx: /^((?:0)|(?:[1-9]\d*))$/ - }; - exports2.version = function(version3, options2) { - return new internals.Version(version3, options2); - }; - exports2.range = function(range) { - return new internals.Range(range); - }; - exports2.match = function(version3, range, options2) { - try { - return exports2.range(range).match(version3, options2); - } catch (err) { - Bounce.rethrow(err, "system"); - return false; - } - }; - exports2.compare = function(a, b, options2 = {}) { - let aFirst = -1; - let bFirst = 1; - a = exports2.version(a, options2); - b = exports2.version(b, options2); - if (options2.range && !options2.includePrerelease && a.prerelease.length && (a.major !== b.major || a.minor !== b.minor || a.patch !== b.patch || !b.prerelease.length)) { - aFirst = -2; - bFirst = 2; - } - for (let i2 = 0; i2 < 3; ++i2) { - const av = a.dots[i2]; - const bv = b.dots[i2]; - if (av === bv || av === internals.any || // Wildcard is equal to everything - bv === internals.any) { - continue; - } - return av - bv < 0 ? aFirst : bFirst; - } - if (!a.prerelease.length && !b.prerelease.length) { - return 0; - } else if (!b.prerelease.length) { - return options2.includePrerelease && b.patch === internals.any ? 0 : aFirst; - } else if (!a.prerelease.length) { - return options2.includePrerelease && a.patch === internals.any ? 0 : bFirst; - } - for (let i2 = 0; ; ++i2) { - const ai = a.prerelease[i2]; - const bi = b.prerelease[i2]; - if (ai === void 0 && bi === void 0) { - return 0; - } - if (ai === bi) { - continue; - } - if (ai === void 0) { - return aFirst; - } - if (bi === void 0) { - return bFirst; - } - const an = Number.isFinite(ai); - const bn = Number.isFinite(bi); - if (an !== bn) { - return an ? aFirst : bFirst; - } - return ai < bi ? aFirst : bFirst; - } - }; - internals.Version = class { - constructor(version3, options2 = {}) { - Hoek.assert(version3, "Missing version argument"); - if (version3 instanceof internals.Version) { - return version3; - } - if (typeof version3 === "object") { - this._copy(version3); - } else { - this._parse(version3, options2); - } - this.format(); - } - _copy(version3) { - this.major = version3.major === void 0 ? internals.any : version3.major; - this.minor = version3.minor === void 0 ? internals.any : version3.minor; - this.patch = version3.patch === void 0 ? internals.any : version3.patch; - this.prerelease = version3.prerelease ?? []; - this.build = version3.build ?? []; - } - _parse(version3, options2) { - Hoek.assert(typeof version3 === "string", "Version argument must be a string"); - Hoek.assert(version3.length <= internals.maxLength, "Version string too long"); - const match = version3.match(internals.versionRx); - if (!match) { - throw new Error(`Invalid version string format: ${version3}`); - } - this.major = internals.Version._number(match[1], "major", options2); - this.minor = internals.Version._number(match[2] || "x", "minor", options2); - this.patch = internals.Version._number(match[3] || "x", "patch", options2); - this.prerelease = internals.Version._sub(match[4], "prerelease", options2); - this.build = internals.Version._sub(match[5], "build", options2); - } - static _number(string3, source, options2) { - if (internals.wildcards.includes(string3)) { - return internals.any; - } - if (options2.strict) { - Hoek.assert(string3.match(internals.strict.numberRx), "Value must be 0 or a number without a leading zero:", source); - } - const value = parseInt(string3, 10); - Hoek.assert(value <= Number.MAX_SAFE_INTEGER, "Value must be positive and less than max safe integer:", source); - return value; - } - static _sub(string3, source, options2) { - if (!string3) { - return []; - } - if (options2.strict) { - Hoek.assert(string3.match(internals.strict.tokenRx), "Value can only contain dot-separated hyphens, digits, a-z or A-Z:", source); - } - const subs = []; - const parts = string3.split("."); - for (const part of parts) { - if (!part) { - throw new Error(`Invalid empty ${source} segment`); - } - subs.push(part.match(/^\d+$/) ? internals.Version._number(part, source, { strict: options2.strict }) : part); - } - return subs; - } - format() { - this.version = `${internals.dot(this.major)}.${internals.dot(this.minor)}.${internals.dot(this.patch)}${internals.token(this.prerelease, "-")}${internals.token(this.build, "+")}`; - this.dots = [this.major, this.minor, this.patch]; - this.wildcard = this.major === internals.any && this.minor === internals.any && this.patch === internals.any && !this.prerelease.length; - } - toString() { - return this.version; - } - compare(to, options2) { - return internals.Version.compare(this, to, options2); - } - static compare(a, b, options2 = {}) { - return exports2.compare(a, b, options2); - } - }; - internals.dot = (v2) => { - return v2 === internals.any ? "x" : v2; - }; - internals.token = (v2, prefix) => { - if (!v2.length) { - return ""; - } - return `${prefix}${v2.join(".")}`; - }; - internals.Range = class { - constructor(range, options2) { - this._settings = Object.assign({}, options2); - this._anything = false; - this._or = []; - this._active = null; - if (range !== void 0) { - this.pattern(range); - } - this._another(); - } - _another() { - if (!this._active || this._active.rules.length) { - this._active = { rules: [] }; - this._or.push(this._active); - } - return this; - } - _rule(operator, version3) { - version3 = exports2.version(version3, this._settings); - const compare = internals.operator(operator); - this._active.rules.push({ compare, version: version3, operator }); - return this; - } - get or() { - return this._another(); - } - equal(version3) { - return this._rule("=", version3); - } - above(version3) { - return this._rule(">", version3); - } - below(version3) { - return this._rule("<", version3); - } - between(from3, to) { - this._rule(">=", from3); - this._rule("<=", to); - return this; - } - minor(version3) { - version3 = exports2.version(version3, this._settings); - if (version3.major === internals.any) { - this._rule("=", version3); - return this; - } - this._rule(">=", version3); - if (version3.minor === internals.any) { - this._rule("<", { major: version3.major + 1, minor: 0, patch: 0, prerelease: [0] }); - } else { - this._rule("<", { major: version3.major, minor: version3.minor + 1, patch: 0, prerelease: [0] }); - } - return this; - } - compatible(version3) { - version3 = exports2.version(version3, this._settings); - if (version3.major === internals.any) { - this._rule("=", version3); - return this; - } - this._rule(">=", version3); - if (version3.major === 0 && version3.minor !== internals.any) { - if (version3.minor === 0) { - this._rule("<", { major: 0, minor: 0, patch: version3.patch + 1, prerelease: [0] }); - } else { - this._rule("<", { major: 0, minor: version3.minor + 1, patch: 0, prerelease: [0] }); - } - } else { - this._rule("<", { major: version3.major + 1, minor: 0, patch: 0, prerelease: [0] }); - } - return this; - } - pattern(range) { - try { - this._pattern(range); - return this; - } catch (err) { - throw new Error(`Invalid range: "${range}" because: ${err.message}`); - } - } - _pattern(range) { - if (range === "") { - this._anything = true; - return; - } - const normalized = internals.normalize(range); - const ors = normalized.split(/\s*\|\|\s*/); - for (const condition of ors) { - if (!condition) { - this._anything = true; - return; - } - this._another(); - const ands = condition.split(/\s+/); - for (const and of ands) { - const hyphen = and.indexOf("@"); - if (hyphen !== -1) { - const from3 = and.slice(0, hyphen); - const to = and.slice(hyphen + 1); - this.between(from3, to); - continue; - } - const parts = and.match(/^(\^|~|<\=|>\=|<|>|\=)?(.+)$/); - const operator = parts[1]; - const version3 = exports2.version(parts[2], this._settings); - if (version3.wildcard) { - this._anything = true; - return; - } - if (operator === "~") { - this.minor(version3); - continue; - } - if (operator === "^") { - this.compatible(version3); - continue; - } - if (operator) { - this._rule(operator, version3); - continue; - } - this.equal(version3); - } - } - } - match(version3, options2 = {}) { - version3 = exports2.version(version3, this._settings); - if (this._anything) { - return !!options2.includePrerelease || !version3.prerelease.length; - } - for (const { rules } of this._or) { - if (!rules.length) { - continue; - } - let matches = 0; - let excludes = 0; - for (const rule of rules) { - const compare = version3.compare(rule.version, Object.assign(this._settings, options2, { range: true })); - const exclude = Math.abs(compare) === 2; - if (rule.compare.includes(compare / (exclude ? 2 : 1))) { - ++matches; - if (exclude) { - ++excludes; - } - } else { - break; - } - } - if (matches === rules.length && excludes < matches) { - return true; - } - } - return false; - } - toString() { - if (this._anything) { - return "*"; - } - let string3 = ""; - for (const { rules } of this._or) { - if (!rules.length) { - continue; - } - const conditions = []; - for (const rule of rules) { - conditions.push(`${rule.operator !== "=" ? rule.operator : ""}${rule.version.version}`); - } - string3 += (string3 ? "||" : "") + conditions.join(" "); - } - return string3; - } - }; - internals.operator = function(compare) { - switch (compare) { - case "=": - return [0]; - case ">": - return [1]; - case ">=": - return [0, 1]; - case "<": - return [-1]; - case "<=": - return [0, -1]; - } - }; - internals.normalize = function(range) { - return range.replace(/ \- /g, "@").replace(/~>/g, "~").replace(/(\^|~|<\=|>\=|<|>|\=)\s*([^\s]+)/g, ($0, $1, $2) => `${$1}${$2}`); - }; - } -}); -var require_config = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/config.js"(exports2) { - "use strict"; - var Os = __require2("os"); - var Somever = require_lib13(); - var Validate = require_lib9(); - var internals = {}; - exports2.symbol = Symbol("hapi-response"); - exports2.apply = function(type, options2, ...message) { - const result = internals[type].validate(options2); - if (result.error) { - throw new Error(`Invalid ${type} options ${message.length ? "(" + message.join(" ") + ")" : ""} ${result.error.annotate()}`); - } - return result.value; - }; - exports2.enable = function(options2) { - const settings = options2 ? Object.assign({}, options2) : {}; - if (settings.security === true) { - settings.security = {}; - } - if (settings.cors === true) { - settings.cors = {}; - } - return settings; - }; - exports2.versionMatch = (version3, range) => Somever.match(version3, range, { includePrerelease: true }); - internals.access = Validate.object({ - entity: Validate.valid("user", "app", "any"), - scope: [false, Validate.array().items(Validate.string()).single().min(1)] - }); - internals.auth = Validate.alternatives([ - Validate.string(), - internals.access.keys({ - mode: Validate.valid("required", "optional", "try"), - strategy: Validate.string(), - strategies: Validate.array().items(Validate.string()).min(1), - access: Validate.array().items(internals.access.min(1)).single().min(1), - payload: [ - Validate.valid("required", "optional"), - Validate.boolean() - ] - }).without("strategy", "strategies").without("access", ["scope", "entity"]) - ]); - internals.event = Validate.object({ - method: Validate.array().items(Validate.function()).single(), - options: Validate.object({ - before: Validate.array().items(Validate.string()).single(), - after: Validate.array().items(Validate.string()).single(), - bind: Validate.any(), - sandbox: Validate.valid("server", "plugin"), - timeout: Validate.number().integer().min(1) - }).default({}) - }); - internals.exts = Validate.array().items(internals.event.keys({ type: Validate.string().required() })).single(); - internals.failAction = Validate.alternatives([ - Validate.valid("error", "log", "ignore"), - Validate.function() - ]).default("error"); - internals.routeBase = Validate.object({ - app: Validate.object().allow(null), - auth: internals.auth.allow(false), - bind: Validate.object().allow(null), - cache: Validate.object({ - expiresIn: Validate.number(), - expiresAt: Validate.string(), - privacy: Validate.valid("default", "public", "private"), - statuses: Validate.array().items(Validate.number().integer().min(200)).min(1).single().default([200, 204]), - otherwise: Validate.string().default("no-cache") - }).allow(false).default(), - compression: Validate.object().pattern(/.+/, Validate.object()).default(), - cors: Validate.object({ - origin: Validate.array().min(1).allow("ignore").default(["*"]), - maxAge: Validate.number().default(86400), - headers: Validate.array().items(Validate.string()).default(["Accept", "Authorization", "Content-Type", "If-None-Match"]), - additionalHeaders: Validate.array().items(Validate.string()).default([]), - exposedHeaders: Validate.array().items(Validate.string()).default(["WWW-Authenticate", "Server-Authorization"]), - additionalExposedHeaders: Validate.array().items(Validate.string()).default([]), - credentials: Validate.boolean().when("origin", { is: "ignore", then: false }).default(false), - preflightStatusCode: Validate.valid(200, 204).default(200) - }).allow(false, true).default(false), - ext: Validate.object({ - onPreAuth: Validate.array().items(internals.event).single(), - onCredentials: Validate.array().items(internals.event).single(), - onPostAuth: Validate.array().items(internals.event).single(), - onPreHandler: Validate.array().items(internals.event).single(), - onPostHandler: Validate.array().items(internals.event).single(), - onPreResponse: Validate.array().items(internals.event).single(), - onPostResponse: Validate.array().items(internals.event).single() - }).default({}), - files: Validate.object({ - relativeTo: Validate.string().pattern(/^([\/\.])|([A-Za-z]:\\)|(\\\\)/).default(".") - }).default(), - json: Validate.object({ - replacer: Validate.alternatives(Validate.function(), Validate.array()).allow(null).default(null), - space: Validate.number().allow(null).default(null), - suffix: Validate.string().allow(null).default(null), - escape: Validate.boolean().default(false) - }).default(), - log: Validate.object({ - collect: Validate.boolean().default(false) - }).default(), - payload: Validate.object({ - output: Validate.valid("data", "stream", "file").default("data"), - parse: Validate.boolean().allow("gunzip").default(true), - multipart: Validate.object({ - output: Validate.valid("data", "stream", "file", "annotated").required() - }).default(false).allow(true, false), - allow: Validate.array().items(Validate.string()).single(), - override: Validate.string(), - protoAction: Validate.valid("error", "remove", "ignore").default("error"), - maxBytes: Validate.number().integer().positive().default(1024 * 1024), - maxParts: Validate.number().integer().positive().default(1e3), - uploads: Validate.string().default(Os.tmpdir()), - failAction: internals.failAction, - timeout: Validate.number().integer().positive().allow(false).default(10 * 1e3), - defaultContentType: Validate.string().default("application/json"), - compression: Validate.object().pattern(/.+/, Validate.object()).default() - }).default(), - plugins: Validate.object(), - response: Validate.object({ - disconnectStatusCode: Validate.number().integer().min(400).default(499), - emptyStatusCode: Validate.valid(200, 204).default(204), - failAction: internals.failAction, - modify: Validate.boolean(), - options: Validate.object(), - ranges: Validate.boolean().default(true), - sample: Validate.number().min(0).max(100).when("modify", { then: Validate.forbidden() }), - schema: Validate.alternatives(Validate.object(), Validate.array(), Validate.function()).allow(true, false), - status: Validate.object().pattern(/\d\d\d/, Validate.alternatives(Validate.object(), Validate.array(), Validate.function()).allow(true, false)) - }).default(), - security: Validate.object({ - hsts: Validate.alternatives([ - Validate.object({ - maxAge: Validate.number(), - includeSubdomains: Validate.boolean(), - includeSubDomains: Validate.boolean(), - preload: Validate.boolean() - }), - Validate.boolean(), - Validate.number() - ]).default(15768e3), - xframe: Validate.alternatives([ - Validate.boolean(), - Validate.valid("sameorigin", "deny"), - Validate.object({ - rule: Validate.valid("sameorigin", "deny", "allow-from"), - source: Validate.string() - }) - ]).default("deny"), - xss: Validate.valid("enabled", "disabled", false).default("disabled"), - noOpen: Validate.boolean().default(true), - noSniff: Validate.boolean().default(true), - referrer: Validate.alternatives([ - Validate.boolean().valid(false), - Validate.valid( - "", - "no-referrer", - "no-referrer-when-downgrade", - "unsafe-url", - "same-origin", - "origin", - "strict-origin", - "origin-when-cross-origin", - "strict-origin-when-cross-origin" - ) - ]).default(false) - }).allow(null, false, true).default(false), - state: Validate.object({ - parse: Validate.boolean().default(true), - failAction: internals.failAction - }).default(), - timeout: Validate.object({ - socket: Validate.number().integer().positive().allow(false), - server: Validate.number().integer().positive().allow(false).default(false) - }).default(), - validate: Validate.object({ - headers: Validate.alternatives(Validate.object(), Validate.array(), Validate.function()).allow(null, true), - params: Validate.alternatives(Validate.object(), Validate.array(), Validate.function()).allow(null, true), - query: Validate.alternatives(Validate.object(), Validate.array(), Validate.function()).allow(null, false, true), - payload: Validate.alternatives(Validate.object(), Validate.array(), Validate.function()).allow(null, false, true), - state: Validate.alternatives(Validate.object(), Validate.array(), Validate.function()).allow(null, false, true), - failAction: internals.failAction, - errorFields: Validate.object(), - options: Validate.object().default(), - validator: Validate.object() - }).default() - }); - internals.server = Validate.object({ - address: Validate.string().hostname(), - app: Validate.object().allow(null), - autoListen: Validate.boolean(), - cache: Validate.allow(null), - // Validated elsewhere - compression: Validate.object({ - minBytes: Validate.number().min(1).integer().default(1024) - }).allow(false).default(), - debug: Validate.object({ - request: Validate.array().items(Validate.string()).single().allow(false).default(["implementation"]), - log: Validate.array().items(Validate.string()).single().allow(false) - }).allow(false).default(), - host: Validate.string().hostname().allow(null), - info: Validate.object({ - remote: Validate.boolean().default(false) - }).default({}), - listener: Validate.any(), - load: Validate.object({ - sampleInterval: Validate.number().integer().min(0).default(0) - }).unknown().default(), - mime: Validate.object().empty(null).default(), - operations: Validate.object({ - cleanStop: Validate.boolean().default(true) - }).default(), - plugins: Validate.object(), - port: Validate.alternatives([ - Validate.number().integer().min(0), - // TCP port - Validate.string().pattern(/\//), - // Unix domain socket - Validate.string().pattern(/^\\\\\.\\pipe\\/) - // Windows named pipe - ]).allow(null), - query: Validate.object({ - parser: Validate.function() - }).default(), - router: Validate.object({ - isCaseSensitive: Validate.boolean().default(true), - stripTrailingSlash: Validate.boolean().default(false) - }).default(), - routes: internals.routeBase.default(), - state: Validate.object(), - // Cookie defaults - tls: Validate.alternatives([ - Validate.object().allow(null), - Validate.boolean() - ]), - uri: Validate.string().pattern(/[^/]$/) - }); - internals.vhost = Validate.alternatives([ - Validate.string().hostname(), - Validate.array().items(Validate.string().hostname()).min(1) - ]); - internals.handler = Validate.alternatives([ - Validate.function(), - Validate.object().length(1) - ]); - internals.route = Validate.object({ - method: Validate.string().pattern(/^[a-zA-Z0-9!#\$%&'\*\+\-\.^_`\|~]+$/).required(), - path: Validate.string().required(), - rules: Validate.object(), - vhost: internals.vhost, - // Validated in route construction - handler: Validate.any(), - options: Validate.any(), - config: Validate.any() - // Backwards compatibility - }).without("config", "options"); - internals.pre = [ - Validate.function(), - Validate.object({ - method: Validate.alternatives(Validate.string(), Validate.function()).required(), - assign: Validate.string(), - mode: Validate.valid("serial", "parallel"), - failAction: internals.failAction - }) - ]; - internals.routeConfig = internals.routeBase.keys({ - description: Validate.string(), - id: Validate.string(), - isInternal: Validate.boolean(), - notes: [ - Validate.string(), - Validate.array().items(Validate.string()) - ], - pre: Validate.array().items(...internals.pre.concat(Validate.array().items(...internals.pre).min(1))), - tags: [ - Validate.string(), - Validate.array().items(Validate.string()) - ] - }); - internals.cacheConfig = Validate.alternatives([ - Validate.function(), - Validate.object({ - name: Validate.string().invalid("_default"), - shared: Validate.boolean(), - provider: [ - Validate.function(), - { - constructor: Validate.function().required(), - options: Validate.object({ - partition: Validate.string().default("hapi-cache") - }).unknown().default({}) - } - ], - engine: Validate.object() - }).xor("provider", "engine") - ]); - internals.cache = Validate.array().items(internals.cacheConfig).min(1).single(); - internals.cachePolicy = Validate.object({ - cache: Validate.string().allow(null).allow(""), - segment: Validate.string(), - shared: Validate.boolean() - }).unknown(); - internals.method = Validate.object({ - bind: Validate.object().allow(null), - generateKey: Validate.function(), - cache: internals.cachePolicy - }); - internals.methodObject = Validate.object({ - name: Validate.string().required(), - method: Validate.function().required(), - options: Validate.object() - }); - internals.register = Validate.object({ - once: true, - routes: Validate.object({ - prefix: Validate.string().pattern(/^\/.+/), - vhost: internals.vhost - }).default({}) - }); - internals.semver = Validate.string(); - internals.plugin = internals.register.keys({ - options: Validate.any(), - plugin: Validate.object({ - register: Validate.function().required(), - name: Validate.string().when("pkg.name", { is: Validate.exist(), otherwise: Validate.required() }), - version: Validate.string(), - multiple: Validate.boolean().default(false), - dependencies: [ - Validate.array().items(Validate.string()).single(), - Validate.object().pattern(/.+/, internals.semver) - ], - once: true, - requirements: Validate.object({ - hapi: Validate.string(), - node: Validate.string() - }).default(), - pkg: Validate.object({ - name: Validate.string(), - version: Validate.string().default("0.0.0") - }).unknown().default({}) - }).unknown() - }).without("once", "options").unknown(); - internals.rules = Validate.object({ - validate: Validate.object({ - schema: Validate.alternatives(Validate.object(), Validate.array()).required(), - options: Validate.object().default({ allowUnknown: true }) - }) - }); - } -}); -var require_decode = __commonJS({ - "node_modules/.deno/@hapi+call@9.0.1/node_modules/@hapi/call/lib/decode.js"(exports2) { - "use strict"; - var internals = {}; - exports2.decode = function(string3) { - let percentPos = string3.indexOf("%"); - if (percentPos === -1) { - return string3; - } - let decoded = ""; - let last = 0; - let codepoint = 0; - let startOfOctets = percentPos; - let state = internals.utf8.accept; - while (percentPos > -1 && percentPos < string3.length) { - const high = internals.resolveHex(string3[percentPos + 1], 4); - const low = internals.resolveHex(string3[percentPos + 2], 0); - const byte = high | low; - const type = internals.utf8.data[byte]; - state = internals.utf8.data[256 + state + type]; - codepoint = codepoint << 6 | byte & internals.utf8.data[364 + type]; - if (state === internals.utf8.accept) { - decoded += string3.slice(last, startOfOctets); - decoded += codepoint <= 65535 ? String.fromCharCode(codepoint) : String.fromCharCode(55232 + (codepoint >> 10), 56320 + (codepoint & 1023)); - codepoint = 0; - last = percentPos + 3; - percentPos = string3.indexOf("%", last); - startOfOctets = percentPos; - continue; - } - if (state === internals.utf8.reject) { - return null; - } - percentPos += 3; - if (percentPos >= string3.length || string3[percentPos] !== "%") { - return null; - } - } - return decoded + string3.slice(last); - }; - internals.resolveHex = function(char, shift) { - const i2 = internals.hex[char]; - return i2 === void 0 ? 255 : i2 << shift; - }; - internals.hex = { - "0": 0, - "1": 1, - "2": 2, - "3": 3, - "4": 4, - "5": 5, - "6": 6, - "7": 7, - "8": 8, - "9": 9, - "a": 10, - "A": 10, - "b": 11, - "B": 11, - "c": 12, - "C": 12, - "d": 13, - "D": 13, - "e": 14, - "E": 14, - "f": 15, - "F": 15 - }; - internals.utf8 = { - accept: 12, - reject: 0, - data: [ - // Maps bytes to character to a transition - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 6, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 8, - 7, - 7, - 10, - 9, - 9, - 9, - 11, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - // Maps a state to a new state when adding a transition - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12, - 0, - 0, - 0, - 0, - 24, - 36, - 48, - 60, - 72, - 84, - 96, - 0, - 12, - 12, - 12, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24, - 24, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 48, - 48, - 48, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 48, - 48, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 48, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - // Maps the current transition to a mask that needs to apply to the byte - 127, - 63, - 63, - 63, - 0, - 31, - 15, - 15, - 15, - 7, - 7, - 7 - ] - }; - } -}); -var require_regex = __commonJS({ - "node_modules/.deno/@hapi+call@9.0.1/node_modules/@hapi/call/lib/regex.js"(exports2) { - "use strict"; - exports2.generate = function() { - const empty2 = "(?:^\\/$)"; - const legalChars = "[\\w\\!\\$&'\\(\\)\\*\\+\\,;\\=\\:@\\-\\.~]"; - const encoded = "%[A-F0-9]{2}"; - const literalChar = "(?:" + legalChars + "|" + encoded + ")"; - const literal = literalChar + "+"; - const literalOptional = literalChar + "*"; - const midParam = "(?:\\{\\w+(?:\\*[1-9]\\d*)?\\})"; - const endParam = "(?:\\/(?:\\{\\w+(?:(?:\\*(?:[1-9]\\d*)?)|(?:\\?))?\\})?)?"; - const partialParam = "(?:\\{\\w+\\??\\})"; - const mixedParam = "(?:(?:" + literal + partialParam + ")+" + literalOptional + ")|(?:" + partialParam + "(?:" + literal + partialParam + ")+" + literalOptional + ")|(?:" + partialParam + literal + ")"; - const segmentContent = "(?:" + literal + "|" + midParam + "|" + mixedParam + ")"; - const segment = "\\/" + segmentContent; - const segments = "(?:" + segment + ")*"; - const path8 = "(?:^" + segments + endParam + "$)"; - const parseParam = "(" + literal + ")|(?:\\{(\\w+)(?:(\\*)(\\d+)?)?(\\?)?\\})"; - const expressions = { - parseParam: new RegExp(parseParam, "g"), - validatePath: new RegExp(empty2 + "|" + path8), - validatePathEncoded: /%(?:2[146-9A-E]|3[\dABD]|4[\dA-F]|5[\dAF]|6[1-9A-F]|7[\dAE])/g - }; - return expressions; - }; - } -}); -var require_segment = __commonJS({ - "node_modules/.deno/@hapi+call@9.0.1/node_modules/@hapi/call/lib/segment.js"(exports2, module14) { - "use strict"; - var Hoek = require_lib(); - var internals = {}; - exports2 = module14.exports = internals.Segment = function() { - this._edge = null; - this._fulls = null; - this._literals = null; - this._param = null; - this._mixed = null; - this._wildcard = null; - }; - internals.Segment.prototype.add = function(segments, record2) { - const current = segments[0]; - const remaining = segments.slice(1); - const isEdge = !remaining.length; - const literals = []; - let isLiteral = true; - for (let i2 = 0; i2 < segments.length && isLiteral; ++i2) { - isLiteral = segments[i2].literal !== void 0; - literals.push(segments[i2].literal); - } - if (isLiteral) { - this._fulls = this._fulls ?? /* @__PURE__ */ new Map(); - let literal = "/" + literals.join("/"); - if (!record2.settings.isCaseSensitive) { - literal = literal.toLowerCase(); - } - Hoek.assert(!this._fulls.has(literal), "New route", record2.path, "conflicts with existing", this._fulls.get(literal)?.record.path); - this._fulls.set(literal, { segment: current, record: record2 }); - } else if (current.literal !== void 0) { - this._literals = this._literals ?? /* @__PURE__ */ new Map(); - const currentLiteral = record2.settings.isCaseSensitive ? current.literal : current.literal.toLowerCase(); - if (!this._literals.has(currentLiteral)) { - this._literals.set(currentLiteral, new internals.Segment()); - } - this._literals.get(currentLiteral).add(remaining, record2); - } else if (current.wildcard) { - Hoek.assert(!this._wildcard, "New route", record2.path, "conflicts with existing", this._wildcard?.record.path); - Hoek.assert(!this._param || !this._param._wildcard, "New route", record2.path, "conflicts with existing", this._param?._wildcard?.record.path); - this._wildcard = { segment: current, record: record2 }; - } else if (current.mixed) { - this._mixed = this._mixed ?? []; - let mixed = this._mixedLookup(current); - if (!mixed) { - mixed = { segment: current, node: new internals.Segment() }; - this._mixed.push(mixed); - this._mixed.sort(internals.mixed); - } - if (isEdge) { - Hoek.assert(!mixed.node._edge, "New route", record2.path, "conflicts with existing", mixed.node._edge?.record.path); - mixed.node._edge = { segment: current, record: record2 }; - } else { - mixed.node.add(remaining, record2); - } - } else { - this._param = this._param ?? new internals.Segment(); - if (isEdge) { - Hoek.assert(!this._param._edge, "New route", record2.path, "conflicts with existing", this._param._edge?.record.path); - this._param._edge = { segment: current, record: record2 }; - } else { - Hoek.assert(!this._wildcard || !remaining[0].wildcard, "New route", record2.path, "conflicts with existing", this._wildcard?.record.path); - this._param.add(remaining, record2); - } - } - }; - internals.Segment.prototype._mixedLookup = function(segment) { - for (let i2 = 0; i2 < this._mixed.length; ++i2) { - if (internals.mixed({ segment }, this._mixed[i2]) === 0) { - return this._mixed[i2]; - } - } - return null; - }; - internals.mixed = function(a, b) { - const aFirst = -1; - const bFirst = 1; - const as = a.segment; - const bs = b.segment; - if (as.length !== bs.length) { - return as.length > bs.length ? aFirst : bFirst; - } - if (as.first !== bs.first) { - return as.first ? bFirst : aFirst; - } - for (let i2 = 0; i2 < as.segments.length; ++i2) { - const am = as.segments[i2]; - const bm = bs.segments[i2]; - if (am === bm) { - continue; - } - if (am.length === bm.length) { - return am > bm ? bFirst : aFirst; - } - return am.length < bm.length ? bFirst : aFirst; - } - return 0; - }; - internals.Segment.prototype.lookup = function(path8, segments, options2) { - let match = null; - if (this._fulls) { - match = this._fulls.get(options2.isCaseSensitive ? path8 : path8.toLowerCase()); - if (match) { - return { record: match.record, array: [] }; - } - } - const current = segments[0]; - const nextPath = path8.slice(current.length + 1); - const remainder = segments.length > 1 ? segments.slice(1) : null; - if (this._literals) { - const literal = options2.isCaseSensitive ? current : current.toLowerCase(); - match = this._literals.get(literal); - if (match) { - const record2 = internals.deeper(match, nextPath, remainder, [], options2); - if (record2) { - return record2; - } - } - } - if (this._mixed) { - for (let i2 = 0; i2 < this._mixed.length; ++i2) { - match = this._mixed[i2]; - const params = current.match(match.segment.mixed); - if (params) { - const array2 = []; - for (let j = 1; j < params.length; ++j) { - array2.push(params[j]); - } - const record2 = internals.deeper(match.node, nextPath, remainder, array2, options2); - if (record2) { - return record2; - } - } - } - } - if (this._param) { - if (current || this._param._edge?.segment.empty) { - const record2 = internals.deeper(this._param, nextPath, remainder, [current], options2); - if (record2) { - return record2; - } - } - } - if (this._wildcard) { - return { record: this._wildcard.record, array: [path8.slice(1)] }; - } - return null; - }; - internals.deeper = function(match, path8, segments, array2, options2) { - if (!segments) { - if (match._edge) { - return { record: match._edge.record, array: array2 }; - } - if (match._wildcard) { - return { record: match._wildcard.record, array: array2 }; - } - } else { - const result = match.lookup(path8, segments, options2); - if (result) { - return { record: result.record, array: array2.concat(result.array) }; - } - } - return null; - }; - } -}); -var require_lib14 = __commonJS({ - "node_modules/.deno/@hapi+call@9.0.1/node_modules/@hapi/call/lib/index.js"(exports2) { - "use strict"; - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var Decode = require_decode(); - var Regex = require_regex(); - var Segment = require_segment(); - var internals = { - pathRegex: Regex.generate(), - defaults: { - isCaseSensitive: true - } - }; - exports2.Router = internals.Router = function(options2) { - this.settings = Hoek.applyToDefaults(internals.defaults, options2 || {}); - this.routes = /* @__PURE__ */ new Map(); - this.ids = /* @__PURE__ */ new Map(); - this.vhosts = null; - this.specials = { - badRequest: null, - notFound: null, - options: null - }; - }; - internals.Router.prototype.add = function(config2, route2) { - const method = config2.method.toLowerCase(); - const vhost = config2.vhost || "*"; - if (vhost !== "*") { - this.vhosts = this.vhosts ?? /* @__PURE__ */ new Map(); - if (!this.vhosts.has(vhost)) { - this.vhosts.set(vhost, /* @__PURE__ */ new Map()); - } - } - const table = vhost === "*" ? this.routes : this.vhosts.get(vhost); - if (!table.has(method)) { - table.set(method, { routes: [], router: new Segment() }); - } - const analysis = config2.analysis ?? this.analyze(config2.path); - const record2 = { - path: config2.path, - route: route2 || config2.path, - segments: analysis.segments, - params: analysis.params, - fingerprint: analysis.fingerprint, - settings: this.settings - }; - const map = table.get(method); - map.router.add(analysis.segments, record2); - map.routes.push(record2); - map.routes.sort(internals.sort); - const last = record2.segments[record2.segments.length - 1]; - if (last.empty) { - map.router.add(analysis.segments.slice(0, -1), record2); - } - if (config2.id) { - Hoek.assert(!this.ids.has(config2.id), "Route id", config2.id, "for path", config2.path, "conflicts with existing path", this.ids.has(config2.id) && this.ids.get(config2.id).path); - this.ids.set(config2.id, record2); - } - return record2; - }; - internals.Router.prototype.special = function(type, route2) { - Hoek.assert(Object.keys(this.specials).indexOf(type) !== -1, "Unknown special route type:", type); - this.specials[type] = { route: route2 }; - }; - internals.Router.prototype.route = function(method, path8, hostname2) { - const segments = path8.length === 1 ? [""] : path8.split("/").slice(1); - const vhost = this.vhosts && hostname2 && this.vhosts.get(hostname2); - const route2 = vhost && this._lookup(path8, segments, vhost, method) || this._lookup(path8, segments, this.routes, method) || method === "head" && vhost && this._lookup(path8, segments, vhost, "get") || method === "head" && this._lookup(path8, segments, this.routes, "get") || method === "options" && this.specials.options || vhost && this._lookup(path8, segments, vhost, "*") || this._lookup(path8, segments, this.routes, "*") || this.specials.notFound || Boom5.notFound(); - return route2; - }; - internals.Router.prototype._lookup = function(path8, segments, table, method) { - const set = table.get(method); - if (!set) { - return null; - } - const match = set.router.lookup(path8, segments, this.settings); - if (!match) { - return null; - } - const assignments = {}; - const array2 = []; - for (let i2 = 0; i2 < match.array.length; ++i2) { - const name = match.record.params[i2]; - const value = Decode.decode(match.array[i2]); - if (value === null) { - return this.specials.badRequest ?? Boom5.badRequest("Invalid request path"); - } - if (assignments[name] !== void 0) { - assignments[name] = assignments[name] + "/" + value; - } else { - assignments[name] = value; - } - if (i2 + 1 === match.array.length || // Only include the last segment of a multi-segment param - name !== match.record.params[i2 + 1]) { - array2.push(assignments[name]); - } - } - return { params: assignments, paramsArray: array2, route: match.record.route }; - }; - internals.Router.prototype.normalize = function(path8) { - if (path8 && path8.indexOf("%") !== -1) { - const uppercase2 = path8.replace(/%[0-9a-fA-F][0-9a-fA-F]/g, (encoded) => encoded.toUpperCase()); - const decoded = uppercase2.replace(/%(?:2[146-9A-E]|3[\dABD]|4[\dA-F]|5[\dAF]|6[1-9A-F]|7[\dAE])/g, (encoded) => String.fromCharCode(parseInt(encoded.substring(1), 16))); - path8 = decoded; - } - if (path8 && (path8.indexOf("/.") !== -1 || path8[0] === ".")) { - const hasLeadingSlash = path8[0] === "/"; - const segments = path8.split("/"); - const normalized = []; - let segment; - for (let i2 = 0; i2 < segments.length; ++i2) { - segment = segments[i2]; - if (segment === "..") { - normalized.pop(); - } else if (segment !== ".") { - normalized.push(segment); - } - } - if (segment === "." || segment === "..") { - normalized.push(""); - } - path8 = normalized.join("/"); - if (path8[0] !== "/" && hasLeadingSlash) { - path8 = "/" + path8; - } - } - return path8; - }; - internals.Router.prototype.analyze = function(path8) { - Hoek.assert(internals.pathRegex.validatePath.test(path8), "Invalid path:", path8); - Hoek.assert(!internals.pathRegex.validatePathEncoded.test(path8), "Path cannot contain encoded non-reserved path characters:", path8); - const pathParts = path8.split("/"); - const segments = []; - const params = []; - const fingers = []; - for (let i2 = 1; i2 < pathParts.length; ++i2) { - let segment = pathParts[i2]; - if (segment.indexOf("{") === -1) { - segment = this.settings.isCaseSensitive ? segment : segment.toLowerCase(); - fingers.push(segment); - segments.push({ literal: segment }); - continue; - } - const parts = internals.parseParams(segment); - if (parts.length === 1) { - const item = parts[0]; - Hoek.assert(params.indexOf(item.name) === -1, "Cannot repeat the same parameter name:", item.name, "in:", path8); - params.push(item.name); - if (item.wildcard) { - if (item.count) { - for (let j = 0; j < item.count; ++j) { - fingers.push("?"); - segments.push({}); - if (j) { - params.push(item.name); - } - } - } else { - fingers.push("#"); - segments.push({ wildcard: true }); - } - } else { - fingers.push("?"); - segments.push({ empty: item.empty }); - } - } else { - const seg = { - length: parts.length, - first: typeof parts[0] !== "string", - segments: [] - }; - let finger = ""; - let regex = "^"; - for (let j = 0; j < parts.length; ++j) { - const part = parts[j]; - if (typeof part === "string") { - finger = finger + part; - regex = regex + Hoek.escapeRegex(part); - seg.segments.push(part); - } else { - Hoek.assert(params.indexOf(part.name) === -1, "Cannot repeat the same parameter name:", part.name, "in:", path8); - params.push(part.name); - finger = finger + "?"; - regex = regex + "(." + (part.empty ? "*" : "+") + ")"; - } - } - seg.mixed = new RegExp(regex + "$", !this.settings.isCaseSensitive ? "i" : ""); - fingers.push(finger); - segments.push(seg); - } - } - return { - segments, - fingerprint: "/" + fingers.join("/"), - params - }; - }; - internals.parseParams = function(segment) { - const parts = []; - segment.replace(internals.pathRegex.parseParam, ($0, literal, name, wildcard, count, empty2) => { - if (literal) { - parts.push(literal); - } else { - parts.push({ - name, - wildcard: !!wildcard, - count: count && parseInt(count, 10), - empty: !!empty2 - }); - } - return ""; - }); - return parts; - }; - internals.Router.prototype.table = function(host) { - const result = []; - const collect = (table) => { - if (!table) { - return; - } - for (const map of table.values()) { - for (const record2 of map.routes) { - result.push(record2.route); - } - } - }; - if (this.vhosts) { - const vhosts = host ? [].concat(host) : [...this.vhosts.keys()]; - for (const vhost of vhosts) { - collect(this.vhosts.get(vhost)); - } - } - collect(this.routes); - return result; - }; - internals.sort = function(a, b) { - const aFirst = -1; - const bFirst = 1; - const as = a.segments; - const bs = b.segments; - if (as.length !== bs.length) { - return as.length > bs.length ? bFirst : aFirst; - } - for (let i2 = 0; ; ++i2) { - if (as[i2].literal) { - if (bs[i2].literal) { - if (as[i2].literal === bs[i2].literal) { - continue; - } - return as[i2].literal > bs[i2].literal ? bFirst : aFirst; - } - return aFirst; - } - if (bs[i2].literal) { - return bFirst; - } - return as[i2].wildcard ? bFirst : aFirst; - } - }; - } -}); -var require_client2 = __commonJS({ - "node_modules/.deno/@hapi+catbox@12.1.1/node_modules/@hapi/catbox/lib/client.js"(exports2, module14) { - "use strict"; - var Hoek = require_lib(); - var Boom5 = require_lib2(); - var internals = { - validate: Symbol("validate") - }; - internals.defaults = { - partition: "catbox" - }; - module14.exports = class { - constructor(engine, options2) { - Hoek.assert(engine, "Missing catbox client engine"); - Hoek.assert(typeof engine === "object" && typeof engine.start === "function" || typeof engine === "function", "engine must be an engine object or engine prototype (function)"); - Hoek.assert(typeof engine === "function" || !options2, "Can only specify options with function engine config"); - const settings = Object.assign({}, internals.defaults, options2); - Hoek.assert(settings.partition.match(/^[\w\-]+$/), "Invalid partition name:" + settings.partition); - this.connection = typeof engine === "object" ? engine : new engine(settings); - } - async start() { - await this.connection.start(); - } - async stop() { - await this.connection.stop(); - } - isReady() { - return this.connection.isReady(); - } - validateSegmentName(name) { - return this.connection.validateSegmentName(name); - } - async get(key) { - this[internals.validate](key, null); - if (key === null) { - return null; - } - const result = await this.connection.get(key); - if (!result || result.item === void 0 || result.item === null) { - return null; - } - const now = Date.now(); - const expires = result.stored + result.ttl; - const ttl = expires - now; - if (ttl <= 0) { - return null; - } - const cached2 = { - item: result.item, - stored: result.stored, - ttl - }; - return cached2; - } - async set(key, value, ttl) { - this[internals.validate](key); - if (ttl <= 0) { - return; - } - await this.connection.set(key, value, ttl); - } - async drop(key) { - this[internals.validate](key); - await this.connection.drop(key); - } - [internals.validate](key, allow = {}) { - if (!this.isReady()) { - throw Boom5.internal("Disconnected"); - } - const isValidKey2 = key && typeof key.id === "string" && key.segment && typeof key.segment === "string"; - if (!isValidKey2 && key !== allow) { - throw Boom5.internal("Invalid key"); - } - } - }; - } -}); -var require_lib15 = __commonJS({ - "node_modules/.deno/@hapi+podium@5.0.2/node_modules/@hapi/podium/lib/index.js"(exports2) { - "use strict"; - var Hoek = require_lib(); - var Teamwork = require_lib11(); - var Validate = require_lib9(); - var internals = { - schema: { - base: Validate.object({ - name: Validate.string().required(), - clone: Validate.boolean(), - tags: Validate.boolean(), - spread: Validate.boolean(), - channels: Validate.array().items(Validate.string()).single().unique().min(1).cast("set") - }) - } - }; - internals.schema.event = internals.schema.base.keys({ - shared: Validate.boolean() - }); - internals.schema.listener = internals.schema.base.keys({ - listener: Validate.func().required(), - context: Validate.object(), - count: Validate.number().integer().min(1), - filter: { - tags: Validate.array().items(Validate.string()).single().unique().min(1).required(), - all: Validate.boolean() - } - }); - exports2.validate = function(events) { - const normalized = []; - events = [].concat(events); - for (let event of events) { - if (typeof event === "string") { - event = { name: event }; - } - normalized.push(Validate.attempt(event, internals.schema.event, "Invalid event options")); - } - return normalized; - }; - exports2.Podium = class { - /** @type {Map} */ - #listeners = /* @__PURE__ */ new Map(); - constructor(events, options2) { - if (events) { - this.registerEvent(events, options2); - } - } - registerEvent(events, options2) { - events = [].concat(events); - for (let event of events) { - if (typeof event === "string") { - event = { name: event }; - } - if (options2?.validate !== false) { - event = Validate.attempt(event, internals.schema.event, "Invalid event options"); - } - const name = event.name; - if (this.#listeners.has(name)) { - Hoek.assert(event.shared, `Event ${name} exists`); - continue; - } - this.#listeners.set(name, new internals.EventListener(event)); - } - } - emit(criteria, data) { - let thrownErr; - this.#emitToEachListener(criteria, data, ([err]) => { - thrownErr = thrownErr ?? err; - }); - if (thrownErr) { - throw thrownErr; - } - } - async gauge(criteria, data) { - const promises = []; - this.#emitToEachListener(criteria, data, ([err, result]) => { - promises.push(err ? Promise.reject(err) : result); - }); - return await Promise.allSettled(promises); - } - #emitToEachListener(criteria, data, fn) { - criteria = internals.criteria(criteria); - const name = criteria.name; - Hoek.assert(name, "Criteria missing event name"); - const event = this.#listeners.get(name); - Hoek.assert(event, `Unknown event ${name}`); - if (!event.handlers) { - return; - } - Hoek.assert(!criteria.channel || typeof criteria.channel === "string", "Invalid channel name"); - Hoek.assert(!criteria.channel || !event.flags.channels || event.flags.channels.has(criteria.channel), `Unknown ${criteria.channel} channel`); - Hoek.assert(!event.flags.spread || Array.isArray(data) || typeof data === "function", "Data must be an array for spread event"); - if (typeof criteria.tags === "string") { - criteria = { ...criteria }; - criteria.tags = { [criteria.tags]: true }; - } - if (criteria.tags && Array.isArray(criteria.tags)) { - const tags = {}; - for (const tag3 of criteria.tags) { - tags[tag3] = true; - } - criteria = { ...criteria }; - criteria.tags = tags; - } - let generated = false; - for (const handler of event.handlers) { - if (handler.channels && !(criteria.channel && handler.channels.has(criteria.channel))) { - continue; - } - if (handler.filter) { - if (!criteria.tags) { - continue; - } - const match = Hoek.intersect(criteria.tags, handler.filter.tags, { first: !handler.filter.all }); - if (!match || handler.filter.all && match.length !== handler.filter.tags.length) { - continue; - } - } - if (handler.count) { - --handler.count; - if (handler.count < 1) { - event.removeListener(handler.listener); - } - } - if (!generated && typeof data === "function") { - data = data(); - generated = true; - } - const update = event.flagged("clone", handler) ? Hoek.clone(data) : data; - const args = event.flagged("spread", handler) && Array.isArray(update) ? update.slice(0) : [update]; - if (event.flagged("tags", handler) && criteria.tags) { - args.push(criteria.tags); - } - try { - if (handler.context) { - fn([null, handler.listener.apply(handler.context, args)]); - } else { - fn([null, handler.listener(...args)]); - } - } catch (err) { - fn([err, null]); - } - } - } - addListener(criteria, listener, context) { - criteria = internals.criteria(criteria); - criteria.listener = listener; - criteria.context = context; - if (criteria.filter && (typeof criteria.filter === "string" || Array.isArray(criteria.filter))) { - criteria = { ...criteria }; - criteria.filter = { tags: criteria.filter }; - } - criteria = Validate.attempt(criteria, internals.schema.listener, "Invalid event listener options"); - const name = criteria.name; - const event = this.#listeners.get(name); - Hoek.assert(event, `Unknown event ${name}`); - event.addHandler(criteria); - return this; - } - on(criteria, listener, context) { - return this.addListener(criteria, listener, context); - } - once(criteria, listener, context) { - criteria = { ...internals.criteria(criteria), count: 1 }; - if (listener) { - return this.addListener(criteria, listener, context); - } - return new Promise((resolve82) => { - this.addListener(criteria, (...args) => resolve82(args)); - }); - } - few(criteria) { - Hoek.assert(typeof criteria === "object", "Criteria must be an object"); - Hoek.assert(criteria.count, "Criteria must include a count limit"); - const team = new Teamwork.Team({ meetings: criteria.count }); - this.addListener(criteria, (...args) => team.attend(args)); - return team.work; - } - removeListener(name, listener) { - Hoek.assert(this.#listeners.has(name), `Unknown event ${name}`); - Hoek.assert(typeof listener === "function", "Listener must be a function"); - this.#listeners.get(name).removeListener(listener); - return this; - } - off(name, listener) { - return this.removeListener(name, listener); - } - removeAllListeners(name) { - Hoek.assert(this.#listeners.has(name), `Unknown event ${name}`); - this.#listeners.get(name).handlers = null; - return this; - } - hasListeners(name) { - Hoek.assert(this.#listeners.has(name), `Unknown event ${name}`); - return !!this.#listeners.get(name).handlers; - } - }; - internals.EventListener = class { - constructor(flags) { - this.flags = flags; - this.handlers = null; - } - addHandler(handler) { - Hoek.assert(!handler.channels || !this.flags.channels || Hoek.intersect(this.flags.channels, handler.channels).length === handler.channels.size, `Unknown event channels ${handler.channels && [...handler.channels].join(", ")}`); - this.handlers = this.handlers ? [...this.handlers, handler] : [handler]; - } - removeListener(listener) { - const filtered = this.handlers?.filter((item) => item.listener !== listener); - this.handlers = filtered?.length ? filtered : null; - } - flagged(name, handler) { - return handler[name] ?? this.flags[name] ?? false; - } - }; - internals.criteria = function(criteria) { - if (typeof criteria === "string") { - return { name: criteria }; - } - return criteria; - }; - } -}); -var require_pending = __commonJS({ - "node_modules/.deno/@hapi+catbox@12.1.1/node_modules/@hapi/catbox/lib/pending.js"(exports2, module14) { - "use strict"; - exports2 = module14.exports = class { - id = null; - timeout = null; - count = 1; - rule = null; - resolve = null; - reject = null; - constructor(id, rule) { - this.id = id; - this.rule = rule; - this.promise = new Promise((resolve82, reject) => { - this.resolve = resolve82; - this.reject = reject; - }); - } - join() { - ++this.count; - return this.promise; - } - send(err, value, cached2, report) { - clearTimeout(this.timeout); - if (err && !cached2) { - this.reject(err); - return; - } - if (!this.rule.getDecoratedValue) { - this.resolve(value); - return; - } - if (err) { - report.error = err; - } - this.resolve({ value, cached: cached2, report }); - } - setTimeout(fn, timeoutMs) { - clearTimeout(this.timeout); - this.timeout = setTimeout(fn, timeoutMs); - } - }; - } -}); -var require_policy = __commonJS({ - "node_modules/.deno/@hapi+catbox@12.1.1/node_modules/@hapi/catbox/lib/policy.js"(exports2, module14) { - "use strict"; - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var Podium = require_lib15(); - var Validate = require_lib9(); - var Pending = require_pending(); - var internals = { - day: 24 * 60 * 60 * 1e3, - events: Podium.validate([ - { name: "error", channels: ["generate", "persist"] } - ]) - }; - internals.schema = Validate.object({ - expiresIn: Validate.number().integer().min(1), - expiresAt: Validate.string().regex(/^\d\d?\:\d\d$/), - staleIn: [ - Validate.number().integer().min(1).when("expiresAt", { is: Validate.required(), then: Validate.number().max(864e5 - 1) }), - // One day - 1 (max is inclusive) - Validate.func() - ], - staleTimeout: Validate.number().integer().min(1), - generateFunc: Validate.func(), - generateTimeout: Validate.number().integer().min(1).allow(false), - generateOnReadError: Validate.boolean(), - generateIgnoreWriteError: Validate.boolean(), - dropOnError: Validate.boolean(), - pendingGenerateTimeout: Validate.number().integer().min(1), - getDecoratedValue: Validate.boolean().default(false), - // Ignored external keys (hapi) - privacy: Validate.any(), - cache: Validate.any(), - segment: Validate.any(), - shared: Validate.any() - }).without("expiresIn", "expiresAt").with("staleIn", "generateFunc").with("generateOnReadError", "generateFunc").with("generateIgnoreWriteError", "generateFunc").with("dropOnError", "generateFunc").and("generateFunc", "generateTimeout").and("staleIn", "staleTimeout"); - exports2 = module14.exports = internals.Policy = class { - rule = null; - stats = { - sets: 0, - gets: 0, - hits: 0, - stales: 0, - generates: 0, - errors: 0 - }; - _events = null; - _cache = null; - _segment = null; - _pendings = /* @__PURE__ */ new Map(); - // id -> Pending - _pendingGenerateCall = /* @__PURE__ */ new Map(); - // id -> timer - constructor(options2, cache2, segment) { - this._cache = cache2; - this.rules(options2); - if (cache2) { - const nameErr = cache2.validateSegmentName(segment); - Hoek.assert(nameErr === null, "Invalid segment name: " + segment + (nameErr ? " (" + nameErr.message + ")" : "")); - this._segment = segment; - } - } - get client() { - return this._cache; - } - get events() { - if (!this._events) { - this._events = new Podium.Podium(internals.events, { validate: false }); - } - return this._events; - } - _error(source, error2) { - if (!this._events) { - return; - } - this._events.emit({ name: "error", channel: source }, { source, error: error2 }); - } - rules(options2) { - this.rule = internals.Policy.compile(options2, !!this._cache); - } - async get(key) { - ++this.stats.gets; - if (!key || typeof key === "string") { - key = { id: key, string: true }; - } - let pending = this._pendings.get(key.id); - if (pending !== void 0) { - return pending.join(); - } - pending = new Pending(key.id, this.rule); - this._pendings.set(key.id, pending); - try { - await this._get(pending, key); - } catch (err) { - this._send(key, err); - } - return pending.promise; - } - async _get(pending, key) { - const report = {}; - const timer2 = new Hoek.Bench(); - if (this._cache) { - try { - var cached2 = await this._cache.get({ segment: this._segment, id: key.id }); - } catch (err) { - report.error = err; - ++this.stats.errors; - this._error("persist", err); - } - } - report.msec = timer2.elapsed(); - if (cached2) { - report.stored = cached2.stored; - report.ttl = cached2.ttl; - const staleIn = typeof this.rule.staleIn === "function" ? this.rule.staleIn(cached2.stored, cached2.ttl) : this.rule.staleIn; - cached2.isStale = staleIn ? Date.now() - cached2.stored >= staleIn : false; - report.isStale = cached2.isStale; - if (cached2.isStale) { - ++this.stats.stales; - } - } - if (!this.rule.generateFunc || report.error && !this.rule.generateOnReadError) { - this._send(key, report.error, cached2 ? cached2.item : null, cached2, report); - return; - } - if (cached2 && !cached2.isStale) { - this._send(key, null, cached2.item, cached2, report); - return; - } - return Promise.race([ - pending.promise, - this._generate(pending, key, cached2, report) - ]); - } - _generate(pending, key, cached2, report) { - if (cached2) { - cached2.ttl = cached2.ttl - this.rule.staleTimeout; - } - if (cached2 && cached2.ttl > 0) { - pending.setTimeout(() => this._send(key, null, cached2.item, cached2, report), this.rule.staleTimeout); - } else if (this.rule.generateTimeout) { - pending.setTimeout(() => this._send(key, Boom5.serverUnavailable(), null, null, report), this.rule.generateTimeout); - } - if (this._pendingGenerateCall.has(key.id)) { - return; - } - ++this.stats.generates; - if (this.rule.pendingGenerateTimeout) { - const timeout = setTimeout(() => this._pendingGenerateCall.delete(key.id), this.rule.pendingGenerateTimeout); - this._pendingGenerateCall.set(key.id, timeout); - } - return this._callGenerateFunc(key, cached2, report); - } - async _callGenerateFunc(key, cached2, report) { - const flags = {}; - try { - var value = await this.rule.generateFunc(key.string ? key.id : key, flags); - } catch (err) { - var generateError = err; - this._error("generate", err); - } - const pendingTimeout = this._pendingGenerateCall.get(key.id); - if (pendingTimeout) { - clearTimeout(pendingTimeout); - this._pendingGenerateCall.delete(key.id); - } - try { - if (flags.ttl === 0 || // null or undefined means use policy - generateError && this.rule.dropOnError) { - await this.drop(key.id); - } else if (!generateError) { - await this.set(key.id, value, flags.ttl); - } - } catch (err) { - var persistError = err; - this._error("persist", err); - } - const error2 = generateError || (this.rule.generateIgnoreWriteError ? null : persistError); - if (cached2 && error2 && !this.rule.dropOnError) { - this._send(key, error2, cached2.item, cached2, report); - return; - } - this._send(key, error2, value, null, report); - } - _send(key, err, value, cached2, report) { - const pending = this._pendings.get(key.id); - if (!pending) { - return; - } - this._pendings.delete(key.id); - pending.send(err, value, cached2, report); - if (report?.isStale !== void 0) { - this.stats.hits = this.stats.hits + pending.count; - } - } - async set(key, value, ttl) { - ++this.stats.sets; - if (!this._cache) { - return; - } - try { - await this._cache.set({ segment: this._segment, id: internals.id(key) }, value, ttl || internals.Policy.ttl(this.rule)); - } catch (err) { - ++this.stats.errors; - throw err; - } - } - async drop(key) { - if (!this._cache) { - return; - } - try { - await this._cache.drop({ segment: this._segment, id: internals.id(key) }); - return; - } catch (err) { - ++this.stats.errors; - throw err; - } - } - ttl(created) { - return internals.Policy.ttl(this.rule, created); - } - isReady() { - if (!this._cache) { - return false; - } - return this._cache.connection.isReady(); - } - static compile(options2, serverSide) { - const rule = {}; - if (!options2 || !Object.keys(options2).length) { - return rule; - } - options2 = Validate.attempt(options2, internals.schema, "Invalid cache policy configuration"); - const hasExpiresIn = options2.expiresIn !== void 0 && options2.expiresIn !== null; - const hasExpiresAt = options2.expiresAt !== void 0 && options2.expiresAt !== null; - Hoek.assert(!hasExpiresIn || !options2.staleIn || typeof options2.staleIn === "function" || options2.staleIn < options2.expiresIn, "staleIn must be less than expiresIn"); - Hoek.assert(!options2.staleIn || serverSide, "Cannot use stale options without server-side caching"); - Hoek.assert(!options2.staleTimeout || !hasExpiresIn || options2.staleTimeout < options2.expiresIn, "staleTimeout must be less than expiresIn"); - Hoek.assert(!options2.staleTimeout || !hasExpiresIn || typeof options2.staleIn === "function" || options2.staleTimeout < options2.expiresIn - options2.staleIn, "staleTimeout must be less than the delta between expiresIn and staleIn"); - Hoek.assert(!options2.staleTimeout || !options2.pendingGenerateTimeout || options2.staleTimeout < options2.pendingGenerateTimeout, "pendingGenerateTimeout must be greater than staleTimeout if specified"); - if (hasExpiresAt) { - const time3 = /^(\d\d?):(\d\d)$/.exec(options2.expiresAt); - rule.expiresAt = { - hours: parseInt(time3[1], 10), - minutes: parseInt(time3[2], 10) - }; - } else { - rule.expiresIn = options2.expiresIn ?? 0; - } - if (options2.generateFunc) { - rule.generateFunc = options2.generateFunc; - rule.generateTimeout = options2.generateTimeout; - if (options2.staleIn) { - rule.staleIn = options2.staleIn; - rule.staleTimeout = options2.staleTimeout; - } - rule.dropOnError = options2.dropOnError !== void 0 ? options2.dropOnError : true; - rule.pendingGenerateTimeout = options2.pendingGenerateTimeout !== void 0 ? options2.pendingGenerateTimeout : 0; - } - rule.generateOnReadError = options2.generateOnReadError !== void 0 ? options2.generateOnReadError : true; - rule.generateIgnoreWriteError = options2.generateIgnoreWriteError !== void 0 ? options2.generateIgnoreWriteError : true; - rule.getDecoratedValue = options2.getDecoratedValue; - return rule; - } - static ttl(rule, created, now) { - now = now ?? Date.now(); - created = created ?? now; - const age = now - created; - if (age < 0) { - return 0; - } - if (rule.expiresIn) { - return Math.max(rule.expiresIn - age, 0); - } - if (rule.expiresAt) { - if (age > internals.day) { - return 0; - } - const expiresAt = new Date(created); - expiresAt.setHours(rule.expiresAt.hours); - expiresAt.setMinutes(rule.expiresAt.minutes); - expiresAt.setSeconds(0); - expiresAt.setMilliseconds(0); - let expires = expiresAt.getTime(); - if (expires <= created) { - expires = expires + internals.day; - } - if (now >= expires) { - return 0; - } - return expires - now; - } - return 0; - } - }; - internals.id = function(key) { - return key && typeof key === "object" ? key.id : key; - }; - } -}); -var require_lib16 = __commonJS({ - "node_modules/.deno/@hapi+catbox@12.1.1/node_modules/@hapi/catbox/lib/index.js"(exports2) { - "use strict"; - var Client = require_client2(); - var Policy = require_policy(); - exports2.Client = Client; - exports2.Policy = exports2.policy = Policy; - } -}); -var require_lib17 = __commonJS({ - "node_modules/.deno/@hapi+catbox-memory@6.0.2/node_modules/@hapi/catbox-memory/lib/index.js"(exports2) { - "use strict"; - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var internals = { - maxTimer: 2147483647, - // 2 ^ 31 - 1 - entrySize: 144 - // Approximate cache entry size without value: 144 bytes - }; - internals.defaults = { - maxByteSize: 100 * 1024 * 1024, - // 100MB - minCleanupIntervalMsec: 1e3, - cloneBuffersOnGet: false - }; - exports2.Engine = class CatboxMemoryEngine { - constructor(options2 = {}) { - Hoek.assert(options2.maxByteSize === void 0 || options2.maxByteSize >= 0, "Invalid cache maxByteSize value"); - Hoek.assert(options2.allowMixedContent === void 0, "allowMixedContent no longer supported"); - Hoek.assert(options2.minCleanupIntervalMsec === void 0 || options2.minCleanupIntervalMsec < internals.maxTimer, "Invalid cache minCleanupIntervalMsec value"); - Hoek.assert(options2.cloneBuffersOnGet === void 0 || typeof options2.cloneBuffersOnGet === "boolean", "Invalid cloneBuffersOnGet value"); - this.settings = Hoek.applyToDefaults(internals.defaults, options2); - this.cache = null; - this._timer = null; - this._timerDue = null; - } - start() { - if (!this.cache) { - this.cache = /* @__PURE__ */ new Map(); - this.byteSize = 0; - } - } - _scheduleCleanup(msec) { - const cleanup = () => { - this._timer = null; - this._timerDue = null; - const now2 = Date.now(); - let next = Infinity; - for (const [, segment] of this.cache) { - for (const [id, envelope] of segment) { - const ttl = envelope.stored + envelope.ttl - now2; - if (ttl <= 0) { - segment.delete(id); - this.byteSize -= envelope.byteSize; - } else { - next = Math.min(next, ttl); - } - } - } - if (next !== Infinity) { - this._scheduleCleanup(next); - } - }; - const now = Date.now(); - const timeout = Math.min(Math.max(this.settings.minCleanupIntervalMsec, msec), internals.maxTimer); - if (this._timer) { - if (this._timerDue - now < msec) { - return; - } - clearTimeout(this._timer); - } - this._timerDue = now + timeout; - this._timer = setTimeout(cleanup, timeout); - } - stop() { - clearTimeout(this._timer); - this._timer = null; - this._timerDue = null; - this.cache = null; - this.byteSize = 0; - } - isReady() { - return !!this.cache; - } - validateSegmentName(name) { - if (!name) { - throw new Boom5.Boom("Empty string"); - } - if (name.indexOf("\0") !== -1) { - throw new Boom5.Boom("Includes null character"); - } - return null; - } - get(key) { - if (!this.cache) { - throw new Boom5.Boom("Connection not started"); - } - const segment = this.cache.get(key.segment); - if (!segment) { - return null; - } - const envelope = segment.get(key.id); - if (!envelope) { - return null; - } - if (envelope.stored + envelope.ttl < Date.now()) { - this.drop(key); - return null; - } - let item = null; - if (Buffer.isBuffer(envelope.item)) { - item = envelope.item; - if (this.settings.cloneBuffersOnGet) { - const copy2 = Buffer.alloc(item.length); - item.copy(copy2); - item = copy2; - } - } else { - try { - item = JSON.parse(envelope.item); - } catch (err) { - throw new Boom5.Boom("Bad value content"); - } - } - const result = { - item, - stored: envelope.stored, - ttl: envelope.ttl - }; - return result; - } - set(key, value, ttl) { - if (!this.cache) { - throw new Boom5.Boom("Connection not started"); - } - const envelope = new internals.MemoryCacheEntry(key, value, ttl); - let segment = this.cache.get(key.segment); - if (!segment) { - segment = /* @__PURE__ */ new Map(); - this.cache.set(key.segment, segment); - } - const cachedItem = segment.get(key.id); - if (cachedItem) { - this.byteSize -= cachedItem.byteSize; - } - if (this.settings.maxByteSize && this.byteSize + envelope.byteSize > this.settings.maxByteSize) { - throw new Boom5.Boom("Cache size limit reached"); - } - this._scheduleCleanup(ttl); - segment.set(key.id, envelope); - this.byteSize += envelope.byteSize; - } - drop(key) { - if (!this.cache) { - throw new Boom5.Boom("Connection not started"); - } - const segment = this.cache.get(key.segment); - if (segment) { - const item = segment.get(key.id); - if (item) { - this.byteSize -= item.byteSize; - segment.delete(key.id); - } - } - } - }; - internals.MemoryCacheEntry = class { - constructor(key, value, ttl) { - let valueByteSize = 0; - if (Buffer.isBuffer(value)) { - this.item = Buffer.alloc(value.length); - value.copy(this.item); - valueByteSize = this.item.length; - } else { - this.item = JSON.stringify(value); - valueByteSize = Buffer.byteLength(this.item); - } - this.stored = Date.now(); - this.ttl = ttl; - this.byteSize = internals.entrySize + valueByteSize + Buffer.byteLength(key.segment) + Buffer.byteLength(key.id); - this.timeoutId = null; - } - }; - } -}); -var require_lib18 = __commonJS({ - "node_modules/.deno/@hapi+heavy@8.0.1/node_modules/@hapi/heavy/lib/index.js"(exports2) { - "use strict"; - var PerfHooks = __require2("perf_hooks"); - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var Validate = require_lib9(); - var internals = {}; - internals.schema = Validate.object({ - sampleInterval: Validate.number().min(0), - maxHeapUsedBytes: Validate.number().min(0), - maxEventLoopDelay: Validate.number().min(0), - maxEventLoopUtilization: Validate.number().min(0), - maxRssBytes: Validate.number().min(0) - }).unknown(); - internals.defaults = { - sampleInterval: 0, - // Frequency of load sampling in milliseconds (zero is no sampling) - maxHeapUsedBytes: 0, - // Reject requests when V8 heap is over size in bytes (zero is no max) - maxRssBytes: 0, - // Reject requests when process RSS is over size in bytes (zero is no max) - maxEventLoopDelay: 0, - // Milliseconds of delay after which requests are rejected (zero is no max) - maxEventLoopUtilization: 0 - // Max event loop utilization value after which requests are rejected (zero is no max) - }; - exports2.Heavy = class Heavy { - constructor(options2) { - options2 = options2 || {}; - Validate.assert(options2, internals.schema, "Invalid load monitoring options"); - this.settings = Hoek.applyToDefaults(internals.defaults, options2); - Hoek.assert(this.settings.sampleInterval || !this.settings.maxEventLoopDelay && !this.settings.maxHeapUsedBytes && !this.settings.maxRssBytes && !this.settings.maxEventLoopUtilization, "Load sample interval must be set to enable load limits"); - this._eventLoopTimer = null; - this._eventLoopUtilization = PerfHooks.performance.eventLoopUtilization(); - this._loadBench = new Hoek.Bench(); - this.load = { - eventLoopDelay: 0, - eventLoopUtilization: 0, - heapUsed: 0, - rss: 0 - }; - } - start() { - if (!this.settings.sampleInterval) { - return; - } - const loopSample = () => { - this._loadBench.reset(); - const measure = () => { - const mem = process.memoryUsage(); - this._eventLoopUtilization = PerfHooks.performance.eventLoopUtilization(this._eventLoopUtilization); - this.load.eventLoopDelay = this._loadBench.elapsed() - this.settings.sampleInterval; - this.load.eventLoopUtilization = this._eventLoopUtilization.utilization; - this.load.heapUsed = mem.heapUsed; - this.load.rss = mem.rss; - loopSample(); - }; - this._eventLoopTimer = setTimeout(measure, this.settings.sampleInterval); - }; - loopSample(); - } - stop() { - clearTimeout(this._eventLoopTimer); - this._eventLoopTimer = null; - } - check() { - if (!this.settings.sampleInterval) { - return; - } - Hoek.assert(this._eventLoopTimer, "Cannot check load when sampler is not started"); - const elapsed = this._loadBench.elapsed(); - const load = this.load; - if (elapsed > this.settings.sampleInterval) { - this._eventLoopUtilization = PerfHooks.performance.eventLoopUtilization(this._eventLoopUtilization); - load.eventLoopDelay = Math.max(load.eventLoopDelay, elapsed - this.settings.sampleInterval); - load.eventLoopUtilization = this._eventLoopUtilization.utilization; - } - if (this.settings.maxEventLoopDelay && load.eventLoopDelay > this.settings.maxEventLoopDelay) { - throw Boom5.serverUnavailable("Server under heavy load (event loop)", load); - } - if (this.settings.maxEventLoopUtilization && load.eventLoopUtilization > this.settings.maxEventLoopUtilization) { - throw Boom5.serverUnavailable("Server under heavy load (event loop utilization)", load); - } - if (this.settings.maxHeapUsedBytes && load.heapUsed > this.settings.maxHeapUsedBytes) { - throw Boom5.serverUnavailable("Server under heavy load (heap)", load); - } - if (this.settings.maxRssBytes && load.rss > this.settings.maxRssBytes) { - throw Boom5.serverUnavailable("Server under heavy load (rss)", load); - } - } - }; - } -}); -var require_db = __commonJS({ - "node_modules/.deno/mime-db@1.54.0/node_modules/mime-db/db.json"(exports2, module14) { - module14.exports = { - "application/1d-interleaved-parityfec": { - source: "iana" - }, - "application/3gpdash-qoe-report+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/3gpp-ims+xml": { - source: "iana", - compressible: true - }, - "application/3gpphal+json": { - source: "iana", - compressible: true - }, - "application/3gpphalforms+json": { - source: "iana", - compressible: true - }, - "application/a2l": { - source: "iana" - }, - "application/ace+cbor": { - source: "iana" - }, - "application/ace+json": { - source: "iana", - compressible: true - }, - "application/ace-groupcomm+cbor": { - source: "iana" - }, - "application/ace-trl+cbor": { - source: "iana" - }, - "application/activemessage": { - source: "iana" - }, - "application/activity+json": { - source: "iana", - compressible: true - }, - "application/aif+cbor": { - source: "iana" - }, - "application/aif+json": { - source: "iana", - compressible: true - }, - "application/alto-cdni+json": { - source: "iana", - compressible: true - }, - "application/alto-cdnifilter+json": { - source: "iana", - compressible: true - }, - "application/alto-costmap+json": { - source: "iana", - compressible: true - }, - "application/alto-costmapfilter+json": { - source: "iana", - compressible: true - }, - "application/alto-directory+json": { - source: "iana", - compressible: true - }, - "application/alto-endpointcost+json": { - source: "iana", - compressible: true - }, - "application/alto-endpointcostparams+json": { - source: "iana", - compressible: true - }, - "application/alto-endpointprop+json": { - source: "iana", - compressible: true - }, - "application/alto-endpointpropparams+json": { - source: "iana", - compressible: true - }, - "application/alto-error+json": { - source: "iana", - compressible: true - }, - "application/alto-networkmap+json": { - source: "iana", - compressible: true - }, - "application/alto-networkmapfilter+json": { - source: "iana", - compressible: true - }, - "application/alto-propmap+json": { - source: "iana", - compressible: true - }, - "application/alto-propmapparams+json": { - source: "iana", - compressible: true - }, - "application/alto-tips+json": { - source: "iana", - compressible: true - }, - "application/alto-tipsparams+json": { - source: "iana", - compressible: true - }, - "application/alto-updatestreamcontrol+json": { - source: "iana", - compressible: true - }, - "application/alto-updatestreamparams+json": { - source: "iana", - compressible: true - }, - "application/aml": { - source: "iana" - }, - "application/andrew-inset": { - source: "iana", - extensions: ["ez"] - }, - "application/appinstaller": { - compressible: false, - extensions: ["appinstaller"] - }, - "application/applefile": { - source: "iana" - }, - "application/applixware": { - source: "apache", - extensions: ["aw"] - }, - "application/appx": { - compressible: false, - extensions: ["appx"] - }, - "application/appxbundle": { - compressible: false, - extensions: ["appxbundle"] - }, - "application/at+jwt": { - source: "iana" - }, - "application/atf": { - source: "iana" - }, - "application/atfx": { - source: "iana" - }, - "application/atom+xml": { - source: "iana", - compressible: true, - extensions: ["atom"] - }, - "application/atomcat+xml": { - source: "iana", - compressible: true, - extensions: ["atomcat"] - }, - "application/atomdeleted+xml": { - source: "iana", - compressible: true, - extensions: ["atomdeleted"] - }, - "application/atomicmail": { - source: "iana" - }, - "application/atomsvc+xml": { - source: "iana", - compressible: true, - extensions: ["atomsvc"] - }, - "application/atsc-dwd+xml": { - source: "iana", - compressible: true, - extensions: ["dwd"] - }, - "application/atsc-dynamic-event-message": { - source: "iana" - }, - "application/atsc-held+xml": { - source: "iana", - compressible: true, - extensions: ["held"] - }, - "application/atsc-rdt+json": { - source: "iana", - compressible: true - }, - "application/atsc-rsat+xml": { - source: "iana", - compressible: true, - extensions: ["rsat"] - }, - "application/atxml": { - source: "iana" - }, - "application/auth-policy+xml": { - source: "iana", - compressible: true - }, - "application/automationml-aml+xml": { - source: "iana", - compressible: true, - extensions: ["aml"] - }, - "application/automationml-amlx+zip": { - source: "iana", - compressible: false, - extensions: ["amlx"] - }, - "application/bacnet-xdd+zip": { - source: "iana", - compressible: false - }, - "application/batch-smtp": { - source: "iana" - }, - "application/bdoc": { - compressible: false, - extensions: ["bdoc"] - }, - "application/beep+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/bufr": { - source: "iana" - }, - "application/c2pa": { - source: "iana" - }, - "application/calendar+json": { - source: "iana", - compressible: true - }, - "application/calendar+xml": { - source: "iana", - compressible: true, - extensions: ["xcs"] - }, - "application/call-completion": { - source: "iana" - }, - "application/cals-1840": { - source: "iana" - }, - "application/captive+json": { - source: "iana", - compressible: true - }, - "application/cbor": { - source: "iana" - }, - "application/cbor-seq": { - source: "iana" - }, - "application/cccex": { - source: "iana" - }, - "application/ccmp+xml": { - source: "iana", - compressible: true - }, - "application/ccxml+xml": { - source: "iana", - compressible: true, - extensions: ["ccxml"] - }, - "application/cda+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/cdfx+xml": { - source: "iana", - compressible: true, - extensions: ["cdfx"] - }, - "application/cdmi-capability": { - source: "iana", - extensions: ["cdmia"] - }, - "application/cdmi-container": { - source: "iana", - extensions: ["cdmic"] - }, - "application/cdmi-domain": { - source: "iana", - extensions: ["cdmid"] - }, - "application/cdmi-object": { - source: "iana", - extensions: ["cdmio"] - }, - "application/cdmi-queue": { - source: "iana", - extensions: ["cdmiq"] - }, - "application/cdni": { - source: "iana" - }, - "application/ce+cbor": { - source: "iana" - }, - "application/cea": { - source: "iana" - }, - "application/cea-2018+xml": { - source: "iana", - compressible: true - }, - "application/cellml+xml": { - source: "iana", - compressible: true - }, - "application/cfw": { - source: "iana" - }, - "application/cid-edhoc+cbor-seq": { - source: "iana" - }, - "application/city+json": { - source: "iana", - compressible: true - }, - "application/city+json-seq": { - source: "iana" - }, - "application/clr": { - source: "iana" - }, - "application/clue+xml": { - source: "iana", - compressible: true - }, - "application/clue_info+xml": { - source: "iana", - compressible: true - }, - "application/cms": { - source: "iana" - }, - "application/cnrp+xml": { - source: "iana", - compressible: true - }, - "application/coap-eap": { - source: "iana" - }, - "application/coap-group+json": { - source: "iana", - compressible: true - }, - "application/coap-payload": { - source: "iana" - }, - "application/commonground": { - source: "iana" - }, - "application/concise-problem-details+cbor": { - source: "iana" - }, - "application/conference-info+xml": { - source: "iana", - compressible: true - }, - "application/cose": { - source: "iana" - }, - "application/cose-key": { - source: "iana" - }, - "application/cose-key-set": { - source: "iana" - }, - "application/cose-x509": { - source: "iana" - }, - "application/cpl+xml": { - source: "iana", - compressible: true, - extensions: ["cpl"] - }, - "application/csrattrs": { - source: "iana" - }, - "application/csta+xml": { - source: "iana", - compressible: true - }, - "application/cstadata+xml": { - source: "iana", - compressible: true - }, - "application/csvm+json": { - source: "iana", - compressible: true - }, - "application/cu-seeme": { - source: "apache", - extensions: ["cu"] - }, - "application/cwl": { - source: "iana", - extensions: ["cwl"] - }, - "application/cwl+json": { - source: "iana", - compressible: true - }, - "application/cwl+yaml": { - source: "iana" - }, - "application/cwt": { - source: "iana" - }, - "application/cybercash": { - source: "iana" - }, - "application/dart": { - compressible: true - }, - "application/dash+xml": { - source: "iana", - compressible: true, - extensions: ["mpd"] - }, - "application/dash-patch+xml": { - source: "iana", - compressible: true, - extensions: ["mpp"] - }, - "application/dashdelta": { - source: "iana" - }, - "application/davmount+xml": { - source: "iana", - compressible: true, - extensions: ["davmount"] - }, - "application/dca-rft": { - source: "iana" - }, - "application/dcd": { - source: "iana" - }, - "application/dec-dx": { - source: "iana" - }, - "application/dialog-info+xml": { - source: "iana", - compressible: true - }, - "application/dicom": { - source: "iana", - extensions: ["dcm"] - }, - "application/dicom+json": { - source: "iana", - compressible: true - }, - "application/dicom+xml": { - source: "iana", - compressible: true - }, - "application/dii": { - source: "iana" - }, - "application/dit": { - source: "iana" - }, - "application/dns": { - source: "iana" - }, - "application/dns+json": { - source: "iana", - compressible: true - }, - "application/dns-message": { - source: "iana" - }, - "application/docbook+xml": { - source: "apache", - compressible: true, - extensions: ["dbk"] - }, - "application/dots+cbor": { - source: "iana" - }, - "application/dpop+jwt": { - source: "iana" - }, - "application/dskpp+xml": { - source: "iana", - compressible: true - }, - "application/dssc+der": { - source: "iana", - extensions: ["dssc"] - }, - "application/dssc+xml": { - source: "iana", - compressible: true, - extensions: ["xdssc"] - }, - "application/dvcs": { - source: "iana" - }, - "application/eat+cwt": { - source: "iana" - }, - "application/eat+jwt": { - source: "iana" - }, - "application/eat-bun+cbor": { - source: "iana" - }, - "application/eat-bun+json": { - source: "iana", - compressible: true - }, - "application/eat-ucs+cbor": { - source: "iana" - }, - "application/eat-ucs+json": { - source: "iana", - compressible: true - }, - "application/ecmascript": { - source: "apache", - compressible: true, - extensions: ["ecma"] - }, - "application/edhoc+cbor-seq": { - source: "iana" - }, - "application/edi-consent": { - source: "iana" - }, - "application/edi-x12": { - source: "iana", - compressible: false - }, - "application/edifact": { - source: "iana", - compressible: false - }, - "application/efi": { - source: "iana" - }, - "application/elm+json": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/elm+xml": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.cap+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/emergencycalldata.comment+xml": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.control+xml": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.deviceinfo+xml": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.ecall.msd": { - source: "iana" - }, - "application/emergencycalldata.legacyesn+json": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.providerinfo+xml": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.serviceinfo+xml": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.subscriberinfo+xml": { - source: "iana", - compressible: true - }, - "application/emergencycalldata.veds+xml": { - source: "iana", - compressible: true - }, - "application/emma+xml": { - source: "iana", - compressible: true, - extensions: ["emma"] - }, - "application/emotionml+xml": { - source: "iana", - compressible: true, - extensions: ["emotionml"] - }, - "application/encaprtp": { - source: "iana" - }, - "application/entity-statement+jwt": { - source: "iana" - }, - "application/epp+xml": { - source: "iana", - compressible: true - }, - "application/epub+zip": { - source: "iana", - compressible: false, - extensions: ["epub"] - }, - "application/eshop": { - source: "iana" - }, - "application/exi": { - source: "iana", - extensions: ["exi"] - }, - "application/expect-ct-report+json": { - source: "iana", - compressible: true - }, - "application/express": { - source: "iana", - extensions: ["exp"] - }, - "application/fastinfoset": { - source: "iana" - }, - "application/fastsoap": { - source: "iana" - }, - "application/fdf": { - source: "iana", - extensions: ["fdf"] - }, - "application/fdt+xml": { - source: "iana", - compressible: true, - extensions: ["fdt"] - }, - "application/fhir+json": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/fhir+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/fido.trusted-apps+json": { - compressible: true - }, - "application/fits": { - source: "iana" - }, - "application/flexfec": { - source: "iana" - }, - "application/font-sfnt": { - source: "iana" - }, - "application/font-tdpfr": { - source: "iana", - extensions: ["pfr"] - }, - "application/font-woff": { - source: "iana", - compressible: false - }, - "application/framework-attributes+xml": { - source: "iana", - compressible: true - }, - "application/geo+json": { - source: "iana", - compressible: true, - extensions: ["geojson"] - }, - "application/geo+json-seq": { - source: "iana" - }, - "application/geopackage+sqlite3": { - source: "iana" - }, - "application/geopose+json": { - source: "iana", - compressible: true - }, - "application/geoxacml+json": { - source: "iana", - compressible: true - }, - "application/geoxacml+xml": { - source: "iana", - compressible: true - }, - "application/gltf-buffer": { - source: "iana" - }, - "application/gml+xml": { - source: "iana", - compressible: true, - extensions: ["gml"] - }, - "application/gnap-binding-jws": { - source: "iana" - }, - "application/gnap-binding-jwsd": { - source: "iana" - }, - "application/gnap-binding-rotation-jws": { - source: "iana" - }, - "application/gnap-binding-rotation-jwsd": { - source: "iana" - }, - "application/gpx+xml": { - source: "apache", - compressible: true, - extensions: ["gpx"] - }, - "application/grib": { - source: "iana" - }, - "application/gxf": { - source: "apache", - extensions: ["gxf"] - }, - "application/gzip": { - source: "iana", - compressible: false, - extensions: ["gz"] - }, - "application/h224": { - source: "iana" - }, - "application/held+xml": { - source: "iana", - compressible: true - }, - "application/hjson": { - extensions: ["hjson"] - }, - "application/hl7v2+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/http": { - source: "iana" - }, - "application/hyperstudio": { - source: "iana", - extensions: ["stk"] - }, - "application/ibe-key-request+xml": { - source: "iana", - compressible: true - }, - "application/ibe-pkg-reply+xml": { - source: "iana", - compressible: true - }, - "application/ibe-pp-data": { - source: "iana" - }, - "application/iges": { - source: "iana" - }, - "application/im-iscomposing+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/index": { - source: "iana" - }, - "application/index.cmd": { - source: "iana" - }, - "application/index.obj": { - source: "iana" - }, - "application/index.response": { - source: "iana" - }, - "application/index.vnd": { - source: "iana" - }, - "application/inkml+xml": { - source: "iana", - compressible: true, - extensions: ["ink", "inkml"] - }, - "application/iotp": { - source: "iana" - }, - "application/ipfix": { - source: "iana", - extensions: ["ipfix"] - }, - "application/ipp": { - source: "iana" - }, - "application/isup": { - source: "iana" - }, - "application/its+xml": { - source: "iana", - compressible: true, - extensions: ["its"] - }, - "application/java-archive": { - source: "iana", - compressible: false, - extensions: ["jar", "war", "ear"] - }, - "application/java-serialized-object": { - source: "apache", - compressible: false, - extensions: ["ser"] - }, - "application/java-vm": { - source: "apache", - compressible: false, - extensions: ["class"] - }, - "application/javascript": { - source: "apache", - charset: "UTF-8", - compressible: true, - extensions: ["js"] - }, - "application/jf2feed+json": { - source: "iana", - compressible: true - }, - "application/jose": { - source: "iana" - }, - "application/jose+json": { - source: "iana", - compressible: true - }, - "application/jrd+json": { - source: "iana", - compressible: true - }, - "application/jscalendar+json": { - source: "iana", - compressible: true - }, - "application/jscontact+json": { - source: "iana", - compressible: true - }, - "application/json": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["json", "map"] - }, - "application/json-patch+json": { - source: "iana", - compressible: true - }, - "application/json-seq": { - source: "iana" - }, - "application/json5": { - extensions: ["json5"] - }, - "application/jsonml+json": { - source: "apache", - compressible: true, - extensions: ["jsonml"] - }, - "application/jsonpath": { - source: "iana" - }, - "application/jwk+json": { - source: "iana", - compressible: true - }, - "application/jwk-set+json": { - source: "iana", - compressible: true - }, - "application/jwk-set+jwt": { - source: "iana" - }, - "application/jwt": { - source: "iana" - }, - "application/kpml-request+xml": { - source: "iana", - compressible: true - }, - "application/kpml-response+xml": { - source: "iana", - compressible: true - }, - "application/ld+json": { - source: "iana", - compressible: true, - extensions: ["jsonld"] - }, - "application/lgr+xml": { - source: "iana", - compressible: true, - extensions: ["lgr"] - }, - "application/link-format": { - source: "iana" - }, - "application/linkset": { - source: "iana" - }, - "application/linkset+json": { - source: "iana", - compressible: true - }, - "application/load-control+xml": { - source: "iana", - compressible: true - }, - "application/logout+jwt": { - source: "iana" - }, - "application/lost+xml": { - source: "iana", - compressible: true, - extensions: ["lostxml"] - }, - "application/lostsync+xml": { - source: "iana", - compressible: true - }, - "application/lpf+zip": { - source: "iana", - compressible: false - }, - "application/lxf": { - source: "iana" - }, - "application/mac-binhex40": { - source: "iana", - extensions: ["hqx"] - }, - "application/mac-compactpro": { - source: "apache", - extensions: ["cpt"] - }, - "application/macwriteii": { - source: "iana" - }, - "application/mads+xml": { - source: "iana", - compressible: true, - extensions: ["mads"] - }, - "application/manifest+json": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["webmanifest"] - }, - "application/marc": { - source: "iana", - extensions: ["mrc"] - }, - "application/marcxml+xml": { - source: "iana", - compressible: true, - extensions: ["mrcx"] - }, - "application/mathematica": { - source: "iana", - extensions: ["ma", "nb", "mb"] - }, - "application/mathml+xml": { - source: "iana", - compressible: true, - extensions: ["mathml"] - }, - "application/mathml-content+xml": { - source: "iana", - compressible: true - }, - "application/mathml-presentation+xml": { - source: "iana", - compressible: true - }, - "application/mbms-associated-procedure-description+xml": { - source: "iana", - compressible: true - }, - "application/mbms-deregister+xml": { - source: "iana", - compressible: true - }, - "application/mbms-envelope+xml": { - source: "iana", - compressible: true - }, - "application/mbms-msk+xml": { - source: "iana", - compressible: true - }, - "application/mbms-msk-response+xml": { - source: "iana", - compressible: true - }, - "application/mbms-protection-description+xml": { - source: "iana", - compressible: true - }, - "application/mbms-reception-report+xml": { - source: "iana", - compressible: true - }, - "application/mbms-register+xml": { - source: "iana", - compressible: true - }, - "application/mbms-register-response+xml": { - source: "iana", - compressible: true - }, - "application/mbms-schedule+xml": { - source: "iana", - compressible: true - }, - "application/mbms-user-service-description+xml": { - source: "iana", - compressible: true - }, - "application/mbox": { - source: "iana", - extensions: ["mbox"] - }, - "application/media-policy-dataset+xml": { - source: "iana", - compressible: true, - extensions: ["mpf"] - }, - "application/media_control+xml": { - source: "iana", - compressible: true - }, - "application/mediaservercontrol+xml": { - source: "iana", - compressible: true, - extensions: ["mscml"] - }, - "application/merge-patch+json": { - source: "iana", - compressible: true - }, - "application/metalink+xml": { - source: "apache", - compressible: true, - extensions: ["metalink"] - }, - "application/metalink4+xml": { - source: "iana", - compressible: true, - extensions: ["meta4"] - }, - "application/mets+xml": { - source: "iana", - compressible: true, - extensions: ["mets"] - }, - "application/mf4": { - source: "iana" - }, - "application/mikey": { - source: "iana" - }, - "application/mipc": { - source: "iana" - }, - "application/missing-blocks+cbor-seq": { - source: "iana" - }, - "application/mmt-aei+xml": { - source: "iana", - compressible: true, - extensions: ["maei"] - }, - "application/mmt-usd+xml": { - source: "iana", - compressible: true, - extensions: ["musd"] - }, - "application/mods+xml": { - source: "iana", - compressible: true, - extensions: ["mods"] - }, - "application/moss-keys": { - source: "iana" - }, - "application/moss-signature": { - source: "iana" - }, - "application/mosskey-data": { - source: "iana" - }, - "application/mosskey-request": { - source: "iana" - }, - "application/mp21": { - source: "iana", - extensions: ["m21", "mp21"] - }, - "application/mp4": { - source: "iana", - extensions: ["mp4", "mpg4", "mp4s", "m4p"] - }, - "application/mpeg4-generic": { - source: "iana" - }, - "application/mpeg4-iod": { - source: "iana" - }, - "application/mpeg4-iod-xmt": { - source: "iana" - }, - "application/mrb-consumer+xml": { - source: "iana", - compressible: true - }, - "application/mrb-publish+xml": { - source: "iana", - compressible: true - }, - "application/msc-ivr+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/msc-mixer+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/msix": { - compressible: false, - extensions: ["msix"] - }, - "application/msixbundle": { - compressible: false, - extensions: ["msixbundle"] - }, - "application/msword": { - source: "iana", - compressible: false, - extensions: ["doc", "dot"] - }, - "application/mud+json": { - source: "iana", - compressible: true - }, - "application/multipart-core": { - source: "iana" - }, - "application/mxf": { - source: "iana", - extensions: ["mxf"] - }, - "application/n-quads": { - source: "iana", - extensions: ["nq"] - }, - "application/n-triples": { - source: "iana", - extensions: ["nt"] - }, - "application/nasdata": { - source: "iana" - }, - "application/news-checkgroups": { - source: "iana", - charset: "US-ASCII" - }, - "application/news-groupinfo": { - source: "iana", - charset: "US-ASCII" - }, - "application/news-transmission": { - source: "iana" - }, - "application/nlsml+xml": { - source: "iana", - compressible: true - }, - "application/node": { - source: "iana", - extensions: ["cjs"] - }, - "application/nss": { - source: "iana" - }, - "application/oauth-authz-req+jwt": { - source: "iana" - }, - "application/oblivious-dns-message": { - source: "iana" - }, - "application/ocsp-request": { - source: "iana" - }, - "application/ocsp-response": { - source: "iana" - }, - "application/octet-stream": { - source: "iana", - compressible: true, - extensions: ["bin", "dms", "lrf", "mar", "so", "dist", "distz", "pkg", "bpk", "dump", "elc", "deploy", "exe", "dll", "deb", "dmg", "iso", "img", "msi", "msp", "msm", "buffer"] - }, - "application/oda": { - source: "iana", - extensions: ["oda"] - }, - "application/odm+xml": { - source: "iana", - compressible: true - }, - "application/odx": { - source: "iana" - }, - "application/oebps-package+xml": { - source: "iana", - compressible: true, - extensions: ["opf"] - }, - "application/ogg": { - source: "iana", - compressible: false, - extensions: ["ogx"] - }, - "application/ohttp-keys": { - source: "iana" - }, - "application/omdoc+xml": { - source: "apache", - compressible: true, - extensions: ["omdoc"] - }, - "application/onenote": { - source: "apache", - extensions: ["onetoc", "onetoc2", "onetmp", "onepkg", "one", "onea"] - }, - "application/opc-nodeset+xml": { - source: "iana", - compressible: true - }, - "application/oscore": { - source: "iana" - }, - "application/oxps": { - source: "iana", - extensions: ["oxps"] - }, - "application/p21": { - source: "iana" - }, - "application/p21+zip": { - source: "iana", - compressible: false - }, - "application/p2p-overlay+xml": { - source: "iana", - compressible: true, - extensions: ["relo"] - }, - "application/parityfec": { - source: "iana" - }, - "application/passport": { - source: "iana" - }, - "application/patch-ops-error+xml": { - source: "iana", - compressible: true, - extensions: ["xer"] - }, - "application/pdf": { - source: "iana", - compressible: false, - extensions: ["pdf"] - }, - "application/pdx": { - source: "iana" - }, - "application/pem-certificate-chain": { - source: "iana" - }, - "application/pgp-encrypted": { - source: "iana", - compressible: false, - extensions: ["pgp"] - }, - "application/pgp-keys": { - source: "iana", - extensions: ["asc"] - }, - "application/pgp-signature": { - source: "iana", - extensions: ["sig", "asc"] - }, - "application/pics-rules": { - source: "apache", - extensions: ["prf"] - }, - "application/pidf+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/pidf-diff+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/pkcs10": { - source: "iana", - extensions: ["p10"] - }, - "application/pkcs12": { - source: "iana" - }, - "application/pkcs7-mime": { - source: "iana", - extensions: ["p7m", "p7c"] - }, - "application/pkcs7-signature": { - source: "iana", - extensions: ["p7s"] - }, - "application/pkcs8": { - source: "iana", - extensions: ["p8"] - }, - "application/pkcs8-encrypted": { - source: "iana" - }, - "application/pkix-attr-cert": { - source: "iana", - extensions: ["ac"] - }, - "application/pkix-cert": { - source: "iana", - extensions: ["cer"] - }, - "application/pkix-crl": { - source: "iana", - extensions: ["crl"] - }, - "application/pkix-pkipath": { - source: "iana", - extensions: ["pkipath"] - }, - "application/pkixcmp": { - source: "iana", - extensions: ["pki"] - }, - "application/pls+xml": { - source: "iana", - compressible: true, - extensions: ["pls"] - }, - "application/poc-settings+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/postscript": { - source: "iana", - compressible: true, - extensions: ["ai", "eps", "ps"] - }, - "application/ppsp-tracker+json": { - source: "iana", - compressible: true - }, - "application/private-token-issuer-directory": { - source: "iana" - }, - "application/private-token-request": { - source: "iana" - }, - "application/private-token-response": { - source: "iana" - }, - "application/problem+json": { - source: "iana", - compressible: true - }, - "application/problem+xml": { - source: "iana", - compressible: true - }, - "application/provenance+xml": { - source: "iana", - compressible: true, - extensions: ["provx"] - }, - "application/provided-claims+jwt": { - source: "iana" - }, - "application/prs.alvestrand.titrax-sheet": { - source: "iana" - }, - "application/prs.cww": { - source: "iana", - extensions: ["cww"] - }, - "application/prs.cyn": { - source: "iana", - charset: "7-BIT" - }, - "application/prs.hpub+zip": { - source: "iana", - compressible: false - }, - "application/prs.implied-document+xml": { - source: "iana", - compressible: true - }, - "application/prs.implied-executable": { - source: "iana" - }, - "application/prs.implied-object+json": { - source: "iana", - compressible: true - }, - "application/prs.implied-object+json-seq": { - source: "iana" - }, - "application/prs.implied-object+yaml": { - source: "iana" - }, - "application/prs.implied-structure": { - source: "iana" - }, - "application/prs.mayfile": { - source: "iana" - }, - "application/prs.nprend": { - source: "iana" - }, - "application/prs.plucker": { - source: "iana" - }, - "application/prs.rdf-xml-crypt": { - source: "iana" - }, - "application/prs.vcfbzip2": { - source: "iana" - }, - "application/prs.xsf+xml": { - source: "iana", - compressible: true, - extensions: ["xsf"] - }, - "application/pskc+xml": { - source: "iana", - compressible: true, - extensions: ["pskcxml"] - }, - "application/pvd+json": { - source: "iana", - compressible: true - }, - "application/qsig": { - source: "iana" - }, - "application/raml+yaml": { - compressible: true, - extensions: ["raml"] - }, - "application/raptorfec": { - source: "iana" - }, - "application/rdap+json": { - source: "iana", - compressible: true - }, - "application/rdf+xml": { - source: "iana", - compressible: true, - extensions: ["rdf", "owl"] - }, - "application/reginfo+xml": { - source: "iana", - compressible: true, - extensions: ["rif"] - }, - "application/relax-ng-compact-syntax": { - source: "iana", - extensions: ["rnc"] - }, - "application/remote-printing": { - source: "apache" - }, - "application/reputon+json": { - source: "iana", - compressible: true - }, - "application/resolve-response+jwt": { - source: "iana" - }, - "application/resource-lists+xml": { - source: "iana", - compressible: true, - extensions: ["rl"] - }, - "application/resource-lists-diff+xml": { - source: "iana", - compressible: true, - extensions: ["rld"] - }, - "application/rfc+xml": { - source: "iana", - compressible: true - }, - "application/riscos": { - source: "iana" - }, - "application/rlmi+xml": { - source: "iana", - compressible: true - }, - "application/rls-services+xml": { - source: "iana", - compressible: true, - extensions: ["rs"] - }, - "application/route-apd+xml": { - source: "iana", - compressible: true, - extensions: ["rapd"] - }, - "application/route-s-tsid+xml": { - source: "iana", - compressible: true, - extensions: ["sls"] - }, - "application/route-usd+xml": { - source: "iana", - compressible: true, - extensions: ["rusd"] - }, - "application/rpki-checklist": { - source: "iana" - }, - "application/rpki-ghostbusters": { - source: "iana", - extensions: ["gbr"] - }, - "application/rpki-manifest": { - source: "iana", - extensions: ["mft"] - }, - "application/rpki-publication": { - source: "iana" - }, - "application/rpki-roa": { - source: "iana", - extensions: ["roa"] - }, - "application/rpki-signed-tal": { - source: "iana" - }, - "application/rpki-updown": { - source: "iana" - }, - "application/rsd+xml": { - source: "apache", - compressible: true, - extensions: ["rsd"] - }, - "application/rss+xml": { - source: "apache", - compressible: true, - extensions: ["rss"] - }, - "application/rtf": { - source: "iana", - compressible: true, - extensions: ["rtf"] - }, - "application/rtploopback": { - source: "iana" - }, - "application/rtx": { - source: "iana" - }, - "application/samlassertion+xml": { - source: "iana", - compressible: true - }, - "application/samlmetadata+xml": { - source: "iana", - compressible: true - }, - "application/sarif+json": { - source: "iana", - compressible: true - }, - "application/sarif-external-properties+json": { - source: "iana", - compressible: true - }, - "application/sbe": { - source: "iana" - }, - "application/sbml+xml": { - source: "iana", - compressible: true, - extensions: ["sbml"] - }, - "application/scaip+xml": { - source: "iana", - compressible: true - }, - "application/scim+json": { - source: "iana", - compressible: true - }, - "application/scvp-cv-request": { - source: "iana", - extensions: ["scq"] - }, - "application/scvp-cv-response": { - source: "iana", - extensions: ["scs"] - }, - "application/scvp-vp-request": { - source: "iana", - extensions: ["spq"] - }, - "application/scvp-vp-response": { - source: "iana", - extensions: ["spp"] - }, - "application/sdp": { - source: "iana", - extensions: ["sdp"] - }, - "application/secevent+jwt": { - source: "iana" - }, - "application/senml+cbor": { - source: "iana" - }, - "application/senml+json": { - source: "iana", - compressible: true - }, - "application/senml+xml": { - source: "iana", - compressible: true, - extensions: ["senmlx"] - }, - "application/senml-etch+cbor": { - source: "iana" - }, - "application/senml-etch+json": { - source: "iana", - compressible: true - }, - "application/senml-exi": { - source: "iana" - }, - "application/sensml+cbor": { - source: "iana" - }, - "application/sensml+json": { - source: "iana", - compressible: true - }, - "application/sensml+xml": { - source: "iana", - compressible: true, - extensions: ["sensmlx"] - }, - "application/sensml-exi": { - source: "iana" - }, - "application/sep+xml": { - source: "iana", - compressible: true - }, - "application/sep-exi": { - source: "iana" - }, - "application/session-info": { - source: "iana" - }, - "application/set-payment": { - source: "iana" - }, - "application/set-payment-initiation": { - source: "iana", - extensions: ["setpay"] - }, - "application/set-registration": { - source: "iana" - }, - "application/set-registration-initiation": { - source: "iana", - extensions: ["setreg"] - }, - "application/sgml": { - source: "iana" - }, - "application/sgml-open-catalog": { - source: "iana" - }, - "application/shf+xml": { - source: "iana", - compressible: true, - extensions: ["shf"] - }, - "application/sieve": { - source: "iana", - extensions: ["siv", "sieve"] - }, - "application/simple-filter+xml": { - source: "iana", - compressible: true - }, - "application/simple-message-summary": { - source: "iana" - }, - "application/simplesymbolcontainer": { - source: "iana" - }, - "application/sipc": { - source: "iana" - }, - "application/slate": { - source: "iana" - }, - "application/smil": { - source: "apache" - }, - "application/smil+xml": { - source: "iana", - compressible: true, - extensions: ["smi", "smil"] - }, - "application/smpte336m": { - source: "iana" - }, - "application/soap+fastinfoset": { - source: "iana" - }, - "application/soap+xml": { - source: "iana", - compressible: true - }, - "application/sparql-query": { - source: "iana", - extensions: ["rq"] - }, - "application/sparql-results+xml": { - source: "iana", - compressible: true, - extensions: ["srx"] - }, - "application/spdx+json": { - source: "iana", - compressible: true - }, - "application/spirits-event+xml": { - source: "iana", - compressible: true - }, - "application/sql": { - source: "iana", - extensions: ["sql"] - }, - "application/srgs": { - source: "iana", - extensions: ["gram"] - }, - "application/srgs+xml": { - source: "iana", - compressible: true, - extensions: ["grxml"] - }, - "application/sru+xml": { - source: "iana", - compressible: true, - extensions: ["sru"] - }, - "application/ssdl+xml": { - source: "apache", - compressible: true, - extensions: ["ssdl"] - }, - "application/sslkeylogfile": { - source: "iana" - }, - "application/ssml+xml": { - source: "iana", - compressible: true, - extensions: ["ssml"] - }, - "application/st2110-41": { - source: "iana" - }, - "application/stix+json": { - source: "iana", - compressible: true - }, - "application/stratum": { - source: "iana" - }, - "application/swid+cbor": { - source: "iana" - }, - "application/swid+xml": { - source: "iana", - compressible: true, - extensions: ["swidtag"] - }, - "application/tamp-apex-update": { - source: "iana" - }, - "application/tamp-apex-update-confirm": { - source: "iana" - }, - "application/tamp-community-update": { - source: "iana" - }, - "application/tamp-community-update-confirm": { - source: "iana" - }, - "application/tamp-error": { - source: "iana" - }, - "application/tamp-sequence-adjust": { - source: "iana" - }, - "application/tamp-sequence-adjust-confirm": { - source: "iana" - }, - "application/tamp-status-query": { - source: "iana" - }, - "application/tamp-status-response": { - source: "iana" - }, - "application/tamp-update": { - source: "iana" - }, - "application/tamp-update-confirm": { - source: "iana" - }, - "application/tar": { - compressible: true - }, - "application/taxii+json": { - source: "iana", - compressible: true - }, - "application/td+json": { - source: "iana", - compressible: true - }, - "application/tei+xml": { - source: "iana", - compressible: true, - extensions: ["tei", "teicorpus"] - }, - "application/tetra_isi": { - source: "iana" - }, - "application/thraud+xml": { - source: "iana", - compressible: true, - extensions: ["tfi"] - }, - "application/timestamp-query": { - source: "iana" - }, - "application/timestamp-reply": { - source: "iana" - }, - "application/timestamped-data": { - source: "iana", - extensions: ["tsd"] - }, - "application/tlsrpt+gzip": { - source: "iana" - }, - "application/tlsrpt+json": { - source: "iana", - compressible: true - }, - "application/tm+json": { - source: "iana", - compressible: true - }, - "application/tnauthlist": { - source: "iana" - }, - "application/toc+cbor": { - source: "iana" - }, - "application/token-introspection+jwt": { - source: "iana" - }, - "application/toml": { - source: "iana", - compressible: true, - extensions: ["toml"] - }, - "application/trickle-ice-sdpfrag": { - source: "iana" - }, - "application/trig": { - source: "iana", - extensions: ["trig"] - }, - "application/trust-chain+json": { - source: "iana", - compressible: true - }, - "application/trust-mark+jwt": { - source: "iana" - }, - "application/trust-mark-delegation+jwt": { - source: "iana" - }, - "application/ttml+xml": { - source: "iana", - compressible: true, - extensions: ["ttml"] - }, - "application/tve-trigger": { - source: "iana" - }, - "application/tzif": { - source: "iana" - }, - "application/tzif-leap": { - source: "iana" - }, - "application/ubjson": { - compressible: false, - extensions: ["ubj"] - }, - "application/uccs+cbor": { - source: "iana" - }, - "application/ujcs+json": { - source: "iana", - compressible: true - }, - "application/ulpfec": { - source: "iana" - }, - "application/urc-grpsheet+xml": { - source: "iana", - compressible: true - }, - "application/urc-ressheet+xml": { - source: "iana", - compressible: true, - extensions: ["rsheet"] - }, - "application/urc-targetdesc+xml": { - source: "iana", - compressible: true, - extensions: ["td"] - }, - "application/urc-uisocketdesc+xml": { - source: "iana", - compressible: true - }, - "application/vc": { - source: "iana" - }, - "application/vc+cose": { - source: "iana" - }, - "application/vc+jwt": { - source: "iana" - }, - "application/vcard+json": { - source: "iana", - compressible: true - }, - "application/vcard+xml": { - source: "iana", - compressible: true - }, - "application/vemmi": { - source: "iana" - }, - "application/vividence.scriptfile": { - source: "apache" - }, - "application/vnd.1000minds.decision-model+xml": { - source: "iana", - compressible: true, - extensions: ["1km"] - }, - "application/vnd.1ob": { - source: "iana" - }, - "application/vnd.3gpp-prose+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp-prose-pc3a+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp-prose-pc3ach+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp-prose-pc3ch+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp-prose-pc8+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp-v2x-local-service-information": { - source: "iana" - }, - "application/vnd.3gpp.5gnas": { - source: "iana" - }, - "application/vnd.3gpp.5gsa2x": { - source: "iana" - }, - "application/vnd.3gpp.5gsa2x-local-service-information": { - source: "iana" - }, - "application/vnd.3gpp.5gsv2x": { - source: "iana" - }, - "application/vnd.3gpp.5gsv2x-local-service-information": { - source: "iana" - }, - "application/vnd.3gpp.access-transfer-events+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.bsf+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.crs+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.current-location-discovery+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.gmop+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.gtpc": { - source: "iana" - }, - "application/vnd.3gpp.interworking-data": { - source: "iana" - }, - "application/vnd.3gpp.lpp": { - source: "iana" - }, - "application/vnd.3gpp.mc-signalling-ear": { - source: "iana" - }, - "application/vnd.3gpp.mcdata-affiliation-command+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcdata-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcdata-msgstore-ctrl-request+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcdata-payload": { - source: "iana" - }, - "application/vnd.3gpp.mcdata-regroup+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcdata-service-config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcdata-signalling": { - source: "iana" - }, - "application/vnd.3gpp.mcdata-ue-config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcdata-user-profile+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-affiliation-command+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-floor-request+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-location-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-mbms-usage-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-regroup+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-service-config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-signed+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-ue-config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-ue-init-config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcptt-user-profile+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-affiliation-command+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-location-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-mbms-usage-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-regroup+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-service-config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-transmission-request+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-ue-config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mcvideo-user-profile+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.mid-call+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.ngap": { - source: "iana" - }, - "application/vnd.3gpp.pfcp": { - source: "iana" - }, - "application/vnd.3gpp.pic-bw-large": { - source: "iana", - extensions: ["plb"] - }, - "application/vnd.3gpp.pic-bw-small": { - source: "iana", - extensions: ["psb"] - }, - "application/vnd.3gpp.pic-bw-var": { - source: "iana", - extensions: ["pvb"] - }, - "application/vnd.3gpp.pinapp-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.s1ap": { - source: "iana" - }, - "application/vnd.3gpp.seal-group-doc+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.seal-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.seal-location-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.seal-mbms-usage-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.seal-network-qos-management-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.seal-ue-config-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.seal-unicast-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.seal-user-profile-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.sms": { - source: "iana" - }, - "application/vnd.3gpp.sms+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.srvcc-ext+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.srvcc-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.state-and-event-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.ussd+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp.v2x": { - source: "iana" - }, - "application/vnd.3gpp.vae-info+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp2.bcmcsinfo+xml": { - source: "iana", - compressible: true - }, - "application/vnd.3gpp2.sms": { - source: "iana" - }, - "application/vnd.3gpp2.tcap": { - source: "iana", - extensions: ["tcap"] - }, - "application/vnd.3lightssoftware.imagescal": { - source: "iana" - }, - "application/vnd.3m.post-it-notes": { - source: "iana", - extensions: ["pwn"] - }, - "application/vnd.accpac.simply.aso": { - source: "iana", - extensions: ["aso"] - }, - "application/vnd.accpac.simply.imp": { - source: "iana", - extensions: ["imp"] - }, - "application/vnd.acm.addressxfer+json": { - source: "iana", - compressible: true - }, - "application/vnd.acm.chatbot+json": { - source: "iana", - compressible: true - }, - "application/vnd.acucobol": { - source: "iana", - extensions: ["acu"] - }, - "application/vnd.acucorp": { - source: "iana", - extensions: ["atc", "acutc"] - }, - "application/vnd.adobe.air-application-installer-package+zip": { - source: "apache", - compressible: false, - extensions: ["air"] - }, - "application/vnd.adobe.flash.movie": { - source: "iana" - }, - "application/vnd.adobe.formscentral.fcdt": { - source: "iana", - extensions: ["fcdt"] - }, - "application/vnd.adobe.fxp": { - source: "iana", - extensions: ["fxp", "fxpl"] - }, - "application/vnd.adobe.partial-upload": { - source: "iana" - }, - "application/vnd.adobe.xdp+xml": { - source: "iana", - compressible: true, - extensions: ["xdp"] - }, - "application/vnd.adobe.xfdf": { - source: "apache", - extensions: ["xfdf"] - }, - "application/vnd.aether.imp": { - source: "iana" - }, - "application/vnd.afpc.afplinedata": { - source: "iana" - }, - "application/vnd.afpc.afplinedata-pagedef": { - source: "iana" - }, - "application/vnd.afpc.cmoca-cmresource": { - source: "iana" - }, - "application/vnd.afpc.foca-charset": { - source: "iana" - }, - "application/vnd.afpc.foca-codedfont": { - source: "iana" - }, - "application/vnd.afpc.foca-codepage": { - source: "iana" - }, - "application/vnd.afpc.modca": { - source: "iana" - }, - "application/vnd.afpc.modca-cmtable": { - source: "iana" - }, - "application/vnd.afpc.modca-formdef": { - source: "iana" - }, - "application/vnd.afpc.modca-mediummap": { - source: "iana" - }, - "application/vnd.afpc.modca-objectcontainer": { - source: "iana" - }, - "application/vnd.afpc.modca-overlay": { - source: "iana" - }, - "application/vnd.afpc.modca-pagesegment": { - source: "iana" - }, - "application/vnd.age": { - source: "iana", - extensions: ["age"] - }, - "application/vnd.ah-barcode": { - source: "apache" - }, - "application/vnd.ahead.space": { - source: "iana", - extensions: ["ahead"] - }, - "application/vnd.airzip.filesecure.azf": { - source: "iana", - extensions: ["azf"] - }, - "application/vnd.airzip.filesecure.azs": { - source: "iana", - extensions: ["azs"] - }, - "application/vnd.amadeus+json": { - source: "iana", - compressible: true - }, - "application/vnd.amazon.ebook": { - source: "apache", - extensions: ["azw"] - }, - "application/vnd.amazon.mobi8-ebook": { - source: "iana" - }, - "application/vnd.americandynamics.acc": { - source: "iana", - extensions: ["acc"] - }, - "application/vnd.amiga.ami": { - source: "iana", - extensions: ["ami"] - }, - "application/vnd.amundsen.maze+xml": { - source: "iana", - compressible: true - }, - "application/vnd.android.ota": { - source: "iana" - }, - "application/vnd.android.package-archive": { - source: "apache", - compressible: false, - extensions: ["apk"] - }, - "application/vnd.anki": { - source: "iana" - }, - "application/vnd.anser-web-certificate-issue-initiation": { - source: "iana", - extensions: ["cii"] - }, - "application/vnd.anser-web-funds-transfer-initiation": { - source: "apache", - extensions: ["fti"] - }, - "application/vnd.antix.game-component": { - source: "iana", - extensions: ["atx"] - }, - "application/vnd.apache.arrow.file": { - source: "iana" - }, - "application/vnd.apache.arrow.stream": { - source: "iana" - }, - "application/vnd.apache.parquet": { - source: "iana" - }, - "application/vnd.apache.thrift.binary": { - source: "iana" - }, - "application/vnd.apache.thrift.compact": { - source: "iana" - }, - "application/vnd.apache.thrift.json": { - source: "iana" - }, - "application/vnd.apexlang": { - source: "iana" - }, - "application/vnd.api+json": { - source: "iana", - compressible: true - }, - "application/vnd.aplextor.warrp+json": { - source: "iana", - compressible: true - }, - "application/vnd.apothekende.reservation+json": { - source: "iana", - compressible: true - }, - "application/vnd.apple.installer+xml": { - source: "iana", - compressible: true, - extensions: ["mpkg"] - }, - "application/vnd.apple.keynote": { - source: "iana", - extensions: ["key"] - }, - "application/vnd.apple.mpegurl": { - source: "iana", - extensions: ["m3u8"] - }, - "application/vnd.apple.numbers": { - source: "iana", - extensions: ["numbers"] - }, - "application/vnd.apple.pages": { - source: "iana", - extensions: ["pages"] - }, - "application/vnd.apple.pkpass": { - compressible: false, - extensions: ["pkpass"] - }, - "application/vnd.arastra.swi": { - source: "apache" - }, - "application/vnd.aristanetworks.swi": { - source: "iana", - extensions: ["swi"] - }, - "application/vnd.artisan+json": { - source: "iana", - compressible: true - }, - "application/vnd.artsquare": { - source: "iana" - }, - "application/vnd.astraea-software.iota": { - source: "iana", - extensions: ["iota"] - }, - "application/vnd.audiograph": { - source: "iana", - extensions: ["aep"] - }, - "application/vnd.autodesk.fbx": { - extensions: ["fbx"] - }, - "application/vnd.autopackage": { - source: "iana" - }, - "application/vnd.avalon+json": { - source: "iana", - compressible: true - }, - "application/vnd.avistar+xml": { - source: "iana", - compressible: true - }, - "application/vnd.balsamiq.bmml+xml": { - source: "iana", - compressible: true, - extensions: ["bmml"] - }, - "application/vnd.balsamiq.bmpr": { - source: "iana" - }, - "application/vnd.banana-accounting": { - source: "iana" - }, - "application/vnd.bbf.usp.error": { - source: "iana" - }, - "application/vnd.bbf.usp.msg": { - source: "iana" - }, - "application/vnd.bbf.usp.msg+json": { - source: "iana", - compressible: true - }, - "application/vnd.bekitzur-stech+json": { - source: "iana", - compressible: true - }, - "application/vnd.belightsoft.lhzd+zip": { - source: "iana", - compressible: false - }, - "application/vnd.belightsoft.lhzl+zip": { - source: "iana", - compressible: false - }, - "application/vnd.bint.med-content": { - source: "iana" - }, - "application/vnd.biopax.rdf+xml": { - source: "iana", - compressible: true - }, - "application/vnd.blink-idb-value-wrapper": { - source: "iana" - }, - "application/vnd.blueice.multipass": { - source: "iana", - extensions: ["mpm"] - }, - "application/vnd.bluetooth.ep.oob": { - source: "iana" - }, - "application/vnd.bluetooth.le.oob": { - source: "iana" - }, - "application/vnd.bmi": { - source: "iana", - extensions: ["bmi"] - }, - "application/vnd.bpf": { - source: "iana" - }, - "application/vnd.bpf3": { - source: "iana" - }, - "application/vnd.businessobjects": { - source: "iana", - extensions: ["rep"] - }, - "application/vnd.byu.uapi+json": { - source: "iana", - compressible: true - }, - "application/vnd.bzip3": { - source: "iana" - }, - "application/vnd.c3voc.schedule+xml": { - source: "iana", - compressible: true - }, - "application/vnd.cab-jscript": { - source: "iana" - }, - "application/vnd.canon-cpdl": { - source: "iana" - }, - "application/vnd.canon-lips": { - source: "iana" - }, - "application/vnd.capasystems-pg+json": { - source: "iana", - compressible: true - }, - "application/vnd.cendio.thinlinc.clientconf": { - source: "iana" - }, - "application/vnd.century-systems.tcp_stream": { - source: "iana" - }, - "application/vnd.chemdraw+xml": { - source: "iana", - compressible: true, - extensions: ["cdxml"] - }, - "application/vnd.chess-pgn": { - source: "iana" - }, - "application/vnd.chipnuts.karaoke-mmd": { - source: "iana", - extensions: ["mmd"] - }, - "application/vnd.ciedi": { - source: "iana" - }, - "application/vnd.cinderella": { - source: "iana", - extensions: ["cdy"] - }, - "application/vnd.cirpack.isdn-ext": { - source: "iana" - }, - "application/vnd.citationstyles.style+xml": { - source: "iana", - compressible: true, - extensions: ["csl"] - }, - "application/vnd.claymore": { - source: "iana", - extensions: ["cla"] - }, - "application/vnd.cloanto.rp9": { - source: "iana", - extensions: ["rp9"] - }, - "application/vnd.clonk.c4group": { - source: "iana", - extensions: ["c4g", "c4d", "c4f", "c4p", "c4u"] - }, - "application/vnd.cluetrust.cartomobile-config": { - source: "iana", - extensions: ["c11amc"] - }, - "application/vnd.cluetrust.cartomobile-config-pkg": { - source: "iana", - extensions: ["c11amz"] - }, - "application/vnd.cncf.helm.chart.content.v1.tar+gzip": { - source: "iana" - }, - "application/vnd.cncf.helm.chart.provenance.v1.prov": { - source: "iana" - }, - "application/vnd.cncf.helm.config.v1+json": { - source: "iana", - compressible: true - }, - "application/vnd.coffeescript": { - source: "iana" - }, - "application/vnd.collabio.xodocuments.document": { - source: "iana" - }, - "application/vnd.collabio.xodocuments.document-template": { - source: "iana" - }, - "application/vnd.collabio.xodocuments.presentation": { - source: "iana" - }, - "application/vnd.collabio.xodocuments.presentation-template": { - source: "iana" - }, - "application/vnd.collabio.xodocuments.spreadsheet": { - source: "iana" - }, - "application/vnd.collabio.xodocuments.spreadsheet-template": { - source: "iana" - }, - "application/vnd.collection+json": { - source: "iana", - compressible: true - }, - "application/vnd.collection.doc+json": { - source: "iana", - compressible: true - }, - "application/vnd.collection.next+json": { - source: "iana", - compressible: true - }, - "application/vnd.comicbook+zip": { - source: "iana", - compressible: false - }, - "application/vnd.comicbook-rar": { - source: "iana" - }, - "application/vnd.commerce-battelle": { - source: "iana" - }, - "application/vnd.commonspace": { - source: "iana", - extensions: ["csp"] - }, - "application/vnd.contact.cmsg": { - source: "iana", - extensions: ["cdbcmsg"] - }, - "application/vnd.coreos.ignition+json": { - source: "iana", - compressible: true - }, - "application/vnd.cosmocaller": { - source: "iana", - extensions: ["cmc"] - }, - "application/vnd.crick.clicker": { - source: "iana", - extensions: ["clkx"] - }, - "application/vnd.crick.clicker.keyboard": { - source: "iana", - extensions: ["clkk"] - }, - "application/vnd.crick.clicker.palette": { - source: "iana", - extensions: ["clkp"] - }, - "application/vnd.crick.clicker.template": { - source: "iana", - extensions: ["clkt"] - }, - "application/vnd.crick.clicker.wordbank": { - source: "iana", - extensions: ["clkw"] - }, - "application/vnd.criticaltools.wbs+xml": { - source: "iana", - compressible: true, - extensions: ["wbs"] - }, - "application/vnd.cryptii.pipe+json": { - source: "iana", - compressible: true - }, - "application/vnd.crypto-shade-file": { - source: "iana" - }, - "application/vnd.cryptomator.encrypted": { - source: "iana" - }, - "application/vnd.cryptomator.vault": { - source: "iana" - }, - "application/vnd.ctc-posml": { - source: "iana", - extensions: ["pml"] - }, - "application/vnd.ctct.ws+xml": { - source: "iana", - compressible: true - }, - "application/vnd.cups-pdf": { - source: "iana" - }, - "application/vnd.cups-postscript": { - source: "iana" - }, - "application/vnd.cups-ppd": { - source: "iana", - extensions: ["ppd"] - }, - "application/vnd.cups-raster": { - source: "iana" - }, - "application/vnd.cups-raw": { - source: "iana" - }, - "application/vnd.curl": { - source: "iana" - }, - "application/vnd.curl.car": { - source: "apache", - extensions: ["car"] - }, - "application/vnd.curl.pcurl": { - source: "apache", - extensions: ["pcurl"] - }, - "application/vnd.cyan.dean.root+xml": { - source: "iana", - compressible: true - }, - "application/vnd.cybank": { - source: "iana" - }, - "application/vnd.cyclonedx+json": { - source: "iana", - compressible: true - }, - "application/vnd.cyclonedx+xml": { - source: "iana", - compressible: true - }, - "application/vnd.d2l.coursepackage1p0+zip": { - source: "iana", - compressible: false - }, - "application/vnd.d3m-dataset": { - source: "iana" - }, - "application/vnd.d3m-problem": { - source: "iana" - }, - "application/vnd.dart": { - source: "iana", - compressible: true, - extensions: ["dart"] - }, - "application/vnd.data-vision.rdz": { - source: "iana", - extensions: ["rdz"] - }, - "application/vnd.datalog": { - source: "iana" - }, - "application/vnd.datapackage+json": { - source: "iana", - compressible: true - }, - "application/vnd.dataresource+json": { - source: "iana", - compressible: true - }, - "application/vnd.dbf": { - source: "iana", - extensions: ["dbf"] - }, - "application/vnd.dcmp+xml": { - source: "iana", - compressible: true, - extensions: ["dcmp"] - }, - "application/vnd.debian.binary-package": { - source: "iana" - }, - "application/vnd.dece.data": { - source: "iana", - extensions: ["uvf", "uvvf", "uvd", "uvvd"] - }, - "application/vnd.dece.ttml+xml": { - source: "iana", - compressible: true, - extensions: ["uvt", "uvvt"] - }, - "application/vnd.dece.unspecified": { - source: "iana", - extensions: ["uvx", "uvvx"] - }, - "application/vnd.dece.zip": { - source: "iana", - extensions: ["uvz", "uvvz"] - }, - "application/vnd.denovo.fcselayout-link": { - source: "iana", - extensions: ["fe_launch"] - }, - "application/vnd.desmume.movie": { - source: "iana" - }, - "application/vnd.dir-bi.plate-dl-nosuffix": { - source: "iana" - }, - "application/vnd.dm.delegation+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dna": { - source: "iana", - extensions: ["dna"] - }, - "application/vnd.document+json": { - source: "iana", - compressible: true - }, - "application/vnd.dolby.mlp": { - source: "apache", - extensions: ["mlp"] - }, - "application/vnd.dolby.mobile.1": { - source: "iana" - }, - "application/vnd.dolby.mobile.2": { - source: "iana" - }, - "application/vnd.doremir.scorecloud-binary-document": { - source: "iana" - }, - "application/vnd.dpgraph": { - source: "iana", - extensions: ["dpg"] - }, - "application/vnd.dreamfactory": { - source: "iana", - extensions: ["dfac"] - }, - "application/vnd.drive+json": { - source: "iana", - compressible: true - }, - "application/vnd.ds-keypoint": { - source: "apache", - extensions: ["kpxx"] - }, - "application/vnd.dtg.local": { - source: "iana" - }, - "application/vnd.dtg.local.flash": { - source: "iana" - }, - "application/vnd.dtg.local.html": { - source: "iana" - }, - "application/vnd.dvb.ait": { - source: "iana", - extensions: ["ait"] - }, - "application/vnd.dvb.dvbisl+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.dvbj": { - source: "iana" - }, - "application/vnd.dvb.esgcontainer": { - source: "iana" - }, - "application/vnd.dvb.ipdcdftnotifaccess": { - source: "iana" - }, - "application/vnd.dvb.ipdcesgaccess": { - source: "iana" - }, - "application/vnd.dvb.ipdcesgaccess2": { - source: "iana" - }, - "application/vnd.dvb.ipdcesgpdd": { - source: "iana" - }, - "application/vnd.dvb.ipdcroaming": { - source: "iana" - }, - "application/vnd.dvb.iptv.alfec-base": { - source: "iana" - }, - "application/vnd.dvb.iptv.alfec-enhancement": { - source: "iana" - }, - "application/vnd.dvb.notif-aggregate-root+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.notif-container+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.notif-generic+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.notif-ia-msglist+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.notif-ia-registration-request+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.notif-ia-registration-response+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.notif-init+xml": { - source: "iana", - compressible: true - }, - "application/vnd.dvb.pfr": { - source: "iana" - }, - "application/vnd.dvb.service": { - source: "iana", - extensions: ["svc"] - }, - "application/vnd.dxr": { - source: "iana" - }, - "application/vnd.dynageo": { - source: "iana", - extensions: ["geo"] - }, - "application/vnd.dzr": { - source: "iana" - }, - "application/vnd.easykaraoke.cdgdownload": { - source: "iana" - }, - "application/vnd.ecdis-update": { - source: "iana" - }, - "application/vnd.ecip.rlp": { - source: "iana" - }, - "application/vnd.eclipse.ditto+json": { - source: "iana", - compressible: true - }, - "application/vnd.ecowin.chart": { - source: "iana", - extensions: ["mag"] - }, - "application/vnd.ecowin.filerequest": { - source: "iana" - }, - "application/vnd.ecowin.fileupdate": { - source: "iana" - }, - "application/vnd.ecowin.series": { - source: "iana" - }, - "application/vnd.ecowin.seriesrequest": { - source: "iana" - }, - "application/vnd.ecowin.seriesupdate": { - source: "iana" - }, - "application/vnd.efi.img": { - source: "iana" - }, - "application/vnd.efi.iso": { - source: "iana" - }, - "application/vnd.eln+zip": { - source: "iana", - compressible: false - }, - "application/vnd.emclient.accessrequest+xml": { - source: "iana", - compressible: true - }, - "application/vnd.enliven": { - source: "iana", - extensions: ["nml"] - }, - "application/vnd.enphase.envoy": { - source: "iana" - }, - "application/vnd.eprints.data+xml": { - source: "iana", - compressible: true - }, - "application/vnd.epson.esf": { - source: "iana", - extensions: ["esf"] - }, - "application/vnd.epson.msf": { - source: "iana", - extensions: ["msf"] - }, - "application/vnd.epson.quickanime": { - source: "iana", - extensions: ["qam"] - }, - "application/vnd.epson.salt": { - source: "iana", - extensions: ["slt"] - }, - "application/vnd.epson.ssf": { - source: "iana", - extensions: ["ssf"] - }, - "application/vnd.ericsson.quickcall": { - source: "iana" - }, - "application/vnd.erofs": { - source: "iana" - }, - "application/vnd.espass-espass+zip": { - source: "iana", - compressible: false - }, - "application/vnd.eszigno3+xml": { - source: "iana", - compressible: true, - extensions: ["es3", "et3"] - }, - "application/vnd.etsi.aoc+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.asic-e+zip": { - source: "iana", - compressible: false - }, - "application/vnd.etsi.asic-s+zip": { - source: "iana", - compressible: false - }, - "application/vnd.etsi.cug+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvcommand+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvdiscovery+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvprofile+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvsad-bc+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvsad-cod+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvsad-npvr+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvservice+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvsync+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.iptvueprofile+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.mcid+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.mheg5": { - source: "iana" - }, - "application/vnd.etsi.overload-control-policy-dataset+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.pstn+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.sci+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.simservs+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.timestamp-token": { - source: "iana" - }, - "application/vnd.etsi.tsl+xml": { - source: "iana", - compressible: true - }, - "application/vnd.etsi.tsl.der": { - source: "iana" - }, - "application/vnd.eu.kasparian.car+json": { - source: "iana", - compressible: true - }, - "application/vnd.eudora.data": { - source: "iana" - }, - "application/vnd.evolv.ecig.profile": { - source: "iana" - }, - "application/vnd.evolv.ecig.settings": { - source: "iana" - }, - "application/vnd.evolv.ecig.theme": { - source: "iana" - }, - "application/vnd.exstream-empower+zip": { - source: "iana", - compressible: false - }, - "application/vnd.exstream-package": { - source: "iana" - }, - "application/vnd.ezpix-album": { - source: "iana", - extensions: ["ez2"] - }, - "application/vnd.ezpix-package": { - source: "iana", - extensions: ["ez3"] - }, - "application/vnd.f-secure.mobile": { - source: "iana" - }, - "application/vnd.familysearch.gedcom+zip": { - source: "iana", - compressible: false - }, - "application/vnd.fastcopy-disk-image": { - source: "iana" - }, - "application/vnd.fdf": { - source: "apache", - extensions: ["fdf"] - }, - "application/vnd.fdsn.mseed": { - source: "iana", - extensions: ["mseed"] - }, - "application/vnd.fdsn.seed": { - source: "iana", - extensions: ["seed", "dataless"] - }, - "application/vnd.fdsn.stationxml+xml": { - source: "iana", - charset: "XML-BASED", - compressible: true - }, - "application/vnd.ffsns": { - source: "iana" - }, - "application/vnd.ficlab.flb+zip": { - source: "iana", - compressible: false - }, - "application/vnd.filmit.zfc": { - source: "iana" - }, - "application/vnd.fints": { - source: "iana" - }, - "application/vnd.firemonkeys.cloudcell": { - source: "iana" - }, - "application/vnd.flographit": { - source: "iana", - extensions: ["gph"] - }, - "application/vnd.fluxtime.clip": { - source: "iana", - extensions: ["ftc"] - }, - "application/vnd.font-fontforge-sfd": { - source: "iana" - }, - "application/vnd.framemaker": { - source: "iana", - extensions: ["fm", "frame", "maker", "book"] - }, - "application/vnd.freelog.comic": { - source: "iana" - }, - "application/vnd.frogans.fnc": { - source: "apache", - extensions: ["fnc"] - }, - "application/vnd.frogans.ltf": { - source: "apache", - extensions: ["ltf"] - }, - "application/vnd.fsc.weblaunch": { - source: "iana", - extensions: ["fsc"] - }, - "application/vnd.fujifilm.fb.docuworks": { - source: "iana" - }, - "application/vnd.fujifilm.fb.docuworks.binder": { - source: "iana" - }, - "application/vnd.fujifilm.fb.docuworks.container": { - source: "iana" - }, - "application/vnd.fujifilm.fb.jfi+xml": { - source: "iana", - compressible: true - }, - "application/vnd.fujitsu.oasys": { - source: "iana", - extensions: ["oas"] - }, - "application/vnd.fujitsu.oasys2": { - source: "iana", - extensions: ["oa2"] - }, - "application/vnd.fujitsu.oasys3": { - source: "iana", - extensions: ["oa3"] - }, - "application/vnd.fujitsu.oasysgp": { - source: "iana", - extensions: ["fg5"] - }, - "application/vnd.fujitsu.oasysprs": { - source: "iana", - extensions: ["bh2"] - }, - "application/vnd.fujixerox.art-ex": { - source: "iana" - }, - "application/vnd.fujixerox.art4": { - source: "iana" - }, - "application/vnd.fujixerox.ddd": { - source: "iana", - extensions: ["ddd"] - }, - "application/vnd.fujixerox.docuworks": { - source: "iana", - extensions: ["xdw"] - }, - "application/vnd.fujixerox.docuworks.binder": { - source: "iana", - extensions: ["xbd"] - }, - "application/vnd.fujixerox.docuworks.container": { - source: "iana" - }, - "application/vnd.fujixerox.hbpl": { - source: "iana" - }, - "application/vnd.fut-misnet": { - source: "iana" - }, - "application/vnd.futoin+cbor": { - source: "iana" - }, - "application/vnd.futoin+json": { - source: "iana", - compressible: true - }, - "application/vnd.fuzzysheet": { - source: "iana", - extensions: ["fzs"] - }, - "application/vnd.ga4gh.passport+jwt": { - source: "iana" - }, - "application/vnd.genomatix.tuxedo": { - source: "iana", - extensions: ["txd"] - }, - "application/vnd.genozip": { - source: "iana" - }, - "application/vnd.gentics.grd+json": { - source: "iana", - compressible: true - }, - "application/vnd.gentoo.catmetadata+xml": { - source: "iana", - compressible: true - }, - "application/vnd.gentoo.ebuild": { - source: "iana" - }, - "application/vnd.gentoo.eclass": { - source: "iana" - }, - "application/vnd.gentoo.gpkg": { - source: "iana" - }, - "application/vnd.gentoo.manifest": { - source: "iana" - }, - "application/vnd.gentoo.pkgmetadata+xml": { - source: "iana", - compressible: true - }, - "application/vnd.gentoo.xpak": { - source: "iana" - }, - "application/vnd.geo+json": { - source: "apache", - compressible: true - }, - "application/vnd.geocube+xml": { - source: "apache", - compressible: true - }, - "application/vnd.geogebra.file": { - source: "iana", - extensions: ["ggb"] - }, - "application/vnd.geogebra.pinboard": { - source: "iana" - }, - "application/vnd.geogebra.slides": { - source: "iana", - extensions: ["ggs"] - }, - "application/vnd.geogebra.tool": { - source: "iana", - extensions: ["ggt"] - }, - "application/vnd.geometry-explorer": { - source: "iana", - extensions: ["gex", "gre"] - }, - "application/vnd.geonext": { - source: "iana", - extensions: ["gxt"] - }, - "application/vnd.geoplan": { - source: "iana", - extensions: ["g2w"] - }, - "application/vnd.geospace": { - source: "iana", - extensions: ["g3w"] - }, - "application/vnd.gerber": { - source: "iana" - }, - "application/vnd.globalplatform.card-content-mgt": { - source: "iana" - }, - "application/vnd.globalplatform.card-content-mgt-response": { - source: "iana" - }, - "application/vnd.gmx": { - source: "iana", - extensions: ["gmx"] - }, - "application/vnd.gnu.taler.exchange+json": { - source: "iana", - compressible: true - }, - "application/vnd.gnu.taler.merchant+json": { - source: "iana", - compressible: true - }, - "application/vnd.google-apps.audio": {}, - "application/vnd.google-apps.document": { - compressible: false, - extensions: ["gdoc"] - }, - "application/vnd.google-apps.drawing": { - compressible: false, - extensions: ["gdraw"] - }, - "application/vnd.google-apps.drive-sdk": { - compressible: false - }, - "application/vnd.google-apps.file": {}, - "application/vnd.google-apps.folder": { - compressible: false - }, - "application/vnd.google-apps.form": { - compressible: false, - extensions: ["gform"] - }, - "application/vnd.google-apps.fusiontable": {}, - "application/vnd.google-apps.jam": { - compressible: false, - extensions: ["gjam"] - }, - "application/vnd.google-apps.mail-layout": {}, - "application/vnd.google-apps.map": { - compressible: false, - extensions: ["gmap"] - }, - "application/vnd.google-apps.photo": {}, - "application/vnd.google-apps.presentation": { - compressible: false, - extensions: ["gslides"] - }, - "application/vnd.google-apps.script": { - compressible: false, - extensions: ["gscript"] - }, - "application/vnd.google-apps.shortcut": {}, - "application/vnd.google-apps.site": { - compressible: false, - extensions: ["gsite"] - }, - "application/vnd.google-apps.spreadsheet": { - compressible: false, - extensions: ["gsheet"] - }, - "application/vnd.google-apps.unknown": {}, - "application/vnd.google-apps.video": {}, - "application/vnd.google-earth.kml+xml": { - source: "iana", - compressible: true, - extensions: ["kml"] - }, - "application/vnd.google-earth.kmz": { - source: "iana", - compressible: false, - extensions: ["kmz"] - }, - "application/vnd.gov.sk.e-form+xml": { - source: "apache", - compressible: true - }, - "application/vnd.gov.sk.e-form+zip": { - source: "iana", - compressible: false - }, - "application/vnd.gov.sk.xmldatacontainer+xml": { - source: "iana", - compressible: true, - extensions: ["xdcf"] - }, - "application/vnd.gpxsee.map+xml": { - source: "iana", - compressible: true - }, - "application/vnd.grafeq": { - source: "iana", - extensions: ["gqf", "gqs"] - }, - "application/vnd.gridmp": { - source: "iana" - }, - "application/vnd.groove-account": { - source: "iana", - extensions: ["gac"] - }, - "application/vnd.groove-help": { - source: "iana", - extensions: ["ghf"] - }, - "application/vnd.groove-identity-message": { - source: "iana", - extensions: ["gim"] - }, - "application/vnd.groove-injector": { - source: "iana", - extensions: ["grv"] - }, - "application/vnd.groove-tool-message": { - source: "iana", - extensions: ["gtm"] - }, - "application/vnd.groove-tool-template": { - source: "iana", - extensions: ["tpl"] - }, - "application/vnd.groove-vcard": { - source: "iana", - extensions: ["vcg"] - }, - "application/vnd.hal+json": { - source: "iana", - compressible: true - }, - "application/vnd.hal+xml": { - source: "iana", - compressible: true, - extensions: ["hal"] - }, - "application/vnd.handheld-entertainment+xml": { - source: "iana", - compressible: true, - extensions: ["zmm"] - }, - "application/vnd.hbci": { - source: "iana", - extensions: ["hbci"] - }, - "application/vnd.hc+json": { - source: "iana", - compressible: true - }, - "application/vnd.hcl-bireports": { - source: "iana" - }, - "application/vnd.hdt": { - source: "iana" - }, - "application/vnd.heroku+json": { - source: "iana", - compressible: true - }, - "application/vnd.hhe.lesson-player": { - source: "iana", - extensions: ["les"] - }, - "application/vnd.hp-hpgl": { - source: "iana", - extensions: ["hpgl"] - }, - "application/vnd.hp-hpid": { - source: "iana", - extensions: ["hpid"] - }, - "application/vnd.hp-hps": { - source: "iana", - extensions: ["hps"] - }, - "application/vnd.hp-jlyt": { - source: "iana", - extensions: ["jlt"] - }, - "application/vnd.hp-pcl": { - source: "iana", - extensions: ["pcl"] - }, - "application/vnd.hp-pclxl": { - source: "iana", - extensions: ["pclxl"] - }, - "application/vnd.hsl": { - source: "iana" - }, - "application/vnd.httphone": { - source: "iana" - }, - "application/vnd.hydrostatix.sof-data": { - source: "iana", - extensions: ["sfd-hdstx"] - }, - "application/vnd.hyper+json": { - source: "iana", - compressible: true - }, - "application/vnd.hyper-item+json": { - source: "iana", - compressible: true - }, - "application/vnd.hyperdrive+json": { - source: "iana", - compressible: true - }, - "application/vnd.hzn-3d-crossword": { - source: "iana" - }, - "application/vnd.ibm.afplinedata": { - source: "apache" - }, - "application/vnd.ibm.electronic-media": { - source: "iana" - }, - "application/vnd.ibm.minipay": { - source: "iana", - extensions: ["mpy"] - }, - "application/vnd.ibm.modcap": { - source: "apache", - extensions: ["afp", "listafp", "list3820"] - }, - "application/vnd.ibm.rights-management": { - source: "iana", - extensions: ["irm"] - }, - "application/vnd.ibm.secure-container": { - source: "iana", - extensions: ["sc"] - }, - "application/vnd.iccprofile": { - source: "iana", - extensions: ["icc", "icm"] - }, - "application/vnd.ieee.1905": { - source: "iana" - }, - "application/vnd.igloader": { - source: "iana", - extensions: ["igl"] - }, - "application/vnd.imagemeter.folder+zip": { - source: "iana", - compressible: false - }, - "application/vnd.imagemeter.image+zip": { - source: "iana", - compressible: false - }, - "application/vnd.immervision-ivp": { - source: "iana", - extensions: ["ivp"] - }, - "application/vnd.immervision-ivu": { - source: "iana", - extensions: ["ivu"] - }, - "application/vnd.ims.imsccv1p1": { - source: "iana" - }, - "application/vnd.ims.imsccv1p2": { - source: "iana" - }, - "application/vnd.ims.imsccv1p3": { - source: "iana" - }, - "application/vnd.ims.lis.v2.result+json": { - source: "iana", - compressible: true - }, - "application/vnd.ims.lti.v2.toolconsumerprofile+json": { - source: "iana", - compressible: true - }, - "application/vnd.ims.lti.v2.toolproxy+json": { - source: "iana", - compressible: true - }, - "application/vnd.ims.lti.v2.toolproxy.id+json": { - source: "iana", - compressible: true - }, - "application/vnd.ims.lti.v2.toolsettings+json": { - source: "iana", - compressible: true - }, - "application/vnd.ims.lti.v2.toolsettings.simple+json": { - source: "iana", - compressible: true - }, - "application/vnd.informedcontrol.rms+xml": { - source: "iana", - compressible: true - }, - "application/vnd.informix-visionary": { - source: "apache" - }, - "application/vnd.infotech.project": { - source: "iana" - }, - "application/vnd.infotech.project+xml": { - source: "iana", - compressible: true - }, - "application/vnd.innopath.wamp.notification": { - source: "iana" - }, - "application/vnd.insors.igm": { - source: "iana", - extensions: ["igm"] - }, - "application/vnd.intercon.formnet": { - source: "iana", - extensions: ["xpw", "xpx"] - }, - "application/vnd.intergeo": { - source: "iana", - extensions: ["i2g"] - }, - "application/vnd.intertrust.digibox": { - source: "iana" - }, - "application/vnd.intertrust.nncp": { - source: "iana" - }, - "application/vnd.intu.qbo": { - source: "iana", - extensions: ["qbo"] - }, - "application/vnd.intu.qfx": { - source: "iana", - extensions: ["qfx"] - }, - "application/vnd.ipfs.ipns-record": { - source: "iana" - }, - "application/vnd.ipld.car": { - source: "iana" - }, - "application/vnd.ipld.dag-cbor": { - source: "iana" - }, - "application/vnd.ipld.dag-json": { - source: "iana" - }, - "application/vnd.ipld.raw": { - source: "iana" - }, - "application/vnd.iptc.g2.catalogitem+xml": { - source: "iana", - compressible: true - }, - "application/vnd.iptc.g2.conceptitem+xml": { - source: "iana", - compressible: true - }, - "application/vnd.iptc.g2.knowledgeitem+xml": { - source: "iana", - compressible: true - }, - "application/vnd.iptc.g2.newsitem+xml": { - source: "iana", - compressible: true - }, - "application/vnd.iptc.g2.newsmessage+xml": { - source: "iana", - compressible: true - }, - "application/vnd.iptc.g2.packageitem+xml": { - source: "iana", - compressible: true - }, - "application/vnd.iptc.g2.planningitem+xml": { - source: "iana", - compressible: true - }, - "application/vnd.ipunplugged.rcprofile": { - source: "iana", - extensions: ["rcprofile"] - }, - "application/vnd.irepository.package+xml": { - source: "iana", - compressible: true, - extensions: ["irp"] - }, - "application/vnd.is-xpr": { - source: "iana", - extensions: ["xpr"] - }, - "application/vnd.isac.fcs": { - source: "iana", - extensions: ["fcs"] - }, - "application/vnd.iso11783-10+zip": { - source: "iana", - compressible: false - }, - "application/vnd.jam": { - source: "iana", - extensions: ["jam"] - }, - "application/vnd.japannet-directory-service": { - source: "iana" - }, - "application/vnd.japannet-jpnstore-wakeup": { - source: "iana" - }, - "application/vnd.japannet-payment-wakeup": { - source: "iana" - }, - "application/vnd.japannet-registration": { - source: "iana" - }, - "application/vnd.japannet-registration-wakeup": { - source: "iana" - }, - "application/vnd.japannet-setstore-wakeup": { - source: "iana" - }, - "application/vnd.japannet-verification": { - source: "iana" - }, - "application/vnd.japannet-verification-wakeup": { - source: "iana" - }, - "application/vnd.jcp.javame.midlet-rms": { - source: "iana", - extensions: ["rms"] - }, - "application/vnd.jisp": { - source: "iana", - extensions: ["jisp"] - }, - "application/vnd.joost.joda-archive": { - source: "iana", - extensions: ["joda"] - }, - "application/vnd.jsk.isdn-ngn": { - source: "iana" - }, - "application/vnd.kahootz": { - source: "iana", - extensions: ["ktz", "ktr"] - }, - "application/vnd.kde.karbon": { - source: "iana", - extensions: ["karbon"] - }, - "application/vnd.kde.kchart": { - source: "iana", - extensions: ["chrt"] - }, - "application/vnd.kde.kformula": { - source: "iana", - extensions: ["kfo"] - }, - "application/vnd.kde.kivio": { - source: "iana", - extensions: ["flw"] - }, - "application/vnd.kde.kontour": { - source: "iana", - extensions: ["kon"] - }, - "application/vnd.kde.kpresenter": { - source: "iana", - extensions: ["kpr", "kpt"] - }, - "application/vnd.kde.kspread": { - source: "iana", - extensions: ["ksp"] - }, - "application/vnd.kde.kword": { - source: "iana", - extensions: ["kwd", "kwt"] - }, - "application/vnd.kdl": { - source: "iana" - }, - "application/vnd.kenameaapp": { - source: "iana", - extensions: ["htke"] - }, - "application/vnd.keyman.kmp+zip": { - source: "iana", - compressible: false - }, - "application/vnd.keyman.kmx": { - source: "iana" - }, - "application/vnd.kidspiration": { - source: "iana", - extensions: ["kia"] - }, - "application/vnd.kinar": { - source: "iana", - extensions: ["kne", "knp"] - }, - "application/vnd.koan": { - source: "iana", - extensions: ["skp", "skd", "skt", "skm"] - }, - "application/vnd.kodak-descriptor": { - source: "iana", - extensions: ["sse"] - }, - "application/vnd.las": { - source: "iana" - }, - "application/vnd.las.las+json": { - source: "iana", - compressible: true - }, - "application/vnd.las.las+xml": { - source: "iana", - compressible: true, - extensions: ["lasxml"] - }, - "application/vnd.laszip": { - source: "iana" - }, - "application/vnd.ldev.productlicensing": { - source: "iana" - }, - "application/vnd.leap+json": { - source: "iana", - compressible: true - }, - "application/vnd.liberty-request+xml": { - source: "iana", - compressible: true - }, - "application/vnd.llamagraphics.life-balance.desktop": { - source: "iana", - extensions: ["lbd"] - }, - "application/vnd.llamagraphics.life-balance.exchange+xml": { - source: "iana", - compressible: true, - extensions: ["lbe"] - }, - "application/vnd.logipipe.circuit+zip": { - source: "iana", - compressible: false - }, - "application/vnd.loom": { - source: "iana" - }, - "application/vnd.lotus-1-2-3": { - source: "iana", - extensions: ["123"] - }, - "application/vnd.lotus-approach": { - source: "iana", - extensions: ["apr"] - }, - "application/vnd.lotus-freelance": { - source: "iana", - extensions: ["pre"] - }, - "application/vnd.lotus-notes": { - source: "iana", - extensions: ["nsf"] - }, - "application/vnd.lotus-organizer": { - source: "iana", - extensions: ["org"] - }, - "application/vnd.lotus-screencam": { - source: "iana", - extensions: ["scm"] - }, - "application/vnd.lotus-wordpro": { - source: "iana", - extensions: ["lwp"] - }, - "application/vnd.macports.portpkg": { - source: "iana", - extensions: ["portpkg"] - }, - "application/vnd.mapbox-vector-tile": { - source: "iana", - extensions: ["mvt"] - }, - "application/vnd.marlin.drm.actiontoken+xml": { - source: "iana", - compressible: true - }, - "application/vnd.marlin.drm.conftoken+xml": { - source: "iana", - compressible: true - }, - "application/vnd.marlin.drm.license+xml": { - source: "iana", - compressible: true - }, - "application/vnd.marlin.drm.mdcf": { - source: "iana" - }, - "application/vnd.mason+json": { - source: "iana", - compressible: true - }, - "application/vnd.maxar.archive.3tz+zip": { - source: "iana", - compressible: false - }, - "application/vnd.maxmind.maxmind-db": { - source: "iana" - }, - "application/vnd.mcd": { - source: "iana", - extensions: ["mcd"] - }, - "application/vnd.mdl": { - source: "iana" - }, - "application/vnd.mdl-mbsdf": { - source: "iana" - }, - "application/vnd.medcalcdata": { - source: "iana", - extensions: ["mc1"] - }, - "application/vnd.mediastation.cdkey": { - source: "iana", - extensions: ["cdkey"] - }, - "application/vnd.medicalholodeck.recordxr": { - source: "iana" - }, - "application/vnd.meridian-slingshot": { - source: "iana" - }, - "application/vnd.mermaid": { - source: "iana" - }, - "application/vnd.mfer": { - source: "iana", - extensions: ["mwf"] - }, - "application/vnd.mfmp": { - source: "iana", - extensions: ["mfm"] - }, - "application/vnd.micro+json": { - source: "iana", - compressible: true - }, - "application/vnd.micrografx.flo": { - source: "iana", - extensions: ["flo"] - }, - "application/vnd.micrografx.igx": { - source: "iana", - extensions: ["igx"] - }, - "application/vnd.microsoft.portable-executable": { - source: "iana" - }, - "application/vnd.microsoft.windows.thumbnail-cache": { - source: "iana" - }, - "application/vnd.miele+json": { - source: "iana", - compressible: true - }, - "application/vnd.mif": { - source: "iana", - extensions: ["mif"] - }, - "application/vnd.minisoft-hp3000-save": { - source: "iana" - }, - "application/vnd.mitsubishi.misty-guard.trustweb": { - source: "iana" - }, - "application/vnd.mobius.daf": { - source: "iana", - extensions: ["daf"] - }, - "application/vnd.mobius.dis": { - source: "iana", - extensions: ["dis"] - }, - "application/vnd.mobius.mbk": { - source: "iana", - extensions: ["mbk"] - }, - "application/vnd.mobius.mqy": { - source: "iana", - extensions: ["mqy"] - }, - "application/vnd.mobius.msl": { - source: "iana", - extensions: ["msl"] - }, - "application/vnd.mobius.plc": { - source: "iana", - extensions: ["plc"] - }, - "application/vnd.mobius.txf": { - source: "iana", - extensions: ["txf"] - }, - "application/vnd.modl": { - source: "iana" - }, - "application/vnd.mophun.application": { - source: "iana", - extensions: ["mpn"] - }, - "application/vnd.mophun.certificate": { - source: "iana", - extensions: ["mpc"] - }, - "application/vnd.motorola.flexsuite": { - source: "iana" - }, - "application/vnd.motorola.flexsuite.adsi": { - source: "iana" - }, - "application/vnd.motorola.flexsuite.fis": { - source: "iana" - }, - "application/vnd.motorola.flexsuite.gotap": { - source: "iana" - }, - "application/vnd.motorola.flexsuite.kmr": { - source: "iana" - }, - "application/vnd.motorola.flexsuite.ttc": { - source: "iana" - }, - "application/vnd.motorola.flexsuite.wem": { - source: "iana" - }, - "application/vnd.motorola.iprm": { - source: "iana" - }, - "application/vnd.mozilla.xul+xml": { - source: "iana", - compressible: true, - extensions: ["xul"] - }, - "application/vnd.ms-3mfdocument": { - source: "iana" - }, - "application/vnd.ms-artgalry": { - source: "iana", - extensions: ["cil"] - }, - "application/vnd.ms-asf": { - source: "iana" - }, - "application/vnd.ms-cab-compressed": { - source: "iana", - extensions: ["cab"] - }, - "application/vnd.ms-color.iccprofile": { - source: "apache" - }, - "application/vnd.ms-excel": { - source: "iana", - compressible: false, - extensions: ["xls", "xlm", "xla", "xlc", "xlt", "xlw"] - }, - "application/vnd.ms-excel.addin.macroenabled.12": { - source: "iana", - extensions: ["xlam"] - }, - "application/vnd.ms-excel.sheet.binary.macroenabled.12": { - source: "iana", - extensions: ["xlsb"] - }, - "application/vnd.ms-excel.sheet.macroenabled.12": { - source: "iana", - extensions: ["xlsm"] - }, - "application/vnd.ms-excel.template.macroenabled.12": { - source: "iana", - extensions: ["xltm"] - }, - "application/vnd.ms-fontobject": { - source: "iana", - compressible: true, - extensions: ["eot"] - }, - "application/vnd.ms-htmlhelp": { - source: "iana", - extensions: ["chm"] - }, - "application/vnd.ms-ims": { - source: "iana", - extensions: ["ims"] - }, - "application/vnd.ms-lrm": { - source: "iana", - extensions: ["lrm"] - }, - "application/vnd.ms-office.activex+xml": { - source: "iana", - compressible: true - }, - "application/vnd.ms-officetheme": { - source: "iana", - extensions: ["thmx"] - }, - "application/vnd.ms-opentype": { - source: "apache", - compressible: true - }, - "application/vnd.ms-outlook": { - compressible: false, - extensions: ["msg"] - }, - "application/vnd.ms-package.obfuscated-opentype": { - source: "apache" - }, - "application/vnd.ms-pki.seccat": { - source: "apache", - extensions: ["cat"] - }, - "application/vnd.ms-pki.stl": { - source: "apache", - extensions: ["stl"] - }, - "application/vnd.ms-playready.initiator+xml": { - source: "iana", - compressible: true - }, - "application/vnd.ms-powerpoint": { - source: "iana", - compressible: false, - extensions: ["ppt", "pps", "pot"] - }, - "application/vnd.ms-powerpoint.addin.macroenabled.12": { - source: "iana", - extensions: ["ppam"] - }, - "application/vnd.ms-powerpoint.presentation.macroenabled.12": { - source: "iana", - extensions: ["pptm"] - }, - "application/vnd.ms-powerpoint.slide.macroenabled.12": { - source: "iana", - extensions: ["sldm"] - }, - "application/vnd.ms-powerpoint.slideshow.macroenabled.12": { - source: "iana", - extensions: ["ppsm"] - }, - "application/vnd.ms-powerpoint.template.macroenabled.12": { - source: "iana", - extensions: ["potm"] - }, - "application/vnd.ms-printdevicecapabilities+xml": { - source: "iana", - compressible: true - }, - "application/vnd.ms-printing.printticket+xml": { - source: "apache", - compressible: true - }, - "application/vnd.ms-printschematicket+xml": { - source: "iana", - compressible: true - }, - "application/vnd.ms-project": { - source: "iana", - extensions: ["mpp", "mpt"] - }, - "application/vnd.ms-tnef": { - source: "iana" - }, - "application/vnd.ms-visio.viewer": { - extensions: ["vdx"] - }, - "application/vnd.ms-windows.devicepairing": { - source: "iana" - }, - "application/vnd.ms-windows.nwprinting.oob": { - source: "iana" - }, - "application/vnd.ms-windows.printerpairing": { - source: "iana" - }, - "application/vnd.ms-windows.wsd.oob": { - source: "iana" - }, - "application/vnd.ms-wmdrm.lic-chlg-req": { - source: "iana" - }, - "application/vnd.ms-wmdrm.lic-resp": { - source: "iana" - }, - "application/vnd.ms-wmdrm.meter-chlg-req": { - source: "iana" - }, - "application/vnd.ms-wmdrm.meter-resp": { - source: "iana" - }, - "application/vnd.ms-word.document.macroenabled.12": { - source: "iana", - extensions: ["docm"] - }, - "application/vnd.ms-word.template.macroenabled.12": { - source: "iana", - extensions: ["dotm"] - }, - "application/vnd.ms-works": { - source: "iana", - extensions: ["wps", "wks", "wcm", "wdb"] - }, - "application/vnd.ms-wpl": { - source: "iana", - extensions: ["wpl"] - }, - "application/vnd.ms-xpsdocument": { - source: "iana", - compressible: false, - extensions: ["xps"] - }, - "application/vnd.msa-disk-image": { - source: "iana" - }, - "application/vnd.mseq": { - source: "iana", - extensions: ["mseq"] - }, - "application/vnd.msgpack": { - source: "iana" - }, - "application/vnd.msign": { - source: "iana" - }, - "application/vnd.multiad.creator": { - source: "iana" - }, - "application/vnd.multiad.creator.cif": { - source: "iana" - }, - "application/vnd.music-niff": { - source: "iana" - }, - "application/vnd.musician": { - source: "iana", - extensions: ["mus"] - }, - "application/vnd.muvee.style": { - source: "iana", - extensions: ["msty"] - }, - "application/vnd.mynfc": { - source: "iana", - extensions: ["taglet"] - }, - "application/vnd.nacamar.ybrid+json": { - source: "iana", - compressible: true - }, - "application/vnd.nato.bindingdataobject+cbor": { - source: "iana" - }, - "application/vnd.nato.bindingdataobject+json": { - source: "iana", - compressible: true - }, - "application/vnd.nato.bindingdataobject+xml": { - source: "iana", - compressible: true, - extensions: ["bdo"] - }, - "application/vnd.nato.openxmlformats-package.iepd+zip": { - source: "iana", - compressible: false - }, - "application/vnd.ncd.control": { - source: "iana" - }, - "application/vnd.ncd.reference": { - source: "iana" - }, - "application/vnd.nearst.inv+json": { - source: "iana", - compressible: true - }, - "application/vnd.nebumind.line": { - source: "iana" - }, - "application/vnd.nervana": { - source: "iana" - }, - "application/vnd.netfpx": { - source: "iana" - }, - "application/vnd.neurolanguage.nlu": { - source: "iana", - extensions: ["nlu"] - }, - "application/vnd.nimn": { - source: "iana" - }, - "application/vnd.nintendo.nitro.rom": { - source: "iana" - }, - "application/vnd.nintendo.snes.rom": { - source: "iana" - }, - "application/vnd.nitf": { - source: "iana", - extensions: ["ntf", "nitf"] - }, - "application/vnd.noblenet-directory": { - source: "iana", - extensions: ["nnd"] - }, - "application/vnd.noblenet-sealer": { - source: "iana", - extensions: ["nns"] - }, - "application/vnd.noblenet-web": { - source: "iana", - extensions: ["nnw"] - }, - "application/vnd.nokia.catalogs": { - source: "iana" - }, - "application/vnd.nokia.conml+wbxml": { - source: "iana" - }, - "application/vnd.nokia.conml+xml": { - source: "iana", - compressible: true - }, - "application/vnd.nokia.iptv.config+xml": { - source: "iana", - compressible: true - }, - "application/vnd.nokia.isds-radio-presets": { - source: "iana" - }, - "application/vnd.nokia.landmark+wbxml": { - source: "iana" - }, - "application/vnd.nokia.landmark+xml": { - source: "iana", - compressible: true - }, - "application/vnd.nokia.landmarkcollection+xml": { - source: "iana", - compressible: true - }, - "application/vnd.nokia.n-gage.ac+xml": { - source: "iana", - compressible: true, - extensions: ["ac"] - }, - "application/vnd.nokia.n-gage.data": { - source: "iana", - extensions: ["ngdat"] - }, - "application/vnd.nokia.n-gage.symbian.install": { - source: "apache", - extensions: ["n-gage"] - }, - "application/vnd.nokia.ncd": { - source: "iana" - }, - "application/vnd.nokia.pcd+wbxml": { - source: "iana" - }, - "application/vnd.nokia.pcd+xml": { - source: "iana", - compressible: true - }, - "application/vnd.nokia.radio-preset": { - source: "iana", - extensions: ["rpst"] - }, - "application/vnd.nokia.radio-presets": { - source: "iana", - extensions: ["rpss"] - }, - "application/vnd.novadigm.edm": { - source: "iana", - extensions: ["edm"] - }, - "application/vnd.novadigm.edx": { - source: "iana", - extensions: ["edx"] - }, - "application/vnd.novadigm.ext": { - source: "iana", - extensions: ["ext"] - }, - "application/vnd.ntt-local.content-share": { - source: "iana" - }, - "application/vnd.ntt-local.file-transfer": { - source: "iana" - }, - "application/vnd.ntt-local.ogw_remote-access": { - source: "iana" - }, - "application/vnd.ntt-local.sip-ta_remote": { - source: "iana" - }, - "application/vnd.ntt-local.sip-ta_tcp_stream": { - source: "iana" - }, - "application/vnd.oai.workflows": { - source: "iana" - }, - "application/vnd.oai.workflows+json": { - source: "iana", - compressible: true - }, - "application/vnd.oai.workflows+yaml": { - source: "iana" - }, - "application/vnd.oasis.opendocument.base": { - source: "iana" - }, - "application/vnd.oasis.opendocument.chart": { - source: "iana", - extensions: ["odc"] - }, - "application/vnd.oasis.opendocument.chart-template": { - source: "iana", - extensions: ["otc"] - }, - "application/vnd.oasis.opendocument.database": { - source: "apache", - extensions: ["odb"] - }, - "application/vnd.oasis.opendocument.formula": { - source: "iana", - extensions: ["odf"] - }, - "application/vnd.oasis.opendocument.formula-template": { - source: "iana", - extensions: ["odft"] - }, - "application/vnd.oasis.opendocument.graphics": { - source: "iana", - compressible: false, - extensions: ["odg"] - }, - "application/vnd.oasis.opendocument.graphics-template": { - source: "iana", - extensions: ["otg"] - }, - "application/vnd.oasis.opendocument.image": { - source: "iana", - extensions: ["odi"] - }, - "application/vnd.oasis.opendocument.image-template": { - source: "iana", - extensions: ["oti"] - }, - "application/vnd.oasis.opendocument.presentation": { - source: "iana", - compressible: false, - extensions: ["odp"] - }, - "application/vnd.oasis.opendocument.presentation-template": { - source: "iana", - extensions: ["otp"] - }, - "application/vnd.oasis.opendocument.spreadsheet": { - source: "iana", - compressible: false, - extensions: ["ods"] - }, - "application/vnd.oasis.opendocument.spreadsheet-template": { - source: "iana", - extensions: ["ots"] - }, - "application/vnd.oasis.opendocument.text": { - source: "iana", - compressible: false, - extensions: ["odt"] - }, - "application/vnd.oasis.opendocument.text-master": { - source: "iana", - extensions: ["odm"] - }, - "application/vnd.oasis.opendocument.text-master-template": { - source: "iana" - }, - "application/vnd.oasis.opendocument.text-template": { - source: "iana", - extensions: ["ott"] - }, - "application/vnd.oasis.opendocument.text-web": { - source: "iana", - extensions: ["oth"] - }, - "application/vnd.obn": { - source: "iana" - }, - "application/vnd.ocf+cbor": { - source: "iana" - }, - "application/vnd.oci.image.manifest.v1+json": { - source: "iana", - compressible: true - }, - "application/vnd.oftn.l10n+json": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.contentaccessdownload+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.contentaccessstreaming+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.cspg-hexbinary": { - source: "iana" - }, - "application/vnd.oipf.dae.svg+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.dae.xhtml+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.mippvcontrolmessage+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.pae.gem": { - source: "iana" - }, - "application/vnd.oipf.spdiscovery+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.spdlist+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.ueprofile+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oipf.userprofile+xml": { - source: "iana", - compressible: true - }, - "application/vnd.olpc-sugar": { - source: "iana", - extensions: ["xo"] - }, - "application/vnd.oma-scws-config": { - source: "iana" - }, - "application/vnd.oma-scws-http-request": { - source: "iana" - }, - "application/vnd.oma-scws-http-response": { - source: "iana" - }, - "application/vnd.oma.bcast.associated-procedure-parameter+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.bcast.drm-trigger+xml": { - source: "apache", - compressible: true - }, - "application/vnd.oma.bcast.imd+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.bcast.ltkm": { - source: "iana" - }, - "application/vnd.oma.bcast.notification+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.bcast.provisioningtrigger": { - source: "iana" - }, - "application/vnd.oma.bcast.sgboot": { - source: "iana" - }, - "application/vnd.oma.bcast.sgdd+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.bcast.sgdu": { - source: "iana" - }, - "application/vnd.oma.bcast.simple-symbol-container": { - source: "iana" - }, - "application/vnd.oma.bcast.smartcard-trigger+xml": { - source: "apache", - compressible: true - }, - "application/vnd.oma.bcast.sprov+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.bcast.stkm": { - source: "iana" - }, - "application/vnd.oma.cab-address-book+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.cab-feature-handler+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.cab-pcc+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.cab-subs-invite+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.cab-user-prefs+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.dcd": { - source: "iana" - }, - "application/vnd.oma.dcdc": { - source: "iana" - }, - "application/vnd.oma.dd2+xml": { - source: "iana", - compressible: true, - extensions: ["dd2"] - }, - "application/vnd.oma.drm.risd+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.group-usage-list+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.lwm2m+cbor": { - source: "iana" - }, - "application/vnd.oma.lwm2m+json": { - source: "iana", - compressible: true - }, - "application/vnd.oma.lwm2m+tlv": { - source: "iana" - }, - "application/vnd.oma.pal+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.poc.detailed-progress-report+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.poc.final-report+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.poc.groups+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.poc.invocation-descriptor+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.poc.optimized-progress-report+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.push": { - source: "iana" - }, - "application/vnd.oma.scidm.messages+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oma.xcap-directory+xml": { - source: "iana", - compressible: true - }, - "application/vnd.omads-email+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/vnd.omads-file+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/vnd.omads-folder+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/vnd.omaloc-supl-init": { - source: "iana" - }, - "application/vnd.onepager": { - source: "iana" - }, - "application/vnd.onepagertamp": { - source: "iana" - }, - "application/vnd.onepagertamx": { - source: "iana" - }, - "application/vnd.onepagertat": { - source: "iana" - }, - "application/vnd.onepagertatp": { - source: "iana" - }, - "application/vnd.onepagertatx": { - source: "iana" - }, - "application/vnd.onvif.metadata": { - source: "iana" - }, - "application/vnd.openblox.game+xml": { - source: "iana", - compressible: true, - extensions: ["obgx"] - }, - "application/vnd.openblox.game-binary": { - source: "iana" - }, - "application/vnd.openeye.oeb": { - source: "iana" - }, - "application/vnd.openofficeorg.extension": { - source: "apache", - extensions: ["oxt"] - }, - "application/vnd.openstreetmap.data+xml": { - source: "iana", - compressible: true, - extensions: ["osm"] - }, - "application/vnd.opentimestamps.ots": { - source: "iana" - }, - "application/vnd.openvpi.dspx+json": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.custom-properties+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.customxmlproperties+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.drawing+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.extended-properties+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.comments+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.presentation": { - source: "iana", - compressible: false, - extensions: ["pptx"] - }, - "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.presprops+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.slide": { - source: "iana", - extensions: ["sldx"] - }, - "application/vnd.openxmlformats-officedocument.presentationml.slide+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.slideshow": { - source: "iana", - extensions: ["ppsx"] - }, - "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.tags+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.template": { - source: "iana", - extensions: ["potx"] - }, - "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": { - source: "iana", - compressible: false, - extensions: ["xlsx"] - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.template": { - source: "iana", - extensions: ["xltx"] - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.theme+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.themeoverride+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.vmldrawing": { - source: "iana" - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.document": { - source: "iana", - compressible: false, - extensions: ["docx"] - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.template": { - source: "iana", - extensions: ["dotx"] - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-package.core-properties+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml": { - source: "iana", - compressible: true - }, - "application/vnd.openxmlformats-package.relationships+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oracle.resource+json": { - source: "iana", - compressible: true - }, - "application/vnd.orange.indata": { - source: "iana" - }, - "application/vnd.osa.netdeploy": { - source: "iana" - }, - "application/vnd.osgeo.mapguide.package": { - source: "iana", - extensions: ["mgp"] - }, - "application/vnd.osgi.bundle": { - source: "iana" - }, - "application/vnd.osgi.dp": { - source: "iana", - extensions: ["dp"] - }, - "application/vnd.osgi.subsystem": { - source: "iana", - extensions: ["esa"] - }, - "application/vnd.otps.ct-kip+xml": { - source: "iana", - compressible: true - }, - "application/vnd.oxli.countgraph": { - source: "iana" - }, - "application/vnd.pagerduty+json": { - source: "iana", - compressible: true - }, - "application/vnd.palm": { - source: "iana", - extensions: ["pdb", "pqa", "oprc"] - }, - "application/vnd.panoply": { - source: "iana" - }, - "application/vnd.paos.xml": { - source: "iana" - }, - "application/vnd.patentdive": { - source: "iana" - }, - "application/vnd.patientecommsdoc": { - source: "iana" - }, - "application/vnd.pawaafile": { - source: "iana", - extensions: ["paw"] - }, - "application/vnd.pcos": { - source: "iana" - }, - "application/vnd.pg.format": { - source: "iana", - extensions: ["str"] - }, - "application/vnd.pg.osasli": { - source: "iana", - extensions: ["ei6"] - }, - "application/vnd.piaccess.application-licence": { - source: "iana" - }, - "application/vnd.picsel": { - source: "iana", - extensions: ["efif"] - }, - "application/vnd.pmi.widget": { - source: "iana", - extensions: ["wg"] - }, - "application/vnd.poc.group-advertisement+xml": { - source: "iana", - compressible: true - }, - "application/vnd.pocketlearn": { - source: "iana", - extensions: ["plf"] - }, - "application/vnd.powerbuilder6": { - source: "iana", - extensions: ["pbd"] - }, - "application/vnd.powerbuilder6-s": { - source: "iana" - }, - "application/vnd.powerbuilder7": { - source: "iana" - }, - "application/vnd.powerbuilder7-s": { - source: "iana" - }, - "application/vnd.powerbuilder75": { - source: "iana" - }, - "application/vnd.powerbuilder75-s": { - source: "iana" - }, - "application/vnd.preminet": { - source: "iana" - }, - "application/vnd.previewsystems.box": { - source: "iana", - extensions: ["box"] - }, - "application/vnd.procrate.brushset": { - extensions: ["brushset"] - }, - "application/vnd.procreate.brush": { - extensions: ["brush"] - }, - "application/vnd.procreate.dream": { - extensions: ["drm"] - }, - "application/vnd.proteus.magazine": { - source: "iana", - extensions: ["mgz"] - }, - "application/vnd.psfs": { - source: "iana" - }, - "application/vnd.pt.mundusmundi": { - source: "iana" - }, - "application/vnd.publishare-delta-tree": { - source: "iana", - extensions: ["qps"] - }, - "application/vnd.pvi.ptid1": { - source: "iana", - extensions: ["ptid"] - }, - "application/vnd.pwg-multiplexed": { - source: "iana" - }, - "application/vnd.pwg-xhtml-print+xml": { - source: "iana", - compressible: true, - extensions: ["xhtm"] - }, - "application/vnd.qualcomm.brew-app-res": { - source: "iana" - }, - "application/vnd.quarantainenet": { - source: "iana" - }, - "application/vnd.quark.quarkxpress": { - source: "iana", - extensions: ["qxd", "qxt", "qwd", "qwt", "qxl", "qxb"] - }, - "application/vnd.quobject-quoxdocument": { - source: "iana" - }, - "application/vnd.radisys.moml+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-audit+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-audit-conf+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-audit-conn+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-audit-dialog+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-audit-stream+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-conf+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-dialog+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-dialog-base+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-dialog-fax-detect+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-dialog-fax-sendrecv+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-dialog-group+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-dialog-speech+xml": { - source: "iana", - compressible: true - }, - "application/vnd.radisys.msml-dialog-transform+xml": { - source: "iana", - compressible: true - }, - "application/vnd.rainstor.data": { - source: "iana" - }, - "application/vnd.rapid": { - source: "iana" - }, - "application/vnd.rar": { - source: "iana", - extensions: ["rar"] - }, - "application/vnd.realvnc.bed": { - source: "iana", - extensions: ["bed"] - }, - "application/vnd.recordare.musicxml": { - source: "iana", - extensions: ["mxl"] - }, - "application/vnd.recordare.musicxml+xml": { - source: "iana", - compressible: true, - extensions: ["musicxml"] - }, - "application/vnd.relpipe": { - source: "iana" - }, - "application/vnd.renlearn.rlprint": { - source: "iana" - }, - "application/vnd.resilient.logic": { - source: "iana" - }, - "application/vnd.restful+json": { - source: "iana", - compressible: true - }, - "application/vnd.rig.cryptonote": { - source: "iana", - extensions: ["cryptonote"] - }, - "application/vnd.rim.cod": { - source: "apache", - extensions: ["cod"] - }, - "application/vnd.rn-realmedia": { - source: "apache", - extensions: ["rm"] - }, - "application/vnd.rn-realmedia-vbr": { - source: "apache", - extensions: ["rmvb"] - }, - "application/vnd.route66.link66+xml": { - source: "iana", - compressible: true, - extensions: ["link66"] - }, - "application/vnd.rs-274x": { - source: "iana" - }, - "application/vnd.ruckus.download": { - source: "iana" - }, - "application/vnd.s3sms": { - source: "iana" - }, - "application/vnd.sailingtracker.track": { - source: "iana", - extensions: ["st"] - }, - "application/vnd.sar": { - source: "iana" - }, - "application/vnd.sbm.cid": { - source: "iana" - }, - "application/vnd.sbm.mid2": { - source: "iana" - }, - "application/vnd.scribus": { - source: "iana" - }, - "application/vnd.sealed.3df": { - source: "iana" - }, - "application/vnd.sealed.csf": { - source: "iana" - }, - "application/vnd.sealed.doc": { - source: "iana" - }, - "application/vnd.sealed.eml": { - source: "iana" - }, - "application/vnd.sealed.mht": { - source: "iana" - }, - "application/vnd.sealed.net": { - source: "iana" - }, - "application/vnd.sealed.ppt": { - source: "iana" - }, - "application/vnd.sealed.tiff": { - source: "iana" - }, - "application/vnd.sealed.xls": { - source: "iana" - }, - "application/vnd.sealedmedia.softseal.html": { - source: "iana" - }, - "application/vnd.sealedmedia.softseal.pdf": { - source: "iana" - }, - "application/vnd.seemail": { - source: "iana", - extensions: ["see"] - }, - "application/vnd.seis+json": { - source: "iana", - compressible: true - }, - "application/vnd.sema": { - source: "iana", - extensions: ["sema"] - }, - "application/vnd.semd": { - source: "iana", - extensions: ["semd"] - }, - "application/vnd.semf": { - source: "iana", - extensions: ["semf"] - }, - "application/vnd.shade-save-file": { - source: "iana" - }, - "application/vnd.shana.informed.formdata": { - source: "iana", - extensions: ["ifm"] - }, - "application/vnd.shana.informed.formtemplate": { - source: "iana", - extensions: ["itp"] - }, - "application/vnd.shana.informed.interchange": { - source: "iana", - extensions: ["iif"] - }, - "application/vnd.shana.informed.package": { - source: "iana", - extensions: ["ipk"] - }, - "application/vnd.shootproof+json": { - source: "iana", - compressible: true - }, - "application/vnd.shopkick+json": { - source: "iana", - compressible: true - }, - "application/vnd.shp": { - source: "iana" - }, - "application/vnd.shx": { - source: "iana" - }, - "application/vnd.sigrok.session": { - source: "iana" - }, - "application/vnd.simtech-mindmapper": { - source: "iana", - extensions: ["twd", "twds"] - }, - "application/vnd.siren+json": { - source: "iana", - compressible: true - }, - "application/vnd.sketchometry": { - source: "iana" - }, - "application/vnd.smaf": { - source: "iana", - extensions: ["mmf"] - }, - "application/vnd.smart.notebook": { - source: "iana" - }, - "application/vnd.smart.teacher": { - source: "iana", - extensions: ["teacher"] - }, - "application/vnd.smintio.portals.archive": { - source: "iana" - }, - "application/vnd.snesdev-page-table": { - source: "iana" - }, - "application/vnd.software602.filler.form+xml": { - source: "iana", - compressible: true, - extensions: ["fo"] - }, - "application/vnd.software602.filler.form-xml-zip": { - source: "iana" - }, - "application/vnd.solent.sdkm+xml": { - source: "iana", - compressible: true, - extensions: ["sdkm", "sdkd"] - }, - "application/vnd.spotfire.dxp": { - source: "iana", - extensions: ["dxp"] - }, - "application/vnd.spotfire.sfs": { - source: "iana", - extensions: ["sfs"] - }, - "application/vnd.sqlite3": { - source: "iana" - }, - "application/vnd.sss-cod": { - source: "iana" - }, - "application/vnd.sss-dtf": { - source: "iana" - }, - "application/vnd.sss-ntf": { - source: "iana" - }, - "application/vnd.stardivision.calc": { - source: "apache", - extensions: ["sdc"] - }, - "application/vnd.stardivision.draw": { - source: "apache", - extensions: ["sda"] - }, - "application/vnd.stardivision.impress": { - source: "apache", - extensions: ["sdd"] - }, - "application/vnd.stardivision.math": { - source: "apache", - extensions: ["smf"] - }, - "application/vnd.stardivision.writer": { - source: "apache", - extensions: ["sdw", "vor"] - }, - "application/vnd.stardivision.writer-global": { - source: "apache", - extensions: ["sgl"] - }, - "application/vnd.stepmania.package": { - source: "iana", - extensions: ["smzip"] - }, - "application/vnd.stepmania.stepchart": { - source: "iana", - extensions: ["sm"] - }, - "application/vnd.street-stream": { - source: "iana" - }, - "application/vnd.sun.wadl+xml": { - source: "iana", - compressible: true, - extensions: ["wadl"] - }, - "application/vnd.sun.xml.calc": { - source: "apache", - extensions: ["sxc"] - }, - "application/vnd.sun.xml.calc.template": { - source: "apache", - extensions: ["stc"] - }, - "application/vnd.sun.xml.draw": { - source: "apache", - extensions: ["sxd"] - }, - "application/vnd.sun.xml.draw.template": { - source: "apache", - extensions: ["std"] - }, - "application/vnd.sun.xml.impress": { - source: "apache", - extensions: ["sxi"] - }, - "application/vnd.sun.xml.impress.template": { - source: "apache", - extensions: ["sti"] - }, - "application/vnd.sun.xml.math": { - source: "apache", - extensions: ["sxm"] - }, - "application/vnd.sun.xml.writer": { - source: "apache", - extensions: ["sxw"] - }, - "application/vnd.sun.xml.writer.global": { - source: "apache", - extensions: ["sxg"] - }, - "application/vnd.sun.xml.writer.template": { - source: "apache", - extensions: ["stw"] - }, - "application/vnd.sus-calendar": { - source: "iana", - extensions: ["sus", "susp"] - }, - "application/vnd.svd": { - source: "iana", - extensions: ["svd"] - }, - "application/vnd.swiftview-ics": { - source: "iana" - }, - "application/vnd.sybyl.mol2": { - source: "iana" - }, - "application/vnd.sycle+xml": { - source: "iana", - compressible: true - }, - "application/vnd.syft+json": { - source: "iana", - compressible: true - }, - "application/vnd.symbian.install": { - source: "apache", - extensions: ["sis", "sisx"] - }, - "application/vnd.syncml+xml": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["xsm"] - }, - "application/vnd.syncml.dm+wbxml": { - source: "iana", - charset: "UTF-8", - extensions: ["bdm"] - }, - "application/vnd.syncml.dm+xml": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["xdm"] - }, - "application/vnd.syncml.dm.notification": { - source: "iana" - }, - "application/vnd.syncml.dmddf+wbxml": { - source: "iana" - }, - "application/vnd.syncml.dmddf+xml": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["ddf"] - }, - "application/vnd.syncml.dmtnds+wbxml": { - source: "iana" - }, - "application/vnd.syncml.dmtnds+xml": { - source: "iana", - charset: "UTF-8", - compressible: true - }, - "application/vnd.syncml.ds.notification": { - source: "iana" - }, - "application/vnd.tableschema+json": { - source: "iana", - compressible: true - }, - "application/vnd.tao.intent-module-archive": { - source: "iana", - extensions: ["tao"] - }, - "application/vnd.tcpdump.pcap": { - source: "iana", - extensions: ["pcap", "cap", "dmp"] - }, - "application/vnd.think-cell.ppttc+json": { - source: "iana", - compressible: true - }, - "application/vnd.tmd.mediaflex.api+xml": { - source: "iana", - compressible: true - }, - "application/vnd.tml": { - source: "iana" - }, - "application/vnd.tmobile-livetv": { - source: "iana", - extensions: ["tmo"] - }, - "application/vnd.tri.onesource": { - source: "iana" - }, - "application/vnd.trid.tpt": { - source: "iana", - extensions: ["tpt"] - }, - "application/vnd.triscape.mxs": { - source: "iana", - extensions: ["mxs"] - }, - "application/vnd.trueapp": { - source: "iana", - extensions: ["tra"] - }, - "application/vnd.truedoc": { - source: "iana" - }, - "application/vnd.ubisoft.webplayer": { - source: "iana" - }, - "application/vnd.ufdl": { - source: "iana", - extensions: ["ufd", "ufdl"] - }, - "application/vnd.uic.osdm+json": { - source: "iana", - compressible: true - }, - "application/vnd.uiq.theme": { - source: "iana", - extensions: ["utz"] - }, - "application/vnd.umajin": { - source: "iana", - extensions: ["umj"] - }, - "application/vnd.unity": { - source: "iana", - extensions: ["unityweb"] - }, - "application/vnd.uoml+xml": { - source: "iana", - compressible: true, - extensions: ["uoml", "uo"] - }, - "application/vnd.uplanet.alert": { - source: "iana" - }, - "application/vnd.uplanet.alert-wbxml": { - source: "iana" - }, - "application/vnd.uplanet.bearer-choice": { - source: "iana" - }, - "application/vnd.uplanet.bearer-choice-wbxml": { - source: "iana" - }, - "application/vnd.uplanet.cacheop": { - source: "iana" - }, - "application/vnd.uplanet.cacheop-wbxml": { - source: "iana" - }, - "application/vnd.uplanet.channel": { - source: "iana" - }, - "application/vnd.uplanet.channel-wbxml": { - source: "iana" - }, - "application/vnd.uplanet.list": { - source: "iana" - }, - "application/vnd.uplanet.list-wbxml": { - source: "iana" - }, - "application/vnd.uplanet.listcmd": { - source: "iana" - }, - "application/vnd.uplanet.listcmd-wbxml": { - source: "iana" - }, - "application/vnd.uplanet.signal": { - source: "iana" - }, - "application/vnd.uri-map": { - source: "iana" - }, - "application/vnd.valve.source.material": { - source: "iana" - }, - "application/vnd.vcx": { - source: "iana", - extensions: ["vcx"] - }, - "application/vnd.vd-study": { - source: "iana" - }, - "application/vnd.vectorworks": { - source: "iana" - }, - "application/vnd.vel+json": { - source: "iana", - compressible: true - }, - "application/vnd.veraison.tsm-report+cbor": { - source: "iana" - }, - "application/vnd.veraison.tsm-report+json": { - source: "iana", - compressible: true - }, - "application/vnd.verimatrix.vcas": { - source: "iana" - }, - "application/vnd.veritone.aion+json": { - source: "iana", - compressible: true - }, - "application/vnd.veryant.thin": { - source: "iana" - }, - "application/vnd.ves.encrypted": { - source: "iana" - }, - "application/vnd.vidsoft.vidconference": { - source: "iana" - }, - "application/vnd.visio": { - source: "iana", - extensions: ["vsd", "vst", "vss", "vsw", "vsdx", "vtx"] - }, - "application/vnd.visionary": { - source: "iana", - extensions: ["vis"] - }, - "application/vnd.vividence.scriptfile": { - source: "iana" - }, - "application/vnd.vocalshaper.vsp4": { - source: "iana" - }, - "application/vnd.vsf": { - source: "iana", - extensions: ["vsf"] - }, - "application/vnd.wap.sic": { - source: "iana" - }, - "application/vnd.wap.slc": { - source: "iana" - }, - "application/vnd.wap.wbxml": { - source: "iana", - charset: "UTF-8", - extensions: ["wbxml"] - }, - "application/vnd.wap.wmlc": { - source: "iana", - extensions: ["wmlc"] - }, - "application/vnd.wap.wmlscriptc": { - source: "iana", - extensions: ["wmlsc"] - }, - "application/vnd.wasmflow.wafl": { - source: "iana" - }, - "application/vnd.webturbo": { - source: "iana", - extensions: ["wtb"] - }, - "application/vnd.wfa.dpp": { - source: "iana" - }, - "application/vnd.wfa.p2p": { - source: "iana" - }, - "application/vnd.wfa.wsc": { - source: "iana" - }, - "application/vnd.windows.devicepairing": { - source: "iana" - }, - "application/vnd.wmc": { - source: "iana" - }, - "application/vnd.wmf.bootstrap": { - source: "iana" - }, - "application/vnd.wolfram.mathematica": { - source: "iana" - }, - "application/vnd.wolfram.mathematica.package": { - source: "iana" - }, - "application/vnd.wolfram.player": { - source: "iana", - extensions: ["nbp"] - }, - "application/vnd.wordlift": { - source: "iana" - }, - "application/vnd.wordperfect": { - source: "iana", - extensions: ["wpd"] - }, - "application/vnd.wqd": { - source: "iana", - extensions: ["wqd"] - }, - "application/vnd.wrq-hp3000-labelled": { - source: "iana" - }, - "application/vnd.wt.stf": { - source: "iana", - extensions: ["stf"] - }, - "application/vnd.wv.csp+wbxml": { - source: "iana" - }, - "application/vnd.wv.csp+xml": { - source: "iana", - compressible: true - }, - "application/vnd.wv.ssp+xml": { - source: "iana", - compressible: true - }, - "application/vnd.xacml+json": { - source: "iana", - compressible: true - }, - "application/vnd.xara": { - source: "iana", - extensions: ["xar"] - }, - "application/vnd.xarin.cpj": { - source: "iana" - }, - "application/vnd.xecrets-encrypted": { - source: "iana" - }, - "application/vnd.xfdl": { - source: "iana", - extensions: ["xfdl"] - }, - "application/vnd.xfdl.webform": { - source: "iana" - }, - "application/vnd.xmi+xml": { - source: "iana", - compressible: true - }, - "application/vnd.xmpie.cpkg": { - source: "iana" - }, - "application/vnd.xmpie.dpkg": { - source: "iana" - }, - "application/vnd.xmpie.plan": { - source: "iana" - }, - "application/vnd.xmpie.ppkg": { - source: "iana" - }, - "application/vnd.xmpie.xlim": { - source: "iana" - }, - "application/vnd.yamaha.hv-dic": { - source: "iana", - extensions: ["hvd"] - }, - "application/vnd.yamaha.hv-script": { - source: "iana", - extensions: ["hvs"] - }, - "application/vnd.yamaha.hv-voice": { - source: "iana", - extensions: ["hvp"] - }, - "application/vnd.yamaha.openscoreformat": { - source: "iana", - extensions: ["osf"] - }, - "application/vnd.yamaha.openscoreformat.osfpvg+xml": { - source: "iana", - compressible: true, - extensions: ["osfpvg"] - }, - "application/vnd.yamaha.remote-setup": { - source: "iana" - }, - "application/vnd.yamaha.smaf-audio": { - source: "iana", - extensions: ["saf"] - }, - "application/vnd.yamaha.smaf-phrase": { - source: "iana", - extensions: ["spf"] - }, - "application/vnd.yamaha.through-ngn": { - source: "iana" - }, - "application/vnd.yamaha.tunnel-udpencap": { - source: "iana" - }, - "application/vnd.yaoweme": { - source: "iana" - }, - "application/vnd.yellowriver-custom-menu": { - source: "iana", - extensions: ["cmp"] - }, - "application/vnd.zul": { - source: "iana", - extensions: ["zir", "zirz"] - }, - "application/vnd.zzazz.deck+xml": { - source: "iana", - compressible: true, - extensions: ["zaz"] - }, - "application/voicexml+xml": { - source: "iana", - compressible: true, - extensions: ["vxml"] - }, - "application/voucher-cms+json": { - source: "iana", - compressible: true - }, - "application/voucher-jws+json": { - source: "iana", - compressible: true - }, - "application/vp": { - source: "iana" - }, - "application/vp+cose": { - source: "iana" - }, - "application/vp+jwt": { - source: "iana" - }, - "application/vq-rtcpxr": { - source: "iana" - }, - "application/wasm": { - source: "iana", - compressible: true, - extensions: ["wasm"] - }, - "application/watcherinfo+xml": { - source: "iana", - compressible: true, - extensions: ["wif"] - }, - "application/webpush-options+json": { - source: "iana", - compressible: true - }, - "application/whoispp-query": { - source: "iana" - }, - "application/whoispp-response": { - source: "iana" - }, - "application/widget": { - source: "iana", - extensions: ["wgt"] - }, - "application/winhlp": { - source: "apache", - extensions: ["hlp"] - }, - "application/wita": { - source: "iana" - }, - "application/wordperfect5.1": { - source: "iana" - }, - "application/wsdl+xml": { - source: "iana", - compressible: true, - extensions: ["wsdl"] - }, - "application/wspolicy+xml": { - source: "iana", - compressible: true, - extensions: ["wspolicy"] - }, - "application/x-7z-compressed": { - source: "apache", - compressible: false, - extensions: ["7z"] - }, - "application/x-abiword": { - source: "apache", - extensions: ["abw"] - }, - "application/x-ace-compressed": { - source: "apache", - extensions: ["ace"] - }, - "application/x-amf": { - source: "apache" - }, - "application/x-apple-diskimage": { - source: "apache", - extensions: ["dmg"] - }, - "application/x-arj": { - compressible: false, - extensions: ["arj"] - }, - "application/x-authorware-bin": { - source: "apache", - extensions: ["aab", "x32", "u32", "vox"] - }, - "application/x-authorware-map": { - source: "apache", - extensions: ["aam"] - }, - "application/x-authorware-seg": { - source: "apache", - extensions: ["aas"] - }, - "application/x-bcpio": { - source: "apache", - extensions: ["bcpio"] - }, - "application/x-bdoc": { - compressible: false, - extensions: ["bdoc"] - }, - "application/x-bittorrent": { - source: "apache", - extensions: ["torrent"] - }, - "application/x-blender": { - extensions: ["blend"] - }, - "application/x-blorb": { - source: "apache", - extensions: ["blb", "blorb"] - }, - "application/x-bzip": { - source: "apache", - compressible: false, - extensions: ["bz"] - }, - "application/x-bzip2": { - source: "apache", - compressible: false, - extensions: ["bz2", "boz"] - }, - "application/x-cbr": { - source: "apache", - extensions: ["cbr", "cba", "cbt", "cbz", "cb7"] - }, - "application/x-cdlink": { - source: "apache", - extensions: ["vcd"] - }, - "application/x-cfs-compressed": { - source: "apache", - extensions: ["cfs"] - }, - "application/x-chat": { - source: "apache", - extensions: ["chat"] - }, - "application/x-chess-pgn": { - source: "apache", - extensions: ["pgn"] - }, - "application/x-chrome-extension": { - extensions: ["crx"] - }, - "application/x-cocoa": { - source: "nginx", - extensions: ["cco"] - }, - "application/x-compress": { - source: "apache" - }, - "application/x-compressed": { - extensions: ["rar"] - }, - "application/x-conference": { - source: "apache", - extensions: ["nsc"] - }, - "application/x-cpio": { - source: "apache", - extensions: ["cpio"] - }, - "application/x-csh": { - source: "apache", - extensions: ["csh"] - }, - "application/x-deb": { - compressible: false - }, - "application/x-debian-package": { - source: "apache", - extensions: ["deb", "udeb"] - }, - "application/x-dgc-compressed": { - source: "apache", - extensions: ["dgc"] - }, - "application/x-director": { - source: "apache", - extensions: ["dir", "dcr", "dxr", "cst", "cct", "cxt", "w3d", "fgd", "swa"] - }, - "application/x-doom": { - source: "apache", - extensions: ["wad"] - }, - "application/x-dtbncx+xml": { - source: "apache", - compressible: true, - extensions: ["ncx"] - }, - "application/x-dtbook+xml": { - source: "apache", - compressible: true, - extensions: ["dtb"] - }, - "application/x-dtbresource+xml": { - source: "apache", - compressible: true, - extensions: ["res"] - }, - "application/x-dvi": { - source: "apache", - compressible: false, - extensions: ["dvi"] - }, - "application/x-envoy": { - source: "apache", - extensions: ["evy"] - }, - "application/x-eva": { - source: "apache", - extensions: ["eva"] - }, - "application/x-font-bdf": { - source: "apache", - extensions: ["bdf"] - }, - "application/x-font-dos": { - source: "apache" - }, - "application/x-font-framemaker": { - source: "apache" - }, - "application/x-font-ghostscript": { - source: "apache", - extensions: ["gsf"] - }, - "application/x-font-libgrx": { - source: "apache" - }, - "application/x-font-linux-psf": { - source: "apache", - extensions: ["psf"] - }, - "application/x-font-pcf": { - source: "apache", - extensions: ["pcf"] - }, - "application/x-font-snf": { - source: "apache", - extensions: ["snf"] - }, - "application/x-font-speedo": { - source: "apache" - }, - "application/x-font-sunos-news": { - source: "apache" - }, - "application/x-font-type1": { - source: "apache", - extensions: ["pfa", "pfb", "pfm", "afm"] - }, - "application/x-font-vfont": { - source: "apache" - }, - "application/x-freearc": { - source: "apache", - extensions: ["arc"] - }, - "application/x-futuresplash": { - source: "apache", - extensions: ["spl"] - }, - "application/x-gca-compressed": { - source: "apache", - extensions: ["gca"] - }, - "application/x-glulx": { - source: "apache", - extensions: ["ulx"] - }, - "application/x-gnumeric": { - source: "apache", - extensions: ["gnumeric"] - }, - "application/x-gramps-xml": { - source: "apache", - extensions: ["gramps"] - }, - "application/x-gtar": { - source: "apache", - extensions: ["gtar"] - }, - "application/x-gzip": { - source: "apache" - }, - "application/x-hdf": { - source: "apache", - extensions: ["hdf"] - }, - "application/x-httpd-php": { - compressible: true, - extensions: ["php"] - }, - "application/x-install-instructions": { - source: "apache", - extensions: ["install"] - }, - "application/x-ipynb+json": { - compressible: true, - extensions: ["ipynb"] - }, - "application/x-iso9660-image": { - source: "apache", - extensions: ["iso"] - }, - "application/x-iwork-keynote-sffkey": { - extensions: ["key"] - }, - "application/x-iwork-numbers-sffnumbers": { - extensions: ["numbers"] - }, - "application/x-iwork-pages-sffpages": { - extensions: ["pages"] - }, - "application/x-java-archive-diff": { - source: "nginx", - extensions: ["jardiff"] - }, - "application/x-java-jnlp-file": { - source: "apache", - compressible: false, - extensions: ["jnlp"] - }, - "application/x-javascript": { - compressible: true - }, - "application/x-keepass2": { - extensions: ["kdbx"] - }, - "application/x-latex": { - source: "apache", - compressible: false, - extensions: ["latex"] - }, - "application/x-lua-bytecode": { - extensions: ["luac"] - }, - "application/x-lzh-compressed": { - source: "apache", - extensions: ["lzh", "lha"] - }, - "application/x-makeself": { - source: "nginx", - extensions: ["run"] - }, - "application/x-mie": { - source: "apache", - extensions: ["mie"] - }, - "application/x-mobipocket-ebook": { - source: "apache", - extensions: ["prc", "mobi"] - }, - "application/x-mpegurl": { - compressible: false - }, - "application/x-ms-application": { - source: "apache", - extensions: ["application"] - }, - "application/x-ms-shortcut": { - source: "apache", - extensions: ["lnk"] - }, - "application/x-ms-wmd": { - source: "apache", - extensions: ["wmd"] - }, - "application/x-ms-wmz": { - source: "apache", - extensions: ["wmz"] - }, - "application/x-ms-xbap": { - source: "apache", - extensions: ["xbap"] - }, - "application/x-msaccess": { - source: "apache", - extensions: ["mdb"] - }, - "application/x-msbinder": { - source: "apache", - extensions: ["obd"] - }, - "application/x-mscardfile": { - source: "apache", - extensions: ["crd"] - }, - "application/x-msclip": { - source: "apache", - extensions: ["clp"] - }, - "application/x-msdos-program": { - extensions: ["exe"] - }, - "application/x-msdownload": { - source: "apache", - extensions: ["exe", "dll", "com", "bat", "msi"] - }, - "application/x-msmediaview": { - source: "apache", - extensions: ["mvb", "m13", "m14"] - }, - "application/x-msmetafile": { - source: "apache", - extensions: ["wmf", "wmz", "emf", "emz"] - }, - "application/x-msmoney": { - source: "apache", - extensions: ["mny"] - }, - "application/x-mspublisher": { - source: "apache", - extensions: ["pub"] - }, - "application/x-msschedule": { - source: "apache", - extensions: ["scd"] - }, - "application/x-msterminal": { - source: "apache", - extensions: ["trm"] - }, - "application/x-mswrite": { - source: "apache", - extensions: ["wri"] - }, - "application/x-netcdf": { - source: "apache", - extensions: ["nc", "cdf"] - }, - "application/x-ns-proxy-autoconfig": { - compressible: true, - extensions: ["pac"] - }, - "application/x-nzb": { - source: "apache", - extensions: ["nzb"] - }, - "application/x-perl": { - source: "nginx", - extensions: ["pl", "pm"] - }, - "application/x-pilot": { - source: "nginx", - extensions: ["prc", "pdb"] - }, - "application/x-pkcs12": { - source: "apache", - compressible: false, - extensions: ["p12", "pfx"] - }, - "application/x-pkcs7-certificates": { - source: "apache", - extensions: ["p7b", "spc"] - }, - "application/x-pkcs7-certreqresp": { - source: "apache", - extensions: ["p7r"] - }, - "application/x-pki-message": { - source: "iana" - }, - "application/x-rar-compressed": { - source: "apache", - compressible: false, - extensions: ["rar"] - }, - "application/x-redhat-package-manager": { - source: "nginx", - extensions: ["rpm"] - }, - "application/x-research-info-systems": { - source: "apache", - extensions: ["ris"] - }, - "application/x-sea": { - source: "nginx", - extensions: ["sea"] - }, - "application/x-sh": { - source: "apache", - compressible: true, - extensions: ["sh"] - }, - "application/x-shar": { - source: "apache", - extensions: ["shar"] - }, - "application/x-shockwave-flash": { - source: "apache", - compressible: false, - extensions: ["swf"] - }, - "application/x-silverlight-app": { - source: "apache", - extensions: ["xap"] - }, - "application/x-sql": { - source: "apache", - extensions: ["sql"] - }, - "application/x-stuffit": { - source: "apache", - compressible: false, - extensions: ["sit"] - }, - "application/x-stuffitx": { - source: "apache", - extensions: ["sitx"] - }, - "application/x-subrip": { - source: "apache", - extensions: ["srt"] - }, - "application/x-sv4cpio": { - source: "apache", - extensions: ["sv4cpio"] - }, - "application/x-sv4crc": { - source: "apache", - extensions: ["sv4crc"] - }, - "application/x-t3vm-image": { - source: "apache", - extensions: ["t3"] - }, - "application/x-tads": { - source: "apache", - extensions: ["gam"] - }, - "application/x-tar": { - source: "apache", - compressible: true, - extensions: ["tar"] - }, - "application/x-tcl": { - source: "apache", - extensions: ["tcl", "tk"] - }, - "application/x-tex": { - source: "apache", - extensions: ["tex"] - }, - "application/x-tex-tfm": { - source: "apache", - extensions: ["tfm"] - }, - "application/x-texinfo": { - source: "apache", - extensions: ["texinfo", "texi"] - }, - "application/x-tgif": { - source: "apache", - extensions: ["obj"] - }, - "application/x-ustar": { - source: "apache", - extensions: ["ustar"] - }, - "application/x-virtualbox-hdd": { - compressible: true, - extensions: ["hdd"] - }, - "application/x-virtualbox-ova": { - compressible: true, - extensions: ["ova"] - }, - "application/x-virtualbox-ovf": { - compressible: true, - extensions: ["ovf"] - }, - "application/x-virtualbox-vbox": { - compressible: true, - extensions: ["vbox"] - }, - "application/x-virtualbox-vbox-extpack": { - compressible: false, - extensions: ["vbox-extpack"] - }, - "application/x-virtualbox-vdi": { - compressible: true, - extensions: ["vdi"] - }, - "application/x-virtualbox-vhd": { - compressible: true, - extensions: ["vhd"] - }, - "application/x-virtualbox-vmdk": { - compressible: true, - extensions: ["vmdk"] - }, - "application/x-wais-source": { - source: "apache", - extensions: ["src"] - }, - "application/x-web-app-manifest+json": { - compressible: true, - extensions: ["webapp"] - }, - "application/x-www-form-urlencoded": { - source: "iana", - compressible: true - }, - "application/x-x509-ca-cert": { - source: "iana", - extensions: ["der", "crt", "pem"] - }, - "application/x-x509-ca-ra-cert": { - source: "iana" - }, - "application/x-x509-next-ca-cert": { - source: "iana" - }, - "application/x-xfig": { - source: "apache", - extensions: ["fig"] - }, - "application/x-xliff+xml": { - source: "apache", - compressible: true, - extensions: ["xlf"] - }, - "application/x-xpinstall": { - source: "apache", - compressible: false, - extensions: ["xpi"] - }, - "application/x-xz": { - source: "apache", - extensions: ["xz"] - }, - "application/x-zip-compressed": { - extensions: ["zip"] - }, - "application/x-zmachine": { - source: "apache", - extensions: ["z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8"] - }, - "application/x400-bp": { - source: "iana" - }, - "application/xacml+xml": { - source: "iana", - compressible: true - }, - "application/xaml+xml": { - source: "apache", - compressible: true, - extensions: ["xaml"] - }, - "application/xcap-att+xml": { - source: "iana", - compressible: true, - extensions: ["xav"] - }, - "application/xcap-caps+xml": { - source: "iana", - compressible: true, - extensions: ["xca"] - }, - "application/xcap-diff+xml": { - source: "iana", - compressible: true, - extensions: ["xdf"] - }, - "application/xcap-el+xml": { - source: "iana", - compressible: true, - extensions: ["xel"] - }, - "application/xcap-error+xml": { - source: "iana", - compressible: true - }, - "application/xcap-ns+xml": { - source: "iana", - compressible: true, - extensions: ["xns"] - }, - "application/xcon-conference-info+xml": { - source: "iana", - compressible: true - }, - "application/xcon-conference-info-diff+xml": { - source: "iana", - compressible: true - }, - "application/xenc+xml": { - source: "iana", - compressible: true, - extensions: ["xenc"] - }, - "application/xfdf": { - source: "iana", - extensions: ["xfdf"] - }, - "application/xhtml+xml": { - source: "iana", - compressible: true, - extensions: ["xhtml", "xht"] - }, - "application/xhtml-voice+xml": { - source: "apache", - compressible: true - }, - "application/xliff+xml": { - source: "iana", - compressible: true, - extensions: ["xlf"] - }, - "application/xml": { - source: "iana", - compressible: true, - extensions: ["xml", "xsl", "xsd", "rng"] - }, - "application/xml-dtd": { - source: "iana", - compressible: true, - extensions: ["dtd"] - }, - "application/xml-external-parsed-entity": { - source: "iana" - }, - "application/xml-patch+xml": { - source: "iana", - compressible: true - }, - "application/xmpp+xml": { - source: "iana", - compressible: true - }, - "application/xop+xml": { - source: "iana", - compressible: true, - extensions: ["xop"] - }, - "application/xproc+xml": { - source: "apache", - compressible: true, - extensions: ["xpl"] - }, - "application/xslt+xml": { - source: "iana", - compressible: true, - extensions: ["xsl", "xslt"] - }, - "application/xspf+xml": { - source: "apache", - compressible: true, - extensions: ["xspf"] - }, - "application/xv+xml": { - source: "iana", - compressible: true, - extensions: ["mxml", "xhvml", "xvml", "xvm"] - }, - "application/yaml": { - source: "iana" - }, - "application/yang": { - source: "iana", - extensions: ["yang"] - }, - "application/yang-data+cbor": { - source: "iana" - }, - "application/yang-data+json": { - source: "iana", - compressible: true - }, - "application/yang-data+xml": { - source: "iana", - compressible: true - }, - "application/yang-patch+json": { - source: "iana", - compressible: true - }, - "application/yang-patch+xml": { - source: "iana", - compressible: true - }, - "application/yang-sid+json": { - source: "iana", - compressible: true - }, - "application/yin+xml": { - source: "iana", - compressible: true, - extensions: ["yin"] - }, - "application/zip": { - source: "iana", - compressible: false, - extensions: ["zip"] - }, - "application/zip+dotlottie": { - extensions: ["lottie"] - }, - "application/zlib": { - source: "iana" - }, - "application/zstd": { - source: "iana" - }, - "audio/1d-interleaved-parityfec": { - source: "iana" - }, - "audio/32kadpcm": { - source: "iana" - }, - "audio/3gpp": { - source: "iana", - compressible: false, - extensions: ["3gpp"] - }, - "audio/3gpp2": { - source: "iana" - }, - "audio/aac": { - source: "iana", - extensions: ["adts", "aac"] - }, - "audio/ac3": { - source: "iana" - }, - "audio/adpcm": { - source: "apache", - extensions: ["adp"] - }, - "audio/amr": { - source: "iana", - extensions: ["amr"] - }, - "audio/amr-wb": { - source: "iana" - }, - "audio/amr-wb+": { - source: "iana" - }, - "audio/aptx": { - source: "iana" - }, - "audio/asc": { - source: "iana" - }, - "audio/atrac-advanced-lossless": { - source: "iana" - }, - "audio/atrac-x": { - source: "iana" - }, - "audio/atrac3": { - source: "iana" - }, - "audio/basic": { - source: "iana", - compressible: false, - extensions: ["au", "snd"] - }, - "audio/bv16": { - source: "iana" - }, - "audio/bv32": { - source: "iana" - }, - "audio/clearmode": { - source: "iana" - }, - "audio/cn": { - source: "iana" - }, - "audio/dat12": { - source: "iana" - }, - "audio/dls": { - source: "iana" - }, - "audio/dsr-es201108": { - source: "iana" - }, - "audio/dsr-es202050": { - source: "iana" - }, - "audio/dsr-es202211": { - source: "iana" - }, - "audio/dsr-es202212": { - source: "iana" - }, - "audio/dv": { - source: "iana" - }, - "audio/dvi4": { - source: "iana" - }, - "audio/eac3": { - source: "iana" - }, - "audio/encaprtp": { - source: "iana" - }, - "audio/evrc": { - source: "iana" - }, - "audio/evrc-qcp": { - source: "iana" - }, - "audio/evrc0": { - source: "iana" - }, - "audio/evrc1": { - source: "iana" - }, - "audio/evrcb": { - source: "iana" - }, - "audio/evrcb0": { - source: "iana" - }, - "audio/evrcb1": { - source: "iana" - }, - "audio/evrcnw": { - source: "iana" - }, - "audio/evrcnw0": { - source: "iana" - }, - "audio/evrcnw1": { - source: "iana" - }, - "audio/evrcwb": { - source: "iana" - }, - "audio/evrcwb0": { - source: "iana" - }, - "audio/evrcwb1": { - source: "iana" - }, - "audio/evs": { - source: "iana" - }, - "audio/flac": { - source: "iana" - }, - "audio/flexfec": { - source: "iana" - }, - "audio/fwdred": { - source: "iana" - }, - "audio/g711-0": { - source: "iana" - }, - "audio/g719": { - source: "iana" - }, - "audio/g722": { - source: "iana" - }, - "audio/g7221": { - source: "iana" - }, - "audio/g723": { - source: "iana" - }, - "audio/g726-16": { - source: "iana" - }, - "audio/g726-24": { - source: "iana" - }, - "audio/g726-32": { - source: "iana" - }, - "audio/g726-40": { - source: "iana" - }, - "audio/g728": { - source: "iana" - }, - "audio/g729": { - source: "iana" - }, - "audio/g7291": { - source: "iana" - }, - "audio/g729d": { - source: "iana" - }, - "audio/g729e": { - source: "iana" - }, - "audio/gsm": { - source: "iana" - }, - "audio/gsm-efr": { - source: "iana" - }, - "audio/gsm-hr-08": { - source: "iana" - }, - "audio/ilbc": { - source: "iana" - }, - "audio/ip-mr_v2.5": { - source: "iana" - }, - "audio/isac": { - source: "apache" - }, - "audio/l16": { - source: "iana" - }, - "audio/l20": { - source: "iana" - }, - "audio/l24": { - source: "iana", - compressible: false - }, - "audio/l8": { - source: "iana" - }, - "audio/lpc": { - source: "iana" - }, - "audio/matroska": { - source: "iana" - }, - "audio/melp": { - source: "iana" - }, - "audio/melp1200": { - source: "iana" - }, - "audio/melp2400": { - source: "iana" - }, - "audio/melp600": { - source: "iana" - }, - "audio/mhas": { - source: "iana" - }, - "audio/midi": { - source: "apache", - extensions: ["mid", "midi", "kar", "rmi"] - }, - "audio/midi-clip": { - source: "iana" - }, - "audio/mobile-xmf": { - source: "iana", - extensions: ["mxmf"] - }, - "audio/mp3": { - compressible: false, - extensions: ["mp3"] - }, - "audio/mp4": { - source: "iana", - compressible: false, - extensions: ["m4a", "mp4a", "m4b"] - }, - "audio/mp4a-latm": { - source: "iana" - }, - "audio/mpa": { - source: "iana" - }, - "audio/mpa-robust": { - source: "iana" - }, - "audio/mpeg": { - source: "iana", - compressible: false, - extensions: ["mpga", "mp2", "mp2a", "mp3", "m2a", "m3a"] - }, - "audio/mpeg4-generic": { - source: "iana" - }, - "audio/musepack": { - source: "apache" - }, - "audio/ogg": { - source: "iana", - compressible: false, - extensions: ["oga", "ogg", "spx", "opus"] - }, - "audio/opus": { - source: "iana" - }, - "audio/parityfec": { - source: "iana" - }, - "audio/pcma": { - source: "iana" - }, - "audio/pcma-wb": { - source: "iana" - }, - "audio/pcmu": { - source: "iana" - }, - "audio/pcmu-wb": { - source: "iana" - }, - "audio/prs.sid": { - source: "iana" - }, - "audio/qcelp": { - source: "iana" - }, - "audio/raptorfec": { - source: "iana" - }, - "audio/red": { - source: "iana" - }, - "audio/rtp-enc-aescm128": { - source: "iana" - }, - "audio/rtp-midi": { - source: "iana" - }, - "audio/rtploopback": { - source: "iana" - }, - "audio/rtx": { - source: "iana" - }, - "audio/s3m": { - source: "apache", - extensions: ["s3m"] - }, - "audio/scip": { - source: "iana" - }, - "audio/silk": { - source: "apache", - extensions: ["sil"] - }, - "audio/smv": { - source: "iana" - }, - "audio/smv-qcp": { - source: "iana" - }, - "audio/smv0": { - source: "iana" - }, - "audio/sofa": { - source: "iana" - }, - "audio/sp-midi": { - source: "iana" - }, - "audio/speex": { - source: "iana" - }, - "audio/t140c": { - source: "iana" - }, - "audio/t38": { - source: "iana" - }, - "audio/telephone-event": { - source: "iana" - }, - "audio/tetra_acelp": { - source: "iana" - }, - "audio/tetra_acelp_bb": { - source: "iana" - }, - "audio/tone": { - source: "iana" - }, - "audio/tsvcis": { - source: "iana" - }, - "audio/uemclip": { - source: "iana" - }, - "audio/ulpfec": { - source: "iana" - }, - "audio/usac": { - source: "iana" - }, - "audio/vdvi": { - source: "iana" - }, - "audio/vmr-wb": { - source: "iana" - }, - "audio/vnd.3gpp.iufp": { - source: "iana" - }, - "audio/vnd.4sb": { - source: "iana" - }, - "audio/vnd.audiokoz": { - source: "iana" - }, - "audio/vnd.celp": { - source: "iana" - }, - "audio/vnd.cisco.nse": { - source: "iana" - }, - "audio/vnd.cmles.radio-events": { - source: "iana" - }, - "audio/vnd.cns.anp1": { - source: "iana" - }, - "audio/vnd.cns.inf1": { - source: "iana" - }, - "audio/vnd.dece.audio": { - source: "iana", - extensions: ["uva", "uvva"] - }, - "audio/vnd.digital-winds": { - source: "iana", - extensions: ["eol"] - }, - "audio/vnd.dlna.adts": { - source: "iana" - }, - "audio/vnd.dolby.heaac.1": { - source: "iana" - }, - "audio/vnd.dolby.heaac.2": { - source: "iana" - }, - "audio/vnd.dolby.mlp": { - source: "iana" - }, - "audio/vnd.dolby.mps": { - source: "iana" - }, - "audio/vnd.dolby.pl2": { - source: "iana" - }, - "audio/vnd.dolby.pl2x": { - source: "iana" - }, - "audio/vnd.dolby.pl2z": { - source: "iana" - }, - "audio/vnd.dolby.pulse.1": { - source: "iana" - }, - "audio/vnd.dra": { - source: "iana", - extensions: ["dra"] - }, - "audio/vnd.dts": { - source: "iana", - extensions: ["dts"] - }, - "audio/vnd.dts.hd": { - source: "iana", - extensions: ["dtshd"] - }, - "audio/vnd.dts.uhd": { - source: "iana" - }, - "audio/vnd.dvb.file": { - source: "iana" - }, - "audio/vnd.everad.plj": { - source: "iana" - }, - "audio/vnd.hns.audio": { - source: "iana" - }, - "audio/vnd.lucent.voice": { - source: "iana", - extensions: ["lvp"] - }, - "audio/vnd.ms-playready.media.pya": { - source: "iana", - extensions: ["pya"] - }, - "audio/vnd.nokia.mobile-xmf": { - source: "iana" - }, - "audio/vnd.nortel.vbk": { - source: "iana" - }, - "audio/vnd.nuera.ecelp4800": { - source: "iana", - extensions: ["ecelp4800"] - }, - "audio/vnd.nuera.ecelp7470": { - source: "iana", - extensions: ["ecelp7470"] - }, - "audio/vnd.nuera.ecelp9600": { - source: "iana", - extensions: ["ecelp9600"] - }, - "audio/vnd.octel.sbc": { - source: "iana" - }, - "audio/vnd.presonus.multitrack": { - source: "iana" - }, - "audio/vnd.qcelp": { - source: "apache" - }, - "audio/vnd.rhetorex.32kadpcm": { - source: "iana" - }, - "audio/vnd.rip": { - source: "iana", - extensions: ["rip"] - }, - "audio/vnd.rn-realaudio": { - compressible: false - }, - "audio/vnd.sealedmedia.softseal.mpeg": { - source: "iana" - }, - "audio/vnd.vmx.cvsd": { - source: "iana" - }, - "audio/vnd.wave": { - compressible: false - }, - "audio/vorbis": { - source: "iana", - compressible: false - }, - "audio/vorbis-config": { - source: "iana" - }, - "audio/wav": { - compressible: false, - extensions: ["wav"] - }, - "audio/wave": { - compressible: false, - extensions: ["wav"] - }, - "audio/webm": { - source: "apache", - compressible: false, - extensions: ["weba"] - }, - "audio/x-aac": { - source: "apache", - compressible: false, - extensions: ["aac"] - }, - "audio/x-aiff": { - source: "apache", - extensions: ["aif", "aiff", "aifc"] - }, - "audio/x-caf": { - source: "apache", - compressible: false, - extensions: ["caf"] - }, - "audio/x-flac": { - source: "apache", - extensions: ["flac"] - }, - "audio/x-m4a": { - source: "nginx", - extensions: ["m4a"] - }, - "audio/x-matroska": { - source: "apache", - extensions: ["mka"] - }, - "audio/x-mpegurl": { - source: "apache", - extensions: ["m3u"] - }, - "audio/x-ms-wax": { - source: "apache", - extensions: ["wax"] - }, - "audio/x-ms-wma": { - source: "apache", - extensions: ["wma"] - }, - "audio/x-pn-realaudio": { - source: "apache", - extensions: ["ram", "ra"] - }, - "audio/x-pn-realaudio-plugin": { - source: "apache", - extensions: ["rmp"] - }, - "audio/x-realaudio": { - source: "nginx", - extensions: ["ra"] - }, - "audio/x-tta": { - source: "apache" - }, - "audio/x-wav": { - source: "apache", - extensions: ["wav"] - }, - "audio/xm": { - source: "apache", - extensions: ["xm"] - }, - "chemical/x-cdx": { - source: "apache", - extensions: ["cdx"] - }, - "chemical/x-cif": { - source: "apache", - extensions: ["cif"] - }, - "chemical/x-cmdf": { - source: "apache", - extensions: ["cmdf"] - }, - "chemical/x-cml": { - source: "apache", - extensions: ["cml"] - }, - "chemical/x-csml": { - source: "apache", - extensions: ["csml"] - }, - "chemical/x-pdb": { - source: "apache" - }, - "chemical/x-xyz": { - source: "apache", - extensions: ["xyz"] - }, - "font/collection": { - source: "iana", - extensions: ["ttc"] - }, - "font/otf": { - source: "iana", - compressible: true, - extensions: ["otf"] - }, - "font/sfnt": { - source: "iana" - }, - "font/ttf": { - source: "iana", - compressible: true, - extensions: ["ttf"] - }, - "font/woff": { - source: "iana", - extensions: ["woff"] - }, - "font/woff2": { - source: "iana", - extensions: ["woff2"] - }, - "image/aces": { - source: "iana", - extensions: ["exr"] - }, - "image/apng": { - source: "iana", - compressible: false, - extensions: ["apng"] - }, - "image/avci": { - source: "iana", - extensions: ["avci"] - }, - "image/avcs": { - source: "iana", - extensions: ["avcs"] - }, - "image/avif": { - source: "iana", - compressible: false, - extensions: ["avif"] - }, - "image/bmp": { - source: "iana", - compressible: true, - extensions: ["bmp", "dib"] - }, - "image/cgm": { - source: "iana", - extensions: ["cgm"] - }, - "image/dicom-rle": { - source: "iana", - extensions: ["drle"] - }, - "image/dpx": { - source: "iana", - extensions: ["dpx"] - }, - "image/emf": { - source: "iana", - extensions: ["emf"] - }, - "image/fits": { - source: "iana", - extensions: ["fits"] - }, - "image/g3fax": { - source: "iana", - extensions: ["g3"] - }, - "image/gif": { - source: "iana", - compressible: false, - extensions: ["gif"] - }, - "image/heic": { - source: "iana", - extensions: ["heic"] - }, - "image/heic-sequence": { - source: "iana", - extensions: ["heics"] - }, - "image/heif": { - source: "iana", - extensions: ["heif"] - }, - "image/heif-sequence": { - source: "iana", - extensions: ["heifs"] - }, - "image/hej2k": { - source: "iana", - extensions: ["hej2"] - }, - "image/ief": { - source: "iana", - extensions: ["ief"] - }, - "image/j2c": { - source: "iana" - }, - "image/jaii": { - source: "iana", - extensions: ["jaii"] - }, - "image/jais": { - source: "iana", - extensions: ["jais"] - }, - "image/jls": { - source: "iana", - extensions: ["jls"] - }, - "image/jp2": { - source: "iana", - compressible: false, - extensions: ["jp2", "jpg2"] - }, - "image/jpeg": { - source: "iana", - compressible: false, - extensions: ["jpg", "jpeg", "jpe"] - }, - "image/jph": { - source: "iana", - extensions: ["jph"] - }, - "image/jphc": { - source: "iana", - extensions: ["jhc"] - }, - "image/jpm": { - source: "iana", - compressible: false, - extensions: ["jpm", "jpgm"] - }, - "image/jpx": { - source: "iana", - compressible: false, - extensions: ["jpx", "jpf"] - }, - "image/jxl": { - source: "iana", - extensions: ["jxl"] - }, - "image/jxr": { - source: "iana", - extensions: ["jxr"] - }, - "image/jxra": { - source: "iana", - extensions: ["jxra"] - }, - "image/jxrs": { - source: "iana", - extensions: ["jxrs"] - }, - "image/jxs": { - source: "iana", - extensions: ["jxs"] - }, - "image/jxsc": { - source: "iana", - extensions: ["jxsc"] - }, - "image/jxsi": { - source: "iana", - extensions: ["jxsi"] - }, - "image/jxss": { - source: "iana", - extensions: ["jxss"] - }, - "image/ktx": { - source: "iana", - extensions: ["ktx"] - }, - "image/ktx2": { - source: "iana", - extensions: ["ktx2"] - }, - "image/naplps": { - source: "iana" - }, - "image/pjpeg": { - compressible: false, - extensions: ["jfif"] - }, - "image/png": { - source: "iana", - compressible: false, - extensions: ["png"] - }, - "image/prs.btif": { - source: "iana", - extensions: ["btif", "btf"] - }, - "image/prs.pti": { - source: "iana", - extensions: ["pti"] - }, - "image/pwg-raster": { - source: "iana" - }, - "image/sgi": { - source: "apache", - extensions: ["sgi"] - }, - "image/svg+xml": { - source: "iana", - compressible: true, - extensions: ["svg", "svgz"] - }, - "image/t38": { - source: "iana", - extensions: ["t38"] - }, - "image/tiff": { - source: "iana", - compressible: false, - extensions: ["tif", "tiff"] - }, - "image/tiff-fx": { - source: "iana", - extensions: ["tfx"] - }, - "image/vnd.adobe.photoshop": { - source: "iana", - compressible: true, - extensions: ["psd"] - }, - "image/vnd.airzip.accelerator.azv": { - source: "iana", - extensions: ["azv"] - }, - "image/vnd.clip": { - source: "iana" - }, - "image/vnd.cns.inf2": { - source: "iana" - }, - "image/vnd.dece.graphic": { - source: "iana", - extensions: ["uvi", "uvvi", "uvg", "uvvg"] - }, - "image/vnd.djvu": { - source: "iana", - extensions: ["djvu", "djv"] - }, - "image/vnd.dvb.subtitle": { - source: "iana", - extensions: ["sub"] - }, - "image/vnd.dwg": { - source: "iana", - extensions: ["dwg"] - }, - "image/vnd.dxf": { - source: "iana", - extensions: ["dxf"] - }, - "image/vnd.fastbidsheet": { - source: "iana", - extensions: ["fbs"] - }, - "image/vnd.fpx": { - source: "iana", - extensions: ["fpx"] - }, - "image/vnd.fst": { - source: "iana", - extensions: ["fst"] - }, - "image/vnd.fujixerox.edmics-mmr": { - source: "iana", - extensions: ["mmr"] - }, - "image/vnd.fujixerox.edmics-rlc": { - source: "iana", - extensions: ["rlc"] - }, - "image/vnd.globalgraphics.pgb": { - source: "iana" - }, - "image/vnd.microsoft.icon": { - source: "iana", - compressible: true, - extensions: ["ico"] - }, - "image/vnd.mix": { - source: "iana" - }, - "image/vnd.mozilla.apng": { - source: "iana" - }, - "image/vnd.ms-dds": { - compressible: true, - extensions: ["dds"] - }, - "image/vnd.ms-modi": { - source: "iana", - extensions: ["mdi"] - }, - "image/vnd.ms-photo": { - source: "apache", - extensions: ["wdp"] - }, - "image/vnd.net-fpx": { - source: "iana", - extensions: ["npx"] - }, - "image/vnd.pco.b16": { - source: "iana", - extensions: ["b16"] - }, - "image/vnd.radiance": { - source: "iana" - }, - "image/vnd.sealed.png": { - source: "iana" - }, - "image/vnd.sealedmedia.softseal.gif": { - source: "iana" - }, - "image/vnd.sealedmedia.softseal.jpg": { - source: "iana" - }, - "image/vnd.svf": { - source: "iana" - }, - "image/vnd.tencent.tap": { - source: "iana", - extensions: ["tap"] - }, - "image/vnd.valve.source.texture": { - source: "iana", - extensions: ["vtf"] - }, - "image/vnd.wap.wbmp": { - source: "iana", - extensions: ["wbmp"] - }, - "image/vnd.xiff": { - source: "iana", - extensions: ["xif"] - }, - "image/vnd.zbrush.pcx": { - source: "iana", - extensions: ["pcx"] - }, - "image/webp": { - source: "iana", - extensions: ["webp"] - }, - "image/wmf": { - source: "iana", - extensions: ["wmf"] - }, - "image/x-3ds": { - source: "apache", - extensions: ["3ds"] - }, - "image/x-adobe-dng": { - extensions: ["dng"] - }, - "image/x-cmu-raster": { - source: "apache", - extensions: ["ras"] - }, - "image/x-cmx": { - source: "apache", - extensions: ["cmx"] - }, - "image/x-emf": { - source: "iana" - }, - "image/x-freehand": { - source: "apache", - extensions: ["fh", "fhc", "fh4", "fh5", "fh7"] - }, - "image/x-icon": { - source: "apache", - compressible: true, - extensions: ["ico"] - }, - "image/x-jng": { - source: "nginx", - extensions: ["jng"] - }, - "image/x-mrsid-image": { - source: "apache", - extensions: ["sid"] - }, - "image/x-ms-bmp": { - source: "nginx", - compressible: true, - extensions: ["bmp"] - }, - "image/x-pcx": { - source: "apache", - extensions: ["pcx"] - }, - "image/x-pict": { - source: "apache", - extensions: ["pic", "pct"] - }, - "image/x-portable-anymap": { - source: "apache", - extensions: ["pnm"] - }, - "image/x-portable-bitmap": { - source: "apache", - extensions: ["pbm"] - }, - "image/x-portable-graymap": { - source: "apache", - extensions: ["pgm"] - }, - "image/x-portable-pixmap": { - source: "apache", - extensions: ["ppm"] - }, - "image/x-rgb": { - source: "apache", - extensions: ["rgb"] - }, - "image/x-tga": { - source: "apache", - extensions: ["tga"] - }, - "image/x-wmf": { - source: "iana" - }, - "image/x-xbitmap": { - source: "apache", - extensions: ["xbm"] - }, - "image/x-xcf": { - compressible: false - }, - "image/x-xpixmap": { - source: "apache", - extensions: ["xpm"] - }, - "image/x-xwindowdump": { - source: "apache", - extensions: ["xwd"] - }, - "message/bhttp": { - source: "iana" - }, - "message/cpim": { - source: "iana" - }, - "message/delivery-status": { - source: "iana" - }, - "message/disposition-notification": { - source: "iana", - extensions: [ - "disposition-notification" - ] - }, - "message/external-body": { - source: "iana" - }, - "message/feedback-report": { - source: "iana" - }, - "message/global": { - source: "iana", - extensions: ["u8msg"] - }, - "message/global-delivery-status": { - source: "iana", - extensions: ["u8dsn"] - }, - "message/global-disposition-notification": { - source: "iana", - extensions: ["u8mdn"] - }, - "message/global-headers": { - source: "iana", - extensions: ["u8hdr"] - }, - "message/http": { - source: "iana", - compressible: false - }, - "message/imdn+xml": { - source: "iana", - compressible: true - }, - "message/mls": { - source: "iana" - }, - "message/news": { - source: "apache" - }, - "message/ohttp-req": { - source: "iana" - }, - "message/ohttp-res": { - source: "iana" - }, - "message/partial": { - source: "iana", - compressible: false - }, - "message/rfc822": { - source: "iana", - compressible: true, - extensions: ["eml", "mime", "mht", "mhtml"] - }, - "message/s-http": { - source: "apache" - }, - "message/sip": { - source: "iana" - }, - "message/sipfrag": { - source: "iana" - }, - "message/tracking-status": { - source: "iana" - }, - "message/vnd.si.simp": { - source: "apache" - }, - "message/vnd.wfa.wsc": { - source: "iana", - extensions: ["wsc"] - }, - "model/3mf": { - source: "iana", - extensions: ["3mf"] - }, - "model/e57": { - source: "iana" - }, - "model/gltf+json": { - source: "iana", - compressible: true, - extensions: ["gltf"] - }, - "model/gltf-binary": { - source: "iana", - compressible: true, - extensions: ["glb"] - }, - "model/iges": { - source: "iana", - compressible: false, - extensions: ["igs", "iges"] - }, - "model/jt": { - source: "iana", - extensions: ["jt"] - }, - "model/mesh": { - source: "iana", - compressible: false, - extensions: ["msh", "mesh", "silo"] - }, - "model/mtl": { - source: "iana", - extensions: ["mtl"] - }, - "model/obj": { - source: "iana", - extensions: ["obj"] - }, - "model/prc": { - source: "iana", - extensions: ["prc"] - }, - "model/step": { - source: "iana", - extensions: ["step", "stp", "stpnc", "p21", "210"] - }, - "model/step+xml": { - source: "iana", - compressible: true, - extensions: ["stpx"] - }, - "model/step+zip": { - source: "iana", - compressible: false, - extensions: ["stpz"] - }, - "model/step-xml+zip": { - source: "iana", - compressible: false, - extensions: ["stpxz"] - }, - "model/stl": { - source: "iana", - extensions: ["stl"] - }, - "model/u3d": { - source: "iana", - extensions: ["u3d"] - }, - "model/vnd.bary": { - source: "iana", - extensions: ["bary"] - }, - "model/vnd.cld": { - source: "iana", - extensions: ["cld"] - }, - "model/vnd.collada+xml": { - source: "iana", - compressible: true, - extensions: ["dae"] - }, - "model/vnd.dwf": { - source: "iana", - extensions: ["dwf"] - }, - "model/vnd.flatland.3dml": { - source: "iana" - }, - "model/vnd.gdl": { - source: "iana", - extensions: ["gdl"] - }, - "model/vnd.gs-gdl": { - source: "apache" - }, - "model/vnd.gs.gdl": { - source: "iana" - }, - "model/vnd.gtw": { - source: "iana", - extensions: ["gtw"] - }, - "model/vnd.moml+xml": { - source: "iana", - compressible: true - }, - "model/vnd.mts": { - source: "iana", - extensions: ["mts"] - }, - "model/vnd.opengex": { - source: "iana", - extensions: ["ogex"] - }, - "model/vnd.parasolid.transmit.binary": { - source: "iana", - extensions: ["x_b"] - }, - "model/vnd.parasolid.transmit.text": { - source: "iana", - extensions: ["x_t"] - }, - "model/vnd.pytha.pyox": { - source: "iana", - extensions: ["pyo", "pyox"] - }, - "model/vnd.rosette.annotated-data-model": { - source: "iana" - }, - "model/vnd.sap.vds": { - source: "iana", - extensions: ["vds"] - }, - "model/vnd.usda": { - source: "iana", - extensions: ["usda"] - }, - "model/vnd.usdz+zip": { - source: "iana", - compressible: false, - extensions: ["usdz"] - }, - "model/vnd.valve.source.compiled-map": { - source: "iana", - extensions: ["bsp"] - }, - "model/vnd.vtu": { - source: "iana", - extensions: ["vtu"] - }, - "model/vrml": { - source: "iana", - compressible: false, - extensions: ["wrl", "vrml"] - }, - "model/x3d+binary": { - source: "apache", - compressible: false, - extensions: ["x3db", "x3dbz"] - }, - "model/x3d+fastinfoset": { - source: "iana", - extensions: ["x3db"] - }, - "model/x3d+vrml": { - source: "apache", - compressible: false, - extensions: ["x3dv", "x3dvz"] - }, - "model/x3d+xml": { - source: "iana", - compressible: true, - extensions: ["x3d", "x3dz"] - }, - "model/x3d-vrml": { - source: "iana", - extensions: ["x3dv"] - }, - "multipart/alternative": { - source: "iana", - compressible: false - }, - "multipart/appledouble": { - source: "iana" - }, - "multipart/byteranges": { - source: "iana" - }, - "multipart/digest": { - source: "iana" - }, - "multipart/encrypted": { - source: "iana", - compressible: false - }, - "multipart/form-data": { - source: "iana", - compressible: false - }, - "multipart/header-set": { - source: "iana" - }, - "multipart/mixed": { - source: "iana" - }, - "multipart/multilingual": { - source: "iana" - }, - "multipart/parallel": { - source: "iana" - }, - "multipart/related": { - source: "iana", - compressible: false - }, - "multipart/report": { - source: "iana" - }, - "multipart/signed": { - source: "iana", - compressible: false - }, - "multipart/vnd.bint.med-plus": { - source: "iana" - }, - "multipart/voice-message": { - source: "iana" - }, - "multipart/x-mixed-replace": { - source: "iana" - }, - "text/1d-interleaved-parityfec": { - source: "iana" - }, - "text/cache-manifest": { - source: "iana", - compressible: true, - extensions: ["appcache", "manifest"] - }, - "text/calendar": { - source: "iana", - extensions: ["ics", "ifb"] - }, - "text/calender": { - compressible: true - }, - "text/cmd": { - compressible: true - }, - "text/coffeescript": { - extensions: ["coffee", "litcoffee"] - }, - "text/cql": { - source: "iana" - }, - "text/cql-expression": { - source: "iana" - }, - "text/cql-identifier": { - source: "iana" - }, - "text/css": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["css"] - }, - "text/csv": { - source: "iana", - compressible: true, - extensions: ["csv"] - }, - "text/csv-schema": { - source: "iana" - }, - "text/directory": { - source: "iana" - }, - "text/dns": { - source: "iana" - }, - "text/ecmascript": { - source: "apache" - }, - "text/encaprtp": { - source: "iana" - }, - "text/enriched": { - source: "iana" - }, - "text/fhirpath": { - source: "iana" - }, - "text/flexfec": { - source: "iana" - }, - "text/fwdred": { - source: "iana" - }, - "text/gff3": { - source: "iana" - }, - "text/grammar-ref-list": { - source: "iana" - }, - "text/hl7v2": { - source: "iana" - }, - "text/html": { - source: "iana", - compressible: true, - extensions: ["html", "htm", "shtml"] - }, - "text/jade": { - extensions: ["jade"] - }, - "text/javascript": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["js", "mjs"] - }, - "text/jcr-cnd": { - source: "iana" - }, - "text/jsx": { - compressible: true, - extensions: ["jsx"] - }, - "text/less": { - compressible: true, - extensions: ["less"] - }, - "text/markdown": { - source: "iana", - compressible: true, - extensions: ["md", "markdown"] - }, - "text/mathml": { - source: "nginx", - extensions: ["mml"] - }, - "text/mdx": { - compressible: true, - extensions: ["mdx"] - }, - "text/mizar": { - source: "iana" - }, - "text/n3": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["n3"] - }, - "text/parameters": { - source: "iana", - charset: "UTF-8" - }, - "text/parityfec": { - source: "iana" - }, - "text/plain": { - source: "iana", - compressible: true, - extensions: ["txt", "text", "conf", "def", "list", "log", "in", "ini"] - }, - "text/provenance-notation": { - source: "iana", - charset: "UTF-8" - }, - "text/prs.fallenstein.rst": { - source: "iana" - }, - "text/prs.lines.tag": { - source: "iana", - extensions: ["dsc"] - }, - "text/prs.prop.logic": { - source: "iana" - }, - "text/prs.texi": { - source: "iana" - }, - "text/raptorfec": { - source: "iana" - }, - "text/red": { - source: "iana" - }, - "text/rfc822-headers": { - source: "iana" - }, - "text/richtext": { - source: "iana", - compressible: true, - extensions: ["rtx"] - }, - "text/rtf": { - source: "iana", - compressible: true, - extensions: ["rtf"] - }, - "text/rtp-enc-aescm128": { - source: "iana" - }, - "text/rtploopback": { - source: "iana" - }, - "text/rtx": { - source: "iana" - }, - "text/sgml": { - source: "iana", - extensions: ["sgml", "sgm"] - }, - "text/shaclc": { - source: "iana" - }, - "text/shex": { - source: "iana", - extensions: ["shex"] - }, - "text/slim": { - extensions: ["slim", "slm"] - }, - "text/spdx": { - source: "iana", - extensions: ["spdx"] - }, - "text/strings": { - source: "iana" - }, - "text/stylus": { - extensions: ["stylus", "styl"] - }, - "text/t140": { - source: "iana" - }, - "text/tab-separated-values": { - source: "iana", - compressible: true, - extensions: ["tsv"] - }, - "text/troff": { - source: "iana", - extensions: ["t", "tr", "roff", "man", "me", "ms"] - }, - "text/turtle": { - source: "iana", - charset: "UTF-8", - extensions: ["ttl"] - }, - "text/ulpfec": { - source: "iana" - }, - "text/uri-list": { - source: "iana", - compressible: true, - extensions: ["uri", "uris", "urls"] - }, - "text/vcard": { - source: "iana", - compressible: true, - extensions: ["vcard"] - }, - "text/vnd.a": { - source: "iana" - }, - "text/vnd.abc": { - source: "iana" - }, - "text/vnd.ascii-art": { - source: "iana" - }, - "text/vnd.curl": { - source: "iana", - extensions: ["curl"] - }, - "text/vnd.curl.dcurl": { - source: "apache", - extensions: ["dcurl"] - }, - "text/vnd.curl.mcurl": { - source: "apache", - extensions: ["mcurl"] - }, - "text/vnd.curl.scurl": { - source: "apache", - extensions: ["scurl"] - }, - "text/vnd.debian.copyright": { - source: "iana", - charset: "UTF-8" - }, - "text/vnd.dmclientscript": { - source: "iana" - }, - "text/vnd.dvb.subtitle": { - source: "iana", - extensions: ["sub"] - }, - "text/vnd.esmertec.theme-descriptor": { - source: "iana", - charset: "UTF-8" - }, - "text/vnd.exchangeable": { - source: "iana" - }, - "text/vnd.familysearch.gedcom": { - source: "iana", - extensions: ["ged"] - }, - "text/vnd.ficlab.flt": { - source: "iana" - }, - "text/vnd.fly": { - source: "iana", - extensions: ["fly"] - }, - "text/vnd.fmi.flexstor": { - source: "iana", - extensions: ["flx"] - }, - "text/vnd.gml": { - source: "iana" - }, - "text/vnd.graphviz": { - source: "iana", - extensions: ["gv"] - }, - "text/vnd.hans": { - source: "iana" - }, - "text/vnd.hgl": { - source: "iana" - }, - "text/vnd.in3d.3dml": { - source: "iana", - extensions: ["3dml"] - }, - "text/vnd.in3d.spot": { - source: "iana", - extensions: ["spot"] - }, - "text/vnd.iptc.newsml": { - source: "iana" - }, - "text/vnd.iptc.nitf": { - source: "iana" - }, - "text/vnd.latex-z": { - source: "iana" - }, - "text/vnd.motorola.reflex": { - source: "iana" - }, - "text/vnd.ms-mediapackage": { - source: "iana" - }, - "text/vnd.net2phone.commcenter.command": { - source: "iana" - }, - "text/vnd.radisys.msml-basic-layout": { - source: "iana" - }, - "text/vnd.senx.warpscript": { - source: "iana" - }, - "text/vnd.si.uricatalogue": { - source: "apache" - }, - "text/vnd.sosi": { - source: "iana" - }, - "text/vnd.sun.j2me.app-descriptor": { - source: "iana", - charset: "UTF-8", - extensions: ["jad"] - }, - "text/vnd.trolltech.linguist": { - source: "iana", - charset: "UTF-8" - }, - "text/vnd.vcf": { - source: "iana" - }, - "text/vnd.wap.si": { - source: "iana" - }, - "text/vnd.wap.sl": { - source: "iana" - }, - "text/vnd.wap.wml": { - source: "iana", - extensions: ["wml"] - }, - "text/vnd.wap.wmlscript": { - source: "iana", - extensions: ["wmls"] - }, - "text/vnd.zoo.kcl": { - source: "iana" - }, - "text/vtt": { - source: "iana", - charset: "UTF-8", - compressible: true, - extensions: ["vtt"] - }, - "text/wgsl": { - source: "iana", - extensions: ["wgsl"] - }, - "text/x-asm": { - source: "apache", - extensions: ["s", "asm"] - }, - "text/x-c": { - source: "apache", - extensions: ["c", "cc", "cxx", "cpp", "h", "hh", "dic"] - }, - "text/x-component": { - source: "nginx", - extensions: ["htc"] - }, - "text/x-fortran": { - source: "apache", - extensions: ["f", "for", "f77", "f90"] - }, - "text/x-gwt-rpc": { - compressible: true - }, - "text/x-handlebars-template": { - extensions: ["hbs"] - }, - "text/x-java-source": { - source: "apache", - extensions: ["java"] - }, - "text/x-jquery-tmpl": { - compressible: true - }, - "text/x-lua": { - extensions: ["lua"] - }, - "text/x-markdown": { - compressible: true, - extensions: ["mkd"] - }, - "text/x-nfo": { - source: "apache", - extensions: ["nfo"] - }, - "text/x-opml": { - source: "apache", - extensions: ["opml"] - }, - "text/x-org": { - compressible: true, - extensions: ["org"] - }, - "text/x-pascal": { - source: "apache", - extensions: ["p", "pas"] - }, - "text/x-processing": { - compressible: true, - extensions: ["pde"] - }, - "text/x-sass": { - extensions: ["sass"] - }, - "text/x-scss": { - extensions: ["scss"] - }, - "text/x-setext": { - source: "apache", - extensions: ["etx"] - }, - "text/x-sfv": { - source: "apache", - extensions: ["sfv"] - }, - "text/x-suse-ymp": { - compressible: true, - extensions: ["ymp"] - }, - "text/x-uuencode": { - source: "apache", - extensions: ["uu"] - }, - "text/x-vcalendar": { - source: "apache", - extensions: ["vcs"] - }, - "text/x-vcard": { - source: "apache", - extensions: ["vcf"] - }, - "text/xml": { - source: "iana", - compressible: true, - extensions: ["xml"] - }, - "text/xml-external-parsed-entity": { - source: "iana" - }, - "text/yaml": { - compressible: true, - extensions: ["yaml", "yml"] - }, - "video/1d-interleaved-parityfec": { - source: "iana" - }, - "video/3gpp": { - source: "iana", - extensions: ["3gp", "3gpp"] - }, - "video/3gpp-tt": { - source: "iana" - }, - "video/3gpp2": { - source: "iana", - extensions: ["3g2"] - }, - "video/av1": { - source: "iana" - }, - "video/bmpeg": { - source: "iana" - }, - "video/bt656": { - source: "iana" - }, - "video/celb": { - source: "iana" - }, - "video/dv": { - source: "iana" - }, - "video/encaprtp": { - source: "iana" - }, - "video/evc": { - source: "iana" - }, - "video/ffv1": { - source: "iana" - }, - "video/flexfec": { - source: "iana" - }, - "video/h261": { - source: "iana", - extensions: ["h261"] - }, - "video/h263": { - source: "iana", - extensions: ["h263"] - }, - "video/h263-1998": { - source: "iana" - }, - "video/h263-2000": { - source: "iana" - }, - "video/h264": { - source: "iana", - extensions: ["h264"] - }, - "video/h264-rcdo": { - source: "iana" - }, - "video/h264-svc": { - source: "iana" - }, - "video/h265": { - source: "iana" - }, - "video/h266": { - source: "iana" - }, - "video/iso.segment": { - source: "iana", - extensions: ["m4s"] - }, - "video/jpeg": { - source: "iana", - extensions: ["jpgv"] - }, - "video/jpeg2000": { - source: "iana" - }, - "video/jpm": { - source: "apache", - extensions: ["jpm", "jpgm"] - }, - "video/jxsv": { - source: "iana" - }, - "video/lottie+json": { - source: "iana", - compressible: true - }, - "video/matroska": { - source: "iana" - }, - "video/matroska-3d": { - source: "iana" - }, - "video/mj2": { - source: "iana", - extensions: ["mj2", "mjp2"] - }, - "video/mp1s": { - source: "iana" - }, - "video/mp2p": { - source: "iana" - }, - "video/mp2t": { - source: "iana", - extensions: ["ts", "m2t", "m2ts", "mts"] - }, - "video/mp4": { - source: "iana", - compressible: false, - extensions: ["mp4", "mp4v", "mpg4"] - }, - "video/mp4v-es": { - source: "iana" - }, - "video/mpeg": { - source: "iana", - compressible: false, - extensions: ["mpeg", "mpg", "mpe", "m1v", "m2v"] - }, - "video/mpeg4-generic": { - source: "iana" - }, - "video/mpv": { - source: "iana" - }, - "video/nv": { - source: "iana" - }, - "video/ogg": { - source: "iana", - compressible: false, - extensions: ["ogv"] - }, - "video/parityfec": { - source: "iana" - }, - "video/pointer": { - source: "iana" - }, - "video/quicktime": { - source: "iana", - compressible: false, - extensions: ["qt", "mov"] - }, - "video/raptorfec": { - source: "iana" - }, - "video/raw": { - source: "iana" - }, - "video/rtp-enc-aescm128": { - source: "iana" - }, - "video/rtploopback": { - source: "iana" - }, - "video/rtx": { - source: "iana" - }, - "video/scip": { - source: "iana" - }, - "video/smpte291": { - source: "iana" - }, - "video/smpte292m": { - source: "iana" - }, - "video/ulpfec": { - source: "iana" - }, - "video/vc1": { - source: "iana" - }, - "video/vc2": { - source: "iana" - }, - "video/vnd.cctv": { - source: "iana" - }, - "video/vnd.dece.hd": { - source: "iana", - extensions: ["uvh", "uvvh"] - }, - "video/vnd.dece.mobile": { - source: "iana", - extensions: ["uvm", "uvvm"] - }, - "video/vnd.dece.mp4": { - source: "iana" - }, - "video/vnd.dece.pd": { - source: "iana", - extensions: ["uvp", "uvvp"] - }, - "video/vnd.dece.sd": { - source: "iana", - extensions: ["uvs", "uvvs"] - }, - "video/vnd.dece.video": { - source: "iana", - extensions: ["uvv", "uvvv"] - }, - "video/vnd.directv.mpeg": { - source: "iana" - }, - "video/vnd.directv.mpeg-tts": { - source: "iana" - }, - "video/vnd.dlna.mpeg-tts": { - source: "iana" - }, - "video/vnd.dvb.file": { - source: "iana", - extensions: ["dvb"] - }, - "video/vnd.fvt": { - source: "iana", - extensions: ["fvt"] - }, - "video/vnd.hns.video": { - source: "iana" - }, - "video/vnd.iptvforum.1dparityfec-1010": { - source: "iana" - }, - "video/vnd.iptvforum.1dparityfec-2005": { - source: "iana" - }, - "video/vnd.iptvforum.2dparityfec-1010": { - source: "iana" - }, - "video/vnd.iptvforum.2dparityfec-2005": { - source: "iana" - }, - "video/vnd.iptvforum.ttsavc": { - source: "iana" - }, - "video/vnd.iptvforum.ttsmpeg2": { - source: "iana" - }, - "video/vnd.motorola.video": { - source: "iana" - }, - "video/vnd.motorola.videop": { - source: "iana" - }, - "video/vnd.mpegurl": { - source: "iana", - extensions: ["mxu", "m4u"] - }, - "video/vnd.ms-playready.media.pyv": { - source: "iana", - extensions: ["pyv"] - }, - "video/vnd.nokia.interleaved-multimedia": { - source: "iana" - }, - "video/vnd.nokia.mp4vr": { - source: "iana" - }, - "video/vnd.nokia.videovoip": { - source: "iana" - }, - "video/vnd.objectvideo": { - source: "iana" - }, - "video/vnd.planar": { - source: "iana" - }, - "video/vnd.radgamettools.bink": { - source: "iana" - }, - "video/vnd.radgamettools.smacker": { - source: "apache" - }, - "video/vnd.sealed.mpeg1": { - source: "iana" - }, - "video/vnd.sealed.mpeg4": { - source: "iana" - }, - "video/vnd.sealed.swf": { - source: "iana" - }, - "video/vnd.sealedmedia.softseal.mov": { - source: "iana" - }, - "video/vnd.uvvu.mp4": { - source: "iana", - extensions: ["uvu", "uvvu"] - }, - "video/vnd.vivo": { - source: "iana", - extensions: ["viv"] - }, - "video/vnd.youtube.yt": { - source: "iana" - }, - "video/vp8": { - source: "iana" - }, - "video/vp9": { - source: "iana" - }, - "video/webm": { - source: "apache", - compressible: false, - extensions: ["webm"] - }, - "video/x-f4v": { - source: "apache", - extensions: ["f4v"] - }, - "video/x-fli": { - source: "apache", - extensions: ["fli"] - }, - "video/x-flv": { - source: "apache", - compressible: false, - extensions: ["flv"] - }, - "video/x-m4v": { - source: "apache", - extensions: ["m4v"] - }, - "video/x-matroska": { - source: "apache", - compressible: false, - extensions: ["mkv", "mk3d", "mks"] - }, - "video/x-mng": { - source: "apache", - extensions: ["mng"] - }, - "video/x-ms-asf": { - source: "apache", - extensions: ["asf", "asx"] - }, - "video/x-ms-vob": { - source: "apache", - extensions: ["vob"] - }, - "video/x-ms-wm": { - source: "apache", - extensions: ["wm"] - }, - "video/x-ms-wmv": { - source: "apache", - compressible: false, - extensions: ["wmv"] - }, - "video/x-ms-wmx": { - source: "apache", - extensions: ["wmx"] - }, - "video/x-ms-wvx": { - source: "apache", - extensions: ["wvx"] + exports2.RedisClientPool = void 0; + var commands_1 = __importDefault(require_commands()); + var _1 = __importDefault(require_client()); + var node_events_1 = __require2("node:events"); + var linked_list_1 = require_linked_list(); + var errors_1 = require_errors(); + var commander_1 = require_commander(); + var multi_command_1 = __importDefault(require_multi_command2()); + var cache_1 = require_cache(); + var parser_1 = require_parser(); + var single_entry_cache_1 = __importDefault(require_single_entry_cache()); + var RedisClientPool = class _RedisClientPool extends node_events_1.EventEmitter { + static #createCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this.execute((client) => client._executeCommand(command2, parser3, this._commandOptions, transformReply)); + }; + } + static #createModuleCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this._self.execute((client) => client._executeCommand(command2, parser3, this._self._commandOptions, transformReply)); + }; + } + static #createFunctionCommand(name, fn, resp) { + const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); + const transformReply = (0, commander_1.getTransformReply)(fn, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + fn.parseCommand(parser3, ...args); + return this._self.execute((client) => client._executeCommand(fn, parser3, this._self._commandOptions, transformReply)); + }; + } + static #createScriptCommand(script, resp) { + const prefix = (0, commander_1.scriptArgumentsPrefix)(script); + const transformReply = (0, commander_1.getTransformReply)(script, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.pushVariadic(prefix); + script.parseCommand(parser3, ...args); + return this.execute((client) => client._executeScript(script, parser3, this._commandOptions, transformReply)); + }; + } + static #SingleEntryCache = new single_entry_cache_1.default(); + static create(clientOptions, options2) { + let Pool = _RedisClientPool.#SingleEntryCache.get(clientOptions); + if (!Pool) { + Pool = (0, commander_1.attachConfig)({ + BaseClass: _RedisClientPool, + commands: commands_1.default, + createCommand: _RedisClientPool.#createCommand, + createModuleCommand: _RedisClientPool.#createModuleCommand, + createFunctionCommand: _RedisClientPool.#createFunctionCommand, + createScriptCommand: _RedisClientPool.#createScriptCommand, + config: clientOptions + }); + Pool.prototype.Multi = multi_command_1.default.extend(clientOptions); + _RedisClientPool.#SingleEntryCache.set(clientOptions, Pool); + } + return Object.create(new Pool(clientOptions, options2)); + } + // TODO: defaults + static #DEFAULTS = { + minimum: 1, + maximum: 100, + acquireTimeout: 3e3, + cleanupDelay: 3e3 + }; + #clientFactory; + #options; + #idleClients = new linked_list_1.SinglyLinkedList(); + /** + * The number of idle clients. + */ + get idleClients() { + return this._self.#idleClients.length; + } + #clientsInUse = new linked_list_1.DoublyLinkedList(); + /** + * The number of clients in use. + */ + get clientsInUse() { + return this._self.#clientsInUse.length; + } + /** + * The total number of clients in the pool (including connecting, idle, and in use). + */ + get totalClients() { + return this._self.#idleClients.length + this._self.#clientsInUse.length; + } + #tasksQueue = new linked_list_1.SinglyLinkedList(); + /** + * The number of tasks waiting for a client to become available. + */ + get tasksQueueLength() { + return this._self.#tasksQueue.length; + } + #isOpen = false; + /** + * Whether the pool is open (either connecting or connected). + */ + get isOpen() { + return this._self.#isOpen; + } + #isClosing = false; + /** + * Whether the pool is closing (*not* closed). + */ + get isClosing() { + return this._self.#isClosing; + } + #clientSideCache; + get clientSideCache() { + return this._self.#clientSideCache; + } + /** + * You are probably looking for {@link RedisClient.createPool `RedisClient.createPool`}, + * {@link RedisClientPool.fromClient `RedisClientPool.fromClient`}, + * or {@link RedisClientPool.fromOptions `RedisClientPool.fromOptions`}... + */ + constructor(clientOptions, options2) { + super(); + this.#options = { + ..._RedisClientPool.#DEFAULTS, + ...options2 + }; + if (options2?.clientSideCache) { + if (clientOptions === void 0) { + clientOptions = {}; + } + if (options2.clientSideCache instanceof cache_1.PooledClientSideCacheProvider) { + this.#clientSideCache = clientOptions.clientSideCache = options2.clientSideCache; + } else { + const cscConfig = options2.clientSideCache; + this.#clientSideCache = clientOptions.clientSideCache = new cache_1.BasicPooledClientSideCache(cscConfig); + } + } + this.#clientFactory = _1.default.factory(clientOptions).bind(void 0, clientOptions); + } + _self = this; + _commandOptions; + withCommandOptions(options2) { + const proxy = Object.create(this._self); + proxy._commandOptions = options2; + return proxy; + } + #commandOptionsProxy(key, value) { + const proxy = Object.create(this._self); + proxy._commandOptions = Object.create(this._commandOptions ?? null); + proxy._commandOptions[key] = value; + return proxy; + } + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping) { + return this._self.#commandOptionsProxy("typeMapping", typeMapping); + } + /** + * Override the `abortSignal` command option + */ + withAbortSignal(abortSignal) { + return this._self.#commandOptionsProxy("abortSignal", abortSignal); + } + /** + * Override the `asap` command option to `true` + * TODO: remove? + */ + asap() { + return this._self.#commandOptionsProxy("asap", true); + } + async connect() { + if (this._self.#isOpen) + return; + this._self.#isOpen = true; + const promises = []; + while (promises.length < this._self.#options.minimum) { + promises.push(this._self.#create()); + } + try { + await Promise.all(promises); + } catch (err) { + this.destroy(); + throw err; + } + return this; + } + async #create() { + const node = this._self.#clientsInUse.push(this._self.#clientFactory().on("error", (err) => this.emit("error", err))); + try { + const client = node.value; + await client.connect(); + } catch (err) { + this._self.#clientsInUse.remove(node); + throw err; + } + this._self.#returnClient(node); + } + execute(fn) { + return new Promise((resolve82, reject) => { + const client = this._self.#idleClients.shift(), { tail } = this._self.#tasksQueue; + if (!client) { + let timeout; + if (this._self.#options.acquireTimeout > 0) { + timeout = setTimeout(() => { + this._self.#tasksQueue.remove(task, tail); + reject(new errors_1.TimeoutError("Timeout waiting for a client")); + }, this._self.#options.acquireTimeout); + } + const task = this._self.#tasksQueue.push({ + timeout, + // @ts-ignore + resolve: resolve82, + reject, + fn + }); + if (this.totalClients < this._self.#options.maximum) { + this._self.#create(); + } + return; + } + const node = this._self.#clientsInUse.push(client); + this._self.#executeTask(node, resolve82, reject, fn); + }); + } + #executeTask(node, resolve82, reject, fn) { + const result = fn(node.value); + if (result instanceof Promise) { + result.then(resolve82, reject).finally(() => this.#returnClient(node)); + } else { + resolve82(result); + this.#returnClient(node); + } + } + #returnClient(node) { + const task = this.#tasksQueue.shift(); + if (task) { + clearTimeout(task.timeout); + this.#executeTask(node, task.resolve, task.reject, task.fn); + return; + } + this.#clientsInUse.remove(node); + this.#idleClients.push(node.value); + this.#scheduleCleanup(); + } + cleanupTimeout; + #scheduleCleanup() { + if (this.totalClients <= this.#options.minimum) + return; + clearTimeout(this.cleanupTimeout); + this.cleanupTimeout = setTimeout(() => this.#cleanup(), this.#options.cleanupDelay); + } + #cleanup() { + const toDestroy = Math.min(this.#idleClients.length, this.totalClients - this.#options.minimum); + for (let i2 = 0; i2 < toDestroy; i2++) { + const client = this.#idleClients.shift(); + client.destroy(); + } + } + sendCommand(args, options2) { + return this.execute((client) => client.sendCommand(args, options2)); + } + MULTI() { + return new this.Multi((commands, selectedDB) => this.execute((client) => client._executeMulti(commands, selectedDB)), (commands) => this.execute((client) => client._executePipeline(commands)), this._commandOptions?.typeMapping); + } + multi = this.MULTI; + async close() { + if (this._self.#isClosing) + return; + if (!this._self.#isOpen) + return; + this._self.#isClosing = true; + try { + const promises = []; + for (const client of this._self.#idleClients) { + promises.push(client.close()); + } + for (const client of this._self.#clientsInUse) { + promises.push(client.close()); + } + await Promise.all(promises); + this.#clientSideCache?.onPoolClose(); + this._self.#idleClients.reset(); + this._self.#clientsInUse.reset(); + } catch (err) { + } finally { + this._self.#isClosing = false; + } + } + destroy() { + for (const client of this._self.#idleClients) { + client.destroy(); + } + this._self.#idleClients.reset(); + for (const client of this._self.#clientsInUse) { + client.destroy(); + } + this._self.#clientSideCache?.onPoolClose(); + this._self.#clientsInUse.reset(); + this._self.#isOpen = false; + } + }; + exports2.RedisClientPool = RedisClientPool; + } +}); +var require_package2 = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/package.json"(exports2, module14) { + module14.exports = { + name: "@redis/client", + version: "5.9.0-beta.3", + license: "MIT", + main: "./dist/index.js", + types: "./dist/index.d.ts", + files: [ + "dist/", + "!dist/tsconfig.tsbuildinfo" + ], + scripts: { + test: "nyc -r text-summary -r lcov mocha -r tsx './lib/**/*.spec.ts'", + release: "release-it" }, - "video/x-msvideo": { - source: "apache", - extensions: ["avi"] + dependencies: { + "cluster-key-slot": "1.1.2" }, - "video/x-sgi-movie": { - source: "apache", - extensions: ["movie"] + devDependencies: { + "@redis/test-utils": "*", + "@types/sinon": "^17.0.3", + sinon: "^17.0.1" }, - "video/x-smv": { - source: "apache", - extensions: ["smv"] + engines: { + node: ">= 18" }, - "x-conference/x-cooltalk": { - source: "apache", - extensions: ["ice"] + repository: { + type: "git", + url: "git://github.com/redis/node-redis.git" }, - "x-shader/x-fragment": { - compressible: true + bugs: { + url: "https://github.com/redis/node-redis/issues" }, - "x-shader/x-vertex": { - compressible: true + homepage: "https://github.com/redis/node-redis/tree/master/packages/client", + keywords: [ + "redis" + ] + }; + } +}); +var require_client = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/client/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + var _a2; + Object.defineProperty(exports2, "__esModule", { value: true }); + var commands_1 = __importDefault(require_commands()); + var socket_1 = __importDefault(require_socket()); + var authx_1 = require_authx(); + var commands_queue_1 = __importDefault(require_commands_queue()); + var node_events_1 = __require2("node:events"); + var commander_1 = require_commander(); + var errors_1 = require_errors(); + var node_url_1 = __require2("node:url"); + var pub_sub_1 = require_pub_sub(); + var multi_command_1 = __importDefault(require_multi_command2()); + var HELLO_1 = __importDefault(require_HELLO()); + var legacy_mode_1 = require_legacy_mode(); + var pool_1 = require_pool(); + var generic_transformers_1 = require_generic_transformers(); + var cache_1 = require_cache(); + var parser_1 = require_parser(); + var single_entry_cache_1 = __importDefault(require_single_entry_cache()); + var package_json_1 = require_package2(); + var enterprise_maintenance_manager_1 = __importDefault(require_enterprise_maintenance_manager()); + var RedisClient = class extends node_events_1.EventEmitter { + static #createCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this._self._executeCommand(command2, parser3, this._commandOptions, transformReply); + }; + } + static #createModuleCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this._self._executeCommand(command2, parser3, this._self._commandOptions, transformReply); + }; + } + static #createFunctionCommand(name, fn, resp) { + const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); + const transformReply = (0, commander_1.getTransformReply)(fn, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + fn.parseCommand(parser3, ...args); + return this._self._executeCommand(fn, parser3, this._self._commandOptions, transformReply); + }; + } + static #createScriptCommand(script, resp) { + const prefix = (0, commander_1.scriptArgumentsPrefix)(script); + const transformReply = (0, commander_1.getTransformReply)(script, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + script.parseCommand(parser3, ...args); + return this._executeScript(script, parser3, this._commandOptions, transformReply); + }; + } + static #SingleEntryCache = new single_entry_cache_1.default(); + static factory(config2) { + let Client = _a2.#SingleEntryCache.get(config2); + if (!Client) { + Client = (0, commander_1.attachConfig)({ + BaseClass: _a2, + commands: commands_1.default, + createCommand: _a2.#createCommand, + createModuleCommand: _a2.#createModuleCommand, + createFunctionCommand: _a2.#createFunctionCommand, + createScriptCommand: _a2.#createScriptCommand, + config: config2 + }); + Client.prototype.Multi = multi_command_1.default.extend(config2); + _a2.#SingleEntryCache.set(config2, Client); + } + return (options2) => { + return Object.create(new Client(options2)); + }; + } + static create(options2) { + return _a2.factory(options2)(options2); + } + static parseOptions(options2) { + if (options2?.url) { + const parsed = _a2.parseURL(options2.url); + if (options2.socket) { + if (options2.socket.tls !== void 0 && options2.socket.tls !== parsed.socket.tls) { + throw new TypeError(`tls socket option is set to ${options2.socket.tls} which is mismatch with protocol or the URL ${options2.url} passed`); + } + parsed.socket = Object.assign(options2.socket, parsed.socket); + } + Object.assign(options2, parsed); + } + return options2; + } + static parseURL(url2) { + const { hostname: hostname2, port, protocol, username, password, pathname } = new node_url_1.URL(url2), parsed = { + socket: { + host: hostname2, + tls: false + } + }; + if (protocol !== "redis:" && protocol !== "rediss:") { + throw new TypeError("Invalid protocol"); + } + parsed.socket.tls = protocol === "rediss:"; + if (port) { + parsed.socket.port = Number(port); + } + if (username) { + parsed.username = decodeURIComponent(username); + } + if (password) { + parsed.password = decodeURIComponent(password); + } + if (username || password) { + parsed.credentialsProvider = { + type: "async-credentials-provider", + credentials: async () => ({ + username: username ? decodeURIComponent(username) : void 0, + password: password ? decodeURIComponent(password) : void 0 + }) + }; + } + if (pathname.length > 1) { + const database = Number(pathname.substring(1)); + if (isNaN(database)) { + throw new TypeError("Invalid pathname"); + } + parsed.database = database; + } + return parsed; + } + #options; + #socket; + #queue; + #selectedDB = 0; + #monitorCallback; + _self = this; + _commandOptions; + // flag used to annotate that the client + // was in a watch transaction when + // a topology change occured + #dirtyWatch; + #watchEpoch; + #clientSideCache; + #credentialsSubscription = null; + // Flag used to pause writing to the socket during maintenance windows. + // When true, prevents new commands from being written while waiting for: + // 1. New socket to be ready after maintenance redirect + // 2. In-flight commands on the old socket to complete + #paused = false; + get clientSideCache() { + return this._self.#clientSideCache; + } + get options() { + return this._self.#options; + } + get isOpen() { + return this._self.#socket.isOpen; + } + get isReady() { + return this._self.#socket.isReady; + } + get isPubSubActive() { + return this._self.#queue.isPubSubActive; + } + get socketEpoch() { + return this._self.#socket.socketEpoch; + } + get isWatching() { + return this._self.#watchEpoch !== void 0; + } + /** + * Indicates whether the client's WATCH command has been invalidated by a topology change. + * When this returns true, any transaction using WATCH will fail with a WatchError. + * @returns true if the watched keys have been modified, false otherwise + */ + get isDirtyWatch() { + return this._self.#dirtyWatch !== void 0; + } + /** + * Marks the client's WATCH command as invalidated due to a topology change. + * This will cause any subsequent EXEC in a transaction to fail with a WatchError. + * @param msg - The error message explaining why the WATCH is dirty + */ + setDirtyWatch(msg) { + this._self.#dirtyWatch = msg; + } + constructor(options2) { + super(); + this.#validateOptions(options2); + this.#options = this.#initiateOptions(options2); + this.#queue = this.#initiateQueue(); + this.#socket = this.#initiateSocket(); + if (this.#options.maintNotifications !== "disabled") { + new enterprise_maintenance_manager_1.default(this.#queue, this, this.#options); + } + ; + if (this.#options.clientSideCache) { + if (this.#options.clientSideCache instanceof cache_1.ClientSideCacheProvider) { + this.#clientSideCache = this.#options.clientSideCache; + } else { + const cscConfig = this.#options.clientSideCache; + this.#clientSideCache = new cache_1.BasicClientSideCache(cscConfig); + } + this.#queue.addPushHandler((push) => { + if (push[0].toString() !== "invalidate") + return false; + if (push[1] !== null) { + for (const key of push[1]) { + this.#clientSideCache?.invalidate(key); + } + } else { + this.#clientSideCache?.invalidate(null); + } + return true; + }); + } else if (options2?.emitInvalidate) { + this.#queue.addPushHandler((push) => { + if (push[0].toString() !== "invalidate") + return false; + if (push[1] !== null) { + for (const key of push[1]) { + this.emit("invalidate", key); + } + } else { + this.emit("invalidate", null); + } + return true; + }); + } } - }; - } -}); -var require_lib19 = __commonJS({ - "node_modules/.deno/@hapi+mimos@7.0.1/node_modules/@hapi/mimos/lib/index.js"(exports2) { - "use strict"; - var Path = __require2("path"); - var Hoek = require_lib(); - var MimeDb = require_db(); - var internals = { - compressibleRx: /^text\/|\+json$|\+text$|\+xml$/ - }; - exports2.MimosEntry = class { - constructor(type, mime) { - this.type = type; - this.source = "mime-db"; - this.extensions = []; - this.compressible = void 0; - Object.assign(this, mime); - if (this.compressible === void 0) { - this.compressible = internals.compressibleRx.test(type); + #validateOptions(options2) { + if (options2?.clientSideCache && options2?.RESP !== 3) { + throw new Error("Client Side Caching is only supported with RESP3"); + } + if (options2?.emitInvalidate && options2?.RESP !== 3) { + throw new Error("emitInvalidate is only supported with RESP3"); + } + if (options2?.clientSideCache && options2?.emitInvalidate) { + throw new Error("emitInvalidate is not supported (or necessary) when clientSideCache is enabled"); + } + if (options2?.maintNotifications && options2?.maintNotifications !== "disabled" && options2?.RESP !== 3) { + throw new Error("Graceful Maintenance is only supported with RESP3"); + } + } + #initiateOptions(options2 = {}) { + if (!options2.credentialsProvider && (options2.username || options2.password)) { + options2.credentialsProvider = { + type: "async-credentials-provider", + credentials: async () => ({ + username: options2.username, + password: options2.password + }) + }; + } + if (options2.database) { + this._self.#selectedDB = options2.database; + } + if (options2.commandOptions) { + this._commandOptions = options2.commandOptions; + } + if (options2.maintNotifications !== "disabled") { + enterprise_maintenance_manager_1.default.setupDefaultMaintOptions(options2); + } + if (options2.url) { + const parsedOptions = _a2.parseOptions(options2); + if (parsedOptions?.database) { + this._self.#selectedDB = parsedOptions.database; + } + return parsedOptions; + } + return options2; + } + #initiateQueue() { + return new commands_queue_1.default(this.#options.RESP ?? 2, this.#options.commandsQueueMaxLength, (channel, listeners) => this.emit("sharded-channel-moved", channel, listeners)); + } + /** + * @param credentials + */ + reAuthenticate = async (credentials) => { + if (!(this.isPubSubActive && !this.#options.RESP)) { + await this.sendCommand((0, generic_transformers_1.parseArgs)(commands_1.default.AUTH, { + username: credentials.username, + password: credentials.password ?? "" + })); + } + }; + #subscribeForStreamingCredentials(cp) { + return cp.subscribe({ + onNext: (credentials) => { + this.reAuthenticate(credentials).catch((error2) => { + const errorMessage = error2 instanceof Error ? error2.message : String(error2); + cp.onReAuthenticationError(new authx_1.CredentialsError(errorMessage)); + }); + }, + onError: (e2) => { + const errorMessage = `Error from streaming credentials provider: ${e2.message}`; + cp.onReAuthenticationError(new authx_1.UnableToObtainNewCredentialsError(errorMessage)); + } + }); + } + async #handshake(chainId, asap) { + const promises = []; + const commandsWithErrorHandlers = await this.#getHandshakeCommands(); + if (asap) + commandsWithErrorHandlers.reverse(); + for (const { cmd, errorHandler: errorHandler2 } of commandsWithErrorHandlers) { + promises.push(this.#queue.addCommand(cmd, { + chainId, + asap + }).catch(errorHandler2)); + } + return promises; + } + async #getHandshakeCommands() { + const commands = []; + const cp = this.#options.credentialsProvider; + if (this.#options.RESP) { + const hello = {}; + if (cp && cp.type === "async-credentials-provider") { + const credentials = await cp.credentials(); + if (credentials.password) { + hello.AUTH = { + username: credentials.username ?? "default", + password: credentials.password + }; + } + } + if (cp && cp.type === "streaming-credentials-provider") { + const [credentials, disposable] = await this.#subscribeForStreamingCredentials(cp); + this.#credentialsSubscription = disposable; + if (credentials.password) { + hello.AUTH = { + username: credentials.username ?? "default", + password: credentials.password + }; + } + } + if (this.#options.name) { + hello.SETNAME = this.#options.name; + } + commands.push({ cmd: (0, generic_transformers_1.parseArgs)(HELLO_1.default, this.#options.RESP, hello) }); + } else { + if (cp && cp.type === "async-credentials-provider") { + const credentials = await cp.credentials(); + if (credentials.username || credentials.password) { + commands.push({ + cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.AUTH, { + username: credentials.username, + password: credentials.password ?? "" + }) + }); + } + } + if (cp && cp.type === "streaming-credentials-provider") { + const [credentials, disposable] = await this.#subscribeForStreamingCredentials(cp); + this.#credentialsSubscription = disposable; + if (credentials.username || credentials.password) { + commands.push({ + cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.AUTH, { + username: credentials.username, + password: credentials.password ?? "" + }) + }); + } + } + if (this.#options.name) { + commands.push({ + cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.CLIENT_SETNAME, this.#options.name) + }); + } + } + if (this.#selectedDB !== 0) { + commands.push({ cmd: ["SELECT", this.#selectedDB.toString()] }); + } + if (this.#options.readonly) { + commands.push({ cmd: (0, generic_transformers_1.parseArgs)(commands_1.default.READONLY) }); + } + if (!this.#options.disableClientInfo) { + commands.push({ + cmd: ["CLIENT", "SETINFO", "LIB-VER", package_json_1.version], + errorHandler: () => { + } + }); + commands.push({ + cmd: [ + "CLIENT", + "SETINFO", + "LIB-NAME", + this.#options.clientInfoTag ? `node-redis(${this.#options.clientInfoTag})` : "node-redis" + ], + errorHandler: () => { + } + }); + } + if (this.#clientSideCache) { + commands.push({ cmd: this.#clientSideCache.trackingOn() }); + } + if (this.#options?.emitInvalidate) { + commands.push({ cmd: ["CLIENT", "TRACKING", "ON"] }); + } + const maintenanceHandshakeCmd = await enterprise_maintenance_manager_1.default.getHandshakeCommand(this.#options); + if (maintenanceHandshakeCmd) { + commands.push(maintenanceHandshakeCmd); + } + ; + return commands; + } + #attachListeners(socket) { + socket.on("data", (chunk) => { + try { + this.#queue.decoder.write(chunk); + } catch (err) { + this.#queue.resetDecoder(); + this.emit("error", err); + } + }).on("error", (err) => { + this.emit("error", err); + this.#clientSideCache?.onError(); + if (this.#socket.isOpen && !this.#options.disableOfflineQueue) { + this.#queue.flushWaitingForReply(err); + } else { + this.#queue.flushAll(err); + } + }).on("connect", () => this.emit("connect")).on("ready", () => { + this.emit("ready"); + this.#setPingTimer(); + this.#maybeScheduleWrite(); + }).on("reconnecting", () => this.emit("reconnecting")).on("drain", () => this.#maybeScheduleWrite()).on("end", () => this.emit("end")); + } + #initiateSocket() { + const socketInitiator = async () => { + const promises = [], chainId = Symbol("Socket Initiator"); + const resubscribePromise = this.#queue.resubscribe(chainId); + resubscribePromise?.catch((error2) => { + if (error2.message && error2.message.startsWith("MOVED")) { + this.emit("__MOVED", this._self.#queue.removeAllPubSubListeners()); + } + }); + if (resubscribePromise) { + promises.push(resubscribePromise); + } + if (this.#monitorCallback) { + promises.push(this.#queue.monitor(this.#monitorCallback, { + typeMapping: this._commandOptions?.typeMapping, + chainId, + asap: true + })); + } + promises.push(...await this.#handshake(chainId, true)); + if (promises.length) { + this.#write(); + return Promise.all(promises); + } + }; + const socket = new socket_1.default(socketInitiator, this.#options.socket); + this.#attachListeners(socket); + return socket; + } + #pingTimer; + #setPingTimer() { + if (!this.#options.pingInterval || !this.#socket.isReady) + return; + clearTimeout(this.#pingTimer); + this.#pingTimer = setTimeout(() => { + if (!this.#socket.isReady) + return; + this.sendCommand(["PING"]).then((reply) => this.emit("ping-interval", reply)).catch((err) => this.emit("error", err)).finally(() => this.#setPingTimer()); + }, this.#options.pingInterval); + } + withCommandOptions(options2) { + const proxy = Object.create(this._self); + proxy._commandOptions = options2; + return proxy; + } + _commandOptionsProxy(key, value) { + const proxy = Object.create(this._self); + proxy._commandOptions = Object.create(this._commandOptions ?? null); + proxy._commandOptions[key] = value; + return proxy; + } + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping) { + return this._commandOptionsProxy("typeMapping", typeMapping); + } + /** + * Override the `abortSignal` command option + */ + withAbortSignal(abortSignal) { + return this._commandOptionsProxy("abortSignal", abortSignal); + } + /** + * Override the `asap` command option to `true` + */ + asap() { + return this._commandOptionsProxy("asap", true); + } + /** + * Create the "legacy" (v3/callback) interface + */ + legacy() { + return new legacy_mode_1.RedisLegacyClient(this); + } + /** + * Create {@link RedisClientPool `RedisClientPool`} using this client as a prototype + */ + createPool(options2) { + return pool_1.RedisClientPool.create(this._self.#options, options2); + } + duplicate(overrides) { + return new (Object.getPrototypeOf(this)).constructor({ + ...this._self.#options, + commandOptions: this._commandOptions, + ...overrides + }); + } + async connect() { + await this._self.#socket.connect(); + return this; + } + /** + * @internal + */ + _ejectSocket() { + const socket = this._self.#socket; + this._self.#socket = null; + socket.removeAllListeners(); + return socket; + } + /** + * @internal + */ + _insertSocket(socket) { + if (this._self.#socket) { + this._self._ejectSocket().destroy(); + } + this._self.#socket = socket; + this._self.#attachListeners(this._self.#socket); + } + /** + * @internal + */ + _maintenanceUpdate(update) { + this._self.#socket.setMaintenanceTimeout(update.relaxedSocketTimeout); + this._self.#queue.setMaintenanceCommandTimeout(update.relaxedCommandTimeout); + } + /** + * @internal + */ + _pause() { + this._self.#paused = true; + } + /** + * @internal + */ + _unpause() { + this._self.#paused = false; + this._self.#maybeScheduleWrite(); + } + /** + * @internal + */ + async _executeCommand(command2, parser3, commandOptions, transformReply) { + const csc = this._self.#clientSideCache; + const defaultTypeMapping = this._self.#options.commandOptions === commandOptions; + const fn = () => { + return this.sendCommand(parser3.redisArgs, commandOptions); + }; + if (csc && command2.CACHEABLE && defaultTypeMapping) { + return await csc.handleCache(this._self, parser3, fn, transformReply, commandOptions?.typeMapping); + } else { + const reply = await fn(); + if (transformReply) { + return transformReply(reply, parser3.preserve, commandOptions?.typeMapping); + } + return reply; + } + } + /** + * @internal + */ + async _executeScript(script, parser3, options2, transformReply) { + const args = parser3.redisArgs; + let reply; + try { + reply = await this.sendCommand(args, options2); + } catch (err) { + if (!err?.message?.startsWith?.("NOSCRIPT")) + throw err; + args[0] = "EVAL"; + args[1] = script.SCRIPT; + reply = await this.sendCommand(args, options2); + } + return transformReply ? transformReply(reply, parser3.preserve, options2?.typeMapping) : reply; + } + sendCommand(args, options2) { + if (!this._self.#socket.isOpen) { + return Promise.reject(new errors_1.ClientClosedError()); + } else if (!this._self.#socket.isReady && this._self.#options.disableOfflineQueue) { + return Promise.reject(new errors_1.ClientOfflineError()); + } + const opts = { + ...this._self._commandOptions, + ...options2 + }; + const promise = this._self.#queue.addCommand(args, opts); + this._self.#scheduleWrite(); + return promise; + } + async SELECT(db2) { + await this.sendCommand(["SELECT", db2.toString()]); + this._self.#selectedDB = db2; + } + select = this.SELECT; + #pubSubCommand(promise) { + if (promise === void 0) + return Promise.resolve(); + this.#scheduleWrite(); + return promise; + } + SUBSCRIBE(channels, listener, bufferMode) { + return this._self.#pubSubCommand(this._self.#queue.subscribe(pub_sub_1.PUBSUB_TYPE.CHANNELS, channels, listener, bufferMode)); + } + subscribe = this.SUBSCRIBE; + UNSUBSCRIBE(channels, listener, bufferMode) { + return this._self.#pubSubCommand(this._self.#queue.unsubscribe(pub_sub_1.PUBSUB_TYPE.CHANNELS, channels, listener, bufferMode)); + } + unsubscribe = this.UNSUBSCRIBE; + PSUBSCRIBE(patterns, listener, bufferMode) { + return this._self.#pubSubCommand(this._self.#queue.subscribe(pub_sub_1.PUBSUB_TYPE.PATTERNS, patterns, listener, bufferMode)); + } + pSubscribe = this.PSUBSCRIBE; + PUNSUBSCRIBE(patterns, listener, bufferMode) { + return this._self.#pubSubCommand(this._self.#queue.unsubscribe(pub_sub_1.PUBSUB_TYPE.PATTERNS, patterns, listener, bufferMode)); + } + pUnsubscribe = this.PUNSUBSCRIBE; + SSUBSCRIBE(channels, listener, bufferMode) { + return this._self.#pubSubCommand(this._self.#queue.subscribe(pub_sub_1.PUBSUB_TYPE.SHARDED, channels, listener, bufferMode)); + } + sSubscribe = this.SSUBSCRIBE; + SUNSUBSCRIBE(channels, listener, bufferMode) { + return this._self.#pubSubCommand(this._self.#queue.unsubscribe(pub_sub_1.PUBSUB_TYPE.SHARDED, channels, listener, bufferMode)); + } + sUnsubscribe = this.SUNSUBSCRIBE; + async WATCH(key) { + const reply = await this._self.sendCommand((0, generic_transformers_1.pushVariadicArguments)(["WATCH"], key)); + this._self.#watchEpoch ??= this._self.socketEpoch; + return reply; + } + watch = this.WATCH; + async UNWATCH() { + const reply = await this._self.sendCommand(["UNWATCH"]); + this._self.#watchEpoch = void 0; + return reply; + } + unwatch = this.UNWATCH; + getPubSubListeners(type) { + return this._self.#queue.getPubSubListeners(type); + } + extendPubSubChannelListeners(type, channel, listeners) { + return this._self.#pubSubCommand(this._self.#queue.extendPubSubChannelListeners(type, channel, listeners)); + } + extendPubSubListeners(type, listeners) { + return this._self.#pubSubCommand(this._self.#queue.extendPubSubListeners(type, listeners)); + } + #write() { + if (this.#paused) { + return; + } + this.#socket.write(this.#queue.commandsToWrite()); + } + #scheduledWrite; + #scheduleWrite() { + if (!this.#socket.isReady || this.#scheduledWrite) + return; + this.#scheduledWrite = setImmediate(() => { + this.#write(); + this.#scheduledWrite = void 0; + }); + } + #maybeScheduleWrite() { + if (!this.#queue.isWaitingToWrite()) + return; + this.#scheduleWrite(); + } + /** + * @internal + */ + async _executePipeline(commands, selectedDB) { + if (!this._self.#socket.isOpen) { + return Promise.reject(new errors_1.ClientClosedError()); + } + const chainId = Symbol("Pipeline Chain"), promise = Promise.all(commands.map(({ args }) => this._self.#queue.addCommand(args, { + chainId, + typeMapping: this._commandOptions?.typeMapping + }))); + this._self.#scheduleWrite(); + const result = await promise; + if (selectedDB !== void 0) { + this._self.#selectedDB = selectedDB; + } + return result; + } + /** + * @internal + */ + async _executeMulti(commands, selectedDB) { + const dirtyWatch = this._self.#dirtyWatch; + this._self.#dirtyWatch = void 0; + const watchEpoch = this._self.#watchEpoch; + this._self.#watchEpoch = void 0; + if (!this._self.#socket.isOpen) { + throw new errors_1.ClientClosedError(); + } + if (dirtyWatch) { + throw new errors_1.WatchError(dirtyWatch); + } + if (watchEpoch && watchEpoch !== this._self.socketEpoch) { + throw new errors_1.WatchError("Client reconnected after WATCH"); + } + const typeMapping = this._commandOptions?.typeMapping; + const chainId = Symbol("MULTI Chain"); + const promises = [ + this._self.#queue.addCommand(["MULTI"], { chainId }) + ]; + for (const { args } of commands) { + promises.push(this._self.#queue.addCommand(args, { + chainId, + typeMapping + })); } - } - }; - internals.insertEntry = function(type, entry, db2) { - db2.byType.set(type, entry); - for (const ext of entry.extensions) { - db2.byExtension.set(ext, entry); - if (ext.length > db2.maxExtLength) { - db2.maxExtLength = ext.length; + promises.push(this._self.#queue.addCommand(["EXEC"], { chainId })); + this._self.#scheduleWrite(); + const results = await Promise.all(promises), execResult = results[results.length - 1]; + if (execResult === null) { + throw new errors_1.WatchError(); + } + if (selectedDB !== void 0) { + this._self.#selectedDB = selectedDB; } + return execResult; } - }; - internals.compile = function(mimedb) { - const db2 = { - byType: /* @__PURE__ */ new Map(), - byExtension: /* @__PURE__ */ new Map(), - maxExtLength: 0 - }; - for (const type in mimedb) { - const entry = new exports2.MimosEntry(type, mimedb[type]); - internals.insertEntry(type, entry, db2); + MULTI() { + return new this.Multi(this._executeMulti.bind(this), this._executePipeline.bind(this), this._commandOptions?.typeMapping); } - return db2; - }; - internals.getTypePart = function(fulltype) { - const splitAt = fulltype.indexOf(";"); - return splitAt === -1 ? fulltype : fulltype.slice(0, splitAt); - }; - internals.applyPredicate = function(mime) { - if (mime.predicate) { - return mime.predicate(Hoek.clone(mime)); + multi = this.MULTI; + async *scanIterator(options2) { + let cursor = options2?.cursor ?? "0"; + do { + const reply = await this.scan(cursor, options2); + cursor = reply.cursor; + yield reply.keys; + } while (cursor !== "0"); } - return mime; - }; - exports2.Mimos = class Mimos { - #db = internals.base; - constructor(options2 = {}) { - if (options2.override) { - Hoek.assert(typeof options2.override === "object", "overrides option must be an object"); - this.#db = { - ...this.#db, - byType: new Map(this.#db.byType), - byExtension: new Map(this.#db.byExtension) - }; - for (const type in options2.override) { - const override = options2.override[type]; - Hoek.assert(!override.predicate || typeof override.predicate === "function", "predicate option must be a function"); - const from3 = this.#db.byType.get(type); - const baseEntry = from3 ? Hoek.applyToDefaults(from3, override) : override; - const entry = new exports2.MimosEntry(type, baseEntry); - internals.insertEntry(type, entry, this.#db); - } - } - } - path(path8) { - const extension = Path.extname(path8).slice(1).toLowerCase(); - const mime = this.#db.byExtension.get(extension) ?? {}; - return internals.applyPredicate(mime); - } - type(type) { - type = internals.getTypePart(type); - let mime = this.#db.byType.get(type); - if (!mime) { - type = type.trim().toLowerCase(); - mime = this.#db.byType.get(type); - } - if (!mime) { - mime = new exports2.MimosEntry(type, { - source: "mimos" - }); - internals.insertEntry(type, mime, this.#db); - return mime; - } - return internals.applyPredicate(mime); + async *hScanIterator(key, options2) { + let cursor = options2?.cursor ?? "0"; + do { + const reply = await this.hScan(key, cursor, options2); + cursor = reply.cursor; + yield reply.entries; + } while (cursor !== "0"); } - }; - internals.base = internals.compile(MimeDb); - } -}); -var require_lib20 = __commonJS({ - "node_modules/.deno/@hapi+bourne@3.0.0/node_modules/@hapi/bourne/lib/index.js"(exports2) { - "use strict"; - var internals = { - suspectRx: /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*\:/ - }; - exports2.parse = function(text, ...args) { - const firstOptions = typeof args[0] === "object" && args[0]; - const reviver = args.length > 1 || !firstOptions ? args[0] : void 0; - const options2 = args.length > 1 && args[1] || firstOptions || {}; - const obj = JSON.parse(text, reviver); - if (options2.protoAction === "ignore") { - return obj; + async *hScanValuesIterator(key, options2) { + let cursor = options2?.cursor ?? "0"; + do { + const reply = await this.hScanNoValues(key, cursor, options2); + cursor = reply.cursor; + yield reply.fields; + } while (cursor !== "0"); } - if (!obj || typeof obj !== "object") { - return obj; + async *hScanNoValuesIterator(key, options2) { + let cursor = options2?.cursor ?? "0"; + do { + const reply = await this.hScanNoValues(key, cursor, options2); + cursor = reply.cursor; + yield reply.fields; + } while (cursor !== "0"); } - if (!text.match(internals.suspectRx)) { - return obj; + async *sScanIterator(key, options2) { + let cursor = options2?.cursor ?? "0"; + do { + const reply = await this.sScan(key, cursor, options2); + cursor = reply.cursor; + yield reply.members; + } while (cursor !== "0"); } - exports2.scan(obj, options2); - return obj; - }; - exports2.scan = function(obj, options2 = {}) { - let next = [obj]; - while (next.length) { - const nodes = next; - next = []; - for (const node of nodes) { - if (Object.prototype.hasOwnProperty.call(node, "__proto__")) { - if (options2.protoAction !== "remove") { - throw new SyntaxError("Object contains forbidden prototype property"); - } - delete node.__proto__; - } - for (const key in node) { - const value = node[key]; - if (value && typeof value === "object") { - next.push(node[key]); - } - } - } + async *zScanIterator(key, options2) { + let cursor = options2?.cursor ?? "0"; + do { + const reply = await this.zScan(key, cursor, options2); + cursor = reply.cursor; + yield reply.members; + } while (cursor !== "0"); } - }; - exports2.safeParse = function(text, reviver) { - try { - return exports2.parse(text, reviver); - } catch (ignoreError) { - return null; + async MONITOR(callback) { + const promise = this._self.#queue.monitor(callback, { + typeMapping: this._commandOptions?.typeMapping + }); + this._self.#scheduleWrite(); + await promise; + this._self.#monitorCallback = callback; } - }; - } -}); -var require_lib21 = __commonJS({ - "node_modules/.deno/@hapi+cryptiles@6.0.1/node_modules/@hapi/cryptiles/lib/index.js"(exports2) { - "use strict"; - var Crypto = __require2("crypto"); - var Boom5 = require_lib2(); - var internals = {}; - exports2.randomString = function(size) { - const buffer = exports2.randomBits((size + 1) * 6); - const string3 = buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, ""); - return string3.slice(0, size); - }; - exports2.randomAlphanumString = function(size) { - let result = ""; - while (result.length < size) { - const buffer = exports2.randomBits((size + 1) * 6); - result += buffer.toString("base64").replace(/[^a-zA-Z0-9]/g, ""); + monitor = this.MONITOR; + /** + * Reset the client to its default state (i.e. stop PubSub, stop monitoring, select default DB, etc.) + */ + async reset() { + const chainId = Symbol("Reset Chain"), promises = [this._self.#queue.reset(chainId)], selectedDB = this._self.#options?.database ?? 0; + this._self.#credentialsSubscription?.dispose(); + this._self.#credentialsSubscription = null; + promises.push(...await this._self.#handshake(chainId, false)); + this._self.#scheduleWrite(); + await Promise.all(promises); + this._self.#selectedDB = selectedDB; + this._self.#monitorCallback = void 0; + this._self.#dirtyWatch = void 0; + this._self.#watchEpoch = void 0; } - return result.slice(0, size); - }; - exports2.randomDigits = function(size) { - const digits = []; - let buffer = internals.random(size * 2); - let pos = 0; - while (digits.length < size) { - if (pos >= buffer.length) { - buffer = internals.random(size * 2); - pos = 0; + /** + * If the client has state, reset it. + * An internal function to be used by wrapper class such as `RedisClientPool`. + * @internal + */ + resetIfDirty() { + let shouldReset = false; + if (this._self.#selectedDB !== (this._self.#options?.database ?? 0)) { + console.warn("Returning a client with a different selected DB"); + shouldReset = true; + } + if (this._self.#monitorCallback) { + console.warn("Returning a client with active MONITOR"); + shouldReset = true; + } + if (this._self.#queue.isPubSubActive) { + console.warn("Returning a client with active PubSub"); + shouldReset = true; + } + if (this._self.#dirtyWatch || this._self.#watchEpoch) { + console.warn("Returning a client with active WATCH"); + shouldReset = true; } - if (buffer[pos] < 250) { - digits.push(buffer[pos] % 10); + if (shouldReset) { + return this.reset(); } - ++pos; } - return digits.join(""); - }; - exports2.randomBits = function(bits) { - if (!bits || bits < 0) { - throw Boom5.internal("Invalid random bits count"); + /** + * @deprecated use .close instead + */ + QUIT() { + this._self.#credentialsSubscription?.dispose(); + this._self.#credentialsSubscription = null; + return this._self.#socket.quit(async () => { + clearTimeout(this._self.#pingTimer); + const quitPromise = this._self.#queue.addCommand(["QUIT"]); + this._self.#scheduleWrite(); + return quitPromise; + }); } - const bytes = Math.ceil(bits / 8); - return internals.random(bytes); - }; - exports2.fixedTimeComparison = function(a, b) { - try { - return Crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)); - } catch (err) { - return false; + quit = this.QUIT; + /** + * @deprecated use .destroy instead + */ + disconnect() { + return Promise.resolve(this.destroy()); } - }; - internals.random = function(bytes) { - try { - return Crypto.randomBytes(bytes); - } catch (err) { - throw Boom5.internal("Failed generating random bits: " + err.message); - } - }; - } -}); -var require_decoder2 = __commonJS({ - "node_modules/.deno/@hapi+b64@6.0.1/node_modules/@hapi/b64/lib/decoder.js"(exports2) { - "use strict"; - var Stream = __require2("stream"); - var internals = { - decodeChars: [ - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - 62, - -1, - -1, - -1, - 63, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - -1, - -1, - -1, - -1, - -1, - -1, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - -1, - -1, - -1, - -1, - -1 - ] - }; - exports2.decode = function(buffer) { - const decodeChars = internals.decodeChars; - const len = buffer.length; - const allocated = Math.ceil(len / 4) * 3; - const result = Buffer.alloc(allocated); - let c1; - let c2; - let c3; - let c4; - let j = 0; - for (let i2 = 0; i2 < len; ) { - do { - c1 = decodeChars[buffer[i2++] & 255]; - } while (i2 < len && c1 === -1); - if (c1 === -1) { - break; - } - do { - c2 = decodeChars[buffer[i2++] & 255]; - } while (i2 < len && c2 === -1); - if (c2 === -1) { - break; - } - result[j++] = c1 << 2 | (c2 & 48) >> 4; - do { - c3 = buffer[i2++] & 255; - if (c3 === 61) { - return result.slice(0, j); + /** + * Close the client. Wait for pending commands. + */ + close() { + return new Promise((resolve82) => { + clearTimeout(this._self.#pingTimer); + this._self.#socket.close(); + this._self.#clientSideCache?.onClose(); + if (this._self.#queue.isEmpty()) { + this._self.#socket.destroySocket(); + return resolve82(); } - c3 = decodeChars[c3]; - } while (i2 < len && c3 === -1); - if (c3 === -1) { - break; + const maybeClose = () => { + if (!this._self.#queue.isEmpty()) + return; + this._self.#socket.off("data", maybeClose); + this._self.#socket.destroySocket(); + resolve82(); + }; + this._self.#socket.on("data", maybeClose); + this._self.#credentialsSubscription?.dispose(); + this._self.#credentialsSubscription = null; + }); + } + /** + * Destroy the client. Rejects all commands immediately. + */ + destroy() { + clearTimeout(this._self.#pingTimer); + this._self.#queue.flushAll(new errors_1.DisconnectsClientError()); + this._self.#socket.destroy(); + this._self.#clientSideCache?.onClose(); + this._self.#credentialsSubscription?.dispose(); + this._self.#credentialsSubscription = null; + } + ref() { + this._self.#socket.ref(); + } + unref() { + this._self.#socket.unref(); + } + }; + _a2 = RedisClient; + exports2.default = RedisClient; + } +}); +var require_lib = __commonJS({ + "node_modules/.deno/cluster-key-slot@1.1.2/node_modules/cluster-key-slot/lib/index.js"(exports2, module14) { + var lookup = [ + 0, + 4129, + 8258, + 12387, + 16516, + 20645, + 24774, + 28903, + 33032, + 37161, + 41290, + 45419, + 49548, + 53677, + 57806, + 61935, + 4657, + 528, + 12915, + 8786, + 21173, + 17044, + 29431, + 25302, + 37689, + 33560, + 45947, + 41818, + 54205, + 50076, + 62463, + 58334, + 9314, + 13379, + 1056, + 5121, + 25830, + 29895, + 17572, + 21637, + 42346, + 46411, + 34088, + 38153, + 58862, + 62927, + 50604, + 54669, + 13907, + 9842, + 5649, + 1584, + 30423, + 26358, + 22165, + 18100, + 46939, + 42874, + 38681, + 34616, + 63455, + 59390, + 55197, + 51132, + 18628, + 22757, + 26758, + 30887, + 2112, + 6241, + 10242, + 14371, + 51660, + 55789, + 59790, + 63919, + 35144, + 39273, + 43274, + 47403, + 23285, + 19156, + 31415, + 27286, + 6769, + 2640, + 14899, + 10770, + 56317, + 52188, + 64447, + 60318, + 39801, + 35672, + 47931, + 43802, + 27814, + 31879, + 19684, + 23749, + 11298, + 15363, + 3168, + 7233, + 60846, + 64911, + 52716, + 56781, + 44330, + 48395, + 36200, + 40265, + 32407, + 28342, + 24277, + 20212, + 15891, + 11826, + 7761, + 3696, + 65439, + 61374, + 57309, + 53244, + 48923, + 44858, + 40793, + 36728, + 37256, + 33193, + 45514, + 41451, + 53516, + 49453, + 61774, + 57711, + 4224, + 161, + 12482, + 8419, + 20484, + 16421, + 28742, + 24679, + 33721, + 37784, + 41979, + 46042, + 49981, + 54044, + 58239, + 62302, + 689, + 4752, + 8947, + 13010, + 16949, + 21012, + 25207, + 29270, + 46570, + 42443, + 38312, + 34185, + 62830, + 58703, + 54572, + 50445, + 13538, + 9411, + 5280, + 1153, + 29798, + 25671, + 21540, + 17413, + 42971, + 47098, + 34713, + 38840, + 59231, + 63358, + 50973, + 55100, + 9939, + 14066, + 1681, + 5808, + 26199, + 30326, + 17941, + 22068, + 55628, + 51565, + 63758, + 59695, + 39368, + 35305, + 47498, + 43435, + 22596, + 18533, + 30726, + 26663, + 6336, + 2273, + 14466, + 10403, + 52093, + 56156, + 60223, + 64286, + 35833, + 39896, + 43963, + 48026, + 19061, + 23124, + 27191, + 31254, + 2801, + 6864, + 10931, + 14994, + 64814, + 60687, + 56684, + 52557, + 48554, + 44427, + 40424, + 36297, + 31782, + 27655, + 23652, + 19525, + 15522, + 11395, + 7392, + 3265, + 61215, + 65342, + 53085, + 57212, + 44955, + 49082, + 36825, + 40952, + 28183, + 32310, + 20053, + 24180, + 11923, + 16050, + 3793, + 7920 + ]; + var toUTF8Array = function toUTF8Array2(str) { + var char; + var i2 = 0; + var p = 0; + var utf8 = []; + var len = str.length; + for (; i2 < len; i2++) { + char = str.charCodeAt(i2); + if (char < 128) { + utf8[p++] = char; + } else if (char < 2048) { + utf8[p++] = char >> 6 | 192; + utf8[p++] = char & 63 | 128; + } else if ((char & 64512) === 55296 && i2 + 1 < str.length && (str.charCodeAt(i2 + 1) & 64512) === 56320) { + char = 65536 + ((char & 1023) << 10) + (str.charCodeAt(++i2) & 1023); + utf8[p++] = char >> 18 | 240; + utf8[p++] = char >> 12 & 63 | 128; + utf8[p++] = char >> 6 & 63 | 128; + utf8[p++] = char & 63 | 128; + } else { + utf8[p++] = char >> 12 | 224; + utf8[p++] = char >> 6 & 63 | 128; + utf8[p++] = char & 63 | 128; } - result[j++] = (c2 & 15) << 4 | (c3 & 60) >> 2; - do { - c4 = buffer[i2++] & 255; - if (c4 === 61) { - return result.slice(0, j); + } + return utf8; + }; + var generate = module14.exports = function generate2(str) { + var char; + var i2 = 0; + var start = -1; + var result = 0; + var resultHash = 0; + var utf8 = typeof str === "string" ? toUTF8Array(str) : str; + var len = utf8.length; + while (i2 < len) { + char = utf8[i2++]; + if (start === -1) { + if (char === 123) { + start = i2; } - c4 = decodeChars[c4]; - } while (i2 < len && c4 === -1); - if (c4 !== -1) { - result[j++] = (c3 & 3) << 6 | c4; + } else if (char !== 125) { + resultHash = lookup[(char ^ resultHash >> 8) & 255] ^ resultHash << 8; + } else if (i2 - 1 !== start) { + return resultHash & 16383; } + result = lookup[(char ^ result >> 8) & 255] ^ result << 8; } - return j === allocated ? result : result.slice(0, j); + return result & 16383; }; - exports2.Decoder = class Decoder extends Stream.Transform { - constructor() { - super(); - this._reminder = null; - } - _transform(chunk, encoding, callback) { - let part = this._reminder ? Buffer.concat([this._reminder, chunk]) : chunk; - const remaining = part.length % 4; - if (remaining) { - this._reminder = part.slice(part.length - remaining); - part = part.slice(0, part.length - remaining); - } else { - this._reminder = null; - } - this.push(exports2.decode(part)); - return callback(); - } - _flush(callback) { - if (this._reminder) { - this.push(exports2.decode(this._reminder)); - } - return callback(); + module14.exports.generateMulti = function generateMulti(keys) { + var i2 = 1; + var len = keys.length; + var base2 = generate(keys[0]); + while (i2 < len) { + if (generate(keys[i2++]) !== base2) return -1; } + return base2; }; } }); -var require_encoder2 = __commonJS({ - "node_modules/.deno/@hapi+b64@6.0.1/node_modules/@hapi/b64/lib/encoder.js"(exports2) { +var require_cluster_slots = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/cluster/cluster-slots.js"(exports2) { "use strict"; - var Stream = __require2("stream"); - exports2.encode = function(buffer) { - return Buffer.from(buffer.toString("base64")); - }; - exports2.Encoder = class Encoder extends Stream.Transform { - constructor() { - super(); - this._reminder = null; - } - _transform(chunk, encoding, callback) { - let part = this._reminder ? Buffer.concat([this._reminder, chunk]) : chunk; - const remaining = part.length % 3; - if (remaining) { - this._reminder = part.slice(part.length - remaining); - part = part.slice(0, part.length - remaining); - } else { - this._reminder = null; - } - this.push(exports2.encode(part)); - return callback(); - } - _flush(callback) { - if (this._reminder) { - this.push(exports2.encode(this._reminder)); - } - return callback(); - } - }; - } -}); -var require_lib22 = __commonJS({ - "node_modules/.deno/@hapi+b64@6.0.1/node_modules/@hapi/b64/lib/index.js"(exports2) { - "use strict"; - var Hoek = require_lib(); - var Decoder2 = require_decoder2(); - var Encoder2 = require_encoder2(); - exports2.decode = Decoder2.decode; - exports2.encode = Encoder2.encode; - exports2.Decoder = Decoder2.Decoder; - exports2.Encoder = Encoder2.Encoder; - exports2.base64urlEncode = function(value, encoding) { - Hoek.assert(typeof value === "string" || Buffer.isBuffer(value), "value must be string or buffer"); - const buf2 = Buffer.isBuffer(value) ? value : Buffer.from(value, encoding || "binary"); - return buf2.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, ""); - }; - exports2.base64urlDecode = function(value, encoding) { - if (typeof value !== "string") { - throw new Error("Value not a string"); - } - if (!/^[\w\-]*$/.test(value)) { - throw new Error("Invalid character"); - } - const buf2 = Buffer.from(value, "base64"); - return encoding === "buffer" ? buf2 : buf2.toString(encoding || "binary"); - }; - } -}); -var require_lib23 = __commonJS({ - "node_modules/.deno/@hapi+iron@7.0.1/node_modules/@hapi/iron/lib/index.js"(exports2) { - "use strict"; - var Crypto = __require2("crypto"); - var B64 = require_lib22(); - var Boom5 = require_lib2(); - var Bourne = require_lib20(); - var Cryptiles = require_lib21(); - var Hoek = require_lib(); - var internals = {}; - exports2.defaults = { - encryption: { - saltBits: 256, - algorithm: "aes-256-cbc", - iterations: 1, - minPasswordlength: 32 - }, - integrity: { - saltBits: 256, - algorithm: "sha256", - iterations: 1, - minPasswordlength: 32 - }, - ttl: 0, - // Milliseconds, 0 means forever - timestampSkewSec: 60, - // Seconds of permitted clock skew for incoming expirations - localtimeOffsetMsec: 0 - // Local clock time offset express in a number of milliseconds (positive or negative) - }; - exports2.algorithms = { - "aes-128-ctr": { keyBits: 128, ivBits: 128 }, - "aes-256-cbc": { keyBits: 256, ivBits: 128 }, - "sha256": { keyBits: 256 } - }; - exports2.macFormatVersion = "2"; - exports2.macPrefix = "Fe26." + exports2.macFormatVersion; - exports2.generateKey = async function(password, options2) { - if (!password) { - throw new Boom5.Boom("Empty password"); - } - if (!options2 || typeof options2 !== "object") { - throw new Boom5.Boom("Bad options"); - } - const algorithm = exports2.algorithms[options2.algorithm]; - if (!algorithm) { - throw new Boom5.Boom("Unknown algorithm: " + options2.algorithm); - } - const result = {}; - if (Buffer.isBuffer(password)) { - if (password.length < algorithm.keyBits / 8) { - throw new Boom5.Boom("Key buffer (password) too small"); - } - result.key = password; - result.salt = ""; - } else { - if (password.length < options2.minPasswordlength) { - throw new Boom5.Boom("Password string too short (min " + options2.minPasswordlength + " characters required)"); - } - let salt = options2.salt; - if (!salt) { - if (!options2.saltBits) { - throw new Boom5.Boom("Missing salt and saltBits options"); - } - const randomSalt = Cryptiles.randomBits(options2.saltBits); - salt = randomSalt.toString("hex"); - } - const derivedKey = await internals.pbkdf2(password, salt, options2.iterations, algorithm.keyBits / 8, "sha1"); - result.key = derivedKey; - result.salt = salt; - } - if (options2.iv) { - result.iv = options2.iv; - } else if (algorithm.ivBits) { - result.iv = Cryptiles.randomBits(algorithm.ivBits); - } - return result; - }; - exports2.encrypt = async function(password, options2, data) { - const key = await exports2.generateKey(password, options2); - const cipher = Crypto.createCipheriv(options2.algorithm, key.key, key.iv); - const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]); - return { encrypted, key }; - }; - exports2.decrypt = async function(password, options2, data) { - const key = await exports2.generateKey(password, options2); - const decipher = Crypto.createDecipheriv(options2.algorithm, key.key, key.iv); - let dec = decipher.update(data, null, "utf8"); - dec = dec + decipher.final("utf8"); - return dec; - }; - exports2.hmacWithPassword = async function(password, options2, data) { - const key = await exports2.generateKey(password, options2); - const hmac = Crypto.createHmac(options2.algorithm, key.key).update(data); - const digest = hmac.digest("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, ""); - return { - digest, - salt: key.salt - }; - }; - internals.normalizePassword = function(password) { - if (password && typeof password === "object" && !Buffer.isBuffer(password)) { - return { - id: password.id, - encryption: password.secret ?? password.encryption, - integrity: password.secret ?? password.integrity - }; - } - return { - encryption: password, - integrity: password - }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - exports2.seal = async function(object2, password, options2) { - options2 = Object.assign({}, options2); - const now = Date.now() + (options2.localtimeOffsetMsec ?? 0); - const objectString = internals.stringify(object2); - let passwordId = ""; - password = internals.normalizePassword(password); - if (password.id) { - if (!/^\w+$/.test(password.id)) { - throw new Boom5.Boom("Invalid password id"); - } - passwordId = password.id; - } - const { encrypted, key } = await exports2.encrypt(password.encryption, options2.encryption, objectString); - const encryptedB64 = B64.base64urlEncode(encrypted); - const iv = B64.base64urlEncode(key.iv); - const expiration = options2.ttl ? now + options2.ttl : ""; - const macBaseString = exports2.macPrefix + "*" + passwordId + "*" + key.salt + "*" + iv + "*" + encryptedB64 + "*" + expiration; - const mac = await exports2.hmacWithPassword(password.integrity, options2.integrity, macBaseString); - const sealed = macBaseString + "*" + mac.salt + "*" + mac.digest; - return sealed; - }; - exports2.unseal = async function(sealed, password, options2) { - options2 = Object.assign({}, options2); - const now = Date.now() + (options2.localtimeOffsetMsec ?? 0); - const parts = sealed.split("*"); - if (parts.length !== 8) { - throw new Boom5.Boom("Incorrect number of sealed components"); - } - const macPrefix = parts[0]; - const passwordId = parts[1]; - const encryptionSalt = parts[2]; - const encryptionIv = parts[3]; - const encryptedB64 = parts[4]; - const expiration = parts[5]; - const hmacSalt = parts[6]; - const hmac = parts[7]; - const macBaseString = macPrefix + "*" + passwordId + "*" + encryptionSalt + "*" + encryptionIv + "*" + encryptedB64 + "*" + expiration; - if (macPrefix !== exports2.macPrefix) { - throw new Boom5.Boom("Wrong mac prefix"); - } - if (expiration) { - if (!expiration.match(/^\d+$/)) { - throw new Boom5.Boom("Invalid expiration"); - } - const exp = parseInt(expiration, 10); - if (exp <= now - options2.timestampSkewSec * 1e3) { - throw new Boom5.Boom("Expired seal"); - } - } - if (!password) { - throw new Boom5.Boom("Empty password"); - } - if (typeof password === "object" && !Buffer.isBuffer(password)) { - password = password[passwordId || "default"]; - if (!password) { - throw new Boom5.Boom("Cannot find password: " + passwordId); - } - } - password = internals.normalizePassword(password); - const macOptions = Hoek.clone(options2.integrity); - macOptions.salt = hmacSalt; - const mac = await exports2.hmacWithPassword(password.integrity, macOptions, macBaseString); - if (!Cryptiles.fixedTimeComparison(mac.digest, hmac)) { - throw new Boom5.Boom("Bad hmac value"); - } - try { - var encrypted = B64.base64urlDecode(encryptedB64, "buffer"); - } catch (err) { - throw Boom5.boomify(err); - } - const decryptOptions = Hoek.clone(options2.encryption); - decryptOptions.salt = encryptionSalt; - try { - decryptOptions.iv = B64.base64urlDecode(encryptionIv, "buffer"); - } catch (err) { - throw Boom5.boomify(err); - } - const decrypted = await exports2.decrypt(password.encryption, decryptOptions, encrypted); - try { - return Bourne.parse(decrypted); - } catch (err) { - throw new Boom5.Boom("Failed parsing sealed object JSON: " + err.message); + var _a2; + Object.defineProperty(exports2, "__esModule", { value: true }); + var errors_1 = require_errors(); + var client_1 = __importDefault(require_client()); + var pub_sub_1 = require_pub_sub(); + var cluster_key_slot_1 = __importDefault(require_lib()); + var cache_1 = require_cache(); + var RedisClusterSlots = class { + static #SLOTS = 16384; + #options; + #clientFactory; + #emit; + slots = new Array(_a2.#SLOTS); + masters = new Array(); + replicas = new Array(); + nodeByAddress = /* @__PURE__ */ new Map(); + pubSubNode; + clientSideCache; + #isOpen = false; + get isOpen() { + return this.#isOpen; } - }; - internals.stringify = function(object2) { - try { - return JSON.stringify(object2); - } catch (err) { - throw new Boom5.Boom("Failed to stringify object: " + err.message); + #validateOptions(options2) { + if (options2?.clientSideCache && options2?.RESP !== 3) { + throw new Error("Client Side Caching is only supported with RESP3"); + } } - }; - internals.pbkdf2 = function(...args) { - return new Promise((resolve82, reject) => { - const next = (err, result) => { - if (err) { - return reject(Boom5.boomify(err)); - } - resolve82(result); - }; - args.push(next); - Crypto.pbkdf2(...args); - }); - }; - } -}); -var require_lib24 = __commonJS({ - "node_modules/.deno/@hapi+statehood@8.2.0/node_modules/@hapi/statehood/lib/index.js"(exports2) { - "use strict"; - var Querystring = __require2("querystring"); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Bourne = require_lib20(); - var Cryptiles = require_lib21(); - var Hoek = require_lib(); - var Iron = require_lib23(); - var Validate = require_lib9(); - var internals = { - macPrefix: "hapi.signed.cookie.1" - }; - internals.schema = Validate.object({ - strictHeader: Validate.boolean(), - ignoreErrors: Validate.boolean(), - isSecure: Validate.boolean(), - isHttpOnly: Validate.boolean(), - isPartitioned: Validate.boolean(), - isSameSite: Validate.valid("Strict", "Lax", "None", false), - path: Validate.string().allow(null), - domain: Validate.string().allow(null), - ttl: Validate.number().allow(null), - encoding: Validate.string().valid("base64json", "base64", "form", "iron", "none"), - sign: Validate.object({ - password: [Validate.string(), Validate.binary(), Validate.object()], - integrity: Validate.object() - }), - iron: Validate.object(), - password: [Validate.string(), Validate.binary(), Validate.object()], - contextualize: Validate.function(), - // Used by hapi - clearInvalid: Validate.boolean(), - autoValue: Validate.any(), - passThrough: Validate.boolean() - }); - internals.defaults = { - strictHeader: true, - // Require an RFC 6265 compliant header format - ignoreErrors: false, - isSecure: true, - isHttpOnly: true, - isPartitioned: false, - isSameSite: "Strict", - path: null, - domain: null, - ttl: null, - // MSecs, 0 means remove - encoding: "none" - // options: 'base64json', 'base64', 'form', 'iron', 'none' - }; - internals.validateRx = { - nameRx: { - strict: /^[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+$/, - loose: /^[^=\s]*$/ - }, - valueRx: { - strict: /^[^\x00-\x20\"\,\;\\\x7F]*$/, - loose: /^(?:"([^\"]*)")|(?:[^\;]*)$/ - }, - domainRx: /^\.?[a-z\d]+(?:(?:[a-z\d]*)|(?:[a-z\d\-]*[a-z\d]))(?:\.[a-z\d]+(?:(?:[a-z\d]*)|(?:[a-z\d\-]*[a-z\d])))*$/, - domainLabelLenRx: /^\.?[a-z\d\-]{1,63}(?:\.[a-z\d\-]{1,63})*$/, - pathRx: /^\/[^\x00-\x1F\;]*$/ - }; - internals.pairsRx = /\s*([^=\s]*)\s*=\s*([^\;]*)(?:(?:;\s*)|$)/g; - exports2.Definitions = class { - constructor(options2) { - this.settings = Hoek.applyToDefaults(internals.defaults, options2 ?? {}); - Validate.assert(this.settings, internals.schema, "Invalid state definition defaults"); - this.cookies = {}; - this.names = []; - } - add(name, options2) { - Hoek.assert(name && typeof name === "string", "Invalid name"); - Hoek.assert(!this.cookies[name], "State already defined:", name); - const settings = Hoek.applyToDefaults(this.settings, options2 ?? {}, { nullOverride: true }); - Validate.assert(settings, internals.schema, "Invalid state definition: " + name); - this.cookies[name] = settings; - this.names.push(name); - } - async parse(cookies) { - const state = {}; - const names = []; - const verify = internals.parsePairs(cookies, (name, value) => { - if (name === "__proto__") { - throw Boom5.badRequest("Invalid cookie header"); - } - if (state[name]) { - if (!Array.isArray(state[name])) { - state[name] = [state[name]]; - } - state[name].push(value); + constructor(options2, emit) { + this.#validateOptions(options2); + this.#options = options2; + if (options2?.clientSideCache) { + if (options2.clientSideCache instanceof cache_1.PooledClientSideCacheProvider) { + this.clientSideCache = options2.clientSideCache; } else { - state[name] = value; - names.push(name); - } - }); - const failed = []; - if (verify !== null) { - if (!this.settings.ignoreErrors) { - throw Boom5.badRequest("Invalid cookie header"); + this.clientSideCache = new cache_1.BasicPooledClientSideCache(options2.clientSideCache); } - failed.push({ settings: this.settings, reason: `Header contains unexpected syntax: ${verify}` }); } - const errored = []; - const record2 = (reason, name, value, definition) => { - const details = { - name, - value, - settings: definition, - reason: typeof reason === "string" ? reason : reason.message - }; - failed.push(details); - if (!definition.ignoreErrors) { - errored.push(details); - } - }; - const parsed = {}; - for (const name of names) { - const value = state[name]; - const definition = this.cookies[name] ?? this.settings; - if (definition.strictHeader) { - const reason = internals.validate(name, state); - if (reason) { - record2(reason, name, value, definition); - continue; - } - } - if (definition.encoding === "none") { - parsed[name] = value; - continue; - } - if (!Array.isArray(value)) { - try { - const unsigned = await internals.unsign(name, value, definition); - const result = await internals.decode(unsigned, definition); - parsed[name] = result; - } catch (err) { - Bounce.rethrow(err, "system"); - record2(err, name, value, definition); - } - continue; - } - const arrayResult = []; - for (const arrayValue of value) { - try { - const unsigned = await internals.unsign(name, arrayValue, definition); - const result = await internals.decode(unsigned, definition); - arrayResult.push(result); - } catch (err) { - Bounce.rethrow(err, "system"); - record2(err, name, value, definition); - } - } - parsed[name] = arrayResult; + this.#clientFactory = client_1.default.factory(this.#options); + this.#emit = emit; + } + async connect() { + if (this.#isOpen) { + throw new Error("Cluster already open"); } - if (errored.length) { - const error2 = Boom5.badRequest("Invalid cookie value", errored); - error2.states = parsed; - error2.failed = failed; - throw error2; + this.#isOpen = true; + try { + await this.#discoverWithRootNodes(); + this.#emit("connect"); + } catch (err) { + this.#isOpen = false; + throw err; } - return { states: parsed, failed }; } - async format(cookies, context) { - if (!cookies || Array.isArray(cookies) && !cookies.length) { - return []; + async #discoverWithRootNodes() { + let start = Math.floor(Math.random() * this.#options.rootNodes.length); + for (let i2 = start; i2 < this.#options.rootNodes.length; i2++) { + if (!this.#isOpen) + throw new Error("Cluster closed"); + if (await this.#discover(this.#options.rootNodes[i2])) + return; } - if (!Array.isArray(cookies)) { - cookies = [cookies]; - } - const header = []; - for (let i2 = 0; i2 < cookies.length; ++i2) { - const cookie = cookies[i2]; - const base2 = this.cookies[cookie.name] ?? this.settings; - let definition = cookie.options ? Hoek.applyToDefaults(base2, cookie.options, { nullOverride: true }) : base2; - if (definition.contextualize) { - if (definition === base2) { - definition = Hoek.clone(definition); - } - await definition.contextualize(definition, context); - } - const nameRx = definition.strictHeader ? internals.validateRx.nameRx.strict : internals.validateRx.nameRx.loose; - if (!nameRx.test(cookie.name)) { - throw Boom5.badImplementation("Invalid cookie name: " + cookie.name); - } - const value = await exports2.prepareValue(cookie.name, cookie.value, definition); - const valueRx = definition.strictHeader ? internals.validateRx.valueRx.strict : internals.validateRx.valueRx.loose; - if (value && (typeof value !== "string" || !value.match(valueRx))) { - throw Boom5.badImplementation("Invalid cookie value: " + cookie.value); - } - let segment = cookie.name + "=" + (value || ""); - if (definition.ttl !== null && definition.ttl !== void 0) { - const expires = new Date(definition.ttl ? Date.now() + definition.ttl : 0); - segment = segment + "; Max-Age=" + Math.floor(definition.ttl / 1e3) + "; Expires=" + expires.toUTCString(); - } - if (definition.isSecure) { - segment = segment + "; Secure"; - } - if (definition.isHttpOnly) { - segment = segment + "; HttpOnly"; - } - if (definition.isSameSite) { - segment = `${segment}; SameSite=${definition.isSameSite}`; - } - if (definition.isPartitioned) { - if (!definition.isSecure) { - throw Boom5.badImplementation("Partitioned cookies must be secure"); + for (let i2 = 0; i2 < start; i2++) { + if (!this.#isOpen) + throw new Error("Cluster closed"); + if (await this.#discover(this.#options.rootNodes[i2])) + return; + } + throw new errors_1.RootNodesUnavailableError(); + } + #resetSlots() { + this.slots = new Array(_a2.#SLOTS); + this.masters = []; + this.replicas = []; + this._randomNodeIterator = void 0; + } + async #discover(rootNode) { + this.clientSideCache?.clear(); + this.clientSideCache?.disable(); + try { + const addressesInUse = /* @__PURE__ */ new Set(), promises = [], eagerConnect = this.#options.minimizeConnections !== true; + const shards = await this.#getShards(rootNode); + this.#resetSlots(); + for (const { from: from3, to, master, replicas } of shards) { + const shard = { + master: this.#initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) + }; + if (this.#options.useReplicas) { + shard.replicas = replicas.map((replica) => this.#initiateSlotNode(replica, true, eagerConnect, addressesInUse, promises)); } - if (definition.isSameSite !== "None") { - throw Boom5.badImplementation("Partitioned cookies must have SameSite=None"); + for (let i2 = from3; i2 <= to; i2++) { + this.slots[i2] = shard; } - segment = `${segment}; Partitioned`; } - if (definition.domain) { - const domain = definition.domain.toLowerCase(); - if (!domain.match(internals.validateRx.domainLabelLenRx)) { - throw Boom5.badImplementation("Cookie domain too long: " + definition.domain); - } - if (!domain.match(internals.validateRx.domainRx)) { - throw Boom5.badImplementation("Invalid cookie domain: " + definition.domain); + if (this.pubSubNode && !addressesInUse.has(this.pubSubNode.address)) { + const channelsListeners = this.pubSubNode.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS), patternsListeners = this.pubSubNode.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS); + this.pubSubNode.client.destroy(); + if (channelsListeners.size || patternsListeners.size) { + promises.push(this.#initiatePubSubClient({ + [pub_sub_1.PUBSUB_TYPE.CHANNELS]: channelsListeners, + [pub_sub_1.PUBSUB_TYPE.PATTERNS]: patternsListeners + })); } - segment = segment + "; Domain=" + domain; } - if (definition.path) { - if (!definition.path.match(internals.validateRx.pathRx)) { - throw Boom5.badImplementation("Invalid cookie path: " + definition.path); + for (const [address, node] of this.nodeByAddress.entries()) { + if (addressesInUse.has(address)) + continue; + if (node.client) { + node.client.destroy(); + } + const { pubSub } = node; + if (pubSub) { + pubSub.client.destroy(); } - segment = segment + "; Path=" + definition.path; + this.nodeByAddress.delete(address); } - header.push(segment); + await Promise.all(promises); + this.clientSideCache?.enable(); + return true; + } catch (err) { + this.#emit("error", err); + return false; } - return header; } - passThrough(header, fallback) { - if (!this.names.length) { - return header; - } - const exclude = []; - for (let i2 = 0; i2 < this.names.length; ++i2) { - const name = this.names[i2]; - const definition = this.cookies[name]; - const passCookie = definition.passThrough !== void 0 ? definition.passThrough : fallback; - if (!passCookie) { - exclude.push(name); - } + async #getShards(rootNode) { + const options2 = this.#clientOptionsDefaults(rootNode); + options2.socket ??= {}; + options2.socket.reconnectStrategy = false; + options2.RESP = this.#options.RESP; + options2.commandOptions = void 0; + const client = await this.#clientFactory(options2).on("error", (err) => this.#emit("error", err)).connect(); + try { + return await client.clusterSlots(); + } finally { + client.destroy(); } - return exports2.exclude(header, exclude); } - }; - internals.parsePairs = function(cookies, eachPairFn) { - let index = 0; - while (index < cookies.length) { - const eqIndex = cookies.indexOf("=", index); - if (eqIndex === -1) { - return cookies.slice(index); + #getNodeAddress(address) { + switch (typeof this.#options.nodeAddressMap) { + case "object": + return this.#options.nodeAddressMap[address]; + case "function": + return this.#options.nodeAddressMap(address); } - const semiIndex = cookies.indexOf(";", eqIndex); - const endOfValueIndex = semiIndex !== -1 ? semiIndex : cookies.length; - const name = cookies.slice(index, eqIndex).trim(); - const value = cookies.slice(eqIndex + 1, endOfValueIndex).trim(); - const unquotedValue = value.startsWith('"') && value.endsWith('"') && value !== '"' ? value.slice(1, -1) : ( - // E.g. '"abc"' -> 'abc' - value - ); - eachPairFn(name, unquotedValue); - index = endOfValueIndex + 1; } - return null; - }; - internals.validate = function(name, state) { - if (!name.match(internals.validateRx.nameRx.strict)) { - return "Invalid cookie name"; - } - const values = [].concat(state[name]); - for (let i2 = 0; i2 < values.length; ++i2) { - if (!values[i2].match(internals.validateRx.valueRx.strict)) { - return "Invalid cookie value"; + #clientOptionsDefaults(options2) { + if (!this.#options.defaults) + return options2; + let socket; + if (this.#options.defaults.socket) { + socket = { + ...this.#options.defaults.socket, + ...options2?.socket + }; + } else { + socket = options2?.socket; } + return { + ...this.#options.defaults, + ...options2, + socket + }; } - return null; - }; - internals.unsign = async function(name, value, definition) { - if (!definition.sign) { - return value; - } - const pos = value.lastIndexOf("."); - if (pos === -1) { - throw Boom5.badRequest("Missing signature separator"); - } - const unsigned = value.slice(0, pos); - const sig = value.slice(pos + 1); - if (!sig) { - throw Boom5.badRequest("Missing signature"); + #initiateSlotNode(shard, readonly2, eagerConnent, addressesInUse, promises) { + const address = `${shard.host}:${shard.port}`; + let node = this.nodeByAddress.get(address); + if (!node) { + node = { + ...shard, + address, + readonly: readonly2, + client: void 0, + connectPromise: void 0 + }; + if (eagerConnent) { + promises.push(this.#createNodeClient(node)); + } + this.nodeByAddress.set(address, node); + } + if (!addressesInUse.has(address)) { + addressesInUse.add(address); + (readonly2 ? this.replicas : this.masters).push(node); + } + return node; } - const sigParts = sig.split("*"); - if (sigParts.length !== 2) { - throw Boom5.badRequest("Invalid signature format"); + #createClient(node, readonly2 = node.readonly) { + const socket = this.#getNodeAddress(node.address) ?? { host: node.host, port: node.port }; + const clientInfo = Object.freeze({ + host: socket.host, + port: socket.port + }); + const emit = this.#emit; + const client = this.#clientFactory(this.#clientOptionsDefaults({ + clientSideCache: this.clientSideCache, + RESP: this.#options.RESP, + socket, + readonly: readonly2 + })).on("error", (error2) => emit("node-error", error2, clientInfo)).on("reconnecting", () => emit("node-reconnecting", clientInfo)).once("ready", () => emit("node-ready", clientInfo)).once("connect", () => emit("node-connect", clientInfo)).once("end", () => emit("node-disconnect", clientInfo)).on("__MOVED", async (allPubSubListeners) => { + await this.rediscover(client); + this.#emit("__resubscribeAllPubSubListeners", allPubSubListeners); + }); + return client; } - const hmacSalt = sigParts[0]; - const hmac = sigParts[1]; - const macOptions = Hoek.clone(definition.sign.integrity ?? Iron.defaults.integrity); - macOptions.salt = hmacSalt; - const mac = await Iron.hmacWithPassword(definition.sign.password, macOptions, [internals.macPrefix, name, unsigned].join("\n")); - if (!Cryptiles.fixedTimeComparison(mac.digest, hmac)) { - throw Boom5.badRequest("Invalid hmac value"); + #createNodeClient(node, readonly2) { + const client = node.client = this.#createClient(node, readonly2); + return node.connectPromise = client.connect().finally(() => node.connectPromise = void 0); } - return unsigned; - }; - internals.decode = async function(value, definition) { - if (!value && definition.encoding === "form") { - return {}; + nodeClient(node) { + return node.connectPromise ?? // if the node is connecting + node.client ?? // if the node is connected + this.#createNodeClient(node); } - Hoek.assert(typeof value === "string", "Invalid string"); - if (definition.encoding === "iron") { - return await Iron.unseal(value, definition.password, definition.iron ?? Iron.defaults); + #runningRediscoverPromise; + async rediscover(startWith) { + this.#runningRediscoverPromise ??= this.#rediscover(startWith).finally(() => { + this.#runningRediscoverPromise = void 0; + }); + return this.#runningRediscoverPromise; } - if (definition.encoding === "base64json") { - const decoded = Buffer.from(value, "base64").toString("binary"); - try { - return Bourne.parse(decoded); - } catch (err) { - throw Boom5.badRequest("Invalid JSON payload"); - } + async #rediscover(startWith) { + if (await this.#discover(startWith.options)) + return; + return this.#discoverWithRootNodes(); } - if (definition.encoding === "base64") { - return Buffer.from(value, "base64").toString("binary"); + /** + * @deprecated Use `close` instead. + */ + quit() { + return this.#destroy((client) => client.quit()); } - return Querystring.parse(value); - }; - exports2.prepareValue = async function(name, value, options2) { - Hoek.assert(options2 && typeof options2 === "object", "Missing or invalid options"); - try { - const encoded = await internals.encode(value, options2); - const signed = await internals.sign(name, encoded, options2.sign); - return signed; - } catch (err) { - throw Boom5.badImplementation("Failed to encode cookie (" + name + ") value: " + err.message); + /** + * @deprecated Use `destroy` instead. + */ + disconnect() { + return this.#destroy((client) => client.disconnect()); } - }; - internals.encode = function(value, options2) { - if (value === void 0 || options2.encoding === "none") { - return value; + close() { + return this.#destroy((client) => client.close()); } - if (options2.encoding === "iron") { - return Iron.seal(value, options2.password, options2.iron ?? Iron.defaults); + destroy() { + this.#isOpen = false; + for (const client of this.#clients()) { + client.destroy(); + } + if (this.pubSubNode) { + this.pubSubNode.client.destroy(); + this.pubSubNode = void 0; + } + this.#resetSlots(); + this.nodeByAddress.clear(); + this.#emit("disconnect"); } - if (options2.encoding === "base64") { - return Buffer.from(value, "binary").toString("base64"); + *#clients() { + for (const master of this.masters) { + if (master.client) { + yield master.client; + } + if (master.pubSub) { + yield master.pubSub.client; + } + } + for (const replica of this.replicas) { + if (replica.client) { + yield replica.client; + } + } } - if (options2.encoding === "base64json") { - const stringified = JSON.stringify(value); - return Buffer.from(stringified, "binary").toString("base64"); + async #destroy(fn) { + this.#isOpen = false; + const promises = []; + for (const client of this.#clients()) { + promises.push(fn(client)); + } + if (this.pubSubNode) { + promises.push(fn(this.pubSubNode.client)); + this.pubSubNode = void 0; + } + this.#resetSlots(); + this.nodeByAddress.clear(); + await Promise.allSettled(promises); + this.#emit("disconnect"); } - return Querystring.stringify(value); - }; - internals.sign = async function(name, value, options2) { - if (value === void 0 || !options2) { - return value; + getClient(firstKey, isReadonly) { + if (!firstKey) { + return this.nodeClient(this.getRandomNode()); + } + const slotNumber = (0, cluster_key_slot_1.default)(firstKey); + if (!isReadonly) { + return this.nodeClient(this.slots[slotNumber].master); + } + return this.nodeClient(this.getSlotRandomNode(slotNumber)); } - const mac = await Iron.hmacWithPassword(options2.password, options2.integrity ?? Iron.defaults.integrity, [internals.macPrefix, name, value].join("\n")); - const signed = value + "." + mac.salt + "*" + mac.digest; - return signed; - }; - exports2.exclude = function(cookies, excludes) { - let result = ""; - const verify = cookies.replace(internals.pairsRx, ($0, $1, $2) => { - if (excludes.indexOf($1) === -1) { - result = result + (result ? ";" : "") + $1 + "=" + $2; + *#iterateAllNodes() { + if (this.masters.length + this.replicas.length === 0) + return; + let i2 = Math.floor(Math.random() * (this.masters.length + this.replicas.length)); + if (i2 < this.masters.length) { + do { + yield this.masters[i2]; + } while (++i2 < this.masters.length); + for (const replica of this.replicas) { + yield replica; + } + } else { + i2 -= this.masters.length; + do { + yield this.replicas[i2]; + } while (++i2 < this.replicas.length); + } + while (true) { + for (const master of this.masters) { + yield master; + } + for (const replica of this.replicas) { + yield replica; + } } - return ""; - }); - return verify === "" ? result : Boom5.badRequest("Invalid cookie header"); - }; - } -}); -var require_lib25 = __commonJS({ - "node_modules/.deno/@hapi+content@6.0.0/node_modules/@hapi/content/lib/index.js"(exports2) { - "use strict"; - var Boom5 = require_lib2(); - var internals = {}; - internals.contentTypeRegex = /^([^\/\s]+\/[^\s;]+)(.*)?$/; - internals.charsetParamRegex = /;\s*charset=(?:"([^"]+)"|([^;"\s]+))/i; - internals.boundaryParamRegex = /;\s*boundary=(?:"([^"]+)"|([^;"\s]+))/i; - exports2.type = function(header) { - if (!header) { - throw Boom5.badRequest("Invalid content-type header"); } - const match = header.match(internals.contentTypeRegex); - if (!match) { - throw Boom5.badRequest("Invalid content-type header"); + _randomNodeIterator; + getRandomNode() { + this._randomNodeIterator ??= this.#iterateAllNodes(); + return this._randomNodeIterator.next().value; } - const result = { - mime: match[1].toLowerCase() - }; - const params = match[2]; - if (params) { - const param = params.match(internals.charsetParamRegex); - if (param) { - result.charset = (param[1] || param[2]).toLowerCase(); + *#slotNodesIterator(slot) { + let i2 = Math.floor(Math.random() * (1 + slot.replicas.length)); + if (i2 < slot.replicas.length) { + do { + yield slot.replicas[i2]; + } while (++i2 < slot.replicas.length); } - } - if (result.mime.indexOf("multipart/") === 0) { - if (params) { - const param = params.match(internals.boundaryParamRegex); - if (param) { - result.boundary = param[1] || param[2]; + while (true) { + yield slot.master; + for (const replica of slot.replicas) { + yield replica; } } - if (!result.boundary) { - throw Boom5.badRequest("Invalid content-type header: multipart missing boundary"); + } + getSlotRandomNode(slotNumber) { + const slot = this.slots[slotNumber]; + if (!slot.replicas?.length) { + return slot.master; } + slot.nodesIterator ??= this.#slotNodesIterator(slot); + return slot.nodesIterator.next().value; } - return result; - }; - internals.contentDispositionRegex = /^\s*form-data\s*(?:;\s*(.+))?$/i; - internals.contentDispositionParamRegex = /([^\=\*\s]+)(\*)?\s*\=\s*(?:([^;'"\s]+\'[\w-]*\'[^;\s]+)|(?:\"([^"]*)\")|([^;\s]*))(?:\s*(?:;\s*)|$)/g; - exports2.disposition = function(header) { - if (!header) { - throw Boom5.badRequest("Missing content-disposition header"); + getMasterByAddress(address) { + const master = this.nodeByAddress.get(address); + if (!master) + return; + return this.nodeClient(master); + } + getPubSubClient() { + if (!this.pubSubNode) + return this.#initiatePubSubClient(); + return this.pubSubNode.connectPromise ?? this.pubSubNode.client; + } + async #initiatePubSubClient(toResubscribe) { + const index = Math.floor(Math.random() * (this.masters.length + this.replicas.length)), node = index < this.masters.length ? this.masters[index] : this.replicas[index - this.masters.length], client = this.#createClient(node, false); + this.pubSubNode = { + address: node.address, + client, + connectPromise: client.connect().then(async (client2) => { + if (toResubscribe) { + await Promise.all([ + client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS, toResubscribe[pub_sub_1.PUBSUB_TYPE.CHANNELS]), + client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS, toResubscribe[pub_sub_1.PUBSUB_TYPE.PATTERNS]) + ]); + } + this.pubSubNode.connectPromise = void 0; + return client2; + }).catch((err) => { + this.pubSubNode = void 0; + throw err; + }) + }; + return this.pubSubNode.connectPromise; + } + async executeUnsubscribeCommand(unsubscribe) { + const client = await this.getPubSubClient(); + await unsubscribe(client); + if (!client.isPubSubActive) { + client.destroy(); + this.pubSubNode = void 0; + } } - const match = header.match(internals.contentDispositionRegex); - if (!match) { - throw Boom5.badRequest("Invalid content-disposition header format"); + getShardedPubSubClient(channel) { + const { master } = this.slots[(0, cluster_key_slot_1.default)(channel)]; + if (!master.pubSub) + return this.#initiateShardedPubSubClient(master); + return master.pubSub.connectPromise ?? master.pubSub.client; } - const parameters = match[1]; - if (!parameters) { - throw Boom5.badRequest("Invalid content-disposition header missing parameters"); + async #initiateShardedPubSubClient(master) { + const client = this.#createClient(master, false).on("server-sunsubscribe", async (channel, listeners) => { + try { + await this.rediscover(client); + const redirectTo = await this.getShardedPubSubClient(channel); + await redirectTo.extendPubSubChannelListeners(pub_sub_1.PUBSUB_TYPE.SHARDED, channel, listeners); + } catch (err) { + this.#emit("sharded-shannel-moved-error", err, channel, listeners); + } + }); + master.pubSub = { + client, + connectPromise: client.connect().then((client2) => { + master.pubSub.connectPromise = void 0; + return client2; + }).catch((err) => { + master.pubSub = void 0; + throw err; + }) + }; + return master.pubSub.connectPromise; } - const result = {}; - parameters.replace(internals.contentDispositionParamRegex, ($0, $1, $2, $3, $4, $5) => { - if ($1 === "__proto__") { - throw Boom5.badRequest("Invalid content-disposition header format includes invalid parameters"); - } - let value; - if ($2) { - if (!$3) { - throw Boom5.badRequest("Invalid content-disposition header format includes invalid parameters"); - } - try { - value = decodeURIComponent($3.split("'")[2]); - } catch (err) { - throw Boom5.badRequest("Invalid content-disposition header format includes invalid parameters"); - } - } else { - value = $4 || $5 || ""; - } - if ($1 === "name" && value === "__proto__") { - throw Boom5.badRequest("Invalid content-disposition header format includes invalid parameters"); + async executeShardedUnsubscribeCommand(channel, unsubscribe) { + const { master } = this.slots[(0, cluster_key_slot_1.default)(channel)]; + if (!master.pubSub) + return; + const client = master.pubSub.connectPromise ? await master.pubSub.connectPromise : master.pubSub.client; + await unsubscribe(client); + if (!client.isPubSubActive) { + client.destroy(); + master.pubSub = void 0; } - result[$1] = value; - }); - if (!result.name) { - throw Boom5.badRequest("Invalid content-disposition header missing name parameter"); } - return result; }; + _a2 = RedisClusterSlots; + exports2.default = RedisClusterSlots; } }); -var require_lib26 = __commonJS({ - "node_modules/.deno/@hapi+file@3.0.0/node_modules/@hapi/file/lib/index.js"(exports2) { +var require_multi_command3 = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/cluster/multi-command.js"(exports2) { "use strict"; - var Crypto = __require2("crypto"); - var Path = __require2("path"); - exports2.uniqueFilename = function(path8, extension) { - if (extension) { - extension = extension[0] !== "." ? "." + extension : extension; - } else { - extension = ""; - } - path8 = Path.resolve(path8); - const name = [Date.now(), process.pid, Crypto.randomBytes(8).toString("hex")].join("-") + extension; - return Path.join(path8, name); + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - } -}); -var require_lib27 = __commonJS({ - "node_modules/.deno/@hapi+vise@5.0.1/node_modules/@hapi/vise/lib/index.js"(exports2) { - "use strict"; - var Hoek = require_lib(); - exports2.Vise = class Vise { - constructor(chunks) { - this.length = 0; - this._chunks = []; - this._offset = 0; - if (chunks) { - chunks = [].concat(chunks); - for (let i2 = 0; i2 < chunks.length; ++i2) { - this.push(chunks[i2]); - } - } - } - push(chunk) { - Hoek.assert(Buffer.isBuffer(chunk), "Chunk must be a buffer"); - const item = { - data: chunk, - length: chunk.length, - offset: this.length + this._offset, - index: this._chunks.length + Object.defineProperty(exports2, "__esModule", { value: true }); + var commands_1 = __importDefault(require_commands()); + var multi_command_1 = __importDefault(require_multi_command()); + var commander_1 = require_commander(); + var parser_1 = require_parser(); + var RedisClusterMultiCommand = class _RedisClusterMultiCommand { + static #createCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + const firstKey = parser3.firstKey; + return this.addCommand(firstKey, command2.IS_READ_ONLY, redisArgs, transformReply); }; - this._chunks.push(item); - this.length += chunk.length; - } - shift(length2) { - if (!length2) { - return []; - } - const prevOffset = this._offset; - const item = this.#chunkAt(length2); - let dropTo = this._chunks.length; - this._offset = 0; - if (item) { - dropTo = item.chunk.index; - this._offset = item.offset; - } - const chunks = []; - for (let i2 = 0; i2 < dropTo; ++i2) { - const chunk = this._chunks.shift(); - if (i2 === 0 && prevOffset) { - chunks.push(chunk.data.slice(prevOffset)); - } else { - chunks.push(chunk.data); - } - } - if (this._offset) { - chunks.push(item.chunk.data.slice(dropTo ? 0 : prevOffset, this._offset)); - } - this.length = 0; - for (let i2 = 0; i2 < this._chunks.length; ++i2) { - const chunk = this._chunks[i2]; - chunk.offset = this.length, chunk.index = i2; - this.length += chunk.length; - } - this.length -= this._offset; - return chunks; - } - readUInt8(pos) { - const item = this.#chunkAt(pos); - return item ? item.chunk.data[item.offset] : void 0; } - at(pos) { - return this.readUInt8(pos); - } - #chunkAt(pos) { - if (pos < 0) { - return null; - } - pos = pos + this._offset; - for (let i2 = 0; i2 < this._chunks.length; ++i2) { - const chunk = this._chunks[i2]; - const offset = pos - chunk.offset; - if (offset < chunk.length) { - return { chunk, offset }; - } - } - return null; + static #createModuleCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + const firstKey = parser3.firstKey; + return this._self.addCommand(firstKey, command2.IS_READ_ONLY, redisArgs, transformReply); + }; } - chunks() { - const chunks = []; - for (let i2 = 0; i2 < this._chunks.length; ++i2) { - const chunk = this._chunks[i2]; - if (i2 === 0 && this._offset) { - chunks.push(chunk.data.slice(this._offset)); - } else { - chunks.push(chunk.data); - } - } - return chunks; + static #createFunctionCommand(name, fn, resp) { + const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); + const transformReply = (0, commander_1.getTransformReply)(fn, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + fn.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + const firstKey = parser3.firstKey; + return this._self.addCommand(firstKey, fn.IS_READ_ONLY, redisArgs, transformReply); + }; } - startsWith(value, pos, length2) { - pos = pos ?? 0; - length2 = length2 ? Math.min(value.length, length2) : value.length; - if (pos + length2 > this.length) { - return false; - } - const start = this.#chunkAt(pos); - if (!start) { - return false; - } - let j = start.chunk.index; - for (let i2 = 0; j < this._chunks.length && i2 < length2; ++j) { - const chunk = this._chunks[j]; - let k = j === start.chunk.index ? start.offset : 0; - for (; k < chunk.length && i2 < length2; ++k, ++i2) { - if (chunk.data[k] !== value[i2]) { - return false; - } - } - } - return true; + static #createScriptCommand(script, resp) { + const transformReply = (0, commander_1.getTransformReply)(script, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + script.parseCommand(parser3, ...args); + const scriptArgs = parser3.redisArgs; + scriptArgs.preserve = parser3.preserve; + const firstKey = parser3.firstKey; + return this.#addScript(firstKey, script.IS_READ_ONLY, script, scriptArgs, transformReply); + }; } - }; - } -}); -var require_lib28 = __commonJS({ - "node_modules/.deno/@hapi+nigel@5.0.1/node_modules/@hapi/nigel/lib/index.js"(exports2) { - "use strict"; - var Stream = __require2("stream"); - var Hoek = require_lib(); - var { Vise } = require_lib27(); - var internals = {}; - exports2.compile = function(needle) { - Hoek.assert(needle?.length, "Missing needle"); - Hoek.assert(Buffer.isBuffer(needle), "Needle must be a buffer"); - const profile = { - value: needle, - lastPos: needle.length - 1, - last: needle[needle.length - 1], - length: needle.length, - badCharShift: Buffer.alloc(256) - // Lookup table of how many characters can be skipped for each match - }; - for (let i2 = 0; i2 < 256; ++i2) { - profile.badCharShift[i2] = profile.length; - } - const last = profile.length - 1; - for (let i2 = 0; i2 < last; ++i2) { - profile.badCharShift[profile.value[i2]] = last - i2; - } - return profile; - }; - exports2.horspool = function(haystack, needle, start) { - Hoek.assert(haystack, "Missing haystack"); - needle = needle.badCharShift ? needle : exports2.compile(needle); - start = start ?? 0; - for (let i2 = start; i2 <= haystack.length - needle.length; ) { - const lastChar = haystack.readUInt8(i2 + needle.lastPos); - if (lastChar === needle.last && internals.startsWith(haystack, needle, i2)) { - return i2; - } - i2 += needle.badCharShift[lastChar]; + static extend(config2) { + return (0, commander_1.attachConfig)({ + BaseClass: _RedisClusterMultiCommand, + commands: commands_1.default, + createCommand: _RedisClusterMultiCommand.#createCommand, + createModuleCommand: _RedisClusterMultiCommand.#createModuleCommand, + createFunctionCommand: _RedisClusterMultiCommand.#createFunctionCommand, + createScriptCommand: _RedisClusterMultiCommand.#createScriptCommand, + config: config2 + }); } - return -1; - }; - internals.startsWith = function(haystack, needle, pos) { - if (haystack.startsWith) { - return haystack.startsWith(needle.value, pos, needle.lastPos); + #multi; + #executeMulti; + #executePipeline; + #firstKey; + #isReadonly = true; + constructor(executeMulti, executePipeline, routing, typeMapping) { + this.#multi = new multi_command_1.default(typeMapping); + this.#executeMulti = executeMulti; + this.#executePipeline = executePipeline; + this.#firstKey = routing; } - for (let i2 = 0; i2 < needle.lastPos; ++i2) { - if (needle.value[i2] !== haystack.readUInt8(pos + i2)) { - return false; - } + #setState(firstKey, isReadonly) { + this.#firstKey ??= firstKey; + this.#isReadonly &&= isReadonly; } - return true; - }; - exports2.all = function(haystack, needle, start) { - needle = exports2.compile(needle); - start = start ?? 0; - const matches = []; - for (let i2 = start; i2 !== -1 && i2 < haystack.length; ) { - i2 = exports2.horspool(haystack, needle, i2); - if (i2 !== -1) { - matches.push(i2); - i2 += needle.length; - } + addCommand(firstKey, isReadonly, args, transformReply) { + this.#setState(firstKey, isReadonly); + this.#multi.addCommand(args, transformReply); + return this; } - return matches; - }; - internals._indexOf = function(haystack, needle) { - Hoek.assert(haystack, "Missing haystack"); - for (let i2 = 0; i2 <= haystack.length - needle.length; ++i2) { - if (haystack.startsWith(needle.value, i2)) { - return i2; - } + #addScript(firstKey, isReadonly, script, args, transformReply) { + this.#setState(firstKey, isReadonly); + this.#multi.addScript(script, args, transformReply); + return this; } - return -1; - }; - exports2.Stream = class extends Stream.Writable { - constructor(needle) { - super(); - this.needle(needle); - this._haystack = new Vise(); - this._indexOf = this._needle.length > 2 ? exports2.horspool : internals._indexOf; - this.on("finish", () => { - const chunks = this._haystack.chunks(); - for (let i2 = 0; i2 < chunks.length; ++i2) { - this.emit("haystack", chunks[i2]); - } - }); + async exec(execAsPipeline = false) { + if (execAsPipeline) + return this.execAsPipeline(); + return this.#multi.transformReplies(await this.#executeMulti(this.#firstKey, this.#isReadonly, this.#multi.queue)); } - needle(needle) { - this._needle = exports2.compile(needle); - } - _write(chunk, encoding, next) { - this._haystack.push(chunk); - let match = this._indexOf(this._haystack, this._needle); - if (match === -1 && chunk.length >= this._needle.length) { - this._flush(this._haystack.length - chunk.length); - } - while (match !== -1) { - this._flush(match); - this._haystack.shift(this._needle.length); - this.emit("needle"); - match = this._indexOf(this._haystack, this._needle); - } - if (this._haystack.length) { - const notChecked = this._haystack.length - this._needle.length + 1; - let i2 = notChecked; - for (; i2 < this._haystack.length; ++i2) { - if (this._haystack.startsWith(this._needle.value, i2, this._haystack.length - i2)) { - break; - } - } - this._flush(i2); - } - return next(); + EXEC = this.exec; + execTyped(execAsPipeline = false) { + return this.exec(execAsPipeline); } - _flush(pos) { - const chunks = this._haystack.shift(pos); - for (let i2 = 0; i2 < chunks.length; ++i2) { - this.emit("haystack", chunks[i2]); - } + async execAsPipeline() { + if (this.#multi.queue.length === 0) + return []; + return this.#multi.transformReplies(await this.#executePipeline(this.#firstKey, this.#isReadonly, this.#multi.queue)); } - flush() { - const chunks = this._haystack.shift(this._haystack.length); - for (let i2 = 0; i2 < chunks.length; ++i2) { - this.emit("haystack", chunks[i2]); - } + execAsPipelineTyped() { + return this.execAsPipeline(); } }; + exports2.default = RedisClusterMultiCommand; } }); -var require_lib29 = __commonJS({ - "node_modules/.deno/@hapi+pez@6.1.0/node_modules/@hapi/pez/lib/index.js"(exports2) { +var require_cluster = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/cluster/index.js"(exports2) { "use strict"; - var Stream = __require2("stream"); - var B64 = require_lib22(); - var Boom5 = require_lib2(); - var Content = require_lib25(); - var Hoek = require_lib(); - var Nigel = require_lib28(); - var internals = {}; - internals.state = { - preamble: 0, - // Until the first boundary is received - boundary: 1, - // After a boundary, waiting for first line with optional linear-whitespace - header: 2, - // Receiving part headers - payload: 3, - // Receiving part payload - epilogue: 4 - }; - internals.defaults = { - maxBytes: Infinity, - maxParts: Infinity + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - exports2.Dispenser = class extends Stream.Writable { - constructor(options2) { - super({ autoDestroy: false }); - Hoek.assert(options2 !== null && typeof options2 === "object", "options must be an object"); - const settings = Hoek.applyToDefaults(internals.defaults, options2); - this._boundary = settings.boundary; - this._state = internals.state.preamble; - this._held = ""; - this._stream = null; - this._headers = {}; - this._name = ""; - this._pendingHeader = ""; - this._error = null; - this._bytesCount = 0; - this._partsCount = 0; - this._maxBytes = settings.maxBytes; - this._maxParts = settings.maxParts; - this._parts = new Nigel.Stream(Buffer.from("--" + settings.boundary)); - this._lines = new Nigel.Stream(Buffer.from("\r\n")); - this._parts.on("needle", () => this.#onPartEnd()); - this._parts.on("haystack", (chunk) => this.#onPart(chunk)); - this._lines.on("needle", () => this.#onLineEnd()); - this._lines.on("haystack", (chunk) => this.#onLine(chunk)); - this.once("finish", () => this._parts.end()); - this._parts.once("close", () => this._lines.end()); - let piper = null; - let finish = (err) => { - if (piper) { - piper.removeListener("data", onReqData); - piper.removeListener("error", finish); - piper.removeListener("aborted", onReqAborted); - } - if (err) { - return this.#abort(err); - } - this.#emit("close"); + Object.defineProperty(exports2, "__esModule", { value: true }); + var commands_1 = __importDefault(require_commands()); + var node_events_1 = __require2("node:events"); + var commander_1 = require_commander(); + var cluster_slots_1 = __importDefault(require_cluster_slots()); + var multi_command_1 = __importDefault(require_multi_command3()); + var errors_1 = require_errors(); + var parser_1 = require_parser(); + var ASKING_1 = require_ASKING(); + var single_entry_cache_1 = __importDefault(require_single_entry_cache()); + var RedisCluster = class _RedisCluster extends node_events_1.EventEmitter { + static #createCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this._self._execute(parser3.firstKey, command2.IS_READ_ONLY, this._commandOptions, (client, opts) => client._executeCommand(command2, parser3, opts, transformReply)); }; - finish = Hoek.once(finish); - this._lines.once("close", () => { - if (this._state === internals.state.epilogue) { - if (this._held) { - this.#emit("epilogue", this._held); - this._held = ""; - } - } else if (this._state === internals.state.boundary) { - if (!this._held) { - this.#abort(Boom5.badRequest("Missing end boundary")); - } else if (this._held !== "--") { - this.#abort(Boom5.badRequest("Only white space allowed after boundary at end")); - } - } else { - this.#abort(Boom5.badRequest("Incomplete multipart payload")); - } - setImmediate(finish); - }); - const onReqAborted = () => { - finish(Boom5.badRequest("Client request aborted")); + } + static #createModuleCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this._self._execute(parser3.firstKey, command2.IS_READ_ONLY, this._self._commandOptions, (client, opts) => client._executeCommand(command2, parser3, opts, transformReply)); }; - const onReqData = (data) => { - this._bytesCount += Buffer.byteLength(data); - if (this._bytesCount > this._maxBytes) { - finish(Boom5.entityTooLarge("Maximum size exceeded")); - } + } + static #createFunctionCommand(name, fn, resp) { + const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); + const transformReply = (0, commander_1.getTransformReply)(fn, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + fn.parseCommand(parser3, ...args); + return this._self._execute(parser3.firstKey, fn.IS_READ_ONLY, this._self._commandOptions, (client, opts) => client._executeCommand(fn, parser3, opts, transformReply)); }; - this.once("pipe", (req) => { - piper = req; - req.on("data", onReqData); - req.once("error", finish); - req.once("aborted", onReqAborted); - }); } - _write(buffer, encoding, next) { - if (this._error) { - return next(); - } - this._parts.write(buffer); - return next(); + static #createScriptCommand(script, resp) { + const prefix = (0, commander_1.scriptArgumentsPrefix)(script); + const transformReply = (0, commander_1.getTransformReply)(script, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + script.parseCommand(parser3, ...args); + return this._self._execute(parser3.firstKey, script.IS_READ_ONLY, this._commandOptions, (client, opts) => client._executeScript(script, parser3, opts, transformReply)); + }; } - #emit(...args) { - if (this._error) { - return; + static #SingleEntryCache = new single_entry_cache_1.default(); + static factory(config2) { + let Cluster = _RedisCluster.#SingleEntryCache.get(config2); + if (!Cluster) { + Cluster = (0, commander_1.attachConfig)({ + BaseClass: _RedisCluster, + commands: commands_1.default, + createCommand: _RedisCluster.#createCommand, + createModuleCommand: _RedisCluster.#createModuleCommand, + createFunctionCommand: _RedisCluster.#createFunctionCommand, + createScriptCommand: _RedisCluster.#createScriptCommand, + config: config2 + }); + Cluster.prototype.Multi = multi_command_1.default.extend(config2); + _RedisCluster.#SingleEntryCache.set(config2, Cluster); } - this.emit(...args); + return (options2) => { + return Object.create(new Cluster(options2)); + }; } - #abort(err) { - this.#emit("error", err); - this._error = err; + static create(options2) { + return _RedisCluster.factory(options2)(options2); } - #onPartEnd() { - this._lines.flush(); - if (this._state === internals.state.preamble) { - if (this._held) { - const last = this._held.length - 1; - if (this._held[last] !== "\n" || this._held[last - 1] !== "\r") { - return this.#abort(Boom5.badRequest("Preamble missing CRLF terminator")); - } - this.#emit("preamble", this._held.slice(0, -2)); - this._held = ""; - } - this._parts.needle(Buffer.from("\r\n--" + this._boundary)); - } else { - this._partsCount++; - if (this._partsCount > this._maxParts) { - return this.#abort(Boom5.badRequest("Maximum parts exceeded")); - } - } - this._state = internals.state.boundary; - if (this._stream) { - this._stream.end(); - this._stream = null; - } else if (this._name) { - this.#emit("field", this._name, this._held); - this._name = ""; - this._held = ""; - } - } - #onPart(chunk) { - if (this._state === internals.state.preamble) { - this._held = this._held + chunk.toString(); - } else if (this._state === internals.state.payload) { - if (this._stream) { - this._stream.write(chunk); - } else { - this._held = this._held + chunk.toString(); - } - } else { - this._lines.write(chunk); - } + _options; + _slots; + _self = this; + _commandOptions; + /** + * An array of the cluster slots, each slot contain its `master` and `replicas`. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). + */ + get slots() { + return this._self._slots.slots; } - #onLineEnd() { - if (this._state === internals.state.boundary) { - if (this._held) { - this._held = this._held.replace(/[\t ]/g, ""); - if (this._held) { - if (this._held === "--") { - this._state = internals.state.epilogue; - this._held = ""; - return; - } - return this.#abort(Boom5.badRequest("Only white space allowed after boundary")); - } - } - this._state = internals.state.header; - return; - } - if (this._state === internals.state.header) { - if (this._held) { - if (this._held[0] === " " || this._held[0] === " ") { - if (!this._pendingHeader) { - return this.#abort(Boom5.badRequest("Invalid header continuation without valid declaration on previous line")); - } - this._pendingHeader = this._pendingHeader + " " + this._held.slice(1); - this._held = ""; - return; - } - this.#flushHeader(); - this._pendingHeader = this._held; - this._held = ""; - return; - } - this.#flushHeader(); - this._state = internals.state.payload; - let disposition; - try { - disposition = Content.disposition(this._headers["content-disposition"]); - } catch (err) { - return this.#abort(err); - } - if (disposition.filename !== void 0) { - const stream = new Stream.PassThrough(); - const transferEncoding = this._headers["content-transfer-encoding"]; - if (transferEncoding && transferEncoding.toLowerCase() === "base64") { - this._stream = new B64.Decoder(); - this._stream.pipe(stream); - } else { - this._stream = stream; - } - stream.name = disposition.name; - stream.filename = disposition.filename; - stream.headers = this._headers; - this._headers = {}; - this.#emit("part", stream); - } else { - this._name = disposition.name; - } - this._lines.flush(); - return; - } - this._held = this._held + "\r\n"; + get clientSideCache() { + return this._self._slots.clientSideCache; } - #onLine(chunk) { - if (this._stream) { - this._stream.write(chunk); - } else { - this._held = this._held + chunk.toString(); - } + /** + * An array of the cluster masters. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific master node. + */ + get masters() { + return this._self._slots.masters; } - #flushHeader() { - if (!this._pendingHeader) { - return; - } - const sep = this._pendingHeader.indexOf(":"); - if (sep === -1) { - return this.#abort(Boom5.badRequest("Invalid header missing colon separator")); - } - if (!sep) { - return this.#abort(Boom5.badRequest("Invalid header missing field name")); - } - const name = this._pendingHeader.slice(0, sep).toLowerCase(); - if (name === "__proto__") { - return this.#abort(Boom5.badRequest("Invalid header")); - } - this._headers[name] = this._pendingHeader.slice(sep + 1).trim(); - this._pendingHeader = ""; + /** + * An array of the cluster replicas. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific replica node. + */ + get replicas() { + return this._self._slots.replicas; } - }; - } -}); -var require_payload = __commonJS({ - "node_modules/.deno/@hapi+wreck@18.1.0/node_modules/@hapi/wreck/lib/payload.js"(exports2, module14) { - "use strict"; - var Stream = __require2("stream"); - var internals = {}; - module14.exports = internals.Payload = class extends Stream.Readable { - constructor(payload, encoding) { - super(); - const data = [].concat(payload || ""); - let size = 0; - for (let i2 = 0; i2 < data.length; ++i2) { - const chunk = data[i2]; - size = size + chunk.length; - data[i2] = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); - } - this._data = Buffer.concat(data, size); - this._position = 0; - this._encoding = encoding || "utf8"; + /** + * A map form a node address (`:`) to its shard, each shard contain its `master` and `replicas`. + * Use with {@link RedisCluster.prototype.nodeClient} to get the client for a specific node (master or replica). + */ + get nodeByAddress() { + return this._self._slots.nodeByAddress; } - _read(size) { - const chunk = this._data.slice(this._position, this._position + size); - this.push(chunk, this._encoding); - this._position = this._position + chunk.length; - if (this._position >= this._data.length) { - this.push(null); - } + /** + * The current pub/sub node. + */ + get pubSubNode() { + return this._self._slots.pubSubNode; + } + get isOpen() { + return this._self._slots.isOpen; } - }; - } -}); -var require_recorder = __commonJS({ - "node_modules/.deno/@hapi+wreck@18.1.0/node_modules/@hapi/wreck/lib/recorder.js"(exports2, module14) { - "use strict"; - var Stream = __require2("stream"); - var Boom5 = require_lib2(); - var internals = {}; - module14.exports = internals.Recorder = class extends Stream.Writable { constructor(options2) { super(); - this.settings = options2; - this.buffers = []; - this.length = 0; - } - _write(chunk, encoding, next) { - if (this.settings.maxBytes && this.length + chunk.length > this.settings.maxBytes) { - return this.emit("error", Boom5.entityTooLarge("Payload content length greater than maximum allowed: " + this.settings.maxBytes)); + this._options = options2; + this._slots = new cluster_slots_1.default(options2, this.emit.bind(this)); + this.on("__resubscribeAllPubSubListeners", this.resubscribeAllPubSubListeners.bind(this)); + if (options2?.commandOptions) { + this._commandOptions = options2.commandOptions; } - this.length = this.length + chunk.length; - this.buffers.push(chunk); - next(); } - collect() { - const buffer = this.buffers.length === 0 ? Buffer.alloc(0) : this.buffers.length === 1 ? this.buffers[0] : Buffer.concat(this.buffers, this.length); - return buffer; - } - }; - } -}); -var require_tap = __commonJS({ - "node_modules/.deno/@hapi+wreck@18.1.0/node_modules/@hapi/wreck/lib/tap.js"(exports2, module14) { - "use strict"; - var Stream = __require2("stream"); - var Payload = require_payload(); - var internals = {}; - module14.exports = internals.Tap = class extends Stream.Transform { - constructor() { - super(); - this.buffers = []; + duplicate(overrides) { + return new (Object.getPrototypeOf(this)).constructor({ + ...this._self._options, + commandOptions: this._commandOptions, + ...overrides + }); } - _transform(chunk, encoding, next) { - this.buffers.push(chunk); - next(null, chunk); + async connect() { + await this._self._slots.connect(); + return this; } - collect() { - return new Payload(this.buffers); + withCommandOptions(options2) { + const proxy = Object.create(this); + proxy._commandOptions = options2; + return proxy; } - }; - } -}); -var require_lib30 = __commonJS({ - "node_modules/.deno/@hapi+wreck@18.1.0/node_modules/@hapi/wreck/lib/index.js"(exports2, module14) { - "use strict"; - var Events2 = __require2("events"); - var Http = __require2("http"); - var Https = __require2("https"); - var Stream = __require2("stream"); - var Url = __require2("url"); - var Zlib = __require2("zlib"); - var Boom5 = require_lib2(); - var Bourne = require_lib20(); - var Hoek = require_lib(); - var Payload = require_payload(); - var Recorder = require_recorder(); - var Tap = require_tap(); - var internals = { - jsonRegex: /^application\/([a-z0-9.]*[+-]json|json)$/, - shallowOptions: ["agent", "agents", "beforeRedirect", "payload", "redirected"], - httpOptions: ["secureProtocol", "ciphers", "lookup", "family", "hints"] - }; - internals.Client = class { - constructor(options2 = {}) { - Hoek.assert(!options2.agents || options2.agents.https && options2.agents.http && options2.agents.httpsAllowUnauthorized, 'Option agents must include "http", "https", and "httpsAllowUnauthorized"'); - this._defaults = Hoek.clone(options2, { shallow: internals.shallowOptions }); - this.agents = this._defaults.agents || { - https: new Https.Agent({ maxSockets: Infinity }), - http: new Http.Agent({ maxSockets: Infinity }), - httpsAllowUnauthorized: new Https.Agent({ maxSockets: Infinity, rejectUnauthorized: false }) - }; - if (this._defaults.events) { - this.events = new Events2.EventEmitter(); - } + _commandOptionsProxy(key, value) { + const proxy = Object.create(this); + proxy._commandOptions = Object.create(this._commandOptions ?? null); + proxy._commandOptions[key] = value; + return proxy; } - defaults(options2) { - Hoek.assert(options2 && typeof options2 === "object", "options must be provided to defaults"); - options2 = Hoek.applyToDefaults(this._defaults, options2, { shallow: internals.shallowOptions }); - return new internals.Client(options2); + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping) { + return this._commandOptionsProxy("typeMapping", typeMapping); } - request(method, url2, options2 = {}) { - try { - options2 = Hoek.applyToDefaults(this._defaults, options2, { shallow: internals.shallowOptions }); - Hoek.assert(options2.payload === void 0 || typeof options2.payload === "string" || typeof options2.payload === "object", "options.payload must be a string, a Buffer, a Stream, or an Object"); - Hoek.assert(internals.isNullOrUndefined(options2.agent) || typeof options2.rejectUnauthorized !== "boolean", "options.agent cannot be set to an Agent at the same time as options.rejectUnauthorized is set"); - Hoek.assert(internals.isNullOrUndefined(options2.beforeRedirect) || typeof options2.beforeRedirect === "function", "options.beforeRedirect must be a function"); - Hoek.assert(internals.isNullOrUndefined(options2.redirected) || typeof options2.redirected === "function", "options.redirected must be a function"); - Hoek.assert(options2.gunzip === void 0 || typeof options2.gunzip === "boolean" || options2.gunzip === "force", 'options.gunzip must be a boolean or "force"'); - } catch (err) { - return Promise.reject(err); - } - if (options2.baseUrl) { - url2 = internals.resolveUrl(options2.baseUrl, url2); - delete options2.baseUrl; - } - const relay = {}; - const req = this._request(method, url2, options2, relay); - const promise = new Promise((resolve82, reject) => { - relay.callback = (err, res) => { - if (err) { - reject(err); - return; - } - resolve82(res); - return; - }; - }); - promise.req = req; - return promise; + // /** + // * Override the `policies` command option + // * TODO + // */ + // withPolicies (policies: POLICIES) { + // return this._commandOptionsProxy('policies', policies); + // } + _handleAsk(fn) { + return async (client, options2) => { + const chainId = Symbol("asking chain"); + const opts = options2 ? { ...options2 } : {}; + opts.chainId = chainId; + const ret = await Promise.all([ + client.sendCommand([ASKING_1.ASKING_CMD], { chainId }), + fn(client, opts) + ]); + return ret[1]; + }; } - _request(method, url2, options2, relay, _trace) { - const uri = {}; - if (options2.socketPath) { - uri.socketPath = options2.socketPath; - const parsedUri = new Url.URL(url2, `unix://${options2.socketPath}`); - internals.applyUrlToOptions(uri, { - host: "", - // host must be empty according to https://tools.ietf.org/html/rfc2616#section-14.23 - protocol: "http:", - hash: parsedUri.hash, - search: parsedUri.search, - searchParams: parsedUri.searchParams, - pathname: parsedUri.pathname, - href: parsedUri.href - }); - } else { - uri.setHost = false; - const parsedUri = new Url.URL(url2); - internals.applyUrlToOptions(uri, parsedUri); - } - uri.method = method.toUpperCase(); - uri.headers = /* @__PURE__ */ Object.create(null); - const usedHeaders = /* @__PURE__ */ new Set(); - if (options2.headers) { - for (const [key, value] of Object.entries(options2.headers)) { - if (value !== void 0) { - uri.headers[key] = value; - usedHeaders.add(key.toLowerCase()); + async _execute(firstKey, isReadonly, options2, fn) { + const maxCommandRedirections = this._options.maxCommandRedirections ?? 16; + let client = await this._slots.getClient(firstKey, isReadonly); + let i2 = 0; + let myFn = fn; + while (true) { + try { + return await myFn(client, options2); + } catch (err) { + myFn = fn; + if (++i2 > maxCommandRedirections || !(err instanceof Error)) { + throw err; } - } - } - if (!usedHeaders.has("host")) { - uri.headers.host = uri.host; - } - if (options2.payload && typeof options2.payload === "object" && !(options2.payload instanceof Stream) && !Buffer.isBuffer(options2.payload)) { - options2.payload = JSON.stringify(options2.payload); - if (!usedHeaders.has("content-type")) { - uri.headers["content-type"] = "application/json"; - } - } - if (options2.gunzip && !usedHeaders.has("accept-encoding")) { - uri.headers["accept-encoding"] = "gzip"; - } - const payloadSupported = uri.method !== "GET" && uri.method !== "HEAD" && !internals.isNullOrUndefined(options2.payload); - if (payloadSupported && (typeof options2.payload === "string" || Buffer.isBuffer(options2.payload)) && !usedHeaders.has("content-length")) { - uri.headers["content-length"] = Buffer.isBuffer(options2.payload) ? options2.payload.length : Buffer.byteLength(options2.payload); - } - let redirects = options2.hasOwnProperty("redirects") ? options2.redirects : false; - _trace = _trace ?? []; - _trace.push({ method: uri.method, url: url2 }); - const client = uri.protocol === "https:" ? Https : Http; - for (const option of internals.httpOptions) { - if (options2[option] !== void 0) { - uri[option] = options2[option]; - } - } - if (options2.rejectUnauthorized !== void 0 && uri.protocol === "https:") { - uri.agent = options2.rejectUnauthorized ? this.agents.https : this.agents.httpsAllowUnauthorized; - } else if (options2.agent || options2.agent === false) { - uri.agent = options2.agent; - } else { - uri.agent = uri.protocol === "https:" ? this.agents.https : this.agents.http; - } - this._emit("preRequest", uri, options2); - const start = Date.now(); - const req = client.request(uri); - this._emit("request", req); - let shadow = null; - let timeoutId; - const onError = (err) => { - err.trace = _trace; - return finishOnce(Boom5.badGateway("Client request error", err)); - }; - const onAbort = () => { - if (!req.socket) { - const error2 = new Error("socket hang up"); - error2.code = "ECONNRESET"; - finishOnce(error2); - } - }; - req.once("error", onError); - const onResponse = (res) => { - const statusCode = res.statusCode; - const redirectMethod = internals.redirectMethod(statusCode, uri.method, options2); - if (redirects === false || !redirectMethod) { - return finishOnce(null, res); - } - res.destroy(); - if (redirects === 0) { - return finishOnce(Boom5.badGateway("Maximum redirections reached", _trace)); - } - let location = res.headers.location; - if (!location) { - return finishOnce(Boom5.badGateway("Received redirection without location", _trace)); - } - if (!/^https?:/i.test(location)) { - location = Url.resolve(uri.href, location); - } - const redirectOptions = Hoek.clone(options2, { shallow: internals.shallowOptions }); - redirectOptions.payload = shadow ?? options2.payload; - redirectOptions.redirects = --redirects; - if (timeoutId) { - clearTimeout(timeoutId); - const elapsed = Date.now() - start; - redirectOptions.timeout = (redirectOptions.timeout - elapsed).toString(); - } - if (redirectOptions.headers) { - const parsedLocation = new URL(location); - if (uri.hostname !== parsedLocation.hostname) { - for (const header of Object.keys(redirectOptions.headers)) { - const lowerHeader = header.toLowerCase(); - if (lowerHeader === "authorization" || lowerHeader === "cookie") { - delete redirectOptions.headers[header]; - } + if (err.message.startsWith("ASK")) { + const address = err.message.substring(err.message.lastIndexOf(" ") + 1); + let redirectTo = await this._slots.getMasterByAddress(address); + if (!redirectTo) { + await this._slots.rediscover(client); + redirectTo = await this._slots.getMasterByAddress(address); } + if (!redirectTo) { + throw new Error(`Cannot find node ${address}`); + } + client = redirectTo; + myFn = this._handleAsk(fn); + continue; } - } - const followRedirect = (err) => { - if (err) { - err.trace = _trace; - return finishOnce(Boom5.badGateway("Invalid redirect", err)); - } - const redirectReq = this._request(redirectMethod, location, redirectOptions, { callback: finishOnce }, _trace); - if (options2.redirected) { - options2.redirected(statusCode, location, redirectReq); + if (err.message.startsWith("MOVED")) { + await this._slots.rediscover(client); + client = await this._slots.getClient(firstKey, isReadonly); + continue; } - }; - if (!options2.beforeRedirect) { - return followRedirect(); + throw err; } - return options2.beforeRedirect(redirectMethod, statusCode, location, res.headers, redirectOptions, followRedirect); - }; - const finish = (err, res) => { - if (err) { - req.abort(); - } - req.removeListener("response", onResponse); - req.removeListener("error", onError); - req.removeListener("abort", onAbort); - req.on("error", Hoek.ignore); - clearTimeout(timeoutId); - this._emit("response", err, { req, res, start, uri }); - return relay.callback(err, res); + } + } + async sendCommand(firstKey, isReadonly, args, options2) { + const opts = { + ...this._self._commandOptions, + ...options2 }; - const finishOnce = Hoek.once(finish); - req.once("response", onResponse); - if (options2.timeout) { - timeoutId = setTimeout(() => finishOnce(Boom5.gatewayTimeout("Client request timeout")), options2.timeout); - } - req.on("abort", onAbort); - if (payloadSupported) { - if (options2.payload instanceof Stream) { - let stream = options2.payload; - if (redirects) { - const collector = new Tap(); - collector.once("finish", () => { - shadow = collector.collect(); - }); - stream = options2.payload.pipe(collector); + return this._self._execute(firstKey, isReadonly, opts, (client, opts2) => client.sendCommand(args, opts2)); + } + MULTI(routing) { + return new this.Multi(async (firstKey, isReadonly, commands) => { + const client = await this._self._slots.getClient(firstKey, isReadonly); + return client._executeMulti(commands); + }, async (firstKey, isReadonly, commands) => { + const client = await this._self._slots.getClient(firstKey, isReadonly); + return client._executePipeline(commands); + }, routing, this._commandOptions?.typeMapping); + } + multi = this.MULTI; + async SUBSCRIBE(channels, listener, bufferMode) { + return (await this._self._slots.getPubSubClient()).SUBSCRIBE(channels, listener, bufferMode); + } + subscribe = this.SUBSCRIBE; + async UNSUBSCRIBE(channels, listener, bufferMode) { + return this._self._slots.executeUnsubscribeCommand((client) => client.UNSUBSCRIBE(channels, listener, bufferMode)); + } + unsubscribe = this.UNSUBSCRIBE; + async PSUBSCRIBE(patterns, listener, bufferMode) { + return (await this._self._slots.getPubSubClient()).PSUBSCRIBE(patterns, listener, bufferMode); + } + pSubscribe = this.PSUBSCRIBE; + async PUNSUBSCRIBE(patterns, listener, bufferMode) { + return this._self._slots.executeUnsubscribeCommand((client) => client.PUNSUBSCRIBE(patterns, listener, bufferMode)); + } + pUnsubscribe = this.PUNSUBSCRIBE; + async SSUBSCRIBE(channels, listener, bufferMode) { + const maxCommandRedirections = this._self._options.maxCommandRedirections ?? 16, firstChannel = Array.isArray(channels) ? channels[0] : channels; + let client = await this._self._slots.getShardedPubSubClient(firstChannel); + for (let i2 = 0; ; i2++) { + try { + return await client.SSUBSCRIBE(channels, listener, bufferMode); + } catch (err) { + if (++i2 > maxCommandRedirections || !(err instanceof errors_1.ErrorReply)) { + throw err; + } + if (err.message.startsWith("MOVED")) { + await this._self._slots.rediscover(client); + client = await this._self._slots.getShardedPubSubClient(firstChannel); + continue; } - internals.deferPipeUntilSocketConnects(req, stream); - return req; + throw err; } - req.write(options2.payload); } - req.end(); - return req; } - _emit(...args) { - if (this.events) { - this.events.emit(...args); - } + sSubscribe = this.SSUBSCRIBE; + SUNSUBSCRIBE(channels, listener, bufferMode) { + return this._self._slots.executeShardedUnsubscribeCommand(Array.isArray(channels) ? channels[0] : channels, (client) => client.SUNSUBSCRIBE(channels, listener, bufferMode)); } - read(res, options2 = {}) { - return new Promise((resolve82, reject) => { - this._read(res, options2, (err, payload) => { - if (err) { - reject(err); - return; - } - resolve82(payload); - return; + resubscribeAllPubSubListeners(allListeners) { + for (const [channel, listeners] of allListeners.CHANNELS) { + listeners.buffers.forEach((bufListener) => { + this.subscribe(channel, bufListener, true); + }); + listeners.strings.forEach((strListener) => { + this.subscribe(channel, strListener); }); - }); - } - _read(res, options2, callback) { - options2 = Hoek.applyToDefaults(this._defaults, options2, { shallow: internals.shallowOptions }); - let clientTimeoutId = null; - const finish = (err, buffer) => { - clearTimeout(clientTimeoutId); - reader.removeListener("error", onReaderError); - reader.removeListener("finish", onReaderFinish); - res.removeListener("error", onResError); - res.removeListener("close", onResAborted); - res.removeListener("aborted", onResAborted); - res.on("error", Hoek.ignore); - if (err) { - return callback(err); - } - if (!options2.json) { - return callback(null, buffer); - } - if (options2.json === "force") { - return internals.tryParseBuffer(buffer, callback); - } - const contentType = res.headers?.["content-type"] ?? ""; - const mime = contentType.split(";")[0].trim().toLowerCase(); - if (!internals.jsonRegex.test(mime)) { - if (options2.json === "strict") { - return callback(Boom5.notAcceptable("The content-type is not JSON compatible")); - } - return callback(null, buffer); - } - return internals.tryParseBuffer(buffer, callback); - }; - const finishOnce = Hoek.once(finish); - const clientTimeout = options2.timeout; - if (clientTimeout && clientTimeout > 0) { - clientTimeoutId = setTimeout(() => finishOnce(Boom5.clientTimeout()), clientTimeout); } - const onResError = (err) => { - return finishOnce(err.isBoom ? err : Boom5.internal("Payload stream error", err)); - }; - const onResAborted = () => { - if (!res.complete) { - finishOnce(Boom5.internal("Payload stream closed prematurely")); - } - }; - res.once("error", onResError); - res.once("close", onResAborted); - res.once("aborted", onResAborted); - const reader = new Recorder({ maxBytes: options2.maxBytes }); - const onReaderError = (err) => { - if (res.destroy) { - res.destroy(); - } - return finishOnce(err); - }; - reader.once("error", onReaderError); - const onReaderFinish = () => { - return finishOnce(null, reader.collect()); - }; - reader.once("finish", onReaderFinish); - if (options2.gunzip) { - const contentEncoding = options2.gunzip === "force" ? "gzip" : res.headers?.["content-encoding"] ?? ""; - if (/^(x-)?gzip(\s*,\s*identity)?$/.test(contentEncoding)) { - const gunzip = Zlib.createGunzip(); - gunzip.once("error", onReaderError); - res.pipe(gunzip).pipe(reader); - return; - } + ; + for (const [channel, listeners] of allListeners.PATTERNS) { + listeners.buffers.forEach((bufListener) => { + this.pSubscribe(channel, bufListener, true); + }); + listeners.strings.forEach((strListener) => { + this.pSubscribe(channel, strListener); + }); + } + ; + for (const [channel, listeners] of allListeners.SHARDED) { + listeners.buffers.forEach((bufListener) => { + this.sSubscribe(channel, bufListener, true); + }); + listeners.strings.forEach((strListener) => { + this.sSubscribe(channel, strListener); + }); } - res.pipe(reader); + ; } - toReadableStream(payload, encoding) { - return new Payload(payload, encoding); + sUnsubscribe = this.SUNSUBSCRIBE; + /** + * @deprecated Use `close` instead. + */ + quit() { + return this._self._slots.quit(); } - parseCacheControl(field) { - const regex = /(?:^|(?:\s*\,\s*))([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g; - const header = {}; - const error2 = field.replace(regex, ($0, $1, $2, $3) => { - const value = $2 || $3; - header[$1] = value ? value.toLowerCase() : true; - return ""; - }); - if (header["max-age"]) { - try { - const maxAge2 = parseInt(header["max-age"], 10); - if (isNaN(maxAge2)) { - return null; - } - header["max-age"] = maxAge2; - } catch (err) { - } - } - return error2 ? null : header; + /** + * @deprecated Use `destroy` instead. + */ + disconnect() { + return this._self._slots.disconnect(); } - // Shortcuts - get(uri, options2) { - return this._shortcut("GET", uri, options2); + close() { + this._self._slots.clientSideCache?.onPoolClose(); + return this._self._slots.close(); } - post(uri, options2) { - return this._shortcut("POST", uri, options2); + destroy() { + this._self._slots.clientSideCache?.onPoolClose(); + return this._self._slots.destroy(); } - patch(uri, options2) { - return this._shortcut("PATCH", uri, options2); + nodeClient(node) { + return this._self._slots.nodeClient(node); } - put(uri, options2) { - return this._shortcut("PUT", uri, options2); + /** + * Returns a random node from the cluster. + * Userful for running "forward" commands (like PUBLISH) on a random node. + */ + getRandomNode() { + return this._self._slots.getRandomNode(); } - delete(uri, options2) { - return this._shortcut("DELETE", uri, options2); + /** + * Get a random node from a slot. + * Useful for running readonly commands on a slot. + */ + getSlotRandomNode(slot) { + return this._self._slots.getSlotRandomNode(slot); } - async _shortcut(method, uri, options2 = {}) { - const res = await this.request(method, uri, options2); - let payload; - try { - payload = await this.read(res, options2); - } catch (err) { - err.data = err.data ?? {}; - err.data.res = res; - throw err; - } - if (res.statusCode < 400) { - return { res, payload }; - } - const data = { - isResponseError: true, - headers: res.headers, - res, - payload - }; - throw new Boom5.Boom(`Response Error: ${res.statusCode} ${res.statusMessage}`, { statusCode: res.statusCode, data }); + /** + * @deprecated use `.masters` instead + * TODO + */ + getMasters() { + return this.masters; } - }; - internals.resolveUrl = function(baseUrl, path8) { - if (!path8) { - return baseUrl; + /** + * @deprecated use `.slots[]` instead + * TODO + */ + getSlotMaster(slot) { + return this.slots[slot].master; } - const url2 = new Url.URL(path8, baseUrl); - return Url.format(url2); }; - internals.deferPipeUntilSocketConnects = function(req, stream) { - const onSocket = (socket) => { - if (!socket.connecting) { - return onSocketConnect(); + exports2.default = RedisCluster; + } +}); +var require_utils = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/utils.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createScriptCommand = exports2.createModuleCommand = exports2.createFunctionCommand = exports2.createCommand = exports2.clientSocketToNode = exports2.createNodeList = exports2.parseNode = void 0; + var parser_1 = require_parser(); + var commander_1 = require_commander(); + function parseNode(node) { + if (node.flags.includes("s_down") || node.flags.includes("disconnected") || node.flags.includes("failover_in_progress")) { + return void 0; + } + return { host: node.ip, port: Number(node.port) }; + } + exports2.parseNode = parseNode; + function createNodeList(nodes) { + var nodeList = []; + for (const nodeData of nodes) { + const node = parseNode(nodeData); + if (node === void 0) { + continue; } - socket.once("connect", onSocketConnect); + nodeList.push(node); + } + return nodeList; + } + exports2.createNodeList = createNodeList; + function clientSocketToNode(socket) { + const s = socket; + return { + host: s.host, + port: s.port + }; + } + exports2.clientSocketToNode = clientSocketToNode; + function createCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this._self._execute(command2.IS_READ_ONLY, (client) => client._executeCommand(command2, parser3, this.commandOptions, transformReply)); }; - const onSocketConnect = () => { - stream.pipe(req); - stream.removeListener("error", onStreamError); + } + exports2.createCommand = createCommand; + function createFunctionCommand(name, fn, resp) { + const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); + const transformReply = (0, commander_1.getTransformReply)(fn, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + fn.parseCommand(parser3, ...args); + return this._self._execute(fn.IS_READ_ONLY, (client) => client._executeCommand(fn, parser3, this._self.commandOptions, transformReply)); }; - const onStreamError = (err) => { - req.emit("error", err); + } + exports2.createFunctionCommand = createFunctionCommand; + function createModuleCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + return this._self._execute(command2.IS_READ_ONLY, (client) => client._executeCommand(command2, parser3, this._self.commandOptions, transformReply)); }; - req.once("socket", onSocket); - stream.on("error", onStreamError); - }; - internals.redirectMethod = function(code2, method, options2) { - switch (code2) { - case 301: - case 302: - return options2.redirectMethod || method; - case 303: - if (options2.redirect303) { - return "GET"; - } - break; - case 307: - case 308: - return method; - } - return null; - }; - internals.tryParseBuffer = function(buffer, next) { - if (buffer.length === 0) { - return next(null, null); - } - let payload; - try { - payload = Bourne.parse(buffer.toString()); - } catch (err) { - return next(Boom5.badGateway(err.message, { payload: buffer })); - } - return next(null, payload); - }; - internals.applyUrlToOptions = (options2, url2) => { - options2.host = url2.host; - options2.origin = url2.origin; - options2.searchParams = url2.searchParams; - options2.protocol = url2.protocol; - options2.hostname = typeof url2.hostname === "string" && url2.hostname.startsWith("[") ? url2.hostname.slice(1, -1) : url2.hostname; - options2.hash = url2.hash; - options2.search = url2.search; - options2.pathname = url2.pathname; - options2.path = `${url2.pathname}${url2.search}`; - options2.href = url2.href; - if (url2.port !== "") { - options2.port = Number(url2.port); - } - if (url2.username || url2.password) { - options2.auth = `${url2.username}:${url2.password}`; - options2.username = url2.username; - options2.password = url2.password; - } - return options2; - }; - internals.isNullOrUndefined = (val) => [null, void 0].includes(val); - module14.exports = new internals.Client(); - } -}); -var require_lib31 = __commonJS({ - "node_modules/.deno/@hapi+subtext@8.1.1/node_modules/@hapi/subtext/lib/index.js"(exports2) { - "use strict"; - var Fs = __require2("fs"); - var Fsp = __require2("fs/promises"); - var Os = __require2("os"); - var Querystring = __require2("querystring"); - var Stream = __require2("stream"); - var Zlib = __require2("zlib"); - var Boom5 = require_lib2(); - var Bourne = require_lib20(); - var Content = require_lib25(); - var File2 = require_lib26(); - var Hoek = require_lib(); - var Pez = require_lib29(); - var Wreck = require_lib30(); - var internals = { - kSubtext: Symbol("subtext"), - decoders: { - gzip: (options2) => Zlib.createGunzip(options2), - deflate: (options2) => Zlib.createInflate(options2) - } - }; - exports2.parse = async function(req, tap, options2) { - Hoek.assert(options2, "Missing options"); - Hoek.assert(options2.parse !== void 0, "Missing parse option setting"); - Hoek.assert(options2.output !== void 0, "Missing output option setting"); - const contentLength = req.headers["content-length"]; - if (options2.maxBytes !== void 0 && contentLength && parseInt(contentLength, 10) > options2.maxBytes) { - throw Boom5.entityTooLarge("Payload content length greater than maximum allowed: " + options2.maxBytes); - } - const contentType = Content.type(options2.override || req.headers["content-type"] || options2.defaultContentType || "application/octet-stream"); - try { - if (options2.allow && options2.allow.indexOf(contentType.mime) === -1) { - throw Boom5.unsupportedMediaType(); - } - const parsed = { mime: contentType.mime }; - if (options2.parse === true) { - parsed.payload = await internals.parse(req, tap, options2, contentType); - return parsed; - } - parsed.payload = await internals.raw(req, tap, options2); - return parsed; - } catch (err) { - err.mime = contentType.mime; - throw err; - } + } + exports2.createModuleCommand = createModuleCommand; + function createScriptCommand(script, resp) { + const prefix = (0, commander_1.scriptArgumentsPrefix)(script); + const transformReply = (0, commander_1.getTransformReply)(script, resp); + return async function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + script.parseCommand(parser3, ...args); + return this._self._execute(script.IS_READ_ONLY, (client) => client._executeScript(script, parser3, this.commandOptions, transformReply)); + }; + } + exports2.createScriptCommand = createScriptCommand; + } +}); +var require_multi_commands = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/multi-commands.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - internals.parse = async function(req, tap, options2, contentType) { - const output = options2.output; - let source = internals.decoder(req, options2); - if (tap) { - [source] = internals.pipe(source, tap); + Object.defineProperty(exports2, "__esModule", { value: true }); + var commands_1 = __importDefault(require_commands()); + var multi_command_1 = __importDefault(require_multi_command()); + var commander_1 = require_commander(); + var parser_1 = require_parser(); + var RedisSentinelMultiCommand = class _RedisSentinelMultiCommand { + static _createCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + return this.addCommand(command2.IS_READ_ONLY, redisArgs, transformReply); + }; } - if (contentType.mime === "multipart/form-data") { - if (options2.multipart === false) { - throw Boom5.unsupportedMediaType(); - } - return await internals.multipart(req, options2, source, contentType); + static _createModuleCommand(command2, resp) { + const transformReply = (0, commander_1.getTransformReply)(command2, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + command2.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + return this._self.addCommand(command2.IS_READ_ONLY, redisArgs, transformReply); + }; } - if (output === "stream") { - return source; + static _createFunctionCommand(name, fn, resp) { + const prefix = (0, commander_1.functionArgumentsPrefix)(name, fn); + const transformReply = (0, commander_1.getTransformReply)(fn, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + parser3.push(...prefix); + fn.parseCommand(parser3, ...args); + const redisArgs = parser3.redisArgs; + redisArgs.preserve = parser3.preserve; + return this._self.addCommand(fn.IS_READ_ONLY, redisArgs, transformReply); + }; } - if (output === "file") { - const file = await internals.writeFile(req, options2, source); - return file.item; + static _createScriptCommand(script, resp) { + const transformReply = (0, commander_1.getTransformReply)(script, resp); + return function(...args) { + const parser3 = new parser_1.BasicCommandParser(); + script.parseCommand(parser3, ...args); + const scriptArgs = parser3.redisArgs; + scriptArgs.preserve = parser3.preserve; + return this.#addScript(script.IS_READ_ONLY, script, scriptArgs, transformReply); + }; } - const payload = await Wreck.read(source, { timeout: options2.timeout, maxBytes: options2.maxBytes }); - return internals.object(options2, payload, contentType.mime); - }; - internals.decoder = function(source, options2) { - const contentEncoding = source.headers["content-encoding"]; - const decoders = options2.decoders ?? internals.decoders; - if (!decoders.hasOwnProperty(contentEncoding)) { - return source; + static extend(config2) { + return (0, commander_1.attachConfig)({ + BaseClass: _RedisSentinelMultiCommand, + commands: commands_1.default, + createCommand: _RedisSentinelMultiCommand._createCommand, + createModuleCommand: _RedisSentinelMultiCommand._createModuleCommand, + createFunctionCommand: _RedisSentinelMultiCommand._createFunctionCommand, + createScriptCommand: _RedisSentinelMultiCommand._createScriptCommand, + config: config2 + }); } - const decoderOptions = options2.compression?.[contentEncoding] ?? null; - const stream = decoders[contentEncoding](decoderOptions); - const orig = stream.emit; - stream.emit = (event, ...args) => { - if (event === "error") { - args = [Boom5.badRequest("Invalid compressed payload", args[0])]; - } - return orig.call(stream, event, ...args); - }; - [source] = internals.pipe(source, stream); - return source; - }; - internals.raw = async function(req, tap, options2) { - const output = options2.output; - let source = req; - if (options2.parse === "gunzip") { - source = internals.decoder(source, options2); + #multi = new multi_command_1.default(); + #sentinel; + #isReadonly = true; + constructor(sentinel, typeMapping) { + this.#multi = new multi_command_1.default(typeMapping); + this.#sentinel = sentinel; } - if (tap) { - [source] = internals.pipe(source, tap); + #setState(isReadonly) { + this.#isReadonly &&= isReadonly; } - if (output === "stream") { - return source; + addCommand(isReadonly, args, transformReply) { + this.#setState(isReadonly); + this.#multi.addCommand(args, transformReply); + return this; } - if (output === "file") { - const file = await internals.writeFile(req, options2, source); - return file.item; + #addScript(isReadonly, script, args, transformReply) { + this.#setState(isReadonly); + this.#multi.addScript(script, args, transformReply); + return this; } - return await Wreck.read(source, { timeout: options2.timeout, maxBytes: options2.maxBytes }); - }; - internals.object = function(options2, payload, mime) { - if (mime === "application/octet-stream") { - return payload.length ? payload : null; + async exec(execAsPipeline = false) { + if (execAsPipeline) + return this.execAsPipeline(); + return this.#multi.transformReplies(await this.#sentinel._executeMulti(this.#isReadonly, this.#multi.queue)); } - if (mime.match(/^text\/.+$/)) { - return payload.toString("utf8"); + EXEC = this.exec; + execTyped(execAsPipeline = false) { + return this.exec(execAsPipeline); } - if (/^application\/(?:.+\+)?json$/.test(mime)) { - if (!payload.length) { - return null; - } - try { - return Bourne.parse(payload.toString("utf8"), { protoAction: options2.protoAction }); - } catch (err) { - const error3 = Boom5.badRequest("Invalid request payload JSON format", err); - error3.raw = payload; - throw error3; - } + async execAsPipeline() { + if (this.#multi.queue.length === 0) + return []; + return this.#multi.transformReplies(await this.#sentinel._executePipeline(this.#isReadonly, this.#multi.queue)); } - if (mime === "application/x-www-form-urlencoded") { - const parse52 = options2.querystring ?? Querystring.parse; - return payload.length ? parse52(payload.toString("utf8")) : {}; + execAsPipelineTyped() { + return this.execAsPipeline(); } - const error2 = Boom5.unsupportedMediaType(); - error2.raw = payload; - throw error2; }; - internals.multipart = function(req, options2, source, contentType) { - return new Promise((resolve82, reject) => { - const clientTimeout = options2.timeout; - const clientTimeoutId = clientTimeout ? setTimeout(() => reject(Boom5.clientTimeout()), clientTimeout) : null; - const dispenserOptions = Hoek.applyToDefaults(contentType, { - maxBytes: options2.maxBytes, - maxParts: options2.maxParts - }); - const dispenser = new Pez.Dispenser(dispenserOptions); - const data = {}; - const pendingFiles = []; - const onError = (err) => { - const cleanup = internals.cleanupFiles(pendingFiles); - cleanup.catch(Hoek.ignore); - reject(Boom5.badRequest("Invalid multipart payload format", err)); - }; - dispenser.once("error", onError); - const set = (name, value) => { - if (!data.hasOwnProperty(name)) { - data[name] = value; - } else if (Array.isArray(data[name])) { - data[name].push(value); - } else { - data[name] = [data[name], value]; - } - }; - const finalize = async () => { - clearTimeout(clientTimeoutId); - dispenser.removeListener("error", onError); - dispenser.removeListener("part", onPart); - dispenser.removeListener("field", onField); - dispenser.removeListener("close", onClose); - try { - const files = await Promise.all(pendingFiles); - for (const { item, name } of files) { - set(name, item); - } - } catch (err) { - reject(err); - return; + exports2.default = RedisSentinelMultiCommand; + } +}); +var require_pub_sub_proxy = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/pub-sub-proxy.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.PubSubProxy = void 0; + var node_events_1 = __importDefault(__require2("node:events")); + var pub_sub_1 = require_pub_sub(); + var client_1 = __importDefault(require_client()); + var PubSubProxy = class extends node_events_1.default { + #clientOptions; + #onError; + #node; + #state; + #subscriptions; + constructor(clientOptions, onError) { + super(); + this.#clientOptions = clientOptions; + this.#onError = onError; + } + #createClient() { + if (this.#node === void 0) { + throw new Error("pubSubProxy: didn't define node to do pubsub against"); + } + return new client_1.default({ + ...this.#clientOptions, + socket: { + ...this.#clientOptions.socket, + host: this.#node.host, + port: this.#node.port } - resolve82(data); - }; - const output = typeof options2.multipart === "object" ? options2.multipart.output : options2.output; - const onPart = (part) => { - if (output === "file") { - pendingFiles.push(internals.writeFile(req, options2, part)); - } else { - internals.part(part, output, set, options2); + }); + } + async #initiatePubSubClient(withSubscriptions = false) { + const client = this.#createClient().on("error", this.#onError); + const connectPromise = client.connect().then(async (client2) => { + if (this.#state?.client !== client2) { + client2.destroy(); + return this.#state?.connectPromise; } - }; - dispenser.on("part", onPart); - const onField = (name, value) => set(name, value); - dispenser.on("field", onField); - const onClose = () => finalize(); - dispenser.once("close", onClose); - source.pipe(dispenser); - }); - }; - internals.writeFile = function(req, options2, stream) { - const promise = new Promise((resolve82, reject) => { - const path8 = File2.uniqueFilename(options2.uploads ?? Os.tmpdir()); - const file = Fs.createWriteStream(path8, { flags: "wx" }); - const counter = new internals.Counter(options2); - const finalize = (err) => { - req.removeListener("aborted", onAbort); - file.removeListener("close", finalize); - file.removeListener("error", finalize); - if (err) { - unpipeStreamToCounter(); - unpipeCounterToFile(); - file.close(); - Fs.unlink(path8, () => reject(err)); - return; + if (withSubscriptions && this.#subscriptions) { + await Promise.all([ + client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS, this.#subscriptions[pub_sub_1.PUBSUB_TYPE.CHANNELS]), + client2.extendPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS, this.#subscriptions[pub_sub_1.PUBSUB_TYPE.PATTERNS]) + ]); } - const result = { - item: { - path: path8, - bytes: counter.bytes - } - }; - if (stream.name) { - result.name = stream.name; - result.item.filename = stream.filename; - result.item.headers = stream.headers; + if (this.#state.client !== client2) { + client2.destroy(); + return this.#state?.connectPromise; } - resolve82(result); - }; - file.once("close", finalize); - file.once("error", finalize); - const onAbort = () => finalize(Boom5.badRequest("Client connection aborted")); - req.once("aborted", onAbort); - const [, unpipeStreamToCounter] = internals.pipe(stream, counter); - const [, unpipeCounterToFile] = internals.pipe(counter, file); - }); - promise.catch(Hoek.ignore); - return promise; - }; - internals.cleanupFiles = async (pendingFiles) => { - const results = await Promise.allSettled(pendingFiles); - await Promise.all(results.map(async (result) => { - if (result.value) { - await Fsp.unlink(result.value.item.path); - } - })); - }; - internals.part = async function(part, output, set, options2) { - const payload = await Wreck.read(part); - if (output === "stream") { - const item = Wreck.toReadableStream(payload); - item.hapi = { - filename: part.filename, - headers: part.headers + this.#state.connectPromise = void 0; + return client2; + }).catch((err) => { + this.#state = void 0; + throw err; + }); + this.#state = { + client, + connectPromise }; - return set(part.name, item); - } - const ct = part.headers["content-type"] || ""; - const mime = ct.split(";")[0].trim().toLowerCase(); - const annotate = (value) => set(part.name, output === "annotated" ? { filename: part.filename, headers: part.headers, payload: value } : value); - if (!mime) { - return annotate(payload); - } - if (!payload.length) { - return annotate({}); + return connectPromise; } - try { - const object2 = internals.object(options2, payload, mime); - annotate(object2); - } catch (err) { - annotate(payload); + #getPubSubClient() { + if (!this.#state) + return this.#initiatePubSubClient(); + return this.#state.connectPromise ?? this.#state.client; } - }; - internals.pipe = function(from3, to) { - const forwardError = (err) => { - unpipe(); - to.emit("error", err); - }; - const unpipe = () => { - from3.removeListener("error", forwardError); - return from3.unpipe(to); - }; - from3.once("error", forwardError); - return [from3.pipe(to), unpipe]; - }; - internals.Counter = class extends Stream.Transform { - constructor(options2) { - super(); - this.bytes = 0; - this._maxBytes = options2.maxBytes; - } - _transform(chunk, encoding, next) { - this.bytes = this.bytes + chunk.length; - if (this._maxBytes !== void 0 && this.bytes > this._maxBytes) { - return next(Boom5.entityTooLarge("Payload content length greater than maximum allowed: " + this._maxBytes)); - } - return next(null, chunk); - } - }; - } -}); -var require_ext = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/ext.js"(exports2, module14) { - "use strict"; - var Hoek = require_lib(); - var Topo = require_lib8(); - var internals = {}; - exports2 = module14.exports = internals.Ext = class { - type = null; - nodes = null; - #core = null; - #routes = []; - #topo = new Topo.Sorter(); - constructor(type, core) { - this.#core = core; - this.type = type; - } - add(event) { - const methods = [].concat(event.method); - for (const method of methods) { - const settings = { - before: event.options.before, - after: event.options.after, - group: event.realm.plugin, - sort: this.#core.extensionsSeq++ - }; - const node = { - func: method, - // Request: function (request, h), Server: function (server) - bind: event.options.bind, - server: event.server, - // Server event - realm: event.realm, - timeout: event.options.timeout + async changeNode(node) { + this.#node = node; + if (!this.#state) + return; + if (this.#state.connectPromise === void 0) { + this.#subscriptions = { + [pub_sub_1.PUBSUB_TYPE.CHANNELS]: this.#state.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.CHANNELS), + [pub_sub_1.PUBSUB_TYPE.PATTERNS]: this.#state.client.getPubSubListeners(pub_sub_1.PUBSUB_TYPE.PATTERNS) }; - this.#topo.add(node, settings); - } - this.nodes = this.#topo.nodes; - for (const route2 of this.#routes) { - route2.rebuild(event); + this.#state.client.destroy(); } + await this.#initiatePubSubClient(true); } - merge(others) { - const merge3 = []; - for (const other of others) { - merge3.push(other.#topo); + #executeCommand(fn) { + const client = this.#getPubSubClient(); + if (client instanceof client_1.default) { + return fn(client); } - this.#topo.merge(merge3); - this.nodes = this.#topo.nodes.length ? this.#topo.nodes : null; + return client.then((client2) => { + if (client2 === void 0) + return; + return fn(client2); + }).catch((err) => { + if (this.#state?.client.isPubSubActive) { + this.#state.client.destroy(); + this.#state = void 0; + } + throw err; + }); } - subscribe(route2) { - this.#routes.push(route2); + subscribe(channels, listener, bufferMode) { + return this.#executeCommand((client) => client.SUBSCRIBE(channels, listener, bufferMode)); } - static combine(route2, type) { - const ext = new internals.Ext(type, route2._core); - const events = route2.settings.ext[type]; - if (events) { - for (let event of events) { - event = Object.assign({}, event); - Hoek.assert(!event.options.sandbox, "Cannot specify sandbox option for route extension"); - event.realm = route2.realm; - ext.add(event); + #unsubscribe(fn) { + return this.#executeCommand(async (client) => { + const reply = await fn(client); + if (!client.isPubSubActive) { + client.destroy(); + this.#state = void 0; } + return reply; + }); + } + async unsubscribe(channels, listener, bufferMode) { + return this.#unsubscribe((client) => client.UNSUBSCRIBE(channels, listener, bufferMode)); + } + async pSubscribe(patterns, listener, bufferMode) { + return this.#executeCommand((client) => client.PSUBSCRIBE(patterns, listener, bufferMode)); + } + async pUnsubscribe(patterns, listener, bufferMode) { + return this.#unsubscribe((client) => client.PUNSUBSCRIBE(patterns, listener, bufferMode)); + } + destroy() { + this.#subscriptions = void 0; + if (this.#state === void 0) + return; + if (!this.#state.connectPromise) { + this.#state.client.destroy(); } - const server = route2._core.extensions.route[type]; - const realm = route2.realm._extensions[type]; - ext.merge([server, realm]); - server.subscribe(route2); - realm.subscribe(route2); - return ext; + this.#state = void 0; + } + }; + exports2.PubSubProxy = PubSubProxy; + } +}); +var require_SENTINEL_MASTER = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_MASTER.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + /** + * Returns information about the specified master. + * @param parser - The Redis command parser. + * @param dbname - Name of the master. + */ + parseCommand(parser3, dbname) { + parser3.push("SENTINEL", "MASTER", dbname); + }, + transformReply: { + 2: generic_transformers_1.transformTuplesReply, + 3: void 0 + } + }; + } +}); +var require_SENTINEL_MONITOR = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_MONITOR.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + /** + * Instructs a Sentinel to monitor a new master with the specified parameters. + * @param parser - The Redis command parser. + * @param dbname - Name that identifies the master. + * @param host - Host of the master. + * @param port - Port of the master. + * @param quorum - Number of Sentinels that need to agree to trigger a failover. + */ + parseCommand(parser3, dbname, host, port, quorum) { + parser3.push("SENTINEL", "MONITOR", dbname, host, port, quorum); + }, + transformReply: void 0 + }; + } +}); +var require_SENTINEL_REPLICAS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_REPLICAS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + /** + * Returns a list of replicas for the specified master. + * @param parser - The Redis command parser. + * @param dbname - Name of the master. + */ + parseCommand(parser3, dbname) { + parser3.push("SENTINEL", "REPLICAS", dbname); + }, + transformReply: { + 2: (reply, preserve, typeMapping) => { + const inferred = reply; + const initial = []; + return inferred.reduce((sentinels, x3) => { + sentinels.push((0, generic_transformers_1.transformTuplesReply)(x3, void 0, typeMapping)); + return sentinels; + }, initial); + }, + 3: void 0 } }; } }); -var require_handler = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/handler.js"(exports2) { +var require_SENTINEL_SENTINELS = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_SENTINELS.js"(exports2) { "use strict"; - var Hoek = require_lib(); - var internals = {}; - exports2.execute = async function(request) { - if (request._route._prerequisites) { - for (const set of request._route._prerequisites) { - const pres = []; - for (const item of set) { - pres.push(internals.handler(request, item.method, item)); - } - const responses = await Promise.all(pres); - for (const response of responses) { - if (response !== void 0) { - return response; - } - } - } - } - const result = await internals.handler(request, request.route.settings.handler); - if (result._takeover || typeof result === "symbol") { - return result; - } - request._setResponse(result); - }; - internals.handler = async function(request, method, pre) { - const bind = request.route.settings.bind; - const realm = request.route.realm; - let response = await request._core.toolkit.execute(method, request, { bind, realm, continue: "null" }); - if (!pre) { - if (response.isBoom) { - request._log(["handler", "error"], response); - throw response; - } - return response; - } - if (response.isBoom) { - response.assign = pre.assign; - response = await request._core.toolkit.failAction(request, pre.failAction, response, { tags: ["pre", "error"], retain: true }); - } - if (typeof response === "symbol") { - return response; - } - if (pre.assign) { - request.pre[pre.assign] = response.isBoom ? response : response.source; - request.preResponses[pre.assign] = response; - } - if (response._takeover) { - return response; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + /** + * Returns a list of Sentinel instances for the specified master. + * @param parser - The Redis command parser. + * @param dbname - Name of the master. + */ + parseCommand(parser3, dbname) { + parser3.push("SENTINEL", "SENTINELS", dbname); + }, + transformReply: { + 2: (reply, preserve, typeMapping) => { + const inferred = reply; + const initial = []; + return inferred.reduce((sentinels, x3) => { + sentinels.push((0, generic_transformers_1.transformTuplesReply)(x3, void 0, typeMapping)); + return sentinels; + }, initial); + }, + 3: void 0 } }; - exports2.defaults = function(method, handler, core) { - let defaults = null; - if (typeof handler === "object") { - const type = Object.keys(handler)[0]; - const serverHandler = core.decorations.handler.get(type); - Hoek.assert(serverHandler, "Unknown handler:", type); - if (serverHandler.defaults) { - defaults = typeof serverHandler.defaults === "function" ? serverHandler.defaults(method) : serverHandler.defaults; + } +}); +var require_SENTINEL_SET = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/SENTINEL_SET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + /** + * Sets configuration parameters for a specific master. + * @param parser - The Redis command parser. + * @param dbname - Name of the master. + * @param options - Configuration options to set as option-value pairs. + */ + parseCommand(parser3, dbname, options2) { + parser3.push("SENTINEL", "SET", dbname); + for (const option of options2) { + parser3.push(option.option, option.value); } - } - return defaults ?? {}; + }, + transformReply: void 0 }; - exports2.configure = function(handler, route2) { - if (typeof handler === "object") { - const type = Object.keys(handler)[0]; - const serverHandler = route2._core.decorations.handler.get(type); - Hoek.assert(serverHandler, "Unknown handler:", type); - return serverHandler(route2.public, handler[type]); - } - return handler; + } +}); +var require_commands2 = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/commands/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - exports2.prerequisitesConfig = function(config2) { - if (!config2) { - return null; - } - const prerequisites = []; - for (let pres of config2) { - pres = [].concat(pres); - const set = []; - for (let pre of pres) { - if (typeof pre !== "object") { - pre = { method: pre }; - } - const item = { - method: pre.method, - assign: pre.assign, - failAction: pre.failAction ?? "error" - }; - set.push(item); - } - prerequisites.push(set); - } - return prerequisites.length ? prerequisites : null; + Object.defineProperty(exports2, "__esModule", { value: true }); + var SENTINEL_MASTER_1 = __importDefault(require_SENTINEL_MASTER()); + var SENTINEL_MONITOR_1 = __importDefault(require_SENTINEL_MONITOR()); + var SENTINEL_REPLICAS_1 = __importDefault(require_SENTINEL_REPLICAS()); + var SENTINEL_SENTINELS_1 = __importDefault(require_SENTINEL_SENTINELS()); + var SENTINEL_SET_1 = __importDefault(require_SENTINEL_SET()); + exports2.default = { + SENTINEL_SENTINELS: SENTINEL_SENTINELS_1.default, + sentinelSentinels: SENTINEL_SENTINELS_1.default, + SENTINEL_MASTER: SENTINEL_MASTER_1.default, + sentinelMaster: SENTINEL_MASTER_1.default, + SENTINEL_REPLICAS: SENTINEL_REPLICAS_1.default, + sentinelReplicas: SENTINEL_REPLICAS_1.default, + SENTINEL_MONITOR: SENTINEL_MONITOR_1.default, + sentinelMonitor: SENTINEL_MONITOR_1.default, + SENTINEL_SET: SENTINEL_SET_1.default, + sentinelSet: SENTINEL_SET_1.default }; } }); -var require_headers = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/headers.js"(exports2) { +var require_module = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/module.js"(exports2) { "use strict"; - var Stream = __require2("stream"); - var Boom5 = require_lib2(); - var internals = {}; - exports2.cache = function(response) { - const request = response.request; - if (response.headers["cache-control"]) { - return; - } - const settings = request.route.settings.cache; - const policy = settings && request._route._cache && (settings._statuses.has(response.statusCode) || response.statusCode === 304 && settings._statuses.has(200)); - if (policy || response.settings.ttl) { - const ttl = response.settings.ttl !== null ? response.settings.ttl : request._route._cache.ttl(); - const privacy = request.auth.isAuthenticated || response.headers["set-cookie"] ? "private" : settings.privacy ?? "default"; - response._header("cache-control", "max-age=" + Math.floor(ttl / 1e3) + ", must-revalidate" + (privacy !== "default" ? ", " + privacy : "")); - } else if (settings) { - response._header("cache-control", settings.otherwise); - } + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - exports2.content = async function(response) { - const request = response.request; - if (response._isPayloadSupported() || request.method === "head") { - await response._marshal(); - if (typeof response._payload.size === "function") { - response._header("content-length", response._payload.size(), { override: false }); - } - if (!response._isPayloadSupported()) { - response._close(); - response._payload = new internals.Empty(); - } - exports2.type(response); - } else { - response._close(); - response._payload = new internals.Empty(); - delete response.headers["content-length"]; - } + Object.defineProperty(exports2, "__esModule", { value: true }); + var commands_1 = __importDefault(require_commands2()); + exports2.default = { + sentinel: commands_1.default }; - exports2.state = async function(response) { - const request = response.request; - const states = []; - for (const stateName in request._states) { - states.push(request._states[stateName]); - } - try { - for (const name in request._core.states.cookies) { - const autoValue = request._core.states.cookies[name].autoValue; - if (!autoValue || name in request._states || name in request.state) { - continue; - } - if (typeof autoValue !== "function") { - states.push({ name, value: autoValue }); - continue; - } - const value = await autoValue(request); - states.push({ name, value }); - } - if (!states.length) { + } +}); +var require_wait_queue = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/wait-queue.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.WaitQueue = void 0; + var linked_list_1 = require_linked_list(); + var WaitQueue = class { + #list = new linked_list_1.SinglyLinkedList(); + #queue = new linked_list_1.SinglyLinkedList(); + push(value) { + const resolve82 = this.#queue.shift(); + if (resolve82 !== void 0) { + resolve82(value); return; } - let header = await request._core.states.format(states, request); - const existing = response.headers["set-cookie"]; - if (existing) { - header = (Array.isArray(existing) ? existing : [existing]).concat(header); - } - response._header("set-cookie", header); - } catch (err) { - const error2 = Boom5.boomify(err); - request._log(["state", "response", "error"], error2); - request._states = {}; - throw error2; - } - }; - exports2.type = function(response) { - const type = response.contentType; - if (type !== null && type !== response.headers["content-type"]) { - response.type(type); - } - }; - exports2.entity = function(response) { - const request = response.request; - if (!request._entity) { - return; - } - if (request._entity.etag && !response.headers.etag) { - response.etag(request._entity.etag, { vary: request._entity.vary }); - } - if (request._entity.modified && !response.headers["last-modified"]) { - response.header("last-modified", request._entity.modified); - } - }; - exports2.unmodified = function(response) { - const request = response.request; - if (response.statusCode === 304) { - return; - } - const entity = { - etag: response.headers.etag, - vary: response.settings.varyEtag, - modified: response.headers["last-modified"] - }; - const etag = request._core.Response.unmodified(request, entity); - if (etag) { - response.code(304); - if (etag !== true) { - response.headers.etag = etag; - } + this.#list.push(value); } - }; - internals.Empty = class extends Stream.Readable { - _read() { - this.push(null); + shift() { + return this.#list.shift(); } - writeToStream(stream) { - stream.end(); + wait() { + return new Promise((resolve82) => this.#queue.push(resolve82)); } }; + exports2.WaitQueue = WaitQueue; } }); -var require_security = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/security.js"(exports2) { +var require_sentinel = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/lib/sentinel/index.js"(exports2) { "use strict"; - exports2.route = function(settings) { - if (!settings) { - return null; - } - const security = settings; - if (security.hsts) { - if (security.hsts === true) { - security._hsts = "max-age=15768000"; - } else if (typeof security.hsts === "number") { - security._hsts = "max-age=" + security.hsts; - } else { - security._hsts = "max-age=" + (security.hsts.maxAge ?? 15768e3); - if (security.hsts.includeSubdomains || security.hsts.includeSubDomains) { - security._hsts = security._hsts + "; includeSubDomains"; - } - if (security.hsts.preload) { - security._hsts = security._hsts + "; preload"; - } - } - } - if (security.xframe) { - if (security.xframe === true) { - security._xframe = "DENY"; - } else if (typeof security.xframe === "string") { - security._xframe = security.xframe.toUpperCase(); - } else if (security.xframe.rule === "allow-from") { - if (!security.xframe.source) { - security._xframe = "SAMEORIGIN"; - } else { - security._xframe = "ALLOW-FROM " + security.xframe.source; - } - } else { - security._xframe = security.xframe.rule.toUpperCase(); - } - } - return security; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - exports2.headers = function(response) { - const security = response.request.route.settings.security; - if (security._hsts) { - response._header("strict-transport-security", security._hsts, { override: false }); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.RedisSentinelFactory = exports2.RedisSentinelClient = void 0; + var node_events_1 = __require2("node:events"); + var client_1 = __importDefault(require_client()); + var commander_1 = require_commander(); + var commands_1 = __importDefault(require_commands()); + var utils_1 = require_utils(); + var multi_commands_1 = __importDefault(require_multi_commands()); + var pub_sub_proxy_1 = require_pub_sub_proxy(); + var promises_1 = __require2("node:timers/promises"); + var module_1 = __importDefault(require_module()); + var wait_queue_1 = require_wait_queue(); + var cache_1 = require_cache(); + var RedisSentinelClient = class _RedisSentinelClient { + #clientInfo; + #internal; + _self; + /** + * Indicates if the client connection is open + * + * @returns `true` if the client connection is open, `false` otherwise + */ + get isOpen() { + return this._self.#internal.isOpen; } - if (security._xframe) { - response._header("x-frame-options", security._xframe, { override: false }); + /** + * Indicates if the client connection is ready to accept commands + * + * @returns `true` if the client connection is ready, `false` otherwise + */ + get isReady() { + return this._self.#internal.isReady; } - if (security.xss === "enabled") { - response._header("x-xss-protection", "1; mode=block", { override: false }); - } else if (security.xss === "disabled") { - response._header("x-xss-protection", "0", { override: false }); + /** + * Gets the command options configured for this client + * + * @returns The command options for this client or `undefined` if none were set + */ + get commandOptions() { + return this._self.#commandOptions; } - if (security.noOpen) { - response._header("x-download-options", "noopen", { override: false }); + #commandOptions; + constructor(internal, clientInfo, commandOptions) { + this._self = this; + this.#internal = internal; + this.#clientInfo = clientInfo; + this.#commandOptions = commandOptions; } - if (security.noSniff) { - response._header("x-content-type-options", "nosniff", { override: false }); + static factory(config2) { + const SentinelClient = (0, commander_1.attachConfig)({ + BaseClass: _RedisSentinelClient, + commands: commands_1.default, + createCommand: utils_1.createCommand, + createModuleCommand: utils_1.createModuleCommand, + createFunctionCommand: utils_1.createFunctionCommand, + createScriptCommand: utils_1.createScriptCommand, + config: config2 + }); + SentinelClient.prototype.Multi = multi_commands_1.default.extend(config2); + return (internal, clientInfo, commandOptions) => { + return Object.create(new SentinelClient(internal, clientInfo, commandOptions)); + }; } - if (security.referrer !== false) { - response._header("referrer-policy", security.referrer, { override: false }); + static create(options2, internal, clientInfo, commandOptions) { + return _RedisSentinelClient.factory(options2)(internal, clientInfo, commandOptions); } - }; - } -}); -var require_streams = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/streams.js"(exports2) { - "use strict"; - var Stream = __require2("stream"); - var Boom5 = require_lib2(); - var Teamwork = require_lib11(); - var internals = { - team: Symbol("team") - }; - exports2.isStream = function(stream) { - const isReadableStream = stream instanceof Stream.Readable; - if (!isReadableStream && typeof stream?.pipe === "function") { - throw Boom5.badImplementation("Cannot reply with a stream-like object that is not an instance of Stream.Readable"); + withCommandOptions(options2) { + const proxy = Object.create(this); + proxy._commandOptions = options2; + return proxy; } - if (!isReadableStream) { - return false; + _commandOptionsProxy(key, value) { + const proxy = Object.create(this); + proxy._commandOptions = Object.create(this._self.#commandOptions ?? null); + proxy._commandOptions[key] = value; + return proxy; } - if (stream.readableObjectMode) { - throw Boom5.badImplementation("Cannot reply with stream in object mode"); + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping) { + return this._commandOptionsProxy("typeMapping", typeMapping); } - return true; - }; - exports2.drain = function(stream) { - const team = new Teamwork.Team(); - stream[internals.team] = team; - stream.on("readable", internals.read); - stream.on("error", internals.end); - stream.on("end", internals.end); - stream.on("close", internals.end); - return team.work; - }; - internals.read = function() { - while (this.read()) { + async _execute(isReadonly, fn) { + if (this._self.#clientInfo === void 0) { + throw new Error("Attempted execution on released RedisSentinelClient lease"); + } + return await this._self.#internal.execute(fn, this._self.#clientInfo); } - }; - internals.end = function() { - this.removeListener("readable", internals.read); - this.removeListener("error", internals.end); - this.removeListener("end", internals.end); - this.removeListener("close", internals.end); - this[internals.team].attend(); - }; - } -}); -var require_validation = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/validation.js"(exports2) { - "use strict"; - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var Validate = require_lib9(); - var internals = {}; - exports2.validator = function(validator) { - Hoek.assert(validator, "Missing validator"); - Hoek.assert(typeof validator.compile === "function", "Invalid validator compile method"); - return validator; - }; - exports2.compile = function(rule, validator, realm, core) { - validator = validator ?? internals.validator(realm, core); - if (rule === false) { - return Validate.object({}).allow(null); - } - if (typeof rule === "function") { - return rule; - } - if (!rule || // false tested above - rule === true) { - return null; + async sendCommand(isReadonly, args, options2) { + return this._execute(isReadonly, (client) => client.sendCommand(args, options2)); } - if (typeof rule.validate === "function") { - return rule; + /** + * @internal + */ + async _executePipeline(isReadonly, commands) { + return this._execute(isReadonly, (client) => client._executePipeline(commands)); } - Hoek.assert(validator, "Cannot set uncompiled validation rules without configuring a validator"); - return validator.compile(rule); - }; - internals.validator = function(realm, core) { - while (realm) { - if (realm.validator) { - return realm.validator; - } - realm = realm.parent; + /**f + * @internal + */ + async _executeMulti(isReadonly, commands) { + return this._execute(isReadonly, (client) => client._executeMulti(commands)); } - return core.validator; - }; - exports2.headers = function(request) { - return internals.input("headers", request); - }; - exports2.params = function(request) { - return internals.input("params", request); - }; - exports2.payload = function(request) { - if (request.method === "get" || request.method === "head") { - return; + MULTI() { + return new this.Multi(this); } - return internals.input("payload", request); - }; - exports2.query = function(request) { - return internals.input("query", request); - }; - exports2.state = function(request) { - return internals.input("state", request); - }; - internals.input = async function(source, request) { - const localOptions = { - context: { - headers: request.headers, - params: request.params, - query: request.query, - payload: request.payload, - state: request.state, - auth: request.auth, - app: { - route: request.route.settings.app, - request: request.app - } - } - }; - delete localOptions.context[source]; - Hoek.merge(localOptions, request.route.settings.validate.options); - try { - const schema = request.route.settings.validate[source]; - const bind = request.route.settings.bind; - var value = await (typeof schema !== "function" ? internals.validate(request[source], schema, localOptions) : schema.call(bind, request[source], localOptions)); - return; - } catch (err) { - var validationError = err; - } finally { - request.orig[source] = request[source]; - if (value !== void 0) { - request[source] = value; + multi = this.MULTI; + WATCH(key) { + if (this._self.#clientInfo === void 0) { + throw new Error("Attempted execution on released RedisSentinelClient lease"); } + return this._execute(false, (client) => client.watch(key)); } - if (request.route.settings.validate.failAction === "ignore") { - return; - } - const defaultError = validationError.isBoom ? validationError : Boom5.badRequest(`Invalid request ${source} input`); - const detailedError = Boom5.boomify(validationError, { statusCode: 400, override: false, data: { defaultError } }); - detailedError.output.payload.validation = { source, keys: [] }; - if (validationError.details) { - for (const details of validationError.details) { - const path8 = details.path; - detailedError.output.payload.validation.keys.push(Hoek.escapeHtml(path8.join("."))); + watch = this.WATCH; + UNWATCH() { + if (this._self.#clientInfo === void 0) { + throw new Error("Attempted execution on released RedisSentinelClient lease"); } + return this._execute(false, (client) => client.unwatch()); } - if (request.route.settings.validate.errorFields) { - for (const field in request.route.settings.validate.errorFields) { - detailedError.output.payload[field] = request.route.settings.validate.errorFields[field]; + unwatch = this.UNWATCH; + /** + * Releases the client lease back to the pool + * + * After calling this method, the client instance should no longer be used as it + * will be returned to the client pool and may be given to other operations. + * + * @returns A promise that resolves when the client is ready to be reused, or undefined + * if the client was immediately ready + * @throws Error if the lease has already been released + */ + release() { + if (this._self.#clientInfo === void 0) { + throw new Error("RedisSentinelClient lease already released"); } + const result = this._self.#internal.releaseClientLease(this._self.#clientInfo); + this._self.#clientInfo = void 0; + return result; } - return request._core.toolkit.failAction(request, request.route.settings.validate.failAction, defaultError, { details: detailedError, tags: ["validation", "error", source] }); }; - exports2.response = async function(request) { - if (request.route.settings.response.sample) { - const currentSample = Math.ceil(Math.random() * 100); - if (currentSample > request.route.settings.response.sample) { - return; - } - } - const response = request.response; - const statusCode = response.isBoom ? response.output.statusCode : response.statusCode; - const statusSchema = request.route.settings.response.status[statusCode]; - if (statusCode >= 400 && !statusSchema) { - return; + exports2.RedisSentinelClient = RedisSentinelClient; + var RedisSentinel = class _RedisSentinel extends node_events_1.EventEmitter { + _self; + #internal; + #options; + /** + * Indicates if the sentinel connection is open + * + * @returns `true` if the sentinel connection is open, `false` otherwise + */ + get isOpen() { + return this._self.#internal.isOpen; } - const schema = statusSchema !== void 0 ? statusSchema : request.route.settings.response.schema; - if (schema === null) { - return; + /** + * Indicates if the sentinel connection is ready to accept commands + * + * @returns `true` if the sentinel connection is ready, `false` otherwise + */ + get isReady() { + return this._self.#internal.isReady; } - if (!response.isBoom && request.response.variety !== "plain") { - throw Boom5.badImplementation("Cannot validate non-object response"); + get commandOptions() { + return this._self.#commandOptions; } - const localOptions = { - context: { - headers: request.headers, - params: request.params, - query: request.query, - payload: request.payload, - state: request.state, - auth: request.auth, - app: { - route: request.route.settings.app, - request: request.app - } - } + #commandOptions; + #trace = () => { }; - const source = response.isBoom ? response.output.payload : response.source; - Hoek.merge(localOptions, request.route.settings.response.options); - try { - let value; - if (typeof schema !== "function") { - value = await internals.validate(source, schema, localOptions); - } else { - value = await schema(source, localOptions); - } - if (value !== void 0 && request.route.settings.response.modify) { - if (response.isBoom) { - response.output.payload = value; - } else { - response.source = value; - } - } - } catch (err) { - return request._core.toolkit.failAction(request, request.route.settings.response.failAction, err, { tags: ["validation", "response", "error"] }); - } - }; - internals.validate = function(value, schema, options2) { - if (typeof schema.validateAsync === "function") { - return schema.validateAsync(value, options2); - } - return schema.validate(value, options2); - }; - } -}); -var require_route2 = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/route.js"(exports2, module14) { - "use strict"; - var Assert = __require2("assert"); - var Bounce = require_lib12(); - var Catbox = require_lib16(); - var Hoek = require_lib(); - var Subtext = require_lib31(); - var Validate = require_lib9(); - var Auth = require_auth(); - var Config = require_config(); - var Cors = require_cors(); - var Ext = require_ext(); - var Handler = require_handler(); - var Headers2 = require_headers(); - var Security = require_security(); - var Streams = require_streams(); - var Validation = require_validation(); - var internals = {}; - exports2 = module14.exports = internals.Route = class { - constructor(route2, server, options2 = {}) { - const core = server._core; - const realm = server.realm; - Config.apply("route", route2, route2.method, route2.path); - const method = route2.method.toLowerCase(); - Hoek.assert(method !== "head", "Cannot set HEAD route:", route2.path); - const path8 = realm.modifiers.route.prefix ? realm.modifiers.route.prefix + (route2.path !== "/" ? route2.path : "") : route2.path; - Hoek.assert(path8 === "/" || path8[path8.length - 1] !== "/" || !core.settings.router.stripTrailingSlash, "Path cannot end with a trailing slash when configured to strip:", route2.method, route2.path); - const vhost = realm.modifiers.route.vhost ?? route2.vhost; - this.method = method; - this.path = path8; - let config2 = route2.options ?? route2.config ?? {}; - if (typeof config2 === "function") { - config2 = config2.call(realm.settings.bind, server); - } - config2 = Config.enable(config2); - this._assert(method !== "get" || !config2.payload, "Cannot set payload settings on HEAD or GET request"); - this._assert(method !== "get" || !config2.validate?.payload, "Cannot validate HEAD or GET request payload"); - this._assert(!route2.rules || !config2.rules, "Route rules can only appear once"); - const rules = route2.rules ?? config2.rules; - const rulesConfig = internals.rules(rules, { method, path: path8, vhost }, server); - delete config2.rules; - this._assert(route2.handler || config2.handler, "Missing or undefined handler"); - this._assert(!!route2.handler ^ !!config2.handler, "Handler must only appear once"); - const handler = Config.apply("handler", route2.handler ?? config2.handler); - delete config2.handler; - const handlerDefaults = Handler.defaults(method, handler, core); - const settings = internals.config([core.settings.routes, handlerDefaults, realm.settings, rulesConfig, config2]); - this.settings = Config.apply("routeConfig", settings, method, path8); - this._core = core; - this.realm = realm; - this.settings.vhost = vhost; - this.settings.plugins = this.settings.plugins ?? {}; - this.settings.app = this.settings.app ?? {}; - this._special = !!options2.special; - this._analysis = this._core.router.analyze(this.path); - this.params = this._analysis.params; - this.fingerprint = this._analysis.fingerprint; - this.public = { - method: this.method, - path: this.path, - vhost, - realm, - settings: this.settings, - fingerprint: this.fingerprint, - auth: { - access: (request) => Auth.testAccess(request, this.public) - } - }; - this._setupValidation(); - if (this.method === "get") { - this.settings.payload = null; - } else { - this.settings.payload.decoders = this._core.compression.decoders; - } - this._assert(!this.settings.validate.payload || this.settings.payload.parse, "Route payload must be set to 'parse' when payload validation enabled"); - this._assert(!this.settings.validate.state || this.settings.state.parse, "Route state must be set to 'parse' when state validation enabled"); - this.settings.auth = this._special ? false : this._core.auth._setupRoute(this.settings.auth, path8); - if (this.method === "get" && typeof this.settings.cache === "object" && (this.settings.cache.expiresIn || this.settings.cache.expiresAt)) { - this.settings.cache._statuses = new Set(this.settings.cache.statuses); - this._cache = new Catbox.Policy({ expiresIn: this.settings.cache.expiresIn, expiresAt: this.settings.cache.expiresAt }); - } - this.settings.cors = Cors.route(this.settings.cors); - this.settings.security = Security.route(this.settings.security); - this.settings.handler = Handler.configure(handler, this); - this._prerequisites = Handler.prerequisitesConfig(this.settings.pre); - this._extensions = { - onPreResponse: Ext.combine(this, "onPreResponse"), - onPostResponse: Ext.combine(this, "onPostResponse") - }; - if (this._special) { - this._cycle = [internals.drain, Handler.execute]; - this.rebuild(); - return; - } - this._extensions.onPreAuth = Ext.combine(this, "onPreAuth"); - this._extensions.onCredentials = Ext.combine(this, "onCredentials"); - this._extensions.onPostAuth = Ext.combine(this, "onPostAuth"); - this._extensions.onPreHandler = Ext.combine(this, "onPreHandler"); - this._extensions.onPostHandler = Ext.combine(this, "onPostHandler"); - this.rebuild(); - } - _setupValidation() { - const validation2 = this.settings.validate; - if (this.method === "get") { - validation2.payload = null; - } - this._assert(!validation2.params || this.params.length, "Cannot set path parameters validations without path parameters"); - for (const type of ["headers", "params", "query", "payload", "state"]) { - validation2[type] = Validation.compile(validation2[type], this.settings.validate.validator, this.realm, this._core); - } - if (this.settings.response.schema !== void 0 || this.settings.response.status) { - this.settings.response._validate = true; - const rule = this.settings.response.schema; - this.settings.response.status = this.settings.response.status ?? {}; - const statuses = Object.keys(this.settings.response.status); - if (rule === true && !statuses.length) { - this.settings.response._validate = false; - } else { - this.settings.response.schema = Validation.compile(rule, this.settings.validate.validator, this.realm, this._core); - for (const code2 of statuses) { - this.settings.response.status[code2] = Validation.compile(this.settings.response.status[code2], this.settings.validate.validator, this.realm, this._core); - } - } - } + #reservedClientInfo; + #masterClientCount = 0; + #masterClientInfo; + get clientSideCache() { + return this._self.#internal.clientSideCache; } - rebuild(event) { - if (event) { - this._extensions[event.type].add(event); - } - if (this._special) { - this._postCycle = this._extensions.onPreResponse.nodes ? [this._extensions.onPreResponse] : []; - this._buildMarshalCycle(); - return; - } - this._cycle = []; - if (this.settings.state.parse) { - this._cycle.push(internals.state); - } - if (this._extensions.onPreAuth.nodes) { - this._cycle.push(this._extensions.onPreAuth); - } - if (this._core.auth._enabled(this, "authenticate")) { - this._cycle.push(Auth.authenticate); + constructor(options2) { + super(); + this._self = this; + this.#options = options2; + if (options2.commandOptions) { + this.#commandOptions = options2.commandOptions; } - if (this.method !== "get") { - this._cycle.push(internals.payload); - if (this._core.auth._enabled(this, "payload")) { - this._cycle.push(Auth.payload); + this.#internal = new RedisSentinelInternal(options2); + this.#internal.on("error", (err) => this.emit("error", err)); + this.#internal.on("topology-change", (event) => { + if (!this.emit("topology-change", event)) { + this._self.#trace(`RedisSentinel: re-emit for topology-change for ${event.type} event returned false`); } - } - if (this._core.auth._enabled(this, "authenticate") && this._extensions.onCredentials.nodes) { - this._cycle.push(this._extensions.onCredentials); - } - if (this._core.auth._enabled(this, "access")) { - this._cycle.push(Auth.access); - } - if (this._extensions.onPostAuth.nodes) { - this._cycle.push(this._extensions.onPostAuth); - } - if (this.settings.validate.headers) { - this._cycle.push(Validation.headers); - } - if (this.settings.validate.params) { - this._cycle.push(Validation.params); - } - if (this.settings.validate.query) { - this._cycle.push(Validation.query); - } - if (this.settings.validate.payload) { - this._cycle.push(Validation.payload); - } - if (this.settings.validate.state) { - this._cycle.push(Validation.state); - } - if (this._extensions.onPreHandler.nodes) { - this._cycle.push(this._extensions.onPreHandler); - } - this._cycle.push(Handler.execute); - if (this._extensions.onPostHandler.nodes) { - this._cycle.push(this._extensions.onPostHandler); - } - this._postCycle = []; - if (this.settings.response._validate && this.settings.response.sample !== 0) { - this._postCycle.push(Validation.response); - } - if (this._extensions.onPreResponse.nodes) { - this._postCycle.push(this._extensions.onPreResponse); - } - this._buildMarshalCycle(); - } - _buildMarshalCycle() { - this._marshalCycle = [Headers2.type]; - if (this.settings.cors) { - this._marshalCycle.push(Cors.headers); - } - if (this.settings.security) { - this._marshalCycle.push(Security.headers); - } - this._marshalCycle.push(Headers2.entity); - if (this.method === "get" || this.method === "*") { - this._marshalCycle.push(Headers2.unmodified); - } - this._marshalCycle.push(Headers2.cache); - this._marshalCycle.push(Headers2.state); - this._marshalCycle.push(Headers2.content); - if (this._core.auth._enabled(this, "response")) { - this._marshalCycle.push(Auth.response); - } - } - _assert(condition, message) { - if (condition) { - return; - } - if (this.method[0] !== "_") { - message = `${message}: ${this.method.toUpperCase()} ${this.path}`; - } - throw new Assert.AssertionError({ - message, - actual: false, - expected: true, - operator: "==", - stackStartFunction: this._assert }); } - }; - internals.state = async function(request) { - request.state = {}; - const req = request.raw.req; - const cookies = req.headers.cookie; - if (!cookies) { - return; - } - try { - var result = await request._core.states.parse(cookies); - } catch (err) { - Bounce.rethrow(err, "system"); - var parseError = err; - } - const { states, failed = [] } = result ?? parseError; - request.state = states ?? {}; - for (const item of failed) { - if (item.settings.clearInvalid) { - request._clearState(item.name); - } - } - if (!parseError) { - return; - } - parseError.header = cookies; - return request._core.toolkit.failAction(request, request.route.settings.state.failAction, parseError, { tags: ["state", "error"] }); - }; - internals.payload = async function(request) { - if (request.method === "get" || request.method === "head") { - return; - } - if (request.payload !== void 0) { - return internals.drain(request); - } - if (request._expectContinue) { - request._expectContinue = false; - request.raw.res.writeContinue(); - } - try { - const { payload, mime } = await Subtext.parse(request.raw.req, request._tap(), request.route.settings.payload); - request._isPayloadPending = !!payload?._readableState; - request.mime = mime; - request.payload = payload; - } catch (err) { - Bounce.rethrow(err, "system"); - await internals.drain(request); - request.mime = err.mime; - request.payload = null; - return request._core.toolkit.failAction(request, request.route.settings.payload.failAction, err, { tags: ["payload", "error"] }); + static factory(config2) { + const Sentinel = (0, commander_1.attachConfig)({ + BaseClass: _RedisSentinel, + commands: commands_1.default, + createCommand: utils_1.createCommand, + createModuleCommand: utils_1.createModuleCommand, + createFunctionCommand: utils_1.createFunctionCommand, + createScriptCommand: utils_1.createScriptCommand, + config: config2 + }); + Sentinel.prototype.Multi = multi_commands_1.default.extend(config2); + return (options2) => { + return Object.create(new Sentinel(options2)); + }; } - }; - internals.drain = async function(request) { - if (request._expectContinue) { - request._isPayloadPending = false; - request._expectContinue = false; + static create(options2) { + return _RedisSentinel.factory(options2)(options2); } - if (request._isPayloadPending) { - await Streams.drain(request.raw.req); - request._isPayloadPending = false; + withCommandOptions(options2) { + const proxy = Object.create(this); + proxy._commandOptions = options2; + return proxy; } - }; - internals.config = function(chain) { - if (!chain.length) { - return {}; + _commandOptionsProxy(key, value) { + const proxy = Object.create(this); + proxy._self.#commandOptions = { + ...this._self.#commandOptions || {}, + [key]: value + }; + return proxy; } - let config2 = chain[0]; - for (const item of chain) { - config2 = Hoek.applyToDefaults(config2, item, { shallow: ["bind", "validate.headers", "validate.payload", "validate.params", "validate.query", "validate.state"] }); + /** + * Override the `typeMapping` command option + */ + withTypeMapping(typeMapping) { + return this._commandOptionsProxy("typeMapping", typeMapping); } - return config2; - }; - internals.rules = function(rules, info, server) { - const configs = []; - let realm = server.realm; - while (realm) { - if (realm._rules) { - const source = !realm._rules.settings.validate ? rules : Validate.attempt(rules, realm._rules.settings.validate.schema, realm._rules.settings.validate.options); - const config2 = realm._rules.processor(source, info); - if (config2) { - configs.unshift(config2); - } + async connect() { + await this._self.#internal.connect(); + if (this._self.#options.reserveClient) { + this._self.#reservedClientInfo = await this._self.#internal.getClientLease(); } - realm = realm.parent; - } - return internals.config(configs); - }; - } -}); -var require_cors = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/cors.js"(exports2) { - "use strict"; - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var Route = null; - var internals = {}; - exports2.route = function(options2) { - if (!options2) { - return false; + return this; } - const settings = Hoek.clone(options2); - settings._headers = settings.headers.concat(settings.additionalHeaders); - settings._headersString = settings._headers.join(","); - for (let i2 = 0; i2 < settings._headers.length; ++i2) { - settings._headers[i2] = settings._headers[i2].toLowerCase(); - } - if (settings._headers.indexOf("origin") === -1) { - settings._headers.push("origin"); - } - settings._exposedHeaders = settings.exposedHeaders.concat(settings.additionalExposedHeaders).join(","); - if (settings.origin === "ignore") { - settings._origin = false; - } else if (settings.origin.indexOf("*") !== -1) { - Hoek.assert(settings.origin.length === 1, "Cannot specify cors.origin * together with other values"); - settings._origin = true; - } else { - settings._origin = { - qualified: [], - wildcards: [] - }; - for (const origin of settings.origin) { - if (origin.indexOf("*") !== -1) { - settings._origin.wildcards.push(new RegExp("^" + Hoek.escapeRegex(origin).replace(/\\\*/g, ".*").replace(/\\\?/g, ".") + "$")); + async _execute(isReadonly, fn) { + let clientInfo; + if (!isReadonly || !this._self.#internal.useReplicas) { + if (this._self.#reservedClientInfo) { + clientInfo = this._self.#reservedClientInfo; } else { - settings._origin.qualified.push(origin); + this._self.#masterClientInfo ??= await this._self.#internal.getClientLease(); + clientInfo = this._self.#masterClientInfo; + this._self.#masterClientCount++; + } + } + try { + return await this._self.#internal.execute(fn, clientInfo); + } finally { + if (clientInfo !== void 0 && clientInfo === this._self.#masterClientInfo && --this._self.#masterClientCount === 0) { + const promise = this._self.#internal.releaseClientLease(clientInfo); + this._self.#masterClientInfo = void 0; + if (promise) + await promise; } } } - return settings; - }; - exports2.options = function(route2, server) { - if (route2.method === "options" || !route2.settings.cors) { - return; - } - exports2.handler(server); - }; - exports2.handler = function(server) { - Route = Route || require_route2(); - if (server._core.router.specials.options) { - return; - } - const definition = { - method: "_special", - path: "/{p*}", - handler: internals.handler, - options: { - cors: false + async use(fn) { + const clientInfo = await this._self.#internal.getClientLease(); + try { + return await fn(RedisSentinelClient.create(this._self.#options, this._self.#internal, clientInfo, this._self.#commandOptions)); + } finally { + const promise = this._self.#internal.releaseClientLease(clientInfo); + if (promise) + await promise; } - }; - const route2 = new Route(definition, server, { special: true }); - server._core.router.special("options", route2); - }; - internals.handler = function(request, h2) { - const method = request.headers["access-control-request-method"]; - if (!method) { - throw Boom5.notFound("CORS error: Missing Access-Control-Request-Method header"); } - const route2 = request.server.match(method, request.path, request.info.hostname); - if (!route2) { - throw Boom5.notFound(); + async sendCommand(isReadonly, args, options2) { + return this._execute(isReadonly, (client) => client.sendCommand(args, options2)); } - const settings = route2.settings.cors; - if (!settings) { - return { message: "CORS is disabled for this route" }; + /** + * @internal + */ + async _executePipeline(isReadonly, commands) { + return this._execute(isReadonly, (client) => client._executePipeline(commands)); } - const origin = request.headers.origin; - if (!origin && settings._origin !== false) { - throw Boom5.notFound("CORS error: Missing Origin header"); + /**f + * @internal + */ + async _executeMulti(isReadonly, commands) { + return this._execute(isReadonly, (client) => client._executeMulti(commands)); } - if (!exports2.matchOrigin(origin, settings)) { - return { message: "CORS error: Origin not allowed" }; + MULTI() { + return new this.Multi(this); } - let headers = request.headers["access-control-request-headers"]; - if (headers) { - headers = headers.toLowerCase().split(/\s*,\s*/); - if (Hoek.intersect(headers, settings._headers).length !== headers.length) { - return { message: "CORS error: Some headers are not allowed" }; - } + multi = this.MULTI; + async close() { + return this._self.#internal.close(); } - const response = h2.response(); - response.code(settings.preflightStatusCode); - response._header("access-control-allow-origin", settings._origin ? origin : "*"); - response._header("access-control-allow-methods", method); - response._header("access-control-allow-headers", settings._headersString); - response._header("access-control-max-age", settings.maxAge); - if (settings.credentials) { - response._header("access-control-allow-credentials", "true"); + destroy() { + return this._self.#internal.destroy(); } - if (settings._exposedHeaders) { - response._header("access-control-expose-headers", settings._exposedHeaders); + async SUBSCRIBE(channels, listener, bufferMode) { + return this._self.#internal.subscribe(channels, listener, bufferMode); } - return response; - }; - exports2.headers = function(response) { - const request = response.request; - const settings = request.route.settings.cors; - if (settings._origin !== false) { - response.vary("origin"); + subscribe = this.SUBSCRIBE; + async UNSUBSCRIBE(channels, listener, bufferMode) { + return this._self.#internal.unsubscribe(channels, listener, bufferMode); } - if (request.info.cors && !request.info.cors.isOriginMatch || // After route lookup - !exports2.matchOrigin(request.headers.origin, request.route.settings.cors)) { - return; + unsubscribe = this.UNSUBSCRIBE; + async PSUBSCRIBE(patterns, listener, bufferMode) { + return this._self.#internal.pSubscribe(patterns, listener, bufferMode); } - response._header("access-control-allow-origin", settings._origin ? request.headers.origin : "*"); - if (settings.credentials) { - response._header("access-control-allow-credentials", "true"); + pSubscribe = this.PSUBSCRIBE; + async PUNSUBSCRIBE(patterns, listener, bufferMode) { + return this._self.#internal.pUnsubscribe(patterns, listener, bufferMode); } - if (settings._exposedHeaders) { - response._header("access-control-expose-headers", settings._exposedHeaders, { append: true }); + pUnsubscribe = this.PUNSUBSCRIBE; + /** + * Acquires a master client lease for exclusive operations + * + * Used when multiple commands need to run on an exclusive client (for example, using `WATCH/MULTI/EXEC`). + * The returned client must be released after use with the `release()` method. + * + * @returns A promise that resolves to a Redis client connected to the master node + * @example + * ```javascript + * const clientLease = await sentinel.acquire(); + * + * try { + * await clientLease.watch('key'); + * const resp = await clientLease.multi() + * .get('key') + * .exec(); + * } finally { + * clientLease.release(); + * } + * ``` + */ + async acquire() { + const clientInfo = await this._self.#internal.getClientLease(); + return RedisSentinelClient.create(this._self.#options, this._self.#internal, clientInfo, this._self.#commandOptions); } - }; - exports2.matchOrigin = function(origin, settings) { - if (settings._origin === true || settings._origin === false) { - return true; + getSentinelNode() { + return this._self.#internal.getSentinelNode(); } - if (!origin) { - return false; + getMasterNode() { + return this._self.#internal.getMasterNode(); } - if (settings._origin.qualified.indexOf(origin) !== -1) { - return true; + getReplicaNodes() { + return this._self.#internal.getReplicaNodes(); } - for (const wildcard of settings._origin.wildcards) { - if (origin.match(wildcard)) { - return true; + setTracer(tracer) { + if (tracer) { + this._self.#trace = (msg) => { + tracer.push(msg); + }; + } else { + this._self.#trace = () => { + }; } + this._self.#internal.setTracer(tracer); } - return false; - }; - } -}); -var require_toolkit = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/toolkit.js"(exports2) { - "use strict"; - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var internals = {}; - exports2.reserved = [ - "abandon", - "authenticated", - "close", - "context", - "continue", - "entity", - "redirect", - "realm", - "request", - "response", - "state", - "unauthenticated", - "unstate" - ]; - exports2.symbols = { - abandon: Symbol("abandon"), - close: Symbol("close"), - continue: Symbol("continue") }; - exports2.Manager = class { - constructor() { - this._toolkit = internals.toolkit(); + exports2.default = RedisSentinel; + var RedisSentinelInternal = class extends node_events_1.EventEmitter { + #isOpen = false; + get isOpen() { + return this.#isOpen; } - async execute(method, request, options2) { - const h2 = new this._toolkit(request, options2); - const bind = options2.bind ?? null; - try { - let operation; - if (bind) { - operation = method.call(bind, request, h2); - } else if (options2.args) { - operation = method(request, h2, ...options2.args); - } else { - operation = method(request, h2); - } - var response = await exports2.timed(operation, options2); - } catch (err) { - if (Bounce.isSystem(err)) { - response = Boom5.badImplementation(err); - } else if (!Bounce.isError(err)) { - response = Boom5.badImplementation("Cannot throw non-error object", err); + #isReady = false; + get isReady() { + return this.#isReady; + } + #name; + #nodeClientOptions; + #sentinelClientOptions; + #scanInterval; + #passthroughClientErrorEvents; + #RESP; + #anotherReset = false; + #configEpoch = 0; + #sentinelRootNodes; + #sentinelClient; + #masterClients = []; + #masterClientQueue; + #masterPoolSize; + #replicaClients = []; + #replicaClientsIdx = 0; + #replicaPoolSize; + get useReplicas() { + return this.#replicaPoolSize > 0; + } + #connectPromise; + #maxCommandRediscovers; + #pubSubProxy; + #scanTimer; + #destroy = false; + #trace = () => { + }; + #clientSideCache; + get clientSideCache() { + return this.#clientSideCache; + } + #validateOptions(options2) { + if (options2?.clientSideCache && options2?.RESP !== 3) { + throw new Error("Client Side Caching is only supported with RESP3"); + } + } + constructor(options2) { + super(); + this.#validateOptions(options2); + this.#name = options2.name; + this.#RESP = options2.RESP; + this.#sentinelRootNodes = Array.from(options2.sentinelRootNodes); + this.#maxCommandRediscovers = options2.maxCommandRediscovers ?? 16; + this.#masterPoolSize = options2.masterPoolSize ?? 1; + this.#replicaPoolSize = options2.replicaPoolSize ?? 0; + this.#scanInterval = options2.scanInterval ?? 0; + this.#passthroughClientErrorEvents = options2.passthroughClientErrorEvents ?? false; + this.#nodeClientOptions = options2.nodeClientOptions ? { ...options2.nodeClientOptions } : {}; + if (this.#nodeClientOptions.url !== void 0) { + throw new Error("invalid nodeClientOptions for Sentinel"); + } + if (options2.clientSideCache) { + if (options2.clientSideCache instanceof cache_1.PooledClientSideCacheProvider) { + this.#clientSideCache = this.#nodeClientOptions.clientSideCache = options2.clientSideCache; } else { - response = Boom5.boomify(err); + const cscConfig = options2.clientSideCache; + this.#clientSideCache = this.#nodeClientOptions.clientSideCache = new cache_1.BasicPooledClientSideCache(cscConfig); } } - if (options2.ignoreResponse) { - return response; + this.#sentinelClientOptions = options2.sentinelClientOptions ? Object.assign({}, options2.sentinelClientOptions) : {}; + this.#sentinelClientOptions.modules = module_1.default; + if (this.#sentinelClientOptions.url !== void 0) { + throw new Error("invalid sentinelClientOptions for Sentinel"); } - if (response === void 0) { - response = Boom5.badImplementation(`${method.name} method did not return a value, a promise, or throw an error`); + this.#masterClientQueue = new wait_queue_1.WaitQueue(); + for (let i2 = 0; i2 < this.#masterPoolSize; i2++) { + this.#masterClientQueue.push(i2); } - if (options2.continue && response === exports2.symbols.continue) { - if (options2.continue === "undefined") { - return; + this.#pubSubProxy = new pub_sub_proxy_1.PubSubProxy(this.#nodeClientOptions, (err) => this.emit("error", err)); + } + #createClient(node, clientOptions, reconnectStrategy) { + return client_1.default.create({ + //first take the globally set RESP + RESP: this.#RESP, + //then take the client options, which can in theory overwrite it + ...clientOptions, + socket: { + ...clientOptions.socket, + host: node.host, + port: node.port, + ...reconnectStrategy !== void 0 && { reconnectStrategy } } - response = null; - } - if (options2.auth && response instanceof internals.Auth) { - return response; + }); + } + /** + * Gets a client lease from the master client pool + * + * @returns A client info object or a promise that resolves to a client info object + * when a client becomes available + */ + getClientLease() { + const id = this.#masterClientQueue.shift(); + if (id !== void 0) { + return { id }; } - if (typeof response !== "symbol") { - response = request._core.Response.wrap(response, request); - if (!response.isBoom && response._state === "init") { - await response._prepare(); + return this.#masterClientQueue.wait().then((id2) => ({ id: id2 })); + } + /** + * Releases a client lease back to the pool + * + * If the client was used for a transaction that might have left it in a dirty state, + * it will be reset before being returned to the pool. + * + * @param clientInfo The client info object representing the client to release + * @returns A promise that resolves when the client is ready to be reused, or undefined + * if the client was immediately ready or no longer exists + */ + releaseClientLease(clientInfo) { + const client = this.#masterClients[clientInfo.id]; + if (client !== void 0) { + const dirtyPromise = client.resetIfDirty(); + if (dirtyPromise) { + return dirtyPromise.then(() => this.#masterClientQueue.push(clientInfo.id)); } } - return response; - } - decorate(name, method) { - this._toolkit.prototype[name] = method; + this.#masterClientQueue.push(clientInfo.id); } - async failAction(request, failAction, err, options2) { - const retain = options2.retain ? err : void 0; - if (failAction === "ignore") { - return retain; - } - if (failAction === "log") { - request._log(options2.tags, err); - return retain; + async connect() { + if (this.#isOpen) { + throw new Error("already attempting to open"); } - if (failAction === "error") { - throw err; + try { + this.#isOpen = true; + this.#connectPromise = this.#connect(); + await this.#connectPromise; + this.#isReady = true; + } finally { + this.#connectPromise = void 0; + if (this.#scanInterval > 0) { + this.#scanTimer = setInterval(this.#reset.bind(this), this.#scanInterval); + } } - return await this.execute(failAction, request, { realm: request.route.realm, args: [options2.details ?? err] }); - } - }; - exports2.timed = async function(method, options2) { - if (!options2.timeout) { - return method; } - const timer2 = new Promise((resolve82, reject) => { - const handler = () => { - reject(Boom5.internal(`${options2.name} timed out`)); - }; - setTimeout(handler, options2.timeout); - }); - return await Promise.race([timer2, method]); - }; - internals.toolkit = function() { - const Toolkit = class { - constructor(request, options2) { - this.context = options2.bind; - this.realm = options2.realm; - this.request = request; - this._auth = options2.auth; - } - response(result) { - Hoek.assert(!result || typeof result !== "object" || typeof result.then !== "function", "Cannot wrap a promise"); - Hoek.assert(result instanceof Error === false, "Cannot wrap an error"); - Hoek.assert(typeof result !== "symbol", "Cannot wrap a symbol"); - return this.request._core.Response.wrap(result, this.request); - } - redirect(location) { - return this.response("").redirect(location); - } - entity(options2) { - Hoek.assert(options2, "Entity method missing required options"); - Hoek.assert(options2.etag || options2.modified, "Entity methods missing required options key"); - this.request._entity = options2; - const entity = this.request._core.Response.entity(options2.etag, options2); - if (this.request._core.Response.unmodified(this.request, entity)) { - return this.response().code(304).takeover(); - } - } - state(name, value, options2) { - this.request._setState(name, value, options2); - } - unstate(name, options2) { - this.request._clearState(name, options2); - } - authenticated(data) { - Hoek.assert(this._auth, "Method not supported outside of authentication"); - Hoek.assert(data?.credentials, "Authentication data missing credentials information"); - return new internals.Auth(null, data); - } - unauthenticated(error2, data) { - Hoek.assert(this._auth, "Method not supported outside of authentication"); - Hoek.assert(!data || data.credentials, "Authentication data missing credentials information"); - return new internals.Auth(error2, data); + async #connect() { + let count = 0; + while (true) { + this.#trace("starting connect loop"); + count += 1; + if (this.#destroy) { + this.#trace("in #connect and want to destroy"); + return; + } + try { + this.#anotherReset = false; + await this.transform(this.analyze(await this.observe())); + if (this.#anotherReset) { + this.#trace("#connect: anotherReset is true, so continuing"); + continue; + } + this.#trace("#connect: returning"); + return; + } catch (e2) { + this.#trace(`#connect: exception ${e2.message}`); + if (!this.#isReady && count > this.#maxCommandRediscovers) { + throw e2; + } + if (e2.message !== "no valid master node") { + console.log(e2); + } + await (0, promises_1.setTimeout)(1e3); + } finally { + this.#trace("finished connect"); + } } - }; - Toolkit.prototype.abandon = exports2.symbols.abandon; - Toolkit.prototype.close = exports2.symbols.close; - Toolkit.prototype.continue = exports2.symbols.continue; - return Toolkit; - }; - internals.Auth = class { - constructor(error2, data) { - this.isAuth = true; - this.error = error2; - this.data = data; - } - }; - } -}); -var require_lib32 = __commonJS({ - "node_modules/.deno/@hapi+ammo@6.0.1/node_modules/@hapi/ammo/lib/index.js"(exports2) { - "use strict"; - var Stream = __require2("stream"); - var Hoek = require_lib(); - var internals = {}; - internals.headerRx = /^bytes=[\s,]*((?:(?:\d+\-\d*)|(?:\-\d+))(?:\s*,\s*(?:(?:\d+\-\d*)|(?:\-\d+)))*)$/i; - exports2.header = function(header, length2) { - const parts = internals.headerRx.exec(header); - if (!parts) { - return null; } - const lastPos = length2 - 1; - const result = []; - const ranges = parts[1].match(/\d*\-\d*/g); - for (let range of ranges) { - let from3; - let to; - range = range.split("-"); - if (range[0]) { - from3 = parseInt(range[0], 10); - } - if (range[1]) { - to = parseInt(range[1], 10); - if (from3 !== void 0) { - if (to > lastPos) { - to = lastPos; + async execute(fn, clientInfo) { + let iter = 0; + while (true) { + if (this.#connectPromise !== void 0) { + await this.#connectPromise; + } + const client = this.#getClient(clientInfo); + if (!client.isReady) { + await this.#reset(); + continue; + } + const sockOpts = client.options?.socket; + this.#trace("attemping to send command to " + sockOpts?.host + ":" + sockOpts?.port); + try { + return await fn(client); + } catch (err) { + if (++iter > this.#maxCommandRediscovers || !(err instanceof Error)) { + throw err; } - } else { - from3 = length2 - to; - to = lastPos; + if (clientInfo !== void 0 && (err.message.startsWith("READONLY") || !client.isReady)) { + await this.#reset(); + continue; + } + throw err; } - } else { - to = lastPos; - } - if (from3 > to) { - return null; } - result.push(new internals.Range(from3, to)); - } - if (result.length === 1) { - return result; } - result.sort((a, b) => a.from - b.from); - const consolidated = []; - for (let i2 = result.length - 1; i2 > 0; --i2) { - const current = result[i2]; - const before = result[i2 - 1]; - if (current.from <= before.to + 1) { - before.to = current.to; - } else { - consolidated.unshift(current); - } + async #createPubSub(client) { + await client.pSubscribe(["switch-master", "[-+]sdown", "+slave", "+sentinel", "[-+]odown", "+slave-reconf-done"], (message, channel) => { + this.#handlePubSubControlChannel(channel, message); + }, true); + return client; } - consolidated.unshift(result[0]); - return consolidated; - }; - internals.Range = class { - constructor(from3, to) { - this.from = from3; - this.to = to; + async #handlePubSubControlChannel(channel, message) { + this.#trace("pubsub control channel message on " + channel); + this.#reset(); } - }; - exports2.Clip = class extends Stream.Transform { - constructor(range) { - if (!(range instanceof internals.Range)) { - Hoek.assert(typeof range === "object", 'Expected "range" object'); - const from3 = range.from ?? 0; - Hoek.assert(typeof from3 === "number", '"range.from" must be a number'); - Hoek.assert(from3 === parseInt(from3, 10) && from3 >= 0, '"range.from" must be a positive integer'); - const to = range.to ?? 0; - Hoek.assert(typeof to === "number", '"range.to" must be a number'); - Hoek.assert(to === parseInt(to, 10) && to >= 0, '"range.to" must be a positive integer'); - Hoek.assert(to >= from3, '"range.to" must be greater than or equal to "range.from"'); - range = new internals.Range(from3, to); + // if clientInfo is defined, it corresponds to a master client in the #masterClients array, otherwise loop around replicaClients + #getClient(clientInfo) { + if (clientInfo !== void 0) { + return this.#masterClients[clientInfo.id]; } - super(); - this._range = range; - this._next = 0; - this._pipes = /* @__PURE__ */ new Set(); - this.on("pipe", (pipe2) => this._pipes.add(pipe2)); - this.on("unpipe", (pipe2) => this._pipes.delete(pipe2)); - } - _transform(chunk, encoding, done) { - try { - internals.processChunk(this, chunk); - } catch (err) { - return done(err); + if (this.#replicaClientsIdx >= this.#replicaClients.length) { + this.#replicaClientsIdx = 0; } - return done(); - } - _flush(done) { - this._pipes.clear(); - done(); - } - }; - internals.processChunk = function(stream, chunk) { - const pos = stream._next; - stream._next = stream._next + chunk.length; - if (stream._next <= stream._range.from) { - return; - } - if (pos > stream._range.to) { - for (const pipe2 of stream._pipes) { - pipe2.unpipe(stream); + if (this.#replicaClients.length == 0) { + throw new Error("no replicas available for read"); } - stream._pipes.clear(); - stream.end(); - return; + return this.#replicaClients[this.#replicaClientsIdx++]; } - const from3 = Math.max(0, stream._range.from - pos); - const to = Math.min(chunk.length, stream._range.to - pos + 1); - stream.push(chunk.slice(from3, to)); - }; - } -}); -var require_transmit = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/transmit.js"(exports2) { - "use strict"; - var Http = __require2("http"); - var Ammo = require_lib32(); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var Teamwork = require_lib11(); - var Config = require_config(); - var internals = {}; - exports2.send = async function(request) { - const response = request.response; - try { - if (response.isBoom) { - await internals.fail(request, response); + async #reset() { + if (this.#isReady == false || this.#destroy == true) { return; } - await internals.marshal(response); - await internals.transmit(response); - } catch (err) { - Bounce.rethrow(err, "system"); - request._setResponse(err); - return internals.fail(request, err); - } - }; - internals.marshal = async function(response) { - for (const func of response.request._route._marshalCycle) { - await func(response); - } - }; - internals.fail = async function(request, boom) { - const response = internals.error(request, boom); - request.response = response; - try { - await internals.marshal(response); - } catch (err) { - Bounce.rethrow(err, "system"); - const minimal = { - statusCode: response.statusCode, - error: Http.STATUS_CODES[response.statusCode], - message: boom.message - }; - response._payload = new request._core.Response.Payload(JSON.stringify(minimal), {}); - } - return internals.transmit(response); - }; - internals.error = function(request, boom) { - const error2 = boom.output; - const response = new request._core.Response(error2.payload, request, { error: boom }); - response.code(error2.statusCode); - response.headers = Hoek.clone(error2.headers); - return response; - }; - internals.transmit = function(response) { - const request = response.request; - const length2 = internals.length(response); - const encoding = request._core.compression.encoding(response, length2); - const ranger = encoding ? null : internals.range(response, length2); - const compressor = internals.encoding(response, encoding); - const isInjection = request.isInjected; - if (!(isInjection || request._core.started) || request._isPayloadPending && !request.raw.req._readableState.ended) { - response._header("connection", "close"); - } - internals.writeHead(response); - if (isInjection) { - request.raw.res[Config.symbol] = { request }; - if (response.variety === "plain") { - request.raw.res[Config.symbol].result = response._isPayloadSupported() ? response.source : null; - } - } - const stream = internals.chain([response._payload, response._tap(), compressor, ranger]); - return internals.pipe(request, stream); - }; - internals.length = function(response) { - const request = response.request; - const header = response.headers["content-length"]; - if (header === void 0) { - return null; - } - let length2 = header; - if (typeof length2 === "string") { - length2 = parseInt(header, 10); - if (!isFinite(length2)) { - delete response.headers["content-length"]; - return null; + if (this.#connectPromise !== void 0) { + this.#anotherReset = true; + return await this.#connectPromise; + } + try { + this.#connectPromise = this.#connect(); + return await this.#connectPromise; + } finally { + this.#trace("finished reconfgure"); + this.#connectPromise = void 0; } } - if (length2 === 0 && !response._statusCode && response.statusCode === 200 && request.route.settings.response.emptyStatusCode !== 200) { - response.code(204); - delete response.headers["content-length"]; - } - return length2; - }; - internals.range = function(response, length2) { - const request = response.request; - if (!length2 || !request.route.settings.response.ranges || request.method !== "get" || response.statusCode !== 200) { - return null; - } - response._header("accept-ranges", "bytes"); - if (!request.headers.range) { - return null; - } - if (request.headers["if-range"] && request.headers["if-range"] !== response.headers.etag) { - return null; - } - const ranges = Ammo.header(request.headers.range, length2); - if (!ranges) { - const error2 = Boom5.rangeNotSatisfiable(); - error2.output.headers["content-range"] = "bytes */" + length2; - throw error2; - } - if (ranges.length !== 1) { - return null; - } - const range = ranges[0]; - response.code(206); - response.bytes(range.to - range.from + 1); - response._header("content-range", "bytes " + range.from + "-" + range.to + "/" + length2); - return new Ammo.Clip(range); - }; - internals.encoding = function(response, encoding) { - const request = response.request; - const header = response.headers["content-encoding"] || encoding; - if (header && response.headers.etag && response.settings.varyEtag) { - response.headers.etag = response.headers.etag.slice(0, -1) + "-" + header + '"'; - } - if (!encoding || response.statusCode === 206 || !response._isPayloadSupported()) { - return null; - } - delete response.headers["content-length"]; - response._header("content-encoding", encoding); - const compressor = request._core.compression.encoder(request, encoding); - if (response.variety === "stream" && typeof response._payload.setCompressor === "function") { - response._payload.setCompressor(compressor); - } - return compressor; - }; - internals.pipe = function(request, stream) { - const team = new Teamwork.Team(); - const env2 = { stream, request, team }; - if (request._closed) { - internals.end(env2, "aborted"); - return team.work; - } - const aborted2 = internals.end.bind(null, env2, "aborted"); - const close = internals.end.bind(null, env2, "close"); - const end = internals.end.bind(null, env2, null); - request.raw.req.on("aborted", aborted2); - request.raw.res.on("close", close); - request.raw.res.on("error", end); - request.raw.res.on("finish", end); - if (stream.writeToStream) { - stream.writeToStream(request.raw.res); - } else { - stream.on("error", end); - stream.on("close", aborted2); - stream.pipe(request.raw.res); - } - return team.work; - }; - internals.end = function(env2, event, err) { - const { request, stream, team } = env2; - if (!team) { - return; - } - env2.team = null; - if (request.raw.res.writableEnded) { - request.info.responded = Date.now(); - team.attend(); - return; - } - if (err) { - request.raw.res.destroy(); - request._core.Response.drain(stream); - } - const origResponse = request.response; - const error2 = err ? Boom5.boomify(err) : new Boom5.Boom(`Request ${event}`, { statusCode: request.route.settings.response.disconnectStatusCode, data: origResponse }); - request._setResponse(error2); - if (request.raw.res[Config.symbol]) { - request.raw.res[Config.symbol].error = event ? error2 : new Boom5.Boom(`Response error`, { statusCode: request.route.settings.response.disconnectStatusCode, data: origResponse }); + #handleSentinelFailure(node) { + const found = this.#sentinelRootNodes.findIndex((rootNode) => rootNode.host === node.host && rootNode.port === node.port); + if (found !== -1) { + this.#sentinelRootNodes.splice(found, 1); + } + this.#reset(); } - if (event) { - request._log(["response", "error", event]); - } else { - request._log(["response", "error"], err); + async close() { + this.#destroy = true; + if (this.#connectPromise != void 0) { + await this.#connectPromise; + } + this.#isReady = false; + this.#clientSideCache?.onPoolClose(); + if (this.#scanTimer) { + clearInterval(this.#scanTimer); + this.#scanTimer = void 0; + } + const promises = []; + if (this.#sentinelClient !== void 0) { + if (this.#sentinelClient.isOpen) { + promises.push(this.#sentinelClient.close()); + } + this.#sentinelClient = void 0; + } + for (const client of this.#masterClients) { + if (client.isOpen) { + promises.push(client.close()); + } + } + this.#masterClients = []; + for (const client of this.#replicaClients) { + if (client.isOpen) { + promises.push(client.close()); + } + } + this.#replicaClients = []; + await Promise.all(promises); + this.#pubSubProxy.destroy(); + this.#isOpen = false; } - request.raw.res.end(); - team.attend(); - }; - internals.writeHead = function(response) { - const res = response.request.raw.res; - const headers = Object.keys(response.headers); - let i2 = 0; - try { - for (; i2 < headers.length; ++i2) { - const header = headers[i2]; - const value = response.headers[header]; - if (value !== void 0) { - res.setHeader(header, value); + // destroy has to be async because its stopping others async events, timers and the like + // and shouldn't return until its finished. + async destroy() { + this.#destroy = true; + if (this.#connectPromise != void 0) { + await this.#connectPromise; + } + this.#isReady = false; + this.#clientSideCache?.onPoolClose(); + if (this.#scanTimer) { + clearInterval(this.#scanTimer); + this.#scanTimer = void 0; + } + if (this.#sentinelClient !== void 0) { + if (this.#sentinelClient.isOpen) { + this.#sentinelClient.destroy(); } + this.#sentinelClient = void 0; } - } catch (err) { - for (--i2; i2 >= 0; --i2) { - res.removeHeader(headers[i2]); + for (const client of this.#masterClients) { + if (client.isOpen) { + client.destroy(); + } + } + this.#masterClients = []; + for (const client of this.#replicaClients) { + if (client.isOpen) { + client.destroy(); + } } - throw Boom5.boomify(err); + this.#replicaClients = []; + this.#pubSubProxy.destroy(); + this.#isOpen = false; + this.#destroy = false; } - if (response.settings.message) { - res.statusMessage = response.settings.message; + async subscribe(channels, listener, bufferMode) { + return this.#pubSubProxy.subscribe(channels, listener, bufferMode); } - try { - res.writeHead(response.statusCode); - } catch (err) { - throw Boom5.boomify(err); - } - }; - internals.chain = function(sources) { - let from3 = sources[0]; - for (let i2 = 1; i2 < sources.length; ++i2) { - const to = sources[i2]; - if (to) { - from3.on("close", internals.destroyPipe.bind(from3, to)); - from3.on("error", internals.errorPipe.bind(from3, to)); - from3 = from3.pipe(to); - } - } - return from3; - }; - internals.destroyPipe = function(to) { - if (!this.readableEnded && !this.errored) { - to.destroy(); - } - }; - internals.errorPipe = function(to, err) { - to.emit("error", err); - }; - } -}); -var require_request2 = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/request.js"(exports2, module14) { - "use strict"; - var Querystring = __require2("querystring"); - var Url = __require2("url"); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var Podium = require_lib15(); - var Cors = require_cors(); - var Toolkit = require_toolkit(); - var Transmit = require_transmit(); - var internals = { - events: Podium.validate(["finish", { name: "peek", spread: true }, "disconnect"]), - reserved: ["server", "url", "query", "path", "method", "mime", "setUrl", "setMethod", "headers", "id", "app", "plugins", "route", "auth", "pre", "preResponses", "info", "isInjected", "orig", "params", "paramsArray", "payload", "state", "response", "raw", "domain", "log", "logs", "generateResponse"] - }; - exports2 = module14.exports = internals.Request = class { - constructor(server, req, res, options2) { - this._allowInternals = !!options2.allowInternals; - this._closed = false; - this._core = server._core; - this._entity = null; - this._eventContext = { request: this }; - this._events = null; - this._expectContinue = !!options2.expectContinue; - this._isInjected = !!options2.isInjected; - this._isPayloadPending = !!(req.headers["content-length"] || req.headers["transfer-encoding"]); - this._isReplied = false; - this._route = this._core.router.specials.notFound.route; - this._serverTimeoutId = null; - this._states = {}; - this._url = null; - this._urlError = null; - this.app = options2.app ? Object.assign({}, options2.app) : {}; - this.headers = req.headers; - this.logs = []; - this.method = req.method.toLowerCase(); - this.mime = null; - this.orig = {}; - this.params = null; - this.paramsArray = null; - this.path = null; - this.payload = void 0; - this.plugins = options2.plugins ? Object.assign({}, options2.plugins) : {}; - this.pre = {}; - this.preResponses = {}; - this.raw = { req, res }; - this.response = null; - this.route = this._route.public; - this.query = null; - this.server = server; - this.state = null; - this.info = new internals.Info(this); - this.auth = { - isAuthenticated: false, - isAuthorized: false, - isInjected: options2.auth ? true : false, - [internals.Request.symbols.authPayload]: options2.auth?.payload ?? true, - credentials: options2.auth?.credentials ?? null, - // Special keys: 'app', 'user', 'scope' - artifacts: options2.auth?.artifacts ?? null, - // Scheme-specific artifacts - strategy: options2.auth?.strategy ?? null, - mode: null, - error: null - }; - this._initializeUrl(); + async unsubscribe(channels, listener, bufferMode) { + return this.#pubSubProxy.unsubscribe(channels, listener, bufferMode); + } + async pSubscribe(patterns, listener, bufferMode) { + return this.#pubSubProxy.pSubscribe(patterns, listener, bufferMode); } - static generate(server, req, res, options2) { - const request = new server._core.Request(server, req, res, options2); - if (server._core.decorations.requestApply) { - for (const [property, assignment] of server._core.decorations.requestApply.entries()) { - request[property] = assignment(request); + async pUnsubscribe(patterns, listener, bufferMode) { + return this.#pubSubProxy.pUnsubscribe(patterns, listener, bufferMode); + } + // observe/analyze/transform remediation functions + async observe() { + for (const node of this.#sentinelRootNodes) { + let client; + try { + this.#trace(`observe: trying to connect to sentinel: ${node.host}:${node.port}`); + client = this.#createClient(node, this.#sentinelClientOptions, false); + client.on("error", (err) => this.emit("error", `obseve client error: ${err}`)); + await client.connect(); + this.#trace(`observe: connected to sentinel`); + const [sentinelData, masterData, replicaData] = await Promise.all([ + client.sentinel.sentinelSentinels(this.#name), + client.sentinel.sentinelMaster(this.#name), + client.sentinel.sentinelReplicas(this.#name) + ]); + this.#trace("observe: got all sentinel data"); + const ret = { + sentinelConnected: node, + sentinelData, + masterData, + replicaData, + currentMaster: this.getMasterNode(), + currentReplicas: this.getReplicaNodes(), + currentSentinel: this.getSentinelNode(), + replicaPoolSize: this.#replicaPoolSize, + useReplicas: this.useReplicas + }; + return ret; + } catch (err) { + this.#trace(`observe: error ${err}`); + this.emit("error", err); + } finally { + if (client !== void 0 && client.isOpen) { + this.#trace(`observe: destroying sentinel client`); + client.destroy(); + } } } - request._listen(); - return request; + this.#trace(`observe: none of the sentinels are available`); + throw new Error("None of the sentinels are available"); } - get events() { - if (!this._events) { - this._events = new Podium.Podium(internals.events); + analyze(observed) { + let master = (0, utils_1.parseNode)(observed.masterData); + if (master === void 0) { + this.#trace(`analyze: no valid master node because ${observed.masterData.flags}`); + throw new Error("no valid master node"); } - return this._events; - } - get isInjected() { - return this._isInjected; - } - get url() { - if (this._urlError) { - return null; + if (master.host === observed.currentMaster?.host && master.port === observed.currentMaster?.port) { + this.#trace(`analyze: master node hasn't changed from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`); + master = void 0; + } else { + this.#trace(`analyze: master node has changed to ${master.host}:${master.port} from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`); } - if (this._url) { - return this._url; + let sentinel = observed.sentinelConnected; + if (sentinel.host === observed.currentSentinel?.host && sentinel.port === observed.currentSentinel.port) { + this.#trace(`analyze: sentinel node hasn't changed`); + sentinel = void 0; + } else { + this.#trace(`analyze: sentinel node has changed to ${sentinel.host}:${sentinel.port}`); } - return this._parseUrl(this.raw.req.url, this._core.settings.router); - } - _initializeUrl() { - try { - this._setUrl(this.raw.req.url, this._core.settings.router.stripTrailingSlash, { fast: true }); - } catch (err) { - this.path = this.raw.req.url; - this.query = {}; - this._urlError = Boom5.boomify(err, { statusCode: 400, override: false }); - } - } - setUrl(url2, stripTrailingSlash) { - Hoek.assert(this.params === null, "Cannot change request URL after routing"); - if (url2 instanceof Url.URL) { - url2 = url2.href; - } - Hoek.assert(typeof url2 === "string", "Url must be a string or URL object"); - this._setUrl(url2, stripTrailingSlash, { fast: false }); - } - _setUrl(source, stripTrailingSlash, { fast }) { - const url2 = this._parseUrl(source, { stripTrailingSlash, _fast: fast }); - this.query = this._parseQuery(url2.searchParams); - this.path = url2.pathname; - } - _parseUrl(source, options2) { - if (source[0] === "/") { - if (options2._fast) { - const url2 = { - pathname: source, - searchParams: "" - }; - const q = source.indexOf("?"); - const h2 = source.indexOf("#"); - if (q !== -1 && (h2 === -1 || q < h2)) { - url2.pathname = source.slice(0, q); - const query = h2 === -1 ? source.slice(q + 1) : source.slice(q + 1, h2); - url2.searchParams = Querystring.parse(query); + const replicasToClose = []; + const replicasToOpen = /* @__PURE__ */ new Map(); + const desiredSet = /* @__PURE__ */ new Set(); + const seen = /* @__PURE__ */ new Set(); + if (observed.useReplicas) { + const replicaList = (0, utils_1.createNodeList)(observed.replicaData); + for (const node of replicaList) { + desiredSet.add(JSON.stringify(node)); + } + for (const [node, value] of observed.currentReplicas) { + if (!desiredSet.has(JSON.stringify(node))) { + replicasToClose.push(node); + this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToClose`); } else { - url2.pathname = h2 === -1 ? source : source.slice(0, h2); + seen.add(JSON.stringify(node)); + if (value != observed.replicaPoolSize) { + replicasToOpen.set(node, observed.replicaPoolSize - value); + this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToOpen`); + } + } + } + for (const node of replicaList) { + if (!seen.has(JSON.stringify(node))) { + replicasToOpen.set(node, observed.replicaPoolSize); + this.#trace(`analyze: adding ${node.host}:${node.port} to replicsToOpen`); } - this._normalizePath(url2, options2); - return url2; } - this._url = new Url.URL(`${this._core.info.protocol}://${this.info.host || `${this._core.info.host}:${this._core.info.port}`}${source}`); - } else { - this._url = new Url.URL(source); - this.info.hostname = this._url.hostname; - this.info.host = this._url.host; } - this._normalizePath(this._url, options2); - this._urlError = null; - return this._url; + const ret = { + sentinelList: [observed.sentinelConnected].concat((0, utils_1.createNodeList)(observed.sentinelData)), + epoch: Number(observed.masterData["config-epoch"]), + sentinelToOpen: sentinel, + masterToOpen: master, + replicasToClose, + replicasToOpen + }; + return ret; } - _normalizePath(url2, options2) { - let path8 = this._core.router.normalize(url2.pathname); - if (options2.stripTrailingSlash && path8.length > 1 && path8[path8.length - 1] === "/") { - path8 = path8.slice(0, -1); + async transform(analyzed) { + this.#trace("transform: enter"); + let promises = []; + if (analyzed.sentinelToOpen) { + this.#trace(`transform: opening a new sentinel`); + if (this.#sentinelClient !== void 0 && this.#sentinelClient.isOpen) { + this.#trace(`transform: destroying old sentinel as open`); + this.#sentinelClient.destroy(); + this.#sentinelClient = void 0; + } else { + this.#trace(`transform: not destroying old sentinel as not open`); + } + this.#trace(`transform: creating new sentinel to ${analyzed.sentinelToOpen.host}:${analyzed.sentinelToOpen.port}`); + const node = analyzed.sentinelToOpen; + const client = this.#createClient(analyzed.sentinelToOpen, this.#sentinelClientOptions, false); + client.on("error", (err) => { + if (this.#passthroughClientErrorEvents) { + this.emit("error", new Error(`Sentinel Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); + } + const event2 = { + type: "SENTINEL", + node: (0, utils_1.clientSocketToNode)(client.options.socket), + error: err + }; + this.emit("client-error", event2); + this.#handleSentinelFailure(node); + }).on("end", () => this.#handleSentinelFailure(node)); + this.#sentinelClient = client; + this.#trace(`transform: adding sentinel client connect() to promise list`); + const promise = this.#sentinelClient.connect().then((client2) => { + return this.#createPubSub(client2); + }); + promises.push(promise); + this.#trace(`created sentinel client to ${analyzed.sentinelToOpen.host}:${analyzed.sentinelToOpen.port}`); + const event = { + type: "SENTINEL_CHANGE", + node: analyzed.sentinelToOpen + }; + this.#trace(`transform: emiting topology-change event for sentinel_change`); + if (!this.emit("topology-change", event)) { + this.#trace(`transform: emit for topology-change for sentinel_change returned false`); + } } - url2.pathname = path8; - } - _parseQuery(searchParams) { - let query = /* @__PURE__ */ Object.create(null); - if (searchParams instanceof Url.URLSearchParams) { - for (let [key, value] of searchParams) { - const entry = query[key]; - if (entry !== void 0) { - value = [].concat(entry, value); + if (analyzed.masterToOpen) { + this.#trace(`transform: opening a new master`); + const masterPromises = []; + const masterWatches = []; + this.#trace(`transform: destroying old masters if open`); + for (const client of this.#masterClients) { + masterWatches.push(client.isWatching || client.isDirtyWatch); + if (client.isOpen) { + client.destroy(); } - query[key] = value; } - } else { - query = Object.assign(query, searchParams); + this.#masterClients = []; + this.#trace(`transform: creating all master clients and adding connect promises`); + for (let i2 = 0; i2 < this.#masterPoolSize; i2++) { + const node = analyzed.masterToOpen; + const client = this.#createClient(analyzed.masterToOpen, this.#nodeClientOptions); + client.on("error", (err) => { + if (this.#passthroughClientErrorEvents) { + this.emit("error", new Error(`Master Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); + } + const event2 = { + type: "MASTER", + node: (0, utils_1.clientSocketToNode)(client.options.socket), + error: err + }; + this.emit("client-error", event2); + }); + if (masterWatches[i2]) { + client.setDirtyWatch("sentinel config changed in middle of a WATCH Transaction"); + } + this.#masterClients.push(client); + masterPromises.push(client.connect()); + this.#trace(`created master client to ${analyzed.masterToOpen.host}:${analyzed.masterToOpen.port}`); + } + this.#trace(`transform: adding promise to change #pubSubProxy node`); + masterPromises.push(this.#pubSubProxy.changeNode(analyzed.masterToOpen)); + promises.push(...masterPromises); + const event = { + type: "MASTER_CHANGE", + node: analyzed.masterToOpen + }; + this.#trace(`transform: emiting topology-change event for master_change`); + if (!this.emit("topology-change", event)) { + this.#trace(`transform: emit for topology-change for master_change returned false`); + } + this.#configEpoch++; + } + const replicaCloseSet = /* @__PURE__ */ new Set(); + for (const node of analyzed.replicasToClose) { + const str = JSON.stringify(node); + replicaCloseSet.add(str); } - const parser3 = this._core.settings.query.parser; - if (parser3) { - query = parser3(query); - if (!query || typeof query !== "object") { - throw Boom5.badImplementation("Parsed query must be an object"); + const newClientList = []; + const removedSet = /* @__PURE__ */ new Set(); + for (const replica of this.#replicaClients) { + const node = (0, utils_1.clientSocketToNode)(replica.options.socket); + const str = JSON.stringify(node); + if (replicaCloseSet.has(str) || !replica.isOpen) { + if (replica.isOpen) { + const sockOpts = replica.options?.socket; + this.#trace(`destroying replica client to ${sockOpts?.host}:${sockOpts?.port}`); + replica.destroy(); + } + if (!removedSet.has(str)) { + const event = { + type: "REPLICA_REMOVE", + node + }; + this.emit("topology-change", event); + removedSet.add(str); + } + } else { + newClientList.push(replica); } } - return query; - } - setMethod(method) { - Hoek.assert(this.params === null, "Cannot change request method after routing"); - Hoek.assert(method && typeof method === "string", "Missing method"); - this.method = method.toLowerCase(); - } - active() { - return !!this._eventContext.request; - } - async _execute() { - this.info.acceptEncoding = this._core.compression.accept(this); - try { - await this._onRequest(); - } catch (err) { - Bounce.rethrow(err, "system"); - return this._reply(err); - } - this._lookup(); - this._setTimeouts(); - await this._lifecycle(); - this._reply(); - } - async _onRequest() { - if (this._core.extensions.route.onRequest.nodes) { - const response = await this._invoke(this._core.extensions.route.onRequest); - if (response) { - if (!internals.skip(response)) { - throw Boom5.badImplementation("onRequest extension methods must return an error, a takeover response, or a continue signal"); + this.#replicaClients = newClientList; + if (analyzed.replicasToOpen.size != 0) { + for (const [node, size] of analyzed.replicasToOpen) { + for (let i2 = 0; i2 < size; i2++) { + const client = this.#createClient(node, this.#nodeClientOptions); + client.on("error", (err) => { + if (this.#passthroughClientErrorEvents) { + this.emit("error", new Error(`Replica Client (${node.host}:${node.port}): ${err.message}`, { cause: err })); + } + const event2 = { + type: "REPLICA", + node: (0, utils_1.clientSocketToNode)(client.options.socket), + error: err + }; + this.emit("client-error", event2); + }); + this.#replicaClients.push(client); + promises.push(client.connect()); + this.#trace(`created replica client to ${node.host}:${node.port}`); } - throw response; + const event = { + type: "REPLICA_ADD", + node + }; + this.emit("topology-change", event); } } - if (this._urlError) { - throw this._urlError; + if (analyzed.sentinelList.length != this.#sentinelRootNodes.length) { + this.#sentinelRootNodes = analyzed.sentinelList; + const event = { + type: "SENTINE_LIST_CHANGE", + size: analyzed.sentinelList.length + }; + this.emit("topology-change", event); } + await Promise.all(promises); + this.#trace("transform: exit"); } - _listen() { - if (this._isPayloadPending) { - this.raw.req.on("end", internals.event.bind(this.raw.req, this._eventContext, "end")); + // introspection functions + getMasterNode() { + if (this.#masterClients.length == 0) { + return void 0; } - this.raw.res.on("close", internals.event.bind(this.raw.res, this._eventContext, "close")); - this.raw.req.on("error", internals.event.bind(this.raw.req, this._eventContext, "error")); - this.raw.req.on("aborted", internals.event.bind(this.raw.req, this._eventContext, "abort")); - this.raw.res.once("close", internals.closed.bind(this.raw.res, this)); - } - _lookup() { - const match = this._core.router.route(this.method, this.path, this.info.hostname); - if (!match.route.settings.isInternal || this._allowInternals) { - this._route = match.route; - this.route = this._route.public; + for (const master of this.#masterClients) { + if (master.isReady) { + return (0, utils_1.clientSocketToNode)(master.options.socket); + } } - this.params = match.params ?? {}; - this.paramsArray = match.paramsArray ?? []; - if (this.route.settings.cors) { - this.info.cors = { - isOriginMatch: Cors.matchOrigin(this.headers.origin, this.route.settings.cors) - }; + return void 0; + } + getSentinelNode() { + if (this.#sentinelClient === void 0) { + return void 0; } + return (0, utils_1.clientSocketToNode)(this.#sentinelClient.options.socket); } - _setTimeouts() { - if (this.raw.req.socket && this.route.settings.timeout.socket !== void 0) { - this.raw.req.socket.setTimeout(this.route.settings.timeout.socket || 0); + getReplicaNodes() { + const ret = /* @__PURE__ */ new Map(); + const initialMap = /* @__PURE__ */ new Map(); + for (const replica of this.#replicaClients) { + const node = (0, utils_1.clientSocketToNode)(replica.options.socket); + const hash3 = JSON.stringify(node); + if (replica.isReady) { + initialMap.set(hash3, (initialMap.get(hash3) ?? 0) + 1); + } else { + if (!initialMap.has(hash3)) { + initialMap.set(hash3, 0); + } + } } - let serverTimeout = this.route.settings.timeout.server; - if (!serverTimeout) { - return; + for (const [key, value] of initialMap) { + ret.set(JSON.parse(key), value); } - const elapsed = Date.now() - this.info.received; - serverTimeout = Math.floor(serverTimeout - elapsed); - if (serverTimeout <= 0) { - internals.timeoutReply(this, serverTimeout); - return; + return ret; + } + setTracer(tracer) { + if (tracer) { + this.#trace = (msg) => { + tracer.push(msg); + }; + } else { + this.#trace = () => { + }; } - this._serverTimeoutId = setTimeout(internals.timeoutReply, serverTimeout, this, serverTimeout); } - async _lifecycle() { - for (const func of this._route._cycle) { - if (this._isReplied) { - return; - } + }; + var RedisSentinelFactory = class extends node_events_1.EventEmitter { + options; + #sentinelRootNodes; + #replicaIdx = -1; + constructor(options2) { + super(); + this.options = options2; + this.#sentinelRootNodes = options2.sentinelRootNodes; + } + async updateSentinelRootNodes() { + for (const node of this.#sentinelRootNodes) { + const client = client_1.default.create({ + ...this.options.sentinelClientOptions, + socket: { + ...this.options.sentinelClientOptions?.socket, + host: node.host, + port: node.port, + reconnectStrategy: false + }, + modules: module_1.default + }).on("error", (err) => this.emit(`updateSentinelRootNodes: ${err}`)); try { - var response = await (typeof func === "function" ? func(this) : this._invoke(func)); - } catch (err) { - Bounce.rethrow(err, "system"); - response = this._core.Response.wrap(err, this); - } - if (!response || response === Toolkit.symbols.continue) { + await client.connect(); + } catch { + if (client.isOpen) { + client.destroy(); + } continue; } - if (!internals.skip(response)) { - response = Boom5.badImplementation("Lifecycle methods called before the handler can only return an error, a takeover response, or a continue signal"); + try { + const sentinelData = await client.sentinel.sentinelSentinels(this.options.name); + this.#sentinelRootNodes = [node].concat((0, utils_1.createNodeList)(sentinelData)); + return; + } finally { + client.destroy(); } - this._setResponse(response); - return; } + throw new Error("Couldn't connect to any sentinel node"); } - async _invoke(event, options2 = {}) { - for (const ext of event.nodes) { - const realm = ext.realm; - const bind = ext.bind ?? realm.settings.bind; - const response = await this._core.toolkit.execute(ext.func, this, { bind, realm, timeout: ext.timeout, name: event.type, ignoreResponse: options2.ignoreResponse }); - if (options2.ignoreResponse) { - if (Boom5.isBoom(response)) { - this._log(["ext", "error"], response); + async getMasterNode() { + let connected = false; + for (const node of this.#sentinelRootNodes) { + const client = client_1.default.create({ + ...this.options.sentinelClientOptions, + socket: { + ...this.options.sentinelClientOptions?.socket, + host: node.host, + port: node.port, + reconnectStrategy: false + }, + modules: module_1.default + }).on("error", (err) => this.emit(`getMasterNode: ${err}`)); + try { + await client.connect(); + } catch { + if (client.isOpen) { + client.destroy(); } continue; } - if (response === Toolkit.symbols.continue) { - continue; - } - if (internals.skip(response) || this.response === null) { - return response; + connected = true; + try { + const masterData = await client.sentinel.sentinelMaster(this.options.name); + let master = (0, utils_1.parseNode)(masterData); + if (master === void 0) { + continue; + } + return master; + } finally { + client.destroy(); } - this._setResponse(response); - } - } - async _reply(exit3) { - if (this._isReplied) { - return; - } - this._isReplied = true; - if (this._serverTimeoutId) { - clearTimeout(this._serverTimeoutId); } - if (exit3) { - this._setResponse(this._core.Response.wrap(exit3, this)); - } - if (!this._eventContext.request) { - this._finalize(); - return; - } - if (typeof this.response === "symbol") { - this._abort(); - return; - } - await this._postCycle(); - if (!this._eventContext.request || typeof this.response === "symbol") { - this._abort(); - return; + if (connected) { + throw new Error("Master Node Not Enumerated"); } - await Transmit.send(this); - this._finalize(); + throw new Error("couldn't connect to any sentinels"); } - async _postCycle() { - for (const func of this._route._postCycle) { - if (!this._eventContext.request) { - return; + async getMasterClient() { + const master = await this.getMasterNode(); + return client_1.default.create({ + ...this.options.nodeClientOptions, + socket: { + ...this.options.nodeClientOptions?.socket, + host: master.host, + port: master.port } + }); + } + async getReplicaNodes() { + let connected = false; + for (const node of this.#sentinelRootNodes) { + const client = client_1.default.create({ + ...this.options.sentinelClientOptions, + socket: { + ...this.options.sentinelClientOptions?.socket, + host: node.host, + port: node.port, + reconnectStrategy: false + }, + modules: module_1.default + }).on("error", (err) => this.emit(`getReplicaNodes: ${err}`)); try { - var response = await (typeof func === "function" ? func(this) : this._invoke(func)); - } catch (err) { - Bounce.rethrow(err, "system"); - response = this._core.Response.wrap(err, this); - } - if (response && response !== Toolkit.symbols.continue) { - this._setResponse(response); + await client.connect(); + } catch { + if (client.isOpen) { + client.destroy(); + } + continue; } - } - } - _abort() { - if (this.response === Toolkit.symbols.close) { - this.raw.res.end(); - } - this._finalize(); - } - _finalize() { - this._eventContext.request = null; - if (this.response._close) { - if (this.response.statusCode === 500 && this.response._error) { - const tags = this.response._error.isDeveloperError ? ["internal", "implementation", "error"] : ["internal", "error"]; - this._log(tags, this.response._error, "error"); + connected = true; + try { + const replicaData = await client.sentinel.sentinelReplicas(this.options.name); + const replicas = (0, utils_1.createNodeList)(replicaData); + if (replicas.length == 0) { + continue; + } + return replicas; + } finally { + client.destroy(); } - this.response._close(); - } - this.info.completed = Date.now(); - this._core.events.emit("response", this); - if (this._route._extensions.onPostResponse.nodes) { - this._invoke(this._route._extensions.onPostResponse, { ignoreResponse: true }); } - } - _setResponse(response) { - if (this.response && !this.response.isBoom && this.response !== response && this.response.source !== response.source) { - this.response._close?.(); - } - if (this.info.completed) { - response._close?.(); - return; - } - this.response = response; - } - _setState(name, value, options2) { - const state = { name, value }; - if (options2) { - Hoek.assert(!options2.autoValue, "Cannot set autoValue directly in a response"); - state.options = Hoek.clone(options2); - } - this._states[name] = state; - } - _clearState(name, options2 = {}) { - const state = { name }; - state.options = Hoek.clone(options2); - state.options.ttl = 0; - this._states[name] = state; - } - _tap() { - if (!this._events) { - return null; - } - if (this._events.hasListeners("peek") || this._events.hasListeners("finish")) { - return new this._core.Response.Peek(this._events); + if (connected) { + throw new Error("No Replicas Nodes Enumerated"); } - return null; - } - log(tags, data) { - return this._log(tags, data, "app"); + throw new Error("couldn't connect to any sentinels"); } - _log(tags, data, channel = "internal") { - if (!this._core.events.hasListeners("request") && !this.route.settings.log.collect) { - return; + async getReplicaClient() { + const replicas = await this.getReplicaNodes(); + if (replicas.length == 0) { + throw new Error("no available replicas"); } - if (!Array.isArray(tags)) { - tags = [tags]; + this.#replicaIdx++; + if (this.#replicaIdx >= replicas.length) { + this.#replicaIdx = 0; } - const timestamp = Date.now(); - const field = data instanceof Error ? "error" : "data"; - let event = [this, { request: this.info.id, timestamp, tags, [field]: data, channel }]; - if (typeof data === "function") { - event = () => [this, { request: this.info.id, timestamp, tags, data: data(), channel }]; - } - if (this.route.settings.log.collect) { - if (typeof data === "function") { - event = event(); - } - this.logs.push(event[1]); - } - this._core.events.emit({ name: "request", channel, tags }, event); - } - generateResponse(source, options2) { - return new this._core.Response(source, this, options2); - } - }; - internals.Request.reserved = internals.reserved; - internals.Request.symbols = { - authPayload: Symbol("auth.payload") - }; - internals.Info = class { - constructor(request) { - this._request = request; - const req = request.raw.req; - const host = req.headers.host ? req.headers.host.trim() : ""; - const received = Date.now(); - this.received = received; - this.referrer = req.headers.referrer || req.headers.referer || ""; - this.host = host; - this.hostname = host.split(":")[0]; - this.id = `${received}:${request._core.info.id}:${request._core._counter()}`; - this._remoteAddress = null; - this._remotePort = null; - this.acceptEncoding = null; - this.cors = null; - this.responded = 0; - this.completed = 0; - if (request._core.settings.info.remote) { - this.remoteAddress; - this.remotePort; - } - } - get remoteAddress() { - if (!this._remoteAddress) { - const ipv6Prefix = "::ffff:"; - const socketAddress = this._request.raw.req.socket.remoteAddress; - if (socketAddress && socketAddress.startsWith(ipv6Prefix) && socketAddress.includes(".", ipv6Prefix.length)) { - this._remoteAddress = socketAddress.slice(ipv6Prefix.length); - } else { - this._remoteAddress = socketAddress; + return client_1.default.create({ + ...this.options.nodeClientOptions, + socket: { + ...this.options.nodeClientOptions?.socket, + host: replicas[this.#replicaIdx].host, + port: replicas[this.#replicaIdx].port } - } - return this._remoteAddress; - } - get remotePort() { - if (this._remotePort === null) { - this._remotePort = this._request.raw.req.socket.remotePort || ""; - } - return this._remotePort; - } - toJSON() { - return { - acceptEncoding: this.acceptEncoding, - completed: this.completed, - cors: this.cors, - host: this.host, - hostname: this.hostname, - id: this.id, - received: this.received, - referrer: this.referrer, - remoteAddress: this.remoteAddress, - remotePort: this.remotePort, - responded: this.responded - }; + }); } }; - internals.closed = function(request) { - request._closed = true; - }; - internals.event = function({ request }, event, err) { - if (!request) { - return; - } - request._isPayloadPending = false; - if (event === "close" && request.raw.res.writableEnded) { - return; - } - if (event === "end") { - return; - } - request._log(err ? ["request", "error"] : ["request", "error", event], err); - if (event === "error") { - return; - } - request._eventContext.request = null; - if (event === "abort") { - request._reply(new Boom5.Boom("Request aborted", { statusCode: request.route.settings.response.disconnectStatusCode, data: request.response })); - if (request._events) { - request._events.emit("disconnect"); - } + exports2.RedisSentinelFactory = RedisSentinelFactory; + } +}); +var require_dist = __commonJS({ + "node_modules/.deno/@redis+client@5.9.0/node_modules/@redis/client/dist/index.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { + for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - internals.timeoutReply = function(request, timeout) { - const elapsed = Date.now() - request.info.received; - request._log(["request", "server", "timeout", "error"], { timeout, elapsed }); - request._reply(Boom5.serverUnavailable()); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.BasicPooledClientSideCache = exports2.BasicClientSideCache = exports2.REDIS_FLUSH_MODES = exports2.COMMAND_LIST_FILTER_BY = exports2.CLUSTER_SLOT_STATES = exports2.FAILOVER_MODES = exports2.CLIENT_KILL_FILTERS = exports2.GEO_REPLY_WITH = exports2.createSentinel = exports2.createCluster = exports2.createClientPool = exports2.createClient = exports2.defineScript = exports2.VerbatimString = exports2.RESP_TYPES = void 0; + var decoder_1 = require_decoder(); + Object.defineProperty(exports2, "RESP_TYPES", { enumerable: true, get: function() { + return decoder_1.RESP_TYPES; + } }); + var verbatim_string_1 = require_verbatim_string(); + Object.defineProperty(exports2, "VerbatimString", { enumerable: true, get: function() { + return verbatim_string_1.VerbatimString; + } }); + var lua_script_1 = require_lua_script(); + Object.defineProperty(exports2, "defineScript", { enumerable: true, get: function() { + return lua_script_1.defineScript; + } }); + __exportStar(require_errors(), exports2); + var client_1 = __importDefault(require_client()); + exports2.createClient = client_1.default.create; + var pool_1 = require_pool(); + exports2.createClientPool = pool_1.RedisClientPool.create; + var cluster_1 = __importDefault(require_cluster()); + exports2.createCluster = cluster_1.default.create; + var sentinel_1 = __importDefault(require_sentinel()); + exports2.createSentinel = sentinel_1.default.create; + var GEOSEARCH_WITH_1 = require_GEOSEARCH_WITH(); + Object.defineProperty(exports2, "GEO_REPLY_WITH", { enumerable: true, get: function() { + return GEOSEARCH_WITH_1.GEO_REPLY_WITH; + } }); + var commands_1 = require_commands(); + Object.defineProperty(exports2, "CLIENT_KILL_FILTERS", { enumerable: true, get: function() { + return commands_1.CLIENT_KILL_FILTERS; + } }); + Object.defineProperty(exports2, "FAILOVER_MODES", { enumerable: true, get: function() { + return commands_1.FAILOVER_MODES; + } }); + Object.defineProperty(exports2, "CLUSTER_SLOT_STATES", { enumerable: true, get: function() { + return commands_1.CLUSTER_SLOT_STATES; + } }); + Object.defineProperty(exports2, "COMMAND_LIST_FILTER_BY", { enumerable: true, get: function() { + return commands_1.COMMAND_LIST_FILTER_BY; + } }); + Object.defineProperty(exports2, "REDIS_FLUSH_MODES", { enumerable: true, get: function() { + return commands_1.REDIS_FLUSH_MODES; + } }); + var cache_1 = require_cache(); + Object.defineProperty(exports2, "BasicClientSideCache", { enumerable: true, get: function() { + return cache_1.BasicClientSideCache; + } }); + Object.defineProperty(exports2, "BasicPooledClientSideCache", { enumerable: true, get: function() { + return cache_1.BasicPooledClientSideCache; + } }); + } +}); +var require_ADD = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/ADD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds an item to a Bloom Filter + * @param parser - The command parser + * @param key - The name of the Bloom filter + * @param item - The item to add to the filter + */ + parseCommand(parser3, key, item) { + parser3.push("BF.ADD"); + parser3.pushKey(key); + parser3.push(item); + }, + transformReply: generic_transformers_1.transformBooleanReply }; - internals.skip = function(response) { - return response.isBoom || response._takeover || typeof response === "symbol"; + } +}); +var require_CARD = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/CARD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the cardinality (number of items) in a Bloom Filter + * @param parser - The command parser + * @param key - The name of the Bloom filter to query + */ + parseCommand(parser3, key) { + parser3.push("BF.CARD"); + parser3.pushKey(key); + }, + transformReply: void 0 }; } }); -var require_auth = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/auth.js"(exports2, module14) { +var require_EXISTS2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/EXISTS.js"(exports2) { "use strict"; - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var Config = require_config(); - var Request2 = require_request2(); - var internals = { - missing: Symbol("missing") + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Checks if an item exists in a Bloom Filter + * @param parser - The command parser + * @param key - The name of the Bloom filter + * @param item - The item to check for existence + */ + parseCommand(parser3, key, item) { + parser3.push("BF.EXISTS"); + parser3.pushKey(key); + parser3.push(item); + }, + transformReply: generic_transformers_1.transformBooleanReply }; - exports2 = module14.exports = internals.Auth = class { - #core = null; - #schemes = {}; - #strategies = {}; - api = {}; - // Do not reassign api or settings, as they are referenced in public() - settings = { - default: null - // Strategy used as default if route has no auth settings - }; - constructor(core) { - this.#core = core; - } - public(server) { - return { - api: this.api, - settings: this.settings, - scheme: this.scheme.bind(this), - strategy: this._strategy.bind(this, server), - default: this.default.bind(this), - test: this.test.bind(this), - verify: this.verify.bind(this), - lookup: this.lookup.bind(this) - }; - } - scheme(name, scheme) { - Hoek.assert(name, "Authentication scheme must have a name"); - Hoek.assert(!this.#schemes[name], "Authentication scheme name already exists:", name); - Hoek.assert(typeof scheme === "function", "scheme must be a function:", name); - this.#schemes[name] = scheme; - } - _strategy(server, name, scheme, options2 = {}) { - Hoek.assert(name, "Authentication strategy must have a name"); - Hoek.assert(typeof options2 === "object", "options must be an object"); - Hoek.assert(!this.#strategies[name], "Authentication strategy name already exists"); - Hoek.assert(scheme, "Authentication strategy", name, "missing scheme"); - Hoek.assert(this.#schemes[scheme], "Authentication strategy", name, "uses unknown scheme:", scheme); - server = server._clone(); - const strategy = this.#schemes[scheme](server, options2); - Hoek.assert(strategy.authenticate, "Invalid scheme:", name, "missing authenticate() method"); - Hoek.assert(typeof strategy.authenticate === "function", "Invalid scheme:", name, "invalid authenticate() method"); - Hoek.assert(!strategy.payload || typeof strategy.payload === "function", "Invalid scheme:", name, "invalid payload() method"); - Hoek.assert(!strategy.response || typeof strategy.response === "function", "Invalid scheme:", name, "invalid response() method"); - strategy.options = strategy.options ?? {}; - Hoek.assert(strategy.payload || !strategy.options.payload, "Cannot require payload validation without a payload method"); - this.#strategies[name] = { - methods: strategy, - realm: server.realm - }; - if (strategy.api) { - this.api[name] = strategy.api; - } - } - default(options2) { - Hoek.assert(!this.settings.default, "Cannot set default strategy more than once"); - options2 = Config.apply("auth", options2, "default strategy"); - this.settings.default = this._setupRoute(Hoek.clone(options2)); - const routes = this.#core.router.table(); - for (const route2 of routes) { - route2.rebuild(); - } - } - async test(name, request) { - Hoek.assert(name, "Missing authentication strategy name"); - const strategy = this.#strategies[name]; - Hoek.assert(strategy, "Unknown authentication strategy:", name); - const bind = strategy.methods; - const realm = strategy.realm; - const response = await request._core.toolkit.execute(strategy.methods.authenticate, request, { bind, realm, auth: true }); - if (!response.isAuth) { - throw response; - } - if (response.error) { - throw response.error; - } - return response.data; - } - async verify(request) { - const auth = request.auth; - if (auth.error) { - throw auth.error; - } - if (!auth.isAuthenticated) { - return; - } - const strategy = this.#strategies[auth.strategy]; - Hoek.assert(strategy, "Unknown authentication strategy:", auth.strategy); - if (!strategy.methods.verify) { - return; - } - const bind = strategy.methods; - await strategy.methods.verify.call(bind, auth); - } - static testAccess(request, route2) { - const auth = request._core.auth; - try { - return auth._access(request, route2); - } catch (err) { - Bounce.rethrow(err, "system"); - return false; - } - } - _setupRoute(options2, path8) { - if (!options2) { - return options2; - } - if (typeof options2 === "string") { - options2 = { strategies: [options2] }; - } else if (options2.strategy) { - options2.strategies = [options2.strategy]; - delete options2.strategy; - } - if (path8 && !options2.strategies) { - Hoek.assert(this.settings.default, "Route missing authentication strategy and no default defined:", path8); - options2 = Hoek.applyToDefaults(this.settings.default, options2); - } - path8 = path8 ?? "default strategy"; - Hoek.assert(options2.strategies?.length, "Missing authentication strategy:", path8); - options2.mode = options2.mode ?? "required"; - if (options2.entity !== void 0 || // Backwards compatibility with <= 11.x.x - options2.scope !== void 0) { - options2.access = [{ entity: options2.entity, scope: options2.scope }]; - delete options2.entity; - delete options2.scope; - } - if (options2.access) { - for (const access of options2.access) { - access.scope = internals.setupScope(access); - } - } - if (options2.payload === true) { - options2.payload = "required"; - } - let hasAuthenticatePayload = false; - for (const name of options2.strategies) { - const strategy = this.#strategies[name]; - Hoek.assert(strategy, "Unknown authentication strategy", name, "in", path8); - Hoek.assert(strategy.methods.payload || options2.payload !== "required", "Payload validation can only be required when all strategies support it in", path8); - hasAuthenticatePayload = hasAuthenticatePayload || strategy.methods.payload; - Hoek.assert(!strategy.methods.options.payload || options2.payload === void 0 || options2.payload === "required", "Cannot set authentication payload to", options2.payload, "when a strategy requires payload validation in", path8); - } - Hoek.assert(!options2.payload || hasAuthenticatePayload, "Payload authentication requires at least one strategy with payload support in", path8); - return options2; - } - lookup(route2) { - if (route2.settings.auth === false) { - return false; - } - return route2.settings.auth || this.settings.default; - } - _enabled(route2, type) { - const config2 = this.lookup(route2); - if (!config2) { - return false; - } - if (type === "authenticate") { - return true; - } - if (type === "access") { - return !!config2.access; - } - for (const name of config2.strategies) { - const strategy = this.#strategies[name]; - if (strategy.methods[type]) { - return true; - } - } - return false; - } - static authenticate(request) { - const auth = request._core.auth; - return auth._authenticate(request); - } - async _authenticate(request) { - const config2 = this.lookup(request.route); - const errors = []; - request.auth.mode = config2.mode; - if (request.auth.credentials) { - internals.validate(null, { credentials: request.auth.credentials, artifacts: request.auth.artifacts }, request.auth.strategy, config2, request, errors); - return; - } - for (const name of config2.strategies) { - const strategy = this.#strategies[name]; - const bind = strategy.methods; - const realm = strategy.realm; - const response = await request._core.toolkit.execute(strategy.methods.authenticate, request, { bind, realm, auth: true }); - const message = response.isAuth ? internals.validate(response.error, response.data, name, config2, request, errors) : internals.validate(response, null, name, config2, request, errors); - if (!message) { - return; - } - if (message !== internals.missing) { - return message; - } - } - const err = Boom5.unauthorized("Missing authentication", errors); - if (config2.mode === "required") { - throw err; - } - request.auth.isAuthenticated = false; - request.auth.credentials = null; - request.auth.error = err; - request._log(["auth", "unauthenticated"]); - } - static access(request) { - const auth = request._core.auth; - request.auth.isAuthorized = auth._access(request); - } - _access(request, route2) { - const config2 = this.lookup(route2 || request.route); - if (!config2?.access) { - return true; + } +}); +var require_helpers = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/helpers.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transformInfoV2Reply = void 0; + var client_1 = require_dist(); + function transformInfoV2Reply(reply, typeMapping) { + const mapType = typeMapping ? typeMapping[client_1.RESP_TYPES.MAP] : void 0; + switch (mapType) { + case Array: { + return reply; } - const credentials = request.auth.credentials; - if (!credentials) { - if (config2.mode !== "required") { - return false; + case Map: { + const ret = /* @__PURE__ */ new Map(); + for (let i2 = 0; i2 < reply.length; i2 += 2) { + ret.set(reply[i2].toString(), reply[i2 + 1]); } - throw Boom5.forbidden("Request is unauthenticated"); + return ret; } - const requestEntity = credentials.user ? "user" : "app"; - const scopeErrors = []; - for (const access of config2.access) { - const entity = access.entity; - if (entity && entity !== "any" && entity !== requestEntity) { - continue; - } - let scope = access.scope; - if (scope) { - if (!credentials.scope) { - scopeErrors.push(scope); - continue; - } - scope = internals.expandScope(request, scope); - if (!internals.validateScope(credentials, scope, "required") || !internals.validateScope(credentials, scope, "selection") || !internals.validateScope(credentials, scope, "forbidden")) { - scopeErrors.push(scope); - continue; - } + default: { + const ret = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < reply.length; i2 += 2) { + ret[reply[i2].toString()] = reply[i2 + 1]; } - return true; - } - if (scopeErrors.length) { - request._log(["auth", "scope", "error"]); - throw Boom5.forbidden("Insufficient scope", { got: credentials.scope, need: scopeErrors }); - } - if (requestEntity === "app") { - request._log(["auth", "entity", "user", "error"]); - throw Boom5.forbidden("Application credentials cannot be used on a user endpoint"); - } - request._log(["auth", "entity", "app", "error"]); - throw Boom5.forbidden("User credentials cannot be used on an application endpoint"); - } - static async payload(request) { - if (!request.auth.isAuthenticated || !request.auth[Request2.symbols.authPayload]) { - return; - } - const auth = request._core.auth; - const strategy = auth.#strategies[request.auth.strategy]; - Hoek.assert(strategy, "Unknown authentication strategy:", request.auth.strategy); - if (!strategy.methods.payload) { - return; - } - const config2 = auth.lookup(request.route); - const setting = config2.payload ?? (strategy.methods.options.payload ? "required" : false); - if (!setting) { - return; - } - const bind = strategy.methods; - const realm = strategy.realm; - const response = await request._core.toolkit.execute(strategy.methods.payload, request, { bind, realm }); - if (response.isBoom && response.isMissing) { - return setting === "optional" ? void 0 : Boom5.unauthorized("Missing payload authentication"); - } - return response; - } - static async response(response) { - const request = response.request; - const auth = request._core.auth; - if (!request.auth.isAuthenticated) { - return; - } - const strategy = auth.#strategies[request.auth.strategy]; - Hoek.assert(strategy, "Unknown authentication strategy:", request.auth.strategy); - if (!strategy.methods.response) { - return; - } - const bind = strategy.methods; - const realm = strategy.realm; - const error2 = await request._core.toolkit.execute(strategy.methods.response, request, { bind, realm, continue: "undefined" }); - if (error2) { - throw error2; - } - } - }; - internals.setupScope = function(access) { - if (!access.scope) { - return false; - } - if (!Array.isArray(access.scope)) { - return access.scope; - } - const scope = {}; - for (const value of access.scope) { - const prefix = value[0]; - const type = prefix === "+" ? "required" : prefix === "!" ? "forbidden" : "selection"; - const clean = type === "selection" ? value : value.slice(1); - scope[type] = scope[type] ?? []; - scope[type].push(clean); - if (!scope._hasParameters?.[type] && /{([^}]+)}/.test(clean)) { - scope._hasParameters = scope._hasParameters ?? {}; - scope._hasParameters[type] = true; - } - } - return scope; - }; - internals.validate = function(err, result, name, config2, request, errors) { - result = result ?? {}; - request.auth.isAuthenticated = !err; - if (err) { - if (err instanceof Error === false) { - request._log(["auth", "unauthenticated", "response", name], { statusCode: err.statusCode }); - return err; - } - if (err.isMissing) { - request._log(["auth", "unauthenticated", "missing", name], err); - errors.push(err.output.headers["WWW-Authenticate"]); - return internals.missing; + return ret; } } - request.auth.strategy = name; - request.auth.credentials = result.credentials; - request.auth.artifacts = result.artifacts; - if (!err) { - return; - } - request.auth.error = err; - if (config2.mode === "try") { - request._log(["auth", "unauthenticated", "try", name], err); - return; - } - request._log(["auth", "unauthenticated", "error", name], err); - throw err; - }; - internals.expandScope = function(request, scope) { - if (!scope._hasParameters) { - return scope; - } - const expanded = { - required: internals.expandScopeType(request, scope, "required"), - selection: internals.expandScopeType(request, scope, "selection"), - forbidden: internals.expandScopeType(request, scope, "forbidden") - }; - return expanded; - }; - internals.expandScopeType = function(request, scope, type) { - if (!scope._hasParameters[type]) { - return scope[type]; - } - const expanded = []; - const context = { - params: request.params, - query: request.query, - payload: request.payload, - credentials: request.auth.credentials - }; - for (const template of scope[type]) { - expanded.push(Hoek.reachTemplate(context, template)); + } + exports2.transformInfoV2Reply = transformInfoV2Reply; + } +}); +var require_INFO2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var helpers_1 = require_helpers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns information about a Bloom Filter, including capacity, size, number of filters, items inserted, and expansion rate + * @param parser - The command parser + * @param key - The name of the Bloom filter to get information about + */ + parseCommand(parser3, key) { + parser3.push("BF.INFO"); + parser3.pushKey(key); + }, + transformReply: { + 2: (reply, _, typeMapping) => { + return (0, helpers_1.transformInfoV2Reply)(reply, typeMapping); + }, + 3: void 0 } - return expanded; }; - internals.validateScope = function(credentials, scope, type) { - if (!scope[type]) { - return true; - } - const count = typeof credentials.scope === "string" ? scope[type].indexOf(credentials.scope) !== -1 ? 1 : 0 : Hoek.intersect(scope[type], credentials.scope).length; - if (type === "forbidden") { - return count === 0; - } - if (type === "required") { - return count === scope.required.length; - } - return !!count; - }; - } -}); -var require_header = __commonJS({ - "node_modules/.deno/@hapi+accept@6.0.3/node_modules/@hapi/accept/lib/header.js"(exports2) { - "use strict"; - var Hoek = require_lib(); - var Boom5 = require_lib2(); - var internals = {}; - exports2.selection = function(header, preferences, options2) { - const selections = exports2.selections(header, preferences, options2); - return selections.length ? selections[0] : ""; - }; - exports2.selections = function(header, preferences, options2) { - Hoek.assert(!preferences || Array.isArray(preferences), "Preferences must be an array"); - return internals.parse(header || "", preferences, options2); - }; - internals.parse = function(raw, preferences, options2) { - const header = raw.replace(/[ \t]/g, ""); - const lowers = /* @__PURE__ */ new Map(); - if (preferences) { - let pos = 0; - for (const preference of preferences) { - const lower = preference.toLowerCase(); - lowers.set(lower, { orig: preference, pos: pos++ }); - if (options2.prefixMatch) { - const parts2 = lower.split("-"); - while (parts2.pop(), parts2.length > 0) { - const joined = parts2.join("-"); - if (!lowers.has(joined)) { - lowers.set(joined, { orig: preference, pos: pos++ }); - } - } - } - } - } - const parts = header.split(","); - const selections = []; - const map = /* @__PURE__ */ new Set(); - for (let i2 = 0; i2 < parts.length; ++i2) { - const part = parts[i2]; - if (!part) { - continue; - } - const params = part.split(";"); - if (params.length > 2) { - throw Boom5.badRequest(`Invalid ${options2.type} header`); + } +}); +var require_INSERT = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/INSERT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds one or more items to a Bloom Filter, creating it if it does not exist + * @param parser - The command parser + * @param key - The name of the Bloom filter + * @param items - One or more items to add to the filter + * @param options - Optional parameters for filter creation + * @param options.CAPACITY - Desired capacity for a new filter + * @param options.ERROR - Desired error rate for a new filter + * @param options.EXPANSION - Expansion rate for a new filter + * @param options.NOCREATE - If true, prevents automatic filter creation + * @param options.NONSCALING - Prevents the filter from creating additional sub-filters + */ + parseCommand(parser3, key, items, options2) { + parser3.push("BF.INSERT"); + parser3.pushKey(key); + if (options2?.CAPACITY !== void 0) { + parser3.push("CAPACITY", options2.CAPACITY.toString()); } - let token = params[0].toLowerCase(); - if (!token) { - throw Boom5.badRequest(`Invalid ${options2.type} header`); + if (options2?.ERROR !== void 0) { + parser3.push("ERROR", options2.ERROR.toString()); } - if (options2.equivalents?.has(token)) { - token = options2.equivalents.get(token); + if (options2?.EXPANSION !== void 0) { + parser3.push("EXPANSION", options2.EXPANSION.toString()); } - const selection = { - token, - pos: i2, - q: 1 - }; - if (preferences && lowers.has(token)) { - selection.pref = lowers.get(token).pos; - } - map.add(selection.token); - if (params.length === 2) { - const q = params[1]; - const [key, value] = q.split("="); - if (!value || key !== "q" && key !== "Q") { - throw Boom5.badRequest(`Invalid ${options2.type} header`); - } - const score = parseFloat(value); - if (score === 0) { - continue; - } - if (Number.isFinite(score) && score <= 1 && score >= 1e-3) { - selection.q = score; - } + if (options2?.NOCREATE) { + parser3.push("NOCREATE"); } - selections.push(selection); - } - selections.sort(internals.sort); - const values = selections.map((selection) => selection.token); - if (options2.default && !map.has(options2.default)) { - values.push(options2.default); - } - if (!preferences?.length) { - return values; - } - const preferred = []; - for (const selection of values) { - if (selection === "*") { - for (const [preference, value] of lowers) { - if (!map.has(preference)) { - preferred.push(value.orig); - } - } - } else { - const lower = selection.toLowerCase(); - if (lowers.has(lower)) { - preferred.push(lowers.get(lower).orig); - } + if (options2?.NONSCALING) { + parser3.push("NONSCALING"); } - } - return preferred; + parser3.push("ITEMS"); + parser3.pushVariadic(items); + }, + transformReply: generic_transformers_1.transformBooleanArrayReply }; - internals.sort = function(a, b) { - const aFirst = -1; - const bFirst = 1; - if (b.q !== a.q) { - return b.q - a.q; - } - if (b.pref !== a.pref) { - if (a.pref === void 0) { - return bFirst; - } - if (b.pref === void 0) { - return aFirst; - } - return a.pref - b.pref; - } - return a.pos - b.pos; + } +}); +var require_LOADCHUNK = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/LOADCHUNK.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Restores a Bloom Filter chunk previously saved using SCANDUMP + * @param parser - The command parser + * @param key - The name of the Bloom filter to restore + * @param iterator - Iterator value from the SCANDUMP command + * @param chunk - Data chunk from the SCANDUMP command + */ + parseCommand(parser3, key, iterator, chunk) { + parser3.push("BF.LOADCHUNK"); + parser3.pushKey(key); + parser3.push(iterator.toString(), chunk); + }, + transformReply: void 0 }; } }); -var require_media = __commonJS({ - "node_modules/.deno/@hapi+accept@6.0.3/node_modules/@hapi/accept/lib/media.js"(exports2) { +var require_MADD = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/MADD.js"(exports2) { "use strict"; - var Hoek = require_lib(); - var Boom5 = require_lib2(); - var internals = {}; - exports2.selection = function(header, preferences) { - const selections = exports2.selections(header, preferences); - return selections.length ? selections[0] : ""; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds multiple items to a Bloom Filter in a single call + * @param parser - The command parser + * @param key - The name of the Bloom filter + * @param items - One or more items to add to the filter + */ + parseCommand(parser3, key, items) { + parser3.push("BF.MADD"); + parser3.pushKey(key); + parser3.pushVariadic(items); + }, + transformReply: generic_transformers_1.transformBooleanArrayReply }; - exports2.selections = function(header, preferences) { - Hoek.assert(!preferences || Array.isArray(preferences), "Preferences must be an array"); - return internals.parse(header, preferences); + } +}); +var require_MEXISTS = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/MEXISTS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Checks if multiple items exist in a Bloom Filter in a single call + * @param parser - The command parser + * @param key - The name of the Bloom filter + * @param items - One or more items to check for existence + */ + parseCommand(parser3, key, items) { + parser3.push("BF.MEXISTS"); + parser3.pushKey(key); + parser3.pushVariadic(items); + }, + transformReply: generic_transformers_1.transformBooleanArrayReply }; - internals.validMediaRx = /^(?:\*\/\*)|(?:[\w\!#\$%&'\*\+\-\.\^`\|~]+\/\*)|(?:[\w\!#\$%&'\*\+\-\.\^`\|~]+\/[\w\!#\$%&'\*\+\-\.\^`\|~]+)$/; - internals.parse = function(raw, preferences) { - const { header, quoted } = internals.normalize(raw); - const parts = header.split(","); - const selections = []; - const map = {}; - for (let i2 = 0; i2 < parts.length; ++i2) { - const part = parts[i2]; - if (!part) { - continue; + } +}); +var require_RESERVE = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/RESERVE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Creates an empty Bloom Filter with a given desired error ratio and initial capacity + * @param parser - The command parser + * @param key - The name of the Bloom filter to create + * @param errorRate - The desired probability for false positives (between 0 and 1) + * @param capacity - The number of entries intended to be added to the filter + * @param options - Optional parameters to tune the filter + * @param options.EXPANSION - Expansion rate for the filter + * @param options.NONSCALING - Prevents the filter from creating additional sub-filters + */ + parseCommand(parser3, key, errorRate, capacity, options2) { + parser3.push("BF.RESERVE"); + parser3.pushKey(key); + parser3.push(errorRate.toString(), capacity.toString()); + if (options2?.EXPANSION) { + parser3.push("EXPANSION", options2.EXPANSION.toString()); } - const pairs = part.split(";"); - const token = pairs.shift().toLowerCase(); - if (!internals.validMediaRx.test(token)) { - continue; + if (options2?.NONSCALING) { + parser3.push("NONSCALING"); } - const selection = { - token, - params: {}, - exts: {}, - pos: i2 + }, + transformReply: void 0 + }; + } +}); +var require_SCANDUMP = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/SCANDUMP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Begins an incremental save of a Bloom Filter. This is useful for large filters that can't be saved at once + * @param parser - The command parser + * @param key - The name of the Bloom filter to save + * @param iterator - Iterator value; Start at 0, and use the iterator from the response for the next chunk + */ + parseCommand(parser3, key, iterator) { + parser3.push("BF.SCANDUMP"); + parser3.pushKey(key); + parser3.push(iterator.toString()); + }, + transformReply(reply) { + return { + iterator: reply[0], + chunk: reply[1] }; - let target = "params"; - for (const pair of pairs) { - const kv = pair.split("="); - if (kv.length !== 2 || !kv[1]) { - throw Boom5.badRequest(`Invalid accept header`); - } - const key = kv[0]; - let value = kv[1]; - if (key === "q" || key === "Q") { - target = "exts"; - value = parseFloat(value); - if (!Number.isFinite(value) || value > 1 || value < 1e-3 && value !== 0) { - value = 1; - } - selection.q = value; - } else { - if (value[0] === '"') { - value = `"${quoted[value]}"`; - } - selection[target][kv[0]] = value; - } - } - const params = Object.keys(selection.params); - selection.original = [""].concat(params.map((key) => `${key}=${selection.params[key]}`)).join(";"); - selection.specificity = params.length; - if (selection.q === void 0) { - selection.q = 1; - } - const tparts = selection.token.split("/"); - selection.type = tparts[0]; - selection.subtype = tparts[1]; - map[selection.token] = selection; - if (selection.q) { - selections.push(selection); - } } - selections.sort(internals.sort); - return internals.preferences(map, selections, preferences); }; - internals.normalize = function(raw) { - raw = raw || "*/*"; - const normalized = { - header: raw, - quoted: {} - }; - if (raw.includes('"')) { - let i2 = 0; - normalized.header = raw.replace(/="([^"]*)"/g, ($0, $1) => { - const key = '"' + ++i2; - normalized.quoted[key] = $1; - return "=" + key; - }); + } +}); +var require_bloom = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/bloom/index.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - normalized.header = normalized.header.replace(/[ \t]/g, ""); - return normalized; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { + for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); }; - internals.sort = function(a, b) { - if (b.q !== a.q) { - return b.q - a.q; - } - if (a.type !== b.type) { - return internals.innerSort(a, b, "type"); - } - if (a.subtype !== b.subtype) { - return internals.innerSort(a, b, "subtype"); - } - if (a.specificity !== b.specificity) { - return b.specificity - a.specificity; - } - return a.pos - b.pos; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - internals.innerSort = function(a, b, key) { - const aFirst = -1; - const bFirst = 1; - if (a[key] === "*") { - return bFirst; - } - if (b[key] === "*") { - return aFirst; - } - return a[key] < b[key] ? aFirst : bFirst; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ADD_1 = __importDefault(require_ADD()); + var CARD_1 = __importDefault(require_CARD()); + var EXISTS_1 = __importDefault(require_EXISTS2()); + var INFO_1 = __importDefault(require_INFO2()); + var INSERT_1 = __importDefault(require_INSERT()); + var LOADCHUNK_1 = __importDefault(require_LOADCHUNK()); + var MADD_1 = __importDefault(require_MADD()); + var MEXISTS_1 = __importDefault(require_MEXISTS()); + var RESERVE_1 = __importDefault(require_RESERVE()); + var SCANDUMP_1 = __importDefault(require_SCANDUMP()); + __exportStar(require_helpers(), exports2); + exports2.default = { + ADD: ADD_1.default, + add: ADD_1.default, + CARD: CARD_1.default, + card: CARD_1.default, + EXISTS: EXISTS_1.default, + exists: EXISTS_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + INSERT: INSERT_1.default, + insert: INSERT_1.default, + LOADCHUNK: LOADCHUNK_1.default, + loadChunk: LOADCHUNK_1.default, + MADD: MADD_1.default, + mAdd: MADD_1.default, + MEXISTS: MEXISTS_1.default, + mExists: MEXISTS_1.default, + RESERVE: RESERVE_1.default, + reserve: RESERVE_1.default, + SCANDUMP: SCANDUMP_1.default, + scanDump: SCANDUMP_1.default }; - internals.preferences = function(map, selections, preferences) { - if (!preferences?.length) { - return selections.map((selection) => selection.token + selection.original); - } - const lowers = /* @__PURE__ */ Object.create(null); - const flat = /* @__PURE__ */ Object.create(null); - let any = false; - for (const preference of preferences) { - const lower = preference.toLowerCase(); - flat[lower] = preference; - const parts = lower.split("/"); - const type = parts[0]; - const subtype = parts[1]; - if (type === "*") { - Hoek.assert(subtype === "*", "Invalid media type preference contains wildcard type with a subtype"); - any = true; - continue; - } - lowers[type] = lowers[type] ?? /* @__PURE__ */ Object.create(null); - lowers[type][subtype] = preference; - } - const preferred = []; - for (const selection of selections) { - const token = selection.token; - const { type, subtype } = map[token]; - const subtypes = lowers[type]; - if (type === "*") { - for (const preference of Object.keys(flat)) { - if (!map[preference]) { - preferred.push(flat[preference]); - } - } - if (any) { - preferred.push("*/*"); - } - continue; - } - if (any) { - preferred.push((flat[token] || token) + selection.original); - continue; - } - if (subtype !== "*") { - const pref = flat[token]; - if (pref || subtypes && subtypes["*"]) { - preferred.push((pref || token) + selection.original); - } - continue; - } - if (subtypes) { - for (const psub of Object.keys(subtypes)) { - if (!map[`${type}/${psub}`]) { - preferred.push(subtypes[psub]); - } + } +}); +var require_INCRBY2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INCRBY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Increases the count of one or more items in a Count-Min Sketch + * @param parser - The command parser + * @param key - The name of the sketch + * @param items - A single item or array of items to increment, each with an item and increment value + */ + parseCommand(parser3, key, items) { + parser3.push("CMS.INCRBY"); + parser3.pushKey(key); + if (Array.isArray(items)) { + for (const item of items) { + pushIncrByItem(parser3, item); } + } else { + pushIncrByItem(parser3, items); } + }, + transformReply: void 0 + }; + function pushIncrByItem(parser3, { item, incrementBy }) { + parser3.push(item, incrementBy.toString()); + } + } +}); +var require_INFO3 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var bloom_1 = require_bloom(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns width, depth, and total count of items in a Count-Min Sketch + * @param parser - The command parser + * @param key - The name of the sketch to get information about + */ + parseCommand(parser3, key) { + parser3.push("CMS.INFO"); + parser3.pushKey(key); + }, + transformReply: { + 2: (reply, _, typeMapping) => { + return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); + }, + 3: void 0 } - return preferred; }; } }); -var require_lib33 = __commonJS({ - "node_modules/.deno/@hapi+accept@6.0.3/node_modules/@hapi/accept/lib/index.js"(exports2) { +var require_INITBYDIM = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INITBYDIM.js"(exports2) { "use strict"; - var Header = require_header(); - var Media = require_media(); - var internals = { - options: { - charset: { - type: "accept-charset" - }, - encoding: { - type: "accept-encoding", - default: "identity", - equivalents: /* @__PURE__ */ new Map([ - ["x-compress", "compress"], - ["x-gzip", "gzip"] - ]) - }, - language: { - type: "accept-language", - prefixMatch: true - } - } - }; - for (const type in internals.options) { - exports2[type] = (header, preferences) => Header.selection(header, preferences, internals.options[type]); - exports2[`${type}s`] = (header, preferences) => Header.selections(header, preferences, internals.options[type]); - } - exports2.mediaType = (header, preferences) => Media.selection(header, preferences); - exports2.mediaTypes = (header, preferences) => Media.selections(header, preferences); - exports2.parseAll = function(requestHeaders) { - return { - charsets: exports2.charsets(requestHeaders["accept-charset"]), - encodings: exports2.encodings(requestHeaders["accept-encoding"]), - languages: exports2.languages(requestHeaders["accept-language"]), - mediaTypes: exports2.mediaTypes(requestHeaders.accept) - }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Initialize a Count-Min Sketch using width and depth parameters + * @param parser - The command parser + * @param key - The name of the sketch + * @param width - Number of counters in each array (must be a multiple of 2) + * @param depth - Number of counter arrays (determines accuracy of estimates) + */ + parseCommand(parser3, key, width, depth) { + parser3.push("CMS.INITBYDIM"); + parser3.pushKey(key); + parser3.push(width.toString(), depth.toString()); + }, + transformReply: void 0 }; } }); -var require_compression = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/compression.js"(exports2, module14) { +var require_INITBYPROB = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/INITBYPROB.js"(exports2) { "use strict"; - var Zlib = __require2("zlib"); - var Accept = require_lib33(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var internals = { - common: ["gzip, deflate", "deflate, gzip", "gzip", "deflate", "gzip, deflate, br"] - }; - exports2 = module14.exports = internals.Compression = class { - decoders = { - gzip: (options2) => Zlib.createGunzip(options2), - deflate: (options2) => Zlib.createInflate(options2) - }; - encodings = ["identity", "gzip", "deflate"]; - encoders = { - identity: null, - gzip: (options2) => Zlib.createGzip(options2), - deflate: (options2) => Zlib.createDeflate(options2) - }; - #common = null; - constructor() { - this._updateCommons(); - } - _updateCommons() { - this.#common = /* @__PURE__ */ new Map(); - for (const header of internals.common) { - this.#common.set(header, Accept.encoding(header, this.encodings)); - } - } - addEncoder(encoding, encoder3) { - Hoek.assert(this.encoders[encoding] === void 0, `Cannot override existing encoder for ${encoding}`); - Hoek.assert(typeof encoder3 === "function", `Invalid encoder function for ${encoding}`); - this.encoders[encoding] = encoder3; - this.encodings.unshift(encoding); - this._updateCommons(); - } - addDecoder(encoding, decoder) { - Hoek.assert(this.decoders[encoding] === void 0, `Cannot override existing decoder for ${encoding}`); - Hoek.assert(typeof decoder === "function", `Invalid decoder function for ${encoding}`); - this.decoders[encoding] = decoder; - } - accept(request) { - const header = request.headers["accept-encoding"]; - if (!header) { - return "identity"; - } - const common4 = this.#common.get(header); - if (common4) { - return common4; - } - try { - return Accept.encoding(header, this.encodings); - } catch (err) { - Bounce.rethrow(err, "system"); - err.header = header; - request._log(["accept-encoding", "error"], err); - return "identity"; - } - } - encoding(response, length2) { - if (response.settings.compressed) { - response.headers["content-encoding"] = response.settings.compressed; - return null; - } - const request = response.request; - if (!request._core.settings.compression || length2 !== null && length2 < request._core.settings.compression.minBytes) { - return null; - } - const mime = request._core.mime.type(response.headers["content-type"] || "application/octet-stream"); - if (!mime.compressible) { - return null; - } - response.vary("accept-encoding"); - if (response.headers["content-encoding"]) { - return null; - } - return request.info.acceptEncoding === "identity" ? null : request.info.acceptEncoding; - } - encoder(request, encoding) { - const encoder3 = this.encoders[encoding]; - Hoek.assert(encoder3 !== void 0, `Unknown encoding ${encoding}`); - return encoder3(request.route.settings.compression[encoding]); - } + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Initialize a Count-Min Sketch using error rate and probability parameters + * @param parser - The command parser + * @param key - The name of the sketch + * @param error - Estimate error, as a decimal between 0 and 1 + * @param probability - The desired probability for inflated count, as a decimal between 0 and 1 + */ + parseCommand(parser3, key, error2, probability) { + parser3.push("CMS.INITBYPROB"); + parser3.pushKey(key); + parser3.push(error2.toString(), probability.toString()); + }, + transformReply: void 0 }; } }); -var require_methods = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/methods.js"(exports2, module14) { +var require_MERGE = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/MERGE.js"(exports2) { "use strict"; - var Boom5 = require_lib2(); - var Hoek = require_lib(); - var Config = require_config(); - var internals = { - methodNameRx: /^[_$a-zA-Z][$\w]*(?:\.[_$a-zA-Z][$\w]*)*$/ - }; - exports2 = module14.exports = internals.Methods = class { - methods = {}; - #core = null; - constructor(core) { - this.#core = core; - } - add(name, method, options2, realm) { - if (typeof name !== "object") { - return this._add(name, method, options2, realm); - } - const items = [].concat(name); - for (let item of items) { - item = Config.apply("methodObject", item); - this._add(item.name, item.method, item.options ?? {}, realm); - } - } - _add(name, method, options2, realm) { - Hoek.assert(typeof method === "function", "method must be a function"); - Hoek.assert(typeof name === "string", "name must be a string"); - Hoek.assert(name.match(internals.methodNameRx), "Invalid name:", name); - Hoek.assert(!Hoek.reach(this.methods, name, { functions: false }), "Server method function name already exists:", name); - options2 = Config.apply("method", options2, name); - const settings = Hoek.clone(options2, { shallow: ["bind"] }); - settings.generateKey = settings.generateKey ?? internals.generateKey; - const bind = settings.bind ?? realm.settings.bind ?? null; - const bound = !bind ? method : (...args) => method.apply(bind, args); - if (!settings.cache) { - return this._assign(name, bound); - } - Hoek.assert(!settings.cache.generateFunc, "Cannot set generateFunc with method caching:", name); - Hoek.assert(settings.cache.generateTimeout !== void 0, "Method caching requires a timeout value in generateTimeout:", name); - settings.cache.generateFunc = (id, flags) => bound(...id.args, flags); - const cache2 = this.#core._cachePolicy(settings.cache, "#" + name); - const func = function(...args) { - const key = settings.generateKey.apply(bind, args); - if (typeof key !== "string") { - return Promise.reject(Boom5.badImplementation("Invalid method key when invoking: " + name, { name, args })); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Merges multiple Count-Min Sketches into a single sketch, with optional weights + * @param parser - The command parser + * @param destination - The name of the destination sketch + * @param source - Array of sketch names or array of sketches with weights + */ + parseCommand(parser3, destination, source) { + parser3.push("CMS.MERGE"); + parser3.pushKey(destination); + parser3.push(source.length.toString()); + if (isPlainSketches(source)) { + parser3.pushVariadic(source); + } else { + for (let i2 = 0; i2 < source.length; i2++) { + parser3.push(source[i2].name); } - return cache2.get({ id: key, args }); - }; - func.cache = { - drop: function(...args) { - const key = settings.generateKey.apply(bind, args); - if (typeof key !== "string") { - return Promise.reject(Boom5.badImplementation("Invalid method key when invoking: " + name, { name, args })); - } - return cache2.drop(key); - }, - stats: cache2.stats - }; - this._assign(name, func, func); - } - _assign(name, method) { - const path8 = name.split("."); - let ref = this.methods; - for (let i2 = 0; i2 < path8.length; ++i2) { - if (!ref[path8[i2]]) { - ref[path8[i2]] = i2 + 1 === path8.length ? method : {}; + parser3.push("WEIGHTS"); + for (let i2 = 0; i2 < source.length; i2++) { + parser3.push(source[i2].weight.toString()); } - ref = ref[path8[i2]]; - } - } - }; - internals.supportedArgs = ["string", "number", "boolean"]; - internals.generateKey = function(...args) { - let key = ""; - for (let i2 = 0; i2 < args.length; ++i2) { - const arg = args[i2]; - if (!internals.supportedArgs.includes(typeof arg)) { - return null; } - key = key + (i2 ? ":" : "") + encodeURIComponent(arg.toString()); - } - return key; + }, + transformReply: void 0 }; + function isPlainSketches(src2) { + return typeof src2[0] === "string" || src2[0] instanceof Buffer; + } } }); -var require_response2 = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/response.js"(exports2, module14) { - "use strict"; - var Stream = __require2("stream"); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var Podium = require_lib15(); - var Streams = require_streams(); - var internals = { - events: Podium.validate(["finish", { name: "peek", spread: true }]), - hopByHop: { - connection: true, - "keep-alive": true, - "proxy-authenticate": true, - "proxy-authorization": true, - "te": true, - "trailer": true, - "transfer-encoding": true, - "upgrade": true - }, - reserved: [ - "app", - "headers", - "plugins", - "request", - "source", - "statusCode", - "variety", - "settings", - "events", - "code", - "message", - "header", - "vary", - "etag", - "type", - "contentType", - "bytes", - "location", - "created", - "compressed", - "replacer", - "space", - "suffix", - "escape", - "passThrough", - "redirect", - "temporary", - "permanent", - "rewritable", - "encoding", - "charset", - "ttl", - "state", - "unstate", - "takeover" - ] - }; - exports2 = module14.exports = internals.Response = class { - constructor(source, request, options2 = {}) { - this.app = {}; - this.headers = {}; - this.plugins = {}; - this.request = request; - this.source = null; - this.statusCode = null; - this.variety = null; - this.settings = { - charset: "utf-8", - // '-' required by IANA - compressed: null, - encoding: "utf8", - message: null, - passThrough: true, - stringify: null, - // JSON.stringify options - ttl: null, - varyEtag: false - }; - this._events = null; - this._payload = null; - this._error = options2.error ?? null; - this._contentType = null; - this._takeover = false; - this._statusCode = false; - this._state = this._error ? "prepare" : "init"; - this._processors = { - marshal: options2.marshal, - prepare: options2.prepare, - close: options2.close - }; - this._setSource(source, options2.variety); - } - static wrap(result, request) { - if (result instanceof request._core.Response || typeof result === "symbol") { - return result; - } - if (result instanceof Error) { - return Boom5.boomify(result); - } - return new request._core.Response(result, request); - } - _setSource(source, variety) { - this.variety = variety ?? "plain"; - if (source === null || source === void 0) { - source = null; - } else if (Buffer.isBuffer(source)) { - this.variety = "buffer"; - this._contentType = "application/octet-stream"; - } else if (Streams.isStream(source)) { - this.variety = "stream"; - this._contentType = "application/octet-stream"; - } - this.source = source; - if (this.variety === "plain" && this.source !== null) { - this._contentType = typeof this.source === "string" ? "text/html" : "application/json"; - } - } - get events() { - if (!this._events) { - this._events = new Podium.Podium(internals.events); - } - return this._events; - } - code(statusCode) { - Hoek.assert(Number.isSafeInteger(statusCode), "Status code must be an integer"); - this.statusCode = statusCode; - this._statusCode = true; - return this; - } - message(httpMessage) { - this.settings.message = httpMessage; - return this; - } - header(key, value, options2) { - key = key.toLowerCase(); - if (key === "vary") { - return this.vary(value); - } - return this._header(key, value, options2); - } - _header(key, value, options2 = {}) { - const append = options2.append ?? false; - const separator = options2.separator || ","; - const override = options2.override !== false; - const duplicate = options2.duplicate !== false; - if (!append && override || !this.headers[key]) { - this.headers[key] = value; - } else if (override) { - if (key === "set-cookie") { - this.headers[key] = [].concat(this.headers[key], value); - } else { - const existing = this.headers[key]; - if (!duplicate) { - const values = existing.split(separator); - for (const v2 of values) { - if (v2 === value) { - return this; - } - } - } - this.headers[key] = existing + separator + value; - } - } - return this; - } - vary(value) { - if (value === "*") { - this.headers.vary = "*"; - } else if (!this.headers.vary) { - this.headers.vary = value; - } else if (this.headers.vary !== "*") { - this._header("vary", value, { append: true, duplicate: false }); - } - return this; - } - etag(tag3, options2) { - const entity = this.request._core.Response.entity(tag3, options2); - this._header("etag", entity.etag); - this.settings.varyEtag = entity.vary; - return this; - } - static entity(tag3, options2 = {}) { - Hoek.assert(tag3 !== "*", "ETag cannot be *"); - return { - etag: (options2.weak ? "W/" : "") + '"' + tag3 + '"', - vary: options2.vary !== false && !options2.weak, - // vary defaults to true - modified: options2.modified - }; - } - static unmodified(request, entity) { - if (request.method !== "get" && request.method !== "head") { - return false; - } - if (entity.etag && request.headers["if-none-match"]) { - const ifNoneMatch = request.headers["if-none-match"].split(/\s*,\s*/); - for (const etag of ifNoneMatch) { - if (etag === entity.etag) { - return true; - } - if (!entity.vary) { - continue; - } - if (etag === `W/${entity.etag}`) { - return etag; - } - const etagBase = entity.etag.slice(0, -1); - const encoders = request._core.compression.encodings; - for (const encoder3 of encoders) { - if (etag === etagBase + `-${encoder3}"`) { - return true; - } - } - } - return false; - } - if (!entity.modified) { - return false; - } - const ifModifiedSinceHeader = request.headers["if-modified-since"]; - if (!ifModifiedSinceHeader) { - return false; - } - const ifModifiedSince = internals.parseDate(ifModifiedSinceHeader); - if (!ifModifiedSince) { - return false; - } - const lastModified = internals.parseDate(entity.modified); - if (!lastModified) { - return false; - } - return ifModifiedSince >= lastModified; - } - type(type) { - this._header("content-type", type); - return this; - } - get contentType() { - let type = this.headers["content-type"]; - if (type) { - type = type.trim(); - if (this.settings.charset && type.match(/^(?:text\/)|(?:application\/(?:json)|(?:javascript))/) && !type.match(/; *charset=/)) { - const semi = type[type.length - 1] === ";"; - return type + (semi ? " " : "; ") + "charset=" + this.settings.charset; - } - return type; - } - if (this._contentType) { - const charset = this.settings.charset && this._contentType !== "application/octet-stream" ? "; charset=" + this.settings.charset : ""; - return this._contentType + charset; - } - return null; - } - bytes(bytes) { - this._header("content-length", bytes); - return this; - } - location(uri) { - this._header("location", uri); - return this; - } - created(location) { - Hoek.assert(this.request.method === "post" || this.request.method === "put" || this.request.method === "patch", "Cannot return 201 status codes for " + this.request.method.toUpperCase()); - this.statusCode = 201; - this.location(location); - return this; - } - compressed(encoding) { - Hoek.assert(encoding && typeof encoding === "string", "Invalid content-encoding"); - this.settings.compressed = encoding; - return this; - } - replacer(method) { - this.settings.stringify = this.settings.stringify ?? {}; - this.settings.stringify.replacer = method; - return this; - } - spaces(count) { - this.settings.stringify = this.settings.stringify ?? {}; - this.settings.stringify.space = count; - return this; - } - suffix(suffix) { - this.settings.stringify = this.settings.stringify ?? {}; - this.settings.stringify.suffix = suffix; - return this; - } - escape(escape) { - this.settings.stringify = this.settings.stringify ?? {}; - this.settings.stringify.escape = escape; - return this; - } - passThrough(enabled2) { - this.settings.passThrough = enabled2 !== false; - return this; - } - redirect(location) { - this.statusCode = 302; - this.location(location); - return this; - } - temporary(isTemporary) { - Hoek.assert(this.headers.location, "Cannot set redirection mode without first setting a location"); - this._setTemporary(isTemporary !== false); - return this; - } - permanent(isPermanent) { - Hoek.assert(this.headers.location, "Cannot set redirection mode without first setting a location"); - this._setTemporary(isPermanent === false); - return this; - } - rewritable(isRewritable) { - Hoek.assert(this.headers.location, "Cannot set redirection mode without first setting a location"); - this._setRewritable(isRewritable !== false); - return this; - } - _isTemporary() { - return this.statusCode === 302 || this.statusCode === 307; - } - _isRewritable() { - return this.statusCode === 301 || this.statusCode === 302; - } - _setTemporary(isTemporary) { - if (isTemporary) { - if (this._isRewritable()) { - this.statusCode = 302; - } else { - this.statusCode = 307; - } - } else { - if (this._isRewritable()) { - this.statusCode = 301; - } else { - this.statusCode = 308; - } - } - } - _setRewritable(isRewritable) { - if (isRewritable) { - if (this._isTemporary()) { - this.statusCode = 302; - } else { - this.statusCode = 301; - } - } else { - if (this._isTemporary()) { - this.statusCode = 307; - } else { - this.statusCode = 308; - } - } - } - encoding(encoding) { - this.settings.encoding = encoding; - return this; - } - charset(charset) { - this.settings.charset = charset ?? null; - return this; - } - ttl(ttl) { - this.settings.ttl = ttl; - return this; - } - state(name, value, options2) { - this.request._setState(name, value, options2); - return this; - } - unstate(name, options2) { - this.request._clearState(name, options2); - return this; - } - takeover() { - this._takeover = true; - return this; - } - _prepare() { - Hoek.assert(this._state === "init"); - this._state = "prepare"; - this._passThrough(); - if (!this._processors.prepare) { - return this; - } - try { - return this._processors.prepare(this); - } catch (err) { - throw Boom5.boomify(err); - } - } - _passThrough() { - if (this.variety === "stream" && this.settings.passThrough) { - if (this.source.statusCode && !this.statusCode) { - this.statusCode = this.source.statusCode; - } - if (this.source.headers) { - let headerKeys = Object.keys(this.source.headers); - if (headerKeys.length) { - const localHeaders = this.headers; - this.headers = {}; - const connection = this.source.headers.connection; - const byHop = {}; - if (connection) { - connection.split(/\s*,\s*/).forEach((header) => { - byHop[header] = true; - }); - } - for (const key of headerKeys) { - const lower = key.toLowerCase(); - if (!internals.hopByHop[lower] && !byHop[lower]) { - this.header(lower, Hoek.clone(this.source.headers[key])); - } - } - headerKeys = Object.keys(localHeaders); - for (const key of headerKeys) { - this.header(key, localHeaders[key], { append: key === "set-cookie" }); - } - } - } - } - this.statusCode = this.statusCode ?? 200; - } - async _marshal() { - Hoek.assert(this._state === "prepare"); - this._state = "marshall"; - let source = this.source; - if (this._processors.marshal) { - try { - source = await this._processors.marshal(this); - } catch (err) { - throw Boom5.boomify(err); - } - } - if (Streams.isStream(source)) { - this._payload = source; - return; - } - const jsonify = this.variety === "plain" && source !== null && typeof source !== "string"; - if (!jsonify && this.settings.stringify) { - throw Boom5.badImplementation("Cannot set formatting options on non object response"); - } - let payload = source; - if (jsonify) { - const options2 = this.settings.stringify ?? {}; - const space = options2.space ?? this.request.route.settings.json.space; - const replacer = options2.replacer ?? this.request.route.settings.json.replacer; - const suffix = options2.suffix ?? this.request.route.settings.json.suffix ?? ""; - const escape = this.request.route.settings.json.escape; - try { - if (replacer || space) { - payload = JSON.stringify(payload, replacer, space); - } else { - payload = JSON.stringify(payload); - } - } catch (err) { - throw Boom5.boomify(err); - } - if (suffix) { - payload = payload + suffix; - } - if (escape) { - payload = Hoek.escapeJson(payload); - } - } - this._payload = new internals.Response.Payload(payload, this.settings); - } - _tap() { - if (!this._events) { - return null; - } - if (this._events.hasListeners("peek") || this._events.hasListeners("finish")) { - return new internals.Response.Peek(this._events); - } - return null; - } - _close() { - if (this._state === "close") { - return; - } - this._state = "close"; - if (this._processors.close) { - try { - this._processors.close(this); - } catch (err) { - Bounce.rethrow(err, "system"); - this.request._log(["response", "cleanup", "error"], err); - } - } - const stream = this._payload || this.source; - if (Streams.isStream(stream)) { - internals.Response.drain(stream); - } - } - _isPayloadSupported() { - return this.request.method !== "head" && this.statusCode !== 304 && this.statusCode !== 204; - } - static drain(stream) { - stream.destroy(); - } - }; - internals.Response.reserved = internals.reserved; - internals.parseDate = function(string3) { - try { - return Date.parse(string3); - } catch (errIgnore) { - } - }; - internals.Response.Payload = class extends Stream.Readable { - constructor(payload, options2) { - super(); - this._data = payload; - this._encoding = options2.encoding; - } - _read(size) { - if (this._data) { - this.push(this._data, this._encoding); - } - this.push(null); - } - size() { - if (!this._data) { - return 0; - } - return Buffer.isBuffer(this._data) ? this._data.length : Buffer.byteLength(this._data, this._encoding); - } - writeToStream(stream) { - if (this._data) { - stream.write(this._data, this._encoding); - } - stream.end(); - } - }; - internals.Response.Peek = class extends Stream.Transform { - constructor(podium) { - super(); - this._podium = podium; - this.on("finish", () => podium.emit("finish")); - } - _transform(chunk, encoding, callback) { - this._podium.emit("peek", [chunk, encoding]); - this.push(chunk, encoding); - callback(); - } - }; - } -}); -var require_core = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/core.js"(exports2, module14) { - "use strict"; - var Http = __require2("http"); - var Https = __require2("https"); - var Os = __require2("os"); - var Path = __require2("path"); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Call = require_lib14(); - var Catbox = require_lib16(); - var { Engine: CatboxMemory } = require_lib17(); - var { Heavy } = require_lib18(); - var Hoek = require_lib(); - var { Mimos } = require_lib19(); - var Podium = require_lib15(); - var Statehood = require_lib24(); - var Auth = require_auth(); - var Compression = require_compression(); - var Config = require_config(); - var Cors = require_cors(); - var Ext = require_ext(); - var Methods = require_methods(); - var Request2 = require_request2(); - var Response2 = require_response2(); - var Route = require_route2(); - var Toolkit = require_toolkit(); - var Validation = require_validation(); - var internals = { - counter: { - min: 1e4, - max: 99999 - }, - events: [ - { name: "cachePolicy", spread: true }, - { name: "log", channels: ["app", "internal"], tags: true }, - { name: "request", channels: ["app", "internal", "error"], tags: true, spread: true }, - "response", - "route", - "start", - "closing", - "stop" - ], - badRequestResponse: Buffer.from("HTTP/1.1 400 Bad Request\r\n\r\n", "ascii") - }; - exports2 = module14.exports = internals.Core = class { - actives = /* @__PURE__ */ new WeakMap(); - // Active requests being processed - app = {}; - auth = new Auth(this); - caches = /* @__PURE__ */ new Map(); - // Cache clients - compression = new Compression(); - controlled = null; - // Other servers linked to the phases of this server - dependencies = []; - // Plugin dependencies - events = new Podium.Podium(internals.events); - heavy = null; - info = null; - instances = /* @__PURE__ */ new Set(); - listener = null; - methods = new Methods(this); - // Server methods - mime = null; - onConnection = null; - // Used to remove event listener on stop - phase = "stopped"; - // 'stopped', 'initializing', 'initialized', 'starting', 'started', 'stopping', 'invalid' - plugins = {}; - // Exposed plugin properties by name - registrations = {}; - // Tracks plugin for dependency validation { name -> { version } } - registring = 0; - // > 0 while register() is waiting for plugin callbacks - Request = class extends Request2 { - }; - Response = class extends Response2 { - }; - requestCounter = { value: internals.counter.min, min: internals.counter.min, max: internals.counter.max }; - root = null; - router = null; - settings = null; - sockets = null; - // Track open sockets for graceful shutdown - started = false; - states = null; - toolkit = new Toolkit.Manager(); - type = null; - validator = null; - extensionsSeq = 0; - // Used to keep absolute order of extensions based on the order added across locations - extensions = { - server: { - onPreStart: new Ext("onPreStart", this), - onPostStart: new Ext("onPostStart", this), - onPreStop: new Ext("onPreStop", this), - onPostStop: new Ext("onPostStop", this) - }, - route: { - onRequest: new Ext("onRequest", this), - onPreAuth: new Ext("onPreAuth", this), - onCredentials: new Ext("onCredentials", this), - onPostAuth: new Ext("onPostAuth", this), - onPreHandler: new Ext("onPreHandler", this), - onPostHandler: new Ext("onPostHandler", this), - onPreResponse: new Ext("onPreResponse", this), - onPostResponse: new Ext("onPostResponse", this) - } - }; - decorations = { - handler: /* @__PURE__ */ new Map(), - request: /* @__PURE__ */ new Map(), - response: /* @__PURE__ */ new Map(), - server: /* @__PURE__ */ new Map(), - toolkit: /* @__PURE__ */ new Map(), - requestApply: null, - public: { handler: [], request: [], response: [], server: [], toolkit: [] } - }; - constructor(options2) { - const { settings, type } = internals.setup(options2); - this.settings = settings; - this.type = type; - this.heavy = new Heavy(this.settings.load); - this.mime = new Mimos(this.settings.mime); - this.router = new Call.Router(this.settings.router); - this.states = new Statehood.Definitions(this.settings.state); - this._debug(); - this._initializeCache(); - if (this.settings.routes.validate.validator) { - this.validator = Validation.validator(this.settings.routes.validate.validator); - } - this.listener = this._createListener(); - this._initializeListener(); - this.info = this._info(); - } - _debug() { - const debug = this.settings.debug; - if (!debug) { - return; - } - const method = (event) => { - const data = event.error ?? event.data; - console.error("Debug:", event.tags.join(", "), data ? "\n " + (data.stack ?? (typeof data === "object" ? Hoek.stringify(data) : data)) : ""); - }; - if (debug.log) { - const filter = debug.log.some((tag3) => tag3 === "*") ? void 0 : debug.log; - this.events.on({ name: "log", filter }, method); - } - if (debug.request) { - const filter = debug.request.some((tag3) => tag3 === "*") ? void 0 : debug.request; - this.events.on({ name: "request", filter }, (request, event) => method(event)); - } - } - _initializeCache() { - if (this.settings.cache) { - this._createCache(this.settings.cache); - } - if (!this.caches.has("_default")) { - this._createCache([{ provider: CatboxMemory }]); - } - } - _info() { - const now = Date.now(); - const protocol = this.type === "tcp" ? this.settings.tls ? "https" : "http" : this.type; - const host = this.settings.host || Os.hostname() || "localhost"; - const port = this.settings.port; - const info = { - created: now, - started: 0, - host, - port, - protocol, - id: Os.hostname() + ":" + process.pid + ":" + now.toString(36), - uri: this.settings.uri ?? protocol + ":" + (this.type === "tcp" ? "//" + host + (port ? ":" + port : "") : port) - }; - return info; - } - _counter() { - const next = ++this.requestCounter.value; - if (this.requestCounter.value > this.requestCounter.max) { - this.requestCounter.value = this.requestCounter.min; - } - return next - 1; - } - _createCache(configs) { - Hoek.assert(this.phase !== "initializing", "Cannot provision server cache while server is initializing"); - configs = Config.apply("cache", configs); - const added = []; - for (let config2 of configs) { - if (typeof config2 === "function") { - config2 = { provider: { constructor: config2 } }; - } - const name = config2.name ?? "_default"; - Hoek.assert(!this.caches.has(name), "Cannot configure the same cache more than once: ", name === "_default" ? "default cache" : name); - let client = null; - if (config2.provider) { - let provider = config2.provider; - if (typeof provider === "function") { - provider = { constructor: provider }; - } - client = new Catbox.Client(provider.constructor, provider.options ?? { partition: "hapi-cache" }); - } else { - client = new Catbox.Client(config2.engine); - } - this.caches.set(name, { client, segments: {}, shared: config2.shared ?? false }); - added.push(client); - } - return added; - } - registerServer(server) { - if (!this.root) { - this.root = server; - this._defaultRoutes(); - } - this.instances.add(server); - } - async _start() { - if (this.phase === "initialized" || this.phase === "started") { - this._validateDeps(); - } - if (this.phase === "started") { - return; - } - if (this.phase !== "stopped" && this.phase !== "initialized") { - throw new Error("Cannot start server while it is in " + this.phase + " phase"); - } - if (this.phase !== "initialized") { - await this._initialize(); - } - this.phase = "starting"; - this.started = true; - this.info.started = Date.now(); - try { - await this._listen(); - } catch (err) { - this.started = false; - this.phase = "invalid"; - throw err; - } - this.phase = "started"; - this.events.emit("start"); - try { - if (this.controlled) { - await Promise.all(this.controlled.map((control) => control.start())); - } - await this._invoke("onPostStart"); - } catch (err) { - this.phase = "invalid"; - throw err; - } - } - _listen() { - return new Promise((resolve82, reject) => { - if (!this.settings.autoListen) { - resolve82(); - return; - } - const onError = (err) => { - reject(err); - return; - }; - this.listener.once("error", onError); - const finalize = () => { - this.listener.removeListener("error", onError); - resolve82(); - return; - }; - if (this.type !== "tcp") { - this.listener.listen(this.settings.port, finalize); - } else { - const address = this.settings.address || this.settings.host || null; - this.listener.listen(this.settings.port, address, finalize); - } - }); - } - async _initialize() { - if (this.registring) { - throw new Error("Cannot start server before plugins finished registration"); - } - if (this.phase === "initialized") { - return; - } - if (this.phase !== "stopped") { - throw new Error("Cannot initialize server while it is in " + this.phase + " phase"); - } - this._validateDeps(); - this.phase = "initializing"; - try { - const caches = []; - this.caches.forEach((cache2) => caches.push(cache2.client.start())); - await Promise.all(caches); - await this._invoke("onPreStart"); - this.heavy.start(); - this.phase = "initialized"; - if (this.controlled) { - await Promise.all(this.controlled.map((control) => control.initialize())); - } - } catch (err) { - this.phase = "invalid"; - throw err; - } - } - _validateDeps() { - for (const { deps, plugin: plugin2 } of this.dependencies) { - for (const dep in deps) { - const version3 = deps[dep]; - Hoek.assert(this.registrations[dep], "Plugin", plugin2, "missing dependency", dep); - Hoek.assert(version3 === "*" || Config.versionMatch(this.registrations[dep].version, version3), "Plugin", plugin2, "requires", dep, "version", version3, "but found", this.registrations[dep].version); - } - } - } - async _stop(options2 = {}) { - options2.timeout = options2.timeout ?? 5e3; - if (["stopped", "initialized", "started", "invalid"].indexOf(this.phase) === -1) { - throw new Error("Cannot stop server while in " + this.phase + " phase"); - } - this.phase = "stopping"; - try { - await this._invoke("onPreStop"); - if (this.started) { - this.started = false; - this.info.started = 0; - await this._unlisten(options2.timeout); - } - const caches = []; - this.caches.forEach((cache2) => caches.push(cache2.client.stop())); - await Promise.all(caches); - this.events.emit("stop"); - this.heavy.stop(); - if (this.controlled) { - await Promise.all(this.controlled.map((control) => control.stop(options2))); - } - await this._invoke("onPostStop"); - this.phase = "stopped"; - } catch (err) { - this.phase = "invalid"; - throw err; - } - } - _unlisten(timeout) { - let timeoutId = null; - if (this.settings.operations.cleanStop) { - const destroy = () => { - for (const connection of this.sockets) { - connection.destroy(); - } - this.sockets.clear(); - }; - timeoutId = setTimeout(destroy, timeout); - for (const connection of this.sockets) { - if (!this.actives.has(connection)) { - connection.end(); - } - } - } - return new Promise((resolve82) => { - this.listener.close(() => { - if (this.settings.operations.cleanStop) { - this.listener.removeListener(this.settings.tls ? "secureConnection" : "connection", this.onConnection); - clearTimeout(timeoutId); - } - this._initializeListener(); - resolve82(); - }); - this.events.emit("closing"); - }); - } - async _invoke(type) { - const exts = this.extensions.server[type]; - if (!exts.nodes) { - return; - } - for (const ext of exts.nodes) { - const bind = ext.bind ?? ext.realm.settings.bind; - const operation = ext.func.call(bind, ext.server, bind); - await Toolkit.timed(operation, { timeout: ext.timeout, name: type }); - } - } - _defaultRoutes() { - this.router.special("notFound", new Route({ method: "_special", path: "/{p*}", handler: internals.notFound }, this.root, { special: true })); - this.router.special("badRequest", new Route({ method: "_special", path: "/{p*}", handler: internals.badRequest }, this.root, { special: true })); - if (this.settings.routes.cors) { - Cors.handler(this.root); - } - } - _dispatch(options2 = {}) { - return (req, res) => { - const request = Request2.generate(this.root, req, res, options2); - if (this.settings.operations.cleanStop && req.socket) { - this.actives.set(req.socket, request); - const env2 = { core: this, req }; - res.on("finish", internals.onFinish.bind(res, env2)); - } - if (this.settings.load.sampleInterval) { - try { - this.heavy.check(); - } catch (err) { - Bounce.rethrow(err, "system"); - this._log(["load"], this.heavy.load); - request._reply(err); - return; - } - } - request._execute(); - }; - } - _createListener() { - const listener = this.settings.listener ?? (this.settings.tls ? Https.createServer(this.settings.tls) : Http.createServer()); - listener.on("request", this._dispatch()); - listener.on("checkContinue", this._dispatch({ expectContinue: true })); - listener.on("clientError", (err, socket) => { - this._log(["connection", "client", "error"], err); - if (socket.readable) { - const request = this.settings.operations.cleanStop && this.actives.get(socket); - if (request) { - if (err.code === "HPE_INVALID_METHOD") { - request.raw.res.once("close", () => { - if (socket.readable) { - socket.end(internals.badRequestResponse); - } else { - socket.destroy(err); - } - }); - return; - } - const error2 = Boom5.badRequest(); - error2.output.headers = { connection: "close" }; - request._reply(error2); - } else { - socket.end(internals.badRequestResponse); - } - } else { - socket.destroy(err); - } - }); - return listener; - } - _initializeListener() { - this.listener.once("listening", () => { - if (this.type === "tcp") { - const address = this.listener.address(); - this.info.address = address.address; - this.info.port = address.port; - this.info.uri = this.settings.uri ?? this.info.protocol + "://" + this.info.host + ":" + this.info.port; - } - if (this.settings.operations.cleanStop) { - this.sockets = /* @__PURE__ */ new Set(); - const self2 = this; - const onClose = function() { - self2.sockets.delete(this); - }; - this.onConnection = (connection) => { - this.sockets.add(connection); - connection.on("close", onClose); - }; - this.listener.on(this.settings.tls ? "secureConnection" : "connection", this.onConnection); - } - }); - } - _cachePolicy(options2, _segment, realm) { - options2 = Config.apply("cachePolicy", options2); - const plugin2 = realm?.plugin; - const segment = options2.segment ?? _segment ?? (plugin2 ? `!${plugin2}` : ""); - Hoek.assert(segment, "Missing cache segment name"); - const cacheName = options2.cache ?? "_default"; - const cache2 = this.caches.get(cacheName); - Hoek.assert(cache2, "Unknown cache", cacheName); - Hoek.assert(!cache2.segments[segment] || cache2.shared || options2.shared, "Cannot provision the same cache segment more than once"); - cache2.segments[segment] = true; - const policy = new Catbox.Policy(options2, cache2.client, segment); - this.events.emit("cachePolicy", [policy, options2.cache, segment]); - return policy; - } - log(tags, data) { - return this._log(tags, data, "app"); - } - _log(tags, data, channel = "internal") { - if (!this.events.hasListeners("log")) { - return; - } - if (!Array.isArray(tags)) { - tags = [tags]; - } - const timestamp = Date.now(); - const field = data instanceof Error ? "error" : "data"; - let event = { timestamp, tags, [field]: data, channel }; - if (typeof data === "function") { - event = () => ({ timestamp, tags, data: data(), channel }); - } - this.events.emit({ name: "log", tags, channel }, event); - } +var require_QUERY = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/QUERY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the count for one or more items in a Count-Min Sketch + * @param parser - The command parser + * @param key - The name of the sketch + * @param items - One or more items to get counts for + */ + parseCommand(parser3, key, items) { + parser3.push("CMS.QUERY"); + parser3.pushKey(key); + parser3.pushVariadic(items); + }, + transformReply: void 0 }; - internals.setup = function(options2 = {}) { - let settings = Hoek.clone(options2, { shallow: ["cache", "listener", "routes.bind"] }); - settings.app = settings.app ?? {}; - settings.routes = Config.enable(settings.routes); - settings = Config.apply("server", settings); - if (settings.port === void 0) { - settings.port = 0; - } - const type = typeof settings.port === "string" ? "socket" : "tcp"; - if (type === "socket") { - settings.port = settings.port.indexOf("/") !== -1 ? Path.resolve(settings.port) : settings.port.toLowerCase(); - } - if (settings.autoListen === void 0) { - settings.autoListen = true; - } - Hoek.assert(settings.autoListen || !settings.port, "Cannot specify port when autoListen is false"); - Hoek.assert(settings.autoListen || !settings.address, "Cannot specify address when autoListen is false"); - return { settings, type }; + } +}); +var require_count_min_sketch = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/count-min-sketch/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - internals.notFound = function() { - throw Boom5.notFound(); + Object.defineProperty(exports2, "__esModule", { value: true }); + var INCRBY_1 = __importDefault(require_INCRBY2()); + var INFO_1 = __importDefault(require_INFO3()); + var INITBYDIM_1 = __importDefault(require_INITBYDIM()); + var INITBYPROB_1 = __importDefault(require_INITBYPROB()); + var MERGE_1 = __importDefault(require_MERGE()); + var QUERY_1 = __importDefault(require_QUERY()); + exports2.default = { + INCRBY: INCRBY_1.default, + incrBy: INCRBY_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + INITBYDIM: INITBYDIM_1.default, + initByDim: INITBYDIM_1.default, + INITBYPROB: INITBYPROB_1.default, + initByProb: INITBYPROB_1.default, + MERGE: MERGE_1.default, + merge: MERGE_1.default, + QUERY: QUERY_1.default, + query: QUERY_1.default }; - internals.badRequest = function() { - throw Boom5.badRequest(); + } +}); +var require_ADD2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/ADD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds an item to a Cuckoo Filter, creating the filter if it does not exist + * @param parser - The command parser + * @param key - The name of the Cuckoo filter + * @param item - The item to add to the filter + */ + parseCommand(parser3, key, item) { + parser3.push("CF.ADD"); + parser3.pushKey(key); + parser3.push(item); + }, + transformReply: generic_transformers_1.transformBooleanReply }; - internals.onFinish = function(env2) { - const { core, req } = env2; - core.actives.delete(req.socket); - if (!core.started) { - req.socket.end(); - } + } +}); +var require_ADDNX = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/ADDNX.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds an item to a Cuckoo Filter only if it does not exist + * @param parser - The command parser + * @param key - The name of the Cuckoo filter + * @param item - The item to add to the filter if it doesn't exist + */ + parseCommand(parser3, key, item) { + parser3.push("CF.ADDNX"); + parser3.pushKey(key); + parser3.push(item); + }, + transformReply: generic_transformers_1.transformBooleanReply }; } }); -var require_package4 = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/package.json"(exports2, module14) { - module14.exports = { - name: "@hapi/hapi", - description: "HTTP Server framework", - homepage: "https://hapi.dev", - version: "21.4.3", - repository: "git://github.com/hapijs/hapi", - main: "lib/index.js", - types: "lib/index.d.ts", - engines: { - node: ">=14.15.0" +var require_COUNT = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/COUNT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the number of times an item appears in a Cuckoo Filter + * @param parser - The command parser + * @param key - The name of the Cuckoo filter + * @param item - The item to count occurrences of + */ + parseCommand(parser3, key, item) { + parser3.push("CF.COUNT"); + parser3.pushKey(key); + parser3.push(item); }, - files: [ - "lib" - ], - keywords: [ - "framework", - "http", - "api", - "web" - ], - eslintConfig: { - extends: [ - "plugin:@hapi/module" - ] + transformReply: void 0 + }; + } +}); +var require_DEL2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/DEL.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Removes an item from a Cuckoo Filter if it exists + * @param parser - The command parser + * @param key - The name of the Cuckoo filter + * @param item - The item to remove from the filter + */ + parseCommand(parser3, key, item) { + parser3.push("CF.DEL"); + parser3.pushKey(key); + parser3.push(item); }, - dependencies: { - "@hapi/accept": "^6.0.3", - "@hapi/ammo": "^6.0.1", - "@hapi/boom": "^10.0.1", - "@hapi/bounce": "^3.0.2", - "@hapi/call": "^9.0.1", - "@hapi/catbox": "^12.1.1", - "@hapi/catbox-memory": "^6.0.2", - "@hapi/heavy": "^8.0.1", - "@hapi/hoek": "^11.0.7", - "@hapi/mimos": "^7.0.1", - "@hapi/podium": "^5.0.2", - "@hapi/shot": "^6.0.2", - "@hapi/somever": "^4.1.1", - "@hapi/statehood": "^8.2.0", - "@hapi/subtext": "^8.1.1", - "@hapi/teamwork": "^6.0.0", - "@hapi/topo": "^6.0.2", - "@hapi/validate": "^2.0.1" + transformReply: generic_transformers_1.transformBooleanReply + }; + } +}); +var require_EXISTS3 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/EXISTS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Checks if an item exists in a Cuckoo Filter + * @param parser - The command parser + * @param key - The name of the Cuckoo filter + * @param item - The item to check for existence + */ + parseCommand(parser3, key, item) { + parser3.push("CF.EXISTS"); + parser3.pushKey(key); + parser3.push(item); }, - devDependencies: { - "@hapi/code": "^9.0.3", - "@hapi/eslint-plugin": "^6.0.0", - "@hapi/inert": "^7.1.0", - "@hapi/joi-legacy-test": "npm:@hapi/joi@^15.0.0", - "@hapi/lab": "^25.3.2", - "@hapi/vision": "^7.0.3", - "@hapi/wreck": "^18.1.0", - "@types/node": "^18.19.122", - handlebars: "^4.7.8", - joi: "^17.13.3", - "legacy-readable-stream": "npm:readable-stream@^1.0.34", - typescript: "^4.9.5" + transformReply: generic_transformers_1.transformBooleanReply + }; + } +}); +var require_INFO4 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var bloom_1 = require_bloom(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns detailed information about a Cuckoo Filter including size, buckets, filters count, items statistics and configuration + * @param parser - The command parser + * @param key - The name of the Cuckoo filter to get information about + */ + parseCommand(parser3, key) { + parser3.push("CF.INFO"); + parser3.pushKey(key); }, - scripts: { - test: "lab -a @hapi/code -t 100 -L -m 5000 -Y", - "test-tap": "lab -a @hapi/code -r tap -o tests.tap -m 5000", - "test-cov-html": "lab -a @hapi/code -r html -o coverage.html -m 5000" - }, - license: "BSD-3-Clause" - }; - } -}); -var require_server = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/server.js"(exports2, module14) { - "use strict"; - var Hoek = require_lib(); - var Shot = require_lib10(); - var Teamwork = require_lib11(); - var Config = require_config(); - var Core = require_core(); - var Cors = require_cors(); - var Ext = require_ext(); - var Package = require_package4(); - var Route = require_route2(); - var Toolkit = require_toolkit(); - var Validation = require_validation(); - var internals = {}; - exports2 = module14.exports = function(options2) { - const core = new Core(options2); - return new internals.Server(core); - }; - internals.Server = class { - constructor(core, name, parent) { - this._core = core; - this.app = core.app; - this.auth = core.auth.public(this); - this.decorations = core.decorations.public; - this.cache = internals.cache(this); - this.events = core.events; - this.info = core.info; - this.listener = core.listener; - this.load = core.heavy.load; - this.methods = core.methods.methods; - this.mime = core.mime; - this.plugins = core.plugins; - this.registrations = core.registrations; - this.settings = core.settings; - this.states = core.states; - this.type = core.type; - this.version = Package.version; - this.realm = { - _extensions: { - onPreAuth: new Ext("onPreAuth", core), - onCredentials: new Ext("onCredentials", core), - onPostAuth: new Ext("onPostAuth", core), - onPreHandler: new Ext("onPreHandler", core), - onPostHandler: new Ext("onPostHandler", core), - onPreResponse: new Ext("onPreResponse", core), - onPostResponse: new Ext("onPostResponse", core) - }, - modifiers: { - route: {} - }, - parent: parent ? parent.realm : null, - plugin: name, - pluginOptions: {}, - plugins: {}, - _rules: null, - settings: { - bind: void 0, - files: { - relativeTo: void 0 - } - }, - validator: null - }; - for (const [property, method] of core.decorations.server.entries()) { - this[property] = method; - } - core.registerServer(this); - } - _clone(name) { - return new internals.Server(this._core, name, this); - } - bind(context) { - Hoek.assert(typeof context === "object", "bind must be an object"); - this.realm.settings.bind = context; - } - control(server) { - Hoek.assert(server instanceof internals.Server, "Can only control Server objects"); - this._core.controlled = this._core.controlled ?? []; - this._core.controlled.push(server); - } - decoder(encoding, decoder) { - return this._core.compression.addDecoder(encoding, decoder); - } - decorate(type, property, method, options2 = {}) { - Hoek.assert(this._core.decorations.public[type], "Unknown decoration type:", type); - Hoek.assert(property, "Missing decoration property name"); - Hoek.assert(typeof property === "string" || typeof property === "symbol", "Decoration property must be a string or a symbol"); - const propertyName = property.toString(); - Hoek.assert(propertyName[0] !== "_", "Property name cannot begin with an underscore:", propertyName); - const existing = this._core.decorations[type].get(property); - if (options2.extend) { - Hoek.assert(type !== "handler", "Cannot extend handler decoration:", propertyName); - Hoek.assert(existing, `Cannot extend missing ${type} decoration: ${propertyName}`); - Hoek.assert(typeof method === "function", `Extended ${type} decoration method must be a function: ${propertyName}`); - method = method(existing); - } else { - Hoek.assert(existing === void 0, `${type[0].toUpperCase() + type.slice(1)} decoration already defined: ${propertyName}`); - } - if (type === "handler") { - Hoek.assert(typeof method === "function", "Handler must be a function:", propertyName); - Hoek.assert(!method.defaults || typeof method.defaults === "object" || typeof method.defaults === "function", "Handler defaults property must be an object or function"); - Hoek.assert(!options2.extend, "Cannot extend handler decoration:", propertyName); - } else if (type === "request") { - Hoek.assert(!this._core.Request.reserved.includes(property), "Cannot override the built-in request interface decoration:", propertyName); - if (options2.apply) { - this._core.decorations.requestApply = this._core.decorations.requestApply ?? /* @__PURE__ */ new Map(); - this._core.decorations.requestApply.set(property, method); - } else { - this._core.Request.prototype[property] = method; - } - } else if (type === "response") { - Hoek.assert(!this._core.Response.reserved.includes(property), "Cannot override the built-in response interface decoration:", propertyName); - this._core.Response.prototype[property] = method; - } else if (type === "toolkit") { - Hoek.assert(!Toolkit.reserved.includes(property), "Cannot override the built-in toolkit decoration:", propertyName); - this._core.toolkit.decorate(property, method); - } else { - if (typeof property === "string") { - Hoek.assert(!Object.getOwnPropertyNames(internals.Server.prototype).includes(property), "Cannot override the built-in server interface method:", propertyName); - } else { - Hoek.assert(!Object.getOwnPropertySymbols(internals.Server.prototype).includes(property), "Cannot override the built-in server interface method:", propertyName); - } - this._core.instances.forEach((server) => { - server[property] = method; - }); - } - this._core.decorations[type].set(property, method); - this._core.decorations.public[type].push(property); - } - dependency(dependencies, after) { - Hoek.assert(this.realm.plugin, "Cannot call dependency() outside of a plugin"); - Hoek.assert(!after || typeof after === "function", "Invalid after method"); - if (typeof dependencies === "string") { - dependencies = { [dependencies]: "*" }; - } else if (Array.isArray(dependencies)) { - const map = {}; - for (const dependency of dependencies) { - map[dependency] = "*"; - } - dependencies = map; - } - this._core.dependencies.push({ plugin: this.realm.plugin, deps: dependencies }); - if (after) { - this.ext("onPreStart", after, { after: Object.keys(dependencies) }); - } + transformReply: { + 2: (reply, _, typeMapping) => { + return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); + }, + 3: void 0 } - encoder(encoding, encoder3) { - return this._core.compression.addEncoder(encoding, encoder3); + }; + } +}); +var require_INSERT2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/INSERT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseCfInsertArguments = void 0; + var generic_transformers_1 = require_generic_transformers(); + function parseCfInsertArguments(parser3, key, items, options2) { + parser3.pushKey(key); + if (options2?.CAPACITY !== void 0) { + parser3.push("CAPACITY", options2.CAPACITY.toString()); } - event(event) { - this._core.events.registerEvent(event); + if (options2?.NOCREATE) { + parser3.push("NOCREATE"); } - expose(key, value, options2 = {}) { - Hoek.assert(this.realm.plugin, "Cannot call expose() outside of a plugin"); - let plugin2 = this.realm.plugin; - if (plugin2[0] === "@" && options2.scope !== true) { - plugin2 = plugin2.replace(/^@([^/]+)\//, ($0, $1) => { - return !options2.scope ? "" : `${$1}__`; - }); - } - this._core.plugins[plugin2] = this._core.plugins[plugin2] ?? {}; - if (typeof key === "string") { - this._core.plugins[plugin2][key] = value; - } else { - Hoek.merge(this._core.plugins[plugin2], key); - } + parser3.push("ITEMS"); + parser3.pushVariadic(items); + } + exports2.parseCfInsertArguments = parseCfInsertArguments; + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds one or more items to a Cuckoo Filter, creating it if it does not exist + * @param parser - The command parser + * @param key - The name of the Cuckoo filter + * @param items - One or more items to add to the filter + * @param options - Optional parameters for filter creation + * @param options.CAPACITY - The number of entries intended to be added to the filter + * @param options.NOCREATE - If true, prevents automatic filter creation + */ + parseCommand(...args) { + args[0].push("CF.INSERT"); + parseCfInsertArguments(...args); + }, + transformReply: generic_transformers_1.transformBooleanArrayReply + }; + } +}); +var require_INSERTNX = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/INSERTNX.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - ext(events, method, options2) { - let promise; - if (typeof events === "string") { - if (!method) { - const team = new Teamwork.Team(); - method = (request, h2) => { - team.attend(request); - return h2.continue; - }; - promise = team.work; - } - events = { type: events, method, options: options2 }; - } - events = Config.apply("exts", events); - for (const event of events) { - this._ext(event); - } - return promise; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - _ext(event) { - event = Object.assign({}, event); - event.realm = this.realm; - const type = event.type; - if (!this._core.extensions.server[type]) { - if (event.options.sandbox === "plugin") { - Hoek.assert(this.realm._extensions[type], "Unknown event type", type); - return this.realm._extensions[type].add(event); - } - Hoek.assert(this._core.extensions.route[type], "Unknown event type", type); - return this._core.extensions.route[type].add(event); - } - Hoek.assert(!event.options.sandbox, "Cannot specify sandbox option for server extension"); - Hoek.assert(type !== "onPreStart" || this._core.phase === "stopped", "Cannot add onPreStart (after) extension after the server was initialized"); - event.server = this; - this._core.extensions.server[type].add(event); - } - async inject(options2) { - let settings = options2; - if (typeof settings === "string") { - settings = { url: settings }; - } - if (!settings.authority || settings.auth || settings.app || settings.plugins || settings.allowInternals !== void 0) { - settings = Object.assign({}, settings); - delete settings.auth; - delete settings.app; - delete settings.plugins; - delete settings.allowInternals; - settings.authority = settings.authority ?? this._core.info.host + ":" + this._core.info.port; - } - Hoek.assert(!options2.credentials, "options.credentials no longer supported (use options.auth)"); - if (options2.auth) { - Hoek.assert(typeof options2.auth === "object", "options.auth must be an object"); - Hoek.assert(options2.auth.credentials, "options.auth.credentials is missing"); - Hoek.assert(options2.auth.strategy, "options.auth.strategy is missing"); - } - const needle = this._core._dispatch({ - auth: options2.auth, - allowInternals: options2.allowInternals, - app: options2.app, - plugins: options2.plugins, - isInjected: true - }); - const res = await Shot.inject(needle, settings); - const custom = res.raw.res[Config.symbol]; - if (custom) { - delete res.raw.res[Config.symbol]; - res.request = custom.request; - if (custom.error) { - throw custom.error; - } - if (custom.result !== void 0) { - res.result = custom.result; - } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var INSERT_1 = __importStar(require_INSERT2()); + exports2.default = { + IS_READ_ONLY: INSERT_1.default.IS_READ_ONLY, + parseCommand(...args) { + args[0].push("CF.INSERTNX"); + (0, INSERT_1.parseCfInsertArguments)(...args); + }, + transformReply: INSERT_1.default.transformReply + }; + } +}); +var require_LOADCHUNK2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/LOADCHUNK.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Restores a Cuckoo Filter chunk previously saved using SCANDUMP + * @param parser - The command parser + * @param key - The name of the Cuckoo filter to restore + * @param iterator - Iterator value from the SCANDUMP command + * @param chunk - Data chunk from the SCANDUMP command + */ + parseCommand(parser3, key, iterator, chunk) { + parser3.push("CF.LOADCHUNK"); + parser3.pushKey(key); + parser3.push(iterator.toString(), chunk); + }, + transformReply: void 0 + }; + } +}); +var require_RESERVE2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/RESERVE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Creates an empty Cuckoo Filter with specified capacity and parameters + * @param parser - The command parser + * @param key - The name of the Cuckoo filter to create + * @param capacity - The number of entries intended to be added to the filter + * @param options - Optional parameters to tune the filter + * @param options.BUCKETSIZE - Number of items in each bucket + * @param options.MAXITERATIONS - Maximum number of iterations before declaring filter full + * @param options.EXPANSION - Number of additional buckets per expansion + */ + parseCommand(parser3, key, capacity, options2) { + parser3.push("CF.RESERVE"); + parser3.pushKey(key); + parser3.push(capacity.toString()); + if (options2?.BUCKETSIZE !== void 0) { + parser3.push("BUCKETSIZE", options2.BUCKETSIZE.toString()); } - if (res.result === void 0) { - res.result = res.payload; + if (options2?.MAXITERATIONS !== void 0) { + parser3.push("MAXITERATIONS", options2.MAXITERATIONS.toString()); } - return res; - } - log(tags, data) { - return this._core.log(tags, data); - } - lookup(id) { - Hoek.assert(id && typeof id === "string", "Invalid route id:", id); - const record2 = this._core.router.ids.get(id); - if (!record2) { - return null; + if (options2?.EXPANSION !== void 0) { + parser3.push("EXPANSION", options2.EXPANSION.toString()); } - return record2.route.public; + }, + transformReply: void 0 + }; + } +}); +var require_SCANDUMP2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/SCANDUMP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Begins an incremental save of a Cuckoo Filter. This is useful for large filters that can't be saved at once + * @param parser - The command parser + * @param key - The name of the Cuckoo filter to save + * @param iterator - Iterator value; Start at 0, and use the iterator from the response for the next chunk + */ + parseCommand(parser3, key, iterator) { + parser3.push("CF.SCANDUMP"); + parser3.pushKey(key); + parser3.push(iterator.toString()); + }, + transformReply(reply) { + return { + iterator: reply[0], + chunk: reply[1] + }; } - match(method, path8, host) { - Hoek.assert(method && typeof method === "string", "Invalid method:", method); - Hoek.assert(path8 && typeof path8 === "string" && path8[0] === "/", "Invalid path:", path8); - Hoek.assert(!host || typeof host === "string", "Invalid host:", host); - const match = this._core.router.route(method.toLowerCase(), path8, host); - Hoek.assert(match !== this._core.router.specials.badRequest, "Invalid path:", path8); - if (match === this._core.router.specials.notFound) { - return null; + }; + } +}); +var require_cuckoo = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/cuckoo/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ADD_1 = __importDefault(require_ADD2()); + var ADDNX_1 = __importDefault(require_ADDNX()); + var COUNT_1 = __importDefault(require_COUNT()); + var DEL_1 = __importDefault(require_DEL2()); + var EXISTS_1 = __importDefault(require_EXISTS3()); + var INFO_1 = __importDefault(require_INFO4()); + var INSERT_1 = __importDefault(require_INSERT2()); + var INSERTNX_1 = __importDefault(require_INSERTNX()); + var LOADCHUNK_1 = __importDefault(require_LOADCHUNK2()); + var RESERVE_1 = __importDefault(require_RESERVE2()); + var SCANDUMP_1 = __importDefault(require_SCANDUMP2()); + exports2.default = { + ADD: ADD_1.default, + add: ADD_1.default, + ADDNX: ADDNX_1.default, + addNX: ADDNX_1.default, + COUNT: COUNT_1.default, + count: COUNT_1.default, + DEL: DEL_1.default, + del: DEL_1.default, + EXISTS: EXISTS_1.default, + exists: EXISTS_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + INSERT: INSERT_1.default, + insert: INSERT_1.default, + INSERTNX: INSERTNX_1.default, + insertNX: INSERTNX_1.default, + LOADCHUNK: LOADCHUNK_1.default, + loadChunk: LOADCHUNK_1.default, + RESERVE: RESERVE_1.default, + reserve: RESERVE_1.default, + SCANDUMP: SCANDUMP_1.default, + scanDump: SCANDUMP_1.default + }; + } +}); +var require_ADD3 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/ADD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds one or more observations to a t-digest sketch + * @param parser - The command parser + * @param key - The name of the t-digest sketch + * @param values - Array of numeric values to add to the sketch + */ + parseCommand(parser3, key, values) { + parser3.push("TDIGEST.ADD"); + parser3.pushKey(key); + for (const value of values) { + parser3.push(value.toString()); } - return match.route.public; - } - method(name, method, options2 = {}) { - return this._core.methods.add(name, method, options2, this.realm); - } - path(relativeTo) { - Hoek.assert(relativeTo && typeof relativeTo === "string", "relativeTo must be a non-empty string"); - this.realm.settings.files.relativeTo = relativeTo; + }, + transformReply: void 0 + }; + } +}); +var require_BYRANK = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/BYRANK.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transformByRankArguments = void 0; + var generic_transformers_1 = require_generic_transformers(); + function transformByRankArguments(parser3, key, ranks) { + parser3.pushKey(key); + for (const rank of ranks) { + parser3.push(rank.toString()); } - async register(plugins, options2 = {}) { - if (this.realm.modifiers.route.prefix || this.realm.modifiers.route.vhost) { - options2 = Hoek.clone(options2); - options2.routes = options2.routes ?? {}; - options2.routes.prefix = (this.realm.modifiers.route.prefix ?? "") + (options2.routes.prefix ?? "") || void 0; - options2.routes.vhost = this.realm.modifiers.route.vhost ?? options2.routes.vhost; - } - options2 = Config.apply("register", options2); - ++this._core.registring; - try { - const items = [].concat(plugins); - for (let item of items) { - if (!item.plugin) { - item = { - plugin: item - }; - } else if (!item.plugin.register) { - item = { - options: item.options, - once: item.once, - routes: item.routes, - plugin: item.plugin.plugin - }; - } else if (typeof item === "function") { - item = Object.assign({}, item); - } - item = Config.apply("plugin", item); - const name = item.plugin.name ?? item.plugin.pkg.name; - const clone2 = this._clone(name); - clone2.realm.modifiers.route.prefix = item.routes.prefix ?? options2.routes.prefix; - clone2.realm.modifiers.route.vhost = item.routes.vhost ?? options2.routes.vhost; - clone2.realm.pluginOptions = item.options ?? {}; - const requirements = item.plugin.requirements; - Hoek.assert(!requirements.node || Config.versionMatch(process.version, requirements.node), "Plugin", name, "requires node version", requirements.node, "but found", process.version); - Hoek.assert(!requirements.hapi || Config.versionMatch(this.version, requirements.hapi), "Plugin", name, "requires hapi version", requirements.hapi, "but found", this.version); - if (this._core.registrations[name]) { - if (item.plugin.once || item.once || options2.once) { - continue; - } - Hoek.assert(item.plugin.multiple, "Plugin", name, "already registered"); - } else { - this._core.registrations[name] = { - version: item.plugin.version ?? item.plugin.pkg.version, - name, - options: item.options - }; - } - if (item.plugin.dependencies) { - clone2.dependency(item.plugin.dependencies); - } - await item.plugin.register(clone2, item.options ?? {}); - } - } finally { - --this._core.registring; - } - return this; + } + exports2.transformByRankArguments = transformByRankArguments; + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns value estimates for one or more ranks in a t-digest sketch + * @param parser - The command parser + * @param key - The name of the t-digest sketch + * @param ranks - Array of ranks to get value estimates for (ascending order) + */ + parseCommand(...args) { + args[0].push("TDIGEST.BYRANK"); + transformByRankArguments(...args); + }, + transformReply: generic_transformers_1.transformDoubleArrayReply + }; + } +}); +var require_BYREVRANK = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/BYREVRANK.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - route(options2) { - Hoek.assert(typeof options2 === "object", "Invalid route options"); - options2 = [].concat(options2); - for (const config2 of options2) { - if (Array.isArray(config2.method)) { - for (const method of config2.method) { - const settings = Object.assign({}, config2); - settings.method = method; - this._addRoute(settings, this); - } - } else { - this._addRoute(config2, this); - } - } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - _addRoute(config2, server) { - const route2 = new Route(config2, server); - const vhosts = [].concat(route2.settings.vhost ?? "*"); - for (const vhost of vhosts) { - const record2 = this._core.router.add({ method: route2.method, path: route2.path, vhost, analysis: route2._analysis, id: route2.settings.id }, route2); - route2.fingerprint = record2.fingerprint; - route2.params = record2.params; + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var BYRANK_1 = __importStar(require_BYRANK()); + exports2.default = { + IS_READ_ONLY: BYRANK_1.default.IS_READ_ONLY, + parseCommand(...args) { + args[0].push("TDIGEST.BYREVRANK"); + (0, BYRANK_1.transformByRankArguments)(...args); + }, + transformReply: BYRANK_1.default.transformReply + }; + } +}); +var require_CDF = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/CDF.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Estimates the cumulative distribution function for values in a t-digest sketch + * @param parser - The command parser + * @param key - The name of the t-digest sketch + * @param values - Array of values to get CDF estimates for + */ + parseCommand(parser3, key, values) { + parser3.push("TDIGEST.CDF"); + parser3.pushKey(key); + for (const item of values) { + parser3.push(item.toString()); } - this.events.emit("route", route2.public); - Cors.options(route2.public, server); - } - rules(processor, options2 = {}) { - Hoek.assert(!this.realm._rules, "Server realm rules already defined"); - const settings = Config.apply("rules", options2); - if (settings.validate) { - const schema = settings.validate.schema; - settings.validate.schema = Validation.compile(schema, null, this.realm, this._core); + }, + transformReply: generic_transformers_1.transformDoubleArrayReply + }; + } +}); +var require_CREATE = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/CREATE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Creates a new t-digest sketch for storing distributions + * @param parser - The command parser + * @param key - The name of the t-digest sketch + * @param options - Optional parameters for sketch creation + * @param options.COMPRESSION - Compression parameter that affects performance and accuracy + */ + parseCommand(parser3, key, options2) { + parser3.push("TDIGEST.CREATE"); + parser3.pushKey(key); + if (options2?.COMPRESSION !== void 0) { + parser3.push("COMPRESSION", options2.COMPRESSION.toString()); } - this.realm._rules = { processor, settings }; - } - state(name, options2) { - this.states.add(name, options2); - } - table(host) { - return this._core.router.table(host); - } - validator(validator) { - Hoek.assert(!this.realm.validator, "Validator already set"); - this.realm.validator = Validation.validator(validator); - } - start() { - return this._core._start(); - } - initialize() { - return this._core._initialize(); - } - stop(options2) { - return this._core._stop(options2); + }, + transformReply: void 0 + }; + } +}); +var require_INFO5 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var bloom_1 = require_bloom(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns information about a t-digest sketch including compression, capacity, nodes, weights, observations and memory usage + * @param parser - The command parser + * @param key - The name of the t-digest sketch to get information about + */ + parseCommand(parser3, key) { + parser3.push("TDIGEST.INFO"); + parser3.pushKey(key); + }, + transformReply: { + 2: (reply, _, typeMapping) => { + return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); + }, + 3: void 0 } }; - internals.cache = (plugin2) => { - const policy = function(options2, _segment) { - return this._core._cachePolicy(options2, _segment, plugin2.realm); - }; - policy.provision = async (opts) => { - const clients = plugin2._core._createCache(opts); - if (["initialized", "starting", "started"].includes(plugin2._core.phase)) { - await Promise.all(clients.map((client) => client.start())); - } - }; - return policy; - }; } }); -var require_lib34 = __commonJS({ - "node_modules/.deno/@hapi+hapi@21.4.3/node_modules/@hapi/hapi/lib/index.js"(exports2) { +var require_MAX = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/MAX.js"(exports2) { "use strict"; - var Server3 = require_server(); - exports2.Server = Server3; - exports2.server = Server3; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the maximum value from a t-digest sketch + * @param parser - The command parser + * @param key - The name of the t-digest sketch + */ + parseCommand(parser3, key) { + parser3.push("TDIGEST.MAX"); + parser3.pushKey(key); + }, + transformReply: generic_transformers_1.transformDoubleReply + }; } }); -var require_lru_cache2 = __commonJS({ - "node_modules/.deno/lru-cache@7.18.3/node_modules/lru-cache/index.js"(exports2, module14) { - var perf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date; - var hasAbortController = typeof AbortController === "function"; - var AC = hasAbortController ? AbortController : class AbortController { - constructor() { - this.signal = new AS(); - } - abort(reason = new Error("This operation was aborted")) { - this.signal.reason = this.signal.reason || reason; - this.signal.aborted = true; - this.signal.dispatchEvent({ - type: "abort", - target: this.signal - }); - } - }; - var hasAbortSignal = typeof AbortSignal === "function"; - var hasACAbortSignal = typeof AC.AbortSignal === "function"; - var AS = hasAbortSignal ? AbortSignal : hasACAbortSignal ? AC.AbortController : class AbortSignal { - constructor() { - this.reason = void 0; - this.aborted = false; - this._listeners = []; - } - dispatchEvent(e2) { - if (e2.type === "abort") { - this.aborted = true; - this.onabort(e2); - this._listeners.forEach((f) => f(e2), this); - } - } - onabort() { - } - addEventListener(ev, fn) { - if (ev === "abort") { - this._listeners.push(fn); +var require_MERGE2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/MERGE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Merges multiple t-digest sketches into one, with optional compression and override settings + * @param parser - The command parser + * @param destination - The name of the destination t-digest sketch + * @param source - One or more source sketch names to merge from + * @param options - Optional parameters for merge operation + * @param options.COMPRESSION - New compression value for merged sketch + * @param options.OVERRIDE - If true, override destination sketch if it exists + */ + parseCommand(parser3, destination, source, options2) { + parser3.push("TDIGEST.MERGE"); + parser3.pushKey(destination); + parser3.pushKeysLength(source); + if (options2?.COMPRESSION !== void 0) { + parser3.push("COMPRESSION", options2.COMPRESSION.toString()); } - } - removeEventListener(ev, fn) { - if (ev === "abort") { - this._listeners = this._listeners.filter((f) => f !== fn); + if (options2?.OVERRIDE) { + parser3.push("OVERRIDE"); } - } + }, + transformReply: void 0 }; - var warned = /* @__PURE__ */ new Set(); - var deprecatedOption = (opt, instead) => { - const code2 = `LRU_CACHE_OPTION_${opt}`; - if (shouldWarn(code2)) { - warn(code2, `${opt} option`, `options.${instead}`, LRUCache); - } + } +}); +var require_MIN = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/MIN.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the minimum value from a t-digest sketch + * @param parser - The command parser + * @param key - The name of the t-digest sketch + */ + parseCommand(parser3, key) { + parser3.push("TDIGEST.MIN"); + parser3.pushKey(key); + }, + transformReply: generic_transformers_1.transformDoubleReply }; - var deprecatedMethod = (method, instead) => { - const code2 = `LRU_CACHE_METHOD_${method}`; - if (shouldWarn(code2)) { - const { prototype } = LRUCache; - const { get: get2 } = Object.getOwnPropertyDescriptor(prototype, method); - warn(code2, `${method} method`, `cache.${instead}()`, get2); - } + } +}); +var require_QUANTILE = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/QUANTILE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns value estimates at requested quantiles from a t-digest sketch + * @param parser - The command parser + * @param key - The name of the t-digest sketch + * @param quantiles - Array of quantiles (between 0 and 1) to get value estimates for + */ + parseCommand(parser3, key, quantiles) { + parser3.push("TDIGEST.QUANTILE"); + parser3.pushKey(key); + for (const quantile of quantiles) { + parser3.push(quantile.toString()); + } + }, + transformReply: generic_transformers_1.transformDoubleArrayReply }; - var deprecatedProperty = (field, instead) => { - const code2 = `LRU_CACHE_PROPERTY_${field}`; - if (shouldWarn(code2)) { - const { prototype } = LRUCache; - const { get: get2 } = Object.getOwnPropertyDescriptor(prototype, field); - warn(code2, `${field} property`, `cache.${instead}`, get2); + } +}); +var require_RANK = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/RANK.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transformRankArguments = void 0; + function transformRankArguments(parser3, key, values) { + parser3.pushKey(key); + for (const value of values) { + parser3.push(value.toString()); } + } + exports2.transformRankArguments = transformRankArguments; + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the rank of one or more values in a t-digest sketch (number of values that are lower than each value) + * @param parser - The command parser + * @param key - The name of the t-digest sketch + * @param values - Array of values to get ranks for + */ + parseCommand(...args) { + args[0].push("TDIGEST.RANK"); + transformRankArguments(...args); + }, + transformReply: void 0 }; - var emitWarning = (...a) => { - typeof process === "object" && process && typeof process.emitWarning === "function" ? process.emitWarning(...a) : console.error(...a); - }; - var shouldWarn = (code2) => !warned.has(code2); - var warn = (code2, what, instead, fn) => { - warned.add(code2); - const msg = `The ${what} is deprecated. Please use ${instead} instead.`; - emitWarning(msg, "DeprecationWarning", code2, fn); - }; - var isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n); - var getUintArray = (max) => !isPosInt(max) ? null : max <= Math.pow(2, 8) ? Uint8Array : max <= Math.pow(2, 16) ? Uint16Array : max <= Math.pow(2, 32) ? Uint32Array : max <= Number.MAX_SAFE_INTEGER ? ZeroArray : null; - var ZeroArray = class extends Array { - constructor(size) { - super(size); - this.fill(0); - } + } +}); +var require_RESET = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/RESET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Resets a t-digest sketch, clearing all previously added observations + * @param parser - The command parser + * @param key - The name of the t-digest sketch to reset + */ + parseCommand(parser3, key) { + parser3.push("TDIGEST.RESET"); + parser3.pushKey(key); + }, + transformReply: void 0 }; - var Stack = class { - constructor(max) { - if (max === 0) { - return []; - } - const UintArray = getUintArray(max); - this.heap = new UintArray(max); - this.length = 0; - } - push(n) { - this.heap[this.length++] = n; + } +}); +var require_REVRANK = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/REVRANK.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - pop() { - return this.heap[--this.length]; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } + __setModuleDefault(result, mod); + return result; }; - var LRUCache = class _LRUCache { - constructor(options2 = {}) { - const { - max = 0, - ttl, - ttlResolution = 1, - ttlAutopurge, - updateAgeOnGet, - updateAgeOnHas, - allowStale, - dispose, - disposeAfter, - noDisposeOnSet, - noUpdateTTL, - maxSize = 0, - maxEntrySize = 0, - sizeCalculation, - fetchMethod, - fetchContext, - noDeleteOnFetchRejection, - noDeleteOnStaleGet, - allowStaleOnFetchRejection, - allowStaleOnFetchAbort, - ignoreFetchAbort - } = options2; - const { length: length2, maxAge: maxAge2, stale } = options2 instanceof _LRUCache ? {} : options2; - if (max !== 0 && !isPosInt(max)) { - throw new TypeError("max option must be a nonnegative integer"); - } - const UintArray = max ? getUintArray(max) : Array; - if (!UintArray) { - throw new Error("invalid max value: " + max); - } - this.max = max; - this.maxSize = maxSize; - this.maxEntrySize = maxEntrySize || this.maxSize; - this.sizeCalculation = sizeCalculation || length2; - if (this.sizeCalculation) { - if (!this.maxSize && !this.maxEntrySize) { - throw new TypeError( - "cannot set sizeCalculation without setting maxSize or maxEntrySize" - ); - } - if (typeof this.sizeCalculation !== "function") { - throw new TypeError("sizeCalculation set to non-function"); - } - } - this.fetchMethod = fetchMethod || null; - if (this.fetchMethod && typeof this.fetchMethod !== "function") { - throw new TypeError( - "fetchMethod must be a function if specified" - ); - } - this.fetchContext = fetchContext; - if (!this.fetchMethod && fetchContext !== void 0) { - throw new TypeError( - "cannot set fetchContext without fetchMethod" - ); - } - this.keyMap = /* @__PURE__ */ new Map(); - this.keyList = new Array(max).fill(null); - this.valList = new Array(max).fill(null); - this.next = new UintArray(max); - this.prev = new UintArray(max); - this.head = 0; - this.tail = 0; - this.free = new Stack(max); - this.initialFill = 1; - this.size = 0; - if (typeof dispose === "function") { - this.dispose = dispose; - } - if (typeof disposeAfter === "function") { - this.disposeAfter = disposeAfter; - this.disposed = []; - } else { - this.disposeAfter = null; - this.disposed = null; - } - this.noDisposeOnSet = !!noDisposeOnSet; - this.noUpdateTTL = !!noUpdateTTL; - this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection; - this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection; - this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort; - this.ignoreFetchAbort = !!ignoreFetchAbort; - if (this.maxEntrySize !== 0) { - if (this.maxSize !== 0) { - if (!isPosInt(this.maxSize)) { - throw new TypeError( - "maxSize must be a positive integer if specified" - ); - } - } - if (!isPosInt(this.maxEntrySize)) { - throw new TypeError( - "maxEntrySize must be a positive integer if specified" - ); - } - this.initializeSizeTracking(); - } - this.allowStale = !!allowStale || !!stale; - this.noDeleteOnStaleGet = !!noDeleteOnStaleGet; - this.updateAgeOnGet = !!updateAgeOnGet; - this.updateAgeOnHas = !!updateAgeOnHas; - this.ttlResolution = isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1; - this.ttlAutopurge = !!ttlAutopurge; - this.ttl = ttl || maxAge2 || 0; - if (this.ttl) { - if (!isPosInt(this.ttl)) { - throw new TypeError( - "ttl must be a positive integer if specified" - ); - } - this.initializeTTLTracking(); - } - if (this.max === 0 && this.ttl === 0 && this.maxSize === 0) { - throw new TypeError( - "At least one of max, maxSize, or ttl is required" - ); - } - if (!this.ttlAutopurge && !this.max && !this.maxSize) { - const code2 = "LRU_CACHE_UNBOUNDED"; - if (shouldWarn(code2)) { - warned.add(code2); - const msg = "TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption."; - emitWarning(msg, "UnboundedCacheWarning", code2, _LRUCache); - } - } - if (stale) { - deprecatedOption("stale", "allowStale"); - } - if (maxAge2) { - deprecatedOption("maxAge", "ttl"); - } - if (length2) { - deprecatedOption("length", "sizeCalculation"); - } - } - getRemainingTTL(key) { - return this.has(key, { updateAgeOnHas: false }) ? Infinity : 0; - } - initializeTTLTracking() { - this.ttls = new ZeroArray(this.max); - this.starts = new ZeroArray(this.max); - this.setItemTTL = (index, ttl, start = perf.now()) => { - this.starts[index] = ttl !== 0 ? start : 0; - this.ttls[index] = ttl; - if (ttl !== 0 && this.ttlAutopurge) { - const t = setTimeout(() => { - if (this.isStale(index)) { - this.delete(this.keyList[index]); - } - }, ttl + 1); - if (t.unref) { - t.unref(); - } - } - }; - this.updateItemAge = (index) => { - this.starts[index] = this.ttls[index] !== 0 ? perf.now() : 0; - }; - this.statusTTL = (status, index) => { - if (status) { - status.ttl = this.ttls[index]; - status.start = this.starts[index]; - status.now = cachedNow || getNow(); - status.remainingTTL = status.now + status.ttl - status.start; - } - }; - let cachedNow = 0; - const getNow = () => { - const n = perf.now(); - if (this.ttlResolution > 0) { - cachedNow = n; - const t = setTimeout( - () => cachedNow = 0, - this.ttlResolution - ); - if (t.unref) { - t.unref(); - } - } - return n; - }; - this.getRemainingTTL = (key) => { - const index = this.keyMap.get(key); - if (index === void 0) { - return 0; - } - return this.ttls[index] === 0 || this.starts[index] === 0 ? Infinity : this.starts[index] + this.ttls[index] - (cachedNow || getNow()); - }; - this.isStale = (index) => { - return this.ttls[index] !== 0 && this.starts[index] !== 0 && (cachedNow || getNow()) - this.starts[index] > this.ttls[index]; - }; - } - updateItemAge(_index) { - } - statusTTL(_status, _index) { - } - setItemTTL(_index, _ttl, _start) { - } - isStale(_index) { - return false; - } - initializeSizeTracking() { - this.calculatedSize = 0; - this.sizes = new ZeroArray(this.max); - this.removeItemSize = (index) => { - this.calculatedSize -= this.sizes[index]; - this.sizes[index] = 0; - }; - this.requireSize = (k, v2, size, sizeCalculation) => { - if (this.isBackgroundFetch(v2)) { - return 0; - } - if (!isPosInt(size)) { - if (sizeCalculation) { - if (typeof sizeCalculation !== "function") { - throw new TypeError("sizeCalculation must be a function"); - } - size = sizeCalculation(v2, k); - if (!isPosInt(size)) { - throw new TypeError( - "sizeCalculation return invalid (expect positive integer)" - ); - } - } else { - throw new TypeError( - "invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set." - ); - } - } - return size; - }; - this.addItemSize = (index, size, status) => { - this.sizes[index] = size; - if (this.maxSize) { - const maxSize = this.maxSize - this.sizes[index]; - while (this.calculatedSize > maxSize) { - this.evict(true); - } - } - this.calculatedSize += this.sizes[index]; - if (status) { - status.entrySize = size; - status.totalCalculatedSize = this.calculatedSize; - } - }; - } - removeItemSize(_index) { - } - addItemSize(_index, _size2) { - } - requireSize(_k, _v, size, sizeCalculation) { - if (size || sizeCalculation) { - throw new TypeError( - "cannot set size without setting maxSize or maxEntrySize on cache" - ); - } - } - *indexes({ allowStale = this.allowStale } = {}) { - if (this.size) { - for (let i2 = this.tail; true; ) { - if (!this.isValidIndex(i2)) { - break; - } - if (allowStale || !this.isStale(i2)) { - yield i2; - } - if (i2 === this.head) { - break; - } else { - i2 = this.prev[i2]; - } - } - } - } - *rindexes({ allowStale = this.allowStale } = {}) { - if (this.size) { - for (let i2 = this.head; true; ) { - if (!this.isValidIndex(i2)) { - break; - } - if (allowStale || !this.isStale(i2)) { - yield i2; - } - if (i2 === this.tail) { - break; - } else { - i2 = this.next[i2]; - } + Object.defineProperty(exports2, "__esModule", { value: true }); + var RANK_1 = __importStar(require_RANK()); + exports2.default = { + IS_READ_ONLY: RANK_1.default.IS_READ_ONLY, + parseCommand(...args) { + args[0].push("TDIGEST.REVRANK"); + (0, RANK_1.transformRankArguments)(...args); + }, + transformReply: RANK_1.default.transformReply + }; + } +}); +var require_TRIMMED_MEAN = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/TRIMMED_MEAN.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the mean value from a t-digest sketch after trimming values at specified percentiles + * @param parser - The command parser + * @param key - The name of the t-digest sketch + * @param lowCutPercentile - Lower percentile cutoff (between 0 and 100) + * @param highCutPercentile - Higher percentile cutoff (between 0 and 100) + */ + parseCommand(parser3, key, lowCutPercentile, highCutPercentile) { + parser3.push("TDIGEST.TRIMMED_MEAN"); + parser3.pushKey(key); + parser3.push(lowCutPercentile.toString(), highCutPercentile.toString()); + }, + transformReply: generic_transformers_1.transformDoubleReply + }; + } +}); +var require_t_digest = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/t-digest/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ADD_1 = __importDefault(require_ADD3()); + var BYRANK_1 = __importDefault(require_BYRANK()); + var BYREVRANK_1 = __importDefault(require_BYREVRANK()); + var CDF_1 = __importDefault(require_CDF()); + var CREATE_1 = __importDefault(require_CREATE()); + var INFO_1 = __importDefault(require_INFO5()); + var MAX_1 = __importDefault(require_MAX()); + var MERGE_1 = __importDefault(require_MERGE2()); + var MIN_1 = __importDefault(require_MIN()); + var QUANTILE_1 = __importDefault(require_QUANTILE()); + var RANK_1 = __importDefault(require_RANK()); + var RESET_1 = __importDefault(require_RESET()); + var REVRANK_1 = __importDefault(require_REVRANK()); + var TRIMMED_MEAN_1 = __importDefault(require_TRIMMED_MEAN()); + exports2.default = { + ADD: ADD_1.default, + add: ADD_1.default, + BYRANK: BYRANK_1.default, + byRank: BYRANK_1.default, + BYREVRANK: BYREVRANK_1.default, + byRevRank: BYREVRANK_1.default, + CDF: CDF_1.default, + cdf: CDF_1.default, + CREATE: CREATE_1.default, + create: CREATE_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + MAX: MAX_1.default, + max: MAX_1.default, + MERGE: MERGE_1.default, + merge: MERGE_1.default, + MIN: MIN_1.default, + min: MIN_1.default, + QUANTILE: QUANTILE_1.default, + quantile: QUANTILE_1.default, + RANK: RANK_1.default, + rank: RANK_1.default, + RESET: RESET_1.default, + reset: RESET_1.default, + REVRANK: REVRANK_1.default, + revRank: REVRANK_1.default, + TRIMMED_MEAN: TRIMMED_MEAN_1.default, + trimmedMean: TRIMMED_MEAN_1.default + }; + } +}); +var require_ADD4 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/ADD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds one or more items to a Top-K filter and returns items dropped from the top-K list + * @param parser - The command parser + * @param key - The name of the Top-K filter + * @param items - One or more items to add to the filter + */ + parseCommand(parser3, key, items) { + parser3.push("TOPK.ADD"); + parser3.pushKey(key); + parser3.pushVariadic(items); + }, + transformReply: void 0 + }; + } +}); +var require_COUNT2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/COUNT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the count of occurrences for one or more items in a Top-K filter + * @param parser - The command parser + * @param key - The name of the Top-K filter + * @param items - One or more items to get counts for + */ + parseCommand(parser3, key, items) { + parser3.push("TOPK.COUNT"); + parser3.pushKey(key); + parser3.pushVariadic(items); + }, + transformReply: void 0 + }; + } +}); +var require_INCRBY3 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/INCRBY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + function pushIncrByItem(parser3, { item, incrementBy }) { + parser3.push(item, incrementBy.toString()); + } + exports2.default = { + IS_READ_ONLY: false, + /** + * Increases the score of one or more items in a Top-K filter by specified increments + * @param parser - The command parser + * @param key - The name of the Top-K filter + * @param items - A single item or array of items to increment, each with an item name and increment value + */ + parseCommand(parser3, key, items) { + parser3.push("TOPK.INCRBY"); + parser3.pushKey(key); + if (Array.isArray(items)) { + for (const item of items) { + pushIncrByItem(parser3, item); } + } else { + pushIncrByItem(parser3, items); } + }, + transformReply: void 0 + }; + } +}); +var require_INFO6 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var bloom_1 = require_bloom(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns configuration and statistics of a Top-K filter, including k, width, depth, and decay parameters + * @param parser - The command parser + * @param key - The name of the Top-K filter to get information about + */ + parseCommand(parser3, key) { + parser3.push("TOPK.INFO"); + parser3.pushKey(key); + }, + transformReply: { + 2: (reply, preserve, typeMapping) => { + reply[7] = generic_transformers_1.transformDoubleReply[2](reply[7], preserve, typeMapping); + return (0, bloom_1.transformInfoV2Reply)(reply, typeMapping); + }, + 3: void 0 } - isValidIndex(index) { - return index !== void 0 && this.keyMap.get(this.keyList[index]) === index; - } - *entries() { - for (const i2 of this.indexes()) { - if (this.valList[i2] !== void 0 && this.keyList[i2] !== void 0 && !this.isBackgroundFetch(this.valList[i2])) { - yield [this.keyList[i2], this.valList[i2]]; - } + }; + } +}); +var require_LIST_WITHCOUNT = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/LIST_WITHCOUNT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns all items in a Top-K filter with their respective counts + * @param parser - The command parser + * @param key - The name of the Top-K filter + */ + parseCommand(parser3, key) { + parser3.push("TOPK.LIST"); + parser3.pushKey(key); + parser3.push("WITHCOUNT"); + }, + transformReply(rawReply) { + const reply = []; + for (let i2 = 0; i2 < rawReply.length; i2++) { + reply.push({ + item: rawReply[i2], + count: rawReply[++i2] + }); } + return reply; } - *rentries() { - for (const i2 of this.rindexes()) { - if (this.valList[i2] !== void 0 && this.keyList[i2] !== void 0 && !this.isBackgroundFetch(this.valList[i2])) { - yield [this.keyList[i2], this.valList[i2]]; - } + }; + } +}); +var require_LIST = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/LIST.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns all items in a Top-K filter + * @param parser - The command parser + * @param key - The name of the Top-K filter + */ + parseCommand(parser3, key) { + parser3.push("TOPK.LIST"); + parser3.pushKey(key); + }, + transformReply: void 0 + }; + } +}); +var require_QUERY2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/QUERY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Checks if one or more items are in the Top-K list + * @param parser - The command parser + * @param key - The name of the Top-K filter + * @param items - One or more items to check in the filter + */ + parseCommand(parser3, key, items) { + parser3.push("TOPK.QUERY"); + parser3.pushKey(key); + parser3.pushVariadic(items); + }, + transformReply: generic_transformers_1.transformBooleanArrayReply + }; + } +}); +var require_RESERVE3 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/RESERVE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Creates a new Top-K filter with specified parameters + * @param parser - The command parser + * @param key - The name of the Top-K filter + * @param topK - Number of top occurring items to keep + * @param options - Optional parameters for filter configuration + * @param options.width - Number of counters in each array + * @param options.depth - Number of counter-arrays + * @param options.decay - Counter decay factor + */ + parseCommand(parser3, key, topK, options2) { + parser3.push("TOPK.RESERVE"); + parser3.pushKey(key); + parser3.push(topK.toString()); + if (options2) { + parser3.push(options2.width.toString(), options2.depth.toString(), options2.decay.toString()); } - } - *keys() { - for (const i2 of this.indexes()) { - if (this.keyList[i2] !== void 0 && !this.isBackgroundFetch(this.valList[i2])) { - yield this.keyList[i2]; - } + }, + transformReply: void 0 + }; + } +}); +var require_top_k = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/top-k/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ADD_1 = __importDefault(require_ADD4()); + var COUNT_1 = __importDefault(require_COUNT2()); + var INCRBY_1 = __importDefault(require_INCRBY3()); + var INFO_1 = __importDefault(require_INFO6()); + var LIST_WITHCOUNT_1 = __importDefault(require_LIST_WITHCOUNT()); + var LIST_1 = __importDefault(require_LIST()); + var QUERY_1 = __importDefault(require_QUERY2()); + var RESERVE_1 = __importDefault(require_RESERVE3()); + exports2.default = { + ADD: ADD_1.default, + add: ADD_1.default, + COUNT: COUNT_1.default, + count: COUNT_1.default, + INCRBY: INCRBY_1.default, + incrBy: INCRBY_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + LIST_WITHCOUNT: LIST_WITHCOUNT_1.default, + listWithCount: LIST_WITHCOUNT_1.default, + LIST: LIST_1.default, + list: LIST_1.default, + QUERY: QUERY_1.default, + query: QUERY_1.default, + RESERVE: RESERVE_1.default, + reserve: RESERVE_1.default + }; + } +}); +var require_commands3 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/commands/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var bloom_1 = __importDefault(require_bloom()); + var count_min_sketch_1 = __importDefault(require_count_min_sketch()); + var cuckoo_1 = __importDefault(require_cuckoo()); + var t_digest_1 = __importDefault(require_t_digest()); + var top_k_1 = __importDefault(require_top_k()); + exports2.default = { + bf: bloom_1.default, + cms: count_min_sketch_1.default, + cf: cuckoo_1.default, + tDigest: t_digest_1.default, + topK: top_k_1.default + }; + } +}); +var require_lib2 = __commonJS({ + "node_modules/.deno/@redis+bloom@5.9.0/node_modules/@redis/bloom/dist/lib/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = void 0; + var commands_1 = require_commands3(); + Object.defineProperty(exports2, "default", { enumerable: true, get: function() { + return __importDefault(commands_1).default; + } }); + } +}); +var require_ARRAPPEND = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRAPPEND.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Appends one or more values to the end of an array in a JSON document. + * Returns the new array length after append, or null if the path does not exist. + * + * @param parser - The Redis command parser + * @param key - The key to append to + * @param path - Path to the array in the JSON document + * @param json - The first value to append + * @param jsons - Additional values to append + */ + parseCommand(parser3, key, path8, json, ...jsons) { + parser3.push("JSON.ARRAPPEND"); + parser3.pushKey(key); + parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(json)); + for (let i2 = 0; i2 < jsons.length; i2++) { + parser3.push((0, generic_transformers_1.transformRedisJsonArgument)(jsons[i2])); } - } - *rkeys() { - for (const i2 of this.rindexes()) { - if (this.keyList[i2] !== void 0 && !this.isBackgroundFetch(this.valList[i2])) { - yield this.keyList[i2]; + }, + transformReply: void 0 + }; + } +}); +var require_ARRINDEX = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRINDEX.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the index of the first occurrence of a value in a JSON array. + * If the specified value is not found, it returns -1, or null if the path does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the array + * @param path - Path to the array in the JSON document + * @param json - The value to search for + * @param options - Optional range parameters for the search + * @param options.range.start - Starting index for the search + * @param options.range.stop - Optional ending index for the search + */ + parseCommand(parser3, key, path8, json, options2) { + parser3.push("JSON.ARRINDEX"); + parser3.pushKey(key); + parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(json)); + if (options2?.range) { + parser3.push(options2.range.start.toString()); + if (options2.range.stop !== void 0) { + parser3.push(options2.range.stop.toString()); } } - } - *values() { - for (const i2 of this.indexes()) { - if (this.valList[i2] !== void 0 && !this.isBackgroundFetch(this.valList[i2])) { - yield this.valList[i2]; - } + }, + transformReply: void 0 + }; + } +}); +var require_ARRINSERT = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRINSERT.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Inserts one or more values into an array at the specified index. + * Returns the new array length after insert, or null if the path does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the array + * @param path - Path to the array in the JSON document + * @param index - The position where to insert the values + * @param json - The first value to insert + * @param jsons - Additional values to insert + */ + parseCommand(parser3, key, path8, index, json, ...jsons) { + parser3.push("JSON.ARRINSERT"); + parser3.pushKey(key); + parser3.push(path8, index.toString(), (0, generic_transformers_1.transformRedisJsonArgument)(json)); + for (let i2 = 0; i2 < jsons.length; i2++) { + parser3.push((0, generic_transformers_1.transformRedisJsonArgument)(jsons[i2])); } - } - *rvalues() { - for (const i2 of this.rindexes()) { - if (this.valList[i2] !== void 0 && !this.isBackgroundFetch(this.valList[i2])) { - yield this.valList[i2]; - } + }, + transformReply: void 0 + }; + } +}); +var require_ARRLEN = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRLEN.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the length of an array in a JSON document. + * Returns null if the path does not exist or the value is not an array. + * + * @param parser - The Redis command parser + * @param key - The key containing the array + * @param options - Optional parameters + * @param options.path - Path to the array in the JSON document + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.ARRLEN"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - } - [Symbol.iterator]() { - return this.entries(); - } - find(fn, getOptions) { - for (const i2 of this.indexes()) { - const v2 = this.valList[i2]; - const value = this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; - if (value === void 0) continue; - if (fn(value, this.keyList[i2], this)) { - return this.get(this.keyList[i2], getOptions); + }, + transformReply: void 0 + }; + } +}); +var require_ARRPOP = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRPOP.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Removes and returns an element from an array in a JSON document. + * Returns null if the path does not exist or the value is not an array. + * + * @param parser - The Redis command parser + * @param key - The key containing the array + * @param options - Optional parameters + * @param options.path - Path to the array in the JSON document + * @param options.index - Optional index to pop from. Default is -1 (last element) + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.ARRPOP"); + parser3.pushKey(key); + if (options2) { + parser3.push(options2.path); + if (options2.index !== void 0) { + parser3.push(options2.index.toString()); } } + }, + transformReply(reply) { + return (0, generic_transformers_1.isArrayReply)(reply) ? reply.map((item) => (0, generic_transformers_1.transformRedisJsonNullReply)(item)) : (0, generic_transformers_1.transformRedisJsonNullReply)(reply); } - forEach(fn, thisp = this) { - for (const i2 of this.indexes()) { - const v2 = this.valList[i2]; - const value = this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; - if (value === void 0) continue; - fn.call(thisp, value, this.keyList[i2], this); + }; + } +}); +var require_ARRTRIM = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/ARRTRIM.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Trims an array in a JSON document to include only elements within the specified range. + * Returns the new array length after trimming, or null if the path does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the array + * @param path - Path to the array in the JSON document + * @param start - Starting index (inclusive) + * @param stop - Ending index (inclusive) + */ + parseCommand(parser3, key, path8, start, stop) { + parser3.push("JSON.ARRTRIM"); + parser3.pushKey(key); + parser3.push(path8, start.toString(), stop.toString()); + }, + transformReply: void 0 + }; + } +}); +var require_CLEAR = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/CLEAR.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Clears container values (arrays/objects) in a JSON document. + * Returns the number of values cleared (0 or 1), or null if the path does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to the container to clear + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.CLEAR"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - } - rforEach(fn, thisp = this) { - for (const i2 of this.rindexes()) { - const v2 = this.valList[i2]; - const value = this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; - if (value === void 0) continue; - fn.call(thisp, value, this.keyList[i2], this); + }, + transformReply: void 0 + }; + } +}); +var require_DEBUG_MEMORY = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/DEBUG_MEMORY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Reports memory usage details for a JSON document value. + * Returns size in bytes of the value, or null if the key or path does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to the value to examine + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.DEBUG", "MEMORY"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - } - get prune() { - deprecatedMethod("prune", "purgeStale"); - return this.purgeStale; - } - purgeStale() { - let deleted = false; - for (const i2 of this.rindexes({ allowStale: true })) { - if (this.isStale(i2)) { - this.delete(this.keyList[i2]); - deleted = true; - } + }, + transformReply: void 0 + }; + } +}); +var require_DEL3 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/DEL.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Deletes a value from a JSON document. + * Returns the number of paths deleted (0 or 1), or null if the key does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to the value to delete + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.DEL"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - return deleted; - } - dump() { - const arr = []; - for (const i2 of this.indexes({ allowStale: true })) { - const key = this.keyList[i2]; - const v2 = this.valList[i2]; - const value = this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; - if (value === void 0) continue; - const entry = { value }; - if (this.ttls) { - entry.ttl = this.ttls[i2]; - const age = perf.now() - this.starts[i2]; - entry.start = Math.floor(Date.now() - age); - } - if (this.sizes) { - entry.size = this.sizes[i2]; - } - arr.unshift([key, entry]); + }, + transformReply: void 0 + }; + } +}); +var require_FORGET = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/FORGET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Alias for JSON.DEL - Deletes a value from a JSON document. + * Returns the number of paths deleted (0 or 1), or null if the key does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to the value to delete + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.FORGET"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - return arr; - } - load(arr) { - this.clear(); - for (const [key, entry] of arr) { - if (entry.start) { - const age = Date.now() - entry.start; - entry.start = perf.now() - age; - } - this.set(key, entry.value, entry); + }, + transformReply: void 0 + }; + } +}); +var require_GET2 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/GET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Gets values from a JSON document. + * Returns the value at the specified path, or null if the key or path does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path(s) to the value(s) to retrieve + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.GET"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.pushVariadic(options2.path); } + }, + transformReply: generic_transformers_1.transformRedisJsonNullReply + }; + } +}); +var require_MERGE3 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/MERGE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Merges a given JSON value into a JSON document. + * Returns OK on success, or null if the key does not exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param path - Path to merge into + * @param value - JSON value to merge + */ + parseCommand(parser3, key, path8, value) { + parser3.push("JSON.MERGE"); + parser3.pushKey(key); + parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(value)); + }, + transformReply: void 0 + }; + } +}); +var require_MGET2 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/MGET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets values at a specific path from multiple JSON documents. + * Returns an array of values at the path from each key, null for missing keys/paths. + * + * @param parser - The Redis command parser + * @param keys - Array of keys containing JSON documents + * @param path - Path to retrieve from each document + */ + parseCommand(parser3, keys, path8) { + parser3.push("JSON.MGET"); + parser3.pushKeys(keys); + parser3.push(path8); + }, + transformReply(reply) { + return reply.map((json) => (0, generic_transformers_1.transformRedisJsonNullReply)(json)); } - dispose(_v, _k, _reason) { - } - set(k, v2, { - ttl = this.ttl, - start, - noDisposeOnSet = this.noDisposeOnSet, - size = 0, - sizeCalculation = this.sizeCalculation, - noUpdateTTL = this.noUpdateTTL, - status - } = {}) { - size = this.requireSize(k, v2, size, sizeCalculation); - if (this.maxEntrySize && size > this.maxEntrySize) { - if (status) { - status.set = "miss"; - status.maxEntrySizeExceeded = true; - } - this.delete(k); - return this; + }; + } +}); +var require_MSET2 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/MSET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Sets multiple JSON values in multiple documents. + * Returns OK on success. + * + * @param parser - The Redis command parser + * @param items - Array of objects containing key, path, and value to set + * @param items[].key - The key containing the JSON document + * @param items[].path - Path in the document to set + * @param items[].value - JSON value to set at the path + */ + parseCommand(parser3, items) { + parser3.push("JSON.MSET"); + for (let i2 = 0; i2 < items.length; i2++) { + parser3.pushKey(items[i2].key); + parser3.push(items[i2].path, (0, generic_transformers_1.transformRedisJsonArgument)(items[i2].value)); } - let index = this.size === 0 ? void 0 : this.keyMap.get(k); - if (index === void 0) { - index = this.newIndex(); - this.keyList[index] = k; - this.valList[index] = v2; - this.keyMap.set(k, index); - this.next[this.tail] = index; - this.prev[index] = this.tail; - this.tail = index; - this.size++; - this.addItemSize(index, size, status); - if (status) { - status.set = "add"; - } - noUpdateTTL = false; - } else { - this.moveToTail(index); - const oldVal = this.valList[index]; - if (v2 !== oldVal) { - if (this.isBackgroundFetch(oldVal)) { - oldVal.__abortController.abort(new Error("replaced")); - } else { - if (!noDisposeOnSet) { - this.dispose(oldVal, k, "set"); - if (this.disposeAfter) { - this.disposed.push([oldVal, k, "set"]); - } - } - } - this.removeItemSize(index); - this.valList[index] = v2; - this.addItemSize(index, size, status); - if (status) { - status.set = "replace"; - const oldValue = oldVal && this.isBackgroundFetch(oldVal) ? oldVal.__staleWhileFetching : oldVal; - if (oldValue !== void 0) status.oldValue = oldValue; - } - } else if (status) { - status.set = "update"; - } + }, + transformReply: void 0 + }; + } +}); +var require_NUMINCRBY = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/NUMINCRBY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Increments a numeric value stored in a JSON document by a given number. + * Returns the value after increment, or null if the key/path doesn't exist or value is not numeric. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param path - Path to the numeric value + * @param by - Amount to increment by + */ + parseCommand(parser3, key, path8, by) { + parser3.push("JSON.NUMINCRBY"); + parser3.pushKey(key); + parser3.push(path8, by.toString()); + }, + transformReply: { + 2: (reply) => { + return JSON.parse(reply.toString()); + }, + 3: void 0 + } + }; + } +}); +var require_NUMMULTBY = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/NUMMULTBY.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var NUMINCRBY_1 = __importDefault(require_NUMINCRBY()); + exports2.default = { + IS_READ_ONLY: false, + /** + * Multiplies a numeric value stored in a JSON document by a given number. + * Returns the value after multiplication, or null if the key/path doesn't exist or value is not numeric. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param path - Path to the numeric value + * @param by - Amount to multiply by + */ + parseCommand(parser3, key, path8, by) { + parser3.push("JSON.NUMMULTBY"); + parser3.pushKey(key); + parser3.push(path8, by.toString()); + }, + transformReply: NUMINCRBY_1.default.transformReply + }; + } +}); +var require_OBJKEYS = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/OBJKEYS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Returns the keys in the object stored in a JSON document. + * Returns array of keys, array of arrays for multiple paths, or null if path doesn't exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to the object to examine + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.OBJKEYS"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - if (ttl !== 0 && this.ttl === 0 && !this.ttls) { - this.initializeTTLTracking(); + }, + transformReply: void 0 + }; + } +}); +var require_OBJLEN = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/OBJLEN.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the number of keys in the object stored in a JSON document. + * Returns length of object, array of lengths for multiple paths, or null if path doesn't exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to the object to examine + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.OBJLEN"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - if (!noUpdateTTL) { - this.setItemTTL(index, ttl, start); + }, + transformReply: void 0 + }; + } +}); +var require_SET2 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/SET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Sets a JSON value at a specific path in a JSON document. + * Returns OK on success, or null if condition (NX/XX) is not met. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param path - Path in the document to set + * @param json - JSON value to set at the path + * @param options - Optional parameters + * @param options.condition - Set condition: NX (only if doesn't exist) or XX (only if exists) + * @deprecated options.NX - Use options.condition instead + * @deprecated options.XX - Use options.condition instead + */ + parseCommand(parser3, key, path8, json, options2) { + parser3.push("JSON.SET"); + parser3.pushKey(key); + parser3.push(path8, (0, generic_transformers_1.transformRedisJsonArgument)(json)); + if (options2?.condition) { + parser3.push(options2?.condition); + } else if (options2?.NX) { + parser3.push("NX"); + } else if (options2?.XX) { + parser3.push("XX"); } - this.statusTTL(status, index); - if (this.disposeAfter) { - while (this.disposed.length) { - this.disposeAfter(...this.disposed.shift()); - } + }, + transformReply: void 0 + }; + } +}); +var require_STRAPPEND = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/STRAPPEND.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Appends a string to a string value stored in a JSON document. + * Returns new string length after append, or null if the path doesn't exist or value is not a string. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param append - String to append + * @param options - Optional parameters + * @param options.path - Path to the string value + */ + parseCommand(parser3, key, append, options2) { + parser3.push("JSON.STRAPPEND"); + parser3.pushKey(key); + if (options2?.path !== void 0) { + parser3.push(options2.path); } - return this; - } - newIndex() { - if (this.size === 0) { - return this.tail; + parser3.push((0, generic_transformers_1.transformRedisJsonArgument)(append)); + }, + transformReply: void 0 + }; + } +}); +var require_STRLEN2 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/STRLEN.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the length of a string value stored in a JSON document. + * Returns string length, array of lengths for multiple paths, or null if path doesn't exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to the string value + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.STRLEN"); + parser3.pushKey(key); + if (options2?.path) { + parser3.push(options2.path); } - if (this.size === this.max && this.max !== 0) { - return this.evict(false); + }, + transformReply: void 0 + }; + } +}); +var require_TOGGLE = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/TOGGLE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Toggles a boolean value stored in a JSON document. + * Returns 1 if value was toggled to true, 0 if toggled to false, or null if path doesn't exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param path - Path to the boolean value + */ + parseCommand(parser3, key, path8) { + parser3.push("JSON.TOGGLE"); + parser3.pushKey(key); + parser3.push(path8); + }, + transformReply: void 0 + }; + } +}); +var require_TYPE2 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/TYPE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Returns the type of JSON value at a specific path in a JSON document. + * Returns the type as a string, array of types for multiple paths, or null if path doesn't exist. + * + * @param parser - The Redis command parser + * @param key - The key containing the JSON document + * @param options - Optional parameters + * @param options.path - Path to examine + */ + parseCommand(parser3, key, options2) { + parser3.push("JSON.TYPE"); + parser3.pushKey(key); + if (options2?.path) { + parser3.push(options2.path); } - if (this.free.length !== 0) { - return this.free.pop(); + }, + transformReply: { + 2: void 0, + // TODO: RESP3 wraps the response in another array, but only returns 1 + 3: (reply) => { + return reply[0]; } - return this.initialFill++; } - pop() { - if (this.size) { - const val = this.valList[this.head]; - this.evict(true); - return val; - } + }; + } +}); +var require_commands4 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/commands/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transformRedisJsonNullReply = exports2.transformRedisJsonReply = exports2.transformRedisJsonArgument = void 0; + var ARRAPPEND_1 = __importDefault(require_ARRAPPEND()); + var ARRINDEX_1 = __importDefault(require_ARRINDEX()); + var ARRINSERT_1 = __importDefault(require_ARRINSERT()); + var ARRLEN_1 = __importDefault(require_ARRLEN()); + var ARRPOP_1 = __importDefault(require_ARRPOP()); + var ARRTRIM_1 = __importDefault(require_ARRTRIM()); + var CLEAR_1 = __importDefault(require_CLEAR()); + var DEBUG_MEMORY_1 = __importDefault(require_DEBUG_MEMORY()); + var DEL_1 = __importDefault(require_DEL3()); + var FORGET_1 = __importDefault(require_FORGET()); + var GET_1 = __importDefault(require_GET2()); + var MERGE_1 = __importDefault(require_MERGE3()); + var MGET_1 = __importDefault(require_MGET2()); + var MSET_1 = __importDefault(require_MSET2()); + var NUMINCRBY_1 = __importDefault(require_NUMINCRBY()); + var NUMMULTBY_1 = __importDefault(require_NUMMULTBY()); + var OBJKEYS_1 = __importDefault(require_OBJKEYS()); + var OBJLEN_1 = __importDefault(require_OBJLEN()); + var SET_1 = __importDefault(require_SET2()); + var STRAPPEND_1 = __importDefault(require_STRAPPEND()); + var STRLEN_1 = __importDefault(require_STRLEN2()); + var TOGGLE_1 = __importDefault(require_TOGGLE()); + var TYPE_1 = __importDefault(require_TYPE2()); + var generic_transformers_1 = require_generic_transformers(); + Object.defineProperty(exports2, "transformRedisJsonArgument", { enumerable: true, get: function() { + return generic_transformers_1.transformRedisJsonArgument; + } }); + Object.defineProperty(exports2, "transformRedisJsonReply", { enumerable: true, get: function() { + return generic_transformers_1.transformRedisJsonReply; + } }); + Object.defineProperty(exports2, "transformRedisJsonNullReply", { enumerable: true, get: function() { + return generic_transformers_1.transformRedisJsonNullReply; + } }); + exports2.default = { + ARRAPPEND: ARRAPPEND_1.default, + arrAppend: ARRAPPEND_1.default, + ARRINDEX: ARRINDEX_1.default, + arrIndex: ARRINDEX_1.default, + ARRINSERT: ARRINSERT_1.default, + arrInsert: ARRINSERT_1.default, + ARRLEN: ARRLEN_1.default, + arrLen: ARRLEN_1.default, + ARRPOP: ARRPOP_1.default, + arrPop: ARRPOP_1.default, + ARRTRIM: ARRTRIM_1.default, + arrTrim: ARRTRIM_1.default, + CLEAR: CLEAR_1.default, + clear: CLEAR_1.default, + DEBUG_MEMORY: DEBUG_MEMORY_1.default, + debugMemory: DEBUG_MEMORY_1.default, + DEL: DEL_1.default, + del: DEL_1.default, + FORGET: FORGET_1.default, + forget: FORGET_1.default, + GET: GET_1.default, + get: GET_1.default, + MERGE: MERGE_1.default, + merge: MERGE_1.default, + MGET: MGET_1.default, + mGet: MGET_1.default, + MSET: MSET_1.default, + mSet: MSET_1.default, + NUMINCRBY: NUMINCRBY_1.default, + numIncrBy: NUMINCRBY_1.default, + /** + * @deprecated since JSON version 2.0 + */ + NUMMULTBY: NUMMULTBY_1.default, + /** + * @deprecated since JSON version 2.0 + */ + numMultBy: NUMMULTBY_1.default, + OBJKEYS: OBJKEYS_1.default, + objKeys: OBJKEYS_1.default, + OBJLEN: OBJLEN_1.default, + objLen: OBJLEN_1.default, + // RESP, + // resp: RESP, + SET: SET_1.default, + set: SET_1.default, + STRAPPEND: STRAPPEND_1.default, + strAppend: STRAPPEND_1.default, + STRLEN: STRLEN_1.default, + strLen: STRLEN_1.default, + TOGGLE: TOGGLE_1.default, + toggle: TOGGLE_1.default, + TYPE: TYPE_1.default, + type: TYPE_1.default + }; + } +}); +var require_lib3 = __commonJS({ + "node_modules/.deno/@redis+json@5.9.0/node_modules/@redis/json/dist/lib/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = void 0; + var commands_1 = require_commands4(); + Object.defineProperty(exports2, "default", { enumerable: true, get: function() { + return __importDefault(commands_1).default; + } }); + } +}); +var require_LIST2 = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/_LIST.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Lists all existing indexes in the database. + * @param parser - The command parser + */ + parseCommand(parser3) { + parser3.push("FT._LIST"); + }, + transformReply: { + 2: void 0, + 3: void 0 } - evict(free) { - const head = this.head; - const k = this.keyList[head]; - const v2 = this.valList[head]; - if (this.isBackgroundFetch(v2)) { - v2.__abortController.abort(new Error("evicted")); - } else { - this.dispose(v2, k, "evict"); - if (this.disposeAfter) { - this.disposed.push([v2, k, "evict"]); - } - } - this.removeItemSize(head); - if (free) { - this.keyList[head] = null; - this.valList[head] = null; - this.free.push(head); + }; + } +}); +var require_CREATE2 = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CREATE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.REDISEARCH_LANGUAGE = exports2.parseSchema = exports2.SCHEMA_GEO_SHAPE_COORD_SYSTEM = exports2.VAMANA_COMPRESSION_ALGORITHM = exports2.SCHEMA_VECTOR_FIELD_ALGORITHM = exports2.SCHEMA_TEXT_FIELD_PHONETIC = exports2.SCHEMA_FIELD_TYPE = void 0; + var generic_transformers_1 = require_generic_transformers(); + exports2.SCHEMA_FIELD_TYPE = { + TEXT: "TEXT", + NUMERIC: "NUMERIC", + GEO: "GEO", + TAG: "TAG", + VECTOR: "VECTOR", + GEOSHAPE: "GEOSHAPE" + }; + exports2.SCHEMA_TEXT_FIELD_PHONETIC = { + DM_EN: "dm:en", + DM_FR: "dm:fr", + FM_PT: "dm:pt", + DM_ES: "dm:es" + }; + exports2.SCHEMA_VECTOR_FIELD_ALGORITHM = { + FLAT: "FLAT", + HNSW: "HNSW", + /** + * available since 8.2 + */ + VAMANA: "SVS-VAMANA" + }; + exports2.VAMANA_COMPRESSION_ALGORITHM = { + LVQ4: "LVQ4", + LVQ8: "LVQ8", + LVQ4x4: "LVQ4x4", + LVQ4x8: "LVQ4x8", + LeanVec4x8: "LeanVec4x8", + LeanVec8x8: "LeanVec8x8" + }; + exports2.SCHEMA_GEO_SHAPE_COORD_SYSTEM = { + SPHERICAL: "SPHERICAL", + FLAT: "FLAT" + }; + function parseCommonSchemaFieldOptions(parser3, fieldOptions) { + if (fieldOptions.SORTABLE) { + parser3.push("SORTABLE"); + if (fieldOptions.SORTABLE === "UNF") { + parser3.push("UNF"); } - this.head = this.next[head]; - this.keyMap.delete(k); - this.size--; - return head; } - has(k, { updateAgeOnHas = this.updateAgeOnHas, status } = {}) { - const index = this.keyMap.get(k); - if (index !== void 0) { - if (!this.isStale(index)) { - if (updateAgeOnHas) { - this.updateItemAge(index); - } - if (status) status.has = "hit"; - this.statusTTL(status, index); - return true; - } else if (status) { - status.has = "stale"; - this.statusTTL(status, index); - } - } else if (status) { - status.has = "miss"; - } - return false; + if (fieldOptions.NOINDEX) { + parser3.push("NOINDEX"); } - // like get(), but without any LRU updating or TTL expiration - peek(k, { allowStale = this.allowStale } = {}) { - const index = this.keyMap.get(k); - if (index !== void 0 && (allowStale || !this.isStale(index))) { - const v2 = this.valList[index]; - return this.isBackgroundFetch(v2) ? v2.__staleWhileFetching : v2; + } + function parseSchema(parser3, schema) { + for (const [field, fieldOptions] of Object.entries(schema)) { + parser3.push(field); + if (typeof fieldOptions === "string") { + parser3.push(fieldOptions); + continue; } - } - backgroundFetch(k, index, options2, context) { - const v2 = index === void 0 ? void 0 : this.valList[index]; - if (this.isBackgroundFetch(v2)) { - return v2; + if (fieldOptions.AS) { + parser3.push("AS", fieldOptions.AS); } - const ac = new AC(); - if (options2.signal) { - options2.signal.addEventListener( - "abort", - () => ac.abort(options2.signal.reason) - ); + parser3.push(fieldOptions.type); + if (fieldOptions.INDEXMISSING) { + parser3.push("INDEXMISSING"); } - const fetchOpts = { - signal: ac.signal, - options: options2, - context - }; - const cb = (v3, updateCache = false) => { - const { aborted: aborted2 } = ac.signal; - const ignoreAbort = options2.ignoreFetchAbort && v3 !== void 0; - if (options2.status) { - if (aborted2 && !updateCache) { - options2.status.fetchAborted = true; - options2.status.fetchError = ac.signal.reason; - if (ignoreAbort) options2.status.fetchAbortIgnored = true; - } else { - options2.status.fetchResolved = true; + switch (fieldOptions.type) { + case exports2.SCHEMA_FIELD_TYPE.TEXT: + if (fieldOptions.NOSTEM) { + parser3.push("NOSTEM"); } - } - if (aborted2 && !ignoreAbort && !updateCache) { - return fetchFail(ac.signal.reason); - } - if (this.valList[index] === p) { - if (v3 === void 0) { - if (p.__staleWhileFetching) { - this.valList[index] = p.__staleWhileFetching; - } else { - this.delete(k); - } - } else { - if (options2.status) options2.status.fetchUpdated = true; - this.set(k, v3, fetchOpts.options); + if (fieldOptions.WEIGHT !== void 0) { + parser3.push("WEIGHT", fieldOptions.WEIGHT.toString()); } - } - return v3; - }; - const eb = (er) => { - if (options2.status) { - options2.status.fetchRejected = true; - options2.status.fetchError = er; - } - return fetchFail(er); - }; - const fetchFail = (er) => { - const { aborted: aborted2 } = ac.signal; - const allowStaleAborted = aborted2 && options2.allowStaleOnFetchAbort; - const allowStale = allowStaleAborted || options2.allowStaleOnFetchRejection; - const noDelete = allowStale || options2.noDeleteOnFetchRejection; - if (this.valList[index] === p) { - const del = !noDelete || p.__staleWhileFetching === void 0; - if (del) { - this.delete(k); - } else if (!allowStaleAborted) { - this.valList[index] = p.__staleWhileFetching; + if (fieldOptions.PHONETIC) { + parser3.push("PHONETIC", fieldOptions.PHONETIC); } - } - if (allowStale) { - if (options2.status && p.__staleWhileFetching !== void 0) { - options2.status.returnedStale = true; + if (fieldOptions.WITHSUFFIXTRIE) { + parser3.push("WITHSUFFIXTRIE"); } - return p.__staleWhileFetching; - } else if (p.__returned === p) { - throw er; - } - }; - const pcall = (res, rej) => { - this.fetchMethod(k, v2, fetchOpts).then((v3) => res(v3), rej); - ac.signal.addEventListener("abort", () => { - if (!options2.ignoreFetchAbort || options2.allowStaleOnFetchAbort) { - res(); - if (options2.allowStaleOnFetchAbort) { - res = (v3) => cb(v3, true); - } + if (fieldOptions.INDEXEMPTY) { + parser3.push("INDEXEMPTY"); } - }); - }; - if (options2.status) options2.status.fetchDispatched = true; - const p = new Promise(pcall).then(cb, eb); - p.__abortController = ac; - p.__staleWhileFetching = v2; - p.__returned = null; - if (index === void 0) { - this.set(k, p, { ...fetchOpts.options, status: void 0 }); - index = this.keyMap.get(k); - } else { - this.valList[index] = p; - } - return p; - } - isBackgroundFetch(p) { - return p && typeof p === "object" && typeof p.then === "function" && Object.prototype.hasOwnProperty.call( - p, - "__staleWhileFetching" - ) && Object.prototype.hasOwnProperty.call(p, "__returned") && (p.__returned === p || p.__returned === null); - } - // this takes the union of get() and set() opts, because it does both - async fetch(k, { - // get options - allowStale = this.allowStale, - updateAgeOnGet = this.updateAgeOnGet, - noDeleteOnStaleGet = this.noDeleteOnStaleGet, - // set options - ttl = this.ttl, - noDisposeOnSet = this.noDisposeOnSet, - size = 0, - sizeCalculation = this.sizeCalculation, - noUpdateTTL = this.noUpdateTTL, - // fetch exclusive options - noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, - allowStaleOnFetchRejection = this.allowStaleOnFetchRejection, - ignoreFetchAbort = this.ignoreFetchAbort, - allowStaleOnFetchAbort = this.allowStaleOnFetchAbort, - fetchContext = this.fetchContext, - forceRefresh = false, - status, - signal - } = {}) { - if (!this.fetchMethod) { - if (status) status.fetch = "get"; - return this.get(k, { - allowStale, - updateAgeOnGet, - noDeleteOnStaleGet, - status - }); - } - const options2 = { - allowStale, - updateAgeOnGet, - noDeleteOnStaleGet, - ttl, - noDisposeOnSet, - size, - sizeCalculation, - noUpdateTTL, - noDeleteOnFetchRejection, - allowStaleOnFetchRejection, - allowStaleOnFetchAbort, - ignoreFetchAbort, - status, - signal - }; - let index = this.keyMap.get(k); - if (index === void 0) { - if (status) status.fetch = "miss"; - const p = this.backgroundFetch(k, index, options2, fetchContext); - return p.__returned = p; - } else { - const v2 = this.valList[index]; - if (this.isBackgroundFetch(v2)) { - const stale = allowStale && v2.__staleWhileFetching !== void 0; - if (status) { - status.fetch = "inflight"; - if (stale) status.returnedStale = true; + parseCommonSchemaFieldOptions(parser3, fieldOptions); + break; + case exports2.SCHEMA_FIELD_TYPE.NUMERIC: + case exports2.SCHEMA_FIELD_TYPE.GEO: + parseCommonSchemaFieldOptions(parser3, fieldOptions); + break; + case exports2.SCHEMA_FIELD_TYPE.TAG: + if (fieldOptions.SEPARATOR) { + parser3.push("SEPARATOR", fieldOptions.SEPARATOR); } - return stale ? v2.__staleWhileFetching : v2.__returned = v2; - } - const isStale = this.isStale(index); - if (!forceRefresh && !isStale) { - if (status) status.fetch = "hit"; - this.moveToTail(index); - if (updateAgeOnGet) { - this.updateItemAge(index); + if (fieldOptions.CASESENSITIVE) { + parser3.push("CASESENSITIVE"); } - this.statusTTL(status, index); - return v2; - } - const p = this.backgroundFetch(k, index, options2, fetchContext); - const hasStale = p.__staleWhileFetching !== void 0; - const staleVal = hasStale && allowStale; - if (status) { - status.fetch = hasStale && isStale ? "stale" : "refresh"; - if (staleVal && isStale) status.returnedStale = true; - } - return staleVal ? p.__staleWhileFetching : p.__returned = p; - } - } - get(k, { - allowStale = this.allowStale, - updateAgeOnGet = this.updateAgeOnGet, - noDeleteOnStaleGet = this.noDeleteOnStaleGet, - status - } = {}) { - const index = this.keyMap.get(k); - if (index !== void 0) { - const value = this.valList[index]; - const fetching = this.isBackgroundFetch(value); - this.statusTTL(status, index); - if (this.isStale(index)) { - if (status) status.get = "stale"; - if (!fetching) { - if (!noDeleteOnStaleGet) { - this.delete(k); - } - if (status) status.returnedStale = allowStale; - return allowStale ? value : void 0; - } else { - if (status) { - status.returnedStale = allowStale && value.__staleWhileFetching !== void 0; - } - return allowStale ? value.__staleWhileFetching : void 0; + if (fieldOptions.WITHSUFFIXTRIE) { + parser3.push("WITHSUFFIXTRIE"); } - } else { - if (status) status.get = "hit"; - if (fetching) { - return value.__staleWhileFetching; + if (fieldOptions.INDEXEMPTY) { + parser3.push("INDEXEMPTY"); + } + parseCommonSchemaFieldOptions(parser3, fieldOptions); + break; + case exports2.SCHEMA_FIELD_TYPE.VECTOR: + parser3.push(fieldOptions.ALGORITHM); + const args = []; + args.push("TYPE", fieldOptions.TYPE, "DIM", fieldOptions.DIM.toString(), "DISTANCE_METRIC", fieldOptions.DISTANCE_METRIC); + if (fieldOptions.INITIAL_CAP !== void 0) { + args.push("INITIAL_CAP", fieldOptions.INITIAL_CAP.toString()); + } + switch (fieldOptions.ALGORITHM) { + case exports2.SCHEMA_VECTOR_FIELD_ALGORITHM.FLAT: + if (fieldOptions.BLOCK_SIZE !== void 0) { + args.push("BLOCK_SIZE", fieldOptions.BLOCK_SIZE.toString()); + } + break; + case exports2.SCHEMA_VECTOR_FIELD_ALGORITHM.HNSW: + if (fieldOptions.M !== void 0) { + args.push("M", fieldOptions.M.toString()); + } + if (fieldOptions.EF_CONSTRUCTION !== void 0) { + args.push("EF_CONSTRUCTION", fieldOptions.EF_CONSTRUCTION.toString()); + } + if (fieldOptions.EF_RUNTIME !== void 0) { + args.push("EF_RUNTIME", fieldOptions.EF_RUNTIME.toString()); + } + break; + case exports2.SCHEMA_VECTOR_FIELD_ALGORITHM["VAMANA"]: + if (fieldOptions.COMPRESSION) { + args.push("COMPRESSION", fieldOptions.COMPRESSION); + } + if (fieldOptions.CONSTRUCTION_WINDOW_SIZE !== void 0) { + args.push("CONSTRUCTION_WINDOW_SIZE", fieldOptions.CONSTRUCTION_WINDOW_SIZE.toString()); + } + if (fieldOptions.GRAPH_MAX_DEGREE !== void 0) { + args.push("GRAPH_MAX_DEGREE", fieldOptions.GRAPH_MAX_DEGREE.toString()); + } + if (fieldOptions.SEARCH_WINDOW_SIZE !== void 0) { + args.push("SEARCH_WINDOW_SIZE", fieldOptions.SEARCH_WINDOW_SIZE.toString()); + } + if (fieldOptions.EPSILON !== void 0) { + args.push("EPSILON", fieldOptions.EPSILON.toString()); + } + if (fieldOptions.TRAINING_THRESHOLD !== void 0) { + args.push("TRAINING_THRESHOLD", fieldOptions.TRAINING_THRESHOLD.toString()); + } + if (fieldOptions.REDUCE !== void 0) { + args.push("REDUCE", fieldOptions.REDUCE.toString()); + } + break; } - this.moveToTail(index); - if (updateAgeOnGet) { - this.updateItemAge(index); + parser3.pushVariadicWithLength(args); + break; + case exports2.SCHEMA_FIELD_TYPE.GEOSHAPE: + if (fieldOptions.COORD_SYSTEM !== void 0) { + parser3.push("COORD_SYSTEM", fieldOptions.COORD_SYSTEM); } - return value; - } - } else if (status) { - status.get = "miss"; + break; } } - connect(p, n) { - this.prev[n] = p; - this.next[p] = n; - } - moveToTail(index) { - if (index !== this.tail) { - if (index === this.head) { - this.head = this.next[index]; - } else { - this.connect(this.prev[index], this.next[index]); - } - this.connect(this.tail, index); - this.tail = index; + } + exports2.parseSchema = parseSchema; + exports2.REDISEARCH_LANGUAGE = { + ARABIC: "Arabic", + BASQUE: "Basque", + CATALANA: "Catalan", + DANISH: "Danish", + DUTCH: "Dutch", + ENGLISH: "English", + FINNISH: "Finnish", + FRENCH: "French", + GERMAN: "German", + GREEK: "Greek", + HUNGARIAN: "Hungarian", + INDONESAIN: "Indonesian", + IRISH: "Irish", + ITALIAN: "Italian", + LITHUANIAN: "Lithuanian", + NEPALI: "Nepali", + NORWEIGAN: "Norwegian", + PORTUGUESE: "Portuguese", + ROMANIAN: "Romanian", + RUSSIAN: "Russian", + SPANISH: "Spanish", + SWEDISH: "Swedish", + TAMIL: "Tamil", + TURKISH: "Turkish", + CHINESE: "Chinese" + }; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Creates a new search index with the given schema and options. + * @param parser - The command parser + * @param index - Name of the index to create + * @param schema - Index schema defining field names and types (TEXT, NUMERIC, GEO, TAG, VECTOR, GEOSHAPE) + * @param options - Optional parameters: + * - ON: Type of container to index (HASH or JSON) + * - PREFIX: Prefixes for document keys to index + * - FILTER: Expression that filters indexed documents + * - LANGUAGE/LANGUAGE_FIELD: Default language for indexing + * - SCORE/SCORE_FIELD: Document ranking parameters + * - MAXTEXTFIELDS: Index all text fields without specifying them + * - TEMPORARY: Create a temporary index + * - NOOFFSETS/NOHL/NOFIELDS/NOFREQS: Index optimization flags + * - STOPWORDS: Custom stopword list + */ + parseCommand(parser3, index, schema, options2) { + parser3.push("FT.CREATE", index); + if (options2?.ON) { + parser3.push("ON", options2.ON); } - } - get del() { - deprecatedMethod("del", "delete"); - return this.delete; - } - delete(k) { - let deleted = false; - if (this.size !== 0) { - const index = this.keyMap.get(k); - if (index !== void 0) { - deleted = true; - if (this.size === 1) { - this.clear(); - } else { - this.removeItemSize(index); - const v2 = this.valList[index]; - if (this.isBackgroundFetch(v2)) { - v2.__abortController.abort(new Error("deleted")); - } else { - this.dispose(v2, k, "delete"); - if (this.disposeAfter) { - this.disposed.push([v2, k, "delete"]); - } - } - this.keyMap.delete(k); - this.keyList[index] = null; - this.valList[index] = null; - if (index === this.tail) { - this.tail = this.prev[index]; - } else if (index === this.head) { - this.head = this.next[index]; - } else { - this.next[this.prev[index]] = this.next[index]; - this.prev[this.next[index]] = this.prev[index]; - } - this.size--; - this.free.push(index); - } - } + (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "PREFIX", options2?.PREFIX); + if (options2?.FILTER) { + parser3.push("FILTER", options2.FILTER); } - if (this.disposed) { - while (this.disposed.length) { - this.disposeAfter(...this.disposed.shift()); - } + if (options2?.LANGUAGE) { + parser3.push("LANGUAGE", options2.LANGUAGE); } - return deleted; - } - clear() { - for (const index of this.rindexes({ allowStale: true })) { - const v2 = this.valList[index]; - if (this.isBackgroundFetch(v2)) { - v2.__abortController.abort(new Error("deleted")); - } else { - const k = this.keyList[index]; - this.dispose(v2, k, "delete"); - if (this.disposeAfter) { - this.disposed.push([v2, k, "delete"]); - } - } + if (options2?.LANGUAGE_FIELD) { + parser3.push("LANGUAGE_FIELD", options2.LANGUAGE_FIELD); } - this.keyMap.clear(); - this.valList.fill(null); - this.keyList.fill(null); - if (this.ttls) { - this.ttls.fill(0); - this.starts.fill(0); + if (options2?.SCORE) { + parser3.push("SCORE", options2.SCORE.toString()); } - if (this.sizes) { - this.sizes.fill(0); + if (options2?.SCORE_FIELD) { + parser3.push("SCORE_FIELD", options2.SCORE_FIELD); } - this.head = 0; - this.tail = 0; - this.initialFill = 1; - this.free.length = 0; - this.calculatedSize = 0; - this.size = 0; - if (this.disposed) { - while (this.disposed.length) { - this.disposeAfter(...this.disposed.shift()); - } + if (options2?.MAXTEXTFIELDS) { + parser3.push("MAXTEXTFIELDS"); } - } - get reset() { - deprecatedMethod("reset", "clear"); - return this.clear; - } - get length() { - deprecatedProperty("length", "size"); - return this.size; - } - static get AbortController() { - return AC; - } - static get AbortSignal() { - return AS; - } + if (options2?.TEMPORARY) { + parser3.push("TEMPORARY", options2.TEMPORARY.toString()); + } + if (options2?.NOOFFSETS) { + parser3.push("NOOFFSETS"); + } + if (options2?.NOHL) { + parser3.push("NOHL"); + } + if (options2?.NOFIELDS) { + parser3.push("NOFIELDS"); + } + if (options2?.NOFREQS) { + parser3.push("NOFREQS"); + } + if (options2?.SKIPINITIALSCAN) { + parser3.push("SKIPINITIALSCAN"); + } + (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "STOPWORDS", options2?.STOPWORDS); + parser3.push("SCHEMA"); + parseSchema(parser3, schema); + }, + transformReply: void 0 }; - module14.exports = LRUCache; } }); -var require_etag = __commonJS({ - "node_modules/.deno/@hapi+inert@7.1.0/node_modules/@hapi/inert/lib/etag.js"(exports2) { +var require_ALTER = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALTER.js"(exports2) { "use strict"; - var Crypto = __require2("crypto"); - var Stream = __require2("stream"); - var Util = __require2("util"); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var LruCache = require_lru_cache2(); - var internals = { - pendings: /* @__PURE__ */ new Map(), - streamEnd: Util.promisify(Stream.finished) + Object.defineProperty(exports2, "__esModule", { value: true }); + var CREATE_1 = require_CREATE2(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Alters an existing RediSearch index schema by adding new fields. + * @param parser - The command parser + * @param index - The index to alter + * @param schema - The schema definition containing new fields to add + */ + parseCommand(parser3, index, schema) { + parser3.push("FT.ALTER", index, "SCHEMA", "ADD"); + (0, CREATE_1.parseSchema)(parser3, schema); + }, + transformReply: void 0 }; - internals.computeHashed = async function(response, stat) { - const etags = response.request.server.plugins.inert._etags; - if (!etags) { - return null; + } +}); +var require_default = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/dialect/default.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.DEFAULT_DIALECT = void 0; + exports2.DEFAULT_DIALECT = "2"; + } +}); +var require_SEARCH = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SEARCH.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseSearchOptions = exports2.parseParamsArgument = void 0; + var generic_transformers_1 = require_generic_transformers(); + var default_1 = require_default(); + function parseParamsArgument(parser3, params) { + if (params) { + parser3.push("PARAMS"); + const args = []; + for (const key in params) { + if (!Object.hasOwn(params, key)) + continue; + const value = params[key]; + args.push(key, typeof value === "number" ? value.toString() : value); + } + parser3.pushVariadicWithLength(args); + } + } + exports2.parseParamsArgument = parseParamsArgument; + function parseSearchOptions(parser3, options2) { + if (options2?.VERBATIM) { + parser3.push("VERBATIM"); } - const path8 = response.source.path; - const cachekey = [path8, stat.ino, stat.size, stat.mtime.getTime()].join("-"); - const cachedEtag = etags.get(cachekey); - if (cachedEtag) { - return cachedEtag; + if (options2?.NOSTOPWORDS) { + parser3.push("NOSTOPWORDS"); } - let promise = internals.pendings.get(cachekey); - if (promise) { - return await promise; + (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "INKEYS", options2?.INKEYS); + (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "INFIELDS", options2?.INFIELDS); + (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "RETURN", options2?.RETURN); + if (options2?.SUMMARIZE) { + parser3.push("SUMMARIZE"); + if (typeof options2.SUMMARIZE === "object") { + (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "FIELDS", options2.SUMMARIZE.FIELDS); + if (options2.SUMMARIZE.FRAGS !== void 0) { + parser3.push("FRAGS", options2.SUMMARIZE.FRAGS.toString()); + } + if (options2.SUMMARIZE.LEN !== void 0) { + parser3.push("LEN", options2.SUMMARIZE.LEN.toString()); + } + if (options2.SUMMARIZE.SEPARATOR !== void 0) { + parser3.push("SEPARATOR", options2.SUMMARIZE.SEPARATOR); + } + } } - const compute = async () => { - try { - const hash3 = await internals.hashFile(response); - etags.set(cachekey, hash3); - return hash3; - } finally { - internals.pendings.delete(cachekey); + if (options2?.HIGHLIGHT) { + parser3.push("HIGHLIGHT"); + if (typeof options2.HIGHLIGHT === "object") { + (0, generic_transformers_1.parseOptionalVariadicArgument)(parser3, "FIELDS", options2.HIGHLIGHT.FIELDS); + if (options2.HIGHLIGHT.TAGS) { + parser3.push("TAGS", options2.HIGHLIGHT.TAGS.open, options2.HIGHLIGHT.TAGS.close); + } } - }; - internals.pendings.set(cachekey, promise = compute()); - return await promise; - }; - internals.hashFile = async function(response) { - const hash3 = Crypto.createHash("sha1"); - hash3.setEncoding("hex"); - const fileStream2 = response.source.file.createReadStream({ autoClose: false }); - fileStream2.pipe(hash3); - try { - await internals.streamEnd(fileStream2); - return hash3.read(); - } catch (err) { - Bounce.rethrow(err, "system"); - throw Boom5.boomify(err, { message: "Failed to hash file", data: { path: response.source.path } }); } - }; - internals.computeSimple = function(response, stat) { - const size = stat.size.toString(16); - const mtime = stat.mtime.getTime().toString(16); - return size + "-" + mtime; - }; - exports2.apply = async function(response, stat) { - const etagMethod = response.source.settings.etagMethod; - if (etagMethod === false) { - return; + if (options2?.SLOP !== void 0) { + parser3.push("SLOP", options2.SLOP.toString()); } - let etag; - if (etagMethod === "simple") { - etag = internals.computeSimple(response, stat); - } else { - etag = await internals.computeHashed(response, stat); + if (options2?.TIMEOUT !== void 0) { + parser3.push("TIMEOUT", options2.TIMEOUT.toString()); } - if (etag !== null) { - response.etag(etag, { vary: true }); + if (options2?.INORDER) { + parser3.push("INORDER"); } - }; - exports2.Cache = LruCache; - } -}); -var require_fs = __commonJS({ - "node_modules/.deno/@hapi+inert@7.1.0/node_modules/@hapi/inert/lib/fs.js"(exports2) { - "use strict"; - var Fs = __require2("fs"); - var Util = __require2("util"); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var internals = { - methods: { - promised: ["open", "close", "fstat", "readdir"], - raw: ["createReadStream"] - }, - notFound: /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR"]) - }; - exports2.File = class { - constructor(path8) { - this.path = path8; - this.fd = null; + if (options2?.LANGUAGE) { + parser3.push("LANGUAGE", options2.LANGUAGE); } - async open(mode) { - Hoek.assert(this.fd === null); - try { - this.fd = await exports2.open(this.path, mode); - } catch (err) { - const data = { path: this.path }; - if (this.path.indexOf("\0") !== -1 || internals.notFound.has(err.code)) { - throw Boom5.notFound(null, data); - } - if (err.code === "EACCES" || err.code === "EPERM") { - data.code = err.code; - throw Boom5.forbidden(null, data); - } - throw Boom5.boomify(err, { message: "Failed to open file", data }); - } + if (options2?.EXPANDER) { + parser3.push("EXPANDER", options2.EXPANDER); } - close() { - if (this.fd !== null) { - Bounce.background(exports2.close(this.fd)); - this.fd = null; - } + if (options2?.SCORER) { + parser3.push("SCORER", options2.SCORER); } - async stat() { - Hoek.assert(this.fd !== null); - try { - const stat = await exports2.fstat(this.fd); - if (stat.isDirectory()) { - throw Boom5.forbidden(null, { code: "EISDIR", path: this.path }); + if (options2?.SORTBY) { + parser3.push("SORTBY"); + if (typeof options2.SORTBY === "string" || options2.SORTBY instanceof Buffer) { + parser3.push(options2.SORTBY); + } else { + parser3.push(options2.SORTBY.BY); + if (options2.SORTBY.DIRECTION) { + parser3.push(options2.SORTBY.DIRECTION); } - return stat; - } catch (err) { - this.close(this.fd); - Bounce.rethrow(err, ["boom", "system"]); - throw Boom5.boomify(err, { message: "Failed to stat file", data: { path: this.path } }); } } - async openStat(mode) { - await this.open(mode); - return this.stat(); + if (options2?.LIMIT) { + parser3.push("LIMIT", options2.LIMIT.from.toString(), options2.LIMIT.size.toString()); + } + parseParamsArgument(parser3, options2?.PARAMS); + if (options2?.DIALECT) { + parser3.push("DIALECT", options2.DIALECT.toString()); + } else { + parser3.push("DIALECT", default_1.DEFAULT_DIALECT); + } + } + exports2.parseSearchOptions = parseSearchOptions; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Searches a RediSearch index with the given query. + * @param parser - The command parser + * @param index - The index name to search + * @param query - The text query to search. For syntax, see https://redis.io/docs/stack/search/reference/query_syntax + * @param options - Optional search parameters including: + * - VERBATIM: do not try to use stemming for query expansion + * - NOSTOPWORDS: do not filter stopwords from the query + * - INKEYS/INFIELDS: restrict the search to specific keys/fields + * - RETURN: limit which fields are returned + * - SUMMARIZE/HIGHLIGHT: create search result highlights + * - LIMIT: pagination control + * - SORTBY: sort results by a specific field + * - PARAMS: bind parameters to the query + */ + parseCommand(parser3, index, query, options2) { + parser3.push("FT.SEARCH", index, query); + parseSearchOptions(parser3, options2); + }, + transformReply: { + 2: (reply) => { + const withoutDocuments = reply.length > 2 && !Array.isArray(reply[2]); + const documents = []; + let i2 = 1; + while (i2 < reply.length) { + documents.push({ + id: reply[i2++], + value: withoutDocuments ? /* @__PURE__ */ Object.create(null) : documentValue(reply[i2++]) + }); + } + return { + total: reply[0], + documents + }; + }, + 3: void 0 + }, + unstableResp3: true + }; + function documentValue(tuples) { + const message = /* @__PURE__ */ Object.create(null); + if (!tuples) { + return message; } - createReadStream(options2) { - Hoek.assert(this.fd !== null); - options2 = Object.assign({ fd: this.fd, start: 0 }, options2); - const stream = exports2.createReadStream(this.path, options2); - if (options2.autoClose !== false) { - this.fd = null; + let i2 = 0; + while (i2 < tuples.length) { + const key = tuples[i2++], value = tuples[i2++]; + if (key === "$") { + try { + Object.assign(message, JSON.parse(value)); + continue; + } catch { + } } - return stream; + message[key] = value; } + return message; + } + } +}); +var require_AGGREGATE = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/AGGREGATE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseAggregateOptions = exports2.FT_AGGREGATE_GROUP_BY_REDUCERS = exports2.FT_AGGREGATE_STEPS = void 0; + var SEARCH_1 = require_SEARCH(); + var generic_transformers_1 = require_generic_transformers(); + var default_1 = require_default(); + exports2.FT_AGGREGATE_STEPS = { + GROUPBY: "GROUPBY", + SORTBY: "SORTBY", + APPLY: "APPLY", + LIMIT: "LIMIT", + FILTER: "FILTER" }; - for (const method of internals.methods.raw) { - exports2[method] = Fs[method].bind(Fs); - } - for (const method of internals.methods.promised) { - exports2[method] = Util.promisify(Fs[method]); - } - } -}); -var require_file2 = __commonJS({ - "node_modules/.deno/@hapi+inert@7.1.0/node_modules/@hapi/inert/lib/file.js"(exports2) { - "use strict"; - var Path = __require2("path"); - var Ammo = require_lib32(); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var Validate = require_lib9(); - var Etag = require_etag(); - var Fs = require_fs(); - var internals = {}; - internals.defaultMap = { - gzip: ".gz" - }; - internals.schema = Validate.alternatives([ - Validate.string(), - Validate.func(), - Validate.object({ - path: Validate.alternatives(Validate.string(), Validate.func()).required(), - confine: Validate.alternatives(Validate.string(), Validate.boolean()).default(true), - filename: Validate.string(), - mode: Validate.string().valid("attachment", "inline").allow(false), - lookupCompressed: Validate.boolean(), - lookupMap: Validate.object().min(1).pattern(/.+/, Validate.string()), - etagMethod: Validate.string().valid("hash", "simple").allow(false), - start: Validate.number().integer().min(0).default(0), - end: Validate.number().integer().min(Validate.ref("start")) - }).with("filename", "mode") - ]); - exports2.handler = function(route2, options2) { - let settings = Validate.attempt(options2, internals.schema, "Invalid file handler options (" + route2.path + ")"); - settings = typeof options2 !== "object" ? { path: options2, confine: "." } : settings; - settings.confine = settings.confine === true ? "." : settings.confine; - Hoek.assert(typeof settings.path !== "string" || settings.path[settings.path.length - 1] !== "/", "File path cannot end with a '/':", route2.path); - const handler = (request) => { - const path8 = typeof settings.path === "function" ? settings.path(request) : settings.path; - return exports2.response(path8, settings, request); - }; - return handler; + exports2.FT_AGGREGATE_GROUP_BY_REDUCERS = { + COUNT: "COUNT", + COUNT_DISTINCT: "COUNT_DISTINCT", + COUNT_DISTINCTISH: "COUNT_DISTINCTISH", + SUM: "SUM", + MIN: "MIN", + MAX: "MAX", + AVG: "AVG", + STDDEV: "STDDEV", + QUANTILE: "QUANTILE", + TOLIST: "TOLIST", + FIRST_VALUE: "FIRST_VALUE", + RANDOM_SAMPLE: "RANDOM_SAMPLE" }; - exports2.load = function(path8, request, options2) { - const response = exports2.response(path8, options2, request, true); - return internals.prepare(response); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: false, + /** + * Performs an aggregation query on a RediSearch index. + * @param parser - The command parser + * @param index - The index name to query + * @param query - The text query to use as filter, use * to indicate no filtering + * @param options - Optional parameters for aggregation: + * - VERBATIM: disable stemming in query evaluation + * - LOAD: specify fields to load from documents + * - STEPS: sequence of aggregation steps (GROUPBY, SORTBY, APPLY, LIMIT, FILTER) + * - PARAMS: bind parameters for query evaluation + * - TIMEOUT: maximum time to run the query + */ + parseCommand(parser3, index, query, options2) { + parser3.push("FT.AGGREGATE", index, query); + return parseAggregateOptions(parser3, options2); + }, + transformReply: { + 2: (rawReply, preserve, typeMapping) => { + const results = []; + for (let i2 = 1; i2 < rawReply.length; i2++) { + results.push((0, generic_transformers_1.transformTuplesReply)(rawReply[i2], preserve, typeMapping)); + } + return { + // https://redis.io/docs/latest/commands/ft.aggregate/#return + // FT.AGGREGATE returns an array reply where each row is an array reply and represents a single aggregate result. + // The integer reply at position 1 does not represent a valid value. + total: Number(rawReply[0]), + results + }; + }, + 3: void 0 + }, + unstableResp3: true }; - exports2.response = function(path8, options2, request, _preloaded) { - Hoek.assert(!options2.mode || ["attachment", "inline"].indexOf(options2.mode) !== -1, "options.mode must be either false, attachment, or inline"); - if (options2.confine) { - const confineDir = Path.resolve(request.route.settings.files.relativeTo, options2.confine); - path8 = Path.isAbsolute(path8) ? Path.normalize(path8) : Path.join(confineDir, path8); - if (path8.lastIndexOf(confineDir, 0) !== 0) { - path8 = null; - } - } else { - path8 = Path.isAbsolute(path8) ? Path.normalize(path8) : Path.join(request.route.settings.files.relativeTo, path8); + function parseAggregateOptions(parser3, options2) { + if (options2?.VERBATIM) { + parser3.push("VERBATIM"); } - const source = { - path: path8, - settings: options2, - stat: null, - file: null - }; - const prepare = _preloaded ? null : internals.prepare; - return request.generateResponse(source, { variety: "file", marshal: internals.marshal, prepare, close: internals.close }); - }; - internals.prepare = async function(response) { - const { request, source } = response; - const { settings, path: path8 } = source; - if (path8 === null) { - throw Boom5.forbidden(null, { code: "EACCES" }); + if (options2?.ADDSCORES) { + parser3.push("ADDSCORES"); } - const file = source.file = new Fs.File(path8); - try { - const stat = await file.openStat("r"); - const start = settings.start ?? 0; - if (settings.end !== void 0) { - response.bytes(settings.end - start + 1); + if (options2?.LOAD) { + const args = []; + if (Array.isArray(options2.LOAD)) { + for (const load of options2.LOAD) { + pushLoadField(args, load); + } } else { - response.bytes(stat.size - start); - } - if (!response.headers["content-type"]) { - response.type(request.server.mime.path(path8).type ?? "application/octet-stream"); - } - response.header("last-modified", stat.mtime.toUTCString()); - if (settings.mode) { - const fileName = settings.filename ?? Path.basename(path8); - response.header("content-disposition", settings.mode + "; filename=" + encodeURIComponent(fileName)); + pushLoadField(args, options2.LOAD); } - await Etag.apply(response, stat); - return response; - } catch (err) { - internals.close(response); - throw err; + parser3.push("LOAD"); + parser3.pushVariadicWithLength(args); } - }; - internals.marshal = async function(response) { - const { request, source } = response; - const { settings } = source; - if (settings.lookupCompressed && !settings.start && settings.end === void 0 && request.server.settings.compression !== false) { - const lookupMap = settings.lookupMap ?? internals.defaultMap; - const encoding = request.info.acceptEncoding; - const extension = lookupMap.hasOwnProperty(encoding) ? lookupMap[encoding] : null; - if (extension) { - const precompressed = new Fs.File(`${source.path}${extension}`); - try { - var stat = await precompressed.openStat("r"); - } catch (err) { - precompressed.close(); - Bounce.ignore(err, "boom"); - } - if (stat) { - source.file.close(); - source.file = precompressed; - response.bytes(stat.size); - response.header("content-encoding", encoding); - response.vary("accept-encoding"); - } - } - } - return internals.createStream(response); - }; - internals.addContentRange = function(response) { - const { request } = response; - let range = null; - if (request.route.settings.response.ranges) { - const length2 = response.headers["content-length"]; - if (request.headers.range && length2) { - if (!request.headers["if-range"] || request.headers["if-range"] === response.headers.etag) { - const mime = request.server.mime.type(response.headers["content-type"] || "application/octet-stream"); - const encoding = request.server.settings.compression && mime.compressible && !response.headers["content-encoding"] ? request.info.acceptEncoding : null; - if (encoding === "identity" || !encoding) { - const ranges = Ammo.header(request.headers.range, length2); - if (!ranges) { - const error2 = Boom5.rangeNotSatisfiable(); - error2.output.headers["content-range"] = "bytes */" + length2; - throw error2; + if (options2?.TIMEOUT !== void 0) { + parser3.push("TIMEOUT", options2.TIMEOUT.toString()); + } + if (options2?.STEPS) { + for (const step of options2.STEPS) { + parser3.push(step.type); + switch (step.type) { + case exports2.FT_AGGREGATE_STEPS.GROUPBY: + if (!step.properties) { + parser3.push("0"); + } else { + parser3.pushVariadicWithLength(step.properties); + } + if (Array.isArray(step.REDUCE)) { + for (const reducer of step.REDUCE) { + parseGroupByReducer(parser3, reducer); + } + } else { + parseGroupByReducer(parser3, step.REDUCE); } - if (ranges.length === 1) { - range = ranges[0]; - response.code(206); - response.bytes(range.to - range.from + 1); - response.header("content-range", "bytes " + range.from + "-" + range.to + "/" + length2); + break; + case exports2.FT_AGGREGATE_STEPS.SORTBY: + const args = []; + if (Array.isArray(step.BY)) { + for (const by of step.BY) { + pushSortByProperty(args, by); + } + } else { + pushSortByProperty(args, step.BY); } - } + if (step.MAX) { + args.push("MAX", step.MAX.toString()); + } + parser3.pushVariadicWithLength(args); + break; + case exports2.FT_AGGREGATE_STEPS.APPLY: + parser3.push(step.expression, "AS", step.AS); + break; + case exports2.FT_AGGREGATE_STEPS.LIMIT: + parser3.push(step.from.toString(), step.size.toString()); + break; + case exports2.FT_AGGREGATE_STEPS.FILTER: + parser3.push(step.expression); + break; } } - response.header("accept-ranges", "bytes"); } - return range; - }; - internals.createStream = function(response) { - const { settings, file } = response.source; - Hoek.assert(file !== null); - const range = internals.addContentRange(response); - const options2 = { - start: settings.start ?? 0, - end: settings.end - }; - if (range) { - options2.end = range.to + options2.start; - options2.start = range.from + options2.start; - } - return file.createReadStream(options2); - }; - internals.close = function(response) { - const { source } = response; - if (source.file !== null) { - source.file.close(); - source.file = null; - } - }; - } -}); -var require_directory = __commonJS({ - "node_modules/.deno/@hapi+inert@7.1.0/node_modules/@hapi/inert/lib/directory.js"(exports2) { - "use strict"; - var Path = __require2("path"); - var Boom5 = require_lib2(); - var Bounce = require_lib12(); - var Hoek = require_lib(); - var Validate = require_lib9(); - var File2 = require_file2(); - var Fs = require_fs(); - var internals = {}; - internals.schema = Validate.object({ - path: Validate.alternatives(Validate.array().items(Validate.string()).single(), Validate.func()).required(), - index: Validate.alternatives(Validate.boolean(), Validate.array().items(Validate.string()).single()).default(true), - listing: Validate.boolean(), - showHidden: Validate.boolean(), - redirectToSlash: Validate.boolean(), - lookupCompressed: Validate.boolean(), - lookupMap: Validate.object().min(1).pattern(/.+/, Validate.string()), - etagMethod: Validate.string().valid("hash", "simple").allow(false), - defaultExtension: Validate.string().alphanum() - }); - internals.resolvePathOption = function(result) { - if (result instanceof Error) { - throw result; - } - if (typeof result === "string") { - return [result]; + (0, SEARCH_1.parseParamsArgument)(parser3, options2?.PARAMS); + if (options2?.DIALECT) { + parser3.push("DIALECT", options2.DIALECT.toString()); + } else { + parser3.push("DIALECT", default_1.DEFAULT_DIALECT); } - if (Array.isArray(result)) { - return result; + } + exports2.parseAggregateOptions = parseAggregateOptions; + function pushLoadField(args, toLoad) { + if (typeof toLoad === "string" || toLoad instanceof Buffer) { + args.push(toLoad); + } else { + args.push(toLoad.identifier); + if (toLoad.AS) { + args.push("AS", toLoad.AS); + } } - throw Boom5.internal("Invalid path function"); - }; - exports2.handler = function(route2, options2) { - const settings = Validate.attempt(options2, internals.schema, "Invalid directory handler options (" + route2.path + ")"); - Hoek.assert(route2.path[route2.path.length - 1] === "}", "The route path for a directory handler must end with a parameter:", route2.path); - const paramName = /\w+/.exec(route2.path.slice(route2.path.lastIndexOf("{")))[0]; - const basePath = route2.settings.files.relativeTo; - const normalized = Array.isArray(settings.path) ? settings.path : null; - const indexNames = settings.index === true ? ["index.html"] : settings.index || []; - const handler = async (request, reply) => { - const paths = normalized ?? internals.resolvePathOption(settings.path.call(null, request)); - const selection = request.params[paramName] ?? ""; - if (Path.isAbsolute(selection)) { - throw Boom5.notFound(null, {}); - } - if (selection && !settings.showHidden && internals.isFileHidden(selection)) { - throw Boom5.notFound(null, {}); - } - if (!selection && (request.server.settings.router.stripTrailingSlash || !request.path.endsWith("/"))) { - request.path += "/"; - } - const resource = request.path; - const hasTrailingSlash = resource.endsWith("/"); - const fileOptions = { - confine: null, - lookupCompressed: settings.lookupCompressed, - lookupMap: settings.lookupMap, - etagMethod: settings.etagMethod - }; - const each = async (baseDir) => { - fileOptions.confine = baseDir; - let path8 = selection; - let error2; - try { - return await File2.load(path8, request, fileOptions); - } catch (err) { - Bounce.ignore(err, "boom"); - error2 = err; - } - if (internals.isNotFound(error2)) { - if (!settings.defaultExtension) { - throw error2; - } - if (hasTrailingSlash) { - path8 = path8.slice(0, -1); - } - return await File2.load(path8 + "." + settings.defaultExtension, request, fileOptions); - } - if (internals.isDirectory(error2)) { - if (settings.redirectToSlash !== false && // Defaults to true - !request.server.settings.router.stripTrailingSlash && !hasTrailingSlash) { - return reply.redirect(resource + "/"); - } - for (const indexName of indexNames) { - const indexFile = Path.join(path8, indexName); - try { - return await File2.load(indexFile, request, fileOptions); - } catch (err) { - Bounce.ignore(err, "boom"); - if (!internals.isNotFound(err)) { - throw Boom5.internal(indexName + " is a directory", err); - } + } + function parseGroupByReducer(parser3, reducer) { + parser3.push("REDUCE", reducer.type); + switch (reducer.type) { + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT: + parser3.push("0"); + break; + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCT: + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.COUNT_DISTINCTISH: + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.SUM: + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.MIN: + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.MAX: + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.AVG: + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.STDDEV: + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.TOLIST: + parser3.push("1", reducer.property); + break; + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.QUANTILE: + parser3.push("2", reducer.property, reducer.quantile.toString()); + break; + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.FIRST_VALUE: { + const args = [reducer.property]; + if (reducer.BY) { + args.push("BY"); + if (typeof reducer.BY === "string" || reducer.BY instanceof Buffer) { + args.push(reducer.BY); + } else { + args.push(reducer.BY.property); + if (reducer.BY.direction) { + args.push(reducer.BY.direction); } } - if (settings.listing) { - return internals.generateListing(Path.join(basePath, baseDir, path8), resource, selection, hasTrailingSlash, settings, request); - } - } - throw error2; - }; - for (let i2 = 0; i2 < paths.length; ++i2) { - try { - return await each(paths[i2]); - } catch (err) { - Bounce.ignore(err, "boom"); - if (!internals.isNotFound(err) || i2 === paths.length - 1) { - throw err; - } } + parser3.pushVariadicWithLength(args); + break; } - throw Boom5.notFound(null, {}); - }; - return handler; - }; - internals.generateListing = async function(path8, resource, selection, hasTrailingSlash, settings, request) { - let files; - try { - files = await Fs.readdir(path8); - } catch (err) { - Bounce.rethrow(err, "system"); - throw Boom5.internal("Error accessing directory", err); + case exports2.FT_AGGREGATE_GROUP_BY_REDUCERS.RANDOM_SAMPLE: + parser3.push("2", reducer.property, reducer.sampleSize.toString()); + break; } - resource = decodeURIComponent(resource); - const display = Hoek.escapeHtml(resource); - let html = "" + display + "

Directory: " + display + "

    "; - if (selection) { - const parent = resource.substring(0, resource.lastIndexOf("/", resource.length - (hasTrailingSlash ? 2 : 1))) + "/"; - html = html + '
  • Parent Directory
  • '; + if (reducer.AS) { + parser3.push("AS", reducer.AS); } - for (const file of files) { - if (settings.showHidden || !internals.isFileHidden(file)) { - html = html + '
  • ' + Hoek.escapeHtml(file) + "
  • "; + } + function pushSortByProperty(args, sortBy) { + if (typeof sortBy === "string" || sortBy instanceof Buffer) { + args.push(sortBy); + } else { + args.push(sortBy.BY); + if (sortBy.DIRECTION) { + args.push(sortBy.DIRECTION); } } - html = html + "
"; - return request.generateResponse(html); - }; - internals.isFileHidden = function(path8) { - return /(^|[\\\/])\.([^.\\\/]|\.[^\\\/])/.test(path8); - }; - internals.pathEncode = function(path8) { - return encodeURIComponent(path8).replace(/%2F/g, "/").replace(/%5C/g, "\\"); - }; - internals.isNotFound = function(boom) { - return boom.output.statusCode === 404; - }; - internals.isDirectory = function(boom) { - return boom.output.statusCode === 403 && boom.data.code === "EISDIR"; - }; + } } }); -var require_package5 = __commonJS({ - "node_modules/.deno/@hapi+inert@7.1.0/node_modules/@hapi/inert/package.json"(exports2, module14) { - module14.exports = { - name: "@hapi/inert", - description: "Static file and directory handlers plugin for hapi.js", - version: "7.1.0", - repository: "https://github.com/hapijs/inert.git", - main: "lib/index.js", - types: "lib/index.d.ts", - files: [ - "lib" - ], - keywords: [ - "file", - "directory", - "handler", - "hapi", - "plugin" - ], - eslintConfig: { - extends: [ - "plugin:@hapi/module" - ] - }, - dependencies: { - "@hapi/ammo": "^6.0.1", - "@hapi/boom": "^10.0.1", - "@hapi/bounce": "^3.0.1", - "@hapi/hoek": "^11.0.2", - "@hapi/validate": "^2.0.1", - "lru-cache": "^7.14.1" - }, - devDependencies: { - "@hapi/code": "^9.0.3", - "@hapi/eslint-plugin": "*", - "@hapi/file": "^3.0.0", - "@hapi/hapi": "^21.3.0", - "@hapi/lab": "^25.1.2", - "@types/node": "^14.18.37", - joi: "^17.8.3", - typescript: "^4.9.5" +var require_AGGREGATE_WITHCURSOR = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/AGGREGATE_WITHCURSOR.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var AGGREGATE_1 = __importDefault(require_AGGREGATE()); + exports2.default = { + IS_READ_ONLY: AGGREGATE_1.default.IS_READ_ONLY, + /** + * Performs an aggregation with a cursor for retrieving large result sets. + * @param parser - The command parser + * @param index - Name of the index to query + * @param query - The aggregation query + * @param options - Optional parameters: + * - All options supported by FT.AGGREGATE + * - COUNT: Number of results to return per cursor fetch + * - MAXIDLE: Maximum idle time for cursor in milliseconds + */ + parseCommand(parser3, index, query, options2) { + AGGREGATE_1.default.parseCommand(parser3, index, query, options2); + parser3.push("WITHCURSOR"); + if (options2?.COUNT !== void 0) { + parser3.push("COUNT", options2.COUNT.toString()); + } + if (options2?.MAXIDLE !== void 0) { + parser3.push("MAXIDLE", options2.MAXIDLE.toString()); + } }, - scripts: { - test: "lab -f -a @hapi/code -t 100 -L -Y", - "test-cov-html": "lab -f -a @hapi/code -r html -o coverage.html" + transformReply: { + 2: (reply) => { + return { + ...AGGREGATE_1.default.transformReply[2](reply[0]), + cursor: reply[1] + }; + }, + 3: void 0 }, - license: "BSD-3-Clause" + unstableResp3: true }; } }); -var require_lib35 = __commonJS({ - "node_modules/.deno/@hapi+inert@7.1.0/node_modules/@hapi/inert/lib/index.js"(exports2) { +var require_ALIASADD = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALIASADD.js"(exports2) { "use strict"; - var Hoek = require_lib(); - var Validate = require_lib9(); - var Directory = require_directory(); - var Etag = require_etag(); - var File2 = require_file2(); - var internals = { - schema: Validate.object({ - etagsCacheMaxSize: Validate.number().integer().min(0).default(1e3) - }).required() - }; - internals.fileMethod = function(path8, responseOptions = {}) { - if (typeof responseOptions.confine === "undefined" || responseOptions.confine === true) { - responseOptions.confine = "."; - } - Hoek.assert(responseOptions.end === void 0 || +responseOptions.start <= +responseOptions.end, "options.start must be less than or equal to options.end"); - return this.response(File2.response(path8, responseOptions, this.request)); - }; - exports2.plugin = { - pkg: require_package5(), - once: true, - requirements: { - hapi: ">=20.0.0" + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Adds an alias to a RediSearch index. + * @param parser - The command parser + * @param alias - The alias to add + * @param index - The index name to alias + */ + parseCommand(parser3, alias, index) { + parser3.push("FT.ALIASADD", alias, index); }, - register(server, options2) { - Hoek.assert(Object.keys(options2).length === 0, "Inert does not support registration options"); - const settings = Validate.attempt(server.settings.plugins?.inert ?? {}, internals.schema, 'Invalid "inert" server options'); - server.expose("_etags", settings.etagsCacheMaxSize > 0 ? new Etag.Cache({ max: settings.etagsCacheMaxSize }) : null); - server.decorate("handler", "file", File2.handler); - server.decorate("handler", "directory", Directory.handler); - server.decorate("toolkit", "file", internals.fileMethod); - } + transformReply: void 0 }; } }); -var dashboard_server_exports = {}; -__export(dashboard_server_exports, { - default: () => dashboard_server_default, - startDashboard: () => startDashboard -}); -async function startDashboard() { - const port = import_npm_nconf4.default.get("server:dashboardPort"); - const dashboardServer = new Hapi.Server({ - port, - host: import_npm_nconf4.default.get("server:host"), - routes: { - files: { - relativeTo: getDashboardPath() - } - } - }); - await dashboardServer.register(import_inert.default); - dashboardServer.route({ - method: "GET", - path: "/assets/{path*}", - handler: { - directory: { - path: "assets", - redirectToSlash: false - } - } - }); - dashboardServer.route({ - method: "GET", - path: "/dashboard", - handler: (_request, h2) => h2.file("index.html") - }); - dashboardServer.route({ - method: "GET", - path: "/dashboard/", - handler: (_request, h2) => h2.file("index.html") - }); - dashboardServer.route({ - method: "GET", - path: "/{path*}", - handler: { - directory: { - path: ".", - index: ["index.html"] - } - } - }); - await dashboardServer.start(); -} -var Hapi; -var import_inert; -var import_npm_nconf4; -var getDashboardPath; -var dashboard_server_default; -var init_dashboard_server = __esm({ - "src/serve/dashboard-server.ts"() { - "use strict"; - Hapi = __toESM(require_lib34()); - import_inert = __toESM(require_lib35()); - import_npm_nconf4 = __toESM(require_nconf()); - getDashboardPath = () => { - return path5.resolve(import.meta.dirname || process5.cwd(), "dist-dashboard"); - }; - dashboard_server_default = startDashboard; - } -}); -var isEventQueueSbpEvent2; -var esm_default5; -var init_esm9 = __esm({ - "node_modules/.deno/@sbp+okturtles.eventqueue@1.2.0/node_modules/@sbp/okturtles.eventqueue/dist/esm/index.js"() { - init_esm(); - isEventQueueSbpEvent2 = (e2) => { - return Object.prototype.hasOwnProperty.call(e2, "sbpInvocation"); - }; - esm_default5 = esm_default("sbp/selectors/register", { - "okTurtles.eventQueue/_init": function() { - this.eventQueues = /* @__PURE__ */ Object.create(null); +var require_ALIASDEL = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALIASDEL.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Removes an existing alias from a RediSearch index. + * @param parser - The command parser + * @param alias - The alias to remove + */ + parseCommand(parser3, alias) { + parser3.push("FT.ALIASDEL", alias); }, - "okTurtles.eventQueue/isWaiting": function(name) { - var _a2; - return !!((_a2 = this.eventQueues[name]) === null || _a2 === void 0 ? void 0 : _a2.length); + transformReply: void 0 + }; + } +}); +var require_ALIASUPDATE = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/ALIASUPDATE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Updates the index pointed to by an existing alias. + * @param parser - The command parser + * @param alias - The existing alias to update + * @param index - The new index name that the alias should point to + */ + parseCommand(parser3, alias, index) { + parser3.push("FT.ALIASUPDATE", alias, index); }, - "okTurtles.eventQueue/queuedInvocations": function(name) { - var _a2, _b; - if (name == null) { - return Object.fromEntries(Object.entries(this.eventQueues).map(([name2, events]) => [name2, events.map((event) => { - if (isEventQueueSbpEvent2(event)) { - return event.sbpInvocation; - } else { - return event.fn; - } - })])); - } - return (_b = (_a2 = this.eventQueues[name]) === null || _a2 === void 0 ? void 0 : _a2.map((event) => { - if (isEventQueueSbpEvent2(event)) { - return event.sbpInvocation; - } else { - return event.fn; - } - })) !== null && _b !== void 0 ? _b : []; + transformReply: void 0 + }; + } +}); +var require_CONFIG_GET2 = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CONFIG_GET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Gets a RediSearch configuration option value. + * @param parser - The command parser + * @param option - The name of the configuration option to retrieve + */ + parseCommand(parser3, option) { + parser3.push("FT.CONFIG", "GET", option); }, - "okTurtles.eventQueue/queueEvent": async function(name, invocation) { - if (!Object.prototype.hasOwnProperty.call(this.eventQueues, name)) { - this.eventQueues[name] = []; - } - const events = this.eventQueues[name]; - let accept; - const promise = new Promise((resolve82) => { - accept = resolve82; - }); - const thisEvent = typeof invocation === "function" ? { - fn: invocation, - promise - } : { - sbpInvocation: invocation, - promise - }; - events.push(thisEvent); - while (events.length > 0) { - const event = events[0]; - if (event === thisEvent) { - try { - if (typeof invocation === "function") { - return await invocation(); - } else { - return await esm_default(...invocation); - } - } finally { - accept(); - events.shift(); - } - } else { - await event.promise; - } + transformReply(reply) { + const transformedReply = /* @__PURE__ */ Object.create(null); + for (const item of reply) { + const [key, value] = item; + transformedReply[key.toString()] = value; } + return transformedReply; } - }); + }; } }); -var listenKey2; -var esm_default6; -var init_esm10 = __esm({ - "node_modules/.deno/@sbp+okturtles.events@1.0.0/node_modules/@sbp/okturtles.events/dist/esm/index.js"() { - init_esm(); - init_esm3(); - listenKey2 = (evt) => `events/${evt}/listeners`; - esm_default6 = esm_default("sbp/selectors/register", { - "okTurtles.events/_init": function() { - this.errorHandler = (event, e2) => { - console.error(`[okTurtles.events] Error at handler for ${event}`, e2); - }; - }, - "okTurtles.events/on": function(event, handler) { - esm_default("okTurtles.data/add", listenKey2(event), handler); - return () => esm_default("okTurtles.events/off", event, handler); - }, - "okTurtles.events/once": function(event, handler) { - const cbWithOff = (...args) => { - handler(...args); - esm_default("okTurtles.events/off", event, cbWithOff); - }; - return esm_default("okTurtles.events/on", event, cbWithOff); - }, - "okTurtles.events/emit": function(event, ...data) { - var _a2; - for (const listener of esm_default("okTurtles.data/get", listenKey2(event)) || []) { - try { - listener(...data); - } catch (e2) { - (_a2 = this.errorHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, event, e2); - } - } - }, - // almost identical to Vue.prototype.$off, except we require `event` argument - "okTurtles.events/off": function(event, handler) { - if (handler) { - esm_default("okTurtles.data/remove", listenKey2(event), handler); - } else { - esm_default("okTurtles.data/delete", listenKey2(event)); - } +var require_CONFIG_SET2 = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CONFIG_SET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Sets a RediSearch configuration option value. + * @param parser - The command parser + * @param property - The name of the configuration option to set + * @param value - The value to set for the configuration option + */ + parseCommand(parser3, property, value) { + parser3.push("FT.CONFIG", "SET", property, value); }, - "okTurtles.events/setErrorHandler": function(errorHandler) { - this.errorHandler = errorHandler; - } - }); + transformReply: void 0 + }; } }); -var require_has_flag = __commonJS({ - "node_modules/.deno/has-flag@4.0.0/node_modules/has-flag/index.js"(exports2, module14) { +var require_CURSOR_DEL = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CURSOR_DEL.js"(exports2) { "use strict"; - module14.exports = (flag, argv = process.argv) => { - const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--"; - const position = argv.indexOf(prefix + flag); - const terminatorPosition = argv.indexOf("--"); - return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Deletes a cursor from an index. + * @param parser - The command parser + * @param index - The index name that contains the cursor + * @param cursorId - The cursor ID to delete + */ + parseCommand(parser3, index, cursorId) { + parser3.push("FT.CURSOR", "DEL", index, cursorId.toString()); + }, + transformReply: void 0 }; } }); -var require_supports_color = __commonJS({ - "node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js"(exports2, module14) { +var require_CURSOR_READ = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/CURSOR_READ.js"(exports2) { "use strict"; - var os = __require2("os"); - var tty = __require2("tty"); - var hasFlag = require_has_flag(); - var { env: env2 } = process; - var forceColor; - if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) { - forceColor = 0; - } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) { - forceColor = 1; - } - if ("FORCE_COLOR" in env2) { - if (env2.FORCE_COLOR === "true") { - forceColor = 1; - } else if (env2.FORCE_COLOR === "false") { - forceColor = 0; - } else { - forceColor = env2.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env2.FORCE_COLOR, 10), 3); - } - } - function translateLevel(level) { - if (level === 0) { - return false; - } - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; - } - function supportsColor(haveStream, streamIsTTY) { - if (forceColor === 0) { - return 0; - } - if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) { - return 3; - } - if (hasFlag("color=256")) { - return 2; - } - if (haveStream && !streamIsTTY && forceColor === void 0) { - return 0; - } - const min = forceColor || 0; - if (env2.TERM === "dumb") { - return min; - } - if (process.platform === "win32") { - const osRelease = os.release().split("."); - if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - return 1; - } - if ("CI" in env2) { - if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign2) => sign2 in env2) || env2.CI_NAME === "codeship") { - return 1; - } - return min; - } - if ("TEAMCITY_VERSION" in env2) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env2.TEAMCITY_VERSION) ? 1 : 0; - } - if (env2.COLORTERM === "truecolor") { - return 3; - } - if ("TERM_PROGRAM" in env2) { - const version3 = parseInt((env2.TERM_PROGRAM_VERSION || "").split(".")[0], 10); - switch (env2.TERM_PROGRAM) { - case "iTerm.app": - return version3 >= 3 ? 3 : 2; - case "Apple_Terminal": - return 2; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var AGGREGATE_WITHCURSOR_1 = __importDefault(require_AGGREGATE_WITHCURSOR()); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Reads from an existing cursor to get more results from an index. + * @param parser - The command parser + * @param index - The index name that contains the cursor + * @param cursor - The cursor ID to read from + * @param options - Optional parameters: + * - COUNT: Maximum number of results to return + */ + parseCommand(parser3, index, cursor, options2) { + parser3.push("FT.CURSOR", "READ", index, cursor.toString()); + if (options2?.COUNT !== void 0) { + parser3.push("COUNT", options2.COUNT.toString()); } - } - if (/-256(color)?$/i.test(env2.TERM)) { - return 2; - } - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env2.TERM)) { - return 1; - } - if ("COLORTERM" in env2) { - return 1; - } - return min; - } - function getSupportLevel(stream) { - const level = supportsColor(stream, stream && stream.isTTY); - return translateLevel(level); - } - module14.exports = { - supportsColor: getSupportLevel, - stdout: translateLevel(supportsColor(true, tty.isatty(1))), - stderr: translateLevel(supportsColor(true, tty.isatty(2))) + }, + transformReply: AGGREGATE_WITHCURSOR_1.default.transformReply, + unstableResp3: true + }; + } +}); +var require_DICTADD = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DICTADD.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Adds terms to a dictionary. + * @param parser - The command parser + * @param dictionary - Name of the dictionary to add terms to + * @param term - One or more terms to add to the dictionary + */ + parseCommand(parser3, dictionary, term) { + parser3.push("FT.DICTADD", dictionary); + parser3.pushVariadic(term); + }, + transformReply: void 0 }; } }); -var require_util2 = __commonJS({ - "node_modules/.deno/chalk@4.1.0/node_modules/chalk/source/util.js"(exports2, module14) { +var require_DICTDEL = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DICTDEL.js"(exports2) { "use strict"; - var stringReplaceAll = (string3, substring, replacer) => { - let index = string3.indexOf(substring); - if (index === -1) { - return string3; - } - const substringLength = substring.length; - let endIndex = 0; - let returnValue = ""; - do { - returnValue += string3.substr(endIndex, index - endIndex) + substring + replacer; - endIndex = index + substringLength; - index = string3.indexOf(substring, endIndex); - } while (index !== -1); - returnValue += string3.substr(endIndex); - return returnValue; - }; - var stringEncaseCRLFWithFirstIndex = (string3, prefix, postfix, index) => { - let endIndex = 0; - let returnValue = ""; - do { - const gotCR = string3[index - 1] === "\r"; - returnValue += string3.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? "\r\n" : "\n") + postfix; - endIndex = index + 1; - index = string3.indexOf("\n", endIndex); - } while (index !== -1); - returnValue += string3.substr(endIndex); - return returnValue; - }; - module14.exports = { - stringReplaceAll, - stringEncaseCRLFWithFirstIndex + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Deletes terms from a dictionary. + * @param parser - The command parser + * @param dictionary - Name of the dictionary to remove terms from + * @param term - One or more terms to delete from the dictionary + */ + parseCommand(parser3, dictionary, term) { + parser3.push("FT.DICTDEL", dictionary); + parser3.pushVariadic(term); + }, + transformReply: void 0 }; } }); -var require_templates = __commonJS({ - "node_modules/.deno/chalk@4.1.0/node_modules/chalk/source/templates.js"(exports2, module14) { +var require_DICTDUMP = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DICTDUMP.js"(exports2) { "use strict"; - var TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; - var STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; - var STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; - var ESCAPE_REGEX2 = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi; - var ESCAPES = /* @__PURE__ */ new Map([ - ["n", "\n"], - ["r", "\r"], - ["t", " "], - ["b", "\b"], - ["f", "\f"], - ["v", "\v"], - ["0", "\0"], - ["\\", "\\"], - ["e", "\x1B"], - ["a", "\x07"] - ]); - function unescape(c) { - const u2 = c[0] === "u"; - const bracket = c[1] === "{"; - if (u2 && !bracket && c.length === 5 || c[0] === "x" && c.length === 3) { - return String.fromCharCode(parseInt(c.slice(1), 16)); - } - if (u2 && bracket) { - return String.fromCodePoint(parseInt(c.slice(2, -1), 16)); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns all terms in a dictionary. + * @param parser - The command parser + * @param dictionary - Name of the dictionary to dump + */ + parseCommand(parser3, dictionary) { + parser3.push("FT.DICTDUMP", dictionary); + }, + transformReply: { + 2: void 0, + 3: void 0 } - return ESCAPES.get(c) || c; - } - function parseArguments(name, arguments_) { - const results = []; - const chunks = arguments_.trim().split(/\s*,\s*/g); - let matches; - for (const chunk of chunks) { - const number3 = Number(chunk); - if (!Number.isNaN(number3)) { - results.push(number3); - } else if (matches = chunk.match(STRING_REGEX)) { - results.push(matches[2].replace(ESCAPE_REGEX2, (m3, escape, character) => escape ? unescape(escape) : character)); - } else { - throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); + }; + } +}); +var require_DROPINDEX = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/DROPINDEX.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Deletes an index and all associated documents. + * @param parser - The command parser + * @param index - Name of the index to delete + * @param options - Optional parameters: + * - DD: Also delete the indexed documents themselves + */ + parseCommand(parser3, index, options2) { + parser3.push("FT.DROPINDEX", index); + if (options2?.DD) { + parser3.push("DD"); } + }, + transformReply: { + 2: void 0, + 3: void 0 } - return results; - } - function parseStyle(style) { - STYLE_REGEX.lastIndex = 0; - const results = []; - let matches; - while ((matches = STYLE_REGEX.exec(style)) !== null) { - const name = matches[1]; - if (matches[2]) { - const args = parseArguments(name, matches[2]); - results.push([name].concat(args)); + }; + } +}); +var require_EXPLAIN = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/EXPLAIN.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var SEARCH_1 = require_SEARCH(); + var default_1 = require_default(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the execution plan for a complex query. + * @param parser - The command parser + * @param index - Name of the index to explain query against + * @param query - The query string to explain + * @param options - Optional parameters: + * - PARAMS: Named parameters to use in the query + * - DIALECT: Version of query dialect to use (defaults to 1) + */ + parseCommand(parser3, index, query, options2) { + parser3.push("FT.EXPLAIN", index, query); + (0, SEARCH_1.parseParamsArgument)(parser3, options2?.PARAMS); + if (options2?.DIALECT) { + parser3.push("DIALECT", options2.DIALECT.toString()); } else { - results.push([name]); - } - } - return results; - } - function buildStyle(chalk5, styles) { - const enabled2 = {}; - for (const layer of styles) { - for (const style of layer.styles) { - enabled2[style[0]] = layer.inverse ? null : style.slice(1); - } - } - let current = chalk5; - for (const [styleName, styles2] of Object.entries(enabled2)) { - if (!Array.isArray(styles2)) { - continue; - } - if (!(styleName in current)) { - throw new Error(`Unknown Chalk style: ${styleName}`); + parser3.push("DIALECT", default_1.DEFAULT_DIALECT); } - current = styles2.length > 0 ? current[styleName](...styles2) : current[styleName]; - } - return current; - } - module14.exports = (chalk5, temporary) => { - const styles = []; - const chunks = []; - let chunk = []; - temporary.replace(TEMPLATE_REGEX, (m3, escapeCharacter, inverse, style, close, character) => { - if (escapeCharacter) { - chunk.push(unescape(escapeCharacter)); - } else if (style) { - const string3 = chunk.join(""); - chunk = []; - chunks.push(styles.length === 0 ? string3 : buildStyle(chalk5, styles)(string3)); - styles.push({ inverse, styles: parseStyle(style) }); - } else if (close) { - if (styles.length === 0) { - throw new Error("Found extraneous } in Chalk template literal"); - } - chunks.push(buildStyle(chalk5, styles)(chunk.join(""))); - chunk = []; - styles.pop(); + }, + transformReply: void 0 + }; + } +}); +var require_EXPLAINCLI = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/EXPLAINCLI.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var default_1 = require_default(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the execution plan for a complex query in a more verbose format than FT.EXPLAIN. + * @param parser - The command parser + * @param index - Name of the index to explain query against + * @param query - The query string to explain + * @param options - Optional parameters: + * - DIALECT: Version of query dialect to use (defaults to 1) + */ + parseCommand(parser3, index, query, options2) { + parser3.push("FT.EXPLAINCLI", index, query); + if (options2?.DIALECT) { + parser3.push("DIALECT", options2.DIALECT.toString()); } else { - chunk.push(character); + parser3.push("DIALECT", default_1.DEFAULT_DIALECT); } - }); - chunks.push(chunk.join("")); - if (styles.length > 0) { - const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? "" : "s"} (\`}\`)`; - throw new Error(errMessage); - } - return chunks.join(""); + }, + transformReply: void 0 }; } }); -var require_source = __commonJS({ - "node_modules/.deno/chalk@4.1.0/node_modules/chalk/source/index.js"(exports2, module14) { +var require_INFO7 = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/INFO.js"(exports2) { "use strict"; - var ansiStyles = require_ansi_styles(); - var { stdout: stdoutColor, stderr: stderrColor } = require_supports_color(); - var { - stringReplaceAll, - stringEncaseCRLFWithFirstIndex - } = require_util2(); - var { isArray } = Array; - var levelMapping = [ - "ansi", - "ansi", - "ansi256", - "ansi16m" - ]; - var styles = /* @__PURE__ */ Object.create(null); - var applyOptions = (object2, options2 = {}) => { - if (options2.level && !(Number.isInteger(options2.level) && options2.level >= 0 && options2.level <= 3)) { - throw new Error("The `level` option should be an integer from 0 to 3"); - } - const colorLevel = stdoutColor ? stdoutColor.level : 0; - object2.level = options2.level === void 0 ? colorLevel : options2.level; - }; - var ChalkClass = class { - constructor(options2) { - return chalkFactory(options2); - } - }; - var chalkFactory = (options2) => { - const chalk6 = {}; - applyOptions(chalk6, options2); - chalk6.template = (...arguments_) => chalkTag(chalk6.template, ...arguments_); - Object.setPrototypeOf(chalk6, Chalk.prototype); - Object.setPrototypeOf(chalk6.template, chalk6); - chalk6.template.constructor = () => { - throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead."); - }; - chalk6.template.Instance = ChalkClass; - return chalk6.template; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns information and statistics about an index. + * @param parser - The command parser + * @param index - Name of the index to get information about + */ + parseCommand(parser3, index) { + parser3.push("FT.INFO", index); + }, + transformReply: { + 2: transformV2Reply, + 3: void 0 + }, + unstableResp3: true }; - function Chalk(options2) { - return chalkFactory(options2); - } - for (const [styleName, style] of Object.entries(ansiStyles)) { - styles[styleName] = { - get() { - const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty); - Object.defineProperty(this, styleName, { value: builder }); - return builder; + function transformV2Reply(reply, preserve, typeMapping) { + const myTransformFunc = (0, generic_transformers_1.createTransformTuplesReplyFunc)(preserve, typeMapping); + const ret = {}; + for (let i2 = 0; i2 < reply.length; i2 += 2) { + const key = reply[i2].toString(); + switch (key) { + case "index_name": + case "index_options": + case "num_docs": + case "max_doc_id": + case "num_terms": + case "num_records": + case "total_inverted_index_blocks": + case "hash_indexing_failures": + case "indexing": + case "number_of_uses": + case "cleaning": + case "stopwords_list": + ret[key] = reply[i2 + 1]; + break; + case "inverted_sz_mb": + case "vector_index_sz_mb": + case "offset_vectors_sz_mb": + case "doc_table_size_mb": + case "sortable_values_size_mb": + case "key_table_size_mb": + case "text_overhead_sz_mb": + case "tag_overhead_sz_mb": + case "total_index_memory_sz_mb": + case "geoshapes_sz_mb": + case "records_per_doc_avg": + case "bytes_per_record_avg": + case "offsets_per_term_avg": + case "offset_bits_per_record_avg": + case "total_indexing_time": + case "percent_indexed": + ret[key] = generic_transformers_1.transformDoubleReply[2](reply[i2 + 1], void 0, typeMapping); + break; + case "index_definition": + ret[key] = myTransformFunc(reply[i2 + 1]); + break; + case "attributes": + ret[key] = reply[i2 + 1].map((attribute) => myTransformFunc(attribute)); + break; + case "gc_stats": { + const innerRet = {}; + const array2 = reply[i2 + 1]; + for (let i3 = 0; i3 < array2.length; i3 += 2) { + const innerKey = array2[i3].toString(); + switch (innerKey) { + case "bytes_collected": + case "total_ms_run": + case "total_cycles": + case "average_cycle_time_ms": + case "last_run_time_ms": + case "gc_numeric_trees_missed": + case "gc_blocks_denied": + innerRet[innerKey] = generic_transformers_1.transformDoubleReply[2](array2[i3 + 1], void 0, typeMapping); + break; + } + } + ret[key] = innerRet; + break; + } + case "cursor_stats": { + const innerRet = {}; + const array2 = reply[i2 + 1]; + for (let i3 = 0; i3 < array2.length; i3 += 2) { + const innerKey = array2[i3].toString(); + switch (innerKey) { + case "global_idle": + case "global_total": + case "index_capacity": + case "index_total": + innerRet[innerKey] = array2[i3 + 1]; + break; + } + } + ret[key] = innerRet; + break; + } } - }; + } + return ret; } - styles.visible = { - get() { - const builder = createBuilder(this, this._styler, true); - Object.defineProperty(this, "visible", { value: builder }); - return builder; + } +}); +var require_PROFILE_SEARCH = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/PROFILE_SEARCH.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } + __setModuleDefault(result, mod); + return result; }; - var usedModels = ["rgb", "hex", "keyword", "hsl", "hsv", "hwb", "ansi", "ansi256"]; - for (const model of usedModels) { - styles[model] = { - get() { - const { level } = this; - return function(...arguments_) { - const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler); - return createBuilder(this, styler, this._isEmpty); - }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var SEARCH_1 = __importStar(require_SEARCH()); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Profiles the execution of a search query for performance analysis. + * @param parser - The command parser + * @param index - Name of the index to profile query against + * @param query - The search query to profile + * @param options - Optional parameters: + * - LIMITED: Collect limited timing information only + * - All options supported by FT.SEARCH command + */ + parseCommand(parser3, index, query, options2) { + parser3.push("FT.PROFILE", index, "SEARCH"); + if (options2?.LIMITED) { + parser3.push("LIMITED"); } - }; - } - for (const model of usedModels) { - const bgModel = "bg" + model[0].toUpperCase() + model.slice(1); - styles[bgModel] = { - get() { - const { level } = this; - return function(...arguments_) { - const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler); - return createBuilder(this, styler, this._isEmpty); + parser3.push("QUERY", query); + (0, SEARCH_1.parseSearchOptions)(parser3, options2); + }, + transformReply: { + 2: (reply) => { + return { + results: SEARCH_1.default.transformReply[2](reply[0]), + profile: reply[1] }; - } - }; - } - var proto3 = Object.defineProperties(() => { - }, { - ...styles, - level: { - enumerable: true, - get() { - return this._generator.level; }, - set(level) { - this._generator.level = level; - } + 3: (reply) => reply + }, + unstableResp3: true + }; + } +}); +var require_PROFILE_AGGREGATE = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/PROFILE_AGGREGATE.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; }); - var createStyler = (open, close, parent) => { - let openAll; - let closeAll; - if (parent === void 0) { - openAll = open; - closeAll = close; - } else { - openAll = parent.openAll + open; - closeAll = close + parent.closeAll; + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - return { - open, - close, - openAll, - closeAll, - parent - }; + __setModuleDefault(result, mod); + return result; }; - var createBuilder = (self2, _styler, _isEmpty) => { - const builder = (...arguments_) => { - if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) { - return applyStyle(builder, chalkTag(builder, ...arguments_)); + Object.defineProperty(exports2, "__esModule", { value: true }); + var AGGREGATE_1 = __importStar(require_AGGREGATE()); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Profiles the execution of an aggregation query for performance analysis. + * @param parser - The command parser + * @param index - Name of the index to profile query against + * @param query - The aggregation query to profile + * @param options - Optional parameters: + * - LIMITED: Collect limited timing information only + * - All options supported by FT.AGGREGATE command + */ + parseCommand(parser3, index, query, options2) { + parser3.push("FT.PROFILE", index, "AGGREGATE"); + if (options2?.LIMITED) { + parser3.push("LIMITED"); } - return applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" ")); - }; - Object.setPrototypeOf(builder, proto3); - builder._generator = self2; - builder._styler = _styler; - builder._isEmpty = _isEmpty; - return builder; + parser3.push("QUERY", query); + (0, AGGREGATE_1.parseAggregateOptions)(parser3, options2); + }, + transformReply: { + 2: (reply) => { + return { + results: AGGREGATE_1.default.transformReply[2](reply[0]), + profile: reply[1] + }; + }, + 3: (reply) => reply + }, + unstableResp3: true }; - var applyStyle = (self2, string3) => { - if (self2.level <= 0 || !string3) { - return self2._isEmpty ? "" : string3; - } - let styler = self2._styler; - if (styler === void 0) { - return string3; - } - const { openAll, closeAll } = styler; - if (string3.indexOf("\x1B") !== -1) { - while (styler !== void 0) { - string3 = stringReplaceAll(string3, styler.close, styler.open); - styler = styler.parent; - } - } - const lfIndex = string3.indexOf("\n"); - if (lfIndex !== -1) { - string3 = stringEncaseCRLFWithFirstIndex(string3, closeAll, openAll, lfIndex); - } - return openAll + string3 + closeAll; + } +}); +var require_SEARCH_NOCONTENT = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SEARCH_NOCONTENT.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - var template; - var chalkTag = (chalk6, ...strings) => { - const [firstString] = strings; - if (!isArray(firstString) || !isArray(firstString.raw)) { - return strings.join(" "); - } - const arguments_ = strings.slice(1); - const parts = [firstString.raw[0]]; - for (let i2 = 1; i2 < firstString.length; i2++) { - parts.push( - String(arguments_[i2 - 1]).replace(/[{}\\]/g, "\\$&"), - String(firstString.raw[i2]) - ); - } - if (template === void 0) { - template = require_templates(); - } - return template(chalk6, parts.join("")); + Object.defineProperty(exports2, "__esModule", { value: true }); + var SEARCH_1 = __importDefault(require_SEARCH()); + exports2.default = { + NOT_KEYED_COMMAND: SEARCH_1.default.NOT_KEYED_COMMAND, + IS_READ_ONLY: SEARCH_1.default.IS_READ_ONLY, + /** + * Performs a search query but returns only document ids without their contents. + * @param args - Same parameters as FT.SEARCH: + * - parser: The command parser + * - index: Name of the index to search + * - query: The text query to search + * - options: Optional search parameters + */ + parseCommand(...args) { + SEARCH_1.default.parseCommand(...args); + args[0].push("NOCONTENT"); + }, + transformReply: { + 2: (reply) => { + return { + total: reply[0], + documents: reply.slice(1) + }; + }, + 3: void 0 + }, + unstableResp3: true }; - Object.defineProperties(Chalk.prototype, styles); - var chalk5 = Chalk(); - chalk5.supportsColor = stdoutColor; - chalk5.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 }); - chalk5.stderr.supportsColor = stderrColor; - module14.exports = chalk5; } }); -var SERVER_INSTANCE; -var PUBSUB_INSTANCE; -var init_instance_keys = __esm({ - "src/serve/instance-keys.ts"() { +var require_SPELLCHECK = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SPELLCHECK.js"(exports2) { "use strict"; - SERVER_INSTANCE = "@instance/server"; - PUBSUB_INSTANCE = "@instance/pubsub"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var default_1 = require_default(); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Performs spelling correction on a search query. + * @param parser - The command parser + * @param index - Name of the index to use for spelling corrections + * @param query - The search query to check for spelling + * @param options - Optional parameters: + * - DISTANCE: Maximum Levenshtein distance for spelling suggestions + * - TERMS: Custom dictionary terms to include/exclude + * - DIALECT: Version of query dialect to use (defaults to 1) + */ + parseCommand(parser3, index, query, options2) { + parser3.push("FT.SPELLCHECK", index, query); + if (options2?.DISTANCE) { + parser3.push("DISTANCE", options2.DISTANCE.toString()); + } + if (options2?.TERMS) { + if (Array.isArray(options2.TERMS)) { + for (const term of options2.TERMS) { + parseTerms(parser3, term); + } + } else { + parseTerms(parser3, options2.TERMS); + } + } + if (options2?.DIALECT) { + parser3.push("DIALECT", options2.DIALECT.toString()); + } else { + parser3.push("DIALECT", default_1.DEFAULT_DIALECT); + } + }, + transformReply: { + 2: (rawReply) => { + return rawReply.map(([, term, suggestions]) => ({ + term, + suggestions: suggestions.map(([score, suggestion]) => ({ + score: Number(score), + suggestion + })) + })); + }, + 3: void 0 + }, + unstableResp3: true + }; + function parseTerms(parser3, { mode, dictionary }) { + parser3.push("TERMS", mode, dictionary); + } } }); -var require_err_helpers = __commonJS({ - "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err-helpers.js"(exports2, module14) { +var require_SUGADD = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGADD.js"(exports2) { "use strict"; - var isErrorLike = (err) => { - return err && typeof err.message === "string"; - }; - var getErrorCause = (err) => { - if (!err) return; - const cause = err.cause; - if (typeof cause === "function") { - const causeResult = err.cause(); - return isErrorLike(causeResult) ? causeResult : void 0; - } else { - return isErrorLike(cause) ? cause : void 0; - } - }; - var _stackWithCauses = (err, seen) => { - if (!isErrorLike(err)) return ""; - const stack = err.stack || ""; - if (seen.has(err)) { - return stack + "\ncauses have become circular..."; - } - const cause = getErrorCause(err); - if (cause) { - seen.add(err); - return stack + "\ncaused by: " + _stackWithCauses(cause, seen); - } else { - return stack; - } - }; - var stackWithCauses = (err) => _stackWithCauses(err, /* @__PURE__ */ new Set()); - var _messageWithCauses = (err, seen, skip) => { - if (!isErrorLike(err)) return ""; - const message = skip ? "" : err.message || ""; - if (seen.has(err)) { - return message + ": ..."; - } - const cause = getErrorCause(err); - if (cause) { - seen.add(err); - const skipIfVErrorStyleCause = typeof err.cause === "function"; - return message + (skipIfVErrorStyleCause ? "" : ": ") + _messageWithCauses(cause, seen, skipIfVErrorStyleCause); - } else { - return message; - } - }; - var messageWithCauses = (err) => _messageWithCauses(err, /* @__PURE__ */ new Set()); - module14.exports = { - isErrorLike, - getErrorCause, - stackWithCauses, - messageWithCauses + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Adds a suggestion string to an auto-complete suggestion dictionary. + * @param parser - The command parser + * @param key - The suggestion dictionary key + * @param string - The suggestion string to add + * @param score - The suggestion score used for sorting + * @param options - Optional parameters: + * - INCR: If true, increment the existing entry's score + * - PAYLOAD: Optional payload to associate with the suggestion + */ + parseCommand(parser3, key, string3, score, options2) { + parser3.push("FT.SUGADD"); + parser3.pushKey(key); + parser3.push(string3, score.toString()); + if (options2?.INCR) { + parser3.push("INCR"); + } + if (options2?.PAYLOAD) { + parser3.push("PAYLOAD", options2.PAYLOAD); + } + }, + transformReply: void 0 }; } }); -var require_err_proto = __commonJS({ - "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err-proto.js"(exports2, module14) { +var require_SUGDEL = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGDEL.js"(exports2) { "use strict"; - var seen = Symbol("circular-ref-tag"); - var rawSymbol = Symbol("pino-raw-err-ref"); - var pinoErrProto = Object.create({}, { - type: { - enumerable: true, - writable: true, - value: void 0 - }, - message: { - enumerable: true, - writable: true, - value: void 0 - }, - stack: { - enumerable: true, - writable: true, - value: void 0 - }, - aggregateErrors: { - enumerable: true, - writable: true, - value: void 0 + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Deletes a string from a suggestion dictionary. + * @param parser - The command parser + * @param key - The suggestion dictionary key + * @param string - The suggestion string to delete + */ + parseCommand(parser3, key, string3) { + parser3.push("FT.SUGDEL"); + parser3.pushKey(key); + parser3.push(string3); }, - raw: { - enumerable: false, - get: function() { - return this[rawSymbol]; - }, - set: function(val) { - this[rawSymbol] = val; + transformReply: void 0 + }; + } +}); +var require_SUGGET = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets completion suggestions for a prefix from a suggestion dictionary. + * @param parser - The command parser + * @param key - The suggestion dictionary key + * @param prefix - The prefix to get completion suggestions for + * @param options - Optional parameters: + * - FUZZY: Enable fuzzy prefix matching + * - MAX: Maximum number of results to return + */ + parseCommand(parser3, key, prefix, options2) { + parser3.push("FT.SUGGET"); + parser3.pushKey(key); + parser3.push(prefix); + if (options2?.FUZZY) { + parser3.push("FUZZY"); } - } - }); - Object.defineProperty(pinoErrProto, rawSymbol, { - writable: true, - value: {} - }); - module14.exports = { - pinoErrProto, - pinoErrorSymbols: { - seen, - rawSymbol - } + if (options2?.MAX !== void 0) { + parser3.push("MAX", options2.MAX.toString()); + } + }, + transformReply: void 0 }; } }); -var require_err = __commonJS({ - "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err.js"(exports2, module14) { +var require_SUGGET_WITHPAYLOADS = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET_WITHPAYLOADS.js"(exports2) { "use strict"; - module14.exports = errSerializer; - var { messageWithCauses, stackWithCauses, isErrorLike } = require_err_helpers(); - var { pinoErrProto, pinoErrorSymbols } = require_err_proto(); - var { seen } = pinoErrorSymbols; - var { toString } = Object.prototype; - function errSerializer(err) { - if (!isErrorLike(err)) { - return err; - } - err[seen] = void 0; - const _err = Object.create(pinoErrProto); - _err.type = toString.call(err.constructor) === "[object Function]" ? err.constructor.name : err.name; - _err.message = messageWithCauses(err); - _err.stack = stackWithCauses(err); - if (Array.isArray(err.errors)) { - _err.aggregateErrors = err.errors.map((err2) => errSerializer(err2)); - } - for (const key in err) { - if (_err[key] === void 0) { - const val = err[key]; - if (isErrorLike(val)) { - if (key !== "cause" && !Object.prototype.hasOwnProperty.call(val, seen)) { - _err[key] = errSerializer(val); - } - } else { - _err[key] = val; - } + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var SUGGET_1 = __importDefault(require_SUGGET()); + exports2.default = { + IS_READ_ONLY: SUGGET_1.default.IS_READ_ONLY, + /** + * Gets completion suggestions with their payloads from a suggestion dictionary. + * @param args - Same parameters as FT.SUGGET: + * - parser: The command parser + * - key: The suggestion dictionary key + * - prefix: The prefix to get completion suggestions for + * - options: Optional parameters for fuzzy matching and max results + */ + parseCommand(...args) { + SUGGET_1.default.parseCommand(...args); + args[0].push("WITHPAYLOADS"); + }, + transformReply(reply) { + if ((0, generic_transformers_1.isNullReply)(reply)) + return null; + const transformedReply = new Array(reply.length / 2); + let replyIndex = 0, arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + payload: reply[replyIndex++] + }; } + return transformedReply; } - delete err[seen]; - _err.raw = err; - return _err; - } + }; } }); -var require_err_with_cause = __commonJS({ - "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err-with-cause.js"(exports2, module14) { +var require_SUGGET_WITHSCORES_WITHPAYLOADS = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET_WITHSCORES_WITHPAYLOADS.js"(exports2) { "use strict"; - module14.exports = errWithCauseSerializer; - var { isErrorLike } = require_err_helpers(); - var { pinoErrProto, pinoErrorSymbols } = require_err_proto(); - var { seen } = pinoErrorSymbols; - var { toString } = Object.prototype; - function errWithCauseSerializer(err) { - if (!isErrorLike(err)) { - return err; - } - err[seen] = void 0; - const _err = Object.create(pinoErrProto); - _err.type = toString.call(err.constructor) === "[object Function]" ? err.constructor.name : err.name; - _err.message = err.message; - _err.stack = err.stack; - if (Array.isArray(err.errors)) { - _err.aggregateErrors = err.errors.map((err2) => errWithCauseSerializer(err2)); - } - if (isErrorLike(err.cause) && !Object.prototype.hasOwnProperty.call(err.cause, seen)) { - _err.cause = errWithCauseSerializer(err.cause); - } - for (const key in err) { - if (_err[key] === void 0) { - const val = err[key]; - if (isErrorLike(val)) { - if (!Object.prototype.hasOwnProperty.call(val, seen)) { - _err[key] = errWithCauseSerializer(val); - } - } else { - _err[key] = val; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var SUGGET_1 = __importDefault(require_SUGGET()); + exports2.default = { + IS_READ_ONLY: SUGGET_1.default.IS_READ_ONLY, + /** + * Gets completion suggestions with their scores and payloads from a suggestion dictionary. + * @param args - Same parameters as FT.SUGGET: + * - parser: The command parser + * - key: The suggestion dictionary key + * - prefix: The prefix to get completion suggestions for + * - options: Optional parameters for fuzzy matching and max results + */ + parseCommand(...args) { + SUGGET_1.default.parseCommand(...args); + args[0].push("WITHSCORES", "WITHPAYLOADS"); + }, + transformReply: { + 2: (reply, preserve, typeMapping) => { + if ((0, generic_transformers_1.isNullReply)(reply)) + return null; + const transformedReply = new Array(reply.length / 3); + let replyIndex = 0, arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + score: generic_transformers_1.transformDoubleReply[2](reply[replyIndex++], preserve, typeMapping), + payload: reply[replyIndex++] + }; + } + return transformedReply; + }, + 3: (reply) => { + if ((0, generic_transformers_1.isNullReply)(reply)) + return null; + const transformedReply = new Array(reply.length / 3); + let replyIndex = 0, arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + score: reply[replyIndex++], + payload: reply[replyIndex++] + }; } + return transformedReply; } } - delete err[seen]; - _err.raw = err; - return _err; - } + }; } }); -var require_req = __commonJS({ - "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/req.js"(exports2, module14) { +var require_SUGGET_WITHSCORES = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGGET_WITHSCORES.js"(exports2) { "use strict"; - module14.exports = { - mapHttpRequest, - reqSerializer + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; }; - var rawSymbol = Symbol("pino-raw-req-ref"); - var pinoReqProto = Object.create({}, { - id: { - enumerable: true, - writable: true, - value: "" - }, - method: { - enumerable: true, - writable: true, - value: "" - }, - url: { - enumerable: true, - writable: true, - value: "" - }, - query: { - enumerable: true, - writable: true, - value: "" - }, - params: { - enumerable: true, - writable: true, - value: "" - }, - headers: { - enumerable: true, - writable: true, - value: {} - }, - remoteAddress: { - enumerable: true, - writable: true, - value: "" - }, - remotePort: { - enumerable: true, - writable: true, - value: "" + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + var SUGGET_1 = __importDefault(require_SUGGET()); + exports2.default = { + IS_READ_ONLY: SUGGET_1.default.IS_READ_ONLY, + /** + * Gets completion suggestions with their scores from a suggestion dictionary. + * @param args - Same parameters as FT.SUGGET: + * - parser: The command parser + * - key: The suggestion dictionary key + * - prefix: The prefix to get completion suggestions for + * - options: Optional parameters for fuzzy matching and max results + */ + parseCommand(...args) { + SUGGET_1.default.parseCommand(...args); + args[0].push("WITHSCORES"); }, - raw: { - enumerable: false, - get: function() { - return this[rawSymbol]; + transformReply: { + 2: (reply, preserve, typeMapping) => { + if ((0, generic_transformers_1.isNullReply)(reply)) + return null; + const transformedReply = new Array(reply.length / 2); + let replyIndex = 0, arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + score: generic_transformers_1.transformDoubleReply[2](reply[replyIndex++], preserve, typeMapping) + }; + } + return transformedReply; }, - set: function(val) { - this[rawSymbol] = val; + 3: (reply) => { + if ((0, generic_transformers_1.isNullReply)(reply)) + return null; + const transformedReply = new Array(reply.length / 2); + let replyIndex = 0, arrIndex = 0; + while (replyIndex < reply.length) { + transformedReply[arrIndex++] = { + suggestion: reply[replyIndex++], + score: reply[replyIndex++] + }; + } + return transformedReply; } } - }); - Object.defineProperty(pinoReqProto, rawSymbol, { - writable: true, - value: {} - }); - function reqSerializer(req) { - const connection = req.info || req.socket; - const _req = Object.create(pinoReqProto); - _req.id = typeof req.id === "function" ? req.id() : req.id || (req.info ? req.info.id : void 0); - _req.method = req.method; - if (req.originalUrl) { - _req.url = req.originalUrl; - } else { - const path8 = req.path; - _req.url = typeof path8 === "string" ? path8 : req.url ? req.url.path || req.url : void 0; - } - if (req.query) { - _req.query = req.query; - } - if (req.params) { - _req.params = req.params; - } - _req.headers = req.headers; - _req.remoteAddress = connection && connection.remoteAddress; - _req.remotePort = connection && connection.remotePort; - _req.raw = req.raw || req; - return _req; - } - function mapHttpRequest(req) { - return { - req: reqSerializer(req) - }; - } + }; } }); -var require_res = __commonJS({ - "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/res.js"(exports2, module14) { +var require_SUGLEN = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SUGLEN.js"(exports2) { "use strict"; - module14.exports = { - mapHttpResponse, - resSerializer - }; - var rawSymbol = Symbol("pino-raw-res-ref"); - var pinoResProto = Object.create({}, { - statusCode: { - enumerable: true, - writable: true, - value: 0 - }, - headers: { - enumerable: true, - writable: true, - value: "" + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets the size of a suggestion dictionary. + * @param parser - The command parser + * @param key - The suggestion dictionary key + */ + parseCommand(parser3, key) { + parser3.push("FT.SUGLEN", key); }, - raw: { - enumerable: false, - get: function() { - return this[rawSymbol]; - }, - set: function(val) { - this[rawSymbol] = val; - } - } - }); - Object.defineProperty(pinoResProto, rawSymbol, { - writable: true, - value: {} - }); - function resSerializer(res) { - const _res = Object.create(pinoResProto); - _res.statusCode = res.headersSent ? res.statusCode : null; - _res.headers = res.getHeaders ? res.getHeaders() : res._headers; - _res.raw = res; - return _res; - } - function mapHttpResponse(res) { - return { - res: resSerializer(res) - }; - } + transformReply: void 0 + }; } }); -var require_pino_std_serializers = __commonJS({ - "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/index.js"(exports2, module14) { +var require_SYNDUMP = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SYNDUMP.js"(exports2) { "use strict"; - var errSerializer = require_err(); - var errWithCauseSerializer = require_err_with_cause(); - var reqSerializers = require_req(); - var resSerializers = require_res(); - module14.exports = { - err: errSerializer, - errWithCause: errWithCauseSerializer, - mapHttpRequest: reqSerializers.mapHttpRequest, - mapHttpResponse: resSerializers.mapHttpResponse, - req: reqSerializers.reqSerializer, - res: resSerializers.resSerializer, - wrapErrorSerializer: function wrapErrorSerializer(customSerializer) { - if (customSerializer === errSerializer) return customSerializer; - return function wrapErrSerializer(err) { - return customSerializer(errSerializer(err)); - }; - }, - wrapRequestSerializer: function wrapRequestSerializer(customSerializer) { - if (customSerializer === reqSerializers.reqSerializer) return customSerializer; - return function wrappedReqSerializer(req) { - return customSerializer(reqSerializers.reqSerializer(req)); - }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Dumps the contents of a synonym group. + * @param parser - The command parser + * @param index - Name of the index that contains the synonym group + */ + parseCommand(parser3, index) { + parser3.push("FT.SYNDUMP", index); }, - wrapResponseSerializer: function wrapResponseSerializer(customSerializer) { - if (customSerializer === resSerializers.resSerializer) return customSerializer; - return function wrappedResSerializer(res) { - return customSerializer(resSerializers.resSerializer(res)); - }; + transformReply: { + 2: (reply) => { + const result = {}; + let i2 = 0; + while (i2 < reply.length) { + const key = reply[i2++].toString(), value = reply[i2++]; + result[key] = value; + } + return result; + }, + 3: void 0 } }; } }); -var require_caller = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/caller.js"(exports2, module14) { +var require_SYNUPDATE = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/SYNUPDATE.js"(exports2) { "use strict"; - function noOpPrepareStackTrace(_, stack) { - return stack; - } - module14.exports = function getCallers() { - const originalPrepare = Error.prepareStackTrace; - Error.prepareStackTrace = noOpPrepareStackTrace; - const stack = new Error().stack; - Error.prepareStackTrace = originalPrepare; - if (!Array.isArray(stack)) { - return void 0; - } - const entries = stack.slice(2); - const fileNames = []; - for (const entry of entries) { - if (!entry) { - continue; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Updates a synonym group with new terms. + * @param parser - The command parser + * @param index - Name of the index that contains the synonym group + * @param groupId - ID of the synonym group to update + * @param terms - One or more synonym terms to add to the group + * @param options - Optional parameters: + * - SKIPINITIALSCAN: Skip the initial scan for existing documents + */ + parseCommand(parser3, index, groupId, terms, options2) { + parser3.push("FT.SYNUPDATE", index, groupId); + if (options2?.SKIPINITIALSCAN) { + parser3.push("SKIPINITIALSCAN"); } - fileNames.push(entry.getFileName()); - } - return fileNames; + parser3.pushVariadic(terms); + }, + transformReply: void 0 }; } }); -var require_validator2 = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/validator.js"(exports2, module14) { +var require_TAGVALS = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/TAGVALS.js"(exports2) { "use strict"; - module14.exports = validator; - function validator(opts = {}) { - const { - ERR_PATHS_MUST_BE_STRINGS = () => "fast-redact - Paths must be (non-empty) strings", - ERR_INVALID_PATH = (s) => `fast-redact \u2013 Invalid path (${s})` - } = opts; - return function validate({ paths }) { - paths.forEach((s) => { - if (typeof s !== "string") { - throw Error(ERR_PATHS_MUST_BE_STRINGS()); - } - try { - if (/〇/.test(s)) throw Error(); - const expr = (s[0] === "[" ? "" : ".") + s.replace(/^\*/, "\u3007").replace(/\.\*/g, ".\u3007").replace(/\[\*\]/g, "[\u3007]"); - if (/\n|\r|;/.test(expr)) throw Error(); - if (/\/\*/.test(expr)) throw Error(); - Function(` - 'use strict' - const o = new Proxy({}, { get: () => o, set: () => { throw Error() } }); - const \u3007 = null; - o${expr} - if ([o${expr}].length !== 1) throw Error()`)(); - } catch (e2) { - throw Error(ERR_INVALID_PATH(s)); - } - }); - }; - } + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Returns the distinct values in a TAG field. + * @param parser - The command parser + * @param index - Name of the index + * @param fieldName - Name of the TAG field to get values from + */ + parseCommand(parser3, index, fieldName) { + parser3.push("FT.TAGVALS", index, fieldName); + }, + transformReply: { + 2: void 0, + 3: void 0 + } + }; } }); -var require_rx = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/rx.js"(exports2, module14) { +var require_commands5 = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/commands/index.js"(exports2) { "use strict"; - module14.exports = /[^.[\]]+|\[((?:.)*?)\]/g; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var _LIST_1 = __importDefault(require_LIST2()); + var ALTER_1 = __importDefault(require_ALTER()); + var AGGREGATE_WITHCURSOR_1 = __importDefault(require_AGGREGATE_WITHCURSOR()); + var AGGREGATE_1 = __importDefault(require_AGGREGATE()); + var ALIASADD_1 = __importDefault(require_ALIASADD()); + var ALIASDEL_1 = __importDefault(require_ALIASDEL()); + var ALIASUPDATE_1 = __importDefault(require_ALIASUPDATE()); + var CONFIG_GET_1 = __importDefault(require_CONFIG_GET2()); + var CONFIG_SET_1 = __importDefault(require_CONFIG_SET2()); + var CREATE_1 = __importDefault(require_CREATE2()); + var CURSOR_DEL_1 = __importDefault(require_CURSOR_DEL()); + var CURSOR_READ_1 = __importDefault(require_CURSOR_READ()); + var DICTADD_1 = __importDefault(require_DICTADD()); + var DICTDEL_1 = __importDefault(require_DICTDEL()); + var DICTDUMP_1 = __importDefault(require_DICTDUMP()); + var DROPINDEX_1 = __importDefault(require_DROPINDEX()); + var EXPLAIN_1 = __importDefault(require_EXPLAIN()); + var EXPLAINCLI_1 = __importDefault(require_EXPLAINCLI()); + var INFO_1 = __importDefault(require_INFO7()); + var PROFILE_SEARCH_1 = __importDefault(require_PROFILE_SEARCH()); + var PROFILE_AGGREGATE_1 = __importDefault(require_PROFILE_AGGREGATE()); + var SEARCH_NOCONTENT_1 = __importDefault(require_SEARCH_NOCONTENT()); + var SEARCH_1 = __importDefault(require_SEARCH()); + var SPELLCHECK_1 = __importDefault(require_SPELLCHECK()); + var SUGADD_1 = __importDefault(require_SUGADD()); + var SUGDEL_1 = __importDefault(require_SUGDEL()); + var SUGGET_WITHPAYLOADS_1 = __importDefault(require_SUGGET_WITHPAYLOADS()); + var SUGGET_WITHSCORES_WITHPAYLOADS_1 = __importDefault(require_SUGGET_WITHSCORES_WITHPAYLOADS()); + var SUGGET_WITHSCORES_1 = __importDefault(require_SUGGET_WITHSCORES()); + var SUGGET_1 = __importDefault(require_SUGGET()); + var SUGLEN_1 = __importDefault(require_SUGLEN()); + var SYNDUMP_1 = __importDefault(require_SYNDUMP()); + var SYNUPDATE_1 = __importDefault(require_SYNUPDATE()); + var TAGVALS_1 = __importDefault(require_TAGVALS()); + exports2.default = { + _LIST: _LIST_1.default, + _list: _LIST_1.default, + ALTER: ALTER_1.default, + alter: ALTER_1.default, + AGGREGATE_WITHCURSOR: AGGREGATE_WITHCURSOR_1.default, + aggregateWithCursor: AGGREGATE_WITHCURSOR_1.default, + AGGREGATE: AGGREGATE_1.default, + aggregate: AGGREGATE_1.default, + ALIASADD: ALIASADD_1.default, + aliasAdd: ALIASADD_1.default, + ALIASDEL: ALIASDEL_1.default, + aliasDel: ALIASDEL_1.default, + ALIASUPDATE: ALIASUPDATE_1.default, + aliasUpdate: ALIASUPDATE_1.default, + /** + * @deprecated Redis >=8 uses the standard CONFIG command + */ + CONFIG_GET: CONFIG_GET_1.default, + /** + * @deprecated Redis >=8 uses the standard CONFIG command + */ + configGet: CONFIG_GET_1.default, + /** + * @deprecated Redis >=8 uses the standard CONFIG command + */ + CONFIG_SET: CONFIG_SET_1.default, + /** + * @deprecated Redis >=8 uses the standard CONFIG command + */ + configSet: CONFIG_SET_1.default, + CREATE: CREATE_1.default, + create: CREATE_1.default, + CURSOR_DEL: CURSOR_DEL_1.default, + cursorDel: CURSOR_DEL_1.default, + CURSOR_READ: CURSOR_READ_1.default, + cursorRead: CURSOR_READ_1.default, + DICTADD: DICTADD_1.default, + dictAdd: DICTADD_1.default, + DICTDEL: DICTDEL_1.default, + dictDel: DICTDEL_1.default, + DICTDUMP: DICTDUMP_1.default, + dictDump: DICTDUMP_1.default, + DROPINDEX: DROPINDEX_1.default, + dropIndex: DROPINDEX_1.default, + EXPLAIN: EXPLAIN_1.default, + explain: EXPLAIN_1.default, + EXPLAINCLI: EXPLAINCLI_1.default, + explainCli: EXPLAINCLI_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + PROFILESEARCH: PROFILE_SEARCH_1.default, + profileSearch: PROFILE_SEARCH_1.default, + PROFILEAGGREGATE: PROFILE_AGGREGATE_1.default, + profileAggregate: PROFILE_AGGREGATE_1.default, + SEARCH_NOCONTENT: SEARCH_NOCONTENT_1.default, + searchNoContent: SEARCH_NOCONTENT_1.default, + SEARCH: SEARCH_1.default, + search: SEARCH_1.default, + SPELLCHECK: SPELLCHECK_1.default, + spellCheck: SPELLCHECK_1.default, + SUGADD: SUGADD_1.default, + sugAdd: SUGADD_1.default, + SUGDEL: SUGDEL_1.default, + sugDel: SUGDEL_1.default, + SUGGET_WITHPAYLOADS: SUGGET_WITHPAYLOADS_1.default, + sugGetWithPayloads: SUGGET_WITHPAYLOADS_1.default, + SUGGET_WITHSCORES_WITHPAYLOADS: SUGGET_WITHSCORES_WITHPAYLOADS_1.default, + sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS_1.default, + SUGGET_WITHSCORES: SUGGET_WITHSCORES_1.default, + sugGetWithScores: SUGGET_WITHSCORES_1.default, + SUGGET: SUGGET_1.default, + sugGet: SUGGET_1.default, + SUGLEN: SUGLEN_1.default, + sugLen: SUGLEN_1.default, + SYNDUMP: SYNDUMP_1.default, + synDump: SYNDUMP_1.default, + SYNUPDATE: SYNUPDATE_1.default, + synUpdate: SYNUPDATE_1.default, + TAGVALS: TAGVALS_1.default, + tagVals: TAGVALS_1.default + }; } }); -var require_parse = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/parse.js"(exports2, module14) { +var require_lib4 = __commonJS({ + "node_modules/.deno/@redis+search@5.9.0/node_modules/@redis/search/dist/lib/index.js"(exports2) { "use strict"; - var rx = require_rx(); - module14.exports = parse52; - function parse52({ paths }) { - const wildcards = []; - var wcLen = 0; - const secret = paths.reduce(function(o2, strPath, ix) { - var path8 = strPath.match(rx).map((p) => p.replace(/'|"|`/g, "")); - const leadingBracket = strPath[0] === "["; - path8 = path8.map((p) => { - if (p[0] === "[") return p.substr(1, p.length - 2); - else return p; - }); - const star = path8.indexOf("*"); - if (star > -1) { - const before = path8.slice(0, star); - const beforeStr = before.join("."); - const after = path8.slice(star + 1, path8.length); - const nested = after.length > 0; - wcLen++; - wildcards.push({ - before, - beforeStr, - after, - nested - }); - } else { - o2[strPath] = { - path: path8, - val: void 0, - precensored: false, - circle: "", - escPath: JSON.stringify(strPath), - leadingBracket - }; - } - return o2; - }, {}); - return { wildcards, wcLen, secret }; - } + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.FT_AGGREGATE_STEPS = exports2.FT_AGGREGATE_GROUP_BY_REDUCERS = exports2.SCHEMA_VECTOR_FIELD_ALGORITHM = exports2.SCHEMA_TEXT_FIELD_PHONETIC = exports2.SCHEMA_FIELD_TYPE = exports2.REDISEARCH_LANGUAGE = exports2.default = void 0; + var commands_1 = require_commands5(); + Object.defineProperty(exports2, "default", { enumerable: true, get: function() { + return __importDefault(commands_1).default; + } }); + var CREATE_1 = require_CREATE2(); + Object.defineProperty(exports2, "REDISEARCH_LANGUAGE", { enumerable: true, get: function() { + return CREATE_1.REDISEARCH_LANGUAGE; + } }); + Object.defineProperty(exports2, "SCHEMA_FIELD_TYPE", { enumerable: true, get: function() { + return CREATE_1.SCHEMA_FIELD_TYPE; + } }); + Object.defineProperty(exports2, "SCHEMA_TEXT_FIELD_PHONETIC", { enumerable: true, get: function() { + return CREATE_1.SCHEMA_TEXT_FIELD_PHONETIC; + } }); + Object.defineProperty(exports2, "SCHEMA_VECTOR_FIELD_ALGORITHM", { enumerable: true, get: function() { + return CREATE_1.SCHEMA_VECTOR_FIELD_ALGORITHM; + } }); + var AGGREGATE_1 = require_AGGREGATE(); + Object.defineProperty(exports2, "FT_AGGREGATE_GROUP_BY_REDUCERS", { enumerable: true, get: function() { + return AGGREGATE_1.FT_AGGREGATE_GROUP_BY_REDUCERS; + } }); + Object.defineProperty(exports2, "FT_AGGREGATE_STEPS", { enumerable: true, get: function() { + return AGGREGATE_1.FT_AGGREGATE_STEPS; + } }); } }); -var require_redactor = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/redactor.js"(exports2, module14) { +var require_helpers2 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/helpers.js"(exports2) { "use strict"; - var rx = require_rx(); - module14.exports = redactor; - function redactor({ secret, serialize, wcLen, strict, isCensorFct, censorFctTakesPath }, state) { - const redact = Function("o", ` - if (typeof o !== 'object' || o == null) { - ${strictImpl(strict, serialize)} - } - const { censor, secret } = this - const originalSecret = {} - const secretKeys = Object.keys(secret) - for (var i = 0; i < secretKeys.length; i++) { - originalSecret[secretKeys[i]] = secret[secretKeys[i]] - } - - ${redactTmpl(secret, isCensorFct, censorFctTakesPath)} - this.compileRestore() - ${dynamicRedactTmpl(wcLen > 0, isCensorFct, censorFctTakesPath)} - this.secret = originalSecret - ${resultTmpl(serialize)} - `).bind(state); - redact.state = state; - if (serialize === false) { - redact.restore = (o2) => state.restore(o2); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transformRESP2LabelsWithSources = exports2.transformRESP2Labels = exports2.parseSelectedLabelsArguments = exports2.resp3MapToValue = exports2.resp2MapToValue = exports2.transformSamplesReply = exports2.transformSampleReply = exports2.parseLabelsArgument = exports2.transformTimestampArgument = exports2.parseDuplicatePolicy = exports2.TIME_SERIES_DUPLICATE_POLICIES = exports2.parseChunkSizeArgument = exports2.parseEncodingArgument = exports2.TIME_SERIES_ENCODING = exports2.parseRetentionArgument = exports2.parseIgnoreArgument = void 0; + var client_1 = require_dist(); + function parseIgnoreArgument(parser3, ignore) { + if (ignore !== void 0) { + parser3.push("IGNORE", ignore.maxTimeDiff.toString(), ignore.maxValDiff.toString()); } - return redact; } - function redactTmpl(secret, isCensorFct, censorFctTakesPath) { - return Object.keys(secret).map((path8) => { - const { escPath, leadingBracket, path: arrPath } = secret[path8]; - const skip = leadingBracket ? 1 : 0; - const delim = leadingBracket ? "" : "."; - const hops = []; - var match; - while ((match = rx.exec(path8)) !== null) { - const [, ix] = match; - const { index, input } = match; - if (index > skip) hops.push(input.substring(0, index - (ix ? 0 : 1))); - } - var existence = hops.map((p) => `o${delim}${p}`).join(" && "); - if (existence.length === 0) existence += `o${delim}${path8} != null`; - else existence += ` && o${delim}${path8} != null`; - const circularDetection = ` - switch (true) { - ${hops.reverse().map((p) => ` - case o${delim}${p} === censor: - secret[${escPath}].circle = ${JSON.stringify(p)} - break - `).join("\n")} - } - `; - const censorArgs = censorFctTakesPath ? `val, ${JSON.stringify(arrPath)}` : `val`; - return ` - if (${existence}) { - const val = o${delim}${path8} - if (val === censor) { - secret[${escPath}].precensored = true - } else { - secret[${escPath}].val = val - o${delim}${path8} = ${isCensorFct ? `censor(${censorArgs})` : "censor"} - ${circularDetection} - } + exports2.parseIgnoreArgument = parseIgnoreArgument; + function parseRetentionArgument(parser3, retention) { + if (retention !== void 0) { + parser3.push("RETENTION", retention.toString()); } - `; - }).join("\n"); } - function dynamicRedactTmpl(hasWildcards, isCensorFct, censorFctTakesPath) { - return hasWildcards === true ? ` - { - const { wildcards, wcLen, groupRedact, nestedRedact } = this - for (var i = 0; i < wcLen; i++) { - const { before, beforeStr, after, nested } = wildcards[i] - if (nested === true) { - secret[beforeStr] = secret[beforeStr] || [] - nestedRedact(secret[beforeStr], o, before, after, censor, ${isCensorFct}, ${censorFctTakesPath}) - } else secret[beforeStr] = groupRedact(o, before, censor, ${isCensorFct}, ${censorFctTakesPath}) + exports2.parseRetentionArgument = parseRetentionArgument; + exports2.TIME_SERIES_ENCODING = { + COMPRESSED: "COMPRESSED", + UNCOMPRESSED: "UNCOMPRESSED" + }; + function parseEncodingArgument(parser3, encoding) { + if (encoding !== void 0) { + parser3.push("ENCODING", encoding); } } - ` : ""; - } - function resultTmpl(serialize) { - return serialize === false ? `return o` : ` - var s = this.serialize(o) - this.restore(o) - return s - `; - } - function strictImpl(strict, serialize) { - return strict === true ? `throw Error('fast-redact: primitives cannot be redacted')` : serialize === false ? `return o` : `return this.serialize(o)`; + exports2.parseEncodingArgument = parseEncodingArgument; + function parseChunkSizeArgument(parser3, chunkSize) { + if (chunkSize !== void 0) { + parser3.push("CHUNK_SIZE", chunkSize.toString()); + } } - } -}); -var require_modifiers = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/modifiers.js"(exports2, module14) { - "use strict"; - module14.exports = { - groupRedact, - groupRestore, - nestedRedact, - nestedRestore + exports2.parseChunkSizeArgument = parseChunkSizeArgument; + exports2.TIME_SERIES_DUPLICATE_POLICIES = { + BLOCK: "BLOCK", + FIRST: "FIRST", + LAST: "LAST", + MIN: "MIN", + MAX: "MAX", + SUM: "SUM" }; - function groupRestore({ keys, values, target }) { - if (target == null || typeof target === "string") return; - const length2 = keys.length; - for (var i2 = 0; i2 < length2; i2++) { - const k = keys[i2]; - target[k] = values[i2]; + function parseDuplicatePolicy(parser3, duplicatePolicy) { + if (duplicatePolicy !== void 0) { + parser3.push("DUPLICATE_POLICY", duplicatePolicy); } } - function groupRedact(o2, path8, censor, isCensorFct, censorFctTakesPath) { - const target = get2(o2, path8); - if (target == null || typeof target === "string") return { keys: null, values: null, target, flat: true }; - const keys = Object.keys(target); - const keysLength = keys.length; - const pathLength = path8.length; - const pathWithKey = censorFctTakesPath ? [...path8] : void 0; - const values = new Array(keysLength); - for (var i2 = 0; i2 < keysLength; i2++) { - const key = keys[i2]; - values[i2] = target[key]; - if (censorFctTakesPath) { - pathWithKey[pathLength] = key; - target[key] = censor(target[key], pathWithKey); - } else if (isCensorFct) { - target[key] = censor(target[key]); - } else { - target[key] = censor; - } - } - return { keys, values, target, flat: true }; + exports2.parseDuplicatePolicy = parseDuplicatePolicy; + function transformTimestampArgument(timestamp) { + if (typeof timestamp === "string") + return timestamp; + return (typeof timestamp === "number" ? timestamp : timestamp.getTime()).toString(); } - function nestedRestore(instructions) { - for (let i2 = 0; i2 < instructions.length; i2++) { - const { target, path: path8, value } = instructions[i2]; - let current = target; - for (let i3 = path8.length - 1; i3 > 0; i3--) { - current = current[path8[i3]]; + exports2.transformTimestampArgument = transformTimestampArgument; + function parseLabelsArgument(parser3, labels) { + if (labels) { + parser3.push("LABELS"); + for (const [label, value] of Object.entries(labels)) { + parser3.push(label, value); } - current[path8[0]] = value; } } - function nestedRedact(store, o2, path8, ns, censor, isCensorFct, censorFctTakesPath) { - const target = get2(o2, path8); - if (target == null) return; - const keys = Object.keys(target); - const keysLength = keys.length; - for (var i2 = 0; i2 < keysLength; i2++) { - const key = keys[i2]; - specialSet(store, target, key, path8, ns, censor, isCensorFct, censorFctTakesPath); + exports2.parseLabelsArgument = parseLabelsArgument; + exports2.transformSampleReply = { + 2(reply) { + const [timestamp, value] = reply; + return { + timestamp, + value: Number(value) + // TODO: use double type mapping instead + }; + }, + 3(reply) { + const [timestamp, value] = reply; + return { + timestamp, + value + }; } - return store; - } - function has2(obj, prop) { - return obj !== void 0 && obj !== null ? "hasOwn" in Object ? Object.hasOwn(obj, prop) : Object.prototype.hasOwnProperty.call(obj, prop) : false; - } - function specialSet(store, o2, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath) { - const afterPathLen = afterPath.length; - const lastPathIndex = afterPathLen - 1; - const originalKey = k; - var i2 = -1; - var n; - var nv; - var ov; - var oov = null; - var wc = null; - var kIsWc; - var wcov; - var consecutive = false; - var level = 0; - var depth = 0; - var redactPathCurrent = tree(); - ov = n = o2[k]; - if (typeof n !== "object") return; - while (n != null && ++i2 < afterPathLen) { - depth += 1; - k = afterPath[i2]; - oov = ov; - if (k !== "*" && !wc && !(typeof n === "object" && k in n)) { - break; - } - if (k === "*") { - if (wc === "*") { - consecutive = true; - } - wc = k; - if (i2 !== lastPathIndex) { - continue; + }; + exports2.transformSamplesReply = { + 2(reply) { + return reply.map((sample) => exports2.transformSampleReply[2](sample)); + }, + 3(reply) { + return reply.map((sample) => exports2.transformSampleReply[3](sample)); + } + }; + function resp2MapToValue(wrappedReply, parseFunc, typeMapping) { + const reply = wrappedReply; + switch (typeMapping?.[client_1.RESP_TYPES.MAP]) { + case Map: { + const ret = /* @__PURE__ */ new Map(); + for (const wrappedTuple of reply) { + const tuple = wrappedTuple; + const key = tuple[0]; + ret.set(key.toString(), parseFunc(tuple)); } + return ret; } - if (wc) { - const wcKeys = Object.keys(n); - for (var j = 0; j < wcKeys.length; j++) { - const wck = wcKeys[j]; - wcov = n[wck]; - kIsWc = k === "*"; - if (consecutive) { - redactPathCurrent = node(redactPathCurrent, wck, depth); - level = i2; - ov = iterateNthLevel(wcov, level - 1, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath, originalKey, n, nv, ov, kIsWc, wck, i2, lastPathIndex, redactPathCurrent, store, o2[originalKey], depth + 1); - } else { - if (kIsWc || typeof wcov === "object" && wcov !== null && k in wcov) { - if (kIsWc) { - ov = wcov; - } else { - ov = wcov[k]; - } - nv = i2 !== lastPathIndex ? ov : isCensorFct ? censorFctTakesPath ? censor(ov, [...path8, originalKey, ...afterPath]) : censor(ov) : censor; - if (kIsWc) { - const rv = restoreInstr(node(redactPathCurrent, wck, depth), ov, o2[originalKey]); - store.push(rv); - n[wck] = nv; - } else { - if (wcov[k] === nv) { - } else if (nv === void 0 && censor !== void 0 || has2(wcov, k) && nv === ov) { - redactPathCurrent = node(redactPathCurrent, wck, depth); - } else { - redactPathCurrent = node(redactPathCurrent, wck, depth); - const rv = restoreInstr(node(redactPathCurrent, k, depth + 1), ov, o2[originalKey]); - store.push(rv); - wcov[k] = nv; - } - } - } - } - } - wc = null; - } else { - ov = n[k]; - redactPathCurrent = node(redactPathCurrent, k, depth); - nv = i2 !== lastPathIndex ? ov : isCensorFct ? censorFctTakesPath ? censor(ov, [...path8, originalKey, ...afterPath]) : censor(ov) : censor; - if (has2(n, k) && nv === ov || nv === void 0 && censor !== void 0) { - } else { - const rv = restoreInstr(redactPathCurrent, ov, o2[originalKey]); - store.push(rv); - n[k] = nv; + case Array: { + for (const wrappedTuple of reply) { + const tuple = wrappedTuple; + tuple[1] = parseFunc(tuple); } - n = n[k]; + return reply; } - if (typeof n !== "object") break; - if (ov === oov || typeof ov === "undefined") { + default: { + const ret = /* @__PURE__ */ Object.create(null); + for (const wrappedTuple of reply) { + const tuple = wrappedTuple; + const key = tuple[0]; + ret[key.toString()] = parseFunc(tuple); + } + return ret; } } } - function get2(o2, p) { - var i2 = -1; - var l = p.length; - var n = o2; - while (n != null && ++i2 < l) { - n = n[p[i2]]; - } - return n; - } - function iterateNthLevel(wcov, level, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath, originalKey, n, nv, ov, kIsWc, wck, i2, lastPathIndex, redactPathCurrent, store, parent, depth) { - if (level === 0) { - if (kIsWc || typeof wcov === "object" && wcov !== null && k in wcov) { - if (kIsWc) { - ov = wcov; - } else { - ov = wcov[k]; - } - nv = i2 !== lastPathIndex ? ov : isCensorFct ? censorFctTakesPath ? censor(ov, [...path8, originalKey, ...afterPath]) : censor(ov) : censor; - if (kIsWc) { - const rv = restoreInstr(redactPathCurrent, ov, parent); - store.push(rv); - n[wck] = nv; - } else { - if (wcov[k] === nv) { - } else if (nv === void 0 && censor !== void 0 || has2(wcov, k) && nv === ov) { - } else { - const rv = restoreInstr(node(redactPathCurrent, k, depth + 1), ov, parent); - store.push(rv); - wcov[k] = nv; - } - } + exports2.resp2MapToValue = resp2MapToValue; + function resp3MapToValue(wrappedReply, parseFunc) { + const reply = wrappedReply; + if (reply instanceof Array) { + for (let i2 = 1; i2 < reply.length; i2 += 2) { + reply[i2] = parseFunc(reply[i2]); } - } - for (const key in wcov) { - if (typeof wcov[key] === "object") { - redactPathCurrent = node(redactPathCurrent, key, depth); - iterateNthLevel(wcov[key], level - 1, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath, originalKey, n, nv, ov, kIsWc, wck, i2, lastPathIndex, redactPathCurrent, store, parent, depth + 1); + } else if (reply instanceof Map) { + for (const [key, value] of reply.entries()) { + reply.set(key, parseFunc(value)); + } + } else { + for (const [key, value] of Object.entries(reply)) { + reply[key] = parseFunc(value); } } + return reply; } - function tree() { - return { parent: null, key: null, children: [], depth: 0 }; + exports2.resp3MapToValue = resp3MapToValue; + function parseSelectedLabelsArguments(parser3, selectedLabels) { + parser3.push("SELECTED_LABELS"); + parser3.pushVariadic(selectedLabels); } - function node(parent, key, depth) { - if (parent.depth === depth) { - return node(parent.parent, key, depth); + exports2.parseSelectedLabelsArguments = parseSelectedLabelsArguments; + function transformRESP2Labels(labels, typeMapping) { + const unwrappedLabels = labels; + switch (typeMapping?.[client_1.RESP_TYPES.MAP]) { + case Map: + const map = /* @__PURE__ */ new Map(); + for (const tuple of unwrappedLabels) { + const [key, value] = tuple; + const unwrappedKey = key; + map.set(unwrappedKey.toString(), value); + } + return map; + case Array: + return unwrappedLabels.flat(); + case Object: + default: + const labelsObject = /* @__PURE__ */ Object.create(null); + for (const tuple of unwrappedLabels) { + const [key, value] = tuple; + const unwrappedKey = key; + labelsObject[unwrappedKey.toString()] = value; + } + return labelsObject; } - var child = { - parent, - key, - depth, - children: [] - }; - parent.children.push(child); - return child; - } - function restoreInstr(node2, value, target) { - let current = node2; - const path8 = []; - do { - path8.push(current.key); - current = current.parent; - } while (current.parent != null); - return { path: path8, value, target }; - } - } -}); -var require_restorer = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/restorer.js"(exports2, module14) { - "use strict"; - var { groupRestore, nestedRestore } = require_modifiers(); - module14.exports = restorer; - function restorer() { - return function compileRestore() { - if (this.restore) { - this.restore.state.secret = this.secret; - return; - } - const { secret, wcLen } = this; - const paths = Object.keys(secret); - const resetters = resetTmpl(secret, paths); - const hasWildcards = wcLen > 0; - const state = hasWildcards ? { secret, groupRestore, nestedRestore } : { secret }; - this.restore = Function( - "o", - restoreTmpl(resetters, paths, hasWildcards) - ).bind(state); - this.restore.state = state; - }; } - function resetTmpl(secret, paths) { - return paths.map((path8) => { - const { circle, escPath, leadingBracket } = secret[path8]; - const delim = leadingBracket ? "" : "."; - const reset = circle ? `o.${circle} = secret[${escPath}].val` : `o${delim}${path8} = secret[${escPath}].val`; - const clear = `secret[${escPath}].val = undefined`; - return ` - if (secret[${escPath}].val !== undefined) { - try { ${reset} } catch (e) {} - ${clear} + exports2.transformRESP2Labels = transformRESP2Labels; + function transformRESP2LabelsWithSources(labels, typeMapping) { + const unwrappedLabels = labels; + const to = unwrappedLabels.length - 2; + let transformedLabels; + switch (typeMapping?.[client_1.RESP_TYPES.MAP]) { + case Map: + const map = /* @__PURE__ */ new Map(); + for (let i2 = 0; i2 < to; i2++) { + const [key, value] = unwrappedLabels[i2]; + const unwrappedKey = key; + map.set(unwrappedKey.toString(), value); + } + transformedLabels = map; + break; + case Array: + transformedLabels = unwrappedLabels.slice(0, to).flat(); + break; + case Object: + default: + const labelsObject = /* @__PURE__ */ Object.create(null); + for (let i2 = 0; i2 < to; i2++) { + const [key, value] = unwrappedLabels[i2]; + const unwrappedKey = key; + labelsObject[unwrappedKey.toString()] = value; + } + transformedLabels = labelsObject; + break; } - `; - }).join(""); + const sourcesTuple = unwrappedLabels[unwrappedLabels.length - 1]; + const unwrappedSourcesTuple = sourcesTuple; + const transformedSources = transformRESP2Sources(unwrappedSourcesTuple[1]); + return { + labels: transformedLabels, + sources: transformedSources + }; } - function restoreTmpl(resetters, paths, hasWildcards) { - const dynamicReset = hasWildcards === true ? ` - const keys = Object.keys(secret) - const len = keys.length - for (var i = len - 1; i >= ${paths.length}; i--) { - const k = keys[i] - const o = secret[k] - if (o) { - if (o.flat === true) this.groupRestore(o) - else this.nestedRestore(o) - secret[k] = null + exports2.transformRESP2LabelsWithSources = transformRESP2LabelsWithSources; + function transformRESP2Sources(sourcesRaw) { + const unwrappedSources = sourcesRaw; + if (typeof unwrappedSources === "string") { + return unwrappedSources.split(","); } - } - ` : ""; - return ` - const secret = this.secret - ${dynamicReset} - ${resetters} - return o - `; + const indexOfComma = unwrappedSources.indexOf(","); + if (indexOfComma === -1) { + return [unwrappedSources]; + } + const sourcesArray = [ + unwrappedSources.subarray(0, indexOfComma) + ]; + let previousComma = indexOfComma + 1; + while (true) { + const indexOf = unwrappedSources.indexOf(",", previousComma); + if (indexOf === -1) { + sourcesArray.push(unwrappedSources.subarray(previousComma)); + break; + } + const source = unwrappedSources.subarray(previousComma, indexOf); + sourcesArray.push(source); + previousComma = indexOf + 1; + } + return sourcesArray; } } }); -var require_state2 = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/state.js"(exports2, module14) { +var require_ADD5 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/ADD.js"(exports2) { "use strict"; - module14.exports = state; - function state(o2) { - const { - secret, - censor, - compileRestore, - serialize, - groupRedact, - nestedRedact, - wildcards, - wcLen - } = o2; - const builder = [{ secret, censor, compileRestore }]; - if (serialize !== false) builder.push({ serialize }); - if (wcLen > 0) builder.push({ groupRedact, nestedRedact, wildcards, wcLen }); - return Object.assign(...builder); - } + Object.defineProperty(exports2, "__esModule", { value: true }); + var helpers_1 = require_helpers2(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Creates or appends a sample to a time series + * @param parser - The command parser + * @param key - The key name for the time series + * @param timestamp - The timestamp of the sample + * @param value - The value of the sample + * @param options - Optional configuration parameters + */ + parseCommand(parser3, key, timestamp, value, options2) { + parser3.push("TS.ADD"); + parser3.pushKey(key); + parser3.push((0, helpers_1.transformTimestampArgument)(timestamp), value.toString()); + (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); + (0, helpers_1.parseEncodingArgument)(parser3, options2?.ENCODING); + (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); + if (options2?.ON_DUPLICATE) { + parser3.push("ON_DUPLICATE", options2.ON_DUPLICATE); + } + (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); + (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); + }, + transformReply: void 0 + }; } }); -var require_fast_redact = __commonJS({ - "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/index.js"(exports2, module14) { +var require_ALTER2 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/ALTER.js"(exports2) { "use strict"; - var validator = require_validator2(); - var parse52 = require_parse(); - var redactor = require_redactor(); - var restorer = require_restorer(); - var { groupRedact, nestedRedact } = require_modifiers(); - var state = require_state2(); - var rx = require_rx(); - var validate = validator(); - var noop = (o2) => o2; - noop.restore = noop; - var DEFAULT_CENSOR = "[REDACTED]"; - fastRedact.rx = rx; - fastRedact.validator = validator; - module14.exports = fastRedact; - function fastRedact(opts = {}) { - const paths = Array.from(new Set(opts.paths || [])); - const serialize = "serialize" in opts ? opts.serialize === false ? opts.serialize : typeof opts.serialize === "function" ? opts.serialize : JSON.stringify : JSON.stringify; - const remove = opts.remove; - if (remove === true && serialize !== JSON.stringify) { - throw Error("fast-redact \u2013 remove option may only be set when serializer is JSON.stringify"); - } - const censor = remove === true ? void 0 : "censor" in opts ? opts.censor : DEFAULT_CENSOR; - const isCensorFct = typeof censor === "function"; - const censorFctTakesPath = isCensorFct && censor.length > 1; - if (paths.length === 0) return serialize || noop; - validate({ paths, serialize, censor }); - const { wildcards, wcLen, secret } = parse52({ paths, censor }); - const compileRestore = restorer(); - const strict = "strict" in opts ? opts.strict : true; - return redactor({ secret, wcLen, serialize, strict, isCensorFct, censorFctTakesPath }, state({ - secret, - censor, - compileRestore, - serialize, - groupRedact, - nestedRedact, - wildcards, - wcLen - })); - } + Object.defineProperty(exports2, "__esModule", { value: true }); + var helpers_1 = require_helpers2(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Alters the configuration of an existing time series + * @param parser - The command parser + * @param key - The key name for the time series + * @param options - Configuration parameters to alter + */ + parseCommand(parser3, key, options2) { + parser3.push("TS.ALTER"); + parser3.pushKey(key); + (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); + (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); + (0, helpers_1.parseDuplicatePolicy)(parser3, options2?.DUPLICATE_POLICY); + (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); + (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); + }, + transformReply: void 0 + }; } }); -var require_symbols2 = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/symbols.js"(exports2, module14) { +var require_CREATE3 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/CREATE.js"(exports2) { "use strict"; - var setLevelSym = Symbol("pino.setLevel"); - var getLevelSym = Symbol("pino.getLevel"); - var levelValSym = Symbol("pino.levelVal"); - var levelCompSym = Symbol("pino.levelComp"); - var useLevelLabelsSym = Symbol("pino.useLevelLabels"); - var useOnlyCustomLevelsSym = Symbol("pino.useOnlyCustomLevels"); - var mixinSym = Symbol("pino.mixin"); - var lsCacheSym = Symbol("pino.lsCache"); - var chindingsSym = Symbol("pino.chindings"); - var asJsonSym = Symbol("pino.asJson"); - var writeSym = Symbol("pino.write"); - var redactFmtSym = Symbol("pino.redactFmt"); - var timeSym = Symbol("pino.time"); - var timeSliceIndexSym = Symbol("pino.timeSliceIndex"); - var streamSym = Symbol("pino.stream"); - var stringifySym = Symbol("pino.stringify"); - var stringifySafeSym = Symbol("pino.stringifySafe"); - var stringifiersSym = Symbol("pino.stringifiers"); - var endSym = Symbol("pino.end"); - var formatOptsSym = Symbol("pino.formatOpts"); - var messageKeySym = Symbol("pino.messageKey"); - var errorKeySym = Symbol("pino.errorKey"); - var nestedKeySym = Symbol("pino.nestedKey"); - var nestedKeyStrSym = Symbol("pino.nestedKeyStr"); - var mixinMergeStrategySym = Symbol("pino.mixinMergeStrategy"); - var msgPrefixSym = Symbol("pino.msgPrefix"); - var wildcardFirstSym = Symbol("pino.wildcardFirst"); - var serializersSym = Symbol.for("pino.serializers"); - var formattersSym = Symbol.for("pino.formatters"); - var hooksSym = Symbol.for("pino.hooks"); - var needsMetadataGsym = Symbol.for("pino.metadata"); - module14.exports = { - setLevelSym, - getLevelSym, - levelValSym, - levelCompSym, - useLevelLabelsSym, - mixinSym, - lsCacheSym, - chindingsSym, - asJsonSym, - writeSym, - serializersSym, - redactFmtSym, - timeSym, - timeSliceIndexSym, - streamSym, - stringifySym, - stringifySafeSym, - stringifiersSym, - endSym, - formatOptsSym, - messageKeySym, - errorKeySym, - nestedKeySym, - wildcardFirstSym, - needsMetadataGsym, - useOnlyCustomLevelsSym, - formattersSym, - hooksSym, - nestedKeyStrSym, - mixinMergeStrategySym, - msgPrefixSym + Object.defineProperty(exports2, "__esModule", { value: true }); + var helpers_1 = require_helpers2(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Creates a new time series + * @param parser - The command parser + * @param key - The key name for the new time series + * @param options - Optional configuration parameters + */ + parseCommand(parser3, key, options2) { + parser3.push("TS.CREATE"); + parser3.pushKey(key); + (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); + (0, helpers_1.parseEncodingArgument)(parser3, options2?.ENCODING); + (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); + (0, helpers_1.parseDuplicatePolicy)(parser3, options2?.DUPLICATE_POLICY); + (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); + (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); + }, + transformReply: void 0 }; } }); -var require_redaction = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/redaction.js"(exports2, module14) { +var require_CREATERULE = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/CREATERULE.js"(exports2) { "use strict"; - var fastRedact = require_fast_redact(); - var { redactFmtSym, wildcardFirstSym } = require_symbols2(); - var { rx, validator } = fastRedact; - var validate = validator({ - ERR_PATHS_MUST_BE_STRINGS: () => "pino \u2013 redacted paths must be strings", - ERR_INVALID_PATH: (s) => `pino \u2013 redact paths array contains an invalid path (${s})` - }); - var CENSOR = "[Redacted]"; - var strict = false; - function redaction(opts, serialize) { - const { paths, censor } = handle(opts); - const shape = paths.reduce((o2, str) => { - rx.lastIndex = 0; - const first = rx.exec(str); - const next = rx.exec(str); - let ns = first[1] !== void 0 ? first[1].replace(/^(?:"|'|`)(.*)(?:"|'|`)$/, "$1") : first[0]; - if (ns === "*") { - ns = wildcardFirstSym; - } - if (next === null) { - o2[ns] = null; - return o2; - } - if (o2[ns] === null) { - return o2; - } - const { index } = next; - const nextPath = `${str.substr(index, str.length - 1)}`; - o2[ns] = o2[ns] || []; - if (ns !== wildcardFirstSym && o2[ns].length === 0) { - o2[ns].push(...o2[wildcardFirstSym] || []); - } - if (ns === wildcardFirstSym) { - Object.keys(o2).forEach(function(k) { - if (o2[k]) { - o2[k].push(nextPath); - } - }); - } - o2[ns].push(nextPath); - return o2; - }, {}); - const result = { - [redactFmtSym]: fastRedact({ paths, censor, serialize, strict }) - }; - const topCensor = (...args) => { - return typeof censor === "function" ? serialize(censor(...args)) : serialize(censor); - }; - return [...Object.keys(shape), ...Object.getOwnPropertySymbols(shape)].reduce((o2, k) => { - if (shape[k] === null) { - o2[k] = (value) => topCensor(value, [k]); - } else { - const wrappedCensor = typeof censor === "function" ? (value, path8) => { - return censor(value, [k, ...path8]); - } : censor; - o2[k] = fastRedact({ - paths: shape[k], - censor: wrappedCensor, - serialize, - strict - }); + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.TIME_SERIES_AGGREGATION_TYPE = void 0; + exports2.TIME_SERIES_AGGREGATION_TYPE = { + AVG: "AVG", + FIRST: "FIRST", + LAST: "LAST", + MIN: "MIN", + MAX: "MAX", + SUM: "SUM", + RANGE: "RANGE", + COUNT: "COUNT", + STD_P: "STD.P", + STD_S: "STD.S", + VAR_P: "VAR.P", + VAR_S: "VAR.S", + TWA: "TWA" + }; + exports2.default = { + IS_READ_ONLY: false, + /** + * Creates a compaction rule from source time series to destination time series + * @param parser - The command parser + * @param sourceKey - The source time series key + * @param destinationKey - The destination time series key + * @param aggregationType - The aggregation type to use + * @param bucketDuration - The duration of each bucket in milliseconds + * @param alignTimestamp - Optional timestamp for alignment + */ + parseCommand(parser3, sourceKey, destinationKey, aggregationType, bucketDuration, alignTimestamp) { + parser3.push("TS.CREATERULE"); + parser3.pushKeys([sourceKey, destinationKey]); + parser3.push("AGGREGATION", aggregationType, bucketDuration.toString()); + if (alignTimestamp !== void 0) { + parser3.push(alignTimestamp.toString()); } - return o2; - }, result); - } - function handle(opts) { - if (Array.isArray(opts)) { - opts = { paths: opts, censor: CENSOR }; - validate(opts); - return opts; + }, + transformReply: void 0 + }; + } +}); +var require_INCRBY4 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/INCRBY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseIncrByArguments = void 0; + var helpers_1 = require_helpers2(); + function parseIncrByArguments(parser3, key, value, options2) { + parser3.pushKey(key); + parser3.push(value.toString()); + if (options2?.TIMESTAMP !== void 0 && options2?.TIMESTAMP !== null) { + parser3.push("TIMESTAMP", (0, helpers_1.transformTimestampArgument)(options2.TIMESTAMP)); } - let { paths, censor = CENSOR, remove } = opts; - if (Array.isArray(paths) === false) { - throw Error("pino \u2013 redact must contain an array of strings"); + (0, helpers_1.parseRetentionArgument)(parser3, options2?.RETENTION); + if (options2?.UNCOMPRESSED) { + parser3.push("UNCOMPRESSED"); } - if (remove === true) censor = void 0; - validate({ paths, censor }); - return { paths, censor }; + (0, helpers_1.parseChunkSizeArgument)(parser3, options2?.CHUNK_SIZE); + (0, helpers_1.parseLabelsArgument)(parser3, options2?.LABELS); + (0, helpers_1.parseIgnoreArgument)(parser3, options2?.IGNORE); } - module14.exports = redaction; + exports2.parseIncrByArguments = parseIncrByArguments; + exports2.default = { + IS_READ_ONLY: false, + /** + * Increases the value of a time series by a given amount + * @param args - Arguments passed to the {@link parseIncrByArguments} function + */ + parseCommand(...args) { + const parser3 = args[0]; + parser3.push("TS.INCRBY"); + parseIncrByArguments(...args); + }, + transformReply: void 0 + }; } }); -var require_time = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/time.js"(exports2, module14) { +var require_DECRBY2 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/DECRBY.js"(exports2) { "use strict"; - var nullTime = () => ""; - var epochTime = () => `,"time":${Date.now()}`; - var unixTime = () => `,"time":${Math.round(Date.now() / 1e3)}`; - var isoTime = () => `,"time":"${new Date(Date.now()).toISOString()}"`; - module14.exports = { nullTime, epochTime, unixTime, isoTime }; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var INCRBY_1 = __importStar(require_INCRBY4()); + exports2.default = { + IS_READ_ONLY: INCRBY_1.default.IS_READ_ONLY, + /** + * Decreases the value of a time series by a given amount + * @param args - Arguments passed to the parseIncrByArguments function + */ + parseCommand(...args) { + const parser3 = args[0]; + parser3.push("TS.DECRBY"); + (0, INCRBY_1.parseIncrByArguments)(...args); + }, + transformReply: INCRBY_1.default.transformReply + }; } }); -var require_quick_format_unescaped = __commonJS({ - "node_modules/.deno/quick-format-unescaped@4.0.4/node_modules/quick-format-unescaped/index.js"(exports2, module14) { +var require_DEL4 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/DEL.js"(exports2) { "use strict"; - function tryStringify(o2) { - try { - return JSON.stringify(o2); - } catch (e2) { - return '"[Circular]"'; - } - } - module14.exports = format52; - function format52(f, args, opts) { - var ss = opts && opts.stringify || tryStringify; - var offset = 1; - if (typeof f === "object" && f !== null) { - var len = args.length + offset; - if (len === 1) return f; - var objects = new Array(len); - objects[0] = ss(f); - for (var index = 1; index < len; index++) { - objects[index] = ss(args[index]); + Object.defineProperty(exports2, "__esModule", { value: true }); + var helpers_1 = require_helpers2(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Deletes samples between two timestamps from a time series + * @param parser - The command parser + * @param key - The key name of the time series + * @param fromTimestamp - Start timestamp to delete from + * @param toTimestamp - End timestamp to delete until + */ + parseCommand(parser3, key, fromTimestamp, toTimestamp) { + parser3.push("TS.DEL"); + parser3.pushKey(key); + parser3.push((0, helpers_1.transformTimestampArgument)(fromTimestamp), (0, helpers_1.transformTimestampArgument)(toTimestamp)); + }, + transformReply: void 0 + }; + } +}); +var require_DELETERULE = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/DELETERULE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: false, + /** + * Deletes a compaction rule between source and destination time series + * @param parser - The command parser + * @param sourceKey - The source time series key + * @param destinationKey - The destination time series key + */ + parseCommand(parser3, sourceKey, destinationKey) { + parser3.push("TS.DELETERULE"); + parser3.pushKeys([sourceKey, destinationKey]); + }, + transformReply: void 0 + }; + } +}); +var require_GET3 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/GET.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets the last sample of a time series + * @param parser - The command parser + * @param key - The key name of the time series + * @param options - Optional parameters for the command + */ + parseCommand(parser3, key, options2) { + parser3.push("TS.GET"); + parser3.pushKey(key); + if (options2?.LATEST) { + parser3.push("LATEST"); } - return objects.join(" "); - } - if (typeof f !== "string") { - return f; - } - var argLen = args.length; - if (argLen === 0) return f; - var str = ""; - var a = 1 - offset; - var lastPos = -1; - var flen = f && f.length || 0; - for (var i2 = 0; i2 < flen; ) { - if (f.charCodeAt(i2) === 37 && i2 + 1 < flen) { - lastPos = lastPos > -1 ? lastPos : 0; - switch (f.charCodeAt(i2 + 1)) { - case 100: - // 'd' - case 102: - if (a >= argLen) + }, + transformReply: { + 2(reply) { + return reply.length === 0 ? null : { + timestamp: reply[0], + value: Number(reply[1]) + }; + }, + 3(reply) { + return reply.length === 0 ? null : { + timestamp: reply[0], + value: reply[1] + }; + } + } + }; + } +}); +var require_INFO8 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/INFO.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var generic_transformers_1 = require_generic_transformers(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets information about a time series + * @param parser - The command parser + * @param key - The key name of the time series + */ + parseCommand(parser3, key) { + parser3.push("TS.INFO"); + parser3.pushKey(key); + }, + transformReply: { + 2: (reply, _, typeMapping) => { + const ret = {}; + for (let i2 = 0; i2 < reply.length; i2 += 2) { + const key = reply[i2].toString(); + switch (key) { + case "totalSamples": + case "memoryUsage": + case "firstTimestamp": + case "lastTimestamp": + case "retentionTime": + case "chunkCount": + case "chunkSize": + case "chunkType": + case "duplicatePolicy": + case "sourceKey": + case "ignoreMaxTimeDiff": + ret[key] = reply[i2 + 1]; break; - if (args[a] == null) break; - if (lastPos < i2) - str += f.slice(lastPos, i2); - str += Number(args[a]); - lastPos = i2 + 2; - i2++; - break; - case 105: - if (a >= argLen) + case "labels": + ret[key] = reply[i2 + 1].map(([name, value]) => ({ + name, + value + })); break; - if (args[a] == null) break; - if (lastPos < i2) - str += f.slice(lastPos, i2); - str += Math.floor(Number(args[a])); - lastPos = i2 + 2; - i2++; - break; - case 79: - // 'O' - case 111: - // 'o' - case 106: - if (a >= argLen) + case "rules": + ret[key] = reply[i2 + 1].map(([key2, timeBucket, aggregationType]) => ({ + key: key2, + timeBucket, + aggregationType + })); break; - if (args[a] === void 0) break; - if (lastPos < i2) - str += f.slice(lastPos, i2); - var type = typeof args[a]; - if (type === "string") { - str += "'" + args[a] + "'"; - lastPos = i2 + 2; - i2++; + case "ignoreMaxValDiff": + ret[key] = generic_transformers_1.transformDoubleReply[2](reply[27], void 0, typeMapping); break; - } - if (type === "function") { - str += args[a].name || ""; - lastPos = i2 + 2; - i2++; + } + } + return ret; + }, + 3: void 0 + }, + unstableResp3: true + }; + } +}); +var require_INFO_DEBUG = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/INFO_DEBUG.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var INFO_1 = __importDefault(require_INFO8()); + exports2.default = { + IS_READ_ONLY: INFO_1.default.IS_READ_ONLY, + /** + * Gets debug information about a time series + * @param parser - The command parser + * @param key - The key name of the time series + */ + parseCommand(parser3, key) { + INFO_1.default.parseCommand(parser3, key); + parser3.push("DEBUG"); + }, + transformReply: { + 2: (reply, _, typeMapping) => { + const ret = INFO_1.default.transformReply[2](reply, _, typeMapping); + for (let i2 = 0; i2 < reply.length; i2 += 2) { + const key = reply[i2].toString(); + switch (key) { + case "keySelfName": { + ret[key] = reply[i2 + 1]; break; } - str += ss(args[a]); - lastPos = i2 + 2; - i2++; - break; - case 115: - if (a >= argLen) + case "Chunks": { + ret["chunks"] = reply[i2 + 1].map((chunk) => ({ + startTimestamp: chunk[1], + endTimestamp: chunk[3], + samples: chunk[5], + size: chunk[7], + bytesPerSample: chunk[9] + })); break; - if (lastPos < i2) - str += f.slice(lastPos, i2); - str += String(args[a]); - lastPos = i2 + 2; - i2++; - break; - case 37: - if (lastPos < i2) - str += f.slice(lastPos, i2); - str += "%"; - lastPos = i2 + 2; - i2++; - a--; - break; + } + } } - ++a; - } - ++i2; - } - if (lastPos === -1) - return f; - else if (lastPos < flen) { - str += f.slice(lastPos); - } - return str; - } + return ret; + }, + 3: void 0 + }, + unstableResp3: true + }; } }); -var require_atomic_sleep = __commonJS({ - "node_modules/.deno/atomic-sleep@1.0.0/node_modules/atomic-sleep/index.js"(exports2, module14) { +var require_MADD2 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MADD.js"(exports2) { "use strict"; - if (typeof SharedArrayBuffer !== "undefined" && typeof Atomics !== "undefined") { - let sleep = function(ms) { - const valid = ms > 0 && ms < Infinity; - if (valid === false) { - if (typeof ms !== "number" && typeof ms !== "bigint") { - throw TypeError("sleep: ms must be a number"); - } - throw RangeError("sleep: ms must be a number that is greater than 0 but less than Infinity"); - } - Atomics.wait(nil, 0, 0, Number(ms)); - }; - const nil = new Int32Array(new SharedArrayBuffer(4)); - module14.exports = sleep; - } else { - let sleep = function(ms) { - const valid = ms > 0 && ms < Infinity; - if (valid === false) { - if (typeof ms !== "number" && typeof ms !== "bigint") { - throw TypeError("sleep: ms must be a number"); - } - throw RangeError("sleep: ms must be a number that is greater than 0 but less than Infinity"); - } - const target = Date.now() + Number(ms); - while (target > Date.now()) { + Object.defineProperty(exports2, "__esModule", { value: true }); + var helpers_1 = require_helpers2(); + exports2.default = { + IS_READ_ONLY: false, + /** + * Adds multiple samples to multiple time series + * @param parser - The command parser + * @param toAdd - Array of samples to add to different time series + */ + parseCommand(parser3, toAdd) { + parser3.push("TS.MADD"); + for (const { key, timestamp, value } of toAdd) { + parser3.pushKey(key); + parser3.push((0, helpers_1.transformTimestampArgument)(timestamp), value.toString()); } - }; - module14.exports = sleep; - } + }, + transformReply: void 0 + }; } }); -var require_sonic_boom = __commonJS({ - "node_modules/.deno/sonic-boom@3.8.1/node_modules/sonic-boom/index.js"(exports2, module14) { +var require_MGET3 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MGET.js"(exports2) { "use strict"; - var fs = __require2("fs"); - var EventEmitter = __require2("events"); - var inherits = __require2("util").inherits; - var path8 = __require2("path"); - var sleep = require_atomic_sleep(); - var BUSY_WRITE_TIMEOUT = 100; - var kEmptyBuffer = Buffer.allocUnsafe(0); - var MAX_WRITE = 16 * 1024; - var kContentModeBuffer = "buffer"; - var kContentModeUtf8 = "utf8"; - function openFile(file, sonic) { - sonic._opening = true; - sonic._writing = true; - sonic._asyncDrainScheduled = false; - function fileOpened(err, fd) { - if (err) { - sonic._reopening = false; - sonic._writing = false; - sonic._opening = false; - if (sonic.sync) { - process.nextTick(() => { - if (sonic.listenerCount("error") > 0) { - sonic.emit("error", err); - } - }); - } else { - sonic.emit("error", err); - } - return; - } - const reopening = sonic._reopening; - sonic.fd = fd; - sonic.file = file; - sonic._reopening = false; - sonic._opening = false; - sonic._writing = false; - if (sonic.sync) { - process.nextTick(() => sonic.emit("ready")); - } else { - sonic.emit("ready"); - } - if (sonic.destroyed) { - return; - } - if (!sonic._writing && sonic._len > sonic.minLength || sonic._flushPending) { - sonic._actualWrite(); - } else if (reopening) { - process.nextTick(() => sonic.emit("drain")); - } - } - const flags = sonic.append ? "a" : "w"; - const mode = sonic.mode; - if (sonic.sync) { - try { - if (sonic.mkdir) fs.mkdirSync(path8.dirname(file), { recursive: true }); - const fd = fs.openSync(file, flags, mode); - fileOpened(null, fd); - } catch (err) { - fileOpened(err); - throw err; - } - } else if (sonic.mkdir) { - fs.mkdir(path8.dirname(file), { recursive: true }, (err) => { - if (err) return fileOpened(err); - fs.open(file, flags, mode, fileOpened); - }); - } else { - fs.open(file, flags, mode, fileOpened); - } - } - function SonicBoom(opts) { - if (!(this instanceof SonicBoom)) { - return new SonicBoom(opts); - } - let { fd, dest, minLength, maxLength, maxWrite, sync, append = true, mkdir: mkdir4, retryEAGAIN, fsync, contentMode, mode } = opts || {}; - fd = fd || dest; - this._len = 0; - this.fd = -1; - this._bufs = []; - this._lens = []; - this._writing = false; - this._ending = false; - this._reopening = false; - this._asyncDrainScheduled = false; - this._flushPending = false; - this._hwm = Math.max(minLength || 0, 16387); - this.file = null; - this.destroyed = false; - this.minLength = minLength || 0; - this.maxLength = maxLength || 0; - this.maxWrite = maxWrite || MAX_WRITE; - this.sync = sync || false; - this.writable = true; - this._fsync = fsync || false; - this.append = append || false; - this.mode = mode; - this.retryEAGAIN = retryEAGAIN || (() => true); - this.mkdir = mkdir4 || false; - let fsWriteSync; - let fsWrite; - if (contentMode === kContentModeBuffer) { - this._writingBuf = kEmptyBuffer; - this.write = writeBuffer; - this.flush = flushBuffer; - this.flushSync = flushBufferSync; - this._actualWrite = actualWriteBuffer; - fsWriteSync = () => fs.writeSync(this.fd, this._writingBuf); - fsWrite = () => fs.write(this.fd, this._writingBuf, this.release); - } else if (contentMode === void 0 || contentMode === kContentModeUtf8) { - this._writingBuf = ""; - this.write = write; - this.flush = flush; - this.flushSync = flushSync; - this._actualWrite = actualWrite; - fsWriteSync = () => fs.writeSync(this.fd, this._writingBuf, "utf8"); - fsWrite = () => fs.write(this.fd, this._writingBuf, "utf8", this.release); - } else { - throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`); - } - if (typeof fd === "number") { - this.fd = fd; - process.nextTick(() => this.emit("ready")); - } else if (typeof fd === "string") { - openFile(fd, this); - } else { - throw new Error("SonicBoom supports only file descriptors and files"); - } - if (this.minLength >= this.maxWrite) { - throw new Error(`minLength should be smaller than maxWrite (${this.maxWrite})`); - } - this.release = (err, n) => { - if (err) { - if ((err.code === "EAGAIN" || err.code === "EBUSY") && this.retryEAGAIN(err, this._writingBuf.length, this._len - this._writingBuf.length)) { - if (this.sync) { - try { - sleep(BUSY_WRITE_TIMEOUT); - this.release(void 0, 0); - } catch (err2) { - this.release(err2); - } - } else { - setTimeout(fsWrite, BUSY_WRITE_TIMEOUT); - } - } else { - this._writing = false; - this.emit("error", err); - } - return; - } - this.emit("write", n); - const releasedBufObj = releaseWritingBuf(this._writingBuf, this._len, n); - this._len = releasedBufObj.len; - this._writingBuf = releasedBufObj.writingBuf; - if (this._writingBuf.length) { - if (!this.sync) { - fsWrite(); - return; - } - try { - do { - const n2 = fsWriteSync(); - const releasedBufObj2 = releaseWritingBuf(this._writingBuf, this._len, n2); - this._len = releasedBufObj2.len; - this._writingBuf = releasedBufObj2.writingBuf; - } while (this._writingBuf.length); - } catch (err2) { - this.release(err2); - return; - } - } - if (this._fsync) { - fs.fsyncSync(this.fd); - } - const len = this._len; - if (this._reopening) { - this._writing = false; - this._reopening = false; - this.reopen(); - } else if (len > this.minLength) { - this._actualWrite(); - } else if (this._ending) { - if (len > 0) { - this._actualWrite(); - } else { - this._writing = false; - actualClose(this); - } - } else { - this._writing = false; - if (this.sync) { - if (!this._asyncDrainScheduled) { - this._asyncDrainScheduled = true; - process.nextTick(emitDrain, this); - } - } else { - this.emit("drain"); - } - } - }; - this.on("newListener", function(name) { - if (name === "drain") { - this._asyncDrainScheduled = false; - } - }); - } - function releaseWritingBuf(writingBuf, len, n) { - if (typeof writingBuf === "string" && Buffer.byteLength(writingBuf) !== n) { - n = Buffer.from(writingBuf).subarray(0, n).toString().length; - } - len = Math.max(len - n, 0); - writingBuf = writingBuf.slice(n); - return { writingBuf, len }; - } - function emitDrain(sonic) { - const hasListeners = sonic.listenerCount("drain") > 0; - if (!hasListeners) return; - sonic._asyncDrainScheduled = false; - sonic.emit("drain"); - } - inherits(SonicBoom, EventEmitter); - function mergeBuf(bufs, len) { - if (bufs.length === 0) { - return kEmptyBuffer; - } - if (bufs.length === 1) { - return bufs[0]; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.parseFilterArgument = exports2.parseLatestArgument = void 0; + var helpers_1 = require_helpers2(); + function parseLatestArgument(parser3, latest) { + if (latest) { + parser3.push("LATEST"); } - return Buffer.concat(bufs, len); } - function write(data) { - if (this.destroyed) { - throw new Error("SonicBoom destroyed"); - } - const len = this._len + data.length; - const bufs = this._bufs; - if (this.maxLength && len > this.maxLength) { - this.emit("drop", data); - return this._len < this._hwm; - } - if (bufs.length === 0 || bufs[bufs.length - 1].length + data.length > this.maxWrite) { - bufs.push("" + data); - } else { - bufs[bufs.length - 1] += data; - } - this._len = len; - if (!this._writing && this._len >= this.minLength) { - this._actualWrite(); - } - return this._len < this._hwm; + exports2.parseLatestArgument = parseLatestArgument; + function parseFilterArgument(parser3, filter) { + parser3.push("FILTER"); + parser3.pushVariadic(filter); } - function writeBuffer(data) { - if (this.destroyed) { - throw new Error("SonicBoom destroyed"); - } - const len = this._len + data.length; - const bufs = this._bufs; - const lens = this._lens; - if (this.maxLength && len > this.maxLength) { - this.emit("drop", data); - return this._len < this._hwm; - } - if (bufs.length === 0 || lens[lens.length - 1] + data.length > this.maxWrite) { - bufs.push([data]); - lens.push(data.length); - } else { - bufs[bufs.length - 1].push(data); - lens[lens.length - 1] += data.length; - } - this._len = len; - if (!this._writing && this._len >= this.minLength) { - this._actualWrite(); + exports2.parseFilterArgument = parseFilterArgument; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Gets the last samples matching a specific filter from multiple time series + * @param parser - The command parser + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand(parser3, filter, options2) { + parser3.push("TS.MGET"); + parseLatestArgument(parser3, options2?.LATEST); + parseFilterArgument(parser3, filter); + }, + transformReply: { + 2(reply, _, typeMapping) { + return (0, helpers_1.resp2MapToValue)(reply, ([, , sample]) => { + return { + sample: helpers_1.transformSampleReply[2](sample) + }; + }, typeMapping); + }, + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([, sample]) => { + return { + sample: helpers_1.transformSampleReply[3](sample) + }; + }); + } } - return this._len < this._hwm; - } - function callFlushCallbackOnDrain(cb) { - this._flushPending = true; - const onDrain = () => { - if (!this._fsync) { - fs.fsync(this.fd, (err) => { - this._flushPending = false; - cb(err); + }; + } +}); +var require_MGET_WITHLABELS = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MGET_WITHLABELS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createTransformMGetLabelsReply = void 0; + var MGET_1 = require_MGET3(); + var helpers_1 = require_helpers2(); + function createTransformMGetLabelsReply() { + return { + 2(reply, _, typeMapping) { + return (0, helpers_1.resp2MapToValue)(reply, ([, labels, sample]) => { + return { + labels: (0, helpers_1.transformRESP2Labels)(labels), + sample: helpers_1.transformSampleReply[2](sample) + }; + }, typeMapping); + }, + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([labels, sample]) => { + return { + labels, + sample: helpers_1.transformSampleReply[3](sample) + }; }); - } else { - this._flushPending = false; - cb(); } - this.off("error", onError); - }; - const onError = (err) => { - this._flushPending = false; - cb(err); - this.off("drain", onDrain); }; - this.once("drain", onDrain); - this.once("error", onError); } - function flush(cb) { - if (cb != null && typeof cb !== "function") { - throw new Error("flush cb must be a function"); + exports2.createTransformMGetLabelsReply = createTransformMGetLabelsReply; + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets the last samples matching a specific filter with labels + * @param parser - The command parser + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand(parser3, filter, options2) { + parser3.push("TS.MGET"); + (0, MGET_1.parseLatestArgument)(parser3, options2?.LATEST); + parser3.push("WITHLABELS"); + (0, MGET_1.parseFilterArgument)(parser3, filter); + }, + transformReply: createTransformMGetLabelsReply() + }; + } +}); +var require_MGET_SELECTED_LABELS = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MGET_SELECTED_LABELS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + var MGET_1 = require_MGET3(); + var helpers_1 = require_helpers2(); + var MGET_WITHLABELS_1 = require_MGET_WITHLABELS(); + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets the last samples matching a specific filter with selected labels + * @param parser - The command parser + * @param filter - Filter to match time series keys + * @param selectedLabels - Labels to include in the output + * @param options - Optional parameters for the command + */ + parseCommand(parser3, filter, selectedLabels, options2) { + parser3.push("TS.MGET"); + (0, MGET_1.parseLatestArgument)(parser3, options2?.LATEST); + (0, helpers_1.parseSelectedLabelsArguments)(parser3, selectedLabels); + (0, MGET_1.parseFilterArgument)(parser3, filter); + }, + transformReply: (0, MGET_WITHLABELS_1.createTransformMGetLabelsReply)() + }; + } +}); +var require_RANGE = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/RANGE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.transformRangeArguments = exports2.parseRangeArguments = exports2.TIME_SERIES_BUCKET_TIMESTAMP = void 0; + var helpers_1 = require_helpers2(); + exports2.TIME_SERIES_BUCKET_TIMESTAMP = { + LOW: "-", + MIDDLE: "~", + END: "+" + }; + function parseRangeArguments(parser3, fromTimestamp, toTimestamp, options2) { + parser3.push((0, helpers_1.transformTimestampArgument)(fromTimestamp), (0, helpers_1.transformTimestampArgument)(toTimestamp)); + if (options2?.LATEST) { + parser3.push("LATEST"); } - if (this.destroyed) { - const error2 = new Error("SonicBoom destroyed"); - if (cb) { - cb(error2); - return; + if (options2?.FILTER_BY_TS) { + parser3.push("FILTER_BY_TS"); + for (const timestamp of options2.FILTER_BY_TS) { + parser3.push((0, helpers_1.transformTimestampArgument)(timestamp)); } - throw error2; - } - if (this.minLength <= 0) { - cb?.(); - return; } - if (cb) { - callFlushCallbackOnDrain.call(this, cb); + if (options2?.FILTER_BY_VALUE) { + parser3.push("FILTER_BY_VALUE", options2.FILTER_BY_VALUE.min.toString(), options2.FILTER_BY_VALUE.max.toString()); } - if (this._writing) { - return; + if (options2?.COUNT !== void 0) { + parser3.push("COUNT", options2.COUNT.toString()); } - if (this._bufs.length === 0) { - this._bufs.push(""); + if (options2?.AGGREGATION) { + if (options2?.ALIGN !== void 0) { + parser3.push("ALIGN", (0, helpers_1.transformTimestampArgument)(options2.ALIGN)); + } + parser3.push("AGGREGATION", options2.AGGREGATION.type, (0, helpers_1.transformTimestampArgument)(options2.AGGREGATION.timeBucket)); + if (options2.AGGREGATION.BUCKETTIMESTAMP) { + parser3.push("BUCKETTIMESTAMP", options2.AGGREGATION.BUCKETTIMESTAMP); + } + if (options2.AGGREGATION.EMPTY) { + parser3.push("EMPTY"); + } } - this._actualWrite(); } - function flushBuffer(cb) { - if (cb != null && typeof cb !== "function") { - throw new Error("flush cb must be a function"); - } - if (this.destroyed) { - const error2 = new Error("SonicBoom destroyed"); - if (cb) { - cb(error2); - return; + exports2.parseRangeArguments = parseRangeArguments; + function transformRangeArguments(parser3, key, fromTimestamp, toTimestamp, options2) { + parser3.pushKey(key); + parseRangeArguments(parser3, fromTimestamp, toTimestamp, options2); + } + exports2.transformRangeArguments = transformRangeArguments; + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets samples from a time series within a time range + * @param args - Arguments passed to the {@link transformRangeArguments} function + */ + parseCommand(...args) { + const parser3 = args[0]; + parser3.push("TS.RANGE"); + transformRangeArguments(...args); + }, + transformReply: { + 2(reply) { + return helpers_1.transformSamplesReply[2](reply); + }, + 3(reply) { + return helpers_1.transformSamplesReply[3](reply); } - throw error2; - } - if (this.minLength <= 0) { - cb?.(); - return; - } - if (cb) { - callFlushCallbackOnDrain.call(this, cb); - } - if (this._writing) { - return; - } - if (this._bufs.length === 0) { - this._bufs.push([]); - this._lens.push(0); } - this._actualWrite(); + }; + } +}); +var require_MRANGE_GROUPBY = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_GROUPBY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.extractResp3MRangeSources = exports2.createTransformMRangeGroupByArguments = exports2.parseGroupByArguments = exports2.TIME_SERIES_REDUCERS = void 0; + var helpers_1 = require_helpers2(); + var RANGE_1 = require_RANGE(); + var MGET_1 = require_MGET3(); + exports2.TIME_SERIES_REDUCERS = { + AVG: "AVG", + SUM: "SUM", + MIN: "MIN", + MAX: "MAX", + RANGE: "RANGE", + COUNT: "COUNT", + STD_P: "STD.P", + STD_S: "STD.S", + VAR_P: "VAR.P", + VAR_S: "VAR.S" + }; + function parseGroupByArguments(parser3, groupBy) { + parser3.push("GROUPBY", groupBy.label, "REDUCE", groupBy.REDUCE); } - SonicBoom.prototype.reopen = function(file) { - if (this.destroyed) { - throw new Error("SonicBoom destroyed"); - } - if (this._opening) { - this.once("ready", () => { - this.reopen(file); - }); - return; - } - if (this._ending) { - return; - } - if (!this.file) { - throw new Error("Unable to reopen a file descriptor, you must pass a file to SonicBoom"); - } - if (file) { - this.file = file; - } - this._reopening = true; - if (this._writing) { - return; + exports2.parseGroupByArguments = parseGroupByArguments; + function createTransformMRangeGroupByArguments(command2) { + return (parser3, fromTimestamp, toTimestamp, filter, groupBy, options2) => { + parser3.push(command2); + (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); + (0, MGET_1.parseFilterArgument)(parser3, filter); + parseGroupByArguments(parser3, groupBy); + }; + } + exports2.createTransformMRangeGroupByArguments = createTransformMRangeGroupByArguments; + function extractResp3MRangeSources(raw2) { + const unwrappedMetadata2 = raw2; + if (unwrappedMetadata2 instanceof Map) { + return unwrappedMetadata2.get("sources"); + } else if (unwrappedMetadata2 instanceof Array) { + return unwrappedMetadata2[1]; + } else { + return unwrappedMetadata2.sources; } - const fd = this.fd; - this.once("ready", () => { - if (fd !== this.fd) { - fs.close(fd, (err) => { - if (err) { - return this.emit("error", err); - } + } + exports2.extractResp3MRangeSources = extractResp3MRangeSources; + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets samples for time series matching a filter within a time range with grouping + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param groupBy - Group by parameters + * @param options - Optional parameters for the command + */ + parseCommand: createTransformMRangeGroupByArguments("TS.MRANGE"), + transformReply: { + 2(reply, _, typeMapping) { + return (0, helpers_1.resp2MapToValue)(reply, ([_key, _labels, samples]) => { + return { + samples: helpers_1.transformSamplesReply[2](samples) + }; + }, typeMapping); + }, + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([_labels, _metadata1, metadata2, samples]) => { + return { + sources: extractResp3MRangeSources(metadata2), + samples: helpers_1.transformSamplesReply[3](samples) + }; }); } - }); - openFile(this.file, this); - }; - SonicBoom.prototype.end = function() { - if (this.destroyed) { - throw new Error("SonicBoom destroyed"); - } - if (this._opening) { - this.once("ready", () => { - this.end(); - }); - return; - } - if (this._ending) { - return; - } - this._ending = true; - if (this._writing) { - return; - } - if (this._len > 0 && this.fd >= 0) { - this._actualWrite(); - } else { - actualClose(this); } }; - function flushSync() { - if (this.destroyed) { - throw new Error("SonicBoom destroyed"); - } - if (this.fd < 0) { - throw new Error("sonic boom is not ready yet"); - } - if (!this._writing && this._writingBuf.length > 0) { - this._bufs.unshift(this._writingBuf); - this._writingBuf = ""; - } - let buf2 = ""; - while (this._bufs.length || buf2) { - if (buf2.length <= 0) { - buf2 = this._bufs[0]; - } - try { - const n = fs.writeSync(this.fd, buf2, "utf8"); - const releasedBufObj = releaseWritingBuf(buf2, this._len, n); - buf2 = releasedBufObj.writingBuf; - this._len = releasedBufObj.len; - if (buf2.length <= 0) { - this._bufs.shift(); - } - } catch (err) { - const shouldRetry = err.code === "EAGAIN" || err.code === "EBUSY"; - if (shouldRetry && !this.retryEAGAIN(err, buf2.length, this._len - buf2.length)) { - throw err; - } - sleep(BUSY_WRITE_TIMEOUT); - } - } - try { - fs.fsyncSync(this.fd); - } catch { - } + } +}); +var require_MRANGE_SELECTED_LABELS = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_SELECTED_LABELS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createTransformMRangeSelectedLabelsArguments = void 0; + var helpers_1 = require_helpers2(); + var RANGE_1 = require_RANGE(); + var MGET_1 = require_MGET3(); + function createTransformMRangeSelectedLabelsArguments(command2) { + return (parser3, fromTimestamp, toTimestamp, selectedLabels, filter, options2) => { + parser3.push(command2); + (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); + (0, helpers_1.parseSelectedLabelsArguments)(parser3, selectedLabels); + (0, MGET_1.parseFilterArgument)(parser3, filter); + }; } - function flushBufferSync() { - if (this.destroyed) { - throw new Error("SonicBoom destroyed"); - } - if (this.fd < 0) { - throw new Error("sonic boom is not ready yet"); - } - if (!this._writing && this._writingBuf.length > 0) { - this._bufs.unshift([this._writingBuf]); - this._writingBuf = kEmptyBuffer; - } - let buf2 = kEmptyBuffer; - while (this._bufs.length || buf2.length) { - if (buf2.length <= 0) { - buf2 = mergeBuf(this._bufs[0], this._lens[0]); - } - try { - const n = fs.writeSync(this.fd, buf2); - buf2 = buf2.subarray(n); - this._len = Math.max(this._len - n, 0); - if (buf2.length <= 0) { - this._bufs.shift(); - this._lens.shift(); - } - } catch (err) { - const shouldRetry = err.code === "EAGAIN" || err.code === "EBUSY"; - if (shouldRetry && !this.retryEAGAIN(err, buf2.length, this._len - buf2.length)) { - throw err; - } - sleep(BUSY_WRITE_TIMEOUT); + exports2.createTransformMRangeSelectedLabelsArguments = createTransformMRangeSelectedLabelsArguments; + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets samples for time series matching a filter with selected labels + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param selectedLabels - Labels to include in the output + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand: createTransformMRangeSelectedLabelsArguments("TS.MRANGE"), + transformReply: { + 2(reply, _, typeMapping) { + return (0, helpers_1.resp2MapToValue)(reply, ([_key, labels, samples]) => { + return { + labels: (0, helpers_1.transformRESP2Labels)(labels, typeMapping), + samples: helpers_1.transformSamplesReply[2](samples) + }; + }, typeMapping); + }, + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([_key, labels, samples]) => { + return { + labels, + samples: helpers_1.transformSamplesReply[3](samples) + }; + }); } } - } - SonicBoom.prototype.destroy = function() { - if (this.destroyed) { - return; - } - actualClose(this); }; - function actualWrite() { - const release = this.release; - this._writing = true; - this._writingBuf = this._writingBuf || this._bufs.shift() || ""; - if (this.sync) { - try { - const written = fs.writeSync(this.fd, this._writingBuf, "utf8"); - release(null, written); - } catch (err) { - release(err); + } +}); +var require_MRANGE_SELECTED_LABELS_GROUPBY = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_SELECTED_LABELS_GROUPBY.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createMRangeSelectedLabelsGroupByTransformArguments = void 0; + var helpers_1 = require_helpers2(); + var RANGE_1 = require_RANGE(); + var MRANGE_GROUPBY_1 = require_MRANGE_GROUPBY(); + var MGET_1 = require_MGET3(); + var MRANGE_SELECTED_LABELS_1 = __importDefault(require_MRANGE_SELECTED_LABELS()); + function createMRangeSelectedLabelsGroupByTransformArguments(command2) { + return (parser3, fromTimestamp, toTimestamp, selectedLabels, filter, groupBy, options2) => { + parser3.push(command2); + (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); + (0, helpers_1.parseSelectedLabelsArguments)(parser3, selectedLabels); + (0, MGET_1.parseFilterArgument)(parser3, filter); + (0, MRANGE_GROUPBY_1.parseGroupByArguments)(parser3, groupBy); + }; + } + exports2.createMRangeSelectedLabelsGroupByTransformArguments = createMRangeSelectedLabelsGroupByTransformArguments; + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets samples for time series matching a filter with selected labels and grouping + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param selectedLabels - Labels to include in the output + * @param filter - Filter to match time series keys + * @param groupBy - Group by parameters + * @param options - Optional parameters for the command + */ + parseCommand: createMRangeSelectedLabelsGroupByTransformArguments("TS.MRANGE"), + transformReply: { + 2: MRANGE_SELECTED_LABELS_1.default.transformReply[2], + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([labels, _metadata, metadata2, samples]) => { + return { + labels, + sources: (0, MRANGE_GROUPBY_1.extractResp3MRangeSources)(metadata2), + samples: helpers_1.transformSamplesReply[3](samples) + }; + }); } - } else { - fs.write(this.fd, this._writingBuf, "utf8", release); } + }; + } +}); +var require_MRANGE_WITHLABELS_GROUPBY = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_WITHLABELS_GROUPBY.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createMRangeWithLabelsGroupByTransformArguments = void 0; + var helpers_1 = require_helpers2(); + var RANGE_1 = require_RANGE(); + var MRANGE_GROUPBY_1 = require_MRANGE_GROUPBY(); + var MGET_1 = require_MGET3(); + function createMRangeWithLabelsGroupByTransformArguments(command2) { + return (parser3, fromTimestamp, toTimestamp, filter, groupBy, options2) => { + parser3.push(command2); + (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); + parser3.push("WITHLABELS"); + (0, MGET_1.parseFilterArgument)(parser3, filter); + (0, MRANGE_GROUPBY_1.parseGroupByArguments)(parser3, groupBy); + }; } - function actualWriteBuffer() { - const release = this.release; - this._writing = true; - this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift()); - if (this.sync) { - try { - const written = fs.writeSync(this.fd, this._writingBuf); - release(null, written); - } catch (err) { - release(err); + exports2.createMRangeWithLabelsGroupByTransformArguments = createMRangeWithLabelsGroupByTransformArguments; + exports2.default = { + IS_READ_ONLY: true, + /** + * Gets samples for time series matching a filter with labels and grouping + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param groupBy - Group by parameters + * @param options - Optional parameters for the command + */ + parseCommand: createMRangeWithLabelsGroupByTransformArguments("TS.MRANGE"), + transformReply: { + 2(reply, _, typeMapping) { + return (0, helpers_1.resp2MapToValue)(reply, ([_key, labels, samples]) => { + const transformed = (0, helpers_1.transformRESP2LabelsWithSources)(labels); + return { + labels: transformed.labels, + sources: transformed.sources, + samples: helpers_1.transformSamplesReply[2](samples) + }; + }, typeMapping); + }, + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([labels, _metadata, metadata2, samples]) => { + return { + labels, + sources: (0, MRANGE_GROUPBY_1.extractResp3MRangeSources)(metadata2), + samples: helpers_1.transformSamplesReply[3](samples) + }; + }); } - } else { - fs.write(this.fd, this._writingBuf, release); } + }; + } +}); +var require_MRANGE_WITHLABELS = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE_WITHLABELS.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createTransformMRangeWithLabelsArguments = void 0; + var helpers_1 = require_helpers2(); + var RANGE_1 = require_RANGE(); + var MGET_1 = require_MGET3(); + function createTransformMRangeWithLabelsArguments(command2) { + return (parser3, fromTimestamp, toTimestamp, filter, options2) => { + parser3.push(command2); + (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); + parser3.push("WITHLABELS"); + (0, MGET_1.parseFilterArgument)(parser3, filter); + }; } - function actualClose(sonic) { - if (sonic.fd === -1) { - sonic.once("ready", actualClose.bind(null, sonic)); - return; - } - sonic.destroyed = true; - sonic._bufs = []; - sonic._lens = []; - fs.fsync(sonic.fd, closeWrapped); - function closeWrapped() { - if (sonic.fd !== 1 && sonic.fd !== 2) { - fs.close(sonic.fd, done); - } else { - done(); + exports2.createTransformMRangeWithLabelsArguments = createTransformMRangeWithLabelsArguments; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Gets samples for time series matching a filter with labels + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand: createTransformMRangeWithLabelsArguments("TS.MRANGE"), + transformReply: { + 2(reply, _, typeMapping) { + return (0, helpers_1.resp2MapToValue)(reply, ([_key, labels, samples]) => { + const unwrappedLabels = labels; + const labelsObject = /* @__PURE__ */ Object.create(null); + for (const tuple of unwrappedLabels) { + const [key, value] = tuple; + const unwrappedKey = key; + labelsObject[unwrappedKey.toString()] = value; + } + return { + labels: labelsObject, + samples: helpers_1.transformSamplesReply[2](samples) + }; + }, typeMapping); + }, + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([labels, _metadata, samples]) => { + return { + labels, + samples: helpers_1.transformSamplesReply[3](samples) + }; + }); } } - function done(err) { - if (err) { - sonic.emit("error", err); - return; - } - if (sonic._ending && !sonic._writing) { - sonic.emit("finish"); + }; + } +}); +var require_MRANGE = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MRANGE.js"(exports2) { + "use strict"; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createTransformMRangeArguments = void 0; + var helpers_1 = require_helpers2(); + var RANGE_1 = require_RANGE(); + var MGET_1 = require_MGET3(); + function createTransformMRangeArguments(command2) { + return (parser3, fromTimestamp, toTimestamp, filter, options2) => { + parser3.push(command2); + (0, RANGE_1.parseRangeArguments)(parser3, fromTimestamp, toTimestamp, options2); + (0, MGET_1.parseFilterArgument)(parser3, filter); + }; + } + exports2.createTransformMRangeArguments = createTransformMRangeArguments; + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Gets samples for time series matching a specific filter within a time range + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand: createTransformMRangeArguments("TS.MRANGE"), + transformReply: { + 2(reply, _, typeMapping) { + return (0, helpers_1.resp2MapToValue)(reply, ([_key, _labels, samples]) => { + return helpers_1.transformSamplesReply[2](samples); + }, typeMapping); + }, + 3(reply) { + return (0, helpers_1.resp3MapToValue)(reply, ([_labels, _metadata, samples]) => { + return helpers_1.transformSamplesReply[3](samples); + }); } - sonic.emit("close"); } - } - SonicBoom.SonicBoom = SonicBoom; - SonicBoom.default = SonicBoom; - module14.exports = SonicBoom; + }; } }); -var require_on_exit_leak_free = __commonJS({ - "node_modules/.deno/on-exit-leak-free@2.1.2/node_modules/on-exit-leak-free/index.js"(exports2, module14) { +var require_MREVRANGE_GROUPBY = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_GROUPBY.js"(exports2) { "use strict"; - var refs = { - exit: [], - beforeExit: [] - }; - var functions = { - exit: onExit, - beforeExit: onBeforeExit - }; - var registry2; - function ensureRegistry() { - if (registry2 === void 0) { - registry2 = new FinalizationRegistry(clear); - } - } - function install(event) { - if (refs[event].length > 0) { - return; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - process.on(event, functions[event]); - } - function uninstall(event) { - if (refs[event].length > 0) { - return; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - process.removeListener(event, functions[event]); - if (refs.exit.length === 0 && refs.beforeExit.length === 0) { - registry2 = void 0; + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var MRANGE_GROUPBY_1 = __importStar(require_MRANGE_GROUPBY()); + exports2.default = { + IS_READ_ONLY: MRANGE_GROUPBY_1.default.IS_READ_ONLY, + /** + * Gets samples for time series matching a filter within a time range with grouping (in reverse order) + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param groupBy - Group by parameters + * @param options - Optional parameters for the command + */ + parseCommand: (0, MRANGE_GROUPBY_1.createTransformMRangeGroupByArguments)("TS.MREVRANGE"), + transformReply: MRANGE_GROUPBY_1.default.transformReply + }; + } +}); +var require_MREVRANGE_SELECTED_LABELS_GROUPBY = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_SELECTED_LABELS_GROUPBY.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - } - function onExit() { - callRefs("exit"); - } - function onBeforeExit() { - callRefs("beforeExit"); - } - function callRefs(event) { - for (const ref of refs[event]) { - const obj = ref.deref(); - const fn = ref.fn; - if (obj !== void 0) { - fn(obj, event); - } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - refs[event] = []; - } - function clear(ref) { - for (const event of ["exit", "beforeExit"]) { - const index = refs[event].indexOf(ref); - refs[event].splice(index, index + 1); - uninstall(event); + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var MRANGE_SELECTED_LABELS_GROUPBY_1 = __importStar(require_MRANGE_SELECTED_LABELS_GROUPBY()); + exports2.default = { + IS_READ_ONLY: MRANGE_SELECTED_LABELS_GROUPBY_1.default.IS_READ_ONLY, + /** + * Gets samples for time series matching a filter with selected labels and grouping (in reverse order) + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param selectedLabels - Labels to include in the output + * @param filter - Filter to match time series keys + * @param groupBy - Group by parameters + * @param options - Optional parameters for the command + */ + parseCommand: (0, MRANGE_SELECTED_LABELS_GROUPBY_1.createMRangeSelectedLabelsGroupByTransformArguments)("TS.MREVRANGE"), + transformReply: MRANGE_SELECTED_LABELS_GROUPBY_1.default.transformReply + }; + } +}); +var require_MREVRANGE_SELECTED_LABELS = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_SELECTED_LABELS.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - } - function _register(event, obj, fn) { - if (obj === void 0) { - throw new Error("the object can't be undefined"); + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - install(event); - const ref = new WeakRef(obj); - ref.fn = fn; - ensureRegistry(); - registry2.register(obj, ref); - refs[event].push(ref); - } - function register2(obj, fn) { - _register("exit", obj, fn); - } - function registerBeforeExit(obj, fn) { - _register("beforeExit", obj, fn); - } - function unregister(obj) { - if (registry2 === void 0) { - return; + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var MRANGE_SELECTED_LABELS_1 = __importStar(require_MRANGE_SELECTED_LABELS()); + exports2.default = { + IS_READ_ONLY: MRANGE_SELECTED_LABELS_1.default.IS_READ_ONLY, + /** + * Gets samples for time series matching a filter with selected labels (in reverse order) + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param selectedLabels - Labels to include in the output + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand: (0, MRANGE_SELECTED_LABELS_1.createTransformMRangeSelectedLabelsArguments)("TS.MREVRANGE"), + transformReply: MRANGE_SELECTED_LABELS_1.default.transformReply + }; + } +}); +var require_MREVRANGE_WITHLABELS_GROUPBY = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_WITHLABELS_GROUPBY.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - registry2.unregister(obj); - for (const event of ["exit", "beforeExit"]) { - refs[event] = refs[event].filter((ref) => { - const _obj = ref.deref(); - return _obj && _obj !== obj; - }); - uninstall(event); + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - } - module14.exports = { - register: register2, - registerBeforeExit, - unregister + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var MRANGE_WITHLABELS_GROUPBY_1 = __importStar(require_MRANGE_WITHLABELS_GROUPBY()); + exports2.default = { + IS_READ_ONLY: MRANGE_WITHLABELS_GROUPBY_1.default.IS_READ_ONLY, + /** + * Gets samples for time series matching a filter with labels and grouping (in reverse order) + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param groupBy - Group by parameters + * @param options - Optional parameters for the command + */ + parseCommand: (0, MRANGE_WITHLABELS_GROUPBY_1.createMRangeWithLabelsGroupByTransformArguments)("TS.MREVRANGE"), + transformReply: MRANGE_WITHLABELS_GROUPBY_1.default.transformReply }; } }); -var require_package6 = __commonJS({ - "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/package.json"(exports2, module14) { - module14.exports = { - name: "thread-stream", - version: "2.7.0", - description: "A streaming way to send data to a Node.js Worker Thread", - main: "index.js", - types: "index.d.ts", - dependencies: { - "real-require": "^0.2.0" - }, - devDependencies: { - "@types/node": "^20.1.0", - "@types/tap": "^15.0.0", - "@yao-pkg/pkg": "^5.11.5", - desm: "^1.3.0", - fastbench: "^1.0.1", - husky: "^9.0.6", - "pino-elasticsearch": "^8.0.0", - "sonic-boom": "^3.0.0", - standard: "^17.0.0", - tap: "^16.2.0", - "ts-node": "^10.8.0", - typescript: "^5.3.2", - "why-is-node-running": "^2.2.2" - }, - scripts: { - test: 'standard && npm run transpile && tap "test/**/*.test.*js" && tap --ts test/*.test.*ts', - "test:ci": "standard && npm run transpile && npm run test:ci:js && npm run test:ci:ts", - "test:ci:js": 'tap --no-check-coverage --timeout=120 --coverage-report=lcovonly "test/**/*.test.*js"', - "test:ci:ts": 'tap --ts --no-check-coverage --coverage-report=lcovonly "test/**/*.test.*ts"', - "test:yarn": 'npm run transpile && tap "test/**/*.test.js" --no-check-coverage', - transpile: "sh ./test/ts/transpile.sh", - prepare: "husky install" - }, - standard: { - ignore: [ - "test/ts/**/*" - ] - }, - repository: { - type: "git", - url: "git+https://github.com/mcollina/thread-stream.git" - }, - keywords: [ - "worker", - "thread", - "threads", - "stream" - ], - author: "Matteo Collina ", - license: "MIT", - bugs: { - url: "https://github.com/mcollina/thread-stream/issues" - }, - homepage: "https://github.com/mcollina/thread-stream#readme" +var require_MREVRANGE_WITHLABELS = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE_WITHLABELS.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; + } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var MRANGE_WITHLABELS_1 = __importStar(require_MRANGE_WITHLABELS()); + exports2.default = { + NOT_KEYED_COMMAND: MRANGE_WITHLABELS_1.default.NOT_KEYED_COMMAND, + IS_READ_ONLY: MRANGE_WITHLABELS_1.default.IS_READ_ONLY, + /** + * Gets samples for time series matching a filter with labels (in reverse order) + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand: (0, MRANGE_WITHLABELS_1.createTransformMRangeWithLabelsArguments)("TS.MREVRANGE"), + transformReply: MRANGE_WITHLABELS_1.default.transformReply }; } }); -var require_wait2 = __commonJS({ - "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/lib/wait.js"(exports2, module14) { +var require_MREVRANGE = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/MREVRANGE.js"(exports2) { "use strict"; - var MAX_TIMEOUT = 1e3; - function wait(state, index, expected, timeout, done) { - const max = Date.now() + timeout; - let current = Atomics.load(state, index); - if (current === expected) { - done(null, "ok"); - return; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - let prior = current; - const check2 = (backoff) => { - if (Date.now() > max) { - done(null, "timed-out"); - } else { - setTimeout(() => { - prior = current; - current = Atomics.load(state, index); - if (current === prior) { - check2(backoff >= MAX_TIMEOUT ? MAX_TIMEOUT : backoff * 2); - } else { - if (current === expected) done(null, "ok"); - else done(null, "not-equal"); - } - }, backoff); - } - }; - check2(1); - } - function waitDiff(state, index, expected, timeout, done) { - const max = Date.now() + timeout; - let current = Atomics.load(state, index); - if (current !== expected) { - done(null, "ok"); - return; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } - const check2 = (backoff) => { - if (Date.now() > max) { - done(null, "timed-out"); - } else { - setTimeout(() => { - current = Atomics.load(state, index); - if (current !== expected) { - done(null, "ok"); - } else { - check2(backoff >= MAX_TIMEOUT ? MAX_TIMEOUT : backoff * 2); - } - }, backoff); - } - }; - check2(1); - } - module14.exports = { wait, waitDiff }; + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var MRANGE_1 = __importStar(require_MRANGE()); + exports2.default = { + NOT_KEYED_COMMAND: MRANGE_1.default.NOT_KEYED_COMMAND, + IS_READ_ONLY: MRANGE_1.default.IS_READ_ONLY, + /** + * Gets samples for time series matching a specific filter within a time range (in reverse order) + * @param parser - The command parser + * @param fromTimestamp - Start timestamp for range + * @param toTimestamp - End timestamp for range + * @param filter - Filter to match time series keys + * @param options - Optional parameters for the command + */ + parseCommand: (0, MRANGE_1.createTransformMRangeArguments)("TS.MREVRANGE"), + transformReply: MRANGE_1.default.transformReply + }; } }); -var require_indexes = __commonJS({ - "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/lib/indexes.js"(exports2, module14) { +var require_QUERYINDEX = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/QUERYINDEX.js"(exports2) { "use strict"; - var WRITE_INDEX = 4; - var READ_INDEX = 8; - module14.exports = { - WRITE_INDEX, - READ_INDEX + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.default = { + NOT_KEYED_COMMAND: true, + IS_READ_ONLY: true, + /** + * Queries the index for time series matching a specific filter + * @param parser - The command parser + * @param filter - Filter to match time series labels + */ + parseCommand(parser3, filter) { + parser3.push("TS.QUERYINDEX"); + parser3.pushVariadic(filter); + }, + transformReply: { + 2: void 0, + 3: void 0 + } }; } }); -var require_thread_stream = __commonJS({ - "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/index.js"(exports2, module14) { +var require_REVRANGE = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/REVRANGE.js"(exports2) { "use strict"; - var { version: version3 } = require_package6(); - var { EventEmitter } = __require2("events"); - var { Worker: Worker2 } = __require2("worker_threads"); - var { join: join92 } = __require2("path"); - var { pathToFileURL: pathToFileURL2 } = __require2("url"); - var { wait } = require_wait2(); - var { - WRITE_INDEX, - READ_INDEX - } = require_indexes(); - var buffer = __require2("buffer"); - var assert2 = __require2("assert"); - var kImpl = Symbol("kImpl"); - var MAX_STRING = buffer.constants.MAX_STRING_LENGTH; - var FakeWeakRef = class { - constructor(value) { - this._value = value; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - deref() { - return this._value; + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o2, v2) { + Object.defineProperty(o2, "default", { enumerable: true, value: v2 }); + } : function(o2, v2) { + o2["default"] = v2; + }); + var __importStar = exports2 && exports2.__importStar || function(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) { + for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); } + __setModuleDefault(result, mod); + return result; }; - var FakeFinalizationRegistry = class { - register() { - } - unregister() { - } + Object.defineProperty(exports2, "__esModule", { value: true }); + var RANGE_1 = __importStar(require_RANGE()); + exports2.default = { + IS_READ_ONLY: RANGE_1.default.IS_READ_ONLY, + /** + * Gets samples from a time series within a time range (in reverse order) + * @param args - Arguments passed to the {@link transformRangeArguments} function + */ + parseCommand(...args) { + const parser3 = args[0]; + parser3.push("TS.REVRANGE"); + (0, RANGE_1.transformRangeArguments)(...args); + }, + transformReply: RANGE_1.default.transformReply }; - var FinalizationRegistry2 = process.env.NODE_V8_COVERAGE ? FakeFinalizationRegistry : global.FinalizationRegistry || FakeFinalizationRegistry; - var WeakRef2 = process.env.NODE_V8_COVERAGE ? FakeWeakRef : global.WeakRef || FakeWeakRef; - var registry2 = new FinalizationRegistry2((worker) => { - if (worker.exited) { - return; + } +}); +var require_commands6 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/commands/index.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } - worker.terminate(); + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; }); - function createWorker2(stream, opts) { - const { filename, workerData } = opts; - const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {}; - const toExecute = bundlerOverrides["thread-stream-worker"] || join92(__dirname, "lib", "worker.js"); - const worker = new Worker2(toExecute, { - ...opts.workerOpts, - trackUnmanagedFds: false, - workerData: { - filename: filename.indexOf("file://") === 0 ? filename : pathToFileURL2(filename).href, - dataBuf: stream[kImpl].dataBuf, - stateBuf: stream[kImpl].stateBuf, - workerData: { - $context: { - threadStreamVersion: version3 - }, - ...workerData - } - } - }); - worker.stream = new FakeWeakRef(stream); - worker.on("message", onWorkerMessage); - worker.on("exit", onWorkerExit); - registry2.register(stream, worker); - return worker; - } - function drain(stream) { - assert2(!stream[kImpl].sync); - if (stream[kImpl].needDrain) { - stream[kImpl].needDrain = false; - stream.emit("drain"); - } - } - function nextFlush(stream) { - const writeIndex = Atomics.load(stream[kImpl].state, WRITE_INDEX); - let leftover = stream[kImpl].data.length - writeIndex; - if (leftover > 0) { - if (stream[kImpl].buf.length === 0) { - stream[kImpl].flushing = false; - if (stream[kImpl].ending) { - end(stream); - } else if (stream[kImpl].needDrain) { - process.nextTick(drain, stream); - } - return; - } - let toWrite = stream[kImpl].buf.slice(0, leftover); - let toWriteBytes = Buffer.byteLength(toWrite); - if (toWriteBytes <= leftover) { - stream[kImpl].buf = stream[kImpl].buf.slice(leftover); - write(stream, toWrite, nextFlush.bind(null, stream)); - } else { - stream.flush(() => { - if (stream.destroyed) { - return; - } - Atomics.store(stream[kImpl].state, READ_INDEX, 0); - Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); - while (toWriteBytes > stream[kImpl].data.length) { - leftover = leftover / 2; - toWrite = stream[kImpl].buf.slice(0, leftover); - toWriteBytes = Buffer.byteLength(toWrite); - } - stream[kImpl].buf = stream[kImpl].buf.slice(leftover); - write(stream, toWrite, nextFlush.bind(null, stream)); - }); - } - } else if (leftover === 0) { - if (writeIndex === 0 && stream[kImpl].buf.length === 0) { - return; - } - stream.flush(() => { - Atomics.store(stream[kImpl].state, READ_INDEX, 0); - Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); - nextFlush(stream); - }); - } else { - destroy(stream, new Error("overwritten")); - } - } - function onWorkerMessage(msg) { - const stream = this.stream.deref(); - if (stream === void 0) { - this.exited = true; - this.terminate(); - return; - } - switch (msg.code) { - case "READY": - this.stream = new WeakRef2(stream); - stream.flush(() => { - stream[kImpl].ready = true; - stream.emit("ready"); - }); - break; - case "ERROR": - destroy(stream, msg.err); - break; - case "EVENT": - if (Array.isArray(msg.args)) { - stream.emit(msg.name, ...msg.args); - } else { - stream.emit(msg.name, msg.args); - } - break; - case "WARNING": - process.emitWarning(msg.err); - break; - default: - destroy(stream, new Error("this should not happen: " + msg.code)); - } - } - function onWorkerExit(code2) { - const stream = this.stream.deref(); - if (stream === void 0) { - return; - } - registry2.unregister(stream); - stream.worker.exited = true; - stream.worker.off("exit", onWorkerExit); - destroy(stream, code2 !== 0 ? new Error("the worker thread exited") : null); - } - var ThreadStream = class extends EventEmitter { - constructor(opts = {}) { - super(); - if (opts.bufferSize < 4) { - throw new Error("bufferSize must at least fit a 4-byte utf-8 char"); - } - this[kImpl] = {}; - this[kImpl].stateBuf = new SharedArrayBuffer(128); - this[kImpl].state = new Int32Array(this[kImpl].stateBuf); - this[kImpl].dataBuf = new SharedArrayBuffer(opts.bufferSize || 4 * 1024 * 1024); - this[kImpl].data = Buffer.from(this[kImpl].dataBuf); - this[kImpl].sync = opts.sync || false; - this[kImpl].ending = false; - this[kImpl].ended = false; - this[kImpl].needDrain = false; - this[kImpl].destroyed = false; - this[kImpl].flushing = false; - this[kImpl].ready = false; - this[kImpl].finished = false; - this[kImpl].errored = null; - this[kImpl].closed = false; - this[kImpl].buf = ""; - this.worker = createWorker2(this, opts); - this.on("message", (message, transferList) => { - this.worker.postMessage(message, transferList); - }); - } - write(data) { - if (this[kImpl].destroyed) { - error2(this, new Error("the worker has exited")); - return false; - } - if (this[kImpl].ending) { - error2(this, new Error("the worker is ending")); - return false; - } - if (this[kImpl].flushing && this[kImpl].buf.length + data.length >= MAX_STRING) { - try { - writeSync(this); - this[kImpl].flushing = true; - } catch (err) { - destroy(this, err); - return false; - } - } - this[kImpl].buf += data; - if (this[kImpl].sync) { - try { - writeSync(this); - return true; - } catch (err) { - destroy(this, err); - return false; - } - } - if (!this[kImpl].flushing) { - this[kImpl].flushing = true; - setImmediate(nextFlush, this); - } - this[kImpl].needDrain = this[kImpl].data.length - this[kImpl].buf.length - Atomics.load(this[kImpl].state, WRITE_INDEX) <= 0; - return !this[kImpl].needDrain; - } - end() { - if (this[kImpl].destroyed) { - return; - } - this[kImpl].ending = true; - end(this); - } - flush(cb) { - if (this[kImpl].destroyed) { - if (typeof cb === "function") { - process.nextTick(cb, new Error("the worker has exited")); - } - return; - } - const writeIndex = Atomics.load(this[kImpl].state, WRITE_INDEX); - wait(this[kImpl].state, READ_INDEX, writeIndex, Infinity, (err, res) => { - if (err) { - destroy(this, err); - process.nextTick(cb, err); - return; - } - if (res === "not-equal") { - this.flush(cb); - return; - } - process.nextTick(cb); - }); - } - flushSync() { - if (this[kImpl].destroyed) { - return; - } - writeSync(this); - flushSync(this); - } - unref() { - this.worker.unref(); - } - ref() { - this.worker.ref(); - } - get ready() { - return this[kImpl].ready; - } - get destroyed() { - return this[kImpl].destroyed; - } - get closed() { - return this[kImpl].closed; - } - get writable() { - return !this[kImpl].destroyed && !this[kImpl].ending; - } - get writableEnded() { - return this[kImpl].ending; - } - get writableFinished() { - return this[kImpl].finished; - } - get writableNeedDrain() { - return this[kImpl].needDrain; - } - get writableObjectMode() { - return false; - } - get writableErrored() { - return this[kImpl].errored; + var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { + for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); + }; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + var ADD_1 = __importDefault(require_ADD5()); + var ALTER_1 = __importDefault(require_ALTER2()); + var CREATE_1 = __importDefault(require_CREATE3()); + var CREATERULE_1 = __importDefault(require_CREATERULE()); + var DECRBY_1 = __importDefault(require_DECRBY2()); + var DEL_1 = __importDefault(require_DEL4()); + var DELETERULE_1 = __importDefault(require_DELETERULE()); + var GET_1 = __importDefault(require_GET3()); + var INCRBY_1 = __importDefault(require_INCRBY4()); + var INFO_DEBUG_1 = __importDefault(require_INFO_DEBUG()); + var INFO_1 = __importDefault(require_INFO8()); + var MADD_1 = __importDefault(require_MADD2()); + var MGET_SELECTED_LABELS_1 = __importDefault(require_MGET_SELECTED_LABELS()); + var MGET_WITHLABELS_1 = __importDefault(require_MGET_WITHLABELS()); + var MGET_1 = __importDefault(require_MGET3()); + var MRANGE_GROUPBY_1 = __importDefault(require_MRANGE_GROUPBY()); + var MRANGE_SELECTED_LABELS_GROUPBY_1 = __importDefault(require_MRANGE_SELECTED_LABELS_GROUPBY()); + var MRANGE_SELECTED_LABELS_1 = __importDefault(require_MRANGE_SELECTED_LABELS()); + var MRANGE_WITHLABELS_GROUPBY_1 = __importDefault(require_MRANGE_WITHLABELS_GROUPBY()); + var MRANGE_WITHLABELS_1 = __importDefault(require_MRANGE_WITHLABELS()); + var MRANGE_1 = __importDefault(require_MRANGE()); + var MREVRANGE_GROUPBY_1 = __importDefault(require_MREVRANGE_GROUPBY()); + var MREVRANGE_SELECTED_LABELS_GROUPBY_1 = __importDefault(require_MREVRANGE_SELECTED_LABELS_GROUPBY()); + var MREVRANGE_SELECTED_LABELS_1 = __importDefault(require_MREVRANGE_SELECTED_LABELS()); + var MREVRANGE_WITHLABELS_GROUPBY_1 = __importDefault(require_MREVRANGE_WITHLABELS_GROUPBY()); + var MREVRANGE_WITHLABELS_1 = __importDefault(require_MREVRANGE_WITHLABELS()); + var MREVRANGE_1 = __importDefault(require_MREVRANGE()); + var QUERYINDEX_1 = __importDefault(require_QUERYINDEX()); + var RANGE_1 = __importDefault(require_RANGE()); + var REVRANGE_1 = __importDefault(require_REVRANGE()); + __exportStar(require_helpers2(), exports2); + exports2.default = { + ADD: ADD_1.default, + add: ADD_1.default, + ALTER: ALTER_1.default, + alter: ALTER_1.default, + CREATE: CREATE_1.default, + create: CREATE_1.default, + CREATERULE: CREATERULE_1.default, + createRule: CREATERULE_1.default, + DECRBY: DECRBY_1.default, + decrBy: DECRBY_1.default, + DEL: DEL_1.default, + del: DEL_1.default, + DELETERULE: DELETERULE_1.default, + deleteRule: DELETERULE_1.default, + GET: GET_1.default, + get: GET_1.default, + INCRBY: INCRBY_1.default, + incrBy: INCRBY_1.default, + INFO_DEBUG: INFO_DEBUG_1.default, + infoDebug: INFO_DEBUG_1.default, + INFO: INFO_1.default, + info: INFO_1.default, + MADD: MADD_1.default, + mAdd: MADD_1.default, + MGET_SELECTED_LABELS: MGET_SELECTED_LABELS_1.default, + mGetSelectedLabels: MGET_SELECTED_LABELS_1.default, + MGET_WITHLABELS: MGET_WITHLABELS_1.default, + mGetWithLabels: MGET_WITHLABELS_1.default, + MGET: MGET_1.default, + mGet: MGET_1.default, + MRANGE_GROUPBY: MRANGE_GROUPBY_1.default, + mRangeGroupBy: MRANGE_GROUPBY_1.default, + MRANGE_SELECTED_LABELS_GROUPBY: MRANGE_SELECTED_LABELS_GROUPBY_1.default, + mRangeSelectedLabelsGroupBy: MRANGE_SELECTED_LABELS_GROUPBY_1.default, + MRANGE_SELECTED_LABELS: MRANGE_SELECTED_LABELS_1.default, + mRangeSelectedLabels: MRANGE_SELECTED_LABELS_1.default, + MRANGE_WITHLABELS_GROUPBY: MRANGE_WITHLABELS_GROUPBY_1.default, + mRangeWithLabelsGroupBy: MRANGE_WITHLABELS_GROUPBY_1.default, + MRANGE_WITHLABELS: MRANGE_WITHLABELS_1.default, + mRangeWithLabels: MRANGE_WITHLABELS_1.default, + MRANGE: MRANGE_1.default, + mRange: MRANGE_1.default, + MREVRANGE_GROUPBY: MREVRANGE_GROUPBY_1.default, + mRevRangeGroupBy: MREVRANGE_GROUPBY_1.default, + MREVRANGE_SELECTED_LABELS_GROUPBY: MREVRANGE_SELECTED_LABELS_GROUPBY_1.default, + mRevRangeSelectedLabelsGroupBy: MREVRANGE_SELECTED_LABELS_GROUPBY_1.default, + MREVRANGE_SELECTED_LABELS: MREVRANGE_SELECTED_LABELS_1.default, + mRevRangeSelectedLabels: MREVRANGE_SELECTED_LABELS_1.default, + MREVRANGE_WITHLABELS_GROUPBY: MREVRANGE_WITHLABELS_GROUPBY_1.default, + mRevRangeWithLabelsGroupBy: MREVRANGE_WITHLABELS_GROUPBY_1.default, + MREVRANGE_WITHLABELS: MREVRANGE_WITHLABELS_1.default, + mRevRangeWithLabels: MREVRANGE_WITHLABELS_1.default, + MREVRANGE: MREVRANGE_1.default, + mRevRange: MREVRANGE_1.default, + QUERYINDEX: QUERYINDEX_1.default, + queryIndex: QUERYINDEX_1.default, + RANGE: RANGE_1.default, + range: RANGE_1.default, + REVRANGE: REVRANGE_1.default, + revRange: REVRANGE_1.default + }; + } +}); +var require_lib5 = __commonJS({ + "node_modules/.deno/@redis+time-series@5.9.0/node_modules/@redis/time-series/dist/lib/index.js"(exports2) { + "use strict"; + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.TIME_SERIES_REDUCERS = exports2.TIME_SERIES_BUCKET_TIMESTAMP = exports2.TIME_SERIES_AGGREGATION_TYPE = exports2.TIME_SERIES_DUPLICATE_POLICIES = exports2.TIME_SERIES_ENCODING = exports2.default = void 0; + var commands_1 = require_commands6(); + Object.defineProperty(exports2, "default", { enumerable: true, get: function() { + return __importDefault(commands_1).default; + } }); + Object.defineProperty(exports2, "TIME_SERIES_ENCODING", { enumerable: true, get: function() { + return commands_1.TIME_SERIES_ENCODING; + } }); + Object.defineProperty(exports2, "TIME_SERIES_DUPLICATE_POLICIES", { enumerable: true, get: function() { + return commands_1.TIME_SERIES_DUPLICATE_POLICIES; + } }); + var CREATERULE_1 = require_CREATERULE(); + Object.defineProperty(exports2, "TIME_SERIES_AGGREGATION_TYPE", { enumerable: true, get: function() { + return CREATERULE_1.TIME_SERIES_AGGREGATION_TYPE; + } }); + var RANGE_1 = require_RANGE(); + Object.defineProperty(exports2, "TIME_SERIES_BUCKET_TIMESTAMP", { enumerable: true, get: function() { + return RANGE_1.TIME_SERIES_BUCKET_TIMESTAMP; + } }); + var MRANGE_GROUPBY_1 = require_MRANGE_GROUPBY(); + Object.defineProperty(exports2, "TIME_SERIES_REDUCERS", { enumerable: true, get: function() { + return MRANGE_GROUPBY_1.TIME_SERIES_REDUCERS; + } }); + } +}); +var require_dist2 = __commonJS({ + "node_modules/.deno/redis@5.9.0/node_modules/redis/dist/index.js"(exports2) { + "use strict"; + var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m3, k); + if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m3[k]; + } }; } + Object.defineProperty(o2, k2, desc); + } : function(o2, m3, k, k2) { + if (k2 === void 0) k2 = k; + o2[k2] = m3[k]; + }); + var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { + for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); }; - function error2(stream, err) { - setImmediate(() => { - stream.emit("error", err); + var __importDefault = exports2 && exports2.__importDefault || function(mod) { + return mod && mod.__esModule ? mod : { "default": mod }; + }; + Object.defineProperty(exports2, "__esModule", { value: true }); + exports2.createSentinel = exports2.createCluster = exports2.createClientPool = exports2.createClient = void 0; + var client_1 = require_dist(); + var bloom_1 = __importDefault(require_lib2()); + var json_1 = __importDefault(require_lib3()); + var search_1 = __importDefault(require_lib4()); + var time_series_1 = __importDefault(require_lib5()); + __exportStar(require_dist(), exports2); + __exportStar(require_lib2(), exports2); + __exportStar(require_lib3(), exports2); + __exportStar(require_lib4(), exports2); + __exportStar(require_lib5(), exports2); + var modules = { + ...bloom_1.default, + json: json_1.default, + ft: search_1.default, + ts: time_series_1.default + }; + function createClient3(options2) { + return (0, client_1.createClient)({ + ...options2, + modules: { + ...modules, + ...options2?.modules + } }); } - function destroy(stream, err) { - if (stream[kImpl].destroyed) { - return; - } - stream[kImpl].destroyed = true; - if (err) { - stream[kImpl].errored = err; - error2(stream, err); - } - if (!stream.worker.exited) { - stream.worker.terminate().catch(() => { - }).then(() => { - stream[kImpl].closed = true; - stream.emit("close"); - }); - } else { - setImmediate(() => { - stream[kImpl].closed = true; - stream.emit("close"); - }); - } - } - function write(stream, data, cb) { - const current = Atomics.load(stream[kImpl].state, WRITE_INDEX); - const length2 = Buffer.byteLength(data); - stream[kImpl].data.write(data, current); - Atomics.store(stream[kImpl].state, WRITE_INDEX, current + length2); - Atomics.notify(stream[kImpl].state, WRITE_INDEX); - cb(); - return true; - } - function end(stream) { - if (stream[kImpl].ended || !stream[kImpl].ending || stream[kImpl].flushing) { - return; - } - stream[kImpl].ended = true; - try { - stream.flushSync(); - let readIndex = Atomics.load(stream[kImpl].state, READ_INDEX); - Atomics.store(stream[kImpl].state, WRITE_INDEX, -1); - Atomics.notify(stream[kImpl].state, WRITE_INDEX); - let spins = 0; - while (readIndex !== -1) { - Atomics.wait(stream[kImpl].state, READ_INDEX, readIndex, 1e3); - readIndex = Atomics.load(stream[kImpl].state, READ_INDEX); - if (readIndex === -2) { - destroy(stream, new Error("end() failed")); - return; - } - if (++spins === 10) { - destroy(stream, new Error("end() took too long (10s)")); - return; - } + exports2.createClient = createClient3; + function createClientPool(clientOptions, options2) { + return (0, client_1.createClientPool)({ + ...clientOptions, + modules: { + ...modules, + ...clientOptions?.modules } - process.nextTick(() => { - stream[kImpl].finished = true; - stream.emit("finish"); - }); - } catch (err) { - destroy(stream, err); - } + }, options2); } - function writeSync(stream) { - const cb = () => { - if (stream[kImpl].ending) { - end(stream); - } else if (stream[kImpl].needDrain) { - process.nextTick(drain, stream); - } - }; - stream[kImpl].flushing = false; - while (stream[kImpl].buf.length !== 0) { - const writeIndex = Atomics.load(stream[kImpl].state, WRITE_INDEX); - let leftover = stream[kImpl].data.length - writeIndex; - if (leftover === 0) { - flushSync(stream); - Atomics.store(stream[kImpl].state, READ_INDEX, 0); - Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); - continue; - } else if (leftover < 0) { - throw new Error("overwritten"); - } - let toWrite = stream[kImpl].buf.slice(0, leftover); - let toWriteBytes = Buffer.byteLength(toWrite); - if (toWriteBytes <= leftover) { - stream[kImpl].buf = stream[kImpl].buf.slice(leftover); - write(stream, toWrite, cb); - } else { - flushSync(stream); - Atomics.store(stream[kImpl].state, READ_INDEX, 0); - Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); - while (toWriteBytes > stream[kImpl].buf.length) { - leftover = leftover / 2; - toWrite = stream[kImpl].buf.slice(0, leftover); - toWriteBytes = Buffer.byteLength(toWrite); - } - stream[kImpl].buf = stream[kImpl].buf.slice(leftover); - write(stream, toWrite, cb); + exports2.createClientPool = createClientPool; + function createCluster(options2) { + return (0, client_1.createCluster)({ + ...options2, + modules: { + ...modules, + ...options2?.modules } - } + }); } - function flushSync(stream) { - if (stream[kImpl].flushing) { - throw new Error("unable to flush while flushing"); - } - const writeIndex = Atomics.load(stream[kImpl].state, WRITE_INDEX); - let spins = 0; - while (true) { - const readIndex = Atomics.load(stream[kImpl].state, READ_INDEX); - if (readIndex === -2) { - throw Error("_flushSync failed"); - } - if (readIndex !== writeIndex) { - Atomics.wait(stream[kImpl].state, READ_INDEX, readIndex, 1e3); - } else { - break; - } - if (++spins === 10) { - throw new Error("_flushSync took too long (10s)"); + exports2.createCluster = createCluster; + function createSentinel(options2) { + return (0, client_1.createSentinel)({ + ...options2, + modules: { + ...modules, + ...options2?.modules } - } + }); } - module14.exports = ThreadStream; + exports2.createSentinel = createSentinel; } }); -var require_transport = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/transport.js"(exports2, module14) { +var database_redis_exports = {}; +__export(database_redis_exports, { + default: () => RedisBackend +}); +var import_npm_redis; +var ConfigSchema2; +var RedisBackend; +var init_database_redis = __esm({ + "src/serve/database-redis.ts"() { "use strict"; - var { createRequire } = __require2("module"); - var getCallers = require_caller(); - var { join: join92, isAbsolute: isAbsolute8, sep } = __require2("path"); - var sleep = require_atomic_sleep(); - var onExit = require_on_exit_leak_free(); - var ThreadStream = require_thread_stream(); - function setupOnExit(stream) { - onExit.register(stream, autoEnd); - onExit.registerBeforeExit(stream, flush); - stream.on("close", function() { - onExit.unregister(stream); - }); - } - function buildStream(filename, workerData, workerOpts) { - const stream = new ThreadStream({ - filename, - workerData, - workerOpts - }); - stream.on("ready", onReady); - stream.on("close", function() { - process.removeListener("exit", onExit2); - }); - process.on("exit", onExit2); - function onReady() { - process.removeListener("exit", onExit2); - stream.unref(); - if (workerOpts.autoEnd !== false) { - setupOnExit(stream); - } + import_npm_redis = __toESM(require_dist2()); + init_zod(); + init_DatabaseBackend(); + ConfigSchema2 = strictObject({ + url: optional(url({ protocol: /^rediss?$/ })) + }); + RedisBackend = class extends DatabaseBackend { + db = null; + url; + constructor(options2 = {}) { + super(); + ConfigSchema2.parse(options2); + this.url = options2.url; } - function onExit2() { - if (stream.closed) { - return; - } - stream.flushSync(); - sleep(100); - stream.end(); + async init() { + const db2 = (0, import_npm_redis.createClient)({ + RESP: 3, + url: this.url + }).withTypeMapping({ + [import_npm_redis.RESP_TYPES.BLOB_STRING]: Buffer10 + }); + await db2.connect(); + this.db = db2; } - return stream; - } - function autoEnd(stream) { - stream.ref(); - stream.flushSync(); - stream.end(); - stream.once("close", function() { - stream.unref(); - }); - } - function flush(stream) { - stream.flushSync(); - } - function transport(fullOptions) { - const { pipeline, targets, levels, dedupe, options: options2 = {}, worker = {}, caller = getCallers() } = fullOptions; - const callers = typeof caller === "string" ? [caller] : caller; - const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {}; - let target = fullOptions.target; - if (target && targets) { - throw new Error("only one of target or targets can be specified"); + // Useful in test hooks. + async clear() { + await this.db.flushAll(); } - if (targets) { - target = bundlerOverrides["pino-worker"] || join92(__dirname, "worker.js"); - options2.targets = targets.map((dest) => { - return { - ...dest, - target: fixTarget(dest.target) - }; - }); - } else if (pipeline) { - target = bundlerOverrides["pino-pipeline-worker"] || join92(__dirname, "worker-pipeline.js"); - options2.targets = pipeline.map((dest) => { - return { - ...dest, - target: fixTarget(dest.target) - }; - }); + async readData(key) { + return await this.db.get(key) ?? void 0; } - if (levels) { - options2.levels = levels; + async writeData(key, value) { + await this.db.set(key, value); } - if (dedupe) { - options2.dedupe = dedupe; + async deleteData(key) { + await this.db.del(key); } - return buildStream(fixTarget(target), options2, worker); - function fixTarget(origin) { - origin = bundlerOverrides[origin] || origin; - if (isAbsolute8(origin) || origin.indexOf("file://") === 0) { - return origin; - } - if (origin === "pino/file") { - return join92(__dirname, "..", "file.js"); - } - let fixTarget2; - for (const filePath of callers) { - try { - const context = filePath === "node:repl" ? process.cwd() + sep : filePath; - fixTarget2 = createRequire(context).resolve(origin); - break; - } catch (err) { - continue; - } - } - if (!fixTarget2) { - throw new Error(`unable to determine transport target for "${origin}"`); + close() { + this.db.destroy(); + } + async *iterKeys() { + const iterator = this.db.withTypeMapping({}).scanIterator({ MATCH: "*" }); + for await (const keys of iterator) { + yield* keys; } - return fixTarget2; } - } - module14.exports = transport; + keyCount() { + return this.db.dbSize(); + } + }; } }); -var require_tools = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/tools.js"(exports2, module14) { +var database_sqlite_exports = {}; +__export(database_sqlite_exports, { + default: () => SqliteBackend +}); +var ConfigSchema3; +var SqliteBackend; +var init_database_sqlite = __esm({ + "src/serve/database-sqlite.ts"() { "use strict"; - var format52 = require_quick_format_unescaped(); - var { mapHttpRequest, mapHttpResponse } = require_pino_std_serializers(); - var SonicBoom = require_sonic_boom(); - var onExit = require_on_exit_leak_free(); - var { - lsCacheSym, - chindingsSym, - writeSym, - serializersSym, - formatOptsSym, - endSym, - stringifiersSym, - stringifySym, - stringifySafeSym, - wildcardFirstSym, - nestedKeySym, - formattersSym, - messageKeySym, - errorKeySym, - nestedKeyStrSym, - msgPrefixSym - } = require_symbols2(); - var { isMainThread } = __require2("worker_threads"); - var transport = require_transport(); - function noop() { - } - function genLog(level, hook) { - if (!hook) return LOG; - return function hookWrappedLog(...args) { - hook.call(this, args, LOG, level); - }; - function LOG(o2, ...n) { - if (typeof o2 === "object") { - let msg = o2; - if (o2 !== null) { - if (o2.method && o2.headers && o2.socket) { - o2 = mapHttpRequest(o2); - } else if (typeof o2.setHeader === "function") { - o2 = mapHttpResponse(o2); - } - } - let formatParams; - if (msg === null && n.length === 0) { - formatParams = [null]; - } else { - msg = n.shift(); - formatParams = n; - } - if (typeof this[msgPrefixSym] === "string" && msg !== void 0 && msg !== null) { - msg = this[msgPrefixSym] + msg; - } - this[writeSym](o2, format52(msg, formatParams, this[formatOptsSym]), level); - } else { - let msg = o2 === void 0 ? n.shift() : o2; - if (typeof this[msgPrefixSym] === "string" && msg !== void 0 && msg !== null) { - msg = this[msgPrefixSym] + msg; - } - this[writeSym](null, format52(msg, n, this[formatOptsSym]), level); + init_zod(); + init_DatabaseBackend(); + ConfigSchema3 = strictObject({ + filepath: optional(string2()) + }); + SqliteBackend = class extends DatabaseBackend { + dataFolder = "data"; + db = null; + filename = "chelonia.db"; + readStatement = null; + writeStatement = null; + deleteStatement = null; + iterKeysStatement = null; + keyCountStatement = null; + constructor(options2 = {}) { + super(); + ConfigSchema3.parse(options2); + const { filepath } = options2; + if (!filepath) return; + const resolvedPath = resolve22(filepath); + this.dataFolder = dirname22(resolvedPath); + this.filename = basename22(resolvedPath); + } + run(sql) { + this.db.prepare(sql).run(); + } + async init() { + const { dataFolder, filename } = this; + await mkdir2(dataFolder, { mode: 488, recursive: true }); + if (this.db) { + throw new Error(`The ${filename} SQLite database is already open.`); } + this.db = new Database(join22(dataFolder, filename)); + this.run("CREATE TABLE IF NOT EXISTS Data(key TEXT NOT NULL PRIMARY KEY, value TEXT NOT NULL)"); + console.info(`Connected to the ${filename} SQLite database.`); + this.readStatement = this.db.prepare("SELECT CAST(value AS BLOB) value FROM Data WHERE key = ?"); + this.writeStatement = this.db.prepare("REPLACE INTO Data(key, value) VALUES(?, ?)"); + this.deleteStatement = this.db.prepare("DELETE FROM Data WHERE key = ?"); + this.iterKeysStatement = this.db.prepare("SELECT key FROM Data"); + this.keyCountStatement = this.db.prepare("SELECT COUNT(*) count FROM Data"); } - } - function asString(str) { - let result = ""; - let last = 0; - let found = false; - let point = 255; - const l = str.length; - if (l > 100) { - return JSON.stringify(str); + // Useful in test hooks. + // deno-lint-ignore require-await + async clear() { + this.run("DELETE FROM Data"); } - for (var i2 = 0; i2 < l && point >= 32; i2++) { - point = str.charCodeAt(i2); - if (point === 34 || point === 92) { - result += str.slice(last, i2) + "\\"; - last = i2; - found = true; + // deno-lint-ignore require-await + async readData(key) { + const row = this.readStatement.get(key); + const value = row?.value; + if (ArrayBuffer.isView(value) && !Buffer11.isBuffer(value)) { + return Buffer11.from(value); + } else { + return value; } } - if (!found) { - result = str; - } else { - result += str.slice(last); + async writeData(key, value) { + await this.writeStatement.run(key, value); } - return point < 32 ? JSON.stringify(str) : '"' + result + '"'; - } - function asJson(obj, msg, num, time3) { - const stringify3 = this[stringifySym]; - const stringifySafe = this[stringifySafeSym]; - const stringifiers = this[stringifiersSym]; - const end = this[endSym]; - const chindings = this[chindingsSym]; - const serializers = this[serializersSym]; - const formatters = this[formattersSym]; - const messageKey = this[messageKeySym]; - const errorKey = this[errorKeySym]; - let data = this[lsCacheSym][num] + time3; - data = data + chindings; - let value; - if (formatters.log) { - obj = formatters.log(obj); + async deleteData(key) { + await this.deleteStatement.run(key); } - const wildcardStringifier = stringifiers[wildcardFirstSym]; - let propStr = ""; - for (const key in obj) { - value = obj[key]; - if (Object.prototype.hasOwnProperty.call(obj, key) && value !== void 0) { - if (serializers[key]) { - value = serializers[key](value); - } else if (key === errorKey && serializers.err) { - value = serializers.err(value); - } - const stringifier = stringifiers[key] || wildcardStringifier; - switch (typeof value) { - case "undefined": - case "function": - continue; - case "number": - if (Number.isFinite(value) === false) { - value = null; - } - // this case explicitly falls through to the next one - case "boolean": - if (stringifier) value = stringifier(value); - break; - case "string": - value = (stringifier || asString)(value); - break; - default: - value = (stringifier || stringify3)(value, stringifySafe); - } - if (value === void 0) continue; - const strKey = asString(key); - propStr += "," + strKey + ":" + value; - } + close() { + this.db.close(); } - let msgStr = ""; - if (msg !== void 0) { - value = serializers[messageKey] ? serializers[messageKey](msg) : msg; - const stringifier = stringifiers[messageKey] || wildcardStringifier; - switch (typeof value) { - case "function": - break; - case "number": - if (Number.isFinite(value) === false) { - value = null; - } - // this case explicitly falls through to the next one - case "boolean": - if (stringifier) value = stringifier(value); - msgStr = ',"' + messageKey + '":' + value; - break; - case "string": - value = (stringifier || asString)(value); - msgStr = ',"' + messageKey + '":' + value; - break; - default: - value = (stringifier || stringify3)(value, stringifySafe); - msgStr = ',"' + messageKey + '":' + value; + async *iterKeys() { + for (const row of this.iterKeysStatement.iter()) { + yield row.key; } } - if (this[nestedKeySym] && propStr) { - return data + this[nestedKeyStrSym] + propStr.slice(1) + "}" + msgStr + end; - } else { - return data + propStr + msgStr + end; + async keyCount() { + const result = await this.keyCountStatement.get(); + return result?.count ?? 0; } - } - function asChindings(instance, bindings) { - let value; - let data = instance[chindingsSym]; - const stringify3 = instance[stringifySym]; - const stringifySafe = instance[stringifySafeSym]; - const stringifiers = instance[stringifiersSym]; - const wildcardStringifier = stringifiers[wildcardFirstSym]; - const serializers = instance[serializersSym]; - const formatter = instance[formattersSym].bindings; - bindings = formatter(bindings); - for (const key in bindings) { - value = bindings[key]; - const valid = key !== "level" && key !== "serializers" && key !== "formatters" && key !== "customLevels" && bindings.hasOwnProperty(key) && value !== void 0; - if (valid === true) { - value = serializers[key] ? serializers[key](value) : value; - value = (stringifiers[key] || wildcardStringifier || stringify3)(value, stringifySafe); - if (value === void 0) continue; - data += ',"' + key + '":' + value; + }; + } +}); +var globImport_database_ts; +var init_ = __esm({ + 'import("./database-*.ts") in src/serve/database-router.ts'() { + globImport_database_ts = __glob({ + "./database-fs.ts": () => Promise.resolve().then(() => (init_database_fs(), database_fs_exports)), + "./database-redis.ts": () => Promise.resolve().then(() => (init_database_redis(), database_redis_exports)), + "./database-router.test.ts": () => Promise.resolve().then(() => (init_database_router_test(), database_router_test_exports)), + "./database-router.ts": () => Promise.resolve().then(() => (init_database_router(), database_router_exports)), + "./database-sqlite.ts": () => Promise.resolve().then(() => (init_database_sqlite(), database_sqlite_exports)) + }); + } +}); +var database_router_exports = {}; +__export(database_router_exports, { + default: () => RouterBackend +}); +var ConfigEntrySchema; +var ConfigSchema4; +var RouterBackend; +var init_database_router = __esm({ + "src/serve/database-router.ts"() { + "use strict"; + init_zod(); + init_DatabaseBackend(); + init_(); + ConfigEntrySchema = strictObject({ + name: string2(), + options: object() + }); + ConfigSchema4 = intersection( + object({ "*": ConfigEntrySchema }), + record(string2(), ConfigEntrySchema) + ); + RouterBackend = class extends DatabaseBackend { + backends; + config; + constructor(config2 = {}) { + super(); + ConfigSchema4.parse(config2); + const configCopy = Object.fromEntries(Object.entries(config2).sort((a, b) => b[0].length - a[0].length)); + const errors2 = this.validateConfig(configCopy); + if (errors2.length) { + throw new Error(`[${this.constructor.name}] ${errors2.length} error(s) found in your config.`, { cause: errors2 }); } + this.config = configCopy; } - return data; - } - function hasBeenTampered(stream) { - return stream.write !== stream.constructor.prototype.write; - } - var hasNodeCodeCoverage = process.env.NODE_V8_COVERAGE || process.env.V8_COVERAGE; - function buildSafeSonicBoom(opts) { - const stream = new SonicBoom(opts); - stream.on("error", filterBrokenPipe); - if (!hasNodeCodeCoverage && !opts.sync && isMainThread) { - onExit.register(stream, autoEnd); - stream.on("close", function() { - onExit.unregister(stream); - }); + lookupBackend(key) { + const { backends, config: config2 } = this; + const keyPrefixes = Object.keys(config2); + for (let i2 = 0; i2 < keyPrefixes.length; i2++) { + if (key.startsWith(keyPrefixes[i2])) { + return backends[keyPrefixes[i2]]; + } + } + return backends["*"]; } - return stream; - function filterBrokenPipe(err) { - if (err.code === "EPIPE") { - stream.write = noop; - stream.end = noop; - stream.flushSync = noop; - stream.destroy = noop; - return; + validateConfig(config2) { + const errors2 = []; + if (!config2["*"]) { + errors2.push({ msg: 'Missing key: "*" (fallback storage is required)' }); } - stream.removeListener("error", filterBrokenPipe); - stream.emit("error", err); + for (const entry of Object.entries(config2)) { + const value = entry[1]; + if (typeof value?.name !== "string" || typeof value?.options !== "object") { + errors2.push({ msg: "entry value must be of type { name: string, options: Object }", entry }); + continue; + } + if (value.name === "router") { + errors2.push({ msg: "Router backends cannot be nested.", entry }); + continue; + } + } + return errors2; } - } - function autoEnd(stream, eventName) { - if (stream.destroyed) { - return; + async init() { + this.backends = /* @__PURE__ */ Object.create(null); + const entries = Object.entries(this.config); + await Promise.all(entries.map(async (entry) => { + const [keyPrefix, { name, options: options2 }] = entry; + const Ctor = (await globImport_database_ts(`./database-${name}.ts`)).default; + const backend = new Ctor(options2); + await backend.init(); + this.backends[keyPrefix] = backend; + })); } - if (eventName === "beforeExit") { - stream.flush(); - stream.on("drain", function() { - stream.end(); - }); - } else { - stream.flushSync(); + async readData(key) { + return await this.lookupBackend(key).readData(key); } - } - function createArgsNormalizer(defaultOptions4) { - return function normalizeArgs(instance, caller, opts = {}, stream) { - if (typeof opts === "string") { - stream = buildSafeSonicBoom({ dest: opts }); - opts = {}; - } else if (typeof stream === "string") { - if (opts && opts.transport) { - throw Error("only one of option.transport or stream can be specified"); - } - stream = buildSafeSonicBoom({ dest: stream }); - } else if (opts instanceof SonicBoom || opts.writable || opts._writableState) { - stream = opts; - opts = {}; - } else if (opts.transport) { - if (opts.transport instanceof SonicBoom || opts.transport.writable || opts.transport._writableState) { - throw Error("option.transport do not allow stream, please pass to option directly. e.g. pino(transport)"); - } - if (opts.transport.targets && opts.transport.targets.length && opts.formatters && typeof opts.formatters.level === "function") { - throw Error("option.transport.targets do not allow custom level formatters"); - } - let customLevels; - if (opts.customLevels) { - customLevels = opts.useOnlyCustomLevels ? opts.customLevels : Object.assign({}, opts.levels, opts.customLevels); + async writeData(key, value) { + return await this.lookupBackend(key).writeData(key, value); + } + async deleteData(key) { + return await this.lookupBackend(key).deleteData(key); + } + async clear() { + for (const backend of new Set(Object.values(this.backends))) { + try { + await backend.clear(); + } catch (e2) { + const prefix = Object.entries(this.backends).find(([, b]) => b === backend)[0]; + console.error(e2, `Error clearing DB for prefix ${prefix}`); } - stream = transport({ caller, ...opts.transport, levels: customLevels }); - } - opts = Object.assign({}, defaultOptions4, opts); - opts.serializers = Object.assign({}, defaultOptions4.serializers, opts.serializers); - opts.formatters = Object.assign({}, defaultOptions4.formatters, opts.formatters); - if (opts.prettyPrint) { - throw new Error("prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)"); } - const { enabled: enabled2, onChild } = opts; - if (enabled2 === false) opts.level = "silent"; - if (!onChild) opts.onChild = noop; - if (!stream) { - if (!hasBeenTampered(process.stdout)) { - stream = buildSafeSonicBoom({ fd: process.stdout.fd || 1 }); - } else { - stream = process.stdout; + } + async close() { + for (const backend of new Set(Object.values(this.backends))) { + try { + await backend.close(); + } catch (e2) { + const prefix = Object.entries(this.backends).find(([, b]) => b === backend)[0]; + console.error(e2, `Error closing DB for prefix ${prefix}`); } } - return { opts, stream }; - }; - } - function stringify2(obj, stringifySafeFn) { - try { - return JSON.stringify(obj); - } catch (_) { - try { - const stringify3 = stringifySafeFn || this[stringifySafeSym]; - return stringify3(obj); - } catch (_2) { - return '"[unable to serialize, circular reference is too complex to analyze]"'; - } } - } - function buildFormatters(level, bindings, log2) { - return { - level, - bindings, - log: log2 - }; - } - function normalizeDestFileDescriptor(destination) { - const fd = Number(destination); - if (typeof destination === "string" && Number.isFinite(fd)) { - return fd; + async *iterKeys() { + for (const backend of new Set(Object.values(this.backends))) { + yield* backend.iterKeys(); + } } - if (destination === void 0) { - return 1; + async keyCount() { + let count = 0; + for (const backend of new Set(Object.values(this.backends))) { + count += await backend.keyCount(); + } + return count; } - return destination; - } - module14.exports = { - noop, - buildSafeSonicBoom, - asChindings, - asJson, - genLog, - createArgsNormalizer, - stringify: stringify2, - buildFormatters, - normalizeDestFileDescriptor - }; - } -}); -var require_constants = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/constants.js"(exports2, module14) { - var DEFAULT_LEVELS = { - trace: 10, - debug: 20, - info: 30, - warn: 40, - error: 50, - fatal: 60 - }; - var SORTING_ORDER = { - ASC: "ASC", - DESC: "DESC" - }; - module14.exports = { - DEFAULT_LEVELS, - SORTING_ORDER }; } }); -var require_levels = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/levels.js"(exports2, module14) { +var database_router_test_exports = {}; +var CID2; +var randomKeyWithPrefix; +var validConfig; +var db; +var init_database_router_test = __esm({ + "src/serve/database-router.test.ts"() { "use strict"; - var { - lsCacheSym, - levelValSym, - useOnlyCustomLevelsSym, - streamSym, - formattersSym, - hooksSym, - levelCompSym - } = require_symbols2(); - var { noop, genLog } = require_tools(); - var { DEFAULT_LEVELS, SORTING_ORDER } = require_constants(); - var levelMethods = { - fatal: (hook) => { - const logFatal = genLog(DEFAULT_LEVELS.fatal, hook); - return function(...args) { - const stream = this[streamSym]; - logFatal.call(this, ...args); - if (typeof stream.flushSync === "function") { - try { - stream.flushSync(); - } catch (e2) { - } - } - }; + init_esm4(); + init_database_router(); + CID2 = "Q"; + randomKeyWithPrefix = (prefix) => `${prefix}${globalThis.crypto.randomUUID().replaceAll("-", "")}`; + validConfig = { + [CID2]: { + name: "sqlite", + options: { + filepath: "./test/temp/sqlite.db" + } }, - error: (hook) => genLog(DEFAULT_LEVELS.error, hook), - warn: (hook) => genLog(DEFAULT_LEVELS.warn, hook), - info: (hook) => genLog(DEFAULT_LEVELS.info, hook), - debug: (hook) => genLog(DEFAULT_LEVELS.debug, hook), - trace: (hook) => genLog(DEFAULT_LEVELS.trace, hook) + "*": { + name: "fs", + options: { + dirname: "./test/temp", + skipFsCaseSensitivityCheck: true + } + } + }; + db = new RouterBackend(validConfig); + Deno.test({ + name: "DatabaseRouter::validateConfig", + async fn(t) { + await t.step("should accept a valid config", () => { + const errors2 = db.validateConfig(validConfig); + if (errors2.length !== 0) throw new Error(`Expected 0 errors but got ${errors2.length}`); + }); + await t.step("should reject configs missing a * key", () => { + const config2 = omit2(validConfig, ["*"]); + const errors2 = db.validateConfig(config2); + if (errors2.length !== 1) throw new Error(`Expected 1 error but got ${errors2.length}`); + }); + await t.step("should reject config entries missing a name", () => { + const config2 = cloneDeep(validConfig); + delete config2["*"].name; + const errors2 = db.validateConfig(config2); + if (errors2.length !== 1) throw new Error(`Expected 1 error but got ${errors2.length}`); + }); + } + }); + Deno.test({ + name: "DatabaseRouter::lookupBackend", + async fn(t) { + await db.init(); + try { + await t.step("should find the right backend for keys starting with configured prefixes", () => { + for (const keyPrefix of Object.keys(db.config)) { + if (keyPrefix === "*") continue; + const key = randomKeyWithPrefix(keyPrefix); + const actual = db.lookupBackend(key); + const expected = db.backends[keyPrefix]; + if (actual !== expected) throw new Error(`Expected ${expected} but got ${actual}`); + } + }); + await t.step("should find the right backend for keys equal to configured prefixes", () => { + for (const keyPrefix of Object.keys(db.config)) { + const key = keyPrefix; + const actual = db.lookupBackend(key); + const expected = db.backends[keyPrefix]; + if (actual !== expected) throw new Error(`Expected ${expected} but got ${actual}`); + } + }); + await t.step("should return the fallback backend for keys not matching any configured prefix", () => { + const key = "foo"; + const actual = db.lookupBackend(key); + const expected = db.backends["*"]; + if (actual !== expected) throw new Error(`Expected ${expected} but got ${actual}`); + }); + } finally { + await db.clear(); + } + } + }); + } +}); +var require_has_flag = __commonJS({ + "node_modules/.deno/has-flag@4.0.0/node_modules/has-flag/index.js"(exports2, module14) { + "use strict"; + module14.exports = (flag, argv = process.argv) => { + const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--"; + const position = argv.indexOf(prefix + flag); + const terminatorPosition = argv.indexOf("--"); + return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); }; - var nums = Object.keys(DEFAULT_LEVELS).reduce((o2, k) => { - o2[DEFAULT_LEVELS[k]] = k; - return o2; - }, {}); - var initialLsCache = Object.keys(nums).reduce((o2, k) => { - o2[k] = '{"level":' + Number(k); - return o2; - }, {}); - function genLsCache(instance) { - const formatter = instance[formattersSym].level; - const { labels } = instance.levels; - const cache2 = {}; - for (const label in labels) { - const level = formatter(labels[label], Number(label)); - cache2[label] = JSON.stringify(level).slice(0, -1); + } +}); +var require_supports_color = __commonJS({ + "node_modules/.deno/supports-color@7.2.0/node_modules/supports-color/index.js"(exports2, module14) { + "use strict"; + var os = __require2("node:os"); + var tty = __require2("node:tty"); + var hasFlag = require_has_flag(); + var { env: env2 } = process; + var forceColor; + if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) { + forceColor = 0; + } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) { + forceColor = 1; + } + if ("FORCE_COLOR" in env2) { + if (env2.FORCE_COLOR === "true") { + forceColor = 1; + } else if (env2.FORCE_COLOR === "false") { + forceColor = 0; + } else { + forceColor = env2.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env2.FORCE_COLOR, 10), 3); } - instance[lsCacheSym] = cache2; - return instance; } - function isStandardLevel(level, useOnlyCustomLevels) { - if (useOnlyCustomLevels) { + function translateLevel(level) { + if (level === 0) { return false; } - switch (level) { - case "fatal": - case "error": - case "warn": - case "info": - case "debug": - case "trace": - return true; - default: - return false; - } + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; } - function setLevel(level) { - const { labels, values } = this.levels; - if (typeof level === "number") { - if (labels[level] === void 0) throw Error("unknown level value" + level); - level = labels[level]; + function supportsColor(haveStream, streamIsTTY) { + if (forceColor === 0) { + return 0; } - if (values[level] === void 0) throw Error("unknown level " + level); - const preLevelVal = this[levelValSym]; - const levelVal = this[levelValSym] = values[level]; - const useOnlyCustomLevelsVal = this[useOnlyCustomLevelsSym]; - const levelComparison = this[levelCompSym]; - const hook = this[hooksSym].logMethod; - for (const key in values) { - if (levelComparison(values[key], levelVal) === false) { - this[key] = noop; - continue; - } - this[key] = isStandardLevel(key, useOnlyCustomLevelsVal) ? levelMethods[key](hook) : genLog(values[key], hook); + if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) { + return 3; } - this.emit( - "level-change", - level, - levelVal, - labels[preLevelVal], - preLevelVal, - this - ); - } - function getLevel(level) { - const { levels, levelVal } = this; - return levels && levels.labels ? levels.labels[levelVal] : ""; - } - function isLevelEnabled(logLevel2) { - const { values } = this.levels; - const logLevelVal = values[logLevel2]; - return logLevelVal !== void 0 && this[levelCompSym](logLevelVal, this[levelValSym]); - } - function compareLevel(direction, current, expected) { - if (direction === SORTING_ORDER.DESC) { - return current <= expected; + if (hasFlag("color=256")) { + return 2; } - return current >= expected; - } - function genLevelComparison(levelComparison) { - if (typeof levelComparison === "string") { - return compareLevel.bind(null, levelComparison); + if (haveStream && !streamIsTTY && forceColor === void 0) { + return 0; } - return levelComparison; - } - function mappings(customLevels = null, useOnlyCustomLevels = false) { - const customNums = customLevels ? Object.keys(customLevels).reduce((o2, k) => { - o2[customLevels[k]] = k; - return o2; - }, {}) : null; - const labels = Object.assign( - Object.create(Object.prototype, { Infinity: { value: "silent" } }), - useOnlyCustomLevels ? null : nums, - customNums - ); - const values = Object.assign( - Object.create(Object.prototype, { silent: { value: Infinity } }), - useOnlyCustomLevels ? null : DEFAULT_LEVELS, - customLevels - ); - return { labels, values }; - } - function assertDefaultLevelFound(defaultLevel, customLevels, useOnlyCustomLevels) { - if (typeof defaultLevel === "number") { - const values = [].concat( - Object.keys(customLevels || {}).map((key) => customLevels[key]), - useOnlyCustomLevels ? [] : Object.keys(nums).map((level) => +level), - Infinity - ); - if (!values.includes(defaultLevel)) { - throw Error(`default level:${defaultLevel} must be included in custom levels`); - } - return; + const min = forceColor || 0; + if (env2.TERM === "dumb") { + return min; } - const labels = Object.assign( - Object.create(Object.prototype, { silent: { value: Infinity } }), - useOnlyCustomLevels ? null : DEFAULT_LEVELS, - customLevels - ); - if (!(defaultLevel in labels)) { - throw Error(`default level:${defaultLevel} must be included in custom levels`); + if (process.platform === "win32") { + const osRelease = os.release().split("."); + if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + return 1; } - } - function assertNoLevelCollisions(levels, customLevels) { - const { labels, values } = levels; - for (const k in customLevels) { - if (k in values) { - throw Error("levels cannot be overridden"); + if ("CI" in env2) { + if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign2) => sign2 in env2) || env2.CI_NAME === "codeship") { + return 1; } - if (customLevels[k] in labels) { - throw Error("pre-existing level values cannot be used for new levels"); + return min; + } + if ("TEAMCITY_VERSION" in env2) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env2.TEAMCITY_VERSION) ? 1 : 0; + } + if (env2.COLORTERM === "truecolor") { + return 3; + } + if ("TERM_PROGRAM" in env2) { + const version3 = parseInt((env2.TERM_PROGRAM_VERSION || "").split(".")[0], 10); + switch (env2.TERM_PROGRAM) { + case "iTerm.app": + return version3 >= 3 ? 3 : 2; + case "Apple_Terminal": + return 2; } } - } - function assertLevelComparison(levelComparison) { - if (typeof levelComparison === "function") { - return; + if (/-256(color)?$/i.test(env2.TERM)) { + return 2; } - if (typeof levelComparison === "string" && Object.values(SORTING_ORDER).includes(levelComparison)) { - return; + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env2.TERM)) { + return 1; } - throw new Error('Levels comparison should be one of "ASC", "DESC" or "function" type'); + if ("COLORTERM" in env2) { + return 1; + } + return min; + } + function getSupportLevel(stream) { + const level = supportsColor(stream, stream && stream.isTTY); + return translateLevel(level); } module14.exports = { - initialLsCache, - genLsCache, - levelMethods, - getLevel, - setLevel, - isLevelEnabled, - mappings, - assertNoLevelCollisions, - assertDefaultLevelFound, - genLevelComparison, - assertLevelComparison + supportsColor: getSupportLevel, + stdout: translateLevel(supportsColor(true, tty.isatty(1))), + stderr: translateLevel(supportsColor(true, tty.isatty(2))) }; } }); -var require_meta = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/meta.js"(exports2, module14) { - "use strict"; - module14.exports = { version: "8.19.0" }; - } -}); -var require_proto = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/proto.js"(exports2, module14) { +var require_util2 = __commonJS({ + "node_modules/.deno/chalk@4.1.0/node_modules/chalk/source/util.js"(exports2, module14) { "use strict"; - var { EventEmitter } = __require2("events"); - var { - lsCacheSym, - levelValSym, - setLevelSym, - getLevelSym, - chindingsSym, - parsedChindingsSym, - mixinSym, - asJsonSym, - writeSym, - mixinMergeStrategySym, - timeSym, - timeSliceIndexSym, - streamSym, - serializersSym, - formattersSym, - errorKeySym, - messageKeySym, - useOnlyCustomLevelsSym, - needsMetadataGsym, - redactFmtSym, - stringifySym, - formatOptsSym, - stringifiersSym, - msgPrefixSym - } = require_symbols2(); - var { - getLevel, - setLevel, - isLevelEnabled, - mappings, - initialLsCache, - genLsCache, - assertNoLevelCollisions - } = require_levels(); - var { - asChindings, - asJson, - buildFormatters, - stringify: stringify2 - } = require_tools(); - var { - version: version3 - } = require_meta(); - var redaction = require_redaction(); - var constructor = class Pino { + var stringReplaceAll = (string3, substring, replacer) => { + let index = string3.indexOf(substring); + if (index === -1) { + return string3; + } + const substringLength = substring.length; + let endIndex = 0; + let returnValue = ""; + do { + returnValue += string3.substr(endIndex, index - endIndex) + substring + replacer; + endIndex = index + substringLength; + index = string3.indexOf(substring, endIndex); + } while (index !== -1); + returnValue += string3.substr(endIndex); + return returnValue; }; - var prototype = { - constructor, - child, - bindings, - setBindings, - flush, - isLevelEnabled, - version: version3, - get level() { - return this[getLevelSym](); - }, - set level(lvl) { - this[setLevelSym](lvl); - }, - get levelVal() { - return this[levelValSym]; - }, - set levelVal(n) { - throw Error("levelVal is read-only"); - }, - [lsCacheSym]: initialLsCache, - [writeSym]: write, - [asJsonSym]: asJson, - [getLevelSym]: getLevel, - [setLevelSym]: setLevel + var stringEncaseCRLFWithFirstIndex = (string3, prefix, postfix, index) => { + let endIndex = 0; + let returnValue = ""; + do { + const gotCR = string3[index - 1] === "\r"; + returnValue += string3.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? "\r\n" : "\n") + postfix; + endIndex = index + 1; + index = string3.indexOf("\n", endIndex); + } while (index !== -1); + returnValue += string3.substr(endIndex); + return returnValue; }; - Object.setPrototypeOf(prototype, EventEmitter.prototype); - module14.exports = function() { - return Object.create(prototype); + module14.exports = { + stringReplaceAll, + stringEncaseCRLFWithFirstIndex }; - var resetChildingsFormatter = (bindings2) => bindings2; - function child(bindings2, options2) { - if (!bindings2) { - throw Error("missing bindings for child Pino"); - } - options2 = options2 || {}; - const serializers = this[serializersSym]; - const formatters = this[formattersSym]; - const instance = Object.create(this); - if (options2.hasOwnProperty("serializers") === true) { - instance[serializersSym] = /* @__PURE__ */ Object.create(null); - for (const k in serializers) { - instance[serializersSym][k] = serializers[k]; - } - const parentSymbols = Object.getOwnPropertySymbols(serializers); - for (var i2 = 0; i2 < parentSymbols.length; i2++) { - const ks = parentSymbols[i2]; - instance[serializersSym][ks] = serializers[ks]; - } - for (const bk in options2.serializers) { - instance[serializersSym][bk] = options2.serializers[bk]; - } - const bindingsSymbols = Object.getOwnPropertySymbols(options2.serializers); - for (var bi = 0; bi < bindingsSymbols.length; bi++) { - const bks = bindingsSymbols[bi]; - instance[serializersSym][bks] = options2.serializers[bks]; - } - } else instance[serializersSym] = serializers; - if (options2.hasOwnProperty("formatters")) { - const { level, bindings: chindings, log: log2 } = options2.formatters; - instance[formattersSym] = buildFormatters( - level || formatters.level, - chindings || resetChildingsFormatter, - log2 || formatters.log - ); - } else { - instance[formattersSym] = buildFormatters( - formatters.level, - resetChildingsFormatter, - formatters.log - ); - } - if (options2.hasOwnProperty("customLevels") === true) { - assertNoLevelCollisions(this.levels, options2.customLevels); - instance.levels = mappings(options2.customLevels, instance[useOnlyCustomLevelsSym]); - genLsCache(instance); - } - if (typeof options2.redact === "object" && options2.redact !== null || Array.isArray(options2.redact)) { - instance.redact = options2.redact; - const stringifiers = redaction(instance.redact, stringify2); - const formatOpts = { stringify: stringifiers[redactFmtSym] }; - instance[stringifySym] = stringify2; - instance[stringifiersSym] = stringifiers; - instance[formatOptsSym] = formatOpts; + } +}); +var require_templates = __commonJS({ + "node_modules/.deno/chalk@4.1.0/node_modules/chalk/source/templates.js"(exports2, module14) { + "use strict"; + var TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; + var STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; + var STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; + var ESCAPE_REGEX2 = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi; + var ESCAPES = /* @__PURE__ */ new Map([ + ["n", "\n"], + ["r", "\r"], + ["t", " "], + ["b", "\b"], + ["f", "\f"], + ["v", "\v"], + ["0", "\0"], + ["\\", "\\"], + ["e", "\x1B"], + ["a", "\x07"] + ]); + function unescape(c) { + const u2 = c[0] === "u"; + const bracket = c[1] === "{"; + if (u2 && !bracket && c.length === 5 || c[0] === "x" && c.length === 3) { + return String.fromCharCode(parseInt(c.slice(1), 16)); } - if (typeof options2.msgPrefix === "string") { - instance[msgPrefixSym] = (this[msgPrefixSym] || "") + options2.msgPrefix; + if (u2 && bracket) { + return String.fromCodePoint(parseInt(c.slice(2, -1), 16)); } - instance[chindingsSym] = asChindings(instance, bindings2); - const childLevel = options2.level || this.level; - instance[setLevelSym](childLevel); - this.onChild(instance); - return instance; - } - function bindings() { - const chindings = this[chindingsSym]; - const chindingsJson = `{${chindings.substr(1)}}`; - const bindingsFromJson = JSON.parse(chindingsJson); - delete bindingsFromJson.pid; - delete bindingsFromJson.hostname; - return bindingsFromJson; - } - function setBindings(newBindings) { - const chindings = asChindings(this, newBindings); - this[chindingsSym] = chindings; - delete this[parsedChindingsSym]; - } - function defaultMixinMergeStrategy(mergeObject, mixinObject) { - return Object.assign(mixinObject, mergeObject); + return ESCAPES.get(c) || c; } - function write(_obj, msg, num) { - const t = this[timeSym](); - const mixin3 = this[mixinSym]; - const errorKey = this[errorKeySym]; - const messageKey = this[messageKeySym]; - const mixinMergeStrategy = this[mixinMergeStrategySym] || defaultMixinMergeStrategy; - let obj; - if (_obj === void 0 || _obj === null) { - obj = {}; - } else if (_obj instanceof Error) { - obj = { [errorKey]: _obj }; - if (msg === void 0) { - msg = _obj.message; + function parseArguments(name, arguments_) { + const results = []; + const chunks = arguments_.trim().split(/\s*,\s*/g); + let matches; + for (const chunk of chunks) { + const number3 = Number(chunk); + if (!Number.isNaN(number3)) { + results.push(number3); + } else if (matches = chunk.match(STRING_REGEX)) { + results.push(matches[2].replace(ESCAPE_REGEX2, (m3, escape, character) => escape ? unescape(escape) : character)); + } else { + throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); } - } else { - obj = _obj; - if (msg === void 0 && _obj[messageKey] === void 0 && _obj[errorKey]) { - msg = _obj[errorKey].message; + } + return results; + } + function parseStyle(style) { + STYLE_REGEX.lastIndex = 0; + const results = []; + let matches; + while ((matches = STYLE_REGEX.exec(style)) !== null) { + const name = matches[1]; + if (matches[2]) { + const args = parseArguments(name, matches[2]); + results.push([name].concat(args)); + } else { + results.push([name]); } } - if (mixin3) { - obj = mixinMergeStrategy(obj, mixin3(obj, num, this)); + return results; + } + function buildStyle(chalk5, styles) { + const enabled2 = {}; + for (const layer of styles) { + for (const style of layer.styles) { + enabled2[style[0]] = layer.inverse ? null : style.slice(1); + } } - const s = this[asJsonSym](obj, msg, num, t); - const stream = this[streamSym]; - if (stream[needsMetadataGsym] === true) { - stream.lastLevel = num; - stream.lastObj = obj; - stream.lastMsg = msg; - stream.lastTime = t.slice(this[timeSliceIndexSym]); - stream.lastLogger = this; + let current = chalk5; + for (const [styleName, styles2] of Object.entries(enabled2)) { + if (!Array.isArray(styles2)) { + continue; + } + if (!(styleName in current)) { + throw new Error(`Unknown Chalk style: ${styleName}`); + } + current = styles2.length > 0 ? current[styleName](...styles2) : current[styleName]; } - stream.write(s); - } - function noop() { + return current; } - function flush(cb) { - if (cb != null && typeof cb !== "function") { - throw Error("callback must be a function"); + module14.exports = (chalk5, temporary) => { + const styles = []; + const chunks = []; + let chunk = []; + temporary.replace(TEMPLATE_REGEX, (m3, escapeCharacter, inverse, style, close, character) => { + if (escapeCharacter) { + chunk.push(unescape(escapeCharacter)); + } else if (style) { + const string3 = chunk.join(""); + chunk = []; + chunks.push(styles.length === 0 ? string3 : buildStyle(chalk5, styles)(string3)); + styles.push({ inverse, styles: parseStyle(style) }); + } else if (close) { + if (styles.length === 0) { + throw new Error("Found extraneous } in Chalk template literal"); + } + chunks.push(buildStyle(chalk5, styles)(chunk.join(""))); + chunk = []; + styles.pop(); + } else { + chunk.push(character); + } + }); + chunks.push(chunk.join("")); + if (styles.length > 0) { + const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? "" : "s"} (\`}\`)`; + throw new Error(errMessage); } - const stream = this[streamSym]; - if (typeof stream.flush === "function") { - stream.flush(cb || noop); - } else if (cb) cb(); - } + return chunks.join(""); + }; } }); -var require_safe_stable_stringify = __commonJS({ - "node_modules/.deno/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports2, module14) { +var require_source = __commonJS({ + "node_modules/.deno/chalk@4.1.0/node_modules/chalk/source/index.js"(exports2, module14) { "use strict"; - var { hasOwnProperty } = Object.prototype; - var stringify2 = configure(); - stringify2.configure = configure; - stringify2.stringify = stringify2; - stringify2.default = stringify2; - exports2.stringify = stringify2; - exports2.configure = configure; - module14.exports = stringify2; - var strEscapeSequencesRegExp = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/; - function strEscape(str) { - if (str.length < 5e3 && !strEscapeSequencesRegExp.test(str)) { - return `"${str}"`; - } - return JSON.stringify(str); - } - function sort(array2, comparator) { - if (array2.length > 200 || comparator) { - return array2.sort(comparator); + var ansiStyles = require_ansi_styles(); + var { stdout: stdoutColor, stderr: stderrColor } = require_supports_color(); + var { + stringReplaceAll, + stringEncaseCRLFWithFirstIndex + } = require_util2(); + var { isArray } = Array; + var levelMapping = [ + "ansi", + "ansi", + "ansi256", + "ansi16m" + ]; + var styles = /* @__PURE__ */ Object.create(null); + var applyOptions = (object2, options2 = {}) => { + if (options2.level && !(Number.isInteger(options2.level) && options2.level >= 0 && options2.level <= 3)) { + throw new Error("The `level` option should be an integer from 0 to 3"); } - for (let i2 = 1; i2 < array2.length; i2++) { - const currentValue = array2[i2]; - let position = i2; - while (position !== 0 && array2[position - 1] > currentValue) { - array2[position] = array2[position - 1]; - position--; - } - array2[position] = currentValue; + const colorLevel = stdoutColor ? stdoutColor.level : 0; + object2.level = options2.level === void 0 ? colorLevel : options2.level; + }; + var ChalkClass = class { + constructor(options2) { + return chalkFactory(options2); } - return array2; + }; + var chalkFactory = (options2) => { + const chalk6 = {}; + applyOptions(chalk6, options2); + chalk6.template = (...arguments_) => chalkTag(chalk6.template, ...arguments_); + Object.setPrototypeOf(chalk6, Chalk.prototype); + Object.setPrototypeOf(chalk6.template, chalk6); + chalk6.template.constructor = () => { + throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead."); + }; + chalk6.template.Instance = ChalkClass; + return chalk6.template; + }; + function Chalk(options2) { + return chalkFactory(options2); } - var typedArrayPrototypeGetSymbolToStringTag = Object.getOwnPropertyDescriptor( - Object.getPrototypeOf( - Object.getPrototypeOf( - new Int8Array() - ) - ), - Symbol.toStringTag - ).get; - function isTypedArrayWithEntries(value) { - return typedArrayPrototypeGetSymbolToStringTag.call(value) !== void 0 && value.length !== 0; + for (const [styleName, style] of Object.entries(ansiStyles)) { + styles[styleName] = { + get() { + const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty); + Object.defineProperty(this, styleName, { value: builder }); + return builder; + } + }; } - function stringifyTypedArray(array2, separator, maximumBreadth) { - if (array2.length < maximumBreadth) { - maximumBreadth = array2.length; - } - const whitespace = separator === "," ? "" : " "; - let res = `"0":${whitespace}${array2[0]}`; - for (let i2 = 1; i2 < maximumBreadth; i2++) { - res += `${separator}"${i2}":${whitespace}${array2[i2]}`; + styles.visible = { + get() { + const builder = createBuilder(this, this._styler, true); + Object.defineProperty(this, "visible", { value: builder }); + return builder; } - return res; - } - function getCircularValueOption(options2) { - if (hasOwnProperty.call(options2, "circularValue")) { - const circularValue = options2.circularValue; - if (typeof circularValue === "string") { - return `"${circularValue}"`; - } - if (circularValue == null) { - return circularValue; - } - if (circularValue === Error || circularValue === TypeError) { - return { - toString() { - throw new TypeError("Converting circular structure to JSON"); - } + }; + var usedModels = ["rgb", "hex", "keyword", "hsl", "hsv", "hwb", "ansi", "ansi256"]; + for (const model of usedModels) { + styles[model] = { + get() { + const { level } = this; + return function(...arguments_) { + const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler); + return createBuilder(this, styler, this._isEmpty); }; } - throw new TypeError('The "circularValue" argument must be of type string or the value null or undefined'); - } - return '"[Circular]"'; + }; } - function getDeterministicOption(options2) { - let value; - if (hasOwnProperty.call(options2, "deterministic")) { - value = options2.deterministic; - if (typeof value !== "boolean" && typeof value !== "function") { - throw new TypeError('The "deterministic" argument must be of type boolean or comparator function'); + for (const model of usedModels) { + const bgModel = "bg" + model[0].toUpperCase() + model.slice(1); + styles[bgModel] = { + get() { + const { level } = this; + return function(...arguments_) { + const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler); + return createBuilder(this, styler, this._isEmpty); + }; } - } - return value === void 0 ? true : value; + }; } - function getBooleanOption(options2, key) { - let value; - if (hasOwnProperty.call(options2, key)) { - value = options2[key]; - if (typeof value !== "boolean") { - throw new TypeError(`The "${key}" argument must be of type boolean`); + var proto3 = Object.defineProperties(() => { + }, { + ...styles, + level: { + enumerable: true, + get() { + return this._generator.level; + }, + set(level) { + this._generator.level = level; } } - return value === void 0 ? true : value; - } - function getPositiveIntegerOption(options2, key) { - let value; - if (hasOwnProperty.call(options2, key)) { - value = options2[key]; - if (typeof value !== "number") { - throw new TypeError(`The "${key}" argument must be of type number`); - } - if (!Number.isInteger(value)) { - throw new TypeError(`The "${key}" argument must be an integer`); + }); + var createStyler = (open2, close, parent) => { + let openAll; + let closeAll; + if (parent === void 0) { + openAll = open2; + closeAll = close; + } else { + openAll = parent.openAll + open2; + closeAll = close + parent.closeAll; + } + return { + open: open2, + close, + openAll, + closeAll, + parent + }; + }; + var createBuilder = (self2, _styler, _isEmpty) => { + const builder = (...arguments_) => { + if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) { + return applyStyle(builder, chalkTag(builder, ...arguments_)); } - if (value < 1) { - throw new RangeError(`The "${key}" argument must be >= 1`); + return applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" ")); + }; + Object.setPrototypeOf(builder, proto3); + builder._generator = self2; + builder._styler = _styler; + builder._isEmpty = _isEmpty; + return builder; + }; + var applyStyle = (self2, string3) => { + if (self2.level <= 0 || !string3) { + return self2._isEmpty ? "" : string3; + } + let styler = self2._styler; + if (styler === void 0) { + return string3; + } + const { openAll, closeAll } = styler; + if (string3.indexOf("\x1B") !== -1) { + while (styler !== void 0) { + string3 = stringReplaceAll(string3, styler.close, styler.open); + styler = styler.parent; } } - return value === void 0 ? Infinity : value; - } - function getItemCount(number3) { - if (number3 === 1) { - return "1 item"; + const lfIndex = string3.indexOf("\n"); + if (lfIndex !== -1) { + string3 = stringEncaseCRLFWithFirstIndex(string3, closeAll, openAll, lfIndex); } - return `${number3} items`; - } - function getUniqueReplacerSet(replacerArray) { - const replacerSet = /* @__PURE__ */ new Set(); - for (const value of replacerArray) { - if (typeof value === "string" || typeof value === "number") { - replacerSet.add(String(value)); + return openAll + string3 + closeAll; + }; + var template; + var chalkTag = (chalk6, ...strings) => { + const [firstString] = strings; + if (!isArray(firstString) || !isArray(firstString.raw)) { + return strings.join(" "); + } + const arguments_ = strings.slice(1); + const parts = [firstString.raw[0]]; + for (let i2 = 1; i2 < firstString.length; i2++) { + parts.push( + String(arguments_[i2 - 1]).replace(/[{}\\]/g, "\\$&"), + String(firstString.raw[i2]) + ); + } + if (template === void 0) { + template = require_templates(); + } + return template(chalk6, parts.join("")); + }; + Object.defineProperties(Chalk.prototype, styles); + var chalk5 = Chalk(); + chalk5.supportsColor = stdoutColor; + chalk5.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 }); + chalk5.stderr.supportsColor = stderrColor; + module14.exports = chalk5; + } +}); +var require_parser2 = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/parser.js"(exports2) { + "use strict"; + exports2.load = function(received, defaults, onto = {}) { + var k, ref, v2; + for (k in defaults) { + v2 = defaults[k]; + onto[k] = (ref = received[k]) != null ? ref : v2; + } + return onto; + }; + exports2.overwrite = function(received, defaults, onto = {}) { + var k, v2; + for (k in received) { + v2 = received[k]; + if (defaults[k] !== void 0) { + onto[k] = v2; } } - return replacerSet; - } - function getStrictOption(options2) { - if (hasOwnProperty.call(options2, "strict")) { - const value = options2.strict; - if (typeof value !== "boolean") { - throw new TypeError('The "strict" argument must be of type boolean'); + return onto; + }; + } +}); +var require_DLList = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/DLList.js"(exports2, module14) { + "use strict"; + var DLList; + DLList = class DLList { + constructor(incr, decr) { + this.incr = incr; + this.decr = decr; + this._first = null; + this._last = null; + this.length = 0; + } + push(value) { + var node; + this.length++; + if (typeof this.incr === "function") { + this.incr(); } - if (value) { - return (value2) => { - let message = `Object can not safely be stringified. Received type ${typeof value2}`; - if (typeof value2 !== "function") message += ` (${value2.toString()})`; - throw new Error(message); - }; + node = { + value, + prev: this._last, + next: null + }; + if (this._last != null) { + this._last.next = node; + this._last = node; + } else { + this._first = this._last = node; } + return void 0; } - } - function configure(options2) { - options2 = { ...options2 }; - const fail = getStrictOption(options2); - if (fail) { - if (options2.bigint === void 0) { - options2.bigint = false; + shift() { + var value; + if (this._first == null) { + return; + } else { + this.length--; + if (typeof this.decr === "function") { + this.decr(); + } } - if (!("circularValue" in options2)) { - options2.circularValue = Error; + value = this._first.value; + if ((this._first = this._first.next) != null) { + this._first.prev = null; + } else { + this._last = null; } + return value; } - const circularValue = getCircularValueOption(options2); - const bigint2 = getBooleanOption(options2, "bigint"); - const deterministic = getDeterministicOption(options2); - const comparator = typeof deterministic === "function" ? deterministic : void 0; - const maximumDepth = getPositiveIntegerOption(options2, "maximumDepth"); - const maximumBreadth = getPositiveIntegerOption(options2, "maximumBreadth"); - function stringifyFnReplacer(key, parent, stack, replacer, spacer, indentation) { - let value = parent[key]; - if (typeof value === "object" && value !== null && typeof value.toJSON === "function") { - value = value.toJSON(key); + first() { + if (this._first != null) { + return this._first.value; } - value = replacer.call(parent, key, value); - switch (typeof value) { - case "string": - return strEscape(value); - case "object": { - if (value === null) { - return "null"; - } - if (stack.indexOf(value) !== -1) { - return circularValue; - } - let res = ""; - let join92 = ","; - const originalIndentation = indentation; - if (Array.isArray(value)) { - if (value.length === 0) { - return "[]"; - } - if (maximumDepth < stack.length + 1) { - return '"[Array]"'; - } - stack.push(value); - if (spacer !== "") { - indentation += spacer; - res += ` -${indentation}`; - join92 = `, -${indentation}`; - } - const maximumValuesToStringify = Math.min(value.length, maximumBreadth); - let i2 = 0; - for (; i2 < maximumValuesToStringify - 1; i2++) { - const tmp2 = stringifyFnReplacer(String(i2), value, stack, replacer, spacer, indentation); - res += tmp2 !== void 0 ? tmp2 : "null"; - res += join92; - } - const tmp = stringifyFnReplacer(String(i2), value, stack, replacer, spacer, indentation); - res += tmp !== void 0 ? tmp : "null"; - if (value.length - 1 > maximumBreadth) { - const removedKeys = value.length - maximumBreadth - 1; - res += `${join92}"... ${getItemCount(removedKeys)} not stringified"`; - } - if (spacer !== "") { - res += ` -${originalIndentation}`; - } - stack.pop(); - return `[${res}]`; - } - let keys = Object.keys(value); - const keyLength = keys.length; - if (keyLength === 0) { - return "{}"; - } - if (maximumDepth < stack.length + 1) { - return '"[Object]"'; - } - let whitespace = ""; - let separator = ""; - if (spacer !== "") { - indentation += spacer; - join92 = `, -${indentation}`; - whitespace = " "; - } - const maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth); - if (deterministic && !isTypedArrayWithEntries(value)) { - keys = sort(keys, comparator); - } - stack.push(value); - for (let i2 = 0; i2 < maximumPropertiesToStringify; i2++) { - const key2 = keys[i2]; - const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation); - if (tmp !== void 0) { - res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`; - separator = join92; - } - } - if (keyLength > maximumBreadth) { - const removedKeys = keyLength - maximumBreadth; - res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`; - separator = join92; - } - if (spacer !== "" && separator.length > 1) { - res = ` -${indentation}${res} -${originalIndentation}`; - } - stack.pop(); - return `{${res}}`; - } - case "number": - return isFinite(value) ? String(value) : fail ? fail(value) : "null"; - case "boolean": - return value === true ? "true" : "false"; - case "undefined": - return void 0; - case "bigint": - if (bigint2) { - return String(value); - } - // fallthrough - default: - return fail ? fail(value) : void 0; + } + getArray() { + var node, ref, results; + node = this._first; + results = []; + while (node != null) { + results.push((ref = node, node = node.next, ref.value)); + } + return results; + } + forEachShift(cb) { + var node; + node = this.shift(); + while (node != null) { + cb(node), node = this.shift(); } + return void 0; } - function stringifyArrayReplacer(key, value, stack, replacer, spacer, indentation) { - if (typeof value === "object" && value !== null && typeof value.toJSON === "function") { - value = value.toJSON(key); + debug() { + var node, ref, ref1, ref2, results; + node = this._first; + results = []; + while (node != null) { + results.push((ref = node, node = node.next, { + value: ref.value, + prev: (ref1 = ref.prev) != null ? ref1.value : void 0, + next: (ref2 = ref.next) != null ? ref2.value : void 0 + })); } - switch (typeof value) { - case "string": - return strEscape(value); - case "object": { - if (value === null) { - return "null"; - } - if (stack.indexOf(value) !== -1) { - return circularValue; - } - const originalIndentation = indentation; - let res = ""; - let join92 = ","; - if (Array.isArray(value)) { - if (value.length === 0) { - return "[]"; - } - if (maximumDepth < stack.length + 1) { - return '"[Array]"'; - } - stack.push(value); - if (spacer !== "") { - indentation += spacer; - res += ` -${indentation}`; - join92 = `, -${indentation}`; - } - const maximumValuesToStringify = Math.min(value.length, maximumBreadth); - let i2 = 0; - for (; i2 < maximumValuesToStringify - 1; i2++) { - const tmp2 = stringifyArrayReplacer(String(i2), value[i2], stack, replacer, spacer, indentation); - res += tmp2 !== void 0 ? tmp2 : "null"; - res += join92; - } - const tmp = stringifyArrayReplacer(String(i2), value[i2], stack, replacer, spacer, indentation); - res += tmp !== void 0 ? tmp : "null"; - if (value.length - 1 > maximumBreadth) { - const removedKeys = value.length - maximumBreadth - 1; - res += `${join92}"... ${getItemCount(removedKeys)} not stringified"`; - } - if (spacer !== "") { - res += ` -${originalIndentation}`; - } - stack.pop(); - return `[${res}]`; - } - stack.push(value); - let whitespace = ""; - if (spacer !== "") { - indentation += spacer; - join92 = `, -${indentation}`; - whitespace = " "; - } - let separator = ""; - for (const key2 of replacer) { - const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation); - if (tmp !== void 0) { - res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`; - separator = join92; - } - } - if (spacer !== "" && separator.length > 1) { - res = ` -${indentation}${res} -${originalIndentation}`; - } - stack.pop(); - return `{${res}}`; + return results; + } + }; + module14.exports = DLList; + } +}); +var require_Events = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Events.js"(exports2, module14) { + "use strict"; + function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; + } + if (info.done) { + resolve82(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + function _asyncToGenerator2(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); } - case "number": - return isFinite(value) ? String(value) : fail ? fail(value) : "null"; - case "boolean": - return value === true ? "true" : "false"; - case "undefined": - return void 0; - case "bigint": - if (bigint2) { - return String(value); - } - // fallthrough - default: - return fail ? fail(value) : void 0; + function _throw(err) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + } + _next(void 0); + }); + }; + } + var Events2; + Events2 = class Events { + constructor(instance) { + this.instance = instance; + this._events = {}; + if (this.instance.on != null || this.instance.once != null || this.instance.removeAllListeners != null) { + throw new Error("An Emitter already exists for this object"); } - } - function stringifyIndent(key, value, stack, spacer, indentation) { - switch (typeof value) { - case "string": - return strEscape(value); - case "object": { - if (value === null) { - return "null"; - } - if (typeof value.toJSON === "function") { - value = value.toJSON(key); - if (typeof value !== "object") { - return stringifyIndent(key, value, stack, spacer, indentation); - } - if (value === null) { - return "null"; - } - } - if (stack.indexOf(value) !== -1) { - return circularValue; - } - const originalIndentation = indentation; - if (Array.isArray(value)) { - if (value.length === 0) { - return "[]"; - } - if (maximumDepth < stack.length + 1) { - return '"[Array]"'; - } - stack.push(value); - indentation += spacer; - let res2 = ` -${indentation}`; - const join10 = `, -${indentation}`; - const maximumValuesToStringify = Math.min(value.length, maximumBreadth); - let i2 = 0; - for (; i2 < maximumValuesToStringify - 1; i2++) { - const tmp2 = stringifyIndent(String(i2), value[i2], stack, spacer, indentation); - res2 += tmp2 !== void 0 ? tmp2 : "null"; - res2 += join10; - } - const tmp = stringifyIndent(String(i2), value[i2], stack, spacer, indentation); - res2 += tmp !== void 0 ? tmp : "null"; - if (value.length - 1 > maximumBreadth) { - const removedKeys = value.length - maximumBreadth - 1; - res2 += `${join10}"... ${getItemCount(removedKeys)} not stringified"`; - } - res2 += ` -${originalIndentation}`; - stack.pop(); - return `[${res2}]`; - } - let keys = Object.keys(value); - const keyLength = keys.length; - if (keyLength === 0) { - return "{}"; - } - if (maximumDepth < stack.length + 1) { - return '"[Object]"'; - } - indentation += spacer; - const join92 = `, -${indentation}`; - let res = ""; - let separator = ""; - let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth); - if (isTypedArrayWithEntries(value)) { - res += stringifyTypedArray(value, join92, maximumBreadth); - keys = keys.slice(value.length); - maximumPropertiesToStringify -= value.length; - separator = join92; - } - if (deterministic) { - keys = sort(keys, comparator); - } - stack.push(value); - for (let i2 = 0; i2 < maximumPropertiesToStringify; i2++) { - const key2 = keys[i2]; - const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation); - if (tmp !== void 0) { - res += `${separator}${strEscape(key2)}: ${tmp}`; - separator = join92; - } - } - if (keyLength > maximumBreadth) { - const removedKeys = keyLength - maximumBreadth; - res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`; - separator = join92; - } - if (separator !== "") { - res = ` -${indentation}${res} -${originalIndentation}`; - } - stack.pop(); - return `{${res}}`; + this.instance.on = (name, cb) => { + return this._addListener(name, "many", cb); + }; + this.instance.once = (name, cb) => { + return this._addListener(name, "once", cb); + }; + this.instance.removeAllListeners = (name = null) => { + if (name != null) { + return delete this._events[name]; + } else { + return this._events = {}; } - case "number": - return isFinite(value) ? String(value) : fail ? fail(value) : "null"; - case "boolean": - return value === true ? "true" : "false"; - case "undefined": - return void 0; - case "bigint": - if (bigint2) { - return String(value); - } - // fallthrough - default: - return fail ? fail(value) : void 0; + }; + } + _addListener(name, status, cb) { + var base2; + if ((base2 = this._events)[name] == null) { + base2[name] = []; } + this._events[name].push({ + cb, + status + }); + return this.instance; } - function stringifySimple(key, value, stack) { - switch (typeof value) { - case "string": - return strEscape(value); - case "object": { - if (value === null) { - return "null"; - } - if (typeof value.toJSON === "function") { - value = value.toJSON(key); - if (typeof value !== "object") { - return stringifySimple(key, value, stack); - } - if (value === null) { - return "null"; - } - } - if (stack.indexOf(value) !== -1) { - return circularValue; - } - let res = ""; - const hasLength = value.length !== void 0; - if (hasLength && Array.isArray(value)) { - if (value.length === 0) { - return "[]"; - } - if (maximumDepth < stack.length + 1) { - return '"[Array]"'; - } - stack.push(value); - const maximumValuesToStringify = Math.min(value.length, maximumBreadth); - let i2 = 0; - for (; i2 < maximumValuesToStringify - 1; i2++) { - const tmp2 = stringifySimple(String(i2), value[i2], stack); - res += tmp2 !== void 0 ? tmp2 : "null"; - res += ","; - } - const tmp = stringifySimple(String(i2), value[i2], stack); - res += tmp !== void 0 ? tmp : "null"; - if (value.length - 1 > maximumBreadth) { - const removedKeys = value.length - maximumBreadth - 1; - res += `,"... ${getItemCount(removedKeys)} not stringified"`; - } - stack.pop(); - return `[${res}]`; - } - let keys = Object.keys(value); - const keyLength = keys.length; - if (keyLength === 0) { - return "{}"; - } - if (maximumDepth < stack.length + 1) { - return '"[Object]"'; - } - let separator = ""; - let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth); - if (hasLength && isTypedArrayWithEntries(value)) { - res += stringifyTypedArray(value, ",", maximumBreadth); - keys = keys.slice(value.length); - maximumPropertiesToStringify -= value.length; - separator = ","; - } - if (deterministic) { - keys = sort(keys, comparator); + listenerCount(name) { + if (this._events[name] != null) { + return this._events[name].length; + } else { + return 0; + } + } + trigger(name, ...args) { + var _this = this; + return _asyncToGenerator2(function* () { + var e2, promises; + try { + if (name !== "debug") { + _this.trigger("debug", `Event triggered: ${name}`, args); } - stack.push(value); - for (let i2 = 0; i2 < maximumPropertiesToStringify; i2++) { - const key2 = keys[i2]; - const tmp = stringifySimple(key2, value[key2], stack); - if (tmp !== void 0) { - res += `${separator}${strEscape(key2)}:${tmp}`; - separator = ","; - } + if (_this._events[name] == null) { + return; } - if (keyLength > maximumBreadth) { - const removedKeys = keyLength - maximumBreadth; - res += `${separator}"...":"${getItemCount(removedKeys)} not stringified"`; + _this._events[name] = _this._events[name].filter(function(listener) { + return listener.status !== "none"; + }); + promises = _this._events[name].map( + /* @__PURE__ */ function() { + var _ref = _asyncToGenerator2(function* (listener) { + var e3, returned; + if (listener.status === "none") { + return; + } + if (listener.status === "once") { + listener.status = "none"; + } + try { + returned = typeof listener.cb === "function" ? listener.cb(...args) : void 0; + if (typeof (returned != null ? returned.then : void 0) === "function") { + return yield returned; + } else { + return returned; + } + } catch (error2) { + e3 = error2; + if (true) { + _this.trigger("error", e3); + } + return null; + } + }); + return function(_x) { + return _ref.apply(this, arguments); + }; + }() + ); + return (yield Promise.all(promises)).find(function(x3) { + return x3 != null; + }); + } catch (error2) { + e2 = error2; + if (true) { + _this.trigger("error", e2); } - stack.pop(); - return `{${res}}`; + return null; } - case "number": - return isFinite(value) ? String(value) : fail ? fail(value) : "null"; - case "boolean": - return value === true ? "true" : "false"; - case "undefined": - return void 0; - case "bigint": - if (bigint2) { - return String(value); - } - // fallthrough - default: - return fail ? fail(value) : void 0; - } + })(); } - function stringify3(value, replacer, space) { - if (arguments.length > 1) { - let spacer = ""; - if (typeof space === "number") { - spacer = " ".repeat(Math.min(space, 10)); - } else if (typeof space === "string") { - spacer = space.slice(0, 10); - } - if (replacer != null) { - if (typeof replacer === "function") { - return stringifyFnReplacer("", { "": value }, [], replacer, spacer, ""); - } - if (Array.isArray(replacer)) { - return stringifyArrayReplacer("", value, [], getUniqueReplacerSet(replacer), spacer, ""); - } + }; + module14.exports = Events2; + } +}); +var require_Queues = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Queues.js"(exports2, module14) { + "use strict"; + var DLList; + var Events2; + var Queues; + DLList = require_DLList(); + Events2 = require_Events(); + Queues = class Queues { + constructor(num_priorities) { + var i2; + this.Events = new Events2(this); + this._length = 0; + this._lists = function() { + var j, ref, results; + results = []; + for (i2 = j = 1, ref = num_priorities; 1 <= ref ? j <= ref : j >= ref; i2 = 1 <= ref ? ++j : --j) { + results.push(new DLList(() => { + return this.incr(); + }, () => { + return this.decr(); + })); } - if (spacer.length !== 0) { - return stringifyIndent("", value, [], spacer, ""); + return results; + }.call(this); + } + incr() { + if (this._length++ === 0) { + return this.Events.trigger("leftzero"); + } + } + decr() { + if (--this._length === 0) { + return this.Events.trigger("zero"); + } + } + push(job) { + return this._lists[job.options.priority].push(job); + } + queued(priority) { + if (priority != null) { + return this._lists[priority].length; + } else { + return this._length; + } + } + shiftAll(fn) { + return this._lists.forEach(function(list) { + return list.forEachShift(fn); + }); + } + getFirst(arr = this._lists) { + var j, len, list; + for (j = 0, len = arr.length; j < len; j++) { + list = arr[j]; + if (list.length > 0) { + return list; } } - return stringifySimple("", value, []); + return []; } - return stringify3; - } + shiftLastFrom(priority) { + return this.getFirst(this._lists.slice(priority).reverse()).shift(); + } + }; + module14.exports = Queues; } }); -var require_multistream = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/multistream.js"(exports2, module14) { +var require_BottleneckError = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/BottleneckError.js"(exports2, module14) { + "use strict"; + var BottleneckError; + BottleneckError = class BottleneckError extends Error { + }; + module14.exports = BottleneckError; + } +}); +var require_Job = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Job.js"(exports2, module14) { "use strict"; - var metadata = Symbol.for("pino.metadata"); - var { DEFAULT_LEVELS } = require_constants(); - var DEFAULT_INFO_LEVEL = DEFAULT_LEVELS.info; - function multistream(streamsArray, opts) { - let counter = 0; - streamsArray = streamsArray || []; - opts = opts || { dedupe: false }; - const streamLevels = Object.create(DEFAULT_LEVELS); - streamLevels.silent = Infinity; - if (opts.levels && typeof opts.levels === "object") { - Object.keys(opts.levels).forEach((i2) => { - streamLevels[i2] = opts.levels[i2]; - }); + function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; } - const res = { - write, - add, - flushSync, - end, - minLevel: 0, - streams: [], - clone: clone2, - [metadata]: true, - streamLevels - }; - if (Array.isArray(streamsArray)) { - streamsArray.forEach(add, res); + if (info.done) { + resolve82(value); } else { - add.call(res, streamsArray); + Promise.resolve(value).then(_next, _throw); } - streamsArray = null; - return res; - function write(data) { - let dest; - const level = this.lastLevel; - const { streams } = this; - let recordedLevel = 0; - let stream; - for (let i2 = initLoopVar(streams.length, opts.dedupe); checkLoopVar(i2, streams.length, opts.dedupe); i2 = adjustLoopVar(i2, opts.dedupe)) { - dest = streams[i2]; - if (dest.level <= level) { - if (recordedLevel !== 0 && recordedLevel !== dest.level) { - break; - } - stream = dest.stream; - if (stream[metadata]) { - const { lastTime, lastMsg, lastObj, lastLogger } = this; - stream.lastLevel = level; - stream.lastTime = lastTime; - stream.lastMsg = lastMsg; - stream.lastObj = lastObj; - stream.lastLogger = lastLogger; - } - stream.write(data); - if (opts.dedupe) { - recordedLevel = dest.level; - } - } else if (!opts.dedupe) { - break; + } + function _asyncToGenerator2(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); } + _next(void 0); + }); + }; + } + var BottleneckError; + var DEFAULT_PRIORITY; + var Job; + var NUM_PRIORITIES; + var parser3; + NUM_PRIORITIES = 10; + DEFAULT_PRIORITY = 5; + parser3 = require_parser2(); + BottleneckError = require_BottleneckError(); + Job = class Job { + constructor(task, args, options2, jobDefaults, rejectOnDrop, Events2, _states, Promise2) { + this.task = task; + this.args = args; + this.rejectOnDrop = rejectOnDrop; + this.Events = Events2; + this._states = _states; + this.Promise = Promise2; + this.options = parser3.load(options2, jobDefaults); + this.options.priority = this._sanitizePriority(this.options.priority); + if (this.options.id === jobDefaults.id) { + this.options.id = `${this.options.id}-${this._randomIndex()}`; } + this.promise = new this.Promise((_resolve, _reject) => { + this._resolve = _resolve; + this._reject = _reject; + }); + this.retryCount = 0; } - function flushSync() { - for (const { stream } of this.streams) { - if (typeof stream.flushSync === "function") { - stream.flushSync(); - } + _sanitizePriority(priority) { + var sProperty; + sProperty = ~~priority !== priority ? DEFAULT_PRIORITY : priority; + if (sProperty < 0) { + return 0; + } else if (sProperty > NUM_PRIORITIES - 1) { + return NUM_PRIORITIES - 1; + } else { + return sProperty; } } - function add(dest) { - if (!dest) { - return res; + _randomIndex() { + return Math.random().toString(36).slice(2); + } + doDrop({ + error: error2, + message = "This job has been dropped by Bottleneck" + } = {}) { + if (this._states.remove(this.options.id)) { + if (this.rejectOnDrop) { + this._reject(error2 != null ? error2 : new BottleneckError(message)); + } + this.Events.trigger("dropped", { + args: this.args, + options: this.options, + task: this.task, + promise: this.promise + }); + return true; + } else { + return false; } - const isStream = typeof dest.write === "function" || dest.stream; - const stream_ = dest.write ? dest : dest.stream; - if (!isStream) { - throw Error("stream object needs to implement either StreamEntry or DestinationStream interface"); + } + _assertStatus(expected) { + var status; + status = this._states.jobStatus(this.options.id); + if (!(status === expected || expected === "DONE" && status === null)) { + throw new BottleneckError(`Invalid job status ${status}, expected ${expected}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`); } - const { streams, streamLevels: streamLevels2 } = this; - let level; - if (typeof dest.levelVal === "number") { - level = dest.levelVal; - } else if (typeof dest.level === "string") { - level = streamLevels2[dest.level]; - } else if (typeof dest.level === "number") { - level = dest.level; + } + doReceive() { + this._states.start(this.options.id); + return this.Events.trigger("received", { + args: this.args, + options: this.options + }); + } + doQueue(reachedHWM, blocked) { + this._assertStatus("RECEIVED"); + this._states.next(this.options.id); + return this.Events.trigger("queued", { + args: this.args, + options: this.options, + reachedHWM, + blocked + }); + } + doRun() { + if (this.retryCount === 0) { + this._assertStatus("QUEUED"); + this._states.next(this.options.id); } else { - level = DEFAULT_INFO_LEVEL; + this._assertStatus("EXECUTING"); } - const dest_ = { - stream: stream_, - level, - levelVal: void 0, - id: counter++ - }; - streams.unshift(dest_); - streams.sort(compareByLevel); - this.minLevel = streams[0].level; - return res; + return this.Events.trigger("scheduled", { + args: this.args, + options: this.options + }); } - function end() { - for (const { stream } of this.streams) { - if (typeof stream.flushSync === "function") { - stream.flushSync(); + doExecute(chained, clearGlobalState, run2, free) { + var _this = this; + return _asyncToGenerator2(function* () { + var error2, eventInfo, passed; + if (_this.retryCount === 0) { + _this._assertStatus("RUNNING"); + _this._states.next(_this.options.id); + } else { + _this._assertStatus("EXECUTING"); } - stream.end(); - } - } - function clone2(level) { - const streams = new Array(this.streams.length); - for (let i2 = 0; i2 < streams.length; i2++) { - streams[i2] = { - level, - stream: this.streams[i2].stream + eventInfo = { + args: _this.args, + options: _this.options, + retryCount: _this.retryCount }; + _this.Events.trigger("executing", eventInfo); + try { + passed = yield chained != null ? chained.schedule(_this.options, _this.task, ..._this.args) : _this.task(..._this.args); + if (clearGlobalState()) { + _this.doDone(eventInfo); + yield free(_this.options, eventInfo); + _this._assertStatus("DONE"); + return _this._resolve(passed); + } + } catch (error1) { + error2 = error1; + return _this._onFailure(error2, eventInfo, clearGlobalState, run2, free); + } + })(); + } + doExpire(clearGlobalState, run2, free) { + var error2, eventInfo; + if (this._states.jobStatus(this.options.id === "RUNNING")) { + this._states.next(this.options.id); } - return { - write, - add, - minLevel: level, - streams, - clone: clone2, - flushSync, - [metadata]: true + this._assertStatus("EXECUTING"); + eventInfo = { + args: this.args, + options: this.options, + retryCount: this.retryCount }; + error2 = new BottleneckError(`This job timed out after ${this.options.expiration} ms.`); + return this._onFailure(error2, eventInfo, clearGlobalState, run2, free); } - } - function compareByLevel(a, b) { - return a.level - b.level; - } - function initLoopVar(length2, dedupe) { - return dedupe ? length2 - 1 : 0; - } - function adjustLoopVar(i2, dedupe) { - return dedupe ? i2 - 1 : i2 + 1; - } - function checkLoopVar(i2, length2, dedupe) { - return dedupe ? i2 >= 0 : i2 < length2; - } - module14.exports = multistream; - } -}); -var require_pino = __commonJS({ - "node_modules/.deno/pino@8.19.0/node_modules/pino/pino.js"(exports2, module14) { - "use strict"; - var os = __require2("os"); - var stdSerializers = require_pino_std_serializers(); - var caller = require_caller(); - var redaction = require_redaction(); - var time3 = require_time(); - var proto3 = require_proto(); - var symbols2 = require_symbols2(); - var { configure } = require_safe_stable_stringify(); - var { assertDefaultLevelFound, mappings, genLsCache, genLevelComparison, assertLevelComparison } = require_levels(); - var { DEFAULT_LEVELS, SORTING_ORDER } = require_constants(); - var { - createArgsNormalizer, - asChindings, - buildSafeSonicBoom, - buildFormatters, - stringify: stringify2, - normalizeDestFileDescriptor, - noop - } = require_tools(); - var { version: version3 } = require_meta(); - var { - chindingsSym, - redactFmtSym, - serializersSym, - timeSym, - timeSliceIndexSym, - streamSym, - stringifySym, - stringifySafeSym, - stringifiersSym, - setLevelSym, - endSym, - formatOptsSym, - messageKeySym, - errorKeySym, - nestedKeySym, - mixinSym, - levelCompSym, - useOnlyCustomLevelsSym, - formattersSym, - hooksSym, - nestedKeyStrSym, - mixinMergeStrategySym, - msgPrefixSym - } = symbols2; - var { epochTime, nullTime } = time3; - var { pid } = process; - var hostname2 = os.hostname(); - var defaultErrorSerializer = stdSerializers.err; - var defaultOptions4 = { - level: "info", - levelComparison: SORTING_ORDER.ASC, - levels: DEFAULT_LEVELS, - messageKey: "msg", - errorKey: "err", - nestedKey: null, - enabled: true, - base: { pid, hostname: hostname2 }, - serializers: Object.assign(/* @__PURE__ */ Object.create(null), { - err: defaultErrorSerializer - }), - formatters: Object.assign(/* @__PURE__ */ Object.create(null), { - bindings(bindings) { - return bindings; - }, - level(label, number3) { - return { level: number3 }; - } - }), - hooks: { - logMethod: void 0 - }, - timestamp: epochTime, - name: void 0, - redact: null, - customLevels: null, - useOnlyCustomLevels: false, - depthLimit: 5, - edgeLimit: 100 - }; - var normalize32 = createArgsNormalizer(defaultOptions4); - var serializers = Object.assign(/* @__PURE__ */ Object.create(null), stdSerializers); - function pino2(...args) { - const instance = {}; - const { opts, stream } = normalize32(instance, caller(), ...args); - const { - redact, - crlf, - serializers: serializers2, - timestamp, - messageKey, - errorKey, - nestedKey, - base: base2, - name, - level, - customLevels, - levelComparison, - mixin: mixin3, - mixinMergeStrategy, - useOnlyCustomLevels, - formatters, - hooks, - depthLimit, - edgeLimit, - onChild, - msgPrefix - } = opts; - const stringifySafe = configure({ - maximumDepth: depthLimit, - maximumBreadth: edgeLimit - }); - const allFormatters = buildFormatters( - formatters.level, - formatters.bindings, - formatters.log - ); - const stringifyFn = stringify2.bind({ - [stringifySafeSym]: stringifySafe - }); - const stringifiers = redact ? redaction(redact, stringifyFn) : {}; - const formatOpts = redact ? { stringify: stringifiers[redactFmtSym] } : { stringify: stringifyFn }; - const end = "}" + (crlf ? "\r\n" : "\n"); - const coreChindings = asChindings.bind(null, { - [chindingsSym]: "", - [serializersSym]: serializers2, - [stringifiersSym]: stringifiers, - [stringifySym]: stringify2, - [stringifySafeSym]: stringifySafe, - [formattersSym]: allFormatters - }); - let chindings = ""; - if (base2 !== null) { - if (name === void 0) { - chindings = coreChindings(base2); - } else { - chindings = coreChindings(Object.assign({}, base2, { name })); - } + _onFailure(error2, eventInfo, clearGlobalState, run2, free) { + var _this2 = this; + return _asyncToGenerator2(function* () { + var retry, retryAfter; + if (clearGlobalState()) { + retry = yield _this2.Events.trigger("failed", error2, eventInfo); + if (retry != null) { + retryAfter = ~~retry; + _this2.Events.trigger("retry", `Retrying ${_this2.options.id} after ${retryAfter} ms`, eventInfo); + _this2.retryCount++; + return run2(retryAfter); + } else { + _this2.doDone(eventInfo); + yield free(_this2.options, eventInfo); + _this2._assertStatus("DONE"); + return _this2._reject(error2); + } + } + })(); } - const time4 = timestamp instanceof Function ? timestamp : timestamp ? epochTime : nullTime; - const timeSliceIndex = time4().indexOf(":") + 1; - if (useOnlyCustomLevels && !customLevels) throw Error("customLevels is required if useOnlyCustomLevels is set true"); - if (mixin3 && typeof mixin3 !== "function") throw Error(`Unknown mixin type "${typeof mixin3}" - expected "function"`); - if (msgPrefix && typeof msgPrefix !== "string") throw Error(`Unknown msgPrefix type "${typeof msgPrefix}" - expected "string"`); - assertDefaultLevelFound(level, customLevels, useOnlyCustomLevels); - const levels = mappings(customLevels, useOnlyCustomLevels); - assertLevelComparison(levelComparison); - const levelCompFunc = genLevelComparison(levelComparison); - Object.assign(instance, { - levels, - [levelCompSym]: levelCompFunc, - [useOnlyCustomLevelsSym]: useOnlyCustomLevels, - [streamSym]: stream, - [timeSym]: time4, - [timeSliceIndexSym]: timeSliceIndex, - [stringifySym]: stringify2, - [stringifySafeSym]: stringifySafe, - [stringifiersSym]: stringifiers, - [endSym]: end, - [formatOptsSym]: formatOpts, - [messageKeySym]: messageKey, - [errorKeySym]: errorKey, - [nestedKeySym]: nestedKey, - // protect against injection - [nestedKeyStrSym]: nestedKey ? `,${JSON.stringify(nestedKey)}:{` : "", - [serializersSym]: serializers2, - [mixinSym]: mixin3, - [mixinMergeStrategySym]: mixinMergeStrategy, - [chindingsSym]: chindings, - [formattersSym]: allFormatters, - [hooksSym]: hooks, - silent: noop, - onChild, - [msgPrefixSym]: msgPrefix - }); - Object.setPrototypeOf(instance, proto3()); - genLsCache(instance); - instance[setLevelSym](level); - return instance; - } - module14.exports = pino2; - module14.exports.destination = (dest = process.stdout.fd) => { - if (typeof dest === "object") { - dest.dest = normalizeDestFileDescriptor(dest.dest || process.stdout.fd); - return buildSafeSonicBoom(dest); - } else { - return buildSafeSonicBoom({ dest: normalizeDestFileDescriptor(dest), minLength: 0 }); + doDone(eventInfo) { + this._assertStatus("EXECUTING"); + this._states.next(this.options.id); + return this.Events.trigger("done", eventInfo); } }; - module14.exports.transport = require_transport(); - module14.exports.multistream = require_multistream(); - module14.exports.levels = mappings(); - module14.exports.stdSerializers = serializers; - module14.exports.stdTimeFunctions = Object.assign({}, time3); - module14.exports.symbols = symbols2; - module14.exports.version = version3; - module14.exports.default = pino2; - module14.exports.pino = pino2; + module14.exports = Job; } }); -function logMethod(args, method) { - const stringIdx = typeof args[0] === "string" ? 0 : 1; - if (args.length > 1) { - for (let i2 = stringIdx + 1; i2 < args.length; ++i2) { - args[stringIdx] += typeof args[i2] === "string" ? " %s" : " %o"; +var require_LocalDatastore = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/LocalDatastore.js"(exports2, module14) { + "use strict"; + function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; + } + if (info.done) { + resolve82(value); + } else { + Promise.resolve(value).then(_next, _throw); + } } - } - method.apply(this, args); -} -var import_npm_pino; -var prettyPrint; -var logger; -var logLevel; -var logger_default; -var init_logger = __esm({ - "src/serve/logger.ts"() { - "use strict"; - import_npm_pino = __toESM(require_pino()); - prettyPrint = process6.env.NODE_ENV === "development" || process6.env.CI || process6.env.CYPRESS_RECORD_KEY || process6.env.PRETTY; - if (prettyPrint) { - try { - logger = (0, import_npm_pino.default)({ - hooks: { logMethod }, - transport: { - target: "pino-pretty", - options: { - colorize: true - } + function _asyncToGenerator2(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); } + _next(void 0); }); - } catch (e2) { - console.warn("pino-pretty transport unavailable, using basic logging", e2); - logger = (0, import_npm_pino.default)({ hooks: { logMethod } }); - } - } else { - logger = (0, import_npm_pino.default)({ hooks: { logMethod } }); + }; } - logLevel = process6.env.LOG_LEVEL || (prettyPrint ? "debug" : "info"); - if (Object.keys(logger.levels.values).includes(logLevel)) { - logger.level = logLevel; - } else { - logger.warn(`Unknown log level: ${logLevel}`); - } - console.debug = logger.debug.bind(logger); - console.info = logger.info.bind(logger); - console.log = logger.info.bind(logger); - console.warn = logger.warn.bind(logger); - console.error = logger.error.bind(logger); - logger_default = logger; - } -}); -var timer; -var coerceToError; -var defaultOptions2; -var tag; -var PersistentAction; -var persistent_actions_default; -var init_persistent_actions = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/persistent-actions.mjs"() { - init_esm4(); - init_esm(); - init_events(); - timer = Symbol("timer"); - coerceToError = (arg) => { - if (arg && arg instanceof Error) - return arg; - console.warn(tag, "Please use Error objects when throwing or rejecting"); - return new Error((typeof arg === "string" ? arg : JSON.stringify(arg)) ?? "undefined"); - }; - defaultOptions2 = { - maxAttempts: Number.POSITIVE_INFINITY, - retrySeconds: 30 - }; - tag = "[chelonia.persistentActions]"; - PersistentAction = class { - id; - invocation; - options; - status; - [timer]; - constructor(invocation, options2 = {}) { - this.id = crypto.randomUUID(); - this.invocation = invocation; - this.options = { ...defaultOptions2, ...options2 }; - this.status = { - attempting: false, - failedAttemptsSoFar: 0, - lastError: "", - nextRetry: "", - resolved: false - }; + var BottleneckError; + var LocalDatastore; + var parser3; + parser3 = require_parser2(); + BottleneckError = require_BottleneckError(); + LocalDatastore = class LocalDatastore { + constructor(instance, storeOptions, storeInstanceOptions) { + this.instance = instance; + this.storeOptions = storeOptions; + this.clientId = this.instance._randomIndex(); + parser3.load(storeInstanceOptions, storeInstanceOptions, this); + this._nextRequest = this._lastReservoirRefresh = this._lastReservoirIncrease = Date.now(); + this._running = 0; + this._done = 0; + this._unblockTime = 0; + this.ready = this.Promise.resolve(); + this.clients = {}; + this._startHeartbeat(); } - async attempt() { - if (this.status.attempting || this.status.resolved) - return; - if (await this.trySBP(this.options.skipCondition)) - this.cancel(); - if (this.status.resolved) - return; - try { - this.status.attempting = true; - const result = await esm_default(...this.invocation); - this.status.attempting = false; - this.handleSuccess(result); - } catch (error2) { - this.status.attempting = false; - await this.handleError(coerceToError(error2)); - } - } - cancel() { - if (this[timer]) - clearTimeout(this[timer]); - this.status.nextRetry = ""; - this.status.resolved = true; - } - async handleError(error2) { - const { id, options: options2, status } = this; - status.failedAttemptsSoFar++; - status.lastError = error2.message; - const anyAttemptLeft = options2.maxAttempts > status.failedAttemptsSoFar; - if (!anyAttemptLeft) - status.resolved = true; - status.nextRetry = anyAttemptLeft && !status.resolved ? new Date(Date.now() + options2.retrySeconds * 1e3).toISOString() : ""; - esm_default("okTurtles.events/emit", PERSISTENT_ACTION_FAILURE, { error: error2, id }); - await this.trySBP(options2.errorInvocation); - if (!anyAttemptLeft) { - esm_default("okTurtles.events/emit", PERSISTENT_ACTION_TOTAL_FAILURE, { error: error2, id }); - await this.trySBP(options2.totalFailureInvocation); - } - if (status.nextRetry) { - this[timer] = setTimeout(() => { - this.attempt().catch((e2) => { - console.error("Error attempting persistent action", id, e2); - }); - }, this.options.retrySeconds * 1e3); + _startHeartbeat() { + var base2; + if (this.heartbeat == null && (this.storeOptions.reservoirRefreshInterval != null && this.storeOptions.reservoirRefreshAmount != null || this.storeOptions.reservoirIncreaseInterval != null && this.storeOptions.reservoirIncreaseAmount != null)) { + return typeof (base2 = this.heartbeat = setInterval(() => { + var amount, incr, maximum, now, reservoir; + now = Date.now(); + if (this.storeOptions.reservoirRefreshInterval != null && now >= this._lastReservoirRefresh + this.storeOptions.reservoirRefreshInterval) { + this._lastReservoirRefresh = now; + this.storeOptions.reservoir = this.storeOptions.reservoirRefreshAmount; + this.instance._drainAll(this.computeCapacity()); + } + if (this.storeOptions.reservoirIncreaseInterval != null && now >= this._lastReservoirIncrease + this.storeOptions.reservoirIncreaseInterval) { + var _this$storeOptions = this.storeOptions; + amount = _this$storeOptions.reservoirIncreaseAmount; + maximum = _this$storeOptions.reservoirIncreaseMaximum; + reservoir = _this$storeOptions.reservoir; + this._lastReservoirIncrease = now; + incr = maximum != null ? Math.min(amount, maximum - reservoir) : amount; + if (incr > 0) { + this.storeOptions.reservoir += incr; + return this.instance._drainAll(this.computeCapacity()); + } + } + }, this.heartbeatInterval)).unref === "function" ? base2.unref() : void 0; + } else { + return clearInterval(this.heartbeat); } } - handleSuccess(result) { - const { id, status } = this; - status.lastError = ""; - status.nextRetry = ""; - status.resolved = true; - esm_default("okTurtles.events/emit", PERSISTENT_ACTION_SUCCESS, { id, result }); + __publish__(message) { + var _this = this; + return _asyncToGenerator2(function* () { + yield _this.yieldLoop(); + return _this.instance.Events.trigger("message", message.toString()); + })(); } - async trySBP(invocation) { - try { - return invocation ? await esm_default(...invocation) : void 0; - } catch (error2) { - console.error(tag, coerceToError(error2).message); + __disconnect__(flush) { + var _this2 = this; + return _asyncToGenerator2(function* () { + yield _this2.yieldLoop(); + clearInterval(_this2.heartbeat); + return _this2.Promise.resolve(); + })(); + } + yieldLoop(t = 0) { + return new this.Promise(function(resolve82, reject) { + return setTimeout(resolve82, t); + }); + } + computePenalty() { + var ref; + return (ref = this.storeOptions.penalty) != null ? ref : 15 * this.storeOptions.minTime || 5e3; + } + __updateSettings__(options2) { + var _this3 = this; + return _asyncToGenerator2(function* () { + yield _this3.yieldLoop(); + parser3.overwrite(options2, options2, _this3.storeOptions); + _this3._startHeartbeat(); + _this3.instance._drainAll(_this3.computeCapacity()); + return true; + })(); + } + __running__() { + var _this4 = this; + return _asyncToGenerator2(function* () { + yield _this4.yieldLoop(); + return _this4._running; + })(); + } + __queued__() { + var _this5 = this; + return _asyncToGenerator2(function* () { + yield _this5.yieldLoop(); + return _this5.instance.queued(); + })(); + } + __done__() { + var _this6 = this; + return _asyncToGenerator2(function* () { + yield _this6.yieldLoop(); + return _this6._done; + })(); + } + __groupCheck__(time3) { + var _this7 = this; + return _asyncToGenerator2(function* () { + yield _this7.yieldLoop(); + return _this7._nextRequest + _this7.timeout < time3; + })(); + } + computeCapacity() { + var maxConcurrent, reservoir; + var _this$storeOptions2 = this.storeOptions; + maxConcurrent = _this$storeOptions2.maxConcurrent; + reservoir = _this$storeOptions2.reservoir; + if (maxConcurrent != null && reservoir != null) { + return Math.min(maxConcurrent - this._running, reservoir); + } else if (maxConcurrent != null) { + return maxConcurrent - this._running; + } else if (reservoir != null) { + return reservoir; + } else { + return null; } } + conditionsCheck(weight) { + var capacity; + capacity = this.computeCapacity(); + return capacity == null || weight <= capacity; + } + __incrementReservoir__(incr) { + var _this8 = this; + return _asyncToGenerator2(function* () { + var reservoir; + yield _this8.yieldLoop(); + reservoir = _this8.storeOptions.reservoir += incr; + _this8.instance._drainAll(_this8.computeCapacity()); + return reservoir; + })(); + } + __currentReservoir__() { + var _this9 = this; + return _asyncToGenerator2(function* () { + yield _this9.yieldLoop(); + return _this9.storeOptions.reservoir; + })(); + } + isBlocked(now) { + return this._unblockTime >= now; + } + check(weight, now) { + return this.conditionsCheck(weight) && this._nextRequest - now <= 0; + } + __check__(weight) { + var _this10 = this; + return _asyncToGenerator2(function* () { + var now; + yield _this10.yieldLoop(); + now = Date.now(); + return _this10.check(weight, now); + })(); + } + __register__(index, weight, expiration) { + var _this11 = this; + return _asyncToGenerator2(function* () { + var now, wait; + yield _this11.yieldLoop(); + now = Date.now(); + if (_this11.conditionsCheck(weight)) { + _this11._running += weight; + if (_this11.storeOptions.reservoir != null) { + _this11.storeOptions.reservoir -= weight; + } + wait = Math.max(_this11._nextRequest - now, 0); + _this11._nextRequest = now + wait + _this11.storeOptions.minTime; + return { + success: true, + wait, + reservoir: _this11.storeOptions.reservoir + }; + } else { + return { + success: false + }; + } + })(); + } + strategyIsBlock() { + return this.storeOptions.strategy === 3; + } + __submit__(queueLength, weight) { + var _this12 = this; + return _asyncToGenerator2(function* () { + var blocked, now, reachedHWM; + yield _this12.yieldLoop(); + if (_this12.storeOptions.maxConcurrent != null && weight > _this12.storeOptions.maxConcurrent) { + throw new BottleneckError(`Impossible to add a job having a weight of ${weight} to a limiter having a maxConcurrent setting of ${_this12.storeOptions.maxConcurrent}`); + } + now = Date.now(); + reachedHWM = _this12.storeOptions.highWater != null && queueLength === _this12.storeOptions.highWater && !_this12.check(weight, now); + blocked = _this12.strategyIsBlock() && (reachedHWM || _this12.isBlocked(now)); + if (blocked) { + _this12._unblockTime = now + _this12.computePenalty(); + _this12._nextRequest = _this12._unblockTime + _this12.storeOptions.minTime; + _this12.instance._dropAllQueued(); + } + return { + reachedHWM, + blocked, + strategy: _this12.storeOptions.strategy + }; + })(); + } + __free__(index, weight) { + var _this13 = this; + return _asyncToGenerator2(function* () { + yield _this13.yieldLoop(); + _this13._running -= weight; + _this13._done += weight; + _this13.instance._drainAll(_this13.computeCapacity()); + return { + running: _this13._running + }; + })(); + } }; - persistent_actions_default = esm_default("sbp/selectors/register", { - "chelonia.persistentActions/_init"() { - this.actionsByID = /* @__PURE__ */ Object.create(null); - this.checkDatabaseKey = () => { - if (!this.databaseKey) - throw new TypeError(`${tag} No database key configured`); - }; - esm_default("okTurtles.events/on", PERSISTENT_ACTION_SUCCESS, ({ id }) => { - esm_default("chelonia.persistentActions/cancel", id); - }); - esm_default("okTurtles.events/on", PERSISTENT_ACTION_TOTAL_FAILURE, ({ id }) => { - esm_default("chelonia.persistentActions/cancel", id); - }); + module14.exports = LocalDatastore; + } +}); +var require_lua = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/lua.json"(exports2, module14) { + module14.exports = { + "blacklist_client.lua": "local blacklist = ARGV[num_static_argv + 1]\n\nif redis.call('zscore', client_last_seen_key, blacklist) then\n redis.call('zadd', client_last_seen_key, 0, blacklist)\nend\n\n\nreturn {}\n", + "check.lua": "local weight = tonumber(ARGV[num_static_argv + 1])\n\nlocal capacity = process_tick(now, false)['capacity']\nlocal nextRequest = tonumber(redis.call('hget', settings_key, 'nextRequest'))\n\nreturn conditions_check(capacity, weight) and nextRequest - now <= 0\n", + "conditions_check.lua": "local conditions_check = function (capacity, weight)\n return capacity == nil or weight <= capacity\nend\n", + "current_reservoir.lua": "return process_tick(now, false)['reservoir']\n", + "done.lua": "process_tick(now, false)\n\nreturn tonumber(redis.call('hget', settings_key, 'done'))\n", + "free.lua": "local index = ARGV[num_static_argv + 1]\n\nredis.call('zadd', job_expirations_key, 0, index)\n\nreturn process_tick(now, false)['running']\n", + "get_time.lua": "redis.replicate_commands()\n\nlocal get_time = function ()\n local time = redis.call('time')\n\n return tonumber(time[1]..string.sub(time[2], 1, 3))\nend\n", + "group_check.lua": "return not (redis.call('exists', settings_key) == 1)\n", + "heartbeat.lua": "process_tick(now, true)\n", + "increment_reservoir.lua": "local incr = tonumber(ARGV[num_static_argv + 1])\n\nredis.call('hincrby', settings_key, 'reservoir', incr)\n\nlocal reservoir = process_tick(now, true)['reservoir']\n\nlocal groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout'))\nrefresh_expiration(0, 0, groupTimeout)\n\nreturn reservoir\n", + "init.lua": `local clear = tonumber(ARGV[num_static_argv + 1]) +local limiter_version = ARGV[num_static_argv + 2] +local num_local_argv = num_static_argv + 2 + +if clear == 1 then + redis.call('del', unpack(KEYS)) +end + +if redis.call('exists', settings_key) == 0 then + -- Create + local args = {'hmset', settings_key} + + for i = num_local_argv + 1, #ARGV do + table.insert(args, ARGV[i]) + end + + redis.call(unpack(args)) + redis.call('hmset', settings_key, + 'nextRequest', now, + 'lastReservoirRefresh', now, + 'lastReservoirIncrease', now, + 'running', 0, + 'done', 0, + 'unblockTime', 0, + 'capacityPriorityCounter', 0 + ) + +else + -- Apply migrations + local settings = redis.call('hmget', settings_key, + 'id', + 'version' + ) + local id = settings[1] + local current_version = settings[2] + + if current_version ~= limiter_version then + local version_digits = {} + for k, v in string.gmatch(current_version, "([^.]+)") do + table.insert(version_digits, tonumber(k)) + end + + -- 2.10.0 + if version_digits[2] < 10 then + redis.call('hsetnx', settings_key, 'reservoirRefreshInterval', '') + redis.call('hsetnx', settings_key, 'reservoirRefreshAmount', '') + redis.call('hsetnx', settings_key, 'lastReservoirRefresh', '') + redis.call('hsetnx', settings_key, 'done', 0) + redis.call('hset', settings_key, 'version', '2.10.0') + end + + -- 2.11.1 + if version_digits[2] < 11 or (version_digits[2] == 11 and version_digits[3] < 1) then + if redis.call('hstrlen', settings_key, 'lastReservoirRefresh') == 0 then + redis.call('hmset', settings_key, + 'lastReservoirRefresh', now, + 'version', '2.11.1' + ) + end + end + + -- 2.14.0 + if version_digits[2] < 14 then + local old_running_key = 'b_'..id..'_running' + local old_executing_key = 'b_'..id..'_executing' + + if redis.call('exists', old_running_key) == 1 then + redis.call('rename', old_running_key, job_weights_key) + end + if redis.call('exists', old_executing_key) == 1 then + redis.call('rename', old_executing_key, job_expirations_key) + end + redis.call('hset', settings_key, 'version', '2.14.0') + end + + -- 2.15.2 + if version_digits[2] < 15 or (version_digits[2] == 15 and version_digits[3] < 2) then + redis.call('hsetnx', settings_key, 'capacityPriorityCounter', 0) + redis.call('hset', settings_key, 'version', '2.15.2') + end + + -- 2.17.0 + if version_digits[2] < 17 then + redis.call('hsetnx', settings_key, 'clientTimeout', 10000) + redis.call('hset', settings_key, 'version', '2.17.0') + end + + -- 2.18.0 + if version_digits[2] < 18 then + redis.call('hsetnx', settings_key, 'reservoirIncreaseInterval', '') + redis.call('hsetnx', settings_key, 'reservoirIncreaseAmount', '') + redis.call('hsetnx', settings_key, 'reservoirIncreaseMaximum', '') + redis.call('hsetnx', settings_key, 'lastReservoirIncrease', now) + redis.call('hset', settings_key, 'version', '2.18.0') + end + + end + + process_tick(now, false) +end + +local groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout')) +refresh_expiration(0, 0, groupTimeout) + +return {} +`, + "process_tick.lua": "local process_tick = function (now, always_publish)\n\n local compute_capacity = function (maxConcurrent, running, reservoir)\n if maxConcurrent ~= nil and reservoir ~= nil then\n return math.min((maxConcurrent - running), reservoir)\n elseif maxConcurrent ~= nil then\n return maxConcurrent - running\n elseif reservoir ~= nil then\n return reservoir\n else\n return nil\n end\n end\n\n local settings = redis.call('hmget', settings_key,\n 'id',\n 'maxConcurrent',\n 'running',\n 'reservoir',\n 'reservoirRefreshInterval',\n 'reservoirRefreshAmount',\n 'lastReservoirRefresh',\n 'reservoirIncreaseInterval',\n 'reservoirIncreaseAmount',\n 'reservoirIncreaseMaximum',\n 'lastReservoirIncrease',\n 'capacityPriorityCounter',\n 'clientTimeout'\n )\n local id = settings[1]\n local maxConcurrent = tonumber(settings[2])\n local running = tonumber(settings[3])\n local reservoir = tonumber(settings[4])\n local reservoirRefreshInterval = tonumber(settings[5])\n local reservoirRefreshAmount = tonumber(settings[6])\n local lastReservoirRefresh = tonumber(settings[7])\n local reservoirIncreaseInterval = tonumber(settings[8])\n local reservoirIncreaseAmount = tonumber(settings[9])\n local reservoirIncreaseMaximum = tonumber(settings[10])\n local lastReservoirIncrease = tonumber(settings[11])\n local capacityPriorityCounter = tonumber(settings[12])\n local clientTimeout = tonumber(settings[13])\n\n local initial_capacity = compute_capacity(maxConcurrent, running, reservoir)\n\n --\n -- Process 'running' changes\n --\n local expired = redis.call('zrangebyscore', job_expirations_key, '-inf', '('..now)\n\n if #expired > 0 then\n redis.call('zremrangebyscore', job_expirations_key, '-inf', '('..now)\n\n local flush_batch = function (batch, acc)\n local weights = redis.call('hmget', job_weights_key, unpack(batch))\n redis.call('hdel', job_weights_key, unpack(batch))\n local clients = redis.call('hmget', job_clients_key, unpack(batch))\n redis.call('hdel', job_clients_key, unpack(batch))\n\n -- Calculate sum of removed weights\n for i = 1, #weights do\n acc['total'] = acc['total'] + (tonumber(weights[i]) or 0)\n end\n\n -- Calculate sum of removed weights by client\n local client_weights = {}\n for i = 1, #clients do\n local removed = tonumber(weights[i]) or 0\n if removed > 0 then\n acc['client_weights'][clients[i]] = (acc['client_weights'][clients[i]] or 0) + removed\n end\n end\n end\n\n local acc = {\n ['total'] = 0,\n ['client_weights'] = {}\n }\n local batch_size = 1000\n\n -- Compute changes to Zsets and apply changes to Hashes\n for i = 1, #expired, batch_size do\n local batch = {}\n for j = i, math.min(i + batch_size - 1, #expired) do\n table.insert(batch, expired[j])\n end\n\n flush_batch(batch, acc)\n end\n\n -- Apply changes to Zsets\n if acc['total'] > 0 then\n redis.call('hincrby', settings_key, 'done', acc['total'])\n running = tonumber(redis.call('hincrby', settings_key, 'running', -acc['total']))\n end\n\n for client, weight in pairs(acc['client_weights']) do\n redis.call('zincrby', client_running_key, -weight, client)\n end\n end\n\n --\n -- Process 'reservoir' changes\n --\n local reservoirRefreshActive = reservoirRefreshInterval ~= nil and reservoirRefreshAmount ~= nil\n if reservoirRefreshActive and now >= lastReservoirRefresh + reservoirRefreshInterval then\n reservoir = reservoirRefreshAmount\n redis.call('hmset', settings_key,\n 'reservoir', reservoir,\n 'lastReservoirRefresh', now\n )\n end\n\n local reservoirIncreaseActive = reservoirIncreaseInterval ~= nil and reservoirIncreaseAmount ~= nil\n if reservoirIncreaseActive and now >= lastReservoirIncrease + reservoirIncreaseInterval then\n local num_intervals = math.floor((now - lastReservoirIncrease) / reservoirIncreaseInterval)\n local incr = reservoirIncreaseAmount * num_intervals\n if reservoirIncreaseMaximum ~= nil then\n incr = math.min(incr, reservoirIncreaseMaximum - (reservoir or 0))\n end\n if incr > 0 then\n reservoir = (reservoir or 0) + incr\n end\n redis.call('hmset', settings_key,\n 'reservoir', reservoir,\n 'lastReservoirIncrease', lastReservoirIncrease + (num_intervals * reservoirIncreaseInterval)\n )\n end\n\n --\n -- Clear unresponsive clients\n --\n local unresponsive = redis.call('zrangebyscore', client_last_seen_key, '-inf', (now - clientTimeout))\n local unresponsive_lookup = {}\n local terminated_clients = {}\n for i = 1, #unresponsive do\n unresponsive_lookup[unresponsive[i]] = true\n if tonumber(redis.call('zscore', client_running_key, unresponsive[i])) == 0 then\n table.insert(terminated_clients, unresponsive[i])\n end\n end\n if #terminated_clients > 0 then\n redis.call('zrem', client_running_key, unpack(terminated_clients))\n redis.call('hdel', client_num_queued_key, unpack(terminated_clients))\n redis.call('zrem', client_last_registered_key, unpack(terminated_clients))\n redis.call('zrem', client_last_seen_key, unpack(terminated_clients))\n end\n\n --\n -- Broadcast capacity changes\n --\n local final_capacity = compute_capacity(maxConcurrent, running, reservoir)\n\n if always_publish or (initial_capacity ~= nil and final_capacity == nil) then\n -- always_publish or was not unlimited, now unlimited\n redis.call('publish', 'b_'..id, 'capacity:'..(final_capacity or ''))\n\n elseif initial_capacity ~= nil and final_capacity ~= nil and final_capacity > initial_capacity then\n -- capacity was increased\n -- send the capacity message to the limiter having the lowest number of running jobs\n -- the tiebreaker is the limiter having not registered a job in the longest time\n\n local lowest_concurrency_value = nil\n local lowest_concurrency_clients = {}\n local lowest_concurrency_last_registered = {}\n local client_concurrencies = redis.call('zrange', client_running_key, 0, -1, 'withscores')\n\n for i = 1, #client_concurrencies, 2 do\n local client = client_concurrencies[i]\n local concurrency = tonumber(client_concurrencies[i+1])\n\n if (\n lowest_concurrency_value == nil or lowest_concurrency_value == concurrency\n ) and (\n not unresponsive_lookup[client]\n ) and (\n tonumber(redis.call('hget', client_num_queued_key, client)) > 0\n ) then\n lowest_concurrency_value = concurrency\n table.insert(lowest_concurrency_clients, client)\n local last_registered = tonumber(redis.call('zscore', client_last_registered_key, client))\n table.insert(lowest_concurrency_last_registered, last_registered)\n end\n end\n\n if #lowest_concurrency_clients > 0 then\n local position = 1\n local earliest = lowest_concurrency_last_registered[1]\n\n for i,v in ipairs(lowest_concurrency_last_registered) do\n if v < earliest then\n position = i\n earliest = v\n end\n end\n\n local next_client = lowest_concurrency_clients[position]\n redis.call('publish', 'b_'..id,\n 'capacity-priority:'..(final_capacity or '')..\n ':'..next_client..\n ':'..capacityPriorityCounter\n )\n redis.call('hincrby', settings_key, 'capacityPriorityCounter', '1')\n else\n redis.call('publish', 'b_'..id, 'capacity:'..(final_capacity or ''))\n end\n end\n\n return {\n ['capacity'] = final_capacity,\n ['running'] = running,\n ['reservoir'] = reservoir\n }\nend\n", + "queued.lua": "local clientTimeout = tonumber(redis.call('hget', settings_key, 'clientTimeout'))\nlocal valid_clients = redis.call('zrangebyscore', client_last_seen_key, (now - clientTimeout), 'inf')\nlocal client_queued = redis.call('hmget', client_num_queued_key, unpack(valid_clients))\n\nlocal sum = 0\nfor i = 1, #client_queued do\n sum = sum + tonumber(client_queued[i])\nend\n\nreturn sum\n", + "refresh_expiration.lua": "local refresh_expiration = function (now, nextRequest, groupTimeout)\n\n if groupTimeout ~= nil then\n local ttl = (nextRequest + groupTimeout) - now\n\n for i = 1, #KEYS do\n redis.call('pexpire', KEYS[i], ttl)\n end\n end\n\nend\n", + "refs.lua": "local settings_key = KEYS[1]\nlocal job_weights_key = KEYS[2]\nlocal job_expirations_key = KEYS[3]\nlocal job_clients_key = KEYS[4]\nlocal client_running_key = KEYS[5]\nlocal client_num_queued_key = KEYS[6]\nlocal client_last_registered_key = KEYS[7]\nlocal client_last_seen_key = KEYS[8]\n\nlocal now = tonumber(ARGV[1])\nlocal client = ARGV[2]\n\nlocal num_static_argv = 2\n", + "register.lua": "local index = ARGV[num_static_argv + 1]\nlocal weight = tonumber(ARGV[num_static_argv + 2])\nlocal expiration = tonumber(ARGV[num_static_argv + 3])\n\nlocal state = process_tick(now, false)\nlocal capacity = state['capacity']\nlocal reservoir = state['reservoir']\n\nlocal settings = redis.call('hmget', settings_key,\n 'nextRequest',\n 'minTime',\n 'groupTimeout'\n)\nlocal nextRequest = tonumber(settings[1])\nlocal minTime = tonumber(settings[2])\nlocal groupTimeout = tonumber(settings[3])\n\nif conditions_check(capacity, weight) then\n\n redis.call('hincrby', settings_key, 'running', weight)\n redis.call('hset', job_weights_key, index, weight)\n if expiration ~= nil then\n redis.call('zadd', job_expirations_key, now + expiration, index)\n end\n redis.call('hset', job_clients_key, index, client)\n redis.call('zincrby', client_running_key, weight, client)\n redis.call('hincrby', client_num_queued_key, client, -1)\n redis.call('zadd', client_last_registered_key, now, client)\n\n local wait = math.max(nextRequest - now, 0)\n local newNextRequest = now + wait + minTime\n\n if reservoir == nil then\n redis.call('hset', settings_key,\n 'nextRequest', newNextRequest\n )\n else\n reservoir = reservoir - weight\n redis.call('hmset', settings_key,\n 'reservoir', reservoir,\n 'nextRequest', newNextRequest\n )\n end\n\n refresh_expiration(now, newNextRequest, groupTimeout)\n\n return {true, wait, reservoir}\n\nelse\n return {false}\nend\n", + "register_client.lua": "local queued = tonumber(ARGV[num_static_argv + 1])\n\n-- Could have been re-registered concurrently\nif not redis.call('zscore', client_last_seen_key, client) then\n redis.call('zadd', client_running_key, 0, client)\n redis.call('hset', client_num_queued_key, client, queued)\n redis.call('zadd', client_last_registered_key, 0, client)\nend\n\nredis.call('zadd', client_last_seen_key, now, client)\n\nreturn {}\n", + "running.lua": "return process_tick(now, false)['running']\n", + "submit.lua": "local queueLength = tonumber(ARGV[num_static_argv + 1])\nlocal weight = tonumber(ARGV[num_static_argv + 2])\n\nlocal capacity = process_tick(now, false)['capacity']\n\nlocal settings = redis.call('hmget', settings_key,\n 'id',\n 'maxConcurrent',\n 'highWater',\n 'nextRequest',\n 'strategy',\n 'unblockTime',\n 'penalty',\n 'minTime',\n 'groupTimeout'\n)\nlocal id = settings[1]\nlocal maxConcurrent = tonumber(settings[2])\nlocal highWater = tonumber(settings[3])\nlocal nextRequest = tonumber(settings[4])\nlocal strategy = tonumber(settings[5])\nlocal unblockTime = tonumber(settings[6])\nlocal penalty = tonumber(settings[7])\nlocal minTime = tonumber(settings[8])\nlocal groupTimeout = tonumber(settings[9])\n\nif maxConcurrent ~= nil and weight > maxConcurrent then\n return redis.error_reply('OVERWEIGHT:'..weight..':'..maxConcurrent)\nend\n\nlocal reachedHWM = (highWater ~= nil and queueLength == highWater\n and not (\n conditions_check(capacity, weight)\n and nextRequest - now <= 0\n )\n)\n\nlocal blocked = strategy == 3 and (reachedHWM or unblockTime >= now)\n\nif blocked then\n local computedPenalty = penalty\n if computedPenalty == nil then\n if minTime == 0 then\n computedPenalty = 5000\n else\n computedPenalty = 15 * minTime\n end\n end\n\n local newNextRequest = now + computedPenalty + minTime\n\n redis.call('hmset', settings_key,\n 'unblockTime', now + computedPenalty,\n 'nextRequest', newNextRequest\n )\n\n local clients_queued_reset = redis.call('hkeys', client_num_queued_key)\n local queued_reset = {}\n for i = 1, #clients_queued_reset do\n table.insert(queued_reset, clients_queued_reset[i])\n table.insert(queued_reset, 0)\n end\n redis.call('hmset', client_num_queued_key, unpack(queued_reset))\n\n redis.call('publish', 'b_'..id, 'blocked:')\n\n refresh_expiration(now, newNextRequest, groupTimeout)\nend\n\nif not blocked and not reachedHWM then\n redis.call('hincrby', client_num_queued_key, client, 1)\nend\n\nreturn {reachedHWM, blocked, strategy}\n", + "update_settings.lua": "local args = {'hmset', settings_key}\n\nfor i = num_static_argv + 1, #ARGV do\n table.insert(args, ARGV[i])\nend\n\nredis.call(unpack(args))\n\nprocess_tick(now, true)\n\nlocal groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout'))\nrefresh_expiration(0, 0, groupTimeout)\n\nreturn {}\n", + "validate_client.lua": "if not redis.call('zscore', client_last_seen_key, client) then\n return redis.error_reply('UNKNOWN_CLIENT')\nend\n\nredis.call('zadd', client_last_seen_key, now, client)\n", + "validate_keys.lua": "if not (redis.call('exists', settings_key) == 1) then\n return redis.error_reply('SETTINGS_KEY_NOT_FOUND')\nend\n" + }; + } +}); +var require_Scripts = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Scripts.js"(exports2) { + "use strict"; + var headers; + var lua; + var templates; + lua = require_lua(); + headers = { + refs: lua["refs.lua"], + validate_keys: lua["validate_keys.lua"], + validate_client: lua["validate_client.lua"], + refresh_expiration: lua["refresh_expiration.lua"], + process_tick: lua["process_tick.lua"], + conditions_check: lua["conditions_check.lua"], + get_time: lua["get_time.lua"] + }; + exports2.allKeys = function(id) { + return [ + /* + HASH + */ + `b_${id}_settings`, + /* + HASH + job index -> weight + */ + `b_${id}_job_weights`, + /* + ZSET + job index -> expiration + */ + `b_${id}_job_expirations`, + /* + HASH + job index -> client + */ + `b_${id}_job_clients`, + /* + ZSET + client -> sum running + */ + `b_${id}_client_running`, + /* + HASH + client -> num queued + */ + `b_${id}_client_num_queued`, + /* + ZSET + client -> last job registered + */ + `b_${id}_client_last_registered`, + /* + ZSET + client -> last seen + */ + `b_${id}_client_last_seen` + ]; + }; + templates = { + init: { + keys: exports2.allKeys, + headers: ["process_tick"], + refresh_expiration: true, + code: lua["init.lua"] + }, + group_check: { + keys: exports2.allKeys, + headers: [], + refresh_expiration: false, + code: lua["group_check.lua"] + }, + register_client: { + keys: exports2.allKeys, + headers: ["validate_keys"], + refresh_expiration: false, + code: lua["register_client.lua"] + }, + blacklist_client: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client"], + refresh_expiration: false, + code: lua["blacklist_client.lua"] + }, + heartbeat: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick"], + refresh_expiration: false, + code: lua["heartbeat.lua"] + }, + update_settings: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick"], + refresh_expiration: true, + code: lua["update_settings.lua"] + }, + running: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick"], + refresh_expiration: false, + code: lua["running.lua"] + }, + queued: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client"], + refresh_expiration: false, + code: lua["queued.lua"] + }, + done: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick"], + refresh_expiration: false, + code: lua["done.lua"] + }, + check: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"], + refresh_expiration: false, + code: lua["check.lua"] }, - // Cancels a specific action by its ID. - // The action won't be retried again, but an async action cannot be aborted if its promise is stil attempting. - async "chelonia.persistentActions/cancel"(id) { - if (id in this.actionsByID) { - this.actionsByID[id].cancel(); - delete this.actionsByID[id]; - return await esm_default("chelonia.persistentActions/save"); - } - }, - // TODO: validation - "chelonia.persistentActions/configure"({ databaseKey, options: options2 = {} }) { - this.databaseKey = databaseKey; - for (const key in options2) { - if (key in defaultOptions2) { - defaultOptions2[key] = options2[key]; - } else { - throw new TypeError(`${tag} Unknown option: ${key}`); - } - } + submit: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"], + refresh_expiration: true, + code: lua["submit.lua"] }, - "chelonia.persistentActions/enqueue"(...args) { - const ids = []; - for (const arg of args) { - const action = Array.isArray(arg) ? new PersistentAction(arg) : new PersistentAction(arg.invocation, arg); - this.actionsByID[action.id] = action; - ids.push(action.id); - } - esm_default("chelonia.persistentActions/save").catch((e2) => { - console.error("Error saving persistent actions", e2); - }); - for (const id of ids) { - this.actionsByID[id].attempt().catch((e2) => { - console.error("Error attempting persistent action", id, e2); - }); - } - return ids; - }, - // Forces retrying a given persisted action immediately, rather than waiting for the scheduled retry. - // - 'status.failedAttemptsSoFar' will still be increased upon failure. - // - Does nothing if a retry is already running. - // - Does nothing if the action has already been resolved, rejected or cancelled. - "chelonia.persistentActions/forceRetry"(id) { - if (id in this.actionsByID) { - return this.actionsByID[id].attempt(); - } - }, - // Loads and tries every stored persistent action under the configured database key. - async "chelonia.persistentActions/load"() { - this.checkDatabaseKey(); - const storedActions = JSON.parse(await esm_default("chelonia.db/get", this.databaseKey) ?? "[]"); - for (const { id, invocation, options: options2 } of storedActions) { - this.actionsByID[id] = new PersistentAction(invocation, options2); - this.actionsByID[id].id = id; - } - return esm_default("chelonia.persistentActions/retryAll"); - }, - // Retry all existing persisted actions. - // TODO: add some delay between actions so as not to spam the server, - // or have a way to issue them all at once in a single network call. - "chelonia.persistentActions/retryAll"() { - return Promise.allSettled(Object.keys(this.actionsByID).map((id) => esm_default("chelonia.persistentActions/forceRetry", id))); - }, - // Updates the database version of the attempting action list. - "chelonia.persistentActions/save"() { - this.checkDatabaseKey(); - return esm_default("chelonia.db/set", this.databaseKey, JSON.stringify(Object.values(this.actionsByID))); - }, - "chelonia.persistentActions/status"() { - return Object.values(this.actionsByID).map((action) => ({ - id: action.id, - invocation: action.invocation, - ...action.status - })); + register: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"], + refresh_expiration: true, + code: lua["register.lua"] }, - // Pauses every currently loaded action, and removes them from memory. - // Note: persistent storage is not affected, so that these actions can be later loaded again and retried. - "chelonia.persistentActions/unload"() { - for (const id in this.actionsByID) { - if (this.actionsByID[id][timer]) { - clearTimeout(this.actionsByID[id][timer]); - } - delete this.actionsByID[id]; - } - } - }); - } -}); -var SERVER; -var init_presets = __esm({ - "node_modules/.deno/@chelonia+lib@1.2.9/node_modules/@chelonia/lib/dist/esm/presets.mjs"() { - SERVER = { - // We don't check the subscriptionSet in the server because we accpt new - // contract registrations, and are also not subcribed to contracts the same - // way clients are - acceptAllMessages: true, - // The server also doesn't process actions - skipActionProcessing: true, - // The previous setting implies this one, which we set to be on the safe side - skipSideEffects: true, - // Changes the behaviour of unwrapMaybeEncryptedData so that it never decrypts. - // Mostly useful for the server, to avoid filling up the logs and for faster - // execution. - skipDecryptionAttempts: true, - // If an error occurs during processing, the message is rejected rather than - // ignored - strictProcessing: true, - // The server expects events to be received in order (no past or future events) - strictOrdering: true - }; - } -}); -var createWorker; -var createWorker_default; -var init_createWorker = __esm({ - "src/serve/createWorker.ts"() { - "use strict"; - init_esm8(); - init_esm(); - Object.defineProperties(Buffer13, { - [serdesDeserializeSymbol]: { - value(buf2) { - return Buffer13.from(buf2); - } + free: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick"], + refresh_expiration: true, + code: lua["free.lua"] }, - [serdesSerializeSymbol]: { - value(buf2) { - return new Uint8Array(buf2.buffer, buf2.byteOffset, buf2.byteLength); - } + current_reservoir: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick"], + refresh_expiration: false, + code: lua["current_reservoir.lua"] }, - [serdesTagSymbol]: { - value: "node:buffer" + increment_reservoir: { + keys: exports2.allKeys, + headers: ["validate_keys", "validate_client", "process_tick"], + refresh_expiration: true, + code: lua["increment_reservoir.lua"] } - }); - deserializer.register(Buffer13); - createWorker = (path8) => { - let worker; - let ready; - const launchWorker = () => { - worker = new Worker(new URL(path8, import.meta.url), { type: "module" }); - return new Promise((resolve82, reject) => { - const msgHandler = (event) => { - const msg = event.data; - if (msg === "ready") { - worker.removeEventListener("error", reject, { capture: false }); - worker.addEventListener("error", (ev) => { - const e2 = ev.error; - console.error(e2, `Running worker ${basename52(path8)} terminated. Attempting relaunch...`); - worker.removeEventListener("message", msgHandler, false); - ready = launchWorker().catch((e3) => { - console.error(e3, `Error on worker ${basename52(path8)} relaunch`); - process7.exit(1); - }); - }, false); - resolve82(); - } else if (msg && typeof msg === "object" && msg.type === "sbp" && Array.isArray(msg.data) && String(msg.data[0]).startsWith("chelonia.db/")) { - const port = msg.port; - Promise.try(() => esm_default(...deserializer(msg.data))).then((r) => { - const { data, transferables } = serializer(r); - port.postMessage([true, data], transferables); - }).catch((e2) => { - const { data, transferables } = serializer(e2); - port.postMessage([false, data], transferables); - }).finally(() => { - port.close(); - }); - } - }; - worker.addEventListener("message", msgHandler, false); - worker.addEventListener("error", reject, { capture: false, once: true }); - }); - }; - ready = launchWorker(); - const rpcSbp = (...args) => { - return ready.then(() => new Promise((resolve82, reject) => { - const mc = new MessageChannel(); - const cleanup = /* @__PURE__ */ ((worker2) => () => { - worker2.removeEventListener("error", reject, { capture: true }); - mc.port2.close(); - mc.port2.onmessage = null; - mc.port2.onmessageerror = null; - })(worker); - mc.port2.onmessage = (event) => { - cleanup(); - const [success, result] = event.data; - if (success) return resolve82(result); - reject(result); - }; - mc.port2.onmessageerror = () => { - cleanup(); - reject(new Error("Message error")); - }; - worker.postMessage([mc.port1, ...args], [mc.port1]); - worker.addEventListener("error", reject, { capture: false, once: true }); - })); - }; - return { - ready, - rpcSbp, - terminate: () => worker.terminate() - }; }; - createWorker_default = createWorker; - } -}); -var import_boom2; -var plugin; -var auth_default; -var init_auth = __esm({ - "src/serve/auth.ts"() { - "use strict"; - init_utils(); - import_boom2 = __toESM(require_lib2()); - plugin = { - name: "chel-auth", - register: function(server) { - server.auth.scheme("chel-bearer", () => { - return { - authenticate: function(request, h2) { - const { authorization } = request.headers; - if (!authorization) { - return h2.unauthenticated(import_boom2.default.unauthorized(null, "bearer")); - } - const thisScheme = "bearer "; - if (authorization.slice(0, thisScheme.length) !== thisScheme) { - return h2.unauthenticated(import_boom2.default.unauthorized(null, "bearer")); - } - const token = authorization.slice(thisScheme.length); - return h2.authenticated({ credentials: { token } }); - } - }; - }); - server.auth.scheme("chel-shelter", () => { - return { - authenticate: function(request, h2) { - const { authorization } = request.headers; - if (!authorization) { - return h2.unauthenticated(import_boom2.default.unauthorized(null, "shelter")); - } - const thisScheme = "shelter "; - if (authorization.slice(0, thisScheme.length) !== thisScheme) { - return h2.unauthenticated(import_boom2.default.unauthorized(null, "shelter")); - } - try { - const billableContractID = verifyShelterAuthorizationHeader(authorization); - return h2.authenticated({ credentials: { billableContractID } }); - } catch (e2) { - console.warn(e2, "Shelter authorization failed"); - return h2.unauthenticated(import_boom2.default.unauthorized("Authentication failed", "shelter")); - } - } - }; - }); - server.auth.strategy("chel-bearer", "chel-bearer"); - server.auth.strategy("chel-shelter", "chel-shelter"); - } + exports2.names = Object.keys(templates); + exports2.keys = function(name, id) { + return templates[name].keys(id); }; - auth_default = plugin; - } -}); -var CREDITS_WORKER_TASK_TIME_INTERVAL; -var OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL; -var init_constants2 = __esm({ - "src/serve/constants.ts"() { - "use strict"; - CREDITS_WORKER_TASK_TIME_INTERVAL = 3e5; - OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL = 3e4; - } -}); -var BackendErrorNotFound; -var BackendErrorGone; -var BackendErrorBadData; -var init_errors4 = __esm({ - "src/serve/errors.ts"() { - "use strict"; - init_errors3(); - BackendErrorNotFound = ChelErrorGenerator("BackendErrorNotFound"); - BackendErrorGone = ChelErrorGenerator("BackendErrorGone"); - BackendErrorBadData = ChelErrorGenerator("BackendErrorBadData"); - } -}); -var x2; -var init_encodings2 = __esm({ - "node_modules/.deno/@apeleghq+rfc8188@1.0.7/node_modules/@apeleghq/rfc8188/dist/encodings.mjs"() { - x2 = { params: { name: "AES-GCM", length: 128 }, get cek_info() { - return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 97, 101, 115, 49, 50, 56, 103, 99, 109, 0]); - }, get nonce_info() { - return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 110, 111, 110, 99, 101, 0]); - }, block_size: 16, tag_length: 16, nonce_length: 12 }; - } -}); -var R3; -var E2; -var B3; -var w3; -var N10; -var U2; -var K2; -var init_encrypt2 = __esm({ - "node_modules/.deno/@apeleghq+rfc8188@1.0.7/node_modules/@apeleghq/rfc8188/dist/encrypt.mjs"() { - R3 = async (e2, b, f, i2) => { - let A2 = await globalThis.crypto.subtle.importKey("raw", b, "HKDF", false, ["deriveKey", "deriveBits"]), y = await globalThis.crypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", info: e2.cek_info, salt: f }, A2, e2.params, false, i2), u2 = await globalThis.crypto.subtle.deriveBits({ name: "HKDF", hash: "SHA-256", info: e2.nonce_info, salt: f }, A2, e2.nonce_length << 3); - return [y, function* () { - let L = new ArrayBuffer(e2.nonce_length), c = new DataView(L), h2 = new Uint8Array(L), a = new Uint8Array(u2), g2 = 4294967295, o2 = (e2.nonce_length >> 2) - 1, s = new Array(o2).fill(0); - for (; ; ) { - for (let t = 0; t <= g2; t++) { - c.setUint32(c.byteLength - 4, t, false); - let n = new Uint8Array(e2.nonce_length); - for (let r = 0; r < n.length; r++) n[r] = a[r] ^ h2[r]; - yield n; - } - for (let t = 0; t < o2; t++) { - if (t === o2 - 1 && s[t] === g2) throw new RangeError("Maximum number of segments exceeded"); - if (s[t] = (s[t] + 1) % (g2 + 1), c.setUint32(c.byteLength - 4 * (t + 2), s[t], false), s[t] !== 0) break; - } - } - }()]; - }; - E2 = R3; - B3 = (e2) => ArrayBuffer.isView(e2) ? new Uint8Array(e2.buffer).subarray(e2.byteOffset, e2.byteOffset + e2.byteLength) : new Uint8Array(e2); - w3 = B3; - N10 = () => { - let e2 = new Uint8Array(16); - return globalThis.crypto.getRandomValues(e2), e2; - }; - U2 = async (e2, b, f, i2, A2, y) => { - if (f <= e2.tag_length + 1 || f > 4294967295) throw new RangeError("Invalid record size: " + f); - if (i2.byteLength > 255) throw new RangeError("Key ID too long"); - if (y && y.byteLength !== 16) throw new RangeError("Invald salt length: " + y.byteLength); - let u2 = f - e2.tag_length - 1, l = y ? w3(y) : N10(), [L, c] = await E2(e2, A2, l, ["encrypt"]); - A2 = void 0; - let h2 = new Uint8Array(u2), a = 0, g2 = new TransformStream({ start: (o2) => { - let s = l.byteLength + 4 + 1 + i2.byteLength, t = new ArrayBuffer(s); - new Uint8Array(t, 0, l.byteLength).set(l); - let r = new DataView(t, l.byteLength, 5); - r.setUint32(0, f, false), r.setUint8(4, i2.byteLength); - let d = new Uint8Array(t, l.byteLength + 4 + 1, i2.byteLength), m3 = w3(i2); - d.set(m3), o2.enqueue(t); - }, transform: async (o2, s) => { - let t = w3(o2), n = 0; - for (; n < o2.byteLength; ) { - let r = t.subarray(n, n + u2 - a); - if (h2.set(r, a), a += r.byteLength, n += r.byteLength, a === u2) { - let m3 = c.next().value, p = new Uint8Array(u2 + 1); - p.set(h2.subarray(0, a)), p[a] = 1; - let T2 = await globalThis.crypto.subtle.encrypt({ name: e2.params.name, iv: m3, tagLength: e2.tag_length << 3 }, L, p); - s.enqueue(T2), a = 0; - } - } - }, flush: async (o2) => { - let t = c.next().value, n = new Uint8Array(a + 1); - n.set(h2.subarray(0, a)), n[a] = 2; - let r = await globalThis.crypto.subtle.encrypt({ name: e2.params.name, iv: t, tagLength: e2.tag_length << 3 }, L, n); - o2.enqueue(r), h2.fill(0), n.fill(0); - } }); - return b.pipeThrough(g2), g2.readable; - }; - K2 = U2; - } -}); -var rfc8291Ikm_default; -var init_rfc8291Ikm = __esm({ - "src/serve/rfc8291Ikm.ts"() { - "use strict"; - rfc8291Ikm_default = async (uaPublic, salt) => { - const [[asPrivateKey, asPublic], uaPublicKey] = await Promise.all([ - crypto.subtle.generateKey( - { - name: "ECDH", - namedCurve: "P-256" - }, - false, - ["deriveKey"] - ).then(async (asKeyPair) => { - const asPublic2 = await crypto.subtle.exportKey( - "raw", - asKeyPair.publicKey - ); - return [asKeyPair.privateKey, asPublic2]; - }), - crypto.subtle.importKey( - "raw", - uaPublic, - { name: "ECDH", namedCurve: "P-256" }, - false, - [] - ) - ]); - const ecdhSecret = await crypto.subtle.deriveKey( - { - name: "ECDH", - public: uaPublicKey - }, - asPrivateKey, - { - name: "HKDF", - hash: "SHA-256" - }, - false, - ["deriveBits"] - ); - const infoString = new Uint8Array([ - 87, - 101, - 98, - 80, - 117, - 115, - 104, - 58, - 32, - 105, - 110, - 102, - 111, - 0 - ]); - const info = new Uint8Array(infoString.byteLength + uaPublic.byteLength + asPublic.byteLength); - info.set(infoString, 0); - info.set(uaPublic, infoString.byteLength); - info.set( - new Uint8Array(asPublic), - infoString.byteLength + uaPublic.byteLength - ); - const IKM = await crypto.subtle.deriveBits( - { - name: "HKDF", - hash: "SHA-256", - salt, - info - }, - ecdhSecret, - 32 << 3 - ); - return [asPublic, IKM]; + exports2.payload = function(name) { + var template; + template = templates[name]; + return Array.prototype.concat(headers.refs, template.headers.map(function(h2) { + return headers[h2]; + }), template.refresh_expiration ? headers.refresh_expiration : "", template.code).join("\n"); }; } }); -var addSubscriptionToIndex; -var deleteSubscriptionFromIndex; -var saveSubscription; -var addChannelToSubscription; -var deleteChannelFromSubscription; -var removeSubscription; -var subscriptionInfoWrapper; -var encryptPayload; -var postEvent; -var pushServerActionhandlers; -var init_push = __esm({ - "src/serve/push.ts"() { +var require_RedisConnection = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/RedisConnection.js"(exports, module) { "use strict"; - init_encodings2(); - init_encrypt2(); - init_functions(); - init_pubsub(); - init_esm(); - init_database(); - init_instance_keys(); - init_rfc8291Ikm(); - init_vapid(); - addSubscriptionToIndex = appendToIndexFactory("_private_webpush_index"); - deleteSubscriptionFromIndex = removeFromIndexFactory("_private_webpush_index"); - saveSubscription = (server, subscriptionId) => { - return esm_default("chelonia.db/set", `_private_webpush_${subscriptionId}`, JSON.stringify({ - settings: server.pushSubscriptions[subscriptionId].settings, - subscriptionInfo: server.pushSubscriptions[subscriptionId], - channelIDs: [...server.pushSubscriptions[subscriptionId].subscriptions] - })).catch((e2) => { - console.error(e2, "Error saving subscription", subscriptionId); - throw e2; - }); - }; - addChannelToSubscription = (server, subscriptionId, channelID) => { - server.pushSubscriptions[subscriptionId].subscriptions.add(channelID); - return saveSubscription(server, subscriptionId); - }; - deleteChannelFromSubscription = (server, subscriptionId, channelID) => { - server.pushSubscriptions[subscriptionId].subscriptions.delete(channelID); - return saveSubscription(server, subscriptionId); - }; - removeSubscription = async (subscriptionId) => { + function asyncGeneratorStep(gen, resolve82, reject, _next, _throw, key, arg) { try { - const server = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); - const subscription = server.pushSubscriptions[subscriptionId]; - if (subscription) { - delete server.pushSubscriptions[subscriptionId]; - if (server.subscribersByChannelID) { - subscription.subscriptions.forEach((channelID) => { - server.subscribersByChannelID[channelID]?.delete(subscription); - }); - } - } else { - } - await esm_default("chelonia.db/delete", `_private_webpush_${subscriptionId}`); - await deleteSubscriptionFromIndex(subscriptionId); - } catch (e2) { - console.error(e2, "Error removing subscription", subscriptionId); + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; } - }; - subscriptionInfoWrapper = (subscriptionId, subscriptionInfo, extra) => { - subscriptionInfo.endpoint = new URL(subscriptionInfo.endpoint); - Object.defineProperties(subscriptionInfo, { - "id": { - get() { - return subscriptionId; + if (info.done) { + resolve82(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + function _asyncToGenerator(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "next", value); } - }, - // These encryption keys are used for encrypting push notification bodies - // and are unrelated to VAPID, which is used for provenance. - "encryptionKeys": { - get: /* @__PURE__ */ (() => { - let count = 0; - let resultPromise; - let salt; - let uaPublic; - return function() { - if ((count | 0) === 0) { - if (!salt) { - salt = Buffer14.from(this.keys.auth, "base64url"); - } - if (!uaPublic) { - uaPublic = Buffer14.from(this.keys.p256dh, "base64url"); - } - resultPromise = rfc8291Ikm_default(uaPublic, salt); - count = 1; - } else { - count++; - } - return resultPromise; + function _throw(err) { + asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "throw", err); + } + _next(void 0); + }); + }; + } + var Events; + var RedisConnection; + var Scripts; + var parser; + parser = require_parser2(); + Events = require_Events(); + Scripts = require_Scripts(); + RedisConnection = function() { + class RedisConnection { + constructor(options = {}) { + parser.load(options, this.defaults, this); + if (this.Redis == null) { + this.Redis = eval("require")("redis"); + } + if (this.Events == null) { + this.Events = new Events(this); + } + this.terminated = false; + if (this.client == null) { + this.client = this.Redis.createClient(this.clientOptions); + } + this.subscriber = this.client.duplicate(); + this.limiters = {}; + this.shas = {}; + this.ready = this.Promise.all([this._setup(this.client, false), this._setup(this.subscriber, true)]).then(() => { + return this._loadScripts(); + }).then(() => { + return { + client: this.client, + subscriber: this.subscriber }; - })() - }, - "settings": { - value: extra.settings || {} - }, - "sockets": { - value: /* @__PURE__ */ new Set() - }, - "subscriptions": { - value: new Set(extra.channelIDs) + }); } - }); - Object.freeze(subscriptionInfo); - return subscriptionInfo; - }; - encryptPayload = async (subscription, data) => { - const readableStream = new Response(data).body; - if (!readableStream) throw new Error("Failed to create readable stream"); - const [asPublic, IKM] = await subscription.encryptionKeys; - return K2(x2, readableStream, 32768, asPublic, IKM).then(async (bodyStream) => { - const chunks = []; - const reader = bodyStream.getReader(); - for (; ; ) { - const { done, value } = await reader.read(); - if (done) break; - chunks.push(new Uint8Array(value)); + _setup(client, sub) { + client.setMaxListeners(0); + return new this.Promise((resolve82, reject) => { + client.on("error", (e2) => { + return this.Events.trigger("error", e2); + }); + if (sub) { + client.on("message", (channel, message) => { + var ref; + return (ref = this.limiters[channel]) != null ? ref._store.onMessage(channel, message) : void 0; + }); + } + if (client.ready) { + return resolve82(); + } else { + return client.once("ready", resolve82); + } + }); } - return Buffer14.concat(chunks); - }); - }; - postEvent = async (subscription, event) => { - const authorization = await vapidAuthorization(subscription.endpoint); - const body = event ? await encryptPayload(subscription, event) : void 0; - const req = await fetch(subscription.endpoint, { - method: "POST", - headers: [ - ["authorization", authorization], - ...body ? [ - ["content-encoding", "aes128gcm"], - [ - "content-type", - "application/octet-stream" - ] - ] : [], - // ['push-receipt', ''], - ["ttl", "60"] - ], - body - }); - if (!req.ok) { - const endpointHost = new URL(subscription.endpoint).host; - console.info( - await req.text().then((response) => ({ response })).catch((e2) => `ERR: ${e2?.message}`), - `Error ${req.status} sending push notification to '${subscription.id}' via ${endpointHost}` - ); - if ([401, 404, 410].includes(req.status)) { - removeSubscription(subscription.id); - throw new Error(`Error sending push: ${req.status}`); + _loadScript(name) { + return new this.Promise((resolve82, reject) => { + var payload; + payload = Scripts.payload(name); + return this.client.multi([["script", "load", payload]]).exec((err, replies) => { + if (err != null) { + return reject(err); + } + this.shas[name] = replies[0]; + return resolve82(replies[0]); + }); + }); } - if (req.status === 413) { - throw new Error("Payload too large"); + _loadScripts() { + return this.Promise.all(Scripts.names.map((k) => { + return this._loadScript(k); + })); } - } - }; - pushServerActionhandlers = { - [PUSH_SERVER_ACTION_TYPE.SEND_PUBLIC_KEY]() { - const socket = this; - socket.send(createMessage(REQUEST_TYPE.PUSH_ACTION, { type: PUSH_SERVER_ACTION_TYPE.SEND_PUBLIC_KEY, data: getVapidPublicKey() })); - }, - async [PUSH_SERVER_ACTION_TYPE.STORE_SUBSCRIPTION](payload) { - const socket = this; - const { server } = socket; - const { applicationServerKey, settings, subscriptionInfo } = payload; - if (applicationServerKey) { - const ourVapidPublicKey = getVapidPublicKey(); - const theirVapidPublicKey = Buffer14.from(applicationServerKey, "base64").toString("base64url"); - if (ourVapidPublicKey !== theirVapidPublicKey) { - socket.send(createMessage(REQUEST_TYPE.PUSH_ACTION, { type: PUSH_SERVER_ACTION_TYPE.SEND_PUBLIC_KEY, data: getVapidPublicKey() })); - console.warn({ ourVapidPublicKey, theirVapidPublicKey }, "Refusing to store subscription because the associated public VAPID key does not match ours"); - return; - } + __runCommand__(cmd) { + var _this = this; + return _asyncToGenerator(function* () { + yield _this.ready; + return new _this.Promise((resolve82, reject) => { + return _this.client.multi([cmd]).exec_atomic(function(err, replies) { + if (err != null) { + return reject(err); + } else { + return resolve82(replies[0]); + } + }); + }); + })(); } - let subscriptionId = null; - let host = ""; - let subscriptionWrapper = null; - try { - subscriptionId = await getSubscriptionId(subscriptionInfo); - subscriptionWrapper = server.pushSubscriptions[subscriptionId]; - if (!subscriptionWrapper) { - console.debug(`saving new push subscription '${subscriptionId}':`, subscriptionInfo); - server.pushSubscriptions[subscriptionId] = subscriptionInfoWrapper(subscriptionId, subscriptionInfo, { settings }); - subscriptionWrapper = server.pushSubscriptions[subscriptionId]; - host = subscriptionWrapper.endpoint.host; - await addSubscriptionToIndex(subscriptionId); - await saveSubscription(server, subscriptionId); - await postEvent(subscriptionWrapper, JSON.stringify({ type: "initial" })); - } else { - host = subscriptionWrapper.endpoint.host; - if (subscriptionWrapper.sockets.size === 0) { - subscriptionWrapper.subscriptions.forEach((channelID) => { - if (!server.subscribersByChannelID[channelID]) return; - server.subscribersByChannelID[channelID].delete(subscriptionWrapper); + __addLimiter__(instance) { + return this.Promise.all([instance.channel(), instance.channel_client()].map((channel) => { + return new this.Promise((resolve82, reject) => { + var handler; + handler = (chan) => { + if (chan === channel) { + this.subscriber.removeListener("subscribe", handler); + this.limiters[channel] = instance; + return resolve82(); + } + }; + this.subscriber.on("subscribe", handler); + return this.subscriber.subscribe(channel); + }); + })); + } + __removeLimiter__(instance) { + var _this2 = this; + return this.Promise.all([instance.channel(), instance.channel_client()].map( + /* @__PURE__ */ function() { + var _ref = _asyncToGenerator(function* (channel) { + if (!_this2.terminated) { + yield new _this2.Promise((resolve82, reject) => { + return _this2.subscriber.unsubscribe(channel, function(err, chan) { + if (err != null) { + return reject(err); + } + if (chan === channel) { + return resolve82(); + } + }); + }); + } + return delete _this2.limiters[channel]; }); - } - } - if (socket.pushSubscriptionId) { - if (socket.pushSubscriptionId === subscriptionId) return; - await removeSubscription(socket.pushSubscriptionId); - } - socket.pushSubscriptionId = subscriptionId; - subscriptionWrapper.subscriptions.forEach((channelID) => { - server.subscribersByChannelID[channelID]?.delete(subscriptionWrapper); - }); - subscriptionWrapper.sockets.add(socket); - socket.subscriptions?.forEach((channelID) => { - subscriptionWrapper.subscriptions.add(channelID); - }); - await saveSubscription(server, subscriptionId); - } catch (e2) { - console.error(e2, `[${socket.ip}] Failed to store subscription '${subscriptionId || "??"}' (${host}), removing it!`); - subscriptionId && removeSubscription(subscriptionId); - throw e2; + return function(_x) { + return _ref.apply(this, arguments); + }; + }() + )); } - }, - [PUSH_SERVER_ACTION_TYPE.DELETE_SUBSCRIPTION]() { - const socket = this; - const { pushSubscriptionId: subscriptionId } = socket; - if (subscriptionId) { - return removeSubscription(subscriptionId); + __scriptArgs__(name, id, args, cb) { + var keys; + keys = Scripts.keys(name, id); + return [this.shas[name], keys.length].concat(keys, args, cb); + } + __scriptFn__(name) { + return this.client.evalsha.bind(this.client); + } + disconnect(flush = true) { + var i2, k, len, ref; + ref = Object.keys(this.limiters); + for (i2 = 0, len = ref.length; i2 < len; i2++) { + k = ref[i2]; + clearInterval(this.limiters[k]._store.heartbeat); + } + this.limiters = {}; + this.terminated = true; + this.client.end(flush); + this.subscriber.end(flush); + return this.Promise.resolve(); } } - }; + ; + RedisConnection.prototype.datastore = "redis"; + RedisConnection.prototype.defaults = { + Redis: null, + clientOptions: {}, + client: null, + Promise, + Events: null + }; + return RedisConnection; + }.call(void 0); + module.exports = RedisConnection; } }); -var require_stream = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/stream.js"(exports2, module14) { +var require_IORedisConnection = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/IORedisConnection.js"(exports, module) { "use strict"; - var { Duplex } = __require2("stream"); - function emitClose(stream) { - stream.emit("close"); + function _slicedToArray(arr, i2) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i2) || _nonIterableRest(); } - function duplexOnEnd() { - if (!this.destroyed && this._writableState.finished) { - this.destroy(); + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + function _iterableToArrayLimit(arr, i2) { + var _arr = []; + var _n = true; + var _d = false; + var _e = void 0; + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + if (i2 && _arr.length === i2) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } } + return _arr; } - function duplexOnError(err) { - this.removeListener("error", duplexOnError); - this.destroy(); - if (this.listenerCount("error") === 0) { - this.emit("error", err); + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + function asyncGeneratorStep(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; + } + if (info.done) { + resolve82(value); + } else { + Promise.resolve(value).then(_next, _throw); } } - function createWebSocketStream2(ws, options2) { - let terminateOnDestroy = true; - const duplex = new Duplex({ - ...options2, - autoDestroy: false, - emitClose: false, - objectMode: false, - writableObjectMode: false - }); - ws.on("message", function message(msg, isBinary) { - const data = !isBinary && duplex._readableState.objectMode ? msg.toString() : msg; - if (!duplex.push(data)) ws.pause(); - }); - ws.once("error", function error2(err) { - if (duplex.destroyed) return; - terminateOnDestroy = false; - duplex.destroy(err); - }); - ws.once("close", function close() { - if (duplex.destroyed) return; - duplex.push(null); - }); - duplex._destroy = function(err, callback) { - if (ws.readyState === ws.CLOSED) { - callback(err); - process.nextTick(emitClose, duplex); - return; - } - let called = false; - ws.once("error", function error2(err2) { - called = true; - callback(err2); - }); - ws.once("close", function close() { - if (!called) callback(err); - process.nextTick(emitClose, duplex); + function _asyncToGenerator(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "throw", err); + } + _next(void 0); }); - if (terminateOnDestroy) ws.terminate(); }; - duplex._final = function(callback) { - if (ws.readyState === ws.CONNECTING) { - ws.once("open", function open() { - duplex._final(callback); + } + var Events; + var IORedisConnection; + var Scripts; + var parser; + parser = require_parser2(); + Events = require_Events(); + Scripts = require_Scripts(); + IORedisConnection = function() { + class IORedisConnection { + constructor(options = {}) { + parser.load(options, this.defaults, this); + if (this.Redis == null) { + this.Redis = eval("require")("ioredis"); + } + if (this.Events == null) { + this.Events = new Events(this); + } + this.terminated = false; + if (this.clusterNodes != null) { + this.client = new this.Redis.Cluster(this.clusterNodes, this.clientOptions); + this.subscriber = new this.Redis.Cluster(this.clusterNodes, this.clientOptions); + } else if (this.client != null && this.client.duplicate == null) { + this.subscriber = new this.Redis.Cluster(this.client.startupNodes, this.client.options); + } else { + if (this.client == null) { + this.client = new this.Redis(this.clientOptions); + } + this.subscriber = this.client.duplicate(); + } + this.limiters = {}; + this.ready = this.Promise.all([this._setup(this.client, false), this._setup(this.subscriber, true)]).then(() => { + this._loadScripts(); + return { + client: this.client, + subscriber: this.subscriber + }; }); - return; } - if (ws._socket === null) return; - if (ws._socket._writableState.finished) { - callback(); - if (duplex._readableState.endEmitted) duplex.destroy(); - } else { - ws._socket.once("finish", function finish() { - callback(); + _setup(client, sub) { + client.setMaxListeners(0); + return new this.Promise((resolve82, reject) => { + client.on("error", (e2) => { + return this.Events.trigger("error", e2); + }); + if (sub) { + client.on("message", (channel, message) => { + var ref; + return (ref = this.limiters[channel]) != null ? ref._store.onMessage(channel, message) : void 0; + }); + } + if (client.status === "ready") { + return resolve82(); + } else { + return client.once("ready", resolve82); + } }); - ws.close(); } - }; - duplex._read = function() { - if (ws.isPaused) ws.resume(); - }; - duplex._write = function(chunk, encoding, callback) { - if (ws.readyState === ws.CONNECTING) { - ws.once("open", function open() { - duplex._write(chunk, encoding, callback); + _loadScripts() { + return Scripts.names.forEach((name) => { + return this.client.defineCommand(name, { + lua: Scripts.payload(name) + }); }); - return; } - ws.send(chunk, callback); - }; - duplex.on("end", duplexOnEnd); - duplex.on("error", duplexOnError); - return duplex; - } - module14.exports = createWebSocketStream2; - } -}); -var require_constants2 = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/constants.js"(exports2, module14) { - "use strict"; - module14.exports = { - BINARY_TYPES: ["nodebuffer", "arraybuffer", "fragments"], - EMPTY_BUFFER: Buffer.alloc(0), - GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", - kForOnEventAttribute: Symbol("kIsForOnEventAttribute"), - kListener: Symbol("kListener"), - kStatusCode: Symbol("status-code"), - kWebSocket: Symbol("websocket"), - NOOP: () => { + __runCommand__(cmd) { + var _this = this; + return _asyncToGenerator(function* () { + var _, deleted; + yield _this.ready; + var _ref = yield _this.client.pipeline([cmd]).exec(); + var _ref2 = _slicedToArray(_ref, 1); + var _ref2$ = _slicedToArray(_ref2[0], 2); + _ = _ref2$[0]; + deleted = _ref2$[1]; + return deleted; + })(); + } + __addLimiter__(instance) { + return this.Promise.all([instance.channel(), instance.channel_client()].map((channel) => { + return new this.Promise((resolve82, reject) => { + return this.subscriber.subscribe(channel, () => { + this.limiters[channel] = instance; + return resolve82(); + }); + }); + })); + } + __removeLimiter__(instance) { + var _this2 = this; + return [instance.channel(), instance.channel_client()].forEach( + /* @__PURE__ */ function() { + var _ref3 = _asyncToGenerator(function* (channel) { + if (!_this2.terminated) { + yield _this2.subscriber.unsubscribe(channel); + } + return delete _this2.limiters[channel]; + }); + return function(_x) { + return _ref3.apply(this, arguments); + }; + }() + ); + } + __scriptArgs__(name, id, args, cb) { + var keys; + keys = Scripts.keys(name, id); + return [keys.length].concat(keys, args, cb); + } + __scriptFn__(name) { + return this.client[name].bind(this.client); + } + disconnect(flush = true) { + var i2, k, len, ref; + ref = Object.keys(this.limiters); + for (i2 = 0, len = ref.length; i2 < len; i2++) { + k = ref[i2]; + clearInterval(this.limiters[k]._store.heartbeat); + } + this.limiters = {}; + this.terminated = true; + if (flush) { + return this.Promise.all([this.client.quit(), this.subscriber.quit()]); + } else { + this.client.disconnect(); + this.subscriber.disconnect(); + return this.Promise.resolve(); + } + } } - }; + ; + IORedisConnection.prototype.datastore = "ioredis"; + IORedisConnection.prototype.defaults = { + Redis: null, + clientOptions: {}, + clusterNodes: null, + client: null, + Promise, + Events: null + }; + return IORedisConnection; + }.call(void 0); + module.exports = IORedisConnection; } }); -var require_buffer_util = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/buffer-util.js"(exports2, module14) { +var require_RedisDatastore = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/RedisDatastore.js"(exports2, module14) { "use strict"; - var { EMPTY_BUFFER } = require_constants2(); - function concat2(list, totalLength) { - if (list.length === 0) return EMPTY_BUFFER; - if (list.length === 1) return list[0]; - const target = Buffer.allocUnsafe(totalLength); - let offset = 0; - for (let i2 = 0; i2 < list.length; i2++) { - const buf2 = list[i2]; - target.set(buf2, offset); - offset += buf2.length; - } - if (offset < totalLength) return target.slice(0, offset); - return target; + function _slicedToArray2(arr, i2) { + return _arrayWithHoles2(arr) || _iterableToArrayLimit2(arr, i2) || _nonIterableRest2(); } - function _mask(source, mask, output, offset, length2) { - for (let i2 = 0; i2 < length2; i2++) { - output[offset + i2] = source[i2] ^ mask[i2 & 3]; - } + function _nonIterableRest2() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); } - function _unmask(buffer, mask) { - for (let i2 = 0; i2 < buffer.length; i2++) { - buffer[i2] ^= mask[i2 & 3]; + function _iterableToArrayLimit2(arr, i2) { + var _arr = []; + var _n = true; + var _d = false; + var _e = void 0; + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + if (i2 && _arr.length === i2) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } } + return _arr; } - function toArrayBuffer(buf2) { - if (buf2.byteLength === buf2.buffer.byteLength) { - return buf2.buffer; - } - return buf2.buffer.slice(buf2.byteOffset, buf2.byteOffset + buf2.byteLength); + function _arrayWithHoles2(arr) { + if (Array.isArray(arr)) return arr; } - function toBuffer(data) { - toBuffer.readOnly = true; - if (Buffer.isBuffer(data)) return data; - let buf2; - if (data instanceof ArrayBuffer) { - buf2 = Buffer.from(data); - } else if (ArrayBuffer.isView(data)) { - buf2 = Buffer.from(data.buffer, data.byteOffset, data.byteLength); + function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; + } + if (info.done) { + resolve82(value); } else { - buf2 = Buffer.from(data); - toBuffer.readOnly = false; + Promise.resolve(value).then(_next, _throw); } - return buf2; } - try { - const bufferUtil = __require2("bufferutil"); - module14.exports = { - concat: concat2, - mask(source, mask, output, offset, length2) { - if (length2 < 48) _mask(source, mask, output, offset, length2); - else bufferUtil.mask(source, mask, output, offset, length2); - }, - toArrayBuffer, - toBuffer, - unmask(buffer, mask) { - if (buffer.length < 32) _unmask(buffer, mask); - else bufferUtil.unmask(buffer, mask); - } - }; - } catch (e2) { - module14.exports = { - concat: concat2, - mask: _mask, - toArrayBuffer, - toBuffer, - unmask: _unmask + function _asyncToGenerator2(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + } + _next(void 0); + }); }; } - } -}); -var require_limiter = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/limiter.js"(exports2, module14) { - "use strict"; - var kDone = Symbol("kDone"); - var kRun = Symbol("kRun"); - var Limiter = class { - /** - * Creates a new `Limiter`. - * - * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed - * to run concurrently - */ - constructor(concurrency) { - this[kDone] = () => { - this.pending--; - this[kRun](); - }; - this.concurrency = concurrency || Infinity; - this.jobs = []; - this.pending = 0; - } - /** - * Adds a job to the queue. - * - * @param {Function} job The job to run - * @public - */ - add(job) { - this.jobs.push(job); - this[kRun](); - } - /** - * Removes a job from the queue and runs it if possible. - * - * @private - */ - [kRun]() { - if (this.pending === this.concurrency) return; - if (this.jobs.length) { - const job = this.jobs.shift(); - this.pending++; - job(this[kDone]); - } - } - }; - module14.exports = Limiter; - } -}); -var require_permessage_deflate = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/permessage-deflate.js"(exports2, module14) { - "use strict"; - var zlib = __require2("zlib"); - var bufferUtil = require_buffer_util(); - var Limiter = require_limiter(); - var { kStatusCode } = require_constants2(); - var TRAILER = Buffer.from([0, 0, 255, 255]); - var kPerMessageDeflate = Symbol("permessage-deflate"); - var kTotalLength = Symbol("total-length"); - var kCallback = Symbol("callback"); - var kBuffers = Symbol("buffers"); - var kError = Symbol("error"); - var zlibLimiter; - var PerMessageDeflate = class { - /** - * Creates a PerMessageDeflate instance. - * - * @param {Object} [options] Configuration options - * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support - * for, or request, a custom client window size - * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/ - * acknowledge disabling of client context takeover - * @param {Number} [options.concurrencyLimit=10] The number of concurrent - * calls to zlib - * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the - * use of a custom server window size - * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept - * disabling of server context takeover - * @param {Number} [options.threshold=1024] Size (in bytes) below which - * messages should not be compressed if context takeover is disabled - * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on - * deflate - * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on - * inflate - * @param {Boolean} [isServer=false] Create the instance in either server or - * client mode - * @param {Number} [maxPayload=0] The maximum allowed message length - */ - constructor(options2, isServer, maxPayload) { - this._maxPayload = maxPayload | 0; - this._options = options2 || {}; - this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024; - this._isServer = !!isServer; - this._deflate = null; - this._inflate = null; - this.params = null; - if (!zlibLimiter) { - const concurrency = this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10; - zlibLimiter = new Limiter(concurrency); - } - } - /** - * @type {String} - */ - static get extensionName() { - return "permessage-deflate"; - } - /** - * Create an extension negotiation offer. - * - * @return {Object} Extension parameters - * @public - */ - offer() { - const params = {}; - if (this._options.serverNoContextTakeover) { - params.server_no_context_takeover = true; - } - if (this._options.clientNoContextTakeover) { - params.client_no_context_takeover = true; - } - if (this._options.serverMaxWindowBits) { - params.server_max_window_bits = this._options.serverMaxWindowBits; - } - if (this._options.clientMaxWindowBits) { - params.client_max_window_bits = this._options.clientMaxWindowBits; - } else if (this._options.clientMaxWindowBits == null) { - params.client_max_window_bits = true; - } - return params; - } - /** - * Accept an extension negotiation offer/response. - * - * @param {Array} configurations The extension negotiation offers/reponse - * @return {Object} Accepted configuration - * @public - */ - accept(configurations) { - configurations = this.normalizeParams(configurations); - this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations); - return this.params; - } - /** - * Releases all resources used by the extension. - * - * @public - */ - cleanup() { - if (this._inflate) { - this._inflate.close(); - this._inflate = null; + var BottleneckError; + var IORedisConnection2; + var RedisConnection2; + var RedisDatastore; + var parser3; + parser3 = require_parser2(); + BottleneckError = require_BottleneckError(); + RedisConnection2 = require_RedisConnection(); + IORedisConnection2 = require_IORedisConnection(); + RedisDatastore = class RedisDatastore { + constructor(instance, storeOptions, storeInstanceOptions) { + this.instance = instance; + this.storeOptions = storeOptions; + this.originalId = this.instance.id; + this.clientId = this.instance._randomIndex(); + parser3.load(storeInstanceOptions, storeInstanceOptions, this); + this.clients = {}; + this.capacityPriorityCounters = {}; + this.sharedConnection = this.connection != null; + if (this.connection == null) { + this.connection = this.instance.datastore === "redis" ? new RedisConnection2({ + Redis: this.Redis, + clientOptions: this.clientOptions, + Promise: this.Promise, + Events: this.instance.Events + }) : this.instance.datastore === "ioredis" ? new IORedisConnection2({ + Redis: this.Redis, + clientOptions: this.clientOptions, + clusterNodes: this.clusterNodes, + Promise: this.Promise, + Events: this.instance.Events + }) : void 0; } - if (this._deflate) { - const callback = this._deflate[kCallback]; - this._deflate.close(); - this._deflate = null; - if (callback) { - callback( - new Error( - "The deflate stream was closed while data was being processed" - ) - ); + this.instance.connection = this.connection; + this.instance.datastore = this.connection.datastore; + this.ready = this.connection.ready.then((clients) => { + this.clients = clients; + return this.runScript("init", this.prepareInitSettings(this.clearDatastore)); + }).then(() => { + return this.connection.__addLimiter__(this.instance); + }).then(() => { + return this.runScript("register_client", [this.instance.queued()]); + }).then(() => { + var base2; + if (typeof (base2 = this.heartbeat = setInterval(() => { + return this.runScript("heartbeat", []).catch((e2) => { + return this.instance.Events.trigger("error", e2); + }); + }, this.heartbeatInterval)).unref === "function") { + base2.unref(); } - } + return this.clients; + }); } - /** - * Accept an extension negotiation offer. - * - * @param {Array} offers The extension negotiation offers - * @return {Object} Accepted configuration - * @private - */ - acceptAsServer(offers) { - const opts = this._options; - const accepted = offers.find((params) => { - if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) { - return false; + __publish__(message) { + var _this = this; + return _asyncToGenerator2(function* () { + var client; + var _ref = yield _this.ready; + client = _ref.client; + return client.publish(_this.instance.channel(), `message:${message.toString()}`); + })(); + } + onMessage(channel, message) { + var _this2 = this; + return _asyncToGenerator2(function* () { + var capacity, counter, data, drained, e2, newCapacity, pos, priorityClient, rawCapacity, type; + try { + pos = message.indexOf(":"); + var _ref2 = [message.slice(0, pos), message.slice(pos + 1)]; + type = _ref2[0]; + data = _ref2[1]; + if (type === "capacity") { + return yield _this2.instance._drainAll(data.length > 0 ? ~~data : void 0); + } else if (type === "capacity-priority") { + var _data$split = data.split(":"); + var _data$split2 = _slicedToArray2(_data$split, 3); + rawCapacity = _data$split2[0]; + priorityClient = _data$split2[1]; + counter = _data$split2[2]; + capacity = rawCapacity.length > 0 ? ~~rawCapacity : void 0; + if (priorityClient === _this2.clientId) { + drained = yield _this2.instance._drainAll(capacity); + newCapacity = capacity != null ? capacity - (drained || 0) : ""; + return yield _this2.clients.client.publish(_this2.instance.channel(), `capacity-priority:${newCapacity}::${counter}`); + } else if (priorityClient === "") { + clearTimeout(_this2.capacityPriorityCounters[counter]); + delete _this2.capacityPriorityCounters[counter]; + return _this2.instance._drainAll(capacity); + } else { + return _this2.capacityPriorityCounters[counter] = setTimeout( + /* @__PURE__ */ _asyncToGenerator2(function* () { + var e3; + try { + delete _this2.capacityPriorityCounters[counter]; + yield _this2.runScript("blacklist_client", [priorityClient]); + return yield _this2.instance._drainAll(capacity); + } catch (error2) { + e3 = error2; + return _this2.instance.Events.trigger("error", e3); + } + }), + 1e3 + ); + } + } else if (type === "message") { + return _this2.instance.Events.trigger("message", data); + } else if (type === "blocked") { + return yield _this2.instance._dropAllQueued(); + } + } catch (error2) { + e2 = error2; + return _this2.instance.Events.trigger("error", e2); } - return true; - }); - if (!accepted) { - throw new Error("None of the extension offers can be accepted"); - } - if (opts.serverNoContextTakeover) { - accepted.server_no_context_takeover = true; - } - if (opts.clientNoContextTakeover) { - accepted.client_no_context_takeover = true; - } - if (typeof opts.serverMaxWindowBits === "number") { - accepted.server_max_window_bits = opts.serverMaxWindowBits; - } - if (typeof opts.clientMaxWindowBits === "number") { - accepted.client_max_window_bits = opts.clientMaxWindowBits; - } else if (accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false) { - delete accepted.client_max_window_bits; - } - return accepted; + })(); } - /** - * Accept the extension negotiation response. - * - * @param {Array} response The extension negotiation response - * @return {Object} Accepted configuration - * @private - */ - acceptAsClient(response) { - const params = response[0]; - if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) { - throw new Error('Unexpected parameter "client_no_context_takeover"'); - } - if (!params.client_max_window_bits) { - if (typeof this._options.clientMaxWindowBits === "number") { - params.client_max_window_bits = this._options.clientMaxWindowBits; - } - } else if (this._options.clientMaxWindowBits === false || typeof this._options.clientMaxWindowBits === "number" && params.client_max_window_bits > this._options.clientMaxWindowBits) { - throw new Error( - 'Unexpected or invalid parameter "client_max_window_bits"' - ); + __disconnect__(flush) { + clearInterval(this.heartbeat); + if (this.sharedConnection) { + return this.connection.__removeLimiter__(this.instance); + } else { + return this.connection.disconnect(flush); } - return params; } - /** - * Normalize parameters. - * - * @param {Array} configurations The extension negotiation offers/reponse - * @return {Array} The offers/response with normalized parameters - * @private - */ - normalizeParams(configurations) { - configurations.forEach((params) => { - Object.keys(params).forEach((key) => { - let value = params[key]; - if (value.length > 1) { - throw new Error(`Parameter "${key}" must have only a single value`); - } - value = value[0]; - if (key === "client_max_window_bits") { - if (value !== true) { - const num = +value; - if (!Number.isInteger(num) || num < 8 || num > 15) { - throw new TypeError( - `Invalid value for parameter "${key}": ${value}` - ); - } - value = num; - } else if (!this._isServer) { - throw new TypeError( - `Invalid value for parameter "${key}": ${value}` - ); - } - } else if (key === "server_max_window_bits") { - const num = +value; - if (!Number.isInteger(num) || num < 8 || num > 15) { - throw new TypeError( - `Invalid value for parameter "${key}": ${value}` - ); + runScript(name, args) { + var _this3 = this; + return _asyncToGenerator2(function* () { + if (!(name === "init" || name === "register_client")) { + yield _this3.ready; + } + return new _this3.Promise((resolve82, reject) => { + var all_args, arr; + all_args = [Date.now(), _this3.clientId].concat(args); + _this3.instance.Events.trigger("debug", `Calling Redis script: ${name}.lua`, all_args); + arr = _this3.connection.__scriptArgs__(name, _this3.originalId, all_args, function(err, replies) { + if (err != null) { + return reject(err); } - value = num; - } else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") { - if (value !== true) { - throw new TypeError( - `Invalid value for parameter "${key}": ${value}` - ); + return resolve82(replies); + }); + return _this3.connection.__scriptFn__(name)(...arr); + }).catch((e2) => { + if (e2.message === "SETTINGS_KEY_NOT_FOUND") { + if (name === "heartbeat") { + return _this3.Promise.resolve(); + } else { + return _this3.runScript("init", _this3.prepareInitSettings(false)).then(() => { + return _this3.runScript(name, args); + }); } + } else if (e2.message === "UNKNOWN_CLIENT") { + return _this3.runScript("register_client", [_this3.instance.queued()]).then(() => { + return _this3.runScript(name, args); + }); } else { - throw new Error(`Unknown parameter "${key}"`); + return _this3.Promise.reject(e2); } - params[key] = value; - }); - }); - return configurations; - } - /** - * Decompress data. Concurrency limited. - * - * @param {Buffer} data Compressed data - * @param {Boolean} fin Specifies whether or not this is the last fragment - * @param {Function} callback Callback - * @public - */ - decompress(data, fin, callback) { - zlibLimiter.add((done) => { - this._decompress(data, fin, (err, result) => { - done(); - callback(err, result); - }); - }); - } - /** - * Compress data. Concurrency limited. - * - * @param {(Buffer|String)} data Data to compress - * @param {Boolean} fin Specifies whether or not this is the last fragment - * @param {Function} callback Callback - * @public - */ - compress(data, fin, callback) { - zlibLimiter.add((done) => { - this._compress(data, fin, (err, result) => { - done(); - callback(err, result); }); - }); + })(); } - /** - * Decompress data. - * - * @param {Buffer} data Compressed data - * @param {Boolean} fin Specifies whether or not this is the last fragment - * @param {Function} callback Callback - * @private - */ - _decompress(data, fin, callback) { - const endpoint = this._isServer ? "client" : "server"; - if (!this._inflate) { - const key = `${endpoint}_max_window_bits`; - const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; - this._inflate = zlib.createInflateRaw({ - ...this._options.zlibInflateOptions, - windowBits - }); - this._inflate[kPerMessageDeflate] = this; - this._inflate[kTotalLength] = 0; - this._inflate[kBuffers] = []; - this._inflate.on("error", inflateOnError); - this._inflate.on("data", inflateOnData); + prepareArray(arr) { + var i2, len, results, x3; + results = []; + for (i2 = 0, len = arr.length; i2 < len; i2++) { + x3 = arr[i2]; + results.push(x3 != null ? x3.toString() : ""); } - this._inflate[kCallback] = callback; - this._inflate.write(data); - if (fin) this._inflate.write(TRAILER); - this._inflate.flush(() => { - const err = this._inflate[kError]; - if (err) { - this._inflate.close(); - this._inflate = null; - callback(err); - return; - } - const data2 = bufferUtil.concat( - this._inflate[kBuffers], - this._inflate[kTotalLength] - ); - if (this._inflate._readableState.endEmitted) { - this._inflate.close(); - this._inflate = null; - } else { - this._inflate[kTotalLength] = 0; - this._inflate[kBuffers] = []; - if (fin && this.params[`${endpoint}_no_context_takeover`]) { - this._inflate.reset(); - } - } - callback(null, data2); - }); + return results; } - /** - * Compress data. - * - * @param {(Buffer|String)} data Data to compress - * @param {Boolean} fin Specifies whether or not this is the last fragment - * @param {Function} callback Callback - * @private - */ - _compress(data, fin, callback) { - const endpoint = this._isServer ? "server" : "client"; - if (!this._deflate) { - const key = `${endpoint}_max_window_bits`; - const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; - this._deflate = zlib.createDeflateRaw({ - ...this._options.zlibDeflateOptions, - windowBits - }); - this._deflate[kTotalLength] = 0; - this._deflate[kBuffers] = []; - this._deflate.on("data", deflateOnData); + prepareObject(obj) { + var arr, k, v2; + arr = []; + for (k in obj) { + v2 = obj[k]; + arr.push(k, v2 != null ? v2.toString() : ""); } - this._deflate[kCallback] = callback; - this._deflate.write(data); - this._deflate.flush(zlib.Z_SYNC_FLUSH, () => { - if (!this._deflate) { - return; - } - let data2 = bufferUtil.concat( - this._deflate[kBuffers], - this._deflate[kTotalLength] - ); - if (fin) data2 = data2.slice(0, data2.length - 4); - this._deflate[kCallback] = null; - this._deflate[kTotalLength] = 0; - this._deflate[kBuffers] = []; - if (fin && this.params[`${endpoint}_no_context_takeover`]) { - this._deflate.reset(); - } - callback(null, data2); - }); + return arr; } - }; - module14.exports = PerMessageDeflate; - function deflateOnData(chunk) { - this[kBuffers].push(chunk); - this[kTotalLength] += chunk.length; - } - function inflateOnData(chunk) { - this[kTotalLength] += chunk.length; - if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) { - this[kBuffers].push(chunk); - return; + prepareInitSettings(clear) { + var args; + args = this.prepareObject(Object.assign({}, this.storeOptions, { + id: this.originalId, + version: this.instance.version, + groupTimeout: this.timeout, + clientTimeout: this.clientTimeout + })); + args.unshift(clear ? 1 : 0, this.instance.version); + return args; } - this[kError] = new RangeError("Max payload size exceeded"); - this[kError].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"; - this[kError][kStatusCode] = 1009; - this.removeListener("data", inflateOnData); - this.reset(); - } - function inflateOnError(err) { - this[kPerMessageDeflate]._inflate = null; - err[kStatusCode] = 1007; - this[kCallback](err); - } - } -}); -var require_validation2 = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/validation.js"(exports2, module14) { - "use strict"; - var tokenChars = [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - // 0 - 15 - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - // 16 - 31 - 0, - 1, - 0, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 1, - 1, - 0, - 1, - 1, - 0, - // 32 - 47 - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - // 48 - 63 - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - // 64 - 79 - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - // 80 - 95 - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - // 96 - 111 - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 1, - 0, - 1, - 0 - // 112 - 127 - ]; - function isValidStatusCode(code2) { - return code2 >= 1e3 && code2 <= 1014 && code2 !== 1004 && code2 !== 1005 && code2 !== 1006 || code2 >= 3e3 && code2 <= 4999; - } - function _isValidUTF8(buf2) { - const len = buf2.length; - let i2 = 0; - while (i2 < len) { - if ((buf2[i2] & 128) === 0) { - i2++; - } else if ((buf2[i2] & 224) === 192) { - if (i2 + 1 === len || (buf2[i2 + 1] & 192) !== 128 || (buf2[i2] & 254) === 192) { - return false; + convertBool(b) { + return !!b; + } + __updateSettings__(options2) { + var _this4 = this; + return _asyncToGenerator2(function* () { + yield _this4.runScript("update_settings", _this4.prepareObject(options2)); + return parser3.overwrite(options2, options2, _this4.storeOptions); + })(); + } + __running__() { + return this.runScript("running", []); + } + __queued__() { + return this.runScript("queued", []); + } + __done__() { + return this.runScript("done", []); + } + __groupCheck__() { + var _this5 = this; + return _asyncToGenerator2(function* () { + return _this5.convertBool(yield _this5.runScript("group_check", [])); + })(); + } + __incrementReservoir__(incr) { + return this.runScript("increment_reservoir", [incr]); + } + __currentReservoir__() { + return this.runScript("current_reservoir", []); + } + __check__(weight) { + var _this6 = this; + return _asyncToGenerator2(function* () { + return _this6.convertBool(yield _this6.runScript("check", _this6.prepareArray([weight]))); + })(); + } + __register__(index, weight, expiration) { + var _this7 = this; + return _asyncToGenerator2(function* () { + var reservoir, success, wait; + var _ref4 = yield _this7.runScript("register", _this7.prepareArray([index, weight, expiration])); + var _ref5 = _slicedToArray2(_ref4, 3); + success = _ref5[0]; + wait = _ref5[1]; + reservoir = _ref5[2]; + return { + success: _this7.convertBool(success), + wait, + reservoir + }; + })(); + } + __submit__(queueLength, weight) { + var _this8 = this; + return _asyncToGenerator2(function* () { + var blocked, e2, maxConcurrent, overweight, reachedHWM, strategy; + try { + var _ref6 = yield _this8.runScript("submit", _this8.prepareArray([queueLength, weight])); + var _ref7 = _slicedToArray2(_ref6, 3); + reachedHWM = _ref7[0]; + blocked = _ref7[1]; + strategy = _ref7[2]; + return { + reachedHWM: _this8.convertBool(reachedHWM), + blocked: _this8.convertBool(blocked), + strategy + }; + } catch (error2) { + e2 = error2; + if (e2.message.indexOf("OVERWEIGHT") === 0) { + var _e$message$split = e2.message.split(":"); + var _e$message$split2 = _slicedToArray2(_e$message$split, 3); + overweight = _e$message$split2[0]; + weight = _e$message$split2[1]; + maxConcurrent = _e$message$split2[2]; + throw new BottleneckError(`Impossible to add a job having a weight of ${weight} to a limiter having a maxConcurrent setting of ${maxConcurrent}`); + } else { + throw e2; + } } - i2 += 2; - } else if ((buf2[i2] & 240) === 224) { - if (i2 + 2 >= len || (buf2[i2 + 1] & 192) !== 128 || (buf2[i2 + 2] & 192) !== 128 || buf2[i2] === 224 && (buf2[i2 + 1] & 224) === 128 || // Overlong - buf2[i2] === 237 && (buf2[i2 + 1] & 224) === 160) { - return false; + })(); + } + __free__(index, weight) { + var _this9 = this; + return _asyncToGenerator2(function* () { + var running; + running = yield _this9.runScript("free", _this9.prepareArray([index])); + return { + running + }; + })(); + } + }; + module14.exports = RedisDatastore; + } +}); +var require_States = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/States.js"(exports2, module14) { + "use strict"; + var BottleneckError; + var States; + BottleneckError = require_BottleneckError(); + States = class States { + constructor(status1) { + this.status = status1; + this._jobs = {}; + this.counts = this.status.map(function() { + return 0; + }); + } + next(id) { + var current, next; + current = this._jobs[id]; + next = current + 1; + if (current != null && next < this.status.length) { + this.counts[current]--; + this.counts[next]++; + return this._jobs[id]++; + } else if (current != null) { + this.counts[current]--; + return delete this._jobs[id]; + } + } + start(id) { + var initial; + initial = 0; + this._jobs[id] = initial; + return this.counts[initial]++; + } + remove(id) { + var current; + current = this._jobs[id]; + if (current != null) { + this.counts[current]--; + delete this._jobs[id]; + } + return current != null; + } + jobStatus(id) { + var ref; + return (ref = this.status[this._jobs[id]]) != null ? ref : null; + } + statusJobs(status) { + var k, pos, ref, results, v2; + if (status != null) { + pos = this.status.indexOf(status); + if (pos < 0) { + throw new BottleneckError(`status must be one of ${this.status.join(", ")}`); } - i2 += 3; - } else if ((buf2[i2] & 248) === 240) { - if (i2 + 3 >= len || (buf2[i2 + 1] & 192) !== 128 || (buf2[i2 + 2] & 192) !== 128 || (buf2[i2 + 3] & 192) !== 128 || buf2[i2] === 240 && (buf2[i2 + 1] & 240) === 128 || // Overlong - buf2[i2] === 244 && buf2[i2 + 1] > 143 || buf2[i2] > 244) { - return false; + ref = this._jobs; + results = []; + for (k in ref) { + v2 = ref[k]; + if (v2 === pos) { + results.push(k); + } } - i2 += 4; + return results; } else { - return false; + return Object.keys(this._jobs); } } - return true; - } - try { - const isValidUTF8 = __require2("utf-8-validate"); - module14.exports = { - isValidStatusCode, - isValidUTF8(buf2) { - return buf2.length < 150 ? _isValidUTF8(buf2) : isValidUTF8(buf2); - }, - tokenChars - }; - } catch (e2) { - module14.exports = { - isValidStatusCode, - isValidUTF8: _isValidUTF8, - tokenChars - }; - } + statusCounts() { + return this.counts.reduce((acc, v2, i2) => { + acc[this.status[i2]] = v2; + return acc; + }, {}); + } + }; + module14.exports = States; } }); -var require_receiver = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/receiver.js"(exports2, module14) { +var require_Sync = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Sync.js"(exports2, module14) { "use strict"; - var { Writable } = __require2("stream"); - var PerMessageDeflate = require_permessage_deflate(); - var { - BINARY_TYPES, - EMPTY_BUFFER, - kStatusCode, - kWebSocket - } = require_constants2(); - var { concat: concat2, toArrayBuffer, unmask } = require_buffer_util(); - var { isValidStatusCode, isValidUTF8 } = require_validation2(); - var GET_INFO = 0; - var GET_PAYLOAD_LENGTH_16 = 1; - var GET_PAYLOAD_LENGTH_64 = 2; - var GET_MASK = 3; - var GET_DATA = 4; - var INFLATING = 5; - var Receiver2 = class extends Writable { - /** - * Creates a Receiver instance. - * - * @param {Object} [options] Options object - * @param {String} [options.binaryType=nodebuffer] The type for binary data - * @param {Object} [options.extensions] An object containing the negotiated - * extensions - * @param {Boolean} [options.isServer=false] Specifies whether to operate in - * client or server mode - * @param {Number} [options.maxPayload=0] The maximum allowed message length - * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or - * not to skip UTF-8 validation for text and close messages - */ - constructor(options2 = {}) { - super(); - this._binaryType = options2.binaryType || BINARY_TYPES[0]; - this._extensions = options2.extensions || {}; - this._isServer = !!options2.isServer; - this._maxPayload = options2.maxPayload | 0; - this._skipUTF8Validation = !!options2.skipUTF8Validation; - this[kWebSocket] = void 0; - this._bufferedBytes = 0; - this._buffers = []; - this._compressed = false; - this._payloadLength = 0; - this._mask = void 0; - this._fragmented = 0; - this._masked = false; - this._fin = false; - this._opcode = 0; - this._totalPayloadLength = 0; - this._messageLength = 0; - this._fragments = []; - this._state = GET_INFO; - this._loop = false; + function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; } - /** - * Implements `Writable.prototype._write()`. - * - * @param {Buffer} chunk The chunk of data to write - * @param {String} encoding The character encoding of `chunk` - * @param {Function} cb Callback - * @private - */ - _write(chunk, encoding, cb) { - if (this._opcode === 8 && this._state == GET_INFO) return cb(); - this._bufferedBytes += chunk.length; - this._buffers.push(chunk); - this.startLoop(cb); + if (info.done) { + resolve82(value); + } else { + Promise.resolve(value).then(_next, _throw); } - /** - * Consumes `n` bytes from the buffered data. - * - * @param {Number} n The number of bytes to consume - * @return {Buffer} The consumed bytes - * @private - */ - consume(n) { - this._bufferedBytes -= n; - if (n === this._buffers[0].length) return this._buffers.shift(); - if (n < this._buffers[0].length) { - const buf2 = this._buffers[0]; - this._buffers[0] = buf2.slice(n); - return buf2.slice(0, n); - } - const dst = Buffer.allocUnsafe(n); - do { - const buf2 = this._buffers[0]; - const offset = dst.length - n; - if (n >= buf2.length) { - dst.set(this._buffers.shift(), offset); - } else { - dst.set(new Uint8Array(buf2.buffer, buf2.byteOffset, n), offset); - this._buffers[0] = buf2.slice(n); + } + function _asyncToGenerator2(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); } - n -= buf2.length; - } while (n > 0); - return dst; + function _throw(err) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + } + _next(void 0); + }); + }; + } + var DLList; + var Sync; + DLList = require_DLList(); + Sync = class Sync { + constructor(name, Promise2) { + this.schedule = this.schedule.bind(this); + this.name = name; + this.Promise = Promise2; + this._running = 0; + this._queue = new DLList(); } - /** - * Starts the parsing loop. - * - * @param {Function} cb Callback - * @private - */ - startLoop(cb) { - let err; - this._loop = true; - do { - switch (this._state) { - case GET_INFO: - err = this.getInfo(); - break; - case GET_PAYLOAD_LENGTH_16: - err = this.getPayloadLength16(); - break; - case GET_PAYLOAD_LENGTH_64: - err = this.getPayloadLength64(); - break; - case GET_MASK: - this.getMask(); - break; - case GET_DATA: - err = this.getData(cb); - break; - default: - this._loop = false; - return; + isEmpty() { + return this._queue.length === 0; + } + _tryToRun() { + var _this = this; + return _asyncToGenerator2(function* () { + var args, cb, error2, reject, resolve82, returned, task; + if (_this._running < 1 && _this._queue.length > 0) { + _this._running++; + var _this$_queue$shift = _this._queue.shift(); + task = _this$_queue$shift.task; + args = _this$_queue$shift.args; + resolve82 = _this$_queue$shift.resolve; + reject = _this$_queue$shift.reject; + cb = yield _asyncToGenerator2(function* () { + try { + returned = yield task(...args); + return function() { + return resolve82(returned); + }; + } catch (error1) { + error2 = error1; + return function() { + return reject(error2); + }; + } + })(); + _this._running--; + _this._tryToRun(); + return cb(); } - } while (this._loop); - cb(err); + })(); } - /** - * Reads the first two bytes of a frame. - * - * @return {(RangeError|undefined)} A possible error - * @private - */ - getInfo() { - if (this._bufferedBytes < 2) { - this._loop = false; - return; - } - const buf2 = this.consume(2); - if ((buf2[0] & 48) !== 0) { - this._loop = false; - return error2( - RangeError, - "RSV2 and RSV3 must be clear", - true, - 1002, - "WS_ERR_UNEXPECTED_RSV_2_3" - ); + schedule(task, ...args) { + var promise, reject, resolve82; + resolve82 = reject = null; + promise = new this.Promise(function(_resolve, _reject) { + resolve82 = _resolve; + return reject = _reject; + }); + this._queue.push({ + task, + args, + resolve: resolve82, + reject + }); + this._tryToRun(); + return promise; + } + }; + module14.exports = Sync; + } +}); +var require_version = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/version.json"(exports2, module14) { + module14.exports = { version: "2.19.5" }; + } +}); +var require_Group = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Group.js"(exports2, module14) { + "use strict"; + function _slicedToArray2(arr, i2) { + return _arrayWithHoles2(arr) || _iterableToArrayLimit2(arr, i2) || _nonIterableRest2(); + } + function _nonIterableRest2() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + function _iterableToArrayLimit2(arr, i2) { + var _arr = []; + var _n = true; + var _d = false; + var _e = void 0; + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + if (i2 && _arr.length === i2) break; } - const compressed = (buf2[0] & 64) === 64; - if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { - this._loop = false; - return error2( - RangeError, - "RSV1 must be clear", - true, - 1002, - "WS_ERR_UNEXPECTED_RSV_1" - ); + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; } - this._fin = (buf2[0] & 128) === 128; - this._opcode = buf2[0] & 15; - this._payloadLength = buf2[1] & 127; - if (this._opcode === 0) { - if (compressed) { - this._loop = false; - return error2( - RangeError, - "RSV1 must be clear", - true, - 1002, - "WS_ERR_UNEXPECTED_RSV_1" - ); - } - if (!this._fragmented) { - this._loop = false; - return error2( - RangeError, - "invalid opcode 0", - true, - 1002, - "WS_ERR_INVALID_OPCODE" - ); - } - this._opcode = this._fragmented; - } else if (this._opcode === 1 || this._opcode === 2) { - if (this._fragmented) { - this._loop = false; - return error2( - RangeError, - `invalid opcode ${this._opcode}`, - true, - 1002, - "WS_ERR_INVALID_OPCODE" - ); - } - this._compressed = compressed; - } else if (this._opcode > 7 && this._opcode < 11) { - if (!this._fin) { - this._loop = false; - return error2( - RangeError, - "FIN must be set", - true, - 1002, - "WS_ERR_EXPECTED_FIN" - ); + } + return _arr; + } + function _arrayWithHoles2(arr) { + if (Array.isArray(arr)) return arr; + } + function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; + } + if (info.done) { + resolve82(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + function _asyncToGenerator2(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); } - if (compressed) { - this._loop = false; - return error2( - RangeError, - "RSV1 must be clear", - true, - 1002, - "WS_ERR_UNEXPECTED_RSV_1" - ); + function _throw(err) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); } - if (this._payloadLength > 125) { - this._loop = false; - return error2( - RangeError, - `invalid payload length ${this._payloadLength}`, - true, - 1002, - "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH" - ); + _next(void 0); + }); + }; + } + var Events2; + var Group; + var IORedisConnection2; + var RedisConnection2; + var Scripts2; + var parser3; + parser3 = require_parser2(); + Events2 = require_Events(); + RedisConnection2 = require_RedisConnection(); + IORedisConnection2 = require_IORedisConnection(); + Scripts2 = require_Scripts(); + Group = function() { + class Group2 { + constructor(limiterOptions = {}) { + this.deleteKey = this.deleteKey.bind(this); + this.limiterOptions = limiterOptions; + parser3.load(this.limiterOptions, this.defaults, this); + this.Events = new Events2(this); + this.instances = {}; + this.Bottleneck = require_Bottleneck(); + this._startAutoCleanup(); + this.sharedConnection = this.connection != null; + if (this.connection == null) { + if (this.limiterOptions.datastore === "redis") { + this.connection = new RedisConnection2(Object.assign({}, this.limiterOptions, { + Events: this.Events + })); + } else if (this.limiterOptions.datastore === "ioredis") { + this.connection = new IORedisConnection2(Object.assign({}, this.limiterOptions, { + Events: this.Events + })); + } } - } else { - this._loop = false; - return error2( - RangeError, - `invalid opcode ${this._opcode}`, - true, - 1002, - "WS_ERR_INVALID_OPCODE" - ); } - if (!this._fin && !this._fragmented) this._fragmented = this._opcode; - this._masked = (buf2[1] & 128) === 128; - if (this._isServer) { - if (!this._masked) { - this._loop = false; - return error2( - RangeError, - "MASK must be set", - true, - 1002, - "WS_ERR_EXPECTED_MASK" - ); + key(key = "") { + var ref; + return (ref = this.instances[key]) != null ? ref : (() => { + var limiter; + limiter = this.instances[key] = new this.Bottleneck(Object.assign(this.limiterOptions, { + id: `${this.id}-${key}`, + timeout: this.timeout, + connection: this.connection + })); + this.Events.trigger("created", limiter, key); + return limiter; + })(); + } + deleteKey(key = "") { + var _this = this; + return _asyncToGenerator2(function* () { + var deleted, instance; + instance = _this.instances[key]; + if (_this.connection) { + deleted = yield _this.connection.__runCommand__(["del", ...Scripts2.allKeys(`${_this.id}-${key}`)]); + } + if (instance != null) { + delete _this.instances[key]; + yield instance.disconnect(); + } + return instance != null || deleted > 0; + })(); + } + limiters() { + var k, ref, results, v2; + ref = this.instances; + results = []; + for (k in ref) { + v2 = ref[k]; + results.push({ + key: k, + limiter: v2 + }); } - } else if (this._masked) { - this._loop = false; - return error2( - RangeError, - "MASK must be clear", - true, - 1002, - "WS_ERR_UNEXPECTED_MASK" - ); + return results; } - if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16; - else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64; - else return this.haveLength(); - } - /** - * Gets extended payload length (7+16). - * - * @return {(RangeError|undefined)} A possible error - * @private - */ - getPayloadLength16() { - if (this._bufferedBytes < 2) { - this._loop = false; - return; + keys() { + return Object.keys(this.instances); } - this._payloadLength = this.consume(2).readUInt16BE(0); - return this.haveLength(); - } - /** - * Gets extended payload length (7+64). - * - * @return {(RangeError|undefined)} A possible error - * @private - */ - getPayloadLength64() { - if (this._bufferedBytes < 8) { - this._loop = false; - return; + clusterKeys() { + var _this2 = this; + return _asyncToGenerator2(function* () { + var cursor, end, found, i2, k, keys, len, next, start; + if (_this2.connection == null) { + return _this2.Promise.resolve(_this2.keys()); + } + keys = []; + cursor = null; + start = `b_${_this2.id}-`.length; + end = "_settings".length; + while (cursor !== 0) { + var _ref = yield _this2.connection.__runCommand__(["scan", cursor != null ? cursor : 0, "match", `b_${_this2.id}-*_settings`, "count", 1e4]); + var _ref2 = _slicedToArray2(_ref, 2); + next = _ref2[0]; + found = _ref2[1]; + cursor = ~~next; + for (i2 = 0, len = found.length; i2 < len; i2++) { + k = found[i2]; + keys.push(k.slice(start, -end)); + } + } + return keys; + })(); } - const buf2 = this.consume(8); - const num = buf2.readUInt32BE(0); - if (num > Math.pow(2, 53 - 32) - 1) { - this._loop = false; - return error2( - RangeError, - "Unsupported WebSocket frame: payload length > 2^53 - 1", - false, - 1009, - "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH" - ); + _startAutoCleanup() { + var _this3 = this; + var base2; + clearInterval(this.interval); + return typeof (base2 = this.interval = setInterval( + /* @__PURE__ */ _asyncToGenerator2(function* () { + var e2, k, ref, results, time3, v2; + time3 = Date.now(); + ref = _this3.instances; + results = []; + for (k in ref) { + v2 = ref[k]; + try { + if (yield v2._store.__groupCheck__(time3)) { + results.push(_this3.deleteKey(k)); + } else { + results.push(void 0); + } + } catch (error2) { + e2 = error2; + results.push(v2.Events.trigger("error", e2)); + } + } + return results; + }), + this.timeout / 2 + )).unref === "function" ? base2.unref() : void 0; } - this._payloadLength = num * Math.pow(2, 32) + buf2.readUInt32BE(4); - return this.haveLength(); - } - /** - * Payload length has been read. - * - * @return {(RangeError|undefined)} A possible error - * @private - */ - haveLength() { - if (this._payloadLength && this._opcode < 8) { - this._totalPayloadLength += this._payloadLength; - if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { - this._loop = false; - return error2( - RangeError, - "Max payload size exceeded", - false, - 1009, - "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH" - ); + updateSettings(options2 = {}) { + parser3.overwrite(options2, this.defaults, this); + parser3.overwrite(options2, options2, this.limiterOptions); + if (options2.timeout != null) { + return this._startAutoCleanup(); } } - if (this._masked) this._state = GET_MASK; - else this._state = GET_DATA; - } - /** - * Reads mask bytes. - * - * @private - */ - getMask() { - if (this._bufferedBytes < 4) { - this._loop = false; - return; + disconnect(flush = true) { + var ref; + if (!this.sharedConnection) { + return (ref = this.connection) != null ? ref.disconnect(flush) : void 0; + } } - this._mask = this.consume(4); - this._state = GET_DATA; } - /** - * Reads data bytes. - * - * @param {Function} cb Callback - * @return {(Error|RangeError|undefined)} A possible error - * @private - */ - getData(cb) { - let data = EMPTY_BUFFER; - if (this._payloadLength) { - if (this._bufferedBytes < this._payloadLength) { - this._loop = false; - return; - } - data = this.consume(this._payloadLength); - if (this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0) { - unmask(data, this._mask); - } + ; + Group2.prototype.defaults = { + timeout: 1e3 * 60 * 5, + connection: null, + Promise, + id: "group-key" + }; + return Group2; + }.call(void 0); + module14.exports = Group; + } +}); +var require_Batcher = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Batcher.js"(exports2, module14) { + "use strict"; + var Batcher; + var Events2; + var parser3; + parser3 = require_parser2(); + Events2 = require_Events(); + Batcher = function() { + class Batcher2 { + constructor(options2 = {}) { + this.options = options2; + parser3.load(this.options, this.defaults, this); + this.Events = new Events2(this); + this._arr = []; + this._resetPromise(); + this._lastFlush = Date.now(); } - if (this._opcode > 7) return this.controlMessage(data); - if (this._compressed) { - this._state = INFLATING; - this.decompress(data, cb); - return; + _resetPromise() { + return this._promise = new this.Promise((res, rej) => { + return this._resolve = res; + }); } - if (data.length) { - this._messageLength = this._totalPayloadLength; - this._fragments.push(data); + _flush() { + clearTimeout(this._timeout); + this._lastFlush = Date.now(); + this._resolve(); + this.Events.trigger("batch", this._arr); + this._arr = []; + return this._resetPromise(); } - return this.dataMessage(); - } - /** - * Decompresses data. - * - * @param {Buffer} data Compressed data - * @param {Function} cb Callback - * @private - */ - decompress(data, cb) { - const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; - perMessageDeflate.decompress(data, this._fin, (err, buf2) => { - if (err) return cb(err); - if (buf2.length) { - this._messageLength += buf2.length; - if (this._messageLength > this._maxPayload && this._maxPayload > 0) { - return cb( - error2( - RangeError, - "Max payload size exceeded", - false, - 1009, - "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH" - ) - ); - } - this._fragments.push(buf2); + add(data) { + var ret; + this._arr.push(data); + ret = this._promise; + if (this._arr.length === this.maxSize) { + this._flush(); + } else if (this.maxTime != null && this._arr.length === 1) { + this._timeout = setTimeout(() => { + return this._flush(); + }, this.maxTime); } - const er = this.dataMessage(); - if (er) return cb(er); - this.startLoop(cb); - }); + return ret; + } } - /** - * Handles a data message. - * - * @return {(Error|undefined)} A possible error - * @private - */ - dataMessage() { - if (this._fin) { - const messageLength = this._messageLength; - const fragments = this._fragments; - this._totalPayloadLength = 0; - this._messageLength = 0; - this._fragmented = 0; - this._fragments = []; - if (this._opcode === 2) { - let data; - if (this._binaryType === "nodebuffer") { - data = concat2(fragments, messageLength); - } else if (this._binaryType === "arraybuffer") { - data = toArrayBuffer(concat2(fragments, messageLength)); - } else { - data = fragments; - } - this.emit("message", data, true); - } else { - const buf2 = concat2(fragments, messageLength); - if (!this._skipUTF8Validation && !isValidUTF8(buf2)) { - this._loop = false; - return error2( - Error, - "invalid UTF-8 sequence", - true, - 1007, - "WS_ERR_INVALID_UTF8" - ); - } - this.emit("message", buf2, false); - } + ; + Batcher2.prototype.defaults = { + maxTime: null, + maxSize: null, + Promise + }; + return Batcher2; + }.call(void 0); + module14.exports = Batcher; + } +}); +var require_Bottleneck = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Bottleneck.js"(exports2, module14) { + "use strict"; + function _slicedToArray2(arr, i2) { + return _arrayWithHoles2(arr) || _iterableToArrayLimit2(arr, i2) || _nonIterableRest2(); + } + function _iterableToArrayLimit2(arr, i2) { + var _arr = []; + var _n = true; + var _d = false; + var _e = void 0; + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + if (i2 && _arr.length === i2) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; } - this._state = GET_INFO; } - /** - * Handles a control message. - * - * @param {Buffer} data Data to handle - * @return {(Error|RangeError|undefined)} A possible error - * @private - */ - controlMessage(data) { - if (this._opcode === 8) { - this._loop = false; - if (data.length === 0) { - this.emit("conclude", 1005, EMPTY_BUFFER); - this.end(); - } else if (data.length === 1) { - return error2( - RangeError, - "invalid payload length 1", - true, - 1002, - "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH" - ); - } else { - const code2 = data.readUInt16BE(0); - if (!isValidStatusCode(code2)) { - return error2( - RangeError, - `invalid status code ${code2}`, - true, - 1002, - "WS_ERR_INVALID_CLOSE_CODE" - ); - } - const buf2 = data.slice(2); - if (!this._skipUTF8Validation && !isValidUTF8(buf2)) { - return error2( - Error, - "invalid UTF-8 sequence", - true, - 1007, - "WS_ERR_INVALID_UTF8" - ); + return _arr; + } + function _toArray(arr) { + return _arrayWithHoles2(arr) || _iterableToArray(arr) || _nonIterableRest2(); + } + function _nonIterableRest2() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } + function _arrayWithHoles2(arr) { + if (Array.isArray(arr)) return arr; + } + function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error2) { + reject(error2); + return; + } + if (info.done) { + resolve82(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + function _asyncToGenerator2(fn) { + return function() { + var self2 = this, args = arguments; + return new Promise(function(resolve82, reject) { + var gen = fn.apply(self2, args); + function _next(value) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); + } + function _throw(err) { + asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + } + _next(void 0); + }); + }; + } + var Bottleneck2; + var DEFAULT_PRIORITY; + var Events2; + var Job; + var LocalDatastore; + var NUM_PRIORITIES; + var Queues; + var RedisDatastore; + var States; + var Sync; + var parser3; + var splice = [].splice; + NUM_PRIORITIES = 10; + DEFAULT_PRIORITY = 5; + parser3 = require_parser2(); + Queues = require_Queues(); + Job = require_Job(); + LocalDatastore = require_LocalDatastore(); + RedisDatastore = require_RedisDatastore(); + Events2 = require_Events(); + States = require_States(); + Sync = require_Sync(); + Bottleneck2 = function() { + class Bottleneck3 { + constructor(options2 = {}, ...invalid) { + var storeInstanceOptions, storeOptions; + this._addToQueue = this._addToQueue.bind(this); + this._validateOptions(options2, invalid); + parser3.load(options2, this.instanceDefaults, this); + this._queues = new Queues(NUM_PRIORITIES); + this._scheduled = {}; + this._states = new States(["RECEIVED", "QUEUED", "RUNNING", "EXECUTING"].concat(this.trackDoneStatus ? ["DONE"] : [])); + this._limiter = null; + this.Events = new Events2(this); + this._submitLock = new Sync("submit", this.Promise); + this._registerLock = new Sync("register", this.Promise); + storeOptions = parser3.load(options2, this.storeDefaults, {}); + this._store = function() { + if (this.datastore === "redis" || this.datastore === "ioredis" || this.connection != null) { + storeInstanceOptions = parser3.load(options2, this.redisStoreDefaults, {}); + return new RedisDatastore(this, storeOptions, storeInstanceOptions); + } else if (this.datastore === "local") { + storeInstanceOptions = parser3.load(options2, this.localStoreDefaults, {}); + return new LocalDatastore(this, storeOptions, storeInstanceOptions); + } else { + throw new Bottleneck3.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`); } - this.emit("conclude", code2, buf2); - this.end(); + }.call(this); + this._queues.on("leftzero", () => { + var ref; + return (ref = this._store.heartbeat) != null ? typeof ref.ref === "function" ? ref.ref() : void 0 : void 0; + }); + this._queues.on("zero", () => { + var ref; + return (ref = this._store.heartbeat) != null ? typeof ref.unref === "function" ? ref.unref() : void 0 : void 0; + }); + } + _validateOptions(options2, invalid) { + if (!(options2 != null && typeof options2 === "object" && invalid.length === 0)) { + throw new Bottleneck3.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1."); } - } else if (this._opcode === 9) { - this.emit("ping", data); - } else { - this.emit("pong", data); } - this._state = GET_INFO; - } - }; - module14.exports = Receiver2; - function error2(ErrorCtor, message, prefix, statusCode, errorCode) { - const err = new ErrorCtor( - prefix ? `Invalid WebSocket frame: ${message}` : message - ); - Error.captureStackTrace(err, error2); - err.code = errorCode; - err[kStatusCode] = statusCode; - return err; - } - } -}); -var require_sender = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/sender.js"(exports2, module14) { - "use strict"; - var net = __require2("net"); - var tls = __require2("tls"); - var { randomFillSync } = __require2("crypto"); - var PerMessageDeflate = require_permessage_deflate(); - var { EMPTY_BUFFER } = require_constants2(); - var { isValidStatusCode } = require_validation2(); - var { mask: applyMask, toBuffer } = require_buffer_util(); - var kByteLength = Symbol("kByteLength"); - var maskBuffer = Buffer.alloc(4); - var Sender2 = class _Sender { - /** - * Creates a Sender instance. - * - * @param {(net.Socket|tls.Socket)} socket The connection socket - * @param {Object} [extensions] An object containing the negotiated extensions - * @param {Function} [generateMask] The function used to generate the masking - * key - */ - constructor(socket, extensions, generateMask) { - this._extensions = extensions || {}; - if (generateMask) { - this._generateMask = generateMask; - this._maskBuffer = Buffer.alloc(4); + ready() { + return this._store.ready; } - this._socket = socket; - this._firstFragment = true; - this._compress = false; - this._bufferedBytes = 0; - this._deflating = false; - this._queue = []; - } - /** - * Frames a piece of data according to the HyBi WebSocket protocol. - * - * @param {(Buffer|String)} data The data to frame - * @param {Object} options Options object - * @param {Boolean} [options.fin=false] Specifies whether or not to set the - * FIN bit - * @param {Function} [options.generateMask] The function used to generate the - * masking key - * @param {Boolean} [options.mask=false] Specifies whether or not to mask - * `data` - * @param {Buffer} [options.maskBuffer] The buffer used to store the masking - * key - * @param {Number} options.opcode The opcode - * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be - * modified - * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the - * RSV1 bit - * @return {(Buffer|String)[]} The framed data - * @public - */ - static frame(data, options2) { - let mask; - let merge3 = false; - let offset = 2; - let skipMasking = false; - if (options2.mask) { - mask = options2.maskBuffer || maskBuffer; - if (options2.generateMask) { - options2.generateMask(mask); - } else { - randomFillSync(mask, 0, 4); - } - skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0; - offset = 6; + clients() { + return this._store.clients; } - let dataLength; - if (typeof data === "string") { - if ((!options2.mask || skipMasking) && options2[kByteLength] !== void 0) { - dataLength = options2[kByteLength]; - } else { - data = Buffer.from(data); - dataLength = data.length; - } - } else { - dataLength = data.length; - merge3 = options2.mask && options2.readOnly && !skipMasking; + channel() { + return `b_${this.id}`; } - let payloadLength = dataLength; - if (dataLength >= 65536) { - offset += 8; - payloadLength = 127; - } else if (dataLength > 125) { - offset += 2; - payloadLength = 126; + channel_client() { + return `b_${this.id}_${this._store.clientId}`; } - const target = Buffer.allocUnsafe(merge3 ? dataLength + offset : offset); - target[0] = options2.fin ? options2.opcode | 128 : options2.opcode; - if (options2.rsv1) target[0] |= 64; - target[1] = payloadLength; - if (payloadLength === 126) { - target.writeUInt16BE(dataLength, 2); - } else if (payloadLength === 127) { - target[2] = target[3] = 0; - target.writeUIntBE(dataLength, 4, 6); + publish(message) { + return this._store.__publish__(message); } - if (!options2.mask) return [target, data]; - target[1] |= 128; - target[offset - 4] = mask[0]; - target[offset - 3] = mask[1]; - target[offset - 2] = mask[2]; - target[offset - 1] = mask[3]; - if (skipMasking) return [target, data]; - if (merge3) { - applyMask(data, mask, target, offset, dataLength); - return [target]; + disconnect(flush = true) { + return this._store.__disconnect__(flush); } - applyMask(data, mask, data, 0, dataLength); - return [target, data]; - } - /** - * Sends a close message to the other peer. - * - * @param {Number} [code] The status code component of the body - * @param {(String|Buffer)} [data] The message component of the body - * @param {Boolean} [mask=false] Specifies whether or not to mask the message - * @param {Function} [cb] Callback - * @public - */ - close(code2, data, mask, cb) { - let buf2; - if (code2 === void 0) { - buf2 = EMPTY_BUFFER; - } else if (typeof code2 !== "number" || !isValidStatusCode(code2)) { - throw new TypeError("First argument must be a valid error code number"); - } else if (data === void 0 || !data.length) { - buf2 = Buffer.allocUnsafe(2); - buf2.writeUInt16BE(code2, 0); - } else { - const length2 = Buffer.byteLength(data); - if (length2 > 123) { - throw new RangeError("The message must not be greater than 123 bytes"); - } - buf2 = Buffer.allocUnsafe(2 + length2); - buf2.writeUInt16BE(code2, 0); - if (typeof data === "string") { - buf2.write(data, 2); - } else { - buf2.set(data, 2); - } + chain(_limiter) { + this._limiter = _limiter; + return this; } - const options2 = { - [kByteLength]: buf2.length, - fin: true, - generateMask: this._generateMask, - mask, - maskBuffer: this._maskBuffer, - opcode: 8, - readOnly: false, - rsv1: false - }; - if (this._deflating) { - this.enqueue([this.dispatch, buf2, false, options2, cb]); - } else { - this.sendFrame(_Sender.frame(buf2, options2), cb); + queued(priority) { + return this._queues.queued(priority); } - } - /** - * Sends a ping message to the other peer. - * - * @param {*} data The message to send - * @param {Boolean} [mask=false] Specifies whether or not to mask `data` - * @param {Function} [cb] Callback - * @public - */ - ping(data, mask, cb) { - let byteLength; - let readOnly; - if (typeof data === "string") { - byteLength = Buffer.byteLength(data); - readOnly = false; - } else { - data = toBuffer(data); - byteLength = data.length; - readOnly = toBuffer.readOnly; + clusterQueued() { + return this._store.__queued__(); } - if (byteLength > 125) { - throw new RangeError("The data size must not be greater than 125 bytes"); + empty() { + return this.queued() === 0 && this._submitLock.isEmpty(); } - const options2 = { - [kByteLength]: byteLength, - fin: true, - generateMask: this._generateMask, - mask, - maskBuffer: this._maskBuffer, - opcode: 9, - readOnly, - rsv1: false - }; - if (this._deflating) { - this.enqueue([this.dispatch, data, false, options2, cb]); - } else { - this.sendFrame(_Sender.frame(data, options2), cb); + running() { + return this._store.__running__(); } - } - /** - * Sends a pong message to the other peer. - * - * @param {*} data The message to send - * @param {Boolean} [mask=false] Specifies whether or not to mask `data` - * @param {Function} [cb] Callback - * @public - */ - pong(data, mask, cb) { - let byteLength; - let readOnly; - if (typeof data === "string") { - byteLength = Buffer.byteLength(data); - readOnly = false; - } else { - data = toBuffer(data); - byteLength = data.length; - readOnly = toBuffer.readOnly; + done() { + return this._store.__done__(); } - if (byteLength > 125) { - throw new RangeError("The data size must not be greater than 125 bytes"); + jobStatus(id) { + return this._states.jobStatus(id); } - const options2 = { - [kByteLength]: byteLength, - fin: true, - generateMask: this._generateMask, - mask, - maskBuffer: this._maskBuffer, - opcode: 10, - readOnly, - rsv1: false - }; - if (this._deflating) { - this.enqueue([this.dispatch, data, false, options2, cb]); - } else { - this.sendFrame(_Sender.frame(data, options2), cb); + jobs(status) { + return this._states.statusJobs(status); } - } - /** - * Sends a data message to the other peer. - * - * @param {*} data The message to send - * @param {Object} options Options object - * @param {Boolean} [options.binary=false] Specifies whether `data` is binary - * or text - * @param {Boolean} [options.compress=false] Specifies whether or not to - * compress `data` - * @param {Boolean} [options.fin=false] Specifies whether the fragment is the - * last one - * @param {Boolean} [options.mask=false] Specifies whether or not to mask - * `data` - * @param {Function} [cb] Callback - * @public - */ - send(data, options2, cb) { - const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; - let opcode = options2.binary ? 2 : 1; - let rsv1 = options2.compress; - let byteLength; - let readOnly; - if (typeof data === "string") { - byteLength = Buffer.byteLength(data); - readOnly = false; - } else { - data = toBuffer(data); - byteLength = data.length; - readOnly = toBuffer.readOnly; + counts() { + return this._states.statusCounts(); + } + _randomIndex() { + return Math.random().toString(36).slice(2); + } + check(weight = 1) { + return this._store.__check__(weight); + } + _clearGlobalState(index) { + if (this._scheduled[index] != null) { + clearTimeout(this._scheduled[index].expiration); + delete this._scheduled[index]; + return true; + } else { + return false; + } + } + _free(index, job, options2, eventInfo) { + var _this = this; + return _asyncToGenerator2(function* () { + var e2, running; + try { + var _ref = yield _this._store.__free__(index, options2.weight); + running = _ref.running; + _this.Events.trigger("debug", `Freed ${options2.id}`, eventInfo); + if (running === 0 && _this.empty()) { + return _this.Events.trigger("idle"); + } + } catch (error1) { + e2 = error1; + return _this.Events.trigger("error", e2); + } + })(); + } + _run(index, job, wait) { + var clearGlobalState, free, run2; + job.doRun(); + clearGlobalState = this._clearGlobalState.bind(this, index); + run2 = this._run.bind(this, index, job); + free = this._free.bind(this, index, job); + return this._scheduled[index] = { + timeout: setTimeout(() => { + return job.doExecute(this._limiter, clearGlobalState, run2, free); + }, wait), + expiration: job.options.expiration != null ? setTimeout(function() { + return job.doExpire(clearGlobalState, run2, free); + }, wait + job.options.expiration) : void 0, + job + }; + } + _drainOne(capacity) { + return this._registerLock.schedule(() => { + var args, index, next, options2, queue; + if (this.queued() === 0) { + return this.Promise.resolve(null); + } + queue = this._queues.getFirst(); + var _next2 = next = queue.first(); + options2 = _next2.options; + args = _next2.args; + if (capacity != null && options2.weight > capacity) { + return this.Promise.resolve(null); + } + this.Events.trigger("debug", `Draining ${options2.id}`, { + args, + options: options2 + }); + index = this._randomIndex(); + return this._store.__register__(index, options2.weight, options2.expiration).then(({ + success, + wait, + reservoir + }) => { + var empty2; + this.Events.trigger("debug", `Drained ${options2.id}`, { + success, + args, + options: options2 + }); + if (success) { + queue.shift(); + empty2 = this.empty(); + if (empty2) { + this.Events.trigger("empty"); + } + if (reservoir === 0) { + this.Events.trigger("depleted", empty2); + } + this._run(index, next, wait); + return this.Promise.resolve(options2.weight); + } else { + return this.Promise.resolve(null); + } + }); + }); + } + _drainAll(capacity, total = 0) { + return this._drainOne(capacity).then((drained) => { + var newCapacity; + if (drained != null) { + newCapacity = capacity != null ? capacity - drained : capacity; + return this._drainAll(newCapacity, total + drained); + } else { + return this.Promise.resolve(total); + } + }).catch((e2) => { + return this.Events.trigger("error", e2); + }); + } + _dropAllQueued(message) { + return this._queues.shiftAll(function(job) { + return job.doDrop({ + message + }); + }); + } + stop(options2 = {}) { + var done, waitForExecuting; + options2 = parser3.load(options2, this.stopDefaults); + waitForExecuting = (at) => { + var finished; + finished = () => { + var counts; + counts = this._states.counts; + return counts[0] + counts[1] + counts[2] + counts[3] === at; + }; + return new this.Promise((resolve82, reject) => { + if (finished()) { + return resolve82(); + } else { + return this.on("done", () => { + if (finished()) { + this.removeAllListeners("done"); + return resolve82(); + } + }); + } + }); + }; + done = options2.dropWaitingJobs ? (this._run = function(index, next) { + return next.doDrop({ + message: options2.dropErrorMessage + }); + }, this._drainOne = () => { + return this.Promise.resolve(null); + }, this._registerLock.schedule(() => { + return this._submitLock.schedule(() => { + var k, ref, v2; + ref = this._scheduled; + for (k in ref) { + v2 = ref[k]; + if (this.jobStatus(v2.job.options.id) === "RUNNING") { + clearTimeout(v2.timeout); + clearTimeout(v2.expiration); + v2.job.doDrop({ + message: options2.dropErrorMessage + }); + } + } + this._dropAllQueued(options2.dropErrorMessage); + return waitForExecuting(0); + }); + })) : this.schedule({ + priority: NUM_PRIORITIES - 1, + weight: 0 + }, () => { + return waitForExecuting(1); + }); + this._receive = function(job) { + return job._reject(new Bottleneck3.prototype.BottleneckError(options2.enqueueErrorMessage)); + }; + this.stop = () => { + return this.Promise.reject(new Bottleneck3.prototype.BottleneckError("stop() has already been called")); + }; + return done; } - if (this._firstFragment) { - this._firstFragment = false; - if (rsv1 && perMessageDeflate && perMessageDeflate.params[perMessageDeflate._isServer ? "server_no_context_takeover" : "client_no_context_takeover"]) { - rsv1 = byteLength >= perMessageDeflate._threshold; + _addToQueue(job) { + var _this2 = this; + return _asyncToGenerator2(function* () { + var args, blocked, error2, options2, reachedHWM, shifted, strategy; + args = job.args; + options2 = job.options; + try { + var _ref2 = yield _this2._store.__submit__(_this2.queued(), options2.weight); + reachedHWM = _ref2.reachedHWM; + blocked = _ref2.blocked; + strategy = _ref2.strategy; + } catch (error1) { + error2 = error1; + _this2.Events.trigger("debug", `Could not queue ${options2.id}`, { + args, + options: options2, + error: error2 + }); + job.doDrop({ + error: error2 + }); + return false; + } + if (blocked) { + job.doDrop(); + return true; + } else if (reachedHWM) { + shifted = strategy === Bottleneck3.prototype.strategy.LEAK ? _this2._queues.shiftLastFrom(options2.priority) : strategy === Bottleneck3.prototype.strategy.OVERFLOW_PRIORITY ? _this2._queues.shiftLastFrom(options2.priority + 1) : strategy === Bottleneck3.prototype.strategy.OVERFLOW ? job : void 0; + if (shifted != null) { + shifted.doDrop(); + } + if (shifted == null || strategy === Bottleneck3.prototype.strategy.OVERFLOW) { + if (shifted == null) { + job.doDrop(); + } + return reachedHWM; + } + } + job.doQueue(reachedHWM, blocked); + _this2._queues.push(job); + yield _this2._drainAll(); + return reachedHWM; + })(); + } + _receive(job) { + if (this._states.jobStatus(job.options.id) != null) { + job._reject(new Bottleneck3.prototype.BottleneckError(`A job with the same id already exists (id=${job.options.id})`)); + return false; + } else { + job.doReceive(); + return this._submitLock.schedule(this._addToQueue, job); } - this._compress = rsv1; - } else { - rsv1 = false; - opcode = 0; } - if (options2.fin) this._firstFragment = true; - if (perMessageDeflate) { - const opts = { - [kByteLength]: byteLength, - fin: options2.fin, - generateMask: this._generateMask, - mask: options2.mask, - maskBuffer: this._maskBuffer, - opcode, - readOnly, - rsv1 + submit(...args) { + var cb, fn, job, options2, ref, ref1, task; + if (typeof args[0] === "function") { + var _ref3, _ref4, _splice$call, _splice$call2; + ref = args, _ref3 = ref, _ref4 = _toArray(_ref3), fn = _ref4[0], args = _ref4.slice(1), _ref3, _splice$call = splice.call(args, -1), _splice$call2 = _slicedToArray2(_splice$call, 1), cb = _splice$call2[0], _splice$call; + options2 = parser3.load({}, this.jobDefaults); + } else { + var _ref5, _ref6, _splice$call3, _splice$call4; + ref1 = args, _ref5 = ref1, _ref6 = _toArray(_ref5), options2 = _ref6[0], fn = _ref6[1], args = _ref6.slice(2), _ref5, _splice$call3 = splice.call(args, -1), _splice$call4 = _slicedToArray2(_splice$call3, 1), cb = _splice$call4[0], _splice$call3; + options2 = parser3.load(options2, this.jobDefaults); + } + task = (...args2) => { + return new this.Promise(function(resolve82, reject) { + return fn(...args2, function(...args3) { + return (args3[0] != null ? reject : resolve82)(args3); + }); + }); }; - if (this._deflating) { - this.enqueue([this.dispatch, data, this._compress, opts, cb]); + job = new Job(task, args, options2, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); + job.promise.then(function(args2) { + return typeof cb === "function" ? cb(...args2) : void 0; + }).catch(function(args2) { + if (Array.isArray(args2)) { + return typeof cb === "function" ? cb(...args2) : void 0; + } else { + return typeof cb === "function" ? cb(args2) : void 0; + } + }); + return this._receive(job); + } + schedule(...args) { + var job, options2, task; + if (typeof args[0] === "function") { + var _args = args; + var _args2 = _toArray(_args); + task = _args2[0]; + args = _args2.slice(1); + options2 = {}; } else { - this.dispatch(data, this._compress, opts, cb); + var _args3 = args; + var _args4 = _toArray(_args3); + options2 = _args4[0]; + task = _args4[1]; + args = _args4.slice(2); } - } else { - this.sendFrame( - _Sender.frame(data, { - [kByteLength]: byteLength, - fin: options2.fin, - generateMask: this._generateMask, - mask: options2.mask, - maskBuffer: this._maskBuffer, - opcode, - readOnly, - rsv1: false - }), - cb - ); + job = new Job(task, args, options2, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); + this._receive(job); + return job.promise; } - } - /** - * Dispatches a message. - * - * @param {(Buffer|String)} data The message to send - * @param {Boolean} [compress=false] Specifies whether or not to compress - * `data` - * @param {Object} options Options object - * @param {Boolean} [options.fin=false] Specifies whether or not to set the - * FIN bit - * @param {Function} [options.generateMask] The function used to generate the - * masking key - * @param {Boolean} [options.mask=false] Specifies whether or not to mask - * `data` - * @param {Buffer} [options.maskBuffer] The buffer used to store the masking - * key - * @param {Number} options.opcode The opcode - * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be - * modified - * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the - * RSV1 bit - * @param {Function} [cb] Callback - * @private - */ - dispatch(data, compress, options2, cb) { - if (!compress) { - this.sendFrame(_Sender.frame(data, options2), cb); - return; + wrap(fn) { + var schedule, wrapped; + schedule = this.schedule.bind(this); + wrapped = function wrapped2(...args) { + return schedule(fn.bind(this), ...args); + }; + wrapped.withOptions = function(options2, ...args) { + return schedule(options2, fn, ...args); + }; + return wrapped; } - const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; - this._bufferedBytes += options2[kByteLength]; - this._deflating = true; - perMessageDeflate.compress(data, options2.fin, (_, buf2) => { - if (this._socket.destroyed) { - const err = new Error( - "The socket was closed while data was being compressed" - ); - if (typeof cb === "function") cb(err); - for (let i2 = 0; i2 < this._queue.length; i2++) { - const params = this._queue[i2]; - const callback = params[params.length - 1]; - if (typeof callback === "function") callback(err); - } - return; - } - this._bufferedBytes -= options2[kByteLength]; - this._deflating = false; - options2.readOnly = false; - this.sendFrame(_Sender.frame(buf2, options2), cb); - this.dequeue(); - }); - } - /** - * Executes queued send operations. - * - * @private - */ - dequeue() { - while (!this._deflating && this._queue.length) { - const params = this._queue.shift(); - this._bufferedBytes -= params[3][kByteLength]; - Reflect.apply(params[0], this, params.slice(1)); + updateSettings(options2 = {}) { + var _this3 = this; + return _asyncToGenerator2(function* () { + yield _this3._store.__updateSettings__(parser3.overwrite(options2, _this3.storeDefaults)); + parser3.overwrite(options2, _this3.instanceDefaults, _this3); + return _this3; + })(); + } + currentReservoir() { + return this._store.__currentReservoir__(); + } + incrementReservoir(incr = 0) { + return this._store.__incrementReservoir__(incr); } } - /** - * Enqueues a send operation. - * - * @param {Array} params Send operation parameters. - * @private - */ - enqueue(params) { - this._bufferedBytes += params[3][kByteLength]; - this._queue.push(params); + ; + Bottleneck3.default = Bottleneck3; + Bottleneck3.Events = Events2; + Bottleneck3.version = Bottleneck3.prototype.version = require_version().version; + Bottleneck3.strategy = Bottleneck3.prototype.strategy = { + LEAK: 1, + OVERFLOW: 2, + OVERFLOW_PRIORITY: 4, + BLOCK: 3 + }; + Bottleneck3.BottleneckError = Bottleneck3.prototype.BottleneckError = require_BottleneckError(); + Bottleneck3.Group = Bottleneck3.prototype.Group = require_Group(); + Bottleneck3.RedisConnection = Bottleneck3.prototype.RedisConnection = require_RedisConnection(); + Bottleneck3.IORedisConnection = Bottleneck3.prototype.IORedisConnection = require_IORedisConnection(); + Bottleneck3.Batcher = Bottleneck3.prototype.Batcher = require_Batcher(); + Bottleneck3.prototype.jobDefaults = { + priority: DEFAULT_PRIORITY, + weight: 1, + expiration: null, + id: "" + }; + Bottleneck3.prototype.storeDefaults = { + maxConcurrent: null, + minTime: 0, + highWater: null, + strategy: Bottleneck3.prototype.strategy.LEAK, + penalty: null, + reservoir: null, + reservoirRefreshInterval: null, + reservoirRefreshAmount: null, + reservoirIncreaseInterval: null, + reservoirIncreaseAmount: null, + reservoirIncreaseMaximum: null + }; + Bottleneck3.prototype.localStoreDefaults = { + Promise, + timeout: null, + heartbeatInterval: 250 + }; + Bottleneck3.prototype.redisStoreDefaults = { + Promise, + timeout: null, + heartbeatInterval: 5e3, + clientTimeout: 1e4, + Redis: null, + clientOptions: {}, + clusterNodes: null, + clearDatastore: false, + connection: null + }; + Bottleneck3.prototype.instanceDefaults = { + datastore: "local", + connection: null, + id: "", + rejectOnDrop: true, + trackDoneStatus: false, + Promise + }; + Bottleneck3.prototype.stopDefaults = { + enqueueErrorMessage: "This limiter has been stopped and cannot accept new jobs.", + dropWaitingJobs: true, + dropErrorMessage: "This limiter has been stopped." + }; + return Bottleneck3; + }.call(void 0); + module14.exports = Bottleneck2; + } +}); +var require_lib6 = __commonJS({ + "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/index.js"(exports2, module14) { + "use strict"; + module14.exports = require_Bottleneck(); + } +}); +var require_err_helpers = __commonJS({ + "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err-helpers.js"(exports2, module14) { + "use strict"; + var isErrorLike = (err) => { + return err && typeof err.message === "string"; + }; + var getErrorCause = (err) => { + if (!err) return; + const cause = err.cause; + if (typeof cause === "function") { + const causeResult = err.cause(); + return isErrorLike(causeResult) ? causeResult : void 0; + } else { + return isErrorLike(cause) ? cause : void 0; } - /** - * Sends a frame. - * - * @param {Buffer[]} list The frame to send - * @param {Function} [cb] Callback - * @private - */ - sendFrame(list, cb) { - if (list.length === 2) { - this._socket.cork(); - this._socket.write(list[0]); - this._socket.write(list[1], cb); - this._socket.uncork(); - } else { - this._socket.write(list[0], cb); + }; + var _stackWithCauses = (err, seen) => { + if (!isErrorLike(err)) return ""; + const stack = err.stack || ""; + if (seen.has(err)) { + return stack + "\ncauses have become circular..."; + } + const cause = getErrorCause(err); + if (cause) { + seen.add(err); + return stack + "\ncaused by: " + _stackWithCauses(cause, seen); + } else { + return stack; + } + }; + var stackWithCauses = (err) => _stackWithCauses(err, /* @__PURE__ */ new Set()); + var _messageWithCauses = (err, seen, skip) => { + if (!isErrorLike(err)) return ""; + const message = skip ? "" : err.message || ""; + if (seen.has(err)) { + return message + ": ..."; + } + const cause = getErrorCause(err); + if (cause) { + seen.add(err); + const skipIfVErrorStyleCause = typeof err.cause === "function"; + return message + (skipIfVErrorStyleCause ? "" : ": ") + _messageWithCauses(cause, seen, skipIfVErrorStyleCause); + } else { + return message; + } + }; + var messageWithCauses = (err) => _messageWithCauses(err, /* @__PURE__ */ new Set()); + module14.exports = { + isErrorLike, + getErrorCause, + stackWithCauses, + messageWithCauses + }; + } +}); +var require_err_proto = __commonJS({ + "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err-proto.js"(exports2, module14) { + "use strict"; + var seen = Symbol("circular-ref-tag"); + var rawSymbol = Symbol("pino-raw-err-ref"); + var pinoErrProto = Object.create({}, { + type: { + enumerable: true, + writable: true, + value: void 0 + }, + message: { + enumerable: true, + writable: true, + value: void 0 + }, + stack: { + enumerable: true, + writable: true, + value: void 0 + }, + aggregateErrors: { + enumerable: true, + writable: true, + value: void 0 + }, + raw: { + enumerable: false, + get: function() { + return this[rawSymbol]; + }, + set: function(val) { + this[rawSymbol] = val; } } + }); + Object.defineProperty(pinoErrProto, rawSymbol, { + writable: true, + value: {} + }); + module14.exports = { + pinoErrProto, + pinoErrorSymbols: { + seen, + rawSymbol + } }; - module14.exports = Sender2; } }); -var require_event_target = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/event-target.js"(exports2, module14) { +var require_err = __commonJS({ + "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err.js"(exports2, module14) { "use strict"; - var { kForOnEventAttribute, kListener } = require_constants2(); - var kCode = Symbol("kCode"); - var kData = Symbol("kData"); - var kError = Symbol("kError"); - var kMessage = Symbol("kMessage"); - var kReason = Symbol("kReason"); - var kTarget = Symbol("kTarget"); - var kType = Symbol("kType"); - var kWasClean = Symbol("kWasClean"); - var Event = class { - /** - * Create a new `Event`. - * - * @param {String} type The name of the event - * @throws {TypeError} If the `type` argument is not specified - */ - constructor(type) { - this[kTarget] = null; - this[kType] = type; + module14.exports = errSerializer; + var { messageWithCauses, stackWithCauses, isErrorLike } = require_err_helpers(); + var { pinoErrProto, pinoErrorSymbols } = require_err_proto(); + var { seen } = pinoErrorSymbols; + var { toString } = Object.prototype; + function errSerializer(err) { + if (!isErrorLike(err)) { + return err; } - /** - * @type {*} - */ - get target() { - return this[kTarget]; + err[seen] = void 0; + const _err = Object.create(pinoErrProto); + _err.type = toString.call(err.constructor) === "[object Function]" ? err.constructor.name : err.name; + _err.message = messageWithCauses(err); + _err.stack = stackWithCauses(err); + if (Array.isArray(err.errors)) { + _err.aggregateErrors = err.errors.map((err2) => errSerializer(err2)); } - /** - * @type {String} - */ - get type() { - return this[kType]; + for (const key in err) { + if (_err[key] === void 0) { + const val = err[key]; + if (isErrorLike(val)) { + if (key !== "cause" && !Object.prototype.hasOwnProperty.call(val, seen)) { + _err[key] = errSerializer(val); + } + } else { + _err[key] = val; + } + } } - }; - Object.defineProperty(Event.prototype, "target", { enumerable: true }); - Object.defineProperty(Event.prototype, "type", { enumerable: true }); - var CloseEvent = class extends Event { - /** - * Create a new `CloseEvent`. - * - * @param {String} type The name of the event - * @param {Object} [options] A dictionary object that allows for setting - * attributes via object members of the same name - * @param {Number} [options.code=0] The status code explaining why the - * connection was closed - * @param {String} [options.reason=''] A human-readable string explaining why - * the connection was closed - * @param {Boolean} [options.wasClean=false] Indicates whether or not the - * connection was cleanly closed - */ - constructor(type, options2 = {}) { - super(type); - this[kCode] = options2.code === void 0 ? 0 : options2.code; - this[kReason] = options2.reason === void 0 ? "" : options2.reason; - this[kWasClean] = options2.wasClean === void 0 ? false : options2.wasClean; + delete err[seen]; + _err.raw = err; + return _err; + } + } +}); +var require_err_with_cause = __commonJS({ + "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/err-with-cause.js"(exports2, module14) { + "use strict"; + module14.exports = errWithCauseSerializer; + var { isErrorLike } = require_err_helpers(); + var { pinoErrProto, pinoErrorSymbols } = require_err_proto(); + var { seen } = pinoErrorSymbols; + var { toString } = Object.prototype; + function errWithCauseSerializer(err) { + if (!isErrorLike(err)) { + return err; } - /** - * @type {Number} - */ - get code() { - return this[kCode]; + err[seen] = void 0; + const _err = Object.create(pinoErrProto); + _err.type = toString.call(err.constructor) === "[object Function]" ? err.constructor.name : err.name; + _err.message = err.message; + _err.stack = err.stack; + if (Array.isArray(err.errors)) { + _err.aggregateErrors = err.errors.map((err2) => errWithCauseSerializer(err2)); } - /** - * @type {String} - */ - get reason() { - return this[kReason]; + if (isErrorLike(err.cause) && !Object.prototype.hasOwnProperty.call(err.cause, seen)) { + _err.cause = errWithCauseSerializer(err.cause); } - /** - * @type {Boolean} - */ - get wasClean() { - return this[kWasClean]; + for (const key in err) { + if (_err[key] === void 0) { + const val = err[key]; + if (isErrorLike(val)) { + if (!Object.prototype.hasOwnProperty.call(val, seen)) { + _err[key] = errWithCauseSerializer(val); + } + } else { + _err[key] = val; + } + } } + delete err[seen]; + _err.raw = err; + return _err; + } + } +}); +var require_req = __commonJS({ + "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/req.js"(exports2, module14) { + "use strict"; + module14.exports = { + mapHttpRequest, + reqSerializer }; - Object.defineProperty(CloseEvent.prototype, "code", { enumerable: true }); - Object.defineProperty(CloseEvent.prototype, "reason", { enumerable: true }); - Object.defineProperty(CloseEvent.prototype, "wasClean", { enumerable: true }); - var ErrorEvent = class extends Event { - /** - * Create a new `ErrorEvent`. - * - * @param {String} type The name of the event - * @param {Object} [options] A dictionary object that allows for setting - * attributes via object members of the same name - * @param {*} [options.error=null] The error that generated this event - * @param {String} [options.message=''] The error message - */ - constructor(type, options2 = {}) { - super(type); - this[kError] = options2.error === void 0 ? null : options2.error; - this[kMessage] = options2.message === void 0 ? "" : options2.message; - } - /** - * @type {*} - */ - get error() { - return this[kError]; + var rawSymbol = Symbol("pino-raw-req-ref"); + var pinoReqProto = Object.create({}, { + id: { + enumerable: true, + writable: true, + value: "" + }, + method: { + enumerable: true, + writable: true, + value: "" + }, + url: { + enumerable: true, + writable: true, + value: "" + }, + query: { + enumerable: true, + writable: true, + value: "" + }, + params: { + enumerable: true, + writable: true, + value: "" + }, + headers: { + enumerable: true, + writable: true, + value: {} + }, + remoteAddress: { + enumerable: true, + writable: true, + value: "" + }, + remotePort: { + enumerable: true, + writable: true, + value: "" + }, + raw: { + enumerable: false, + get: function() { + return this[rawSymbol]; + }, + set: function(val) { + this[rawSymbol] = val; + } } - /** - * @type {String} - */ - get message() { - return this[kMessage]; + }); + Object.defineProperty(pinoReqProto, rawSymbol, { + writable: true, + value: {} + }); + function reqSerializer(req) { + const connection = req.info || req.socket; + const _req = Object.create(pinoReqProto); + _req.id = typeof req.id === "function" ? req.id() : req.id || (req.info ? req.info.id : void 0); + _req.method = req.method; + if (req.originalUrl) { + _req.url = req.originalUrl; + } else { + const path8 = req.path; + _req.url = typeof path8 === "string" ? path8 : req.url ? req.url.path || req.url : void 0; } - }; - Object.defineProperty(ErrorEvent.prototype, "error", { enumerable: true }); - Object.defineProperty(ErrorEvent.prototype, "message", { enumerable: true }); - var MessageEvent = class extends Event { - /** - * Create a new `MessageEvent`. - * - * @param {String} type The name of the event - * @param {Object} [options] A dictionary object that allows for setting - * attributes via object members of the same name - * @param {*} [options.data=null] The message content - */ - constructor(type, options2 = {}) { - super(type); - this[kData] = options2.data === void 0 ? null : options2.data; + if (req.query) { + _req.query = req.query; } - /** - * @type {*} - */ - get data() { - return this[kData]; + if (req.params) { + _req.params = req.params; } + _req.headers = req.headers; + _req.remoteAddress = connection && connection.remoteAddress; + _req.remotePort = connection && connection.remotePort; + _req.raw = req.raw || req; + return _req; + } + function mapHttpRequest(req) { + return { + req: reqSerializer(req) + }; + } + } +}); +var require_res = __commonJS({ + "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/lib/res.js"(exports2, module14) { + "use strict"; + module14.exports = { + mapHttpResponse, + resSerializer }; - Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true }); - var EventTarget2 = { - /** - * Register an event listener. - * - * @param {String} type A string representing the event type to listen for - * @param {Function} listener The listener to add - * @param {Object} [options] An options object specifies characteristics about - * the event listener - * @param {Boolean} [options.once=false] A `Boolean` indicating that the - * listener should be invoked at most once after being added. If `true`, - * the listener would be automatically removed when invoked. - * @public - */ - addEventListener(type, listener, options2 = {}) { - let wrapper3; - if (type === "message") { - wrapper3 = function onMessage(data, isBinary) { - const event = new MessageEvent("message", { - data: isBinary ? data : data.toString() - }); - event[kTarget] = this; - listener.call(this, event); - }; - } else if (type === "close") { - wrapper3 = function onClose(code2, message) { - const event = new CloseEvent("close", { - code: code2, - reason: message.toString(), - wasClean: this._closeFrameReceived && this._closeFrameSent - }); - event[kTarget] = this; - listener.call(this, event); - }; - } else if (type === "error") { - wrapper3 = function onError(error2) { - const event = new ErrorEvent("error", { - error: error2, - message: error2.message - }); - event[kTarget] = this; - listener.call(this, event); - }; - } else if (type === "open") { - wrapper3 = function onOpen() { - const event = new Event("open"); - event[kTarget] = this; - listener.call(this, event); - }; - } else { - return; - } - wrapper3[kForOnEventAttribute] = !!options2[kForOnEventAttribute]; - wrapper3[kListener] = listener; - if (options2.once) { - this.once(type, wrapper3); - } else { - this.on(type, wrapper3); - } + var rawSymbol = Symbol("pino-raw-res-ref"); + var pinoResProto = Object.create({}, { + statusCode: { + enumerable: true, + writable: true, + value: 0 }, - /** - * Remove an event listener. - * - * @param {String} type A string representing the event type to remove - * @param {Function} handler The listener to remove - * @public - */ - removeEventListener(type, handler) { - for (const listener of this.listeners(type)) { - if (listener[kListener] === handler && !listener[kForOnEventAttribute]) { - this.removeListener(type, listener); - break; - } + headers: { + enumerable: true, + writable: true, + value: "" + }, + raw: { + enumerable: false, + get: function() { + return this[rawSymbol]; + }, + set: function(val) { + this[rawSymbol] = val; } } - }; + }); + Object.defineProperty(pinoResProto, rawSymbol, { + writable: true, + value: {} + }); + function resSerializer(res) { + const _res = Object.create(pinoResProto); + _res.statusCode = res.headersSent ? res.statusCode : null; + _res.headers = res.getHeaders ? res.getHeaders() : res._headers; + _res.raw = res; + return _res; + } + function mapHttpResponse(res) { + return { + res: resSerializer(res) + }; + } + } +}); +var require_pino_std_serializers = __commonJS({ + "node_modules/.deno/pino-std-serializers@6.2.2/node_modules/pino-std-serializers/index.js"(exports2, module14) { + "use strict"; + var errSerializer = require_err(); + var errWithCauseSerializer = require_err_with_cause(); + var reqSerializers = require_req(); + var resSerializers = require_res(); module14.exports = { - CloseEvent, - ErrorEvent, - Event, - EventTarget: EventTarget2, - MessageEvent + err: errSerializer, + errWithCause: errWithCauseSerializer, + mapHttpRequest: reqSerializers.mapHttpRequest, + mapHttpResponse: resSerializers.mapHttpResponse, + req: reqSerializers.reqSerializer, + res: resSerializers.resSerializer, + wrapErrorSerializer: function wrapErrorSerializer(customSerializer) { + if (customSerializer === errSerializer) return customSerializer; + return function wrapErrSerializer(err) { + return customSerializer(errSerializer(err)); + }; + }, + wrapRequestSerializer: function wrapRequestSerializer(customSerializer) { + if (customSerializer === reqSerializers.reqSerializer) return customSerializer; + return function wrappedReqSerializer(req) { + return customSerializer(reqSerializers.reqSerializer(req)); + }; + }, + wrapResponseSerializer: function wrapResponseSerializer(customSerializer) { + if (customSerializer === resSerializers.resSerializer) return customSerializer; + return function wrappedResSerializer(res) { + return customSerializer(resSerializers.resSerializer(res)); + }; + } }; } }); -var require_extension = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/extension.js"(exports2, module14) { +var require_caller = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/caller.js"(exports2, module14) { "use strict"; - var { tokenChars } = require_validation2(); - function push(dest, name, elem) { - if (dest[name] === void 0) dest[name] = [elem]; - else dest[name].push(elem); + function noOpPrepareStackTrace(_, stack) { + return stack; } - function parse52(header) { - const offers = /* @__PURE__ */ Object.create(null); - let params = /* @__PURE__ */ Object.create(null); - let mustUnescape = false; - let isEscaping = false; - let inQuotes = false; - let extensionName; - let paramName; - let start = -1; - let code2 = -1; - let end = -1; - let i2 = 0; - for (; i2 < header.length; i2++) { - code2 = header.charCodeAt(i2); - if (extensionName === void 0) { - if (end === -1 && tokenChars[code2] === 1) { - if (start === -1) start = i2; - } else if (i2 !== 0 && (code2 === 32 || code2 === 9)) { - if (end === -1 && start !== -1) end = i2; - } else if (code2 === 59 || code2 === 44) { - if (start === -1) { - throw new SyntaxError(`Unexpected character at index ${i2}`); - } - if (end === -1) end = i2; - const name = header.slice(start, end); - if (code2 === 44) { - push(offers, name, params); - params = /* @__PURE__ */ Object.create(null); - } else { - extensionName = name; - } - start = end = -1; - } else { - throw new SyntaxError(`Unexpected character at index ${i2}`); - } - } else if (paramName === void 0) { - if (end === -1 && tokenChars[code2] === 1) { - if (start === -1) start = i2; - } else if (code2 === 32 || code2 === 9) { - if (end === -1 && start !== -1) end = i2; - } else if (code2 === 59 || code2 === 44) { - if (start === -1) { - throw new SyntaxError(`Unexpected character at index ${i2}`); - } - if (end === -1) end = i2; - push(params, header.slice(start, end), true); - if (code2 === 44) { - push(offers, extensionName, params); - params = /* @__PURE__ */ Object.create(null); - extensionName = void 0; - } - start = end = -1; - } else if (code2 === 61 && start !== -1 && end === -1) { - paramName = header.slice(start, i2); - start = end = -1; - } else { - throw new SyntaxError(`Unexpected character at index ${i2}`); + module14.exports = function getCallers() { + const originalPrepare = Error.prepareStackTrace; + Error.prepareStackTrace = noOpPrepareStackTrace; + const stack = new Error().stack; + Error.prepareStackTrace = originalPrepare; + if (!Array.isArray(stack)) { + return void 0; + } + const entries = stack.slice(2); + const fileNames = []; + for (const entry of entries) { + if (!entry) { + continue; + } + fileNames.push(entry.getFileName()); + } + return fileNames; + }; + } +}); +var require_validator = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/validator.js"(exports2, module14) { + "use strict"; + module14.exports = validator2; + function validator2(opts = {}) { + const { + ERR_PATHS_MUST_BE_STRINGS = () => "fast-redact - Paths must be (non-empty) strings", + ERR_INVALID_PATH = (s) => `fast-redact \u2013 Invalid path (${s})` + } = opts; + return function validate({ paths }) { + paths.forEach((s) => { + if (typeof s !== "string") { + throw Error(ERR_PATHS_MUST_BE_STRINGS()); } - } else { - if (isEscaping) { - if (tokenChars[code2] !== 1) { - throw new SyntaxError(`Unexpected character at index ${i2}`); - } - if (start === -1) start = i2; - else if (!mustUnescape) mustUnescape = true; - isEscaping = false; - } else if (inQuotes) { - if (tokenChars[code2] === 1) { - if (start === -1) start = i2; - } else if (code2 === 34 && start !== -1) { - inQuotes = false; - end = i2; - } else if (code2 === 92) { - isEscaping = true; - } else { - throw new SyntaxError(`Unexpected character at index ${i2}`); - } - } else if (code2 === 34 && header.charCodeAt(i2 - 1) === 61) { - inQuotes = true; - } else if (end === -1 && tokenChars[code2] === 1) { - if (start === -1) start = i2; - } else if (start !== -1 && (code2 === 32 || code2 === 9)) { - if (end === -1) end = i2; - } else if (code2 === 59 || code2 === 44) { - if (start === -1) { - throw new SyntaxError(`Unexpected character at index ${i2}`); - } - if (end === -1) end = i2; - let value = header.slice(start, end); - if (mustUnescape) { - value = value.replace(/\\/g, ""); - mustUnescape = false; - } - push(params, paramName, value); - if (code2 === 44) { - push(offers, extensionName, params); - params = /* @__PURE__ */ Object.create(null); - extensionName = void 0; - } - paramName = void 0; - start = end = -1; - } else { - throw new SyntaxError(`Unexpected character at index ${i2}`); + try { + if (/〇/.test(s)) throw Error(); + const expr = (s[0] === "[" ? "" : ".") + s.replace(/^\*/, "\u3007").replace(/\.\*/g, ".\u3007").replace(/\[\*\]/g, "[\u3007]"); + if (/\n|\r|;/.test(expr)) throw Error(); + if (/\/\*/.test(expr)) throw Error(); + Function(` + 'use strict' + const o = new Proxy({}, { get: () => o, set: () => { throw Error() } }); + const \u3007 = null; + o${expr} + if ([o${expr}].length !== 1) throw Error()`)(); + } catch (e2) { + throw Error(ERR_INVALID_PATH(s)); } + }); + }; + } + } +}); +var require_rx = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/rx.js"(exports2, module14) { + "use strict"; + module14.exports = /[^.[\]]+|\[((?:.)*?)\]/g; + } +}); +var require_parse = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/parse.js"(exports2, module14) { + "use strict"; + var rx = require_rx(); + module14.exports = parse62; + function parse62({ paths }) { + const wildcards = []; + var wcLen = 0; + const secret = paths.reduce(function(o2, strPath, ix) { + var path8 = strPath.match(rx).map((p) => p.replace(/'|"|`/g, "")); + const leadingBracket = strPath[0] === "["; + path8 = path8.map((p) => { + if (p[0] === "[") return p.substr(1, p.length - 2); + else return p; + }); + const star = path8.indexOf("*"); + if (star > -1) { + const before = path8.slice(0, star); + const beforeStr = before.join("."); + const after = path8.slice(star + 1, path8.length); + const nested = after.length > 0; + wcLen++; + wildcards.push({ + before, + beforeStr, + after, + nested + }); + } else { + o2[strPath] = { + path: path8, + val: void 0, + precensored: false, + circle: "", + escPath: JSON.stringify(strPath), + leadingBracket + }; } + return o2; + }, {}); + return { wildcards, wcLen, secret }; + } + } +}); +var require_redactor = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/redactor.js"(exports2, module14) { + "use strict"; + var rx = require_rx(); + module14.exports = redactor; + function redactor({ secret, serialize: serialize2, wcLen, strict, isCensorFct, censorFctTakesPath }, state) { + const redact = Function("o", ` + if (typeof o !== 'object' || o == null) { + ${strictImpl(strict, serialize2)} + } + const { censor, secret } = this + const originalSecret = {} + const secretKeys = Object.keys(secret) + for (var i = 0; i < secretKeys.length; i++) { + originalSecret[secretKeys[i]] = secret[secretKeys[i]] + } + + ${redactTmpl(secret, isCensorFct, censorFctTakesPath)} + this.compileRestore() + ${dynamicRedactTmpl(wcLen > 0, isCensorFct, censorFctTakesPath)} + this.secret = originalSecret + ${resultTmpl(serialize2)} + `).bind(state); + redact.state = state; + if (serialize2 === false) { + redact.restore = (o2) => state.restore(o2); } - if (start === -1 || inQuotes || code2 === 32 || code2 === 9) { - throw new SyntaxError("Unexpected end of input"); + return redact; + } + function redactTmpl(secret, isCensorFct, censorFctTakesPath) { + return Object.keys(secret).map((path8) => { + const { escPath, leadingBracket, path: arrPath } = secret[path8]; + const skip = leadingBracket ? 1 : 0; + const delim = leadingBracket ? "" : "."; + const hops = []; + var match2; + while ((match2 = rx.exec(path8)) !== null) { + const [, ix] = match2; + const { index, input } = match2; + if (index > skip) hops.push(input.substring(0, index - (ix ? 0 : 1))); + } + var existence = hops.map((p) => `o${delim}${p}`).join(" && "); + if (existence.length === 0) existence += `o${delim}${path8} != null`; + else existence += ` && o${delim}${path8} != null`; + const circularDetection = ` + switch (true) { + ${hops.reverse().map((p) => ` + case o${delim}${p} === censor: + secret[${escPath}].circle = ${JSON.stringify(p)} + break + `).join("\n")} } - if (end === -1) end = i2; - const token = header.slice(start, end); - if (extensionName === void 0) { - push(offers, token, params); - } else { - if (paramName === void 0) { - push(params, token, true); - } else if (mustUnescape) { - push(params, paramName, token.replace(/\\/g, "")); + `; + const censorArgs = censorFctTakesPath ? `val, ${JSON.stringify(arrPath)}` : `val`; + return ` + if (${existence}) { + const val = o${delim}${path8} + if (val === censor) { + secret[${escPath}].precensored = true } else { - push(params, paramName, token); + secret[${escPath}].val = val + o${delim}${path8} = ${isCensorFct ? `censor(${censorArgs})` : "censor"} + ${circularDetection} } - push(offers, extensionName, params); } - return offers; + `; + }).join("\n"); } - function format52(extensions) { - return Object.keys(extensions).map((extension) => { - let configurations = extensions[extension]; - if (!Array.isArray(configurations)) configurations = [configurations]; - return configurations.map((params) => { - return [extension].concat( - Object.keys(params).map((k) => { - let values = params[k]; - if (!Array.isArray(values)) values = [values]; - return values.map((v2) => v2 === true ? k : `${k}=${v2}`).join("; "); - }) - ).join("; "); - }).join(", "); - }).join(", "); + function dynamicRedactTmpl(hasWildcards, isCensorFct, censorFctTakesPath) { + return hasWildcards === true ? ` + { + const { wildcards, wcLen, groupRedact, nestedRedact } = this + for (var i = 0; i < wcLen; i++) { + const { before, beforeStr, after, nested } = wildcards[i] + if (nested === true) { + secret[beforeStr] = secret[beforeStr] || [] + nestedRedact(secret[beforeStr], o, before, after, censor, ${isCensorFct}, ${censorFctTakesPath}) + } else secret[beforeStr] = groupRedact(o, before, censor, ${isCensorFct}, ${censorFctTakesPath}) + } + } + ` : ""; + } + function resultTmpl(serialize2) { + return serialize2 === false ? `return o` : ` + var s = this.serialize(o) + this.restore(o) + return s + `; + } + function strictImpl(strict, serialize2) { + return strict === true ? `throw Error('fast-redact: primitives cannot be redacted')` : serialize2 === false ? `return o` : `return this.serialize(o)`; } - module14.exports = { format: format52, parse: parse52 }; } }); -var require_websocket = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/websocket.js"(exports2, module14) { +var require_modifiers = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/modifiers.js"(exports2, module14) { "use strict"; - var EventEmitter = __require2("events"); - var https = __require2("https"); - var http = __require2("http"); - var net = __require2("net"); - var tls = __require2("tls"); - var { randomBytes: randomBytes3, createHash } = __require2("crypto"); - var { Readable: Readable2 } = __require2("stream"); - var { URL: URL2 } = __require2("url"); - var PerMessageDeflate = require_permessage_deflate(); - var Receiver2 = require_receiver(); - var Sender2 = require_sender(); - var { - BINARY_TYPES, - EMPTY_BUFFER, - GUID, - kForOnEventAttribute, - kListener, - kStatusCode, - kWebSocket, - NOOP - } = require_constants2(); - var { - EventTarget: { addEventListener, removeEventListener } - } = require_event_target(); - var { format: format52, parse: parse52 } = require_extension(); - var { toBuffer } = require_buffer_util(); - var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"]; - var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/; - var protocolVersions = [8, 13]; - var closeTimeout = 30 * 1e3; - var WebSocket3 = class _WebSocket extends EventEmitter { - /** - * Create a new `WebSocket`. - * - * @param {(String|URL)} address The URL to which to connect - * @param {(String|String[])} [protocols] The subprotocols - * @param {Object} [options] Connection options - */ - constructor(address, protocols, options2) { - super(); - this._binaryType = BINARY_TYPES[0]; - this._closeCode = 1006; - this._closeFrameReceived = false; - this._closeFrameSent = false; - this._closeMessage = EMPTY_BUFFER; - this._closeTimer = null; - this._extensions = {}; - this._paused = false; - this._protocol = ""; - this._readyState = _WebSocket.CONNECTING; - this._receiver = null; - this._sender = null; - this._socket = null; - if (address !== null) { - this._bufferedAmount = 0; - this._isServer = false; - this._redirects = 0; - if (protocols === void 0) { - protocols = []; - } else if (!Array.isArray(protocols)) { - if (typeof protocols === "object" && protocols !== null) { - options2 = protocols; - protocols = []; - } else { - protocols = [protocols]; - } - } - initAsClient(this, address, protocols, options2); + module14.exports = { + groupRedact, + groupRestore, + nestedRedact, + nestedRestore + }; + function groupRestore({ keys, values, target }) { + if (target == null || typeof target === "string") return; + const length2 = keys.length; + for (var i2 = 0; i2 < length2; i2++) { + const k = keys[i2]; + target[k] = values[i2]; + } + } + function groupRedact(o2, path8, censor, isCensorFct, censorFctTakesPath) { + const target = get2(o2, path8); + if (target == null || typeof target === "string") return { keys: null, values: null, target, flat: true }; + const keys = Object.keys(target); + const keysLength = keys.length; + const pathLength = path8.length; + const pathWithKey = censorFctTakesPath ? [...path8] : void 0; + const values = new Array(keysLength); + for (var i2 = 0; i2 < keysLength; i2++) { + const key = keys[i2]; + values[i2] = target[key]; + if (censorFctTakesPath) { + pathWithKey[pathLength] = key; + target[key] = censor(target[key], pathWithKey); + } else if (isCensorFct) { + target[key] = censor(target[key]); } else { - this._isServer = true; + target[key] = censor; } } - /** - * This deviates from the WHATWG interface since ws doesn't support the - * required default "blob" type (instead we define a custom "nodebuffer" - * type). - * - * @type {String} - */ - get binaryType() { - return this._binaryType; - } - set binaryType(type) { - if (!BINARY_TYPES.includes(type)) return; - this._binaryType = type; - if (this._receiver) this._receiver._binaryType = type; - } - /** - * @type {Number} - */ - get bufferedAmount() { - if (!this._socket) return this._bufferedAmount; - return this._socket._writableState.length + this._sender._bufferedBytes; - } - /** - * @type {String} - */ - get extensions() { - return Object.keys(this._extensions).join(); - } - /** - * @type {Boolean} - */ - get isPaused() { - return this._paused; - } - /** - * @type {Function} - */ - /* istanbul ignore next */ - get onclose() { - return null; - } - /** - * @type {Function} - */ - /* istanbul ignore next */ - get onerror() { - return null; - } - /** - * @type {Function} - */ - /* istanbul ignore next */ - get onopen() { - return null; - } - /** - * @type {Function} - */ - /* istanbul ignore next */ - get onmessage() { - return null; - } - /** - * @type {String} - */ - get protocol() { - return this._protocol; - } - /** - * @type {Number} - */ - get readyState() { - return this._readyState; - } - /** - * @type {String} - */ - get url() { - return this._url; + return { keys, values, target, flat: true }; + } + function nestedRestore(instructions) { + for (let i2 = 0; i2 < instructions.length; i2++) { + const { target, path: path8, value } = instructions[i2]; + let current = target; + for (let i3 = path8.length - 1; i3 > 0; i3--) { + current = current[path8[i3]]; + } + current[path8[0]] = value; } - /** - * Set up the socket and the internal resources. - * - * @param {(net.Socket|tls.Socket)} socket The network socket between the - * server and client - * @param {Buffer} head The first packet of the upgraded stream - * @param {Object} options Options object - * @param {Function} [options.generateMask] The function used to generate the - * masking key - * @param {Number} [options.maxPayload=0] The maximum allowed message size - * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or - * not to skip UTF-8 validation for text and close messages - * @private - */ - setSocket(socket, head, options2) { - const receiver = new Receiver2({ - binaryType: this.binaryType, - extensions: this._extensions, - isServer: this._isServer, - maxPayload: options2.maxPayload, - skipUTF8Validation: options2.skipUTF8Validation - }); - this._sender = new Sender2(socket, this._extensions, options2.generateMask); - this._receiver = receiver; - this._socket = socket; - receiver[kWebSocket] = this; - socket[kWebSocket] = this; - receiver.on("conclude", receiverOnConclude); - receiver.on("drain", receiverOnDrain); - receiver.on("error", receiverOnError); - receiver.on("message", receiverOnMessage); - receiver.on("ping", receiverOnPing); - receiver.on("pong", receiverOnPong); - socket.setTimeout(0); - socket.setNoDelay(); - if (head.length > 0) socket.unshift(head); - socket.on("close", socketOnClose); - socket.on("data", socketOnData); - socket.on("end", socketOnEnd); - socket.on("error", socketOnError); - this._readyState = _WebSocket.OPEN; - this.emit("open"); + } + function nestedRedact(store, o2, path8, ns, censor, isCensorFct, censorFctTakesPath) { + const target = get2(o2, path8); + if (target == null) return; + const keys = Object.keys(target); + const keysLength = keys.length; + for (var i2 = 0; i2 < keysLength; i2++) { + const key = keys[i2]; + specialSet(store, target, key, path8, ns, censor, isCensorFct, censorFctTakesPath); } - /** - * Emit the `'close'` event. - * - * @private - */ - emitClose() { - if (!this._socket) { - this._readyState = _WebSocket.CLOSED; - this.emit("close", this._closeCode, this._closeMessage); - return; + return store; + } + function has2(obj, prop) { + return obj !== void 0 && obj !== null ? "hasOwn" in Object ? Object.hasOwn(obj, prop) : Object.prototype.hasOwnProperty.call(obj, prop) : false; + } + function specialSet(store, o2, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath) { + const afterPathLen = afterPath.length; + const lastPathIndex = afterPathLen - 1; + const originalKey = k; + var i2 = -1; + var n; + var nv; + var ov; + var oov = null; + var wc = null; + var kIsWc; + var wcov; + var consecutive = false; + var level = 0; + var depth = 0; + var redactPathCurrent = tree(); + ov = n = o2[k]; + if (typeof n !== "object") return; + while (n != null && ++i2 < afterPathLen) { + depth += 1; + k = afterPath[i2]; + oov = ov; + if (k !== "*" && !wc && !(typeof n === "object" && k in n)) { + break; } - if (this._extensions[PerMessageDeflate.extensionName]) { - this._extensions[PerMessageDeflate.extensionName].cleanup(); + if (k === "*") { + if (wc === "*") { + consecutive = true; + } + wc = k; + if (i2 !== lastPathIndex) { + continue; + } } - this._receiver.removeAllListeners(); - this._readyState = _WebSocket.CLOSED; - this.emit("close", this._closeCode, this._closeMessage); - } - /** - * Start a closing handshake. - * - * +----------+ +-----------+ +----------+ - * - - -|ws.close()|-->|close frame|-->|ws.close()|- - - - * | +----------+ +-----------+ +----------+ | - * +----------+ +-----------+ | - * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING - * +----------+ +-----------+ | - * | | | +---+ | - * +------------------------+-->|fin| - - - - - * | +---+ | +---+ - * - - - - -|fin|<---------------------+ - * +---+ - * - * @param {Number} [code] Status code explaining why the connection is closing - * @param {(String|Buffer)} [data] The reason why the connection is - * closing - * @public - */ - close(code2, data) { - if (this.readyState === _WebSocket.CLOSED) return; - if (this.readyState === _WebSocket.CONNECTING) { - const msg = "WebSocket was closed before the connection was established"; - return abortHandshake(this, this._req, msg); + if (wc) { + const wcKeys = Object.keys(n); + for (var j = 0; j < wcKeys.length; j++) { + const wck = wcKeys[j]; + wcov = n[wck]; + kIsWc = k === "*"; + if (consecutive) { + redactPathCurrent = node(redactPathCurrent, wck, depth); + level = i2; + ov = iterateNthLevel(wcov, level - 1, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath, originalKey, n, nv, ov, kIsWc, wck, i2, lastPathIndex, redactPathCurrent, store, o2[originalKey], depth + 1); + } else { + if (kIsWc || typeof wcov === "object" && wcov !== null && k in wcov) { + if (kIsWc) { + ov = wcov; + } else { + ov = wcov[k]; + } + nv = i2 !== lastPathIndex ? ov : isCensorFct ? censorFctTakesPath ? censor(ov, [...path8, originalKey, ...afterPath]) : censor(ov) : censor; + if (kIsWc) { + const rv = restoreInstr(node(redactPathCurrent, wck, depth), ov, o2[originalKey]); + store.push(rv); + n[wck] = nv; + } else { + if (wcov[k] === nv) { + } else if (nv === void 0 && censor !== void 0 || has2(wcov, k) && nv === ov) { + redactPathCurrent = node(redactPathCurrent, wck, depth); + } else { + redactPathCurrent = node(redactPathCurrent, wck, depth); + const rv = restoreInstr(node(redactPathCurrent, k, depth + 1), ov, o2[originalKey]); + store.push(rv); + wcov[k] = nv; + } + } + } + } + } + wc = null; + } else { + ov = n[k]; + redactPathCurrent = node(redactPathCurrent, k, depth); + nv = i2 !== lastPathIndex ? ov : isCensorFct ? censorFctTakesPath ? censor(ov, [...path8, originalKey, ...afterPath]) : censor(ov) : censor; + if (has2(n, k) && nv === ov || nv === void 0 && censor !== void 0) { + } else { + const rv = restoreInstr(redactPathCurrent, ov, o2[originalKey]); + store.push(rv); + n[k] = nv; + } + n = n[k]; } - if (this.readyState === _WebSocket.CLOSING) { - if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) { - this._socket.end(); + if (typeof n !== "object") break; + if (ov === oov || typeof ov === "undefined") { + } + } + } + function get2(o2, p) { + var i2 = -1; + var l = p.length; + var n = o2; + while (n != null && ++i2 < l) { + n = n[p[i2]]; + } + return n; + } + function iterateNthLevel(wcov, level, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath, originalKey, n, nv, ov, kIsWc, wck, i2, lastPathIndex, redactPathCurrent, store, parent, depth) { + if (level === 0) { + if (kIsWc || typeof wcov === "object" && wcov !== null && k in wcov) { + if (kIsWc) { + ov = wcov; + } else { + ov = wcov[k]; + } + nv = i2 !== lastPathIndex ? ov : isCensorFct ? censorFctTakesPath ? censor(ov, [...path8, originalKey, ...afterPath]) : censor(ov) : censor; + if (kIsWc) { + const rv = restoreInstr(redactPathCurrent, ov, parent); + store.push(rv); + n[wck] = nv; + } else { + if (wcov[k] === nv) { + } else if (nv === void 0 && censor !== void 0 || has2(wcov, k) && nv === ov) { + } else { + const rv = restoreInstr(node(redactPathCurrent, k, depth + 1), ov, parent); + store.push(rv); + wcov[k] = nv; + } } - return; } - this._readyState = _WebSocket.CLOSING; - this._sender.close(code2, data, !this._isServer, (err) => { - if (err) return; - this._closeFrameSent = true; - if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) { - this._socket.end(); - } - }); - this._closeTimer = setTimeout( - this._socket.destroy.bind(this._socket), - closeTimeout - ); } - /** - * Pause the socket. - * - * @public - */ - pause() { - if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) { - return; + for (const key in wcov) { + if (typeof wcov[key] === "object") { + redactPathCurrent = node(redactPathCurrent, key, depth); + iterateNthLevel(wcov[key], level - 1, k, path8, afterPath, censor, isCensorFct, censorFctTakesPath, originalKey, n, nv, ov, kIsWc, wck, i2, lastPathIndex, redactPathCurrent, store, parent, depth + 1); } - this._paused = true; - this._socket.pause(); } - /** - * Send a ping. - * - * @param {*} [data] The data to send - * @param {Boolean} [mask] Indicates whether or not to mask `data` - * @param {Function} [cb] Callback which is executed when the ping is sent - * @public - */ - ping(data, mask, cb) { - if (this.readyState === _WebSocket.CONNECTING) { - throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); - } - if (typeof data === "function") { - cb = data; - data = mask = void 0; - } else if (typeof mask === "function") { - cb = mask; - mask = void 0; - } - if (typeof data === "number") data = data.toString(); - if (this.readyState !== _WebSocket.OPEN) { - sendAfterClose(this, data, cb); + } + function tree() { + return { parent: null, key: null, children: [], depth: 0 }; + } + function node(parent, key, depth) { + if (parent.depth === depth) { + return node(parent.parent, key, depth); + } + var child = { + parent, + key, + depth, + children: [] + }; + parent.children.push(child); + return child; + } + function restoreInstr(node2, value, target) { + let current = node2; + const path8 = []; + do { + path8.push(current.key); + current = current.parent; + } while (current.parent != null); + return { path: path8, value, target }; + } + } +}); +var require_restorer = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/restorer.js"(exports2, module14) { + "use strict"; + var { groupRestore, nestedRestore } = require_modifiers(); + module14.exports = restorer; + function restorer() { + return function compileRestore() { + if (this.restore) { + this.restore.state.secret = this.secret; return; } - if (mask === void 0) mask = !this._isServer; - this._sender.ping(data || EMPTY_BUFFER, mask, cb); + const { secret, wcLen } = this; + const paths = Object.keys(secret); + const resetters = resetTmpl(secret, paths); + const hasWildcards = wcLen > 0; + const state = hasWildcards ? { secret, groupRestore, nestedRestore } : { secret }; + this.restore = Function( + "o", + restoreTmpl(resetters, paths, hasWildcards) + ).bind(state); + this.restore.state = state; + }; + } + function resetTmpl(secret, paths) { + return paths.map((path8) => { + const { circle, escPath, leadingBracket } = secret[path8]; + const delim = leadingBracket ? "" : "."; + const reset = circle ? `o.${circle} = secret[${escPath}].val` : `o${delim}${path8} = secret[${escPath}].val`; + const clear = `secret[${escPath}].val = undefined`; + return ` + if (secret[${escPath}].val !== undefined) { + try { ${reset} } catch (e) {} + ${clear} } - /** - * Send a pong. - * - * @param {*} [data] The data to send - * @param {Boolean} [mask] Indicates whether or not to mask `data` - * @param {Function} [cb] Callback which is executed when the pong is sent - * @public - */ - pong(data, mask, cb) { - if (this.readyState === _WebSocket.CONNECTING) { - throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); + `; + }).join(""); + } + function restoreTmpl(resetters, paths, hasWildcards) { + const dynamicReset = hasWildcards === true ? ` + const keys = Object.keys(secret) + const len = keys.length + for (var i = len - 1; i >= ${paths.length}; i--) { + const k = keys[i] + const o = secret[k] + if (o) { + if (o.flat === true) this.groupRestore(o) + else this.nestedRestore(o) + secret[k] = null + } + } + ` : ""; + return ` + const secret = this.secret + ${dynamicReset} + ${resetters} + return o + `; + } + } +}); +var require_state = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/lib/state.js"(exports2, module14) { + "use strict"; + module14.exports = state; + function state(o2) { + const { + secret, + censor, + compileRestore, + serialize: serialize2, + groupRedact, + nestedRedact, + wildcards, + wcLen + } = o2; + const builder = [{ secret, censor, compileRestore }]; + if (serialize2 !== false) builder.push({ serialize: serialize2 }); + if (wcLen > 0) builder.push({ groupRedact, nestedRedact, wildcards, wcLen }); + return Object.assign(...builder); + } + } +}); +var require_fast_redact = __commonJS({ + "node_modules/.deno/fast-redact@3.5.0/node_modules/fast-redact/index.js"(exports2, module14) { + "use strict"; + var validator2 = require_validator(); + var parse62 = require_parse(); + var redactor = require_redactor(); + var restorer = require_restorer(); + var { groupRedact, nestedRedact } = require_modifiers(); + var state = require_state(); + var rx = require_rx(); + var validate = validator2(); + var noop = (o2) => o2; + noop.restore = noop; + var DEFAULT_CENSOR = "[REDACTED]"; + fastRedact.rx = rx; + fastRedact.validator = validator2; + module14.exports = fastRedact; + function fastRedact(opts = {}) { + const paths = Array.from(new Set(opts.paths || [])); + const serialize2 = "serialize" in opts ? opts.serialize === false ? opts.serialize : typeof opts.serialize === "function" ? opts.serialize : JSON.stringify : JSON.stringify; + const remove = opts.remove; + if (remove === true && serialize2 !== JSON.stringify) { + throw Error("fast-redact \u2013 remove option may only be set when serializer is JSON.stringify"); + } + const censor = remove === true ? void 0 : "censor" in opts ? opts.censor : DEFAULT_CENSOR; + const isCensorFct = typeof censor === "function"; + const censorFctTakesPath = isCensorFct && censor.length > 1; + if (paths.length === 0) return serialize2 || noop; + validate({ paths, serialize: serialize2, censor }); + const { wildcards, wcLen, secret } = parse62({ paths, censor }); + const compileRestore = restorer(); + const strict = "strict" in opts ? opts.strict : true; + return redactor({ secret, wcLen, serialize: serialize2, strict, isCensorFct, censorFctTakesPath }, state({ + secret, + censor, + compileRestore, + serialize: serialize2, + groupRedact, + nestedRedact, + wildcards, + wcLen + })); + } + } +}); +var require_symbols = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/symbols.js"(exports2, module14) { + "use strict"; + var setLevelSym = Symbol("pino.setLevel"); + var getLevelSym = Symbol("pino.getLevel"); + var levelValSym = Symbol("pino.levelVal"); + var levelCompSym = Symbol("pino.levelComp"); + var useLevelLabelsSym = Symbol("pino.useLevelLabels"); + var useOnlyCustomLevelsSym = Symbol("pino.useOnlyCustomLevels"); + var mixinSym = Symbol("pino.mixin"); + var lsCacheSym = Symbol("pino.lsCache"); + var chindingsSym = Symbol("pino.chindings"); + var asJsonSym = Symbol("pino.asJson"); + var writeSym = Symbol("pino.write"); + var redactFmtSym = Symbol("pino.redactFmt"); + var timeSym = Symbol("pino.time"); + var timeSliceIndexSym = Symbol("pino.timeSliceIndex"); + var streamSym = Symbol("pino.stream"); + var stringifySym = Symbol("pino.stringify"); + var stringifySafeSym = Symbol("pino.stringifySafe"); + var stringifiersSym = Symbol("pino.stringifiers"); + var endSym = Symbol("pino.end"); + var formatOptsSym = Symbol("pino.formatOpts"); + var messageKeySym = Symbol("pino.messageKey"); + var errorKeySym = Symbol("pino.errorKey"); + var nestedKeySym = Symbol("pino.nestedKey"); + var nestedKeyStrSym = Symbol("pino.nestedKeyStr"); + var mixinMergeStrategySym = Symbol("pino.mixinMergeStrategy"); + var msgPrefixSym = Symbol("pino.msgPrefix"); + var wildcardFirstSym = Symbol("pino.wildcardFirst"); + var serializersSym = Symbol.for("pino.serializers"); + var formattersSym = Symbol.for("pino.formatters"); + var hooksSym = Symbol.for("pino.hooks"); + var needsMetadataGsym = Symbol.for("pino.metadata"); + module14.exports = { + setLevelSym, + getLevelSym, + levelValSym, + levelCompSym, + useLevelLabelsSym, + mixinSym, + lsCacheSym, + chindingsSym, + asJsonSym, + writeSym, + serializersSym, + redactFmtSym, + timeSym, + timeSliceIndexSym, + streamSym, + stringifySym, + stringifySafeSym, + stringifiersSym, + endSym, + formatOptsSym, + messageKeySym, + errorKeySym, + nestedKeySym, + wildcardFirstSym, + needsMetadataGsym, + useOnlyCustomLevelsSym, + formattersSym, + hooksSym, + nestedKeyStrSym, + mixinMergeStrategySym, + msgPrefixSym + }; + } +}); +var require_redaction = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/redaction.js"(exports2, module14) { + "use strict"; + var fastRedact = require_fast_redact(); + var { redactFmtSym, wildcardFirstSym } = require_symbols(); + var { rx, validator: validator2 } = fastRedact; + var validate = validator2({ + ERR_PATHS_MUST_BE_STRINGS: () => "pino \u2013 redacted paths must be strings", + ERR_INVALID_PATH: (s) => `pino \u2013 redact paths array contains an invalid path (${s})` + }); + var CENSOR = "[Redacted]"; + var strict = false; + function redaction(opts, serialize2) { + const { paths, censor } = handle(opts); + const shape = paths.reduce((o2, str) => { + rx.lastIndex = 0; + const first = rx.exec(str); + const next = rx.exec(str); + let ns = first[1] !== void 0 ? first[1].replace(/^(?:"|'|`)(.*)(?:"|'|`)$/, "$1") : first[0]; + if (ns === "*") { + ns = wildcardFirstSym; } - if (typeof data === "function") { - cb = data; - data = mask = void 0; - } else if (typeof mask === "function") { - cb = mask; - mask = void 0; + if (next === null) { + o2[ns] = null; + return o2; } - if (typeof data === "number") data = data.toString(); - if (this.readyState !== _WebSocket.OPEN) { - sendAfterClose(this, data, cb); - return; + if (o2[ns] === null) { + return o2; } - if (mask === void 0) mask = !this._isServer; - this._sender.pong(data || EMPTY_BUFFER, mask, cb); - } - /** - * Resume the socket. - * - * @public - */ - resume() { - if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) { - return; + const { index } = next; + const nextPath = `${str.substr(index, str.length - 1)}`; + o2[ns] = o2[ns] || []; + if (ns !== wildcardFirstSym && o2[ns].length === 0) { + o2[ns].push(...o2[wildcardFirstSym] || []); } - this._paused = false; - if (!this._receiver._writableState.needDrain) this._socket.resume(); - } - /** - * Send a data message. - * - * @param {*} data The message to send - * @param {Object} [options] Options object - * @param {Boolean} [options.binary] Specifies whether `data` is binary or - * text - * @param {Boolean} [options.compress] Specifies whether or not to compress - * `data` - * @param {Boolean} [options.fin=true] Specifies whether the fragment is the - * last one - * @param {Boolean} [options.mask] Specifies whether or not to mask `data` - * @param {Function} [cb] Callback which is executed when data is written out - * @public - */ - send(data, options2, cb) { - if (this.readyState === _WebSocket.CONNECTING) { - throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); + if (ns === wildcardFirstSym) { + Object.keys(o2).forEach(function(k) { + if (o2[k]) { + o2[k].push(nextPath); + } + }); } - if (typeof options2 === "function") { - cb = options2; - options2 = {}; + o2[ns].push(nextPath); + return o2; + }, {}); + const result = { + [redactFmtSym]: fastRedact({ paths, censor, serialize: serialize2, strict }) + }; + const topCensor = (...args) => { + return typeof censor === "function" ? serialize2(censor(...args)) : serialize2(censor); + }; + return [...Object.keys(shape), ...Object.getOwnPropertySymbols(shape)].reduce((o2, k) => { + if (shape[k] === null) { + o2[k] = (value) => topCensor(value, [k]); + } else { + const wrappedCensor = typeof censor === "function" ? (value, path8) => { + return censor(value, [k, ...path8]); + } : censor; + o2[k] = fastRedact({ + paths: shape[k], + censor: wrappedCensor, + serialize: serialize2, + strict + }); } - if (typeof data === "number") data = data.toString(); - if (this.readyState !== _WebSocket.OPEN) { - sendAfterClose(this, data, cb); - return; + return o2; + }, result); + } + function handle(opts) { + if (Array.isArray(opts)) { + opts = { paths: opts, censor: CENSOR }; + validate(opts); + return opts; + } + let { paths, censor = CENSOR, remove } = opts; + if (Array.isArray(paths) === false) { + throw Error("pino \u2013 redact must contain an array of strings"); + } + if (remove === true) censor = void 0; + validate({ paths, censor }); + return { paths, censor }; + } + module14.exports = redaction; + } +}); +var require_time = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/time.js"(exports2, module14) { + "use strict"; + var nullTime = () => ""; + var epochTime = () => `,"time":${Date.now()}`; + var unixTime = () => `,"time":${Math.round(Date.now() / 1e3)}`; + var isoTime = () => `,"time":"${new Date(Date.now()).toISOString()}"`; + module14.exports = { nullTime, epochTime, unixTime, isoTime }; + } +}); +var require_quick_format_unescaped = __commonJS({ + "node_modules/.deno/quick-format-unescaped@4.0.4/node_modules/quick-format-unescaped/index.js"(exports2, module14) { + "use strict"; + function tryStringify(o2) { + try { + return JSON.stringify(o2); + } catch (e2) { + return '"[Circular]"'; + } + } + module14.exports = format52; + function format52(f, args, opts) { + var ss = opts && opts.stringify || tryStringify; + var offset = 1; + if (typeof f === "object" && f !== null) { + var len = args.length + offset; + if (len === 1) return f; + var objects = new Array(len); + objects[0] = ss(f); + for (var index = 1; index < len; index++) { + objects[index] = ss(args[index]); } - const opts = { - binary: typeof data !== "string", - mask: !this._isServer, - compress: true, - fin: true, - ...options2 - }; - if (!this._extensions[PerMessageDeflate.extensionName]) { - opts.compress = false; + return objects.join(" "); + } + if (typeof f !== "string") { + return f; + } + var argLen = args.length; + if (argLen === 0) return f; + var str = ""; + var a = 1 - offset; + var lastPos = -1; + var flen = f && f.length || 0; + for (var i2 = 0; i2 < flen; ) { + if (f.charCodeAt(i2) === 37 && i2 + 1 < flen) { + lastPos = lastPos > -1 ? lastPos : 0; + switch (f.charCodeAt(i2 + 1)) { + case 100: + // 'd' + case 102: + if (a >= argLen) + break; + if (args[a] == null) break; + if (lastPos < i2) + str += f.slice(lastPos, i2); + str += Number(args[a]); + lastPos = i2 + 2; + i2++; + break; + case 105: + if (a >= argLen) + break; + if (args[a] == null) break; + if (lastPos < i2) + str += f.slice(lastPos, i2); + str += Math.floor(Number(args[a])); + lastPos = i2 + 2; + i2++; + break; + case 79: + // 'O' + case 111: + // 'o' + case 106: + if (a >= argLen) + break; + if (args[a] === void 0) break; + if (lastPos < i2) + str += f.slice(lastPos, i2); + var type = typeof args[a]; + if (type === "string") { + str += "'" + args[a] + "'"; + lastPos = i2 + 2; + i2++; + break; + } + if (type === "function") { + str += args[a].name || ""; + lastPos = i2 + 2; + i2++; + break; + } + str += ss(args[a]); + lastPos = i2 + 2; + i2++; + break; + case 115: + if (a >= argLen) + break; + if (lastPos < i2) + str += f.slice(lastPos, i2); + str += String(args[a]); + lastPos = i2 + 2; + i2++; + break; + case 37: + if (lastPos < i2) + str += f.slice(lastPos, i2); + str += "%"; + lastPos = i2 + 2; + i2++; + a--; + break; + } + ++a; } - this._sender.send(data || EMPTY_BUFFER, opts, cb); + ++i2; } - /** - * Forcibly close the connection. - * - * @public - */ - terminate() { - if (this.readyState === _WebSocket.CLOSED) return; - if (this.readyState === _WebSocket.CONNECTING) { - const msg = "WebSocket was closed before the connection was established"; - return abortHandshake(this, this._req, msg); - } - if (this._socket) { - this._readyState = _WebSocket.CLOSING; - this._socket.destroy(); - } + if (lastPos === -1) + return f; + else if (lastPos < flen) { + str += f.slice(lastPos); } - }; - Object.defineProperty(WebSocket3, "CONNECTING", { - enumerable: true, - value: readyStates.indexOf("CONNECTING") - }); - Object.defineProperty(WebSocket3.prototype, "CONNECTING", { - enumerable: true, - value: readyStates.indexOf("CONNECTING") - }); - Object.defineProperty(WebSocket3, "OPEN", { - enumerable: true, - value: readyStates.indexOf("OPEN") - }); - Object.defineProperty(WebSocket3.prototype, "OPEN", { - enumerable: true, - value: readyStates.indexOf("OPEN") - }); - Object.defineProperty(WebSocket3, "CLOSING", { - enumerable: true, - value: readyStates.indexOf("CLOSING") - }); - Object.defineProperty(WebSocket3.prototype, "CLOSING", { - enumerable: true, - value: readyStates.indexOf("CLOSING") - }); - Object.defineProperty(WebSocket3, "CLOSED", { - enumerable: true, - value: readyStates.indexOf("CLOSED") - }); - Object.defineProperty(WebSocket3.prototype, "CLOSED", { - enumerable: true, - value: readyStates.indexOf("CLOSED") - }); - [ - "binaryType", - "bufferedAmount", - "extensions", - "isPaused", - "protocol", - "readyState", - "url" - ].forEach((property) => { - Object.defineProperty(WebSocket3.prototype, property, { enumerable: true }); - }); - ["open", "error", "close", "message"].forEach((method) => { - Object.defineProperty(WebSocket3.prototype, `on${method}`, { - enumerable: true, - get() { - for (const listener of this.listeners(method)) { - if (listener[kForOnEventAttribute]) return listener[kListener]; + return str; + } + } +}); +var require_atomic_sleep = __commonJS({ + "node_modules/.deno/atomic-sleep@1.0.0/node_modules/atomic-sleep/index.js"(exports2, module14) { + "use strict"; + if (typeof SharedArrayBuffer !== "undefined" && typeof Atomics !== "undefined") { + let sleep = function(ms) { + const valid = ms > 0 && ms < Infinity; + if (valid === false) { + if (typeof ms !== "number" && typeof ms !== "bigint") { + throw TypeError("sleep: ms must be a number"); } - return null; - }, - set(handler) { - for (const listener of this.listeners(method)) { - if (listener[kForOnEventAttribute]) { - this.removeListener(method, listener); - break; - } + throw RangeError("sleep: ms must be a number that is greater than 0 but less than Infinity"); + } + Atomics.wait(nil, 0, 0, Number(ms)); + }; + const nil = new Int32Array(new SharedArrayBuffer(4)); + module14.exports = sleep; + } else { + let sleep = function(ms) { + const valid = ms > 0 && ms < Infinity; + if (valid === false) { + if (typeof ms !== "number" && typeof ms !== "bigint") { + throw TypeError("sleep: ms must be a number"); } - if (typeof handler !== "function") return; - this.addEventListener(method, handler, { - [kForOnEventAttribute]: true - }); + throw RangeError("sleep: ms must be a number that is greater than 0 but less than Infinity"); + } + const target = Date.now() + Number(ms); + while (target > Date.now()) { } - }); - }); - WebSocket3.prototype.addEventListener = addEventListener; - WebSocket3.prototype.removeEventListener = removeEventListener; - module14.exports = WebSocket3; - function initAsClient(websocket, address, protocols, options2) { - const opts = { - protocolVersion: protocolVersions[1], - maxPayload: 100 * 1024 * 1024, - skipUTF8Validation: false, - perMessageDeflate: true, - followRedirects: false, - maxRedirects: 10, - ...options2, - createConnection: void 0, - socketPath: void 0, - hostname: void 0, - protocol: void 0, - timeout: void 0, - method: void 0, - host: void 0, - path: void 0, - port: void 0 }; - if (!protocolVersions.includes(opts.protocolVersion)) { - throw new RangeError( - `Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})` - ); - } - let parsedUrl; - if (address instanceof URL2) { - parsedUrl = address; - websocket._url = address.href; - } else { - try { - parsedUrl = new URL2(address); - } catch (e2) { - throw new SyntaxError(`Invalid URL: ${address}`); + module14.exports = sleep; + } + } +}); +var require_sonic_boom = __commonJS({ + "node_modules/.deno/sonic-boom@3.8.1/node_modules/sonic-boom/index.js"(exports2, module14) { + "use strict"; + var fs = __require2("node:fs"); + var EventEmitter = __require2("node:events"); + var inherits = __require2("node:util").inherits; + var path8 = __require2("node:path"); + var sleep = require_atomic_sleep(); + var BUSY_WRITE_TIMEOUT = 100; + var kEmptyBuffer = Buffer.allocUnsafe(0); + var MAX_WRITE = 16 * 1024; + var kContentModeBuffer = "buffer"; + var kContentModeUtf8 = "utf8"; + function openFile(file, sonic) { + sonic._opening = true; + sonic._writing = true; + sonic._asyncDrainScheduled = false; + function fileOpened(err, fd) { + if (err) { + sonic._reopening = false; + sonic._writing = false; + sonic._opening = false; + if (sonic.sync) { + process.nextTick(() => { + if (sonic.listenerCount("error") > 0) { + sonic.emit("error", err); + } + }); + } else { + sonic.emit("error", err); + } + return; } - websocket._url = address; - } - const isSecure = parsedUrl.protocol === "wss:"; - const isUnixSocket = parsedUrl.protocol === "ws+unix:"; - let invalidURLMessage; - if (parsedUrl.protocol !== "ws:" && !isSecure && !isUnixSocket) { - invalidURLMessage = `The URL's protocol must be one of "ws:", "wss:", or "ws+unix:"`; - } else if (isUnixSocket && !parsedUrl.pathname) { - invalidURLMessage = "The URL's pathname is empty"; - } else if (parsedUrl.hash) { - invalidURLMessage = "The URL contains a fragment identifier"; - } - if (invalidURLMessage) { - const err = new SyntaxError(invalidURLMessage); - if (websocket._redirects === 0) { - throw err; + const reopening = sonic._reopening; + sonic.fd = fd; + sonic.file = file; + sonic._reopening = false; + sonic._opening = false; + sonic._writing = false; + if (sonic.sync) { + process.nextTick(() => sonic.emit("ready")); } else { - emitErrorAndClose(websocket, err); + sonic.emit("ready"); + } + if (sonic.destroyed) { return; } + if (!sonic._writing && sonic._len > sonic.minLength || sonic._flushPending) { + sonic._actualWrite(); + } else if (reopening) { + process.nextTick(() => sonic.emit("drain")); + } } - const defaultPort = isSecure ? 443 : 80; - const key = randomBytes3(16).toString("base64"); - const get2 = isSecure ? https.get : http.get; - const protocolSet = /* @__PURE__ */ new Set(); - let perMessageDeflate; - opts.createConnection = isSecure ? tlsConnect : netConnect; - opts.defaultPort = opts.defaultPort || defaultPort; - opts.port = parsedUrl.port || defaultPort; - opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname; - opts.headers = { - "Sec-WebSocket-Version": opts.protocolVersion, - "Sec-WebSocket-Key": key, - Connection: "Upgrade", - Upgrade: "websocket", - ...opts.headers - }; - opts.path = parsedUrl.pathname + parsedUrl.search; - opts.timeout = opts.handshakeTimeout; - if (opts.perMessageDeflate) { - perMessageDeflate = new PerMessageDeflate( - opts.perMessageDeflate !== true ? opts.perMessageDeflate : {}, - false, - opts.maxPayload - ); - opts.headers["Sec-WebSocket-Extensions"] = format52({ - [PerMessageDeflate.extensionName]: perMessageDeflate.offer() + const flags = sonic.append ? "a" : "w"; + const mode = sonic.mode; + if (sonic.sync) { + try { + if (sonic.mkdir) fs.mkdirSync(path8.dirname(file), { recursive: true }); + const fd = fs.openSync(file, flags, mode); + fileOpened(null, fd); + } catch (err) { + fileOpened(err); + throw err; + } + } else if (sonic.mkdir) { + fs.mkdir(path8.dirname(file), { recursive: true }, (err) => { + if (err) return fileOpened(err); + fs.open(file, flags, mode, fileOpened); }); + } else { + fs.open(file, flags, mode, fileOpened); } - if (protocols.length) { - for (const protocol of protocols) { - if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) { - throw new SyntaxError( - "An invalid or duplicated subprotocol was specified" - ); - } - protocolSet.add(protocol); - } - opts.headers["Sec-WebSocket-Protocol"] = protocols.join(","); + } + function SonicBoom(opts) { + if (!(this instanceof SonicBoom)) { + return new SonicBoom(opts); } - if (opts.origin) { - if (opts.protocolVersion < 13) { - opts.headers["Sec-WebSocket-Origin"] = opts.origin; - } else { - opts.headers.Origin = opts.origin; - } + let { fd, dest, minLength, maxLength, maxWrite, sync, append = true, mkdir: mkdir4, retryEAGAIN, fsync, contentMode, mode } = opts || {}; + fd = fd || dest; + this._len = 0; + this.fd = -1; + this._bufs = []; + this._lens = []; + this._writing = false; + this._ending = false; + this._reopening = false; + this._asyncDrainScheduled = false; + this._flushPending = false; + this._hwm = Math.max(minLength || 0, 16387); + this.file = null; + this.destroyed = false; + this.minLength = minLength || 0; + this.maxLength = maxLength || 0; + this.maxWrite = maxWrite || MAX_WRITE; + this.sync = sync || false; + this.writable = true; + this._fsync = fsync || false; + this.append = append || false; + this.mode = mode; + this.retryEAGAIN = retryEAGAIN || (() => true); + this.mkdir = mkdir4 || false; + let fsWriteSync; + let fsWrite; + if (contentMode === kContentModeBuffer) { + this._writingBuf = kEmptyBuffer; + this.write = writeBuffer; + this.flush = flushBuffer; + this.flushSync = flushBufferSync; + this._actualWrite = actualWriteBuffer; + fsWriteSync = () => fs.writeSync(this.fd, this._writingBuf); + fsWrite = () => fs.write(this.fd, this._writingBuf, this.release); + } else if (contentMode === void 0 || contentMode === kContentModeUtf8) { + this._writingBuf = ""; + this.write = write; + this.flush = flush; + this.flushSync = flushSync; + this._actualWrite = actualWrite; + fsWriteSync = () => fs.writeSync(this.fd, this._writingBuf, "utf8"); + fsWrite = () => fs.write(this.fd, this._writingBuf, "utf8", this.release); + } else { + throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`); } - if (parsedUrl.username || parsedUrl.password) { - opts.auth = `${parsedUrl.username}:${parsedUrl.password}`; + if (typeof fd === "number") { + this.fd = fd; + process.nextTick(() => this.emit("ready")); + } else if (typeof fd === "string") { + openFile(fd, this); + } else { + throw new Error("SonicBoom supports only file descriptors and files"); } - if (isUnixSocket) { - const parts = opts.path.split(":"); - opts.socketPath = parts[0]; - opts.path = parts[1]; + if (this.minLength >= this.maxWrite) { + throw new Error(`minLength should be smaller than maxWrite (${this.maxWrite})`); } - if (opts.followRedirects) { - if (websocket._redirects === 0) { - websocket._originalHost = parsedUrl.host; - const headers = options2 && options2.headers; - options2 = { ...options2, headers: {} }; - if (headers) { - for (const [key2, value] of Object.entries(headers)) { - options2.headers[key2.toLowerCase()] = value; + this.release = (err, n) => { + if (err) { + if ((err.code === "EAGAIN" || err.code === "EBUSY") && this.retryEAGAIN(err, this._writingBuf.length, this._len - this._writingBuf.length)) { + if (this.sync) { + try { + sleep(BUSY_WRITE_TIMEOUT); + this.release(void 0, 0); + } catch (err2) { + this.release(err2); + } + } else { + setTimeout(fsWrite, BUSY_WRITE_TIMEOUT); } + } else { + this._writing = false; + this.emit("error", err); } - } else if (parsedUrl.host !== websocket._originalHost) { - delete opts.headers.authorization; - delete opts.headers.cookie; - delete opts.headers.host; - opts.auth = void 0; - } - if (opts.auth && !options2.headers.authorization) { - options2.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64"); + return; } - } - let req = websocket._req = get2(opts); - if (opts.timeout) { - req.on("timeout", () => { - abortHandshake(websocket, req, "Opening handshake has timed out"); - }); - } - req.on("error", (err) => { - if (req === null || req.aborted) return; - req = websocket._req = null; - emitErrorAndClose(websocket, err); - }); - req.on("response", (res) => { - const location = res.headers.location; - const statusCode = res.statusCode; - if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) { - if (++websocket._redirects > opts.maxRedirects) { - abortHandshake(websocket, req, "Maximum redirects exceeded"); + this.emit("write", n); + const releasedBufObj = releaseWritingBuf(this._writingBuf, this._len, n); + this._len = releasedBufObj.len; + this._writingBuf = releasedBufObj.writingBuf; + if (this._writingBuf.length) { + if (!this.sync) { + fsWrite(); return; } - req.abort(); - let addr; try { - addr = new URL2(location, address); - } catch (e2) { - const err = new SyntaxError(`Invalid URL: ${location}`); - emitErrorAndClose(websocket, err); + do { + const n2 = fsWriteSync(); + const releasedBufObj2 = releaseWritingBuf(this._writingBuf, this._len, n2); + this._len = releasedBufObj2.len; + this._writingBuf = releasedBufObj2.writingBuf; + } while (this._writingBuf.length); + } catch (err2) { + this.release(err2); return; } - initAsClient(websocket, addr, protocols, options2); - } else if (!websocket.emit("unexpected-response", req, res)) { - abortHandshake( - websocket, - req, - `Unexpected server response: ${res.statusCode}` - ); - } - }); - req.on("upgrade", (res, socket, head) => { - websocket.emit("upgrade", res); - if (websocket.readyState !== WebSocket3.CONNECTING) return; - req = websocket._req = null; - const digest = createHash("sha1").update(key + GUID).digest("base64"); - if (res.headers["sec-websocket-accept"] !== digest) { - abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header"); - return; - } - const serverProt = res.headers["sec-websocket-protocol"]; - let protError; - if (serverProt !== void 0) { - if (!protocolSet.size) { - protError = "Server sent a subprotocol but none was requested"; - } else if (!protocolSet.has(serverProt)) { - protError = "Server sent an invalid subprotocol"; - } - } else if (protocolSet.size) { - protError = "Server sent no subprotocol"; } - if (protError) { - abortHandshake(websocket, socket, protError); - return; + if (this._fsync) { + fs.fsyncSync(this.fd); } - if (serverProt) websocket._protocol = serverProt; - const secWebSocketExtensions = res.headers["sec-websocket-extensions"]; - if (secWebSocketExtensions !== void 0) { - if (!perMessageDeflate) { - const message = "Server sent a Sec-WebSocket-Extensions header but no extension was requested"; - abortHandshake(websocket, socket, message); - return; - } - let extensions; - try { - extensions = parse52(secWebSocketExtensions); - } catch (err) { - const message = "Invalid Sec-WebSocket-Extensions header"; - abortHandshake(websocket, socket, message); - return; - } - const extensionNames = Object.keys(extensions); - if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate.extensionName) { - const message = "Server indicated an extension that was not requested"; - abortHandshake(websocket, socket, message); - return; + const len = this._len; + if (this._reopening) { + this._writing = false; + this._reopening = false; + this.reopen(); + } else if (len > this.minLength) { + this._actualWrite(); + } else if (this._ending) { + if (len > 0) { + this._actualWrite(); + } else { + this._writing = false; + actualClose(this); } - try { - perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]); - } catch (err) { - const message = "Invalid Sec-WebSocket-Extensions header"; - abortHandshake(websocket, socket, message); - return; + } else { + this._writing = false; + if (this.sync) { + if (!this._asyncDrainScheduled) { + this._asyncDrainScheduled = true; + process.nextTick(emitDrain, this); + } + } else { + this.emit("drain"); } - websocket._extensions[PerMessageDeflate.extensionName] = perMessageDeflate; } - websocket.setSocket(socket, head, { - generateMask: opts.generateMask, - maxPayload: opts.maxPayload, - skipUTF8Validation: opts.skipUTF8Validation - }); - }); - } - function emitErrorAndClose(websocket, err) { - websocket._readyState = WebSocket3.CLOSING; - websocket.emit("error", err); - websocket.emitClose(); - } - function netConnect(options2) { - options2.path = options2.socketPath; - return net.connect(options2); + }; + this.on("newListener", function(name) { + if (name === "drain") { + this._asyncDrainScheduled = false; + } + }); } - function tlsConnect(options2) { - options2.path = void 0; - if (!options2.servername && options2.servername !== "") { - options2.servername = net.isIP(options2.host) ? "" : options2.host; + function releaseWritingBuf(writingBuf, len, n) { + if (typeof writingBuf === "string" && Buffer.byteLength(writingBuf) !== n) { + n = Buffer.from(writingBuf).subarray(0, n).toString().length; } - return tls.connect(options2); + len = Math.max(len - n, 0); + writingBuf = writingBuf.slice(n); + return { writingBuf, len }; } - function abortHandshake(websocket, stream, message) { - websocket._readyState = WebSocket3.CLOSING; - const err = new Error(message); - Error.captureStackTrace(err, abortHandshake); - if (stream.setHeader) { - stream.abort(); - if (stream.socket && !stream.socket.destroyed) { - stream.socket.destroy(); - } - stream.once("abort", websocket.emitClose.bind(websocket)); - websocket.emit("error", err); - } else { - stream.destroy(err); - stream.once("error", websocket.emit.bind(websocket, "error")); - stream.once("close", websocket.emitClose.bind(websocket)); - } + function emitDrain(sonic) { + const hasListeners = sonic.listenerCount("drain") > 0; + if (!hasListeners) return; + sonic._asyncDrainScheduled = false; + sonic.emit("drain"); } - function sendAfterClose(websocket, data, cb) { - if (data) { - const length2 = toBuffer(data).length; - if (websocket._socket) websocket._sender._bufferedBytes += length2; - else websocket._bufferedAmount += length2; + inherits(SonicBoom, EventEmitter); + function mergeBuf(bufs, len) { + if (bufs.length === 0) { + return kEmptyBuffer; } - if (cb) { - const err = new Error( - `WebSocket is not open: readyState ${websocket.readyState} (${readyStates[websocket.readyState]})` - ); - cb(err); + if (bufs.length === 1) { + return bufs[0]; } + return Buffer.concat(bufs, len); } - function receiverOnConclude(code2, reason) { - const websocket = this[kWebSocket]; - websocket._closeFrameReceived = true; - websocket._closeMessage = reason; - websocket._closeCode = code2; - if (websocket._socket[kWebSocket] === void 0) return; - websocket._socket.removeListener("data", socketOnData); - process.nextTick(resume, websocket._socket); - if (code2 === 1005) websocket.close(); - else websocket.close(code2, reason); - } - function receiverOnDrain() { - const websocket = this[kWebSocket]; - if (!websocket.isPaused) websocket._socket.resume(); - } - function receiverOnError(err) { - const websocket = this[kWebSocket]; - if (websocket._socket[kWebSocket] !== void 0) { - websocket._socket.removeListener("data", socketOnData); - process.nextTick(resume, websocket._socket); - websocket.close(err[kStatusCode]); + function write(data) { + if (this.destroyed) { + throw new Error("SonicBoom destroyed"); } - websocket.emit("error", err); - } - function receiverOnFinish() { - this[kWebSocket].emitClose(); - } - function receiverOnMessage(data, isBinary) { - this[kWebSocket].emit("message", data, isBinary); - } - function receiverOnPing(data) { - const websocket = this[kWebSocket]; - websocket.pong(data, !websocket._isServer, NOOP); - websocket.emit("ping", data); - } - function receiverOnPong(data) { - this[kWebSocket].emit("pong", data); - } - function resume(stream) { - stream.resume(); - } - function socketOnClose() { - const websocket = this[kWebSocket]; - this.removeListener("close", socketOnClose); - this.removeListener("data", socketOnData); - this.removeListener("end", socketOnEnd); - websocket._readyState = WebSocket3.CLOSING; - let chunk; - if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && (chunk = websocket._socket.read()) !== null) { - websocket._receiver.write(chunk); + const len = this._len + data.length; + const bufs = this._bufs; + if (this.maxLength && len > this.maxLength) { + this.emit("drop", data); + return this._len < this._hwm; } - websocket._receiver.end(); - this[kWebSocket] = void 0; - clearTimeout(websocket._closeTimer); - if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) { - websocket.emitClose(); + if (bufs.length === 0 || bufs[bufs.length - 1].length + data.length > this.maxWrite) { + bufs.push("" + data); } else { - websocket._receiver.on("error", receiverOnFinish); - websocket._receiver.on("finish", receiverOnFinish); + bufs[bufs.length - 1] += data; } - } - function socketOnData(chunk) { - if (!this[kWebSocket]._receiver.write(chunk)) { - this.pause(); + this._len = len; + if (!this._writing && this._len >= this.minLength) { + this._actualWrite(); } + return this._len < this._hwm; } - function socketOnEnd() { - const websocket = this[kWebSocket]; - websocket._readyState = WebSocket3.CLOSING; - websocket._receiver.end(); - this.end(); - } - function socketOnError() { - const websocket = this[kWebSocket]; - this.removeListener("error", socketOnError); - this.on("error", NOOP); - if (websocket) { - websocket._readyState = WebSocket3.CLOSING; - this.destroy(); + function writeBuffer(data) { + if (this.destroyed) { + throw new Error("SonicBoom destroyed"); + } + const len = this._len + data.length; + const bufs = this._bufs; + const lens = this._lens; + if (this.maxLength && len > this.maxLength) { + this.emit("drop", data); + return this._len < this._hwm; + } + if (bufs.length === 0 || lens[lens.length - 1] + data.length > this.maxWrite) { + bufs.push([data]); + lens.push(data.length); + } else { + bufs[bufs.length - 1].push(data); + lens[lens.length - 1] += data.length; } + this._len = len; + if (!this._writing && this._len >= this.minLength) { + this._actualWrite(); + } + return this._len < this._hwm; } - } -}); -var require_subprotocol = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/subprotocol.js"(exports2, module14) { - "use strict"; - var { tokenChars } = require_validation2(); - function parse52(header) { - const protocols = /* @__PURE__ */ new Set(); - let start = -1; - let end = -1; - let i2 = 0; - for (i2; i2 < header.length; i2++) { - const code2 = header.charCodeAt(i2); - if (end === -1 && tokenChars[code2] === 1) { - if (start === -1) start = i2; - } else if (i2 !== 0 && (code2 === 32 || code2 === 9)) { - if (end === -1 && start !== -1) end = i2; - } else if (code2 === 44) { - if (start === -1) { - throw new SyntaxError(`Unexpected character at index ${i2}`); - } - if (end === -1) end = i2; - const protocol2 = header.slice(start, end); - if (protocols.has(protocol2)) { - throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`); - } - protocols.add(protocol2); - start = end = -1; + function callFlushCallbackOnDrain(cb) { + this._flushPending = true; + const onDrain = () => { + if (!this._fsync) { + fs.fsync(this.fd, (err) => { + this._flushPending = false; + cb(err); + }); } else { - throw new SyntaxError(`Unexpected character at index ${i2}`); + this._flushPending = false; + cb(); } + this.off("error", onError); + }; + const onError = (err) => { + this._flushPending = false; + cb(err); + this.off("drain", onDrain); + }; + this.once("drain", onDrain); + this.once("error", onError); + } + function flush(cb) { + if (cb != null && typeof cb !== "function") { + throw new Error("flush cb must be a function"); } - if (start === -1 || end !== -1) { - throw new SyntaxError("Unexpected end of input"); + if (this.destroyed) { + const error2 = new Error("SonicBoom destroyed"); + if (cb) { + cb(error2); + return; + } + throw error2; } - const protocol = header.slice(start, i2); - if (protocols.has(protocol)) { - throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`); + if (this.minLength <= 0) { + cb?.(); + return; } - protocols.add(protocol); - return protocols; + if (cb) { + callFlushCallbackOnDrain.call(this, cb); + } + if (this._writing) { + return; + } + if (this._bufs.length === 0) { + this._bufs.push(""); + } + this._actualWrite(); } - module14.exports = { parse: parse52 }; - } -}); -var require_websocket_server = __commonJS({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/websocket-server.js"(exports2, module14) { - "use strict"; - var EventEmitter = __require2("events"); - var http = __require2("http"); - var https = __require2("https"); - var net = __require2("net"); - var tls = __require2("tls"); - var { createHash } = __require2("crypto"); - var extension = require_extension(); - var PerMessageDeflate = require_permessage_deflate(); - var subprotocol = require_subprotocol(); - var WebSocket3 = require_websocket(); - var { GUID, kWebSocket } = require_constants2(); - var keyRegex = /^[+/0-9A-Za-z]{22}==$/; - var RUNNING = 0; - var CLOSING = 1; - var CLOSED = 2; - var WebSocketServer2 = class extends EventEmitter { - /** - * Create a `WebSocketServer` instance. - * - * @param {Object} options Configuration options - * @param {Number} [options.backlog=511] The maximum length of the queue of - * pending connections - * @param {Boolean} [options.clientTracking=true] Specifies whether or not to - * track clients - * @param {Function} [options.handleProtocols] A hook to handle protocols - * @param {String} [options.host] The hostname where to bind the server - * @param {Number} [options.maxPayload=104857600] The maximum allowed message - * size - * @param {Boolean} [options.noServer=false] Enable no server mode - * @param {String} [options.path] Accept only connections matching this path - * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable - * permessage-deflate - * @param {Number} [options.port] The port where to bind the server - * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S - * server to use - * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or - * not to skip UTF-8 validation for text and close messages - * @param {Function} [options.verifyClient] A hook to reject connections - * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket` - * class to use. It must be the `WebSocket` class or class that extends it - * @param {Function} [callback] A listener for the `listening` event - */ - constructor(options2, callback) { - super(); - options2 = { - maxPayload: 100 * 1024 * 1024, - skipUTF8Validation: false, - perMessageDeflate: false, - handleProtocols: null, - clientTracking: true, - verifyClient: null, - noServer: false, - backlog: null, - // use default (511 as implemented in net.js) - server: null, - host: null, - path: null, - port: null, - WebSocket: WebSocket3, - ...options2 - }; - if (options2.port == null && !options2.server && !options2.noServer || options2.port != null && (options2.server || options2.noServer) || options2.server && options2.noServer) { - throw new TypeError( - 'One and only one of the "port", "server", or "noServer" options must be specified' - ); - } - if (options2.port != null) { - this._server = http.createServer((req, res) => { - const body = http.STATUS_CODES[426]; - res.writeHead(426, { - "Content-Length": body.length, - "Content-Type": "text/plain" - }); - res.end(body); - }); - this._server.listen( - options2.port, - options2.host, - options2.backlog, - callback - ); - } else if (options2.server) { - this._server = options2.server; + function flushBuffer(cb) { + if (cb != null && typeof cb !== "function") { + throw new Error("flush cb must be a function"); + } + if (this.destroyed) { + const error2 = new Error("SonicBoom destroyed"); + if (cb) { + cb(error2); + return; } - if (this._server) { - const emitConnection = this.emit.bind(this, "connection"); - this._removeListeners = addListeners(this._server, { - listening: this.emit.bind(this, "listening"), - error: this.emit.bind(this, "error"), - upgrade: (req, socket, head) => { - this.handleUpgrade(req, socket, head, emitConnection); + throw error2; + } + if (this.minLength <= 0) { + cb?.(); + return; + } + if (cb) { + callFlushCallbackOnDrain.call(this, cb); + } + if (this._writing) { + return; + } + if (this._bufs.length === 0) { + this._bufs.push([]); + this._lens.push(0); + } + this._actualWrite(); + } + SonicBoom.prototype.reopen = function(file) { + if (this.destroyed) { + throw new Error("SonicBoom destroyed"); + } + if (this._opening) { + this.once("ready", () => { + this.reopen(file); + }); + return; + } + if (this._ending) { + return; + } + if (!this.file) { + throw new Error("Unable to reopen a file descriptor, you must pass a file to SonicBoom"); + } + if (file) { + this.file = file; + } + this._reopening = true; + if (this._writing) { + return; + } + const fd = this.fd; + this.once("ready", () => { + if (fd !== this.fd) { + fs.close(fd, (err) => { + if (err) { + return this.emit("error", err); } }); } - if (options2.perMessageDeflate === true) options2.perMessageDeflate = {}; - if (options2.clientTracking) { - this.clients = /* @__PURE__ */ new Set(); - this._shouldEmitClose = false; - } - this.options = options2; - this._state = RUNNING; + }); + openFile(this.file, this); + }; + SonicBoom.prototype.end = function() { + if (this.destroyed) { + throw new Error("SonicBoom destroyed"); } - /** - * Returns the bound address, the address family name, and port of the server - * as reported by the operating system if listening on an IP socket. - * If the server is listening on a pipe or UNIX domain socket, the name is - * returned as a string. - * - * @return {(Object|String|null)} The address of the server - * @public - */ - address() { - if (this.options.noServer) { - throw new Error('The server is operating in "noServer" mode'); - } - if (!this._server) return null; - return this._server.address(); + if (this._opening) { + this.once("ready", () => { + this.end(); + }); + return; } - /** - * Stop the server from accepting new connections and emit the `'close'` event - * when all existing connections are closed. - * - * @param {Function} [cb] A one-time listener for the `'close'` event - * @public - */ - close(cb) { - if (this._state === CLOSED) { - if (cb) { - this.once("close", () => { - cb(new Error("The server is not running")); - }); - } - process.nextTick(emitClose, this); - return; + if (this._ending) { + return; + } + this._ending = true; + if (this._writing) { + return; + } + if (this._len > 0 && this.fd >= 0) { + this._actualWrite(); + } else { + actualClose(this); + } + }; + function flushSync() { + if (this.destroyed) { + throw new Error("SonicBoom destroyed"); + } + if (this.fd < 0) { + throw new Error("sonic boom is not ready yet"); + } + if (!this._writing && this._writingBuf.length > 0) { + this._bufs.unshift(this._writingBuf); + this._writingBuf = ""; + } + let buf2 = ""; + while (this._bufs.length || buf2) { + if (buf2.length <= 0) { + buf2 = this._bufs[0]; } - if (cb) this.once("close", cb); - if (this._state === CLOSING) return; - this._state = CLOSING; - if (this.options.noServer || this.options.server) { - if (this._server) { - this._removeListeners(); - this._removeListeners = this._server = null; + try { + const n = fs.writeSync(this.fd, buf2, "utf8"); + const releasedBufObj = releaseWritingBuf(buf2, this._len, n); + buf2 = releasedBufObj.writingBuf; + this._len = releasedBufObj.len; + if (buf2.length <= 0) { + this._bufs.shift(); } - if (this.clients) { - if (!this.clients.size) { - process.nextTick(emitClose, this); - } else { - this._shouldEmitClose = true; - } - } else { - process.nextTick(emitClose, this); + } catch (err) { + const shouldRetry = err.code === "EAGAIN" || err.code === "EBUSY"; + if (shouldRetry && !this.retryEAGAIN(err, buf2.length, this._len - buf2.length)) { + throw err; } - } else { - const server = this._server; - this._removeListeners(); - this._removeListeners = this._server = null; - server.close(() => { - emitClose(this); - }); - } - } - /** - * See if a given request should be handled by this server instance. - * - * @param {http.IncomingMessage} req Request object to inspect - * @return {Boolean} `true` if the request is valid, else `false` - * @public - */ - shouldHandle(req) { - if (this.options.path) { - const index = req.url.indexOf("?"); - const pathname = index !== -1 ? req.url.slice(0, index) : req.url; - if (pathname !== this.options.path) return false; + sleep(BUSY_WRITE_TIMEOUT); } - return true; } - /** - * Handle a HTTP Upgrade request. - * - * @param {http.IncomingMessage} req The request object - * @param {(net.Socket|tls.Socket)} socket The network socket between the - * server and client - * @param {Buffer} head The first packet of the upgraded stream - * @param {Function} cb Callback - * @public - */ - handleUpgrade(req, socket, head, cb) { - socket.on("error", socketOnError); - const key = req.headers["sec-websocket-key"] !== void 0 ? req.headers["sec-websocket-key"] : false; - const version3 = +req.headers["sec-websocket-version"]; - if (req.method !== "GET" || req.headers.upgrade.toLowerCase() !== "websocket" || !key || !keyRegex.test(key) || version3 !== 8 && version3 !== 13 || !this.shouldHandle(req)) { - return abortHandshake(socket, 400); + try { + fs.fsyncSync(this.fd); + } catch { + } + } + function flushBufferSync() { + if (this.destroyed) { + throw new Error("SonicBoom destroyed"); + } + if (this.fd < 0) { + throw new Error("sonic boom is not ready yet"); + } + if (!this._writing && this._writingBuf.length > 0) { + this._bufs.unshift([this._writingBuf]); + this._writingBuf = kEmptyBuffer; + } + let buf2 = kEmptyBuffer; + while (this._bufs.length || buf2.length) { + if (buf2.length <= 0) { + buf2 = mergeBuf(this._bufs[0], this._lens[0]); } - const secWebSocketProtocol = req.headers["sec-websocket-protocol"]; - let protocols = /* @__PURE__ */ new Set(); - if (secWebSocketProtocol !== void 0) { - try { - protocols = subprotocol.parse(secWebSocketProtocol); - } catch (err) { - return abortHandshake(socket, 400); + try { + const n = fs.writeSync(this.fd, buf2); + buf2 = buf2.subarray(n); + this._len = Math.max(this._len - n, 0); + if (buf2.length <= 0) { + this._bufs.shift(); + this._lens.shift(); } - } - const secWebSocketExtensions = req.headers["sec-websocket-extensions"]; - const extensions = {}; - if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) { - const perMessageDeflate = new PerMessageDeflate( - this.options.perMessageDeflate, - true, - this.options.maxPayload - ); - try { - const offers = extension.parse(secWebSocketExtensions); - if (offers[PerMessageDeflate.extensionName]) { - perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]); - extensions[PerMessageDeflate.extensionName] = perMessageDeflate; - } - } catch (err) { - return abortHandshake(socket, 400); + } catch (err) { + const shouldRetry = err.code === "EAGAIN" || err.code === "EBUSY"; + if (shouldRetry && !this.retryEAGAIN(err, buf2.length, this._len - buf2.length)) { + throw err; } + sleep(BUSY_WRITE_TIMEOUT); } - if (this.options.verifyClient) { - const info = { - origin: req.headers[`${version3 === 8 ? "sec-websocket-origin" : "origin"}`], - secure: !!(req.socket.authorized || req.socket.encrypted), - req - }; - if (this.options.verifyClient.length === 2) { - this.options.verifyClient(info, (verified, code2, message, headers) => { - if (!verified) { - return abortHandshake(socket, code2 || 401, message, headers); - } - this.completeUpgrade( - extensions, - key, - protocols, - req, - socket, - head, - cb - ); - }); - return; - } - if (!this.options.verifyClient(info)) return abortHandshake(socket, 401); + } + } + SonicBoom.prototype.destroy = function() { + if (this.destroyed) { + return; + } + actualClose(this); + }; + function actualWrite() { + const release = this.release; + this._writing = true; + this._writingBuf = this._writingBuf || this._bufs.shift() || ""; + if (this.sync) { + try { + const written = fs.writeSync(this.fd, this._writingBuf, "utf8"); + release(null, written); + } catch (err) { + release(err); } - this.completeUpgrade(extensions, key, protocols, req, socket, head, cb); + } else { + fs.write(this.fd, this._writingBuf, "utf8", release); } - /** - * Upgrade the connection to WebSocket. - * - * @param {Object} extensions The accepted extensions - * @param {String} key The value of the `Sec-WebSocket-Key` header - * @param {Set} protocols The subprotocols - * @param {http.IncomingMessage} req The request object - * @param {(net.Socket|tls.Socket)} socket The network socket between the - * server and client - * @param {Buffer} head The first packet of the upgraded stream - * @param {Function} cb Callback - * @throws {Error} If called more than once with the same socket - * @private - */ - completeUpgrade(extensions, key, protocols, req, socket, head, cb) { - if (!socket.readable || !socket.writable) return socket.destroy(); - if (socket[kWebSocket]) { - throw new Error( - "server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration" - ); + } + function actualWriteBuffer() { + const release = this.release; + this._writing = true; + this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift()); + if (this.sync) { + try { + const written = fs.writeSync(this.fd, this._writingBuf); + release(null, written); + } catch (err) { + release(err); } - if (this._state > RUNNING) return abortHandshake(socket, 503); - const digest = createHash("sha1").update(key + GUID).digest("base64"); - const headers = [ - "HTTP/1.1 101 Switching Protocols", - "Upgrade: websocket", - "Connection: Upgrade", - `Sec-WebSocket-Accept: ${digest}` - ]; - const ws = new this.options.WebSocket(null); - if (protocols.size) { - const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value; - if (protocol) { - headers.push(`Sec-WebSocket-Protocol: ${protocol}`); - ws._protocol = protocol; - } + } else { + fs.write(this.fd, this._writingBuf, release); + } + } + function actualClose(sonic) { + if (sonic.fd === -1) { + sonic.once("ready", actualClose.bind(null, sonic)); + return; + } + sonic.destroyed = true; + sonic._bufs = []; + sonic._lens = []; + fs.fsync(sonic.fd, closeWrapped); + function closeWrapped() { + if (sonic.fd !== 1 && sonic.fd !== 2) { + fs.close(sonic.fd, done); + } else { + done(); } - if (extensions[PerMessageDeflate.extensionName]) { - const params = extensions[PerMessageDeflate.extensionName].params; - const value = extension.format({ - [PerMessageDeflate.extensionName]: [params] - }); - headers.push(`Sec-WebSocket-Extensions: ${value}`); - ws._extensions = extensions; + } + function done(err) { + if (err) { + sonic.emit("error", err); + return; } - this.emit("headers", headers, req); - socket.write(headers.concat("\r\n").join("\r\n")); - socket.removeListener("error", socketOnError); - ws.setSocket(socket, head, { - maxPayload: this.options.maxPayload, - skipUTF8Validation: this.options.skipUTF8Validation - }); - if (this.clients) { - this.clients.add(ws); - ws.on("close", () => { - this.clients.delete(ws); - if (this._shouldEmitClose && !this.clients.size) { - process.nextTick(emitClose, this); - } - }); + if (sonic._ending && !sonic._writing) { + sonic.emit("finish"); } - cb(ws, req); + sonic.emit("close"); } + } + SonicBoom.SonicBoom = SonicBoom; + SonicBoom.default = SonicBoom; + module14.exports = SonicBoom; + } +}); +var require_on_exit_leak_free = __commonJS({ + "node_modules/.deno/on-exit-leak-free@2.1.2/node_modules/on-exit-leak-free/index.js"(exports2, module14) { + "use strict"; + var refs = { + exit: [], + beforeExit: [] }; - module14.exports = WebSocketServer2; - function addListeners(server, map) { - for (const event of Object.keys(map)) server.on(event, map[event]); - return function removeListeners() { - for (const event of Object.keys(map)) { - server.removeListener(event, map[event]); + var functions = { + exit: onExit, + beforeExit: onBeforeExit + }; + var registry2; + function ensureRegistry() { + if (registry2 === void 0) { + registry2 = new FinalizationRegistry(clear); + } + } + function install(event) { + if (refs[event].length > 0) { + return; + } + process.on(event, functions[event]); + } + function uninstall(event) { + if (refs[event].length > 0) { + return; + } + process.removeListener(event, functions[event]); + if (refs.exit.length === 0 && refs.beforeExit.length === 0) { + registry2 = void 0; + } + } + function onExit() { + callRefs("exit"); + } + function onBeforeExit() { + callRefs("beforeExit"); + } + function callRefs(event) { + for (const ref of refs[event]) { + const obj = ref.deref(); + const fn = ref.fn; + if (obj !== void 0) { + fn(obj, event); } - }; + } + refs[event] = []; } - function emitClose(server) { - server._state = CLOSED; - server.emit("close"); + function clear(ref) { + for (const event of ["exit", "beforeExit"]) { + const index = refs[event].indexOf(ref); + refs[event].splice(index, index + 1); + uninstall(event); + } } - function socketOnError() { - this.destroy(); + function _register(event, obj, fn) { + if (obj === void 0) { + throw new Error("the object can't be undefined"); + } + install(event); + const ref = new WeakRef(obj); + ref.fn = fn; + ensureRegistry(); + registry2.register(obj, ref); + refs[event].push(ref); } - function abortHandshake(socket, code2, message, headers) { - if (socket.writable) { - message = message || http.STATUS_CODES[code2]; - headers = { - Connection: "close", - "Content-Type": "text/html", - "Content-Length": Buffer.byteLength(message), - ...headers - }; - socket.write( - `HTTP/1.1 ${code2} ${http.STATUS_CODES[code2]}\r -` + Object.keys(headers).map((h2) => `${h2}: ${headers[h2]}`).join("\r\n") + "\r\n\r\n" + message - ); + function register2(obj, fn) { + _register("exit", obj, fn); + } + function registerBeforeExit(obj, fn) { + _register("beforeExit", obj, fn); + } + function unregister(obj) { + if (registry2 === void 0) { + return; + } + registry2.unregister(obj); + for (const event of ["exit", "beforeExit"]) { + refs[event] = refs[event].filter((ref) => { + const _obj = ref.deref(); + return _obj && _obj !== obj; + }); + uninstall(event); } - socket.removeListener("error", socketOnError); - socket.destroy(); } + module14.exports = { + register: register2, + registerBeforeExit, + unregister + }; } }); -var import_stream; -var import_receiver; -var import_sender; -var import_websocket; -var import_websocket_server; -var wrapper_default; -var init_wrapper = __esm({ - "node_modules/.deno/ws@8.5.0/node_modules/ws/wrapper.mjs"() { - import_stream = __toESM(require_stream(), 1); - import_receiver = __toESM(require_receiver(), 1); - import_sender = __toESM(require_sender(), 1); - import_websocket = __toESM(require_websocket(), 1); - import_websocket_server = __toESM(require_websocket_server(), 1); - wrapper_default = import_websocket.default; +var require_package3 = __commonJS({ + "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/package.json"(exports2, module14) { + module14.exports = { + name: "thread-stream", + version: "2.7.0", + description: "A streaming way to send data to a Node.js Worker Thread", + main: "index.js", + types: "index.d.ts", + dependencies: { + "real-require": "^0.2.0" + }, + devDependencies: { + "@types/node": "^20.1.0", + "@types/tap": "^15.0.0", + "@yao-pkg/pkg": "^5.11.5", + desm: "^1.3.0", + fastbench: "^1.0.1", + husky: "^9.0.6", + "pino-elasticsearch": "^8.0.0", + "sonic-boom": "^3.0.0", + standard: "^17.0.0", + tap: "^16.2.0", + "ts-node": "^10.8.0", + typescript: "^5.3.2", + "why-is-node-running": "^2.2.2" + }, + scripts: { + test: 'standard && npm run transpile && tap "test/**/*.test.*js" && tap --ts test/*.test.*ts', + "test:ci": "standard && npm run transpile && npm run test:ci:js && npm run test:ci:ts", + "test:ci:js": 'tap --no-check-coverage --timeout=120 --coverage-report=lcovonly "test/**/*.test.*js"', + "test:ci:ts": 'tap --ts --no-check-coverage --coverage-report=lcovonly "test/**/*.test.*ts"', + "test:yarn": 'npm run transpile && tap "test/**/*.test.js" --no-check-coverage', + transpile: "sh ./test/ts/transpile.sh", + prepare: "husky install" + }, + standard: { + ignore: [ + "test/ts/**/*" + ] + }, + repository: { + type: "git", + url: "git+https://github.com/mcollina/thread-stream.git" + }, + keywords: [ + "worker", + "thread", + "threads", + "stream" + ], + author: "Matteo Collina ", + license: "MIT", + bugs: { + url: "https://github.com/mcollina/thread-stream/issues" + }, + homepage: "https://github.com/mcollina/thread-stream#readme" + }; } }); -function createErrorResponse(data) { - return JSON.stringify({ type: ERROR, data }); -} -function createPushErrorResponse(data) { - return JSON.stringify({ - type: ERROR, - data: { - ...data, - type: REQUEST_TYPE.PUSH_ACTION +var require_wait = __commonJS({ + "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/lib/wait.js"(exports2, module14) { + "use strict"; + var MAX_TIMEOUT = 1e3; + function wait(state, index, expected, timeout, done) { + const max = Date.now() + timeout; + let current = Atomics.load(state, index); + if (current === expected) { + done(null, "ok"); + return; + } + let prior = current; + const check2 = (backoff) => { + if (Date.now() > max) { + done(null, "timed-out"); + } else { + setTimeout(() => { + prior = current; + current = Atomics.load(state, index); + if (current === prior) { + check2(backoff >= MAX_TIMEOUT ? MAX_TIMEOUT : backoff * 2); + } else { + if (current === expected) done(null, "ok"); + else done(null, "not-equal"); + } + }, backoff); + } + }; + check2(1); } - }); -} -function createNotification(type, data) { - return JSON.stringify({ type, data }); -} -function createOkResponse(data) { - return JSON.stringify({ type: OK, data }); -} -function createServer(httpServer, options2 = {}) { - const server = new import_websocket_server.default({ - ...defaultOptions3, - ...options2, - ...{ clientTracking: true }, - server: httpServer - }); - server.channels = /* @__PURE__ */ new Set(); - server.customServerEventHandlers = { ...options2.serverHandlers }; - server.customSocketEventHandlers = { ...options2.socketHandlers }; - server.customMessageHandlers = { ...options2.messageHandlers }; - server.pingIntervalID = void 0; - server.subscribersByChannelID = /* @__PURE__ */ Object.create(null); - server.pushSubscriptions = /* @__PURE__ */ Object.create(null); - const handlers = Object.keys(defaultServerHandlers); - handlers.forEach((name) => { - server.on(name, (...args) => { - try { - ; - defaultServerHandlers[name].apply(server, args); - server.customServerEventHandlers[name]?.apply(server, args); - } catch (error2) { - server.emit("error", error2); + function waitDiff(state, index, expected, timeout, done) { + const max = Date.now() + timeout; + let current = Atomics.load(state, index); + if (current !== expected) { + done(null, "ok"); + return; + } + const check2 = (backoff) => { + if (Date.now() > max) { + done(null, "timed-out"); + } else { + setTimeout(() => { + current = Atomics.load(state, index); + if (current !== expected) { + done(null, "ok"); + } else { + check2(backoff >= MAX_TIMEOUT ? MAX_TIMEOUT : backoff * 2); + } + }, backoff); + } + }; + check2(1); + } + module14.exports = { wait, waitDiff }; + } +}); +var require_indexes = __commonJS({ + "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/lib/indexes.js"(exports2, module14) { + "use strict"; + var WRITE_INDEX = 4; + var READ_INDEX = 8; + module14.exports = { + WRITE_INDEX, + READ_INDEX + }; + } +}); +var require_thread_stream = __commonJS({ + "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/index.js"(exports2, module14) { + "use strict"; + var { version: version3 } = require_package3(); + var { EventEmitter } = __require2("node:events"); + var { Worker: Worker2 } = __require2("node:worker_threads"); + var { join: join10 } = __require2("node:path"); + var { pathToFileURL: pathToFileURL2 } = __require2("node:url"); + var { wait } = require_wait(); + var { + WRITE_INDEX, + READ_INDEX + } = require_indexes(); + var buffer = __require2("node:buffer"); + var assert2 = __require2("node:assert"); + var kImpl = Symbol("kImpl"); + var MAX_STRING = buffer.constants.MAX_STRING_LENGTH; + var FakeWeakRef = class { + constructor(value) { + this._value = value; + } + deref() { + return this._value; + } + }; + var FakeFinalizationRegistry = class { + register() { + } + unregister() { } - }); - }); - if (server.options.pingInterval > 0) { - server.pingIntervalID = setInterval(() => { - if (server.clients.size && server.options.logPingRounds) { - log.debug("Pinging clients"); + }; + var FinalizationRegistry2 = process.env.NODE_V8_COVERAGE ? FakeFinalizationRegistry : global.FinalizationRegistry || FakeFinalizationRegistry; + var WeakRef2 = process.env.NODE_V8_COVERAGE ? FakeWeakRef : global.WeakRef || FakeWeakRef; + var registry2 = new FinalizationRegistry2((worker) => { + if (worker.exited) { + return; } - server.clients.forEach((client) => { - if (isPushSubscriptionInfo(client)) return; - if (client.pinged && !client.activeSinceLastPing) { - log(`Disconnecting irresponsive client ${client.id}`); - return client.terminate(); - } - if (client.readyState === wrapper_default.OPEN) { - client.send(createMessage(PING, Date.now()), () => { - client.activeSinceLastPing = false; - client.pinged = true; - }); + worker.terminate(); + }); + function createWorker2(stream, opts) { + const { filename, workerData } = opts; + const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {}; + const toExecute = bundlerOverrides["thread-stream-worker"] || join10(__dirname, "lib", "worker.js"); + const worker = new Worker2(toExecute, { + ...opts.workerOpts, + trackUnmanagedFds: false, + workerData: { + filename: filename.indexOf("file://") === 0 ? filename : pathToFileURL2(filename).href, + dataBuf: stream[kImpl].dataBuf, + stateBuf: stream[kImpl].stateBuf, + workerData: { + $context: { + threadStreamVersion: version3 + }, + ...workerData + } } }); - }, server.options.pingInterval); - } - return Object.assign(server, publicMethods2); -} -var import_npm_chalk; -var isPushSubscriptionInfo; -var bold; -var PING; -var PONG; -var PUB; -var SUB; -var UNSUB; -var KV_FILTER; -var ERROR; -var OK; -var defaultOptions3; -var tag2; -var generateSocketID; -var log; -var defaultServerHandlers; -var defaultSocketEventHandlers; -var defaultMessageHandlers2; -var publicMethods2; -var init_pubsub2 = __esm({ - "src/serve/pubsub.ts"() { - "use strict"; - init_esm5(); - init_pubsub(); - init_push(); - init_logger(); - import_npm_chalk = __toESM(require_source()); - init_wrapper(); - isPushSubscriptionInfo = (x3) => { - return has(x3, "endpoint"); - }; - ({ bold } = import_npm_chalk.default); - ({ PING, PONG, PUB, SUB, UNSUB, KV_FILTER } = NOTIFICATION_TYPE); - ({ ERROR, OK } = RESPONSE_TYPE); - defaultOptions3 = { - logPingRounds: process8.env.NODE_ENV !== "production" && !process8.env.CI, - logPongMessages: false, - maxPayload: 6 * 1024 * 1024, - pingInterval: 3e4 - }; - tag2 = "[pubsub]"; - generateSocketID = /* @__PURE__ */ (() => { - let counter = 0; - return (debugID) => String(counter++) + (debugID ? "-" + debugID : ""); - })(); - log = logger_default.info.bind(logger_default, tag2); - log.bold = (...args) => logger_default.debug(bold(tag2, ...args)); - log.debug = logger_default.debug.bind(logger_default, tag2); - log.error = (error2, ...args) => logger_default.error(error2, bold.red(tag2, ...args)); - defaultServerHandlers = { - close() { - clearInterval(this.pingIntervalID); - log("Server closed"); - }, - /** - * Emitted when a connection handshake completes. - * - * @see https://github.com/websockets/ws/blob/master/doc/ws.md#event-connection - * @param {ws.WebSocket} socket - The client socket that connected. - * @param {http.IncomingMessage} request - The underlying Node http GET request. - */ - connection(socket, request) { - const server = this; - const url2 = request.url; - const urlSearch = url2?.includes("?") ? url2.slice(url2.lastIndexOf("?")) : ""; - const debugID = new URLSearchParams(urlSearch).get("debugID") || ""; - const send = socket.send.bind(socket); - socket.id = generateSocketID(debugID); - socket.activeSinceLastPing = true; - socket.pinged = false; - socket.server = server; - socket.subscriptions = /* @__PURE__ */ new Set(); - socket.kvFilter = /* @__PURE__ */ new Map(); - socket.ip = request.headers["x-real-ip"] || request.headers["x-forwarded-for"]?.split(",")[0].trim() || request.socket.remoteAddress; - socket.send = function(data) { - if (typeof data === "object" && data !== null && typeof data[Symbol.toPrimitive] === "function") { - return send(data[Symbol.toPrimitive]()); - } - return send(data); - }; - log.bold(`Socket ${socket.id} connected. Total: ${this.clients.size}`); - ["close", "error", "message", "ping", "pong"].forEach((eventName) => { - socket.on(eventName, (...args) => { - if (eventName !== "message") { - log.debug(`Event '${eventName}' on socket ${socket.id}`, ...args.map((arg) => String(arg))); + worker.stream = new FakeWeakRef(stream); + worker.on("message", onWorkerMessage); + worker.on("exit", onWorkerExit); + registry2.register(stream, worker); + return worker; + } + function drain(stream) { + assert2(!stream[kImpl].sync); + if (stream[kImpl].needDrain) { + stream[kImpl].needDrain = false; + stream.emit("drain"); + } + } + function nextFlush(stream) { + const writeIndex = Atomics.load(stream[kImpl].state, WRITE_INDEX); + let leftover = stream[kImpl].data.length - writeIndex; + if (leftover > 0) { + if (stream[kImpl].buf.length === 0) { + stream[kImpl].flushing = false; + if (stream[kImpl].ending) { + end(stream); + } else if (stream[kImpl].needDrain) { + process.nextTick(drain, stream); + } + return; + } + let toWrite = stream[kImpl].buf.slice(0, leftover); + let toWriteBytes = Buffer.byteLength(toWrite); + if (toWriteBytes <= leftover) { + stream[kImpl].buf = stream[kImpl].buf.slice(leftover); + write(stream, toWrite, nextFlush.bind(null, stream)); + } else { + stream.flush(() => { + if (stream.destroyed) { + return; } - try { - ; - defaultSocketEventHandlers[eventName]?.call(socket, ...args); - socket.server.customSocketEventHandlers[eventName]?.call(socket, ...args); - } catch (error2) { - socket.server.emit("error", error2); - socket.terminate(); + Atomics.store(stream[kImpl].state, READ_INDEX, 0); + Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); + while (toWriteBytes > stream[kImpl].data.length) { + leftover = leftover / 2; + toWrite = stream[kImpl].buf.slice(0, leftover); + toWriteBytes = Buffer.byteLength(toWrite); } + stream[kImpl].buf = stream[kImpl].buf.slice(leftover); + write(stream, toWrite, nextFlush.bind(null, stream)); }); - }); - }, - error(error2) { - log.error(error2, "Server error"); - }, - headers() { - }, - listening() { - log("Server listening"); - } - }; - defaultSocketEventHandlers = { - close() { - const socket = this; - const { server } = this; - for (const channelID of socket.subscriptions) { - server.subscribersByChannelID[channelID].delete(socket); } - socket.subscriptions.clear(); - }, - message(data) { - const socket = this; - const { server } = this; - const text = data.toString(); - let msg = { type: "" }; - try { - msg = messageParser(text); - } catch (error2) { - log.error(error2, `Malformed message: ${error2.message}`); - server.rejectMessageAndTerminateSocket(msg, socket); + } else if (leftover === 0) { + if (writeIndex === 0 && stream[kImpl].buf.length === 0) { return; } - if (msg.type !== "pong" || server.options.logPongMessages) { - log.debug(`Received '${msg.type}' on socket ${socket.id}`, text); - } - socket.activeSinceLastPing = true; - const defaultHandler = defaultMessageHandlers2[msg.type]; - const customHandler = server.customMessageHandlers[msg.type]; - if (defaultHandler || customHandler) { - try { - ; - defaultHandler?.call(socket, msg); - customHandler?.call(socket, msg); - } catch (error2) { - log.error(error2, "onMessage"); - server.rejectMessageAndTerminateSocket(msg, socket); + stream.flush(() => { + Atomics.store(stream[kImpl].state, READ_INDEX, 0); + Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); + nextFlush(stream); + }); + } else { + destroy(stream, new Error("overwritten")); + } + } + function onWorkerMessage(msg) { + const stream = this.stream.deref(); + if (stream === void 0) { + this.exited = true; + this.terminate(); + return; + } + switch (msg.code) { + case "READY": + this.stream = new WeakRef2(stream); + stream.flush(() => { + stream[kImpl].ready = true; + stream.emit("ready"); + }); + break; + case "ERROR": + destroy(stream, msg.err); + break; + case "EVENT": + if (Array.isArray(msg.args)) { + stream.emit(msg.name, ...msg.args); + } else { + stream.emit(msg.name, msg.args); } - } else { - log.error(`Unhandled message type: ${msg.type}`); - server.rejectMessageAndTerminateSocket(msg, socket); + break; + case "WARNING": + process.emitWarning(msg.err); + break; + default: + destroy(stream, new Error("this should not happen: " + msg.code)); + } + } + function onWorkerExit(code2) { + const stream = this.stream.deref(); + if (stream === void 0) { + return; + } + registry2.unregister(stream); + stream.worker.exited = true; + stream.worker.off("exit", onWorkerExit); + destroy(stream, code2 !== 0 ? new Error("the worker thread exited") : null); + } + var ThreadStream = class extends EventEmitter { + constructor(opts = {}) { + super(); + if (opts.bufferSize < 4) { + throw new Error("bufferSize must at least fit a 4-byte utf-8 char"); } + this[kImpl] = {}; + this[kImpl].stateBuf = new SharedArrayBuffer(128); + this[kImpl].state = new Int32Array(this[kImpl].stateBuf); + this[kImpl].dataBuf = new SharedArrayBuffer(opts.bufferSize || 4 * 1024 * 1024); + this[kImpl].data = Buffer.from(this[kImpl].dataBuf); + this[kImpl].sync = opts.sync || false; + this[kImpl].ending = false; + this[kImpl].ended = false; + this[kImpl].needDrain = false; + this[kImpl].destroyed = false; + this[kImpl].flushing = false; + this[kImpl].ready = false; + this[kImpl].finished = false; + this[kImpl].errored = null; + this[kImpl].closed = false; + this[kImpl].buf = ""; + this.worker = createWorker2(this, opts); + this.on("message", (message, transferList) => { + this.worker.postMessage(message, transferList); + }); } - }; - defaultMessageHandlers2 = { - [PONG]() { - const socket = this; - socket.activeSinceLastPing = true; - }, - [PUB](msg) { - const { server } = this; - const subscribers = server.subscribersByChannelID[msg.channelID]; - server.broadcast(msg, { to: subscribers ?? [] }); - }, - [SUB]({ channelID, kvFilter }) { - const socket = this; - const { server } = this; - if (!server.channels.has(channelID)) { - socket.send(createErrorResponse( - { type: SUB, channelID, reason: `Unknown channel id: ${channelID}` } - )); - return; + write(data) { + if (this[kImpl].destroyed) { + error2(this, new Error("the worker has exited")); + return false; } - if (!socket.subscriptions.has(channelID)) { - socket.subscriptions.add(channelID); - if (Array.isArray(kvFilter)) { - socket.kvFilter.set(channelID, new Set(kvFilter)); - } - if (!server.subscribersByChannelID[channelID]) { - server.subscribersByChannelID[channelID] = /* @__PURE__ */ new Set(); - } - server.subscribersByChannelID[channelID].add(socket); - } else { - log.debug("Already subscribed to", channelID); + if (this[kImpl].ending) { + error2(this, new Error("the worker is ending")); + return false; } - socket.send(createOkResponse({ type: SUB, channelID, kvFilter })); - }, - [KV_FILTER]({ channelID, kvFilter }) { - const socket = this; - const { server } = this; - if (!server.channels.has(channelID)) { - socket.send(createErrorResponse( - { type: SUB, channelID, reason: `Unknown channel id: ${channelID}` } - )); - return; + if (this[kImpl].flushing && this[kImpl].buf.length + data.length >= MAX_STRING) { + try { + writeSync(this); + this[kImpl].flushing = true; + } catch (err) { + destroy(this, err); + return false; + } } - if (socket.subscriptions.has(channelID)) { - if (Array.isArray(kvFilter)) { - socket.kvFilter.set(channelID, new Set(kvFilter)); - } else { - socket.kvFilter.delete(channelID); + this[kImpl].buf += data; + if (this[kImpl].sync) { + try { + writeSync(this); + return true; + } catch (err) { + destroy(this, err); + return false; } - } else { - log.debug("[KV_FILTER] Not subscribed to", channelID); } - socket.send(createOkResponse({ type: KV_FILTER, channelID, kvFilter })); - }, - [UNSUB]({ channelID }) { - const socket = this; - const { server } = this; - if (!server.channels.has(channelID)) { - socket.send(createErrorResponse( - { type: UNSUB, channelID, reason: `Unknown channel id: ${channelID}` } - )); + if (!this[kImpl].flushing) { + this[kImpl].flushing = true; + setImmediate(nextFlush, this); } - if (socket.subscriptions.has(channelID)) { - socket.subscriptions.delete(channelID); - socket.kvFilter.delete(channelID); - if (server.subscribersByChannelID[channelID]) { - server.subscribersByChannelID[channelID].delete(socket); - } + this[kImpl].needDrain = this[kImpl].data.length - this[kImpl].buf.length - Atomics.load(this[kImpl].state, WRITE_INDEX) <= 0; + return !this[kImpl].needDrain; + } + end() { + if (this[kImpl].destroyed) { + return; } - socket.send(createOkResponse({ type: UNSUB, channelID })); + this[kImpl].ending = true; + end(this); } - }; - publicMethods2 = { - /** - * Broadcasts a message, ignoring clients which are not open. - * - * @param message - * @param to - The intended recipients of the message. Defaults to every open client socket. - * @param except - A recipient to exclude. Optional. - */ - broadcast(message, { to, except, wsOnly } = {}) { - const server = this; - const msg = typeof message === "string" ? message : JSON.stringify(message); - let shortMsg; - const shortenPayload = () => { - if (!shortMsg && (typeof message === "object" && message.type === NOTIFICATION_TYPE.ENTRY && message.data)) { - delete message.data; - shortMsg = JSON.stringify(message); - } - return shortMsg; - }; - for (const client of to || server.clients) { - if (!wsOnly && isPushSubscriptionInfo(client)) { - if (msg.length > 4096 - 86 - 17) { - if (!shortenPayload()) { - console.info("Skipping too large of a payload for", client.id); - continue; - } - } - postEvent(client, shortMsg || msg).catch((e2) => { - if (e2?.message === "Payload too large") { - if (shortMsg || !shortenPayload()) { - console.info("Skipping too large of a payload for", client.id); - return; - } - postEvent(client, shortMsg).catch((e3) => { - console.error(e3, "Error posting push notification"); - }); - return; - } - console.error(e2, "Error posting push notification"); - }); - continue; - } - if (client.readyState === wrapper_default.OPEN && client !== except) { - client.send(msg); + flush(cb) { + if (this[kImpl].destroyed) { + if (typeof cb === "function") { + process.nextTick(cb, new Error("the worker has exited")); } + return; } - }, - // Enumerates the subscribers of a given channel. - *enumerateSubscribers(channelID, kvKey) { - const server = this; - if (channelID in server.subscribersByChannelID) { - const subscribers = server.subscribersByChannelID[channelID]; - if (!kvKey) { - yield* subscribers; - } else { - for (const subscriber of subscribers) { - const kvFilter = subscriber.kvFilter?.get(channelID); - if (!kvFilter || kvFilter.has(kvKey)) yield subscriber; - } + const writeIndex = Atomics.load(this[kImpl].state, WRITE_INDEX); + wait(this[kImpl].state, READ_INDEX, writeIndex, Infinity, (err, res) => { + if (err) { + destroy(this, err); + process.nextTick(cb, err); + return; + } + if (res === "not-equal") { + this.flush(cb); + return; } + process.nextTick(cb); + }); + } + flushSync() { + if (this[kImpl].destroyed) { + return; } - }, - rejectMessageAndTerminateSocket(request, socket) { - socket.send(createErrorResponse({ ...request }), () => socket.terminate()); + writeSync(this); + flushSync(this); } - }; - } -}); -var require_parser2 = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/parser.js"(exports2) { - "use strict"; - exports2.load = function(received, defaults, onto = {}) { - var k, ref, v2; - for (k in defaults) { - v2 = defaults[k]; - onto[k] = (ref = received[k]) != null ? ref : v2; + unref() { + this.worker.unref(); } - return onto; - }; - exports2.overwrite = function(received, defaults, onto = {}) { - var k, v2; - for (k in received) { - v2 = received[k]; - if (defaults[k] !== void 0) { - onto[k] = v2; - } + ref() { + this.worker.ref(); } - return onto; - }; - } -}); -var require_DLList = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/DLList.js"(exports2, module14) { - "use strict"; - var DLList; - DLList = class DLList { - constructor(incr, decr) { - this.incr = incr; - this.decr = decr; - this._first = null; - this._last = null; - this.length = 0; + get ready() { + return this[kImpl].ready; } - push(value) { - var node; - this.length++; - if (typeof this.incr === "function") { - this.incr(); - } - node = { - value, - prev: this._last, - next: null - }; - if (this._last != null) { - this._last.next = node; - this._last = node; - } else { - this._first = this._last = node; - } - return void 0; + get destroyed() { + return this[kImpl].destroyed; } - shift() { - var value; - if (this._first == null) { - return; - } else { - this.length--; - if (typeof this.decr === "function") { - this.decr(); - } - } - value = this._first.value; - if ((this._first = this._first.next) != null) { - this._first.prev = null; - } else { - this._last = null; - } - return value; + get closed() { + return this[kImpl].closed; } - first() { - if (this._first != null) { - return this._first.value; - } + get writable() { + return !this[kImpl].destroyed && !this[kImpl].ending; } - getArray() { - var node, ref, results; - node = this._first; - results = []; - while (node != null) { - results.push((ref = node, node = node.next, ref.value)); - } - return results; + get writableEnded() { + return this[kImpl].ending; } - forEachShift(cb) { - var node; - node = this.shift(); - while (node != null) { - cb(node), node = this.shift(); - } - return void 0; + get writableFinished() { + return this[kImpl].finished; } - debug() { - var node, ref, ref1, ref2, results; - node = this._first; - results = []; - while (node != null) { - results.push((ref = node, node = node.next, { - value: ref.value, - prev: (ref1 = ref.prev) != null ? ref1.value : void 0, - next: (ref2 = ref.next) != null ? ref2.value : void 0 - })); - } - return results; + get writableNeedDrain() { + return this[kImpl].needDrain; + } + get writableObjectMode() { + return false; + } + get writableErrored() { + return this[kImpl].errored; } }; - module14.exports = DLList; - } -}); -var require_Events = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Events.js"(exports2, module14) { - "use strict"; - function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); + function error2(stream, err) { + setImmediate(() => { + stream.emit("error", err); + }); + } + function destroy(stream, err) { + if (stream[kImpl].destroyed) { return; } - if (info.done) { - resolve82(value); + stream[kImpl].destroyed = true; + if (err) { + stream[kImpl].errored = err; + error2(stream, err); + } + if (!stream.worker.exited) { + stream.worker.terminate().catch(() => { + }).then(() => { + stream[kImpl].closed = true; + stream.emit("close"); + }); } else { - Promise.resolve(value).then(_next, _throw); + setImmediate(() => { + stream[kImpl].closed = true; + stream.emit("close"); + }); } } - function _asyncToGenerator2(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); - } - function _throw(err) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); - } - _next(void 0); - }); - }; + function write(stream, data, cb) { + const current = Atomics.load(stream[kImpl].state, WRITE_INDEX); + const length2 = Buffer.byteLength(data); + stream[kImpl].data.write(data, current); + Atomics.store(stream[kImpl].state, WRITE_INDEX, current + length2); + Atomics.notify(stream[kImpl].state, WRITE_INDEX); + cb(); + return true; } - var Events2; - Events2 = class Events { - constructor(instance) { - this.instance = instance; - this._events = {}; - if (this.instance.on != null || this.instance.once != null || this.instance.removeAllListeners != null) { - throw new Error("An Emitter already exists for this object"); - } - this.instance.on = (name, cb) => { - return this._addListener(name, "many", cb); - }; - this.instance.once = (name, cb) => { - return this._addListener(name, "once", cb); - }; - this.instance.removeAllListeners = (name = null) => { - if (name != null) { - return delete this._events[name]; - } else { - return this._events = {}; + function end(stream) { + if (stream[kImpl].ended || !stream[kImpl].ending || stream[kImpl].flushing) { + return; + } + stream[kImpl].ended = true; + try { + stream.flushSync(); + let readIndex = Atomics.load(stream[kImpl].state, READ_INDEX); + Atomics.store(stream[kImpl].state, WRITE_INDEX, -1); + Atomics.notify(stream[kImpl].state, WRITE_INDEX); + let spins = 0; + while (readIndex !== -1) { + Atomics.wait(stream[kImpl].state, READ_INDEX, readIndex, 1e3); + readIndex = Atomics.load(stream[kImpl].state, READ_INDEX); + if (readIndex === -2) { + destroy(stream, new Error("end() failed")); + return; + } + if (++spins === 10) { + destroy(stream, new Error("end() took too long (10s)")); + return; } - }; - } - _addListener(name, status, cb) { - var base2; - if ((base2 = this._events)[name] == null) { - base2[name] = []; } - this._events[name].push({ - cb, - status + process.nextTick(() => { + stream[kImpl].finished = true; + stream.emit("finish"); }); - return this.instance; + } catch (err) { + destroy(stream, err); } - listenerCount(name) { - if (this._events[name] != null) { - return this._events[name].length; + } + function writeSync(stream) { + const cb = () => { + if (stream[kImpl].ending) { + end(stream); + } else if (stream[kImpl].needDrain) { + process.nextTick(drain, stream); + } + }; + stream[kImpl].flushing = false; + while (stream[kImpl].buf.length !== 0) { + const writeIndex = Atomics.load(stream[kImpl].state, WRITE_INDEX); + let leftover = stream[kImpl].data.length - writeIndex; + if (leftover === 0) { + flushSync(stream); + Atomics.store(stream[kImpl].state, READ_INDEX, 0); + Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); + continue; + } else if (leftover < 0) { + throw new Error("overwritten"); + } + let toWrite = stream[kImpl].buf.slice(0, leftover); + let toWriteBytes = Buffer.byteLength(toWrite); + if (toWriteBytes <= leftover) { + stream[kImpl].buf = stream[kImpl].buf.slice(leftover); + write(stream, toWrite, cb); } else { - return 0; + flushSync(stream); + Atomics.store(stream[kImpl].state, READ_INDEX, 0); + Atomics.store(stream[kImpl].state, WRITE_INDEX, 0); + while (toWriteBytes > stream[kImpl].buf.length) { + leftover = leftover / 2; + toWrite = stream[kImpl].buf.slice(0, leftover); + toWriteBytes = Buffer.byteLength(toWrite); + } + stream[kImpl].buf = stream[kImpl].buf.slice(leftover); + write(stream, toWrite, cb); } } - trigger(name, ...args) { - var _this = this; - return _asyncToGenerator2(function* () { - var e2, promises; - try { - if (name !== "debug") { - _this.trigger("debug", `Event triggered: ${name}`, args); - } - if (_this._events[name] == null) { - return; - } - _this._events[name] = _this._events[name].filter(function(listener) { - return listener.status !== "none"; - }); - promises = _this._events[name].map( - /* @__PURE__ */ function() { - var _ref = _asyncToGenerator2(function* (listener) { - var e3, returned; - if (listener.status === "none") { - return; - } - if (listener.status === "once") { - listener.status = "none"; - } - try { - returned = typeof listener.cb === "function" ? listener.cb(...args) : void 0; - if (typeof (returned != null ? returned.then : void 0) === "function") { - return yield returned; - } else { - return returned; - } - } catch (error2) { - e3 = error2; - if (true) { - _this.trigger("error", e3); - } - return null; - } - }); - return function(_x) { - return _ref.apply(this, arguments); - }; - }() - ); - return (yield Promise.all(promises)).find(function(x3) { - return x3 != null; - }); - } catch (error2) { - e2 = error2; - if (true) { - _this.trigger("error", e2); - } - return null; - } - })(); + } + function flushSync(stream) { + if (stream[kImpl].flushing) { + throw new Error("unable to flush while flushing"); } - }; - module14.exports = Events2; + const writeIndex = Atomics.load(stream[kImpl].state, WRITE_INDEX); + let spins = 0; + while (true) { + const readIndex = Atomics.load(stream[kImpl].state, READ_INDEX); + if (readIndex === -2) { + throw Error("_flushSync failed"); + } + if (readIndex !== writeIndex) { + Atomics.wait(stream[kImpl].state, READ_INDEX, readIndex, 1e3); + } else { + break; + } + if (++spins === 10) { + throw new Error("_flushSync took too long (10s)"); + } + } + } + module14.exports = ThreadStream; } }); -var require_Queues = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Queues.js"(exports2, module14) { +var require_transport = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/transport.js"(exports2, module14) { "use strict"; - var DLList; - var Events2; - var Queues; - DLList = require_DLList(); - Events2 = require_Events(); - Queues = class Queues { - constructor(num_priorities) { - var i2; - this.Events = new Events2(this); - this._length = 0; - this._lists = function() { - var j, ref, results; - results = []; - for (i2 = j = 1, ref = num_priorities; 1 <= ref ? j <= ref : j >= ref; i2 = 1 <= ref ? ++j : --j) { - results.push(new DLList(() => { - return this.incr(); - }, () => { - return this.decr(); - })); - } - return results; - }.call(this); - } - incr() { - if (this._length++ === 0) { - return this.Events.trigger("leftzero"); + var { createRequire } = __require2("node:module"); + var getCallers = require_caller(); + var { join: join10, isAbsolute: isAbsolute8, sep } = __require2("node:path"); + var sleep = require_atomic_sleep(); + var onExit = require_on_exit_leak_free(); + var ThreadStream = require_thread_stream(); + function setupOnExit(stream) { + onExit.register(stream, autoEnd); + onExit.registerBeforeExit(stream, flush); + stream.on("close", function() { + onExit.unregister(stream); + }); + } + function buildStream(filename, workerData, workerOpts) { + const stream = new ThreadStream({ + filename, + workerData, + workerOpts + }); + stream.on("ready", onReady); + stream.on("close", function() { + process.removeListener("exit", onExit2); + }); + process.on("exit", onExit2); + function onReady() { + process.removeListener("exit", onExit2); + stream.unref(); + if (workerOpts.autoEnd !== false) { + setupOnExit(stream); } } - decr() { - if (--this._length === 0) { - return this.Events.trigger("zero"); + function onExit2() { + if (stream.closed) { + return; } + stream.flushSync(); + sleep(100); + stream.end(); } - push(job) { - return this._lists[job.options.priority].push(job); - } - queued(priority) { - if (priority != null) { - return this._lists[priority].length; - } else { - return this._length; - } + return stream; + } + function autoEnd(stream) { + stream.ref(); + stream.flushSync(); + stream.end(); + stream.once("close", function() { + stream.unref(); + }); + } + function flush(stream) { + stream.flushSync(); + } + function transport(fullOptions) { + const { pipeline, targets, levels, dedupe, options: options2 = {}, worker = {}, caller = getCallers() } = fullOptions; + const callers = typeof caller === "string" ? [caller] : caller; + const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {}; + let target = fullOptions.target; + if (target && targets) { + throw new Error("only one of target or targets can be specified"); } - shiftAll(fn) { - return this._lists.forEach(function(list) { - return list.forEachShift(fn); + if (targets) { + target = bundlerOverrides["pino-worker"] || join10(__dirname, "worker.js"); + options2.targets = targets.map((dest) => { + return { + ...dest, + target: fixTarget(dest.target) + }; + }); + } else if (pipeline) { + target = bundlerOverrides["pino-pipeline-worker"] || join10(__dirname, "worker-pipeline.js"); + options2.targets = pipeline.map((dest) => { + return { + ...dest, + target: fixTarget(dest.target) + }; }); } - getFirst(arr = this._lists) { - var j, len, list; - for (j = 0, len = arr.length; j < len; j++) { - list = arr[j]; - if (list.length > 0) { - return list; + if (levels) { + options2.levels = levels; + } + if (dedupe) { + options2.dedupe = dedupe; + } + return buildStream(fixTarget(target), options2, worker); + function fixTarget(origin) { + origin = bundlerOverrides[origin] || origin; + if (isAbsolute8(origin) || origin.indexOf("file://") === 0) { + return origin; + } + if (origin === "pino/file") { + return join10(__dirname, "..", "file.js"); + } + let fixTarget2; + for (const filePath of callers) { + try { + const context = filePath === "node:repl" ? process.cwd() + sep : filePath; + fixTarget2 = createRequire(context).resolve(origin); + break; + } catch (err) { + continue; } } - return []; - } - shiftLastFrom(priority) { - return this.getFirst(this._lists.slice(priority).reverse()).shift(); + if (!fixTarget2) { + throw new Error(`unable to determine transport target for "${origin}"`); + } + return fixTarget2; } - }; - module14.exports = Queues; - } -}); -var require_BottleneckError = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/BottleneckError.js"(exports2, module14) { - "use strict"; - var BottleneckError; - BottleneckError = class BottleneckError extends Error { - }; - module14.exports = BottleneckError; + } + module14.exports = transport; } }); -var require_Job = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Job.js"(exports2, module14) { +var require_tools = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/tools.js"(exports2, module14) { "use strict"; - function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); - return; - } - if (info.done) { - resolve82(value); - } else { - Promise.resolve(value).then(_next, _throw); - } + var format52 = require_quick_format_unescaped(); + var { mapHttpRequest, mapHttpResponse } = require_pino_std_serializers(); + var SonicBoom = require_sonic_boom(); + var onExit = require_on_exit_leak_free(); + var { + lsCacheSym, + chindingsSym, + writeSym, + serializersSym, + formatOptsSym, + endSym, + stringifiersSym, + stringifySym, + stringifySafeSym, + wildcardFirstSym, + nestedKeySym, + formattersSym, + messageKeySym, + errorKeySym, + nestedKeyStrSym, + msgPrefixSym + } = require_symbols(); + var { isMainThread } = __require2("node:worker_threads"); + var transport = require_transport(); + function noop() { } - function _asyncToGenerator2(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); + function genLog(level, hook) { + if (!hook) return LOG; + return function hookWrappedLog(...args) { + hook.call(this, args, LOG, level); + }; + function LOG(o2, ...n) { + if (typeof o2 === "object") { + let msg = o2; + if (o2 !== null) { + if (o2.method && o2.headers && o2.socket) { + o2 = mapHttpRequest(o2); + } else if (typeof o2.setHeader === "function") { + o2 = mapHttpResponse(o2); + } } - function _throw(err) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + let formatParams; + if (msg === null && n.length === 0) { + formatParams = [null]; + } else { + msg = n.shift(); + formatParams = n; } - _next(void 0); - }); - }; - } - var BottleneckError; - var DEFAULT_PRIORITY; - var Job; - var NUM_PRIORITIES; - var parser3; - NUM_PRIORITIES = 10; - DEFAULT_PRIORITY = 5; - parser3 = require_parser2(); - BottleneckError = require_BottleneckError(); - Job = class Job { - constructor(task, args, options2, jobDefaults, rejectOnDrop, Events2, _states, Promise2) { - this.task = task; - this.args = args; - this.rejectOnDrop = rejectOnDrop; - this.Events = Events2; - this._states = _states; - this.Promise = Promise2; - this.options = parser3.load(options2, jobDefaults); - this.options.priority = this._sanitizePriority(this.options.priority); - if (this.options.id === jobDefaults.id) { - this.options.id = `${this.options.id}-${this._randomIndex()}`; - } - this.promise = new this.Promise((_resolve, _reject) => { - this._resolve = _resolve; - this._reject = _reject; - }); - this.retryCount = 0; - } - _sanitizePriority(priority) { - var sProperty; - sProperty = ~~priority !== priority ? DEFAULT_PRIORITY : priority; - if (sProperty < 0) { - return 0; - } else if (sProperty > NUM_PRIORITIES - 1) { - return NUM_PRIORITIES - 1; + if (typeof this[msgPrefixSym] === "string" && msg !== void 0 && msg !== null) { + msg = this[msgPrefixSym] + msg; + } + this[writeSym](o2, format52(msg, formatParams, this[formatOptsSym]), level); } else { - return sProperty; + let msg = o2 === void 0 ? n.shift() : o2; + if (typeof this[msgPrefixSym] === "string" && msg !== void 0 && msg !== null) { + msg = this[msgPrefixSym] + msg; + } + this[writeSym](null, format52(msg, n, this[formatOptsSym]), level); } } - _randomIndex() { - return Math.random().toString(36).slice(2); + } + function asString(str) { + let result = ""; + let last = 0; + let found = false; + let point = 255; + const l = str.length; + if (l > 100) { + return JSON.stringify(str); } - doDrop({ - error: error2, - message = "This job has been dropped by Bottleneck" - } = {}) { - if (this._states.remove(this.options.id)) { - if (this.rejectOnDrop) { - this._reject(error2 != null ? error2 : new BottleneckError(message)); - } - this.Events.trigger("dropped", { - args: this.args, - options: this.options, - task: this.task, - promise: this.promise - }); - return true; - } else { - return false; + for (var i2 = 0; i2 < l && point >= 32; i2++) { + point = str.charCodeAt(i2); + if (point === 34 || point === 92) { + result += str.slice(last, i2) + "\\"; + last = i2; + found = true; } } - _assertStatus(expected) { - var status; - status = this._states.jobStatus(this.options.id); - if (!(status === expected || expected === "DONE" && status === null)) { - throw new BottleneckError(`Invalid job status ${status}, expected ${expected}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`); + if (!found) { + result = str; + } else { + result += str.slice(last); + } + return point < 32 ? JSON.stringify(str) : '"' + result + '"'; + } + function asJson(obj, msg, num, time3) { + const stringify3 = this[stringifySym]; + const stringifySafe = this[stringifySafeSym]; + const stringifiers = this[stringifiersSym]; + const end = this[endSym]; + const chindings = this[chindingsSym]; + const serializers = this[serializersSym]; + const formatters = this[formattersSym]; + const messageKey = this[messageKeySym]; + const errorKey = this[errorKeySym]; + let data = this[lsCacheSym][num] + time3; + data = data + chindings; + let value; + if (formatters.log) { + obj = formatters.log(obj); + } + const wildcardStringifier = stringifiers[wildcardFirstSym]; + let propStr = ""; + for (const key in obj) { + value = obj[key]; + if (Object.prototype.hasOwnProperty.call(obj, key) && value !== void 0) { + if (serializers[key]) { + value = serializers[key](value); + } else if (key === errorKey && serializers.err) { + value = serializers.err(value); + } + const stringifier = stringifiers[key] || wildcardStringifier; + switch (typeof value) { + case "undefined": + case "function": + continue; + case "number": + if (Number.isFinite(value) === false) { + value = null; + } + // this case explicitly falls through to the next one + case "boolean": + if (stringifier) value = stringifier(value); + break; + case "string": + value = (stringifier || asString)(value); + break; + default: + value = (stringifier || stringify3)(value, stringifySafe); + } + if (value === void 0) continue; + const strKey = asString(key); + propStr += "," + strKey + ":" + value; } } - doReceive() { - this._states.start(this.options.id); - return this.Events.trigger("received", { - args: this.args, - options: this.options - }); - } - doQueue(reachedHWM, blocked) { - this._assertStatus("RECEIVED"); - this._states.next(this.options.id); - return this.Events.trigger("queued", { - args: this.args, - options: this.options, - reachedHWM, - blocked - }); - } - doRun() { - if (this.retryCount === 0) { - this._assertStatus("QUEUED"); - this._states.next(this.options.id); - } else { - this._assertStatus("EXECUTING"); + let msgStr = ""; + if (msg !== void 0) { + value = serializers[messageKey] ? serializers[messageKey](msg) : msg; + const stringifier = stringifiers[messageKey] || wildcardStringifier; + switch (typeof value) { + case "function": + break; + case "number": + if (Number.isFinite(value) === false) { + value = null; + } + // this case explicitly falls through to the next one + case "boolean": + if (stringifier) value = stringifier(value); + msgStr = ',"' + messageKey + '":' + value; + break; + case "string": + value = (stringifier || asString)(value); + msgStr = ',"' + messageKey + '":' + value; + break; + default: + value = (stringifier || stringify3)(value, stringifySafe); + msgStr = ',"' + messageKey + '":' + value; } - return this.Events.trigger("scheduled", { - args: this.args, - options: this.options - }); } - doExecute(chained, clearGlobalState, run2, free) { - var _this = this; - return _asyncToGenerator2(function* () { - var error2, eventInfo, passed; - if (_this.retryCount === 0) { - _this._assertStatus("RUNNING"); - _this._states.next(_this.options.id); - } else { - _this._assertStatus("EXECUTING"); - } - eventInfo = { - args: _this.args, - options: _this.options, - retryCount: _this.retryCount - }; - _this.Events.trigger("executing", eventInfo); - try { - passed = yield chained != null ? chained.schedule(_this.options, _this.task, ..._this.args) : _this.task(..._this.args); - if (clearGlobalState()) { - _this.doDone(eventInfo); - yield free(_this.options, eventInfo); - _this._assertStatus("DONE"); - return _this._resolve(passed); - } - } catch (error1) { - error2 = error1; - return _this._onFailure(error2, eventInfo, clearGlobalState, run2, free); - } - })(); + if (this[nestedKeySym] && propStr) { + return data + this[nestedKeyStrSym] + propStr.slice(1) + "}" + msgStr + end; + } else { + return data + propStr + msgStr + end; } - doExpire(clearGlobalState, run2, free) { - var error2, eventInfo; - if (this._states.jobStatus(this.options.id === "RUNNING")) { - this._states.next(this.options.id); + } + function asChindings(instance, bindings) { + let value; + let data = instance[chindingsSym]; + const stringify3 = instance[stringifySym]; + const stringifySafe = instance[stringifySafeSym]; + const stringifiers = instance[stringifiersSym]; + const wildcardStringifier = stringifiers[wildcardFirstSym]; + const serializers = instance[serializersSym]; + const formatter = instance[formattersSym].bindings; + bindings = formatter(bindings); + for (const key in bindings) { + value = bindings[key]; + const valid = key !== "level" && key !== "serializers" && key !== "formatters" && key !== "customLevels" && bindings.hasOwnProperty(key) && value !== void 0; + if (valid === true) { + value = serializers[key] ? serializers[key](value) : value; + value = (stringifiers[key] || wildcardStringifier || stringify3)(value, stringifySafe); + if (value === void 0) continue; + data += ',"' + key + '":' + value; } - this._assertStatus("EXECUTING"); - eventInfo = { - args: this.args, - options: this.options, - retryCount: this.retryCount - }; - error2 = new BottleneckError(`This job timed out after ${this.options.expiration} ms.`); - return this._onFailure(error2, eventInfo, clearGlobalState, run2, free); } - _onFailure(error2, eventInfo, clearGlobalState, run2, free) { - var _this2 = this; - return _asyncToGenerator2(function* () { - var retry, retryAfter; - if (clearGlobalState()) { - retry = yield _this2.Events.trigger("failed", error2, eventInfo); - if (retry != null) { - retryAfter = ~~retry; - _this2.Events.trigger("retry", `Retrying ${_this2.options.id} after ${retryAfter} ms`, eventInfo); - _this2.retryCount++; - return run2(retryAfter); - } else { - _this2.doDone(eventInfo); - yield free(_this2.options, eventInfo); - _this2._assertStatus("DONE"); - return _this2._reject(error2); - } - } - })(); + return data; + } + function hasBeenTampered(stream) { + return stream.write !== stream.constructor.prototype.write; + } + var hasNodeCodeCoverage = process.env.NODE_V8_COVERAGE || process.env.V8_COVERAGE; + function buildSafeSonicBoom(opts) { + const stream = new SonicBoom(opts); + stream.on("error", filterBrokenPipe); + if (!hasNodeCodeCoverage && !opts.sync && isMainThread) { + onExit.register(stream, autoEnd); + stream.on("close", function() { + onExit.unregister(stream); + }); } - doDone(eventInfo) { - this._assertStatus("EXECUTING"); - this._states.next(this.options.id); - return this.Events.trigger("done", eventInfo); + return stream; + function filterBrokenPipe(err) { + if (err.code === "EPIPE") { + stream.write = noop; + stream.end = noop; + stream.flushSync = noop; + stream.destroy = noop; + return; + } + stream.removeListener("error", filterBrokenPipe); + stream.emit("error", err); } - }; - module14.exports = Job; - } -}); -var require_LocalDatastore = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/LocalDatastore.js"(exports2, module14) { - "use strict"; - function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); + } + function autoEnd(stream, eventName) { + if (stream.destroyed) { return; } - if (info.done) { - resolve82(value); + if (eventName === "beforeExit") { + stream.flush(); + stream.on("drain", function() { + stream.end(); + }); } else { - Promise.resolve(value).then(_next, _throw); + stream.flushSync(); } } - function _asyncToGenerator2(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); + function createArgsNormalizer(defaultOptions4) { + return function normalizeArgs(instance, caller, opts = {}, stream) { + if (typeof opts === "string") { + stream = buildSafeSonicBoom({ dest: opts }); + opts = {}; + } else if (typeof stream === "string") { + if (opts && opts.transport) { + throw Error("only one of option.transport or stream can be specified"); } - function _throw(err) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + stream = buildSafeSonicBoom({ dest: stream }); + } else if (opts instanceof SonicBoom || opts.writable || opts._writableState) { + stream = opts; + opts = {}; + } else if (opts.transport) { + if (opts.transport instanceof SonicBoom || opts.transport.writable || opts.transport._writableState) { + throw Error("option.transport do not allow stream, please pass to option directly. e.g. pino(transport)"); } - _next(void 0); - }); + if (opts.transport.targets && opts.transport.targets.length && opts.formatters && typeof opts.formatters.level === "function") { + throw Error("option.transport.targets do not allow custom level formatters"); + } + let customLevels; + if (opts.customLevels) { + customLevels = opts.useOnlyCustomLevels ? opts.customLevels : Object.assign({}, opts.levels, opts.customLevels); + } + stream = transport({ caller, ...opts.transport, levels: customLevels }); + } + opts = Object.assign({}, defaultOptions4, opts); + opts.serializers = Object.assign({}, defaultOptions4.serializers, opts.serializers); + opts.formatters = Object.assign({}, defaultOptions4.formatters, opts.formatters); + if (opts.prettyPrint) { + throw new Error("prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)"); + } + const { enabled: enabled2, onChild } = opts; + if (enabled2 === false) opts.level = "silent"; + if (!onChild) opts.onChild = noop; + if (!stream) { + if (!hasBeenTampered(process.stdout)) { + stream = buildSafeSonicBoom({ fd: process.stdout.fd || 1 }); + } else { + stream = process.stdout; + } + } + return { opts, stream }; }; } - var BottleneckError; - var LocalDatastore; - var parser3; - parser3 = require_parser2(); - BottleneckError = require_BottleneckError(); - LocalDatastore = class LocalDatastore { - constructor(instance, storeOptions, storeInstanceOptions) { - this.instance = instance; - this.storeOptions = storeOptions; - this.clientId = this.instance._randomIndex(); - parser3.load(storeInstanceOptions, storeInstanceOptions, this); - this._nextRequest = this._lastReservoirRefresh = this._lastReservoirIncrease = Date.now(); - this._running = 0; - this._done = 0; - this._unblockTime = 0; - this.ready = this.Promise.resolve(); - this.clients = {}; - this._startHeartbeat(); - } - _startHeartbeat() { - var base2; - if (this.heartbeat == null && (this.storeOptions.reservoirRefreshInterval != null && this.storeOptions.reservoirRefreshAmount != null || this.storeOptions.reservoirIncreaseInterval != null && this.storeOptions.reservoirIncreaseAmount != null)) { - return typeof (base2 = this.heartbeat = setInterval(() => { - var amount, incr, maximum, now, reservoir; - now = Date.now(); - if (this.storeOptions.reservoirRefreshInterval != null && now >= this._lastReservoirRefresh + this.storeOptions.reservoirRefreshInterval) { - this._lastReservoirRefresh = now; - this.storeOptions.reservoir = this.storeOptions.reservoirRefreshAmount; - this.instance._drainAll(this.computeCapacity()); - } - if (this.storeOptions.reservoirIncreaseInterval != null && now >= this._lastReservoirIncrease + this.storeOptions.reservoirIncreaseInterval) { - var _this$storeOptions = this.storeOptions; - amount = _this$storeOptions.reservoirIncreaseAmount; - maximum = _this$storeOptions.reservoirIncreaseMaximum; - reservoir = _this$storeOptions.reservoir; - this._lastReservoirIncrease = now; - incr = maximum != null ? Math.min(amount, maximum - reservoir) : amount; - if (incr > 0) { - this.storeOptions.reservoir += incr; - return this.instance._drainAll(this.computeCapacity()); - } - } - }, this.heartbeatInterval)).unref === "function" ? base2.unref() : void 0; - } else { - return clearInterval(this.heartbeat); + function stringify2(obj, stringifySafeFn) { + try { + return JSON.stringify(obj); + } catch (_) { + try { + const stringify3 = stringifySafeFn || this[stringifySafeSym]; + return stringify3(obj); + } catch (_2) { + return '"[unable to serialize, circular reference is too complex to analyze]"'; } } - __publish__(message) { - var _this = this; - return _asyncToGenerator2(function* () { - yield _this.yieldLoop(); - return _this.instance.Events.trigger("message", message.toString()); - })(); + } + function buildFormatters(level, bindings, log2) { + return { + level, + bindings, + log: log2 + }; + } + function normalizeDestFileDescriptor(destination) { + const fd = Number(destination); + if (typeof destination === "string" && Number.isFinite(fd)) { + return fd; } - __disconnect__(flush) { - var _this2 = this; - return _asyncToGenerator2(function* () { - yield _this2.yieldLoop(); - clearInterval(_this2.heartbeat); - return _this2.Promise.resolve(); - })(); + if (destination === void 0) { + return 1; } - yieldLoop(t = 0) { - return new this.Promise(function(resolve82, reject) { - return setTimeout(resolve82, t); - }); + return destination; + } + module14.exports = { + noop, + buildSafeSonicBoom, + asChindings, + asJson, + genLog, + createArgsNormalizer, + stringify: stringify2, + buildFormatters, + normalizeDestFileDescriptor + }; + } +}); +var require_constants = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/constants.js"(exports2, module14) { + var DEFAULT_LEVELS = { + trace: 10, + debug: 20, + info: 30, + warn: 40, + error: 50, + fatal: 60 + }; + var SORTING_ORDER = { + ASC: "ASC", + DESC: "DESC" + }; + module14.exports = { + DEFAULT_LEVELS, + SORTING_ORDER + }; + } +}); +var require_levels = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/levels.js"(exports2, module14) { + "use strict"; + var { + lsCacheSym, + levelValSym, + useOnlyCustomLevelsSym, + streamSym, + formattersSym, + hooksSym, + levelCompSym + } = require_symbols(); + var { noop, genLog } = require_tools(); + var { DEFAULT_LEVELS, SORTING_ORDER } = require_constants(); + var levelMethods = { + fatal: (hook) => { + const logFatal = genLog(DEFAULT_LEVELS.fatal, hook); + return function(...args) { + const stream = this[streamSym]; + logFatal.call(this, ...args); + if (typeof stream.flushSync === "function") { + try { + stream.flushSync(); + } catch (e2) { + } + } + }; + }, + error: (hook) => genLog(DEFAULT_LEVELS.error, hook), + warn: (hook) => genLog(DEFAULT_LEVELS.warn, hook), + info: (hook) => genLog(DEFAULT_LEVELS.info, hook), + debug: (hook) => genLog(DEFAULT_LEVELS.debug, hook), + trace: (hook) => genLog(DEFAULT_LEVELS.trace, hook) + }; + var nums = Object.keys(DEFAULT_LEVELS).reduce((o2, k) => { + o2[DEFAULT_LEVELS[k]] = k; + return o2; + }, {}); + var initialLsCache = Object.keys(nums).reduce((o2, k) => { + o2[k] = '{"level":' + Number(k); + return o2; + }, {}); + function genLsCache(instance) { + const formatter = instance[formattersSym].level; + const { labels } = instance.levels; + const cache2 = {}; + for (const label in labels) { + const level = formatter(labels[label], Number(label)); + cache2[label] = JSON.stringify(level).slice(0, -1); } - computePenalty() { - var ref; - return (ref = this.storeOptions.penalty) != null ? ref : 15 * this.storeOptions.minTime || 5e3; + instance[lsCacheSym] = cache2; + return instance; + } + function isStandardLevel(level, useOnlyCustomLevels) { + if (useOnlyCustomLevels) { + return false; } - __updateSettings__(options2) { - var _this3 = this; - return _asyncToGenerator2(function* () { - yield _this3.yieldLoop(); - parser3.overwrite(options2, options2, _this3.storeOptions); - _this3._startHeartbeat(); - _this3.instance._drainAll(_this3.computeCapacity()); + switch (level) { + case "fatal": + case "error": + case "warn": + case "info": + case "debug": + case "trace": return true; - })(); - } - __running__() { - var _this4 = this; - return _asyncToGenerator2(function* () { - yield _this4.yieldLoop(); - return _this4._running; - })(); - } - __queued__() { - var _this5 = this; - return _asyncToGenerator2(function* () { - yield _this5.yieldLoop(); - return _this5.instance.queued(); - })(); - } - __done__() { - var _this6 = this; - return _asyncToGenerator2(function* () { - yield _this6.yieldLoop(); - return _this6._done; - })(); - } - __groupCheck__(time3) { - var _this7 = this; - return _asyncToGenerator2(function* () { - yield _this7.yieldLoop(); - return _this7._nextRequest + _this7.timeout < time3; - })(); - } - computeCapacity() { - var maxConcurrent, reservoir; - var _this$storeOptions2 = this.storeOptions; - maxConcurrent = _this$storeOptions2.maxConcurrent; - reservoir = _this$storeOptions2.reservoir; - if (maxConcurrent != null && reservoir != null) { - return Math.min(maxConcurrent - this._running, reservoir); - } else if (maxConcurrent != null) { - return maxConcurrent - this._running; - } else if (reservoir != null) { - return reservoir; - } else { - return null; - } - } - conditionsCheck(weight) { - var capacity; - capacity = this.computeCapacity(); - return capacity == null || weight <= capacity; + default: + return false; } - __incrementReservoir__(incr) { - var _this8 = this; - return _asyncToGenerator2(function* () { - var reservoir; - yield _this8.yieldLoop(); - reservoir = _this8.storeOptions.reservoir += incr; - _this8.instance._drainAll(_this8.computeCapacity()); - return reservoir; - })(); + } + function setLevel(level) { + const { labels, values } = this.levels; + if (typeof level === "number") { + if (labels[level] === void 0) throw Error("unknown level value" + level); + level = labels[level]; } - __currentReservoir__() { - var _this9 = this; - return _asyncToGenerator2(function* () { - yield _this9.yieldLoop(); - return _this9.storeOptions.reservoir; - })(); + if (values[level] === void 0) throw Error("unknown level " + level); + const preLevelVal = this[levelValSym]; + const levelVal = this[levelValSym] = values[level]; + const useOnlyCustomLevelsVal = this[useOnlyCustomLevelsSym]; + const levelComparison = this[levelCompSym]; + const hook = this[hooksSym].logMethod; + for (const key in values) { + if (levelComparison(values[key], levelVal) === false) { + this[key] = noop; + continue; + } + this[key] = isStandardLevel(key, useOnlyCustomLevelsVal) ? levelMethods[key](hook) : genLog(values[key], hook); } - isBlocked(now) { - return this._unblockTime >= now; + this.emit( + "level-change", + level, + levelVal, + labels[preLevelVal], + preLevelVal, + this + ); + } + function getLevel(level) { + const { levels, levelVal } = this; + return levels && levels.labels ? levels.labels[levelVal] : ""; + } + function isLevelEnabled(logLevel2) { + const { values } = this.levels; + const logLevelVal = values[logLevel2]; + return logLevelVal !== void 0 && this[levelCompSym](logLevelVal, this[levelValSym]); + } + function compareLevel(direction, current, expected) { + if (direction === SORTING_ORDER.DESC) { + return current <= expected; } - check(weight, now) { - return this.conditionsCheck(weight) && this._nextRequest - now <= 0; + return current >= expected; + } + function genLevelComparison(levelComparison) { + if (typeof levelComparison === "string") { + return compareLevel.bind(null, levelComparison); } - __check__(weight) { - var _this10 = this; - return _asyncToGenerator2(function* () { - var now; - yield _this10.yieldLoop(); - now = Date.now(); - return _this10.check(weight, now); - })(); + return levelComparison; + } + function mappings(customLevels = null, useOnlyCustomLevels = false) { + const customNums = customLevels ? Object.keys(customLevels).reduce((o2, k) => { + o2[customLevels[k]] = k; + return o2; + }, {}) : null; + const labels = Object.assign( + Object.create(Object.prototype, { Infinity: { value: "silent" } }), + useOnlyCustomLevels ? null : nums, + customNums + ); + const values = Object.assign( + Object.create(Object.prototype, { silent: { value: Infinity } }), + useOnlyCustomLevels ? null : DEFAULT_LEVELS, + customLevels + ); + return { labels, values }; + } + function assertDefaultLevelFound(defaultLevel, customLevels, useOnlyCustomLevels) { + if (typeof defaultLevel === "number") { + const values = [].concat( + Object.keys(customLevels || {}).map((key) => customLevels[key]), + useOnlyCustomLevels ? [] : Object.keys(nums).map((level) => +level), + Infinity + ); + if (!values.includes(defaultLevel)) { + throw Error(`default level:${defaultLevel} must be included in custom levels`); + } + return; } - __register__(index, weight, expiration) { - var _this11 = this; - return _asyncToGenerator2(function* () { - var now, wait; - yield _this11.yieldLoop(); - now = Date.now(); - if (_this11.conditionsCheck(weight)) { - _this11._running += weight; - if (_this11.storeOptions.reservoir != null) { - _this11.storeOptions.reservoir -= weight; - } - wait = Math.max(_this11._nextRequest - now, 0); - _this11._nextRequest = now + wait + _this11.storeOptions.minTime; - return { - success: true, - wait, - reservoir: _this11.storeOptions.reservoir - }; - } else { - return { - success: false - }; - } - })(); + const labels = Object.assign( + Object.create(Object.prototype, { silent: { value: Infinity } }), + useOnlyCustomLevels ? null : DEFAULT_LEVELS, + customLevels + ); + if (!(defaultLevel in labels)) { + throw Error(`default level:${defaultLevel} must be included in custom levels`); } - strategyIsBlock() { - return this.storeOptions.strategy === 3; + } + function assertNoLevelCollisions(levels, customLevels) { + const { labels, values } = levels; + for (const k in customLevels) { + if (k in values) { + throw Error("levels cannot be overridden"); + } + if (customLevels[k] in labels) { + throw Error("pre-existing level values cannot be used for new levels"); + } } - __submit__(queueLength, weight) { - var _this12 = this; - return _asyncToGenerator2(function* () { - var blocked, now, reachedHWM; - yield _this12.yieldLoop(); - if (_this12.storeOptions.maxConcurrent != null && weight > _this12.storeOptions.maxConcurrent) { - throw new BottleneckError(`Impossible to add a job having a weight of ${weight} to a limiter having a maxConcurrent setting of ${_this12.storeOptions.maxConcurrent}`); - } - now = Date.now(); - reachedHWM = _this12.storeOptions.highWater != null && queueLength === _this12.storeOptions.highWater && !_this12.check(weight, now); - blocked = _this12.strategyIsBlock() && (reachedHWM || _this12.isBlocked(now)); - if (blocked) { - _this12._unblockTime = now + _this12.computePenalty(); - _this12._nextRequest = _this12._unblockTime + _this12.storeOptions.minTime; - _this12.instance._dropAllQueued(); - } - return { - reachedHWM, - blocked, - strategy: _this12.storeOptions.strategy - }; - })(); + } + function assertLevelComparison(levelComparison) { + if (typeof levelComparison === "function") { + return; } - __free__(index, weight) { - var _this13 = this; - return _asyncToGenerator2(function* () { - yield _this13.yieldLoop(); - _this13._running -= weight; - _this13._done += weight; - _this13.instance._drainAll(_this13.computeCapacity()); - return { - running: _this13._running - }; - })(); + if (typeof levelComparison === "string" && Object.values(SORTING_ORDER).includes(levelComparison)) { + return; } + throw new Error('Levels comparison should be one of "ASC", "DESC" or "function" type'); + } + module14.exports = { + initialLsCache, + genLsCache, + levelMethods, + getLevel, + setLevel, + isLevelEnabled, + mappings, + assertNoLevelCollisions, + assertDefaultLevelFound, + genLevelComparison, + assertLevelComparison }; - module14.exports = LocalDatastore; } }); -var require_lua = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/lua.json"(exports2, module14) { - module14.exports = { - "blacklist_client.lua": "local blacklist = ARGV[num_static_argv + 1]\n\nif redis.call('zscore', client_last_seen_key, blacklist) then\n redis.call('zadd', client_last_seen_key, 0, blacklist)\nend\n\n\nreturn {}\n", - "check.lua": "local weight = tonumber(ARGV[num_static_argv + 1])\n\nlocal capacity = process_tick(now, false)['capacity']\nlocal nextRequest = tonumber(redis.call('hget', settings_key, 'nextRequest'))\n\nreturn conditions_check(capacity, weight) and nextRequest - now <= 0\n", - "conditions_check.lua": "local conditions_check = function (capacity, weight)\n return capacity == nil or weight <= capacity\nend\n", - "current_reservoir.lua": "return process_tick(now, false)['reservoir']\n", - "done.lua": "process_tick(now, false)\n\nreturn tonumber(redis.call('hget', settings_key, 'done'))\n", - "free.lua": "local index = ARGV[num_static_argv + 1]\n\nredis.call('zadd', job_expirations_key, 0, index)\n\nreturn process_tick(now, false)['running']\n", - "get_time.lua": "redis.replicate_commands()\n\nlocal get_time = function ()\n local time = redis.call('time')\n\n return tonumber(time[1]..string.sub(time[2], 1, 3))\nend\n", - "group_check.lua": "return not (redis.call('exists', settings_key) == 1)\n", - "heartbeat.lua": "process_tick(now, true)\n", - "increment_reservoir.lua": "local incr = tonumber(ARGV[num_static_argv + 1])\n\nredis.call('hincrby', settings_key, 'reservoir', incr)\n\nlocal reservoir = process_tick(now, true)['reservoir']\n\nlocal groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout'))\nrefresh_expiration(0, 0, groupTimeout)\n\nreturn reservoir\n", - "init.lua": `local clear = tonumber(ARGV[num_static_argv + 1]) -local limiter_version = ARGV[num_static_argv + 2] -local num_local_argv = num_static_argv + 2 - -if clear == 1 then - redis.call('del', unpack(KEYS)) -end - -if redis.call('exists', settings_key) == 0 then - -- Create - local args = {'hmset', settings_key} - - for i = num_local_argv + 1, #ARGV do - table.insert(args, ARGV[i]) - end - - redis.call(unpack(args)) - redis.call('hmset', settings_key, - 'nextRequest', now, - 'lastReservoirRefresh', now, - 'lastReservoirIncrease', now, - 'running', 0, - 'done', 0, - 'unblockTime', 0, - 'capacityPriorityCounter', 0 - ) - -else - -- Apply migrations - local settings = redis.call('hmget', settings_key, - 'id', - 'version' - ) - local id = settings[1] - local current_version = settings[2] - - if current_version ~= limiter_version then - local version_digits = {} - for k, v in string.gmatch(current_version, "([^.]+)") do - table.insert(version_digits, tonumber(k)) - end - - -- 2.10.0 - if version_digits[2] < 10 then - redis.call('hsetnx', settings_key, 'reservoirRefreshInterval', '') - redis.call('hsetnx', settings_key, 'reservoirRefreshAmount', '') - redis.call('hsetnx', settings_key, 'lastReservoirRefresh', '') - redis.call('hsetnx', settings_key, 'done', 0) - redis.call('hset', settings_key, 'version', '2.10.0') - end - - -- 2.11.1 - if version_digits[2] < 11 or (version_digits[2] == 11 and version_digits[3] < 1) then - if redis.call('hstrlen', settings_key, 'lastReservoirRefresh') == 0 then - redis.call('hmset', settings_key, - 'lastReservoirRefresh', now, - 'version', '2.11.1' - ) - end - end - - -- 2.14.0 - if version_digits[2] < 14 then - local old_running_key = 'b_'..id..'_running' - local old_executing_key = 'b_'..id..'_executing' - - if redis.call('exists', old_running_key) == 1 then - redis.call('rename', old_running_key, job_weights_key) - end - if redis.call('exists', old_executing_key) == 1 then - redis.call('rename', old_executing_key, job_expirations_key) - end - redis.call('hset', settings_key, 'version', '2.14.0') - end - - -- 2.15.2 - if version_digits[2] < 15 or (version_digits[2] == 15 and version_digits[3] < 2) then - redis.call('hsetnx', settings_key, 'capacityPriorityCounter', 0) - redis.call('hset', settings_key, 'version', '2.15.2') - end - - -- 2.17.0 - if version_digits[2] < 17 then - redis.call('hsetnx', settings_key, 'clientTimeout', 10000) - redis.call('hset', settings_key, 'version', '2.17.0') - end - - -- 2.18.0 - if version_digits[2] < 18 then - redis.call('hsetnx', settings_key, 'reservoirIncreaseInterval', '') - redis.call('hsetnx', settings_key, 'reservoirIncreaseAmount', '') - redis.call('hsetnx', settings_key, 'reservoirIncreaseMaximum', '') - redis.call('hsetnx', settings_key, 'lastReservoirIncrease', now) - redis.call('hset', settings_key, 'version', '2.18.0') - end - - end - - process_tick(now, false) -end - -local groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout')) -refresh_expiration(0, 0, groupTimeout) - -return {} -`, - "process_tick.lua": "local process_tick = function (now, always_publish)\n\n local compute_capacity = function (maxConcurrent, running, reservoir)\n if maxConcurrent ~= nil and reservoir ~= nil then\n return math.min((maxConcurrent - running), reservoir)\n elseif maxConcurrent ~= nil then\n return maxConcurrent - running\n elseif reservoir ~= nil then\n return reservoir\n else\n return nil\n end\n end\n\n local settings = redis.call('hmget', settings_key,\n 'id',\n 'maxConcurrent',\n 'running',\n 'reservoir',\n 'reservoirRefreshInterval',\n 'reservoirRefreshAmount',\n 'lastReservoirRefresh',\n 'reservoirIncreaseInterval',\n 'reservoirIncreaseAmount',\n 'reservoirIncreaseMaximum',\n 'lastReservoirIncrease',\n 'capacityPriorityCounter',\n 'clientTimeout'\n )\n local id = settings[1]\n local maxConcurrent = tonumber(settings[2])\n local running = tonumber(settings[3])\n local reservoir = tonumber(settings[4])\n local reservoirRefreshInterval = tonumber(settings[5])\n local reservoirRefreshAmount = tonumber(settings[6])\n local lastReservoirRefresh = tonumber(settings[7])\n local reservoirIncreaseInterval = tonumber(settings[8])\n local reservoirIncreaseAmount = tonumber(settings[9])\n local reservoirIncreaseMaximum = tonumber(settings[10])\n local lastReservoirIncrease = tonumber(settings[11])\n local capacityPriorityCounter = tonumber(settings[12])\n local clientTimeout = tonumber(settings[13])\n\n local initial_capacity = compute_capacity(maxConcurrent, running, reservoir)\n\n --\n -- Process 'running' changes\n --\n local expired = redis.call('zrangebyscore', job_expirations_key, '-inf', '('..now)\n\n if #expired > 0 then\n redis.call('zremrangebyscore', job_expirations_key, '-inf', '('..now)\n\n local flush_batch = function (batch, acc)\n local weights = redis.call('hmget', job_weights_key, unpack(batch))\n redis.call('hdel', job_weights_key, unpack(batch))\n local clients = redis.call('hmget', job_clients_key, unpack(batch))\n redis.call('hdel', job_clients_key, unpack(batch))\n\n -- Calculate sum of removed weights\n for i = 1, #weights do\n acc['total'] = acc['total'] + (tonumber(weights[i]) or 0)\n end\n\n -- Calculate sum of removed weights by client\n local client_weights = {}\n for i = 1, #clients do\n local removed = tonumber(weights[i]) or 0\n if removed > 0 then\n acc['client_weights'][clients[i]] = (acc['client_weights'][clients[i]] or 0) + removed\n end\n end\n end\n\n local acc = {\n ['total'] = 0,\n ['client_weights'] = {}\n }\n local batch_size = 1000\n\n -- Compute changes to Zsets and apply changes to Hashes\n for i = 1, #expired, batch_size do\n local batch = {}\n for j = i, math.min(i + batch_size - 1, #expired) do\n table.insert(batch, expired[j])\n end\n\n flush_batch(batch, acc)\n end\n\n -- Apply changes to Zsets\n if acc['total'] > 0 then\n redis.call('hincrby', settings_key, 'done', acc['total'])\n running = tonumber(redis.call('hincrby', settings_key, 'running', -acc['total']))\n end\n\n for client, weight in pairs(acc['client_weights']) do\n redis.call('zincrby', client_running_key, -weight, client)\n end\n end\n\n --\n -- Process 'reservoir' changes\n --\n local reservoirRefreshActive = reservoirRefreshInterval ~= nil and reservoirRefreshAmount ~= nil\n if reservoirRefreshActive and now >= lastReservoirRefresh + reservoirRefreshInterval then\n reservoir = reservoirRefreshAmount\n redis.call('hmset', settings_key,\n 'reservoir', reservoir,\n 'lastReservoirRefresh', now\n )\n end\n\n local reservoirIncreaseActive = reservoirIncreaseInterval ~= nil and reservoirIncreaseAmount ~= nil\n if reservoirIncreaseActive and now >= lastReservoirIncrease + reservoirIncreaseInterval then\n local num_intervals = math.floor((now - lastReservoirIncrease) / reservoirIncreaseInterval)\n local incr = reservoirIncreaseAmount * num_intervals\n if reservoirIncreaseMaximum ~= nil then\n incr = math.min(incr, reservoirIncreaseMaximum - (reservoir or 0))\n end\n if incr > 0 then\n reservoir = (reservoir or 0) + incr\n end\n redis.call('hmset', settings_key,\n 'reservoir', reservoir,\n 'lastReservoirIncrease', lastReservoirIncrease + (num_intervals * reservoirIncreaseInterval)\n )\n end\n\n --\n -- Clear unresponsive clients\n --\n local unresponsive = redis.call('zrangebyscore', client_last_seen_key, '-inf', (now - clientTimeout))\n local unresponsive_lookup = {}\n local terminated_clients = {}\n for i = 1, #unresponsive do\n unresponsive_lookup[unresponsive[i]] = true\n if tonumber(redis.call('zscore', client_running_key, unresponsive[i])) == 0 then\n table.insert(terminated_clients, unresponsive[i])\n end\n end\n if #terminated_clients > 0 then\n redis.call('zrem', client_running_key, unpack(terminated_clients))\n redis.call('hdel', client_num_queued_key, unpack(terminated_clients))\n redis.call('zrem', client_last_registered_key, unpack(terminated_clients))\n redis.call('zrem', client_last_seen_key, unpack(terminated_clients))\n end\n\n --\n -- Broadcast capacity changes\n --\n local final_capacity = compute_capacity(maxConcurrent, running, reservoir)\n\n if always_publish or (initial_capacity ~= nil and final_capacity == nil) then\n -- always_publish or was not unlimited, now unlimited\n redis.call('publish', 'b_'..id, 'capacity:'..(final_capacity or ''))\n\n elseif initial_capacity ~= nil and final_capacity ~= nil and final_capacity > initial_capacity then\n -- capacity was increased\n -- send the capacity message to the limiter having the lowest number of running jobs\n -- the tiebreaker is the limiter having not registered a job in the longest time\n\n local lowest_concurrency_value = nil\n local lowest_concurrency_clients = {}\n local lowest_concurrency_last_registered = {}\n local client_concurrencies = redis.call('zrange', client_running_key, 0, -1, 'withscores')\n\n for i = 1, #client_concurrencies, 2 do\n local client = client_concurrencies[i]\n local concurrency = tonumber(client_concurrencies[i+1])\n\n if (\n lowest_concurrency_value == nil or lowest_concurrency_value == concurrency\n ) and (\n not unresponsive_lookup[client]\n ) and (\n tonumber(redis.call('hget', client_num_queued_key, client)) > 0\n ) then\n lowest_concurrency_value = concurrency\n table.insert(lowest_concurrency_clients, client)\n local last_registered = tonumber(redis.call('zscore', client_last_registered_key, client))\n table.insert(lowest_concurrency_last_registered, last_registered)\n end\n end\n\n if #lowest_concurrency_clients > 0 then\n local position = 1\n local earliest = lowest_concurrency_last_registered[1]\n\n for i,v in ipairs(lowest_concurrency_last_registered) do\n if v < earliest then\n position = i\n earliest = v\n end\n end\n\n local next_client = lowest_concurrency_clients[position]\n redis.call('publish', 'b_'..id,\n 'capacity-priority:'..(final_capacity or '')..\n ':'..next_client..\n ':'..capacityPriorityCounter\n )\n redis.call('hincrby', settings_key, 'capacityPriorityCounter', '1')\n else\n redis.call('publish', 'b_'..id, 'capacity:'..(final_capacity or ''))\n end\n end\n\n return {\n ['capacity'] = final_capacity,\n ['running'] = running,\n ['reservoir'] = reservoir\n }\nend\n", - "queued.lua": "local clientTimeout = tonumber(redis.call('hget', settings_key, 'clientTimeout'))\nlocal valid_clients = redis.call('zrangebyscore', client_last_seen_key, (now - clientTimeout), 'inf')\nlocal client_queued = redis.call('hmget', client_num_queued_key, unpack(valid_clients))\n\nlocal sum = 0\nfor i = 1, #client_queued do\n sum = sum + tonumber(client_queued[i])\nend\n\nreturn sum\n", - "refresh_expiration.lua": "local refresh_expiration = function (now, nextRequest, groupTimeout)\n\n if groupTimeout ~= nil then\n local ttl = (nextRequest + groupTimeout) - now\n\n for i = 1, #KEYS do\n redis.call('pexpire', KEYS[i], ttl)\n end\n end\n\nend\n", - "refs.lua": "local settings_key = KEYS[1]\nlocal job_weights_key = KEYS[2]\nlocal job_expirations_key = KEYS[3]\nlocal job_clients_key = KEYS[4]\nlocal client_running_key = KEYS[5]\nlocal client_num_queued_key = KEYS[6]\nlocal client_last_registered_key = KEYS[7]\nlocal client_last_seen_key = KEYS[8]\n\nlocal now = tonumber(ARGV[1])\nlocal client = ARGV[2]\n\nlocal num_static_argv = 2\n", - "register.lua": "local index = ARGV[num_static_argv + 1]\nlocal weight = tonumber(ARGV[num_static_argv + 2])\nlocal expiration = tonumber(ARGV[num_static_argv + 3])\n\nlocal state = process_tick(now, false)\nlocal capacity = state['capacity']\nlocal reservoir = state['reservoir']\n\nlocal settings = redis.call('hmget', settings_key,\n 'nextRequest',\n 'minTime',\n 'groupTimeout'\n)\nlocal nextRequest = tonumber(settings[1])\nlocal minTime = tonumber(settings[2])\nlocal groupTimeout = tonumber(settings[3])\n\nif conditions_check(capacity, weight) then\n\n redis.call('hincrby', settings_key, 'running', weight)\n redis.call('hset', job_weights_key, index, weight)\n if expiration ~= nil then\n redis.call('zadd', job_expirations_key, now + expiration, index)\n end\n redis.call('hset', job_clients_key, index, client)\n redis.call('zincrby', client_running_key, weight, client)\n redis.call('hincrby', client_num_queued_key, client, -1)\n redis.call('zadd', client_last_registered_key, now, client)\n\n local wait = math.max(nextRequest - now, 0)\n local newNextRequest = now + wait + minTime\n\n if reservoir == nil then\n redis.call('hset', settings_key,\n 'nextRequest', newNextRequest\n )\n else\n reservoir = reservoir - weight\n redis.call('hmset', settings_key,\n 'reservoir', reservoir,\n 'nextRequest', newNextRequest\n )\n end\n\n refresh_expiration(now, newNextRequest, groupTimeout)\n\n return {true, wait, reservoir}\n\nelse\n return {false}\nend\n", - "register_client.lua": "local queued = tonumber(ARGV[num_static_argv + 1])\n\n-- Could have been re-registered concurrently\nif not redis.call('zscore', client_last_seen_key, client) then\n redis.call('zadd', client_running_key, 0, client)\n redis.call('hset', client_num_queued_key, client, queued)\n redis.call('zadd', client_last_registered_key, 0, client)\nend\n\nredis.call('zadd', client_last_seen_key, now, client)\n\nreturn {}\n", - "running.lua": "return process_tick(now, false)['running']\n", - "submit.lua": "local queueLength = tonumber(ARGV[num_static_argv + 1])\nlocal weight = tonumber(ARGV[num_static_argv + 2])\n\nlocal capacity = process_tick(now, false)['capacity']\n\nlocal settings = redis.call('hmget', settings_key,\n 'id',\n 'maxConcurrent',\n 'highWater',\n 'nextRequest',\n 'strategy',\n 'unblockTime',\n 'penalty',\n 'minTime',\n 'groupTimeout'\n)\nlocal id = settings[1]\nlocal maxConcurrent = tonumber(settings[2])\nlocal highWater = tonumber(settings[3])\nlocal nextRequest = tonumber(settings[4])\nlocal strategy = tonumber(settings[5])\nlocal unblockTime = tonumber(settings[6])\nlocal penalty = tonumber(settings[7])\nlocal minTime = tonumber(settings[8])\nlocal groupTimeout = tonumber(settings[9])\n\nif maxConcurrent ~= nil and weight > maxConcurrent then\n return redis.error_reply('OVERWEIGHT:'..weight..':'..maxConcurrent)\nend\n\nlocal reachedHWM = (highWater ~= nil and queueLength == highWater\n and not (\n conditions_check(capacity, weight)\n and nextRequest - now <= 0\n )\n)\n\nlocal blocked = strategy == 3 and (reachedHWM or unblockTime >= now)\n\nif blocked then\n local computedPenalty = penalty\n if computedPenalty == nil then\n if minTime == 0 then\n computedPenalty = 5000\n else\n computedPenalty = 15 * minTime\n end\n end\n\n local newNextRequest = now + computedPenalty + minTime\n\n redis.call('hmset', settings_key,\n 'unblockTime', now + computedPenalty,\n 'nextRequest', newNextRequest\n )\n\n local clients_queued_reset = redis.call('hkeys', client_num_queued_key)\n local queued_reset = {}\n for i = 1, #clients_queued_reset do\n table.insert(queued_reset, clients_queued_reset[i])\n table.insert(queued_reset, 0)\n end\n redis.call('hmset', client_num_queued_key, unpack(queued_reset))\n\n redis.call('publish', 'b_'..id, 'blocked:')\n\n refresh_expiration(now, newNextRequest, groupTimeout)\nend\n\nif not blocked and not reachedHWM then\n redis.call('hincrby', client_num_queued_key, client, 1)\nend\n\nreturn {reachedHWM, blocked, strategy}\n", - "update_settings.lua": "local args = {'hmset', settings_key}\n\nfor i = num_static_argv + 1, #ARGV do\n table.insert(args, ARGV[i])\nend\n\nredis.call(unpack(args))\n\nprocess_tick(now, true)\n\nlocal groupTimeout = tonumber(redis.call('hget', settings_key, 'groupTimeout'))\nrefresh_expiration(0, 0, groupTimeout)\n\nreturn {}\n", - "validate_client.lua": "if not redis.call('zscore', client_last_seen_key, client) then\n return redis.error_reply('UNKNOWN_CLIENT')\nend\n\nredis.call('zadd', client_last_seen_key, now, client)\n", - "validate_keys.lua": "if not (redis.call('exists', settings_key) == 1) then\n return redis.error_reply('SETTINGS_KEY_NOT_FOUND')\nend\n" - }; +var require_meta = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/meta.js"(exports2, module14) { + "use strict"; + module14.exports = { version: "8.19.0" }; } }); -var require_Scripts = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Scripts.js"(exports2) { +var require_proto = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/proto.js"(exports2, module14) { "use strict"; - var headers; - var lua; - var templates; - lua = require_lua(); - headers = { - refs: lua["refs.lua"], - validate_keys: lua["validate_keys.lua"], - validate_client: lua["validate_client.lua"], - refresh_expiration: lua["refresh_expiration.lua"], - process_tick: lua["process_tick.lua"], - conditions_check: lua["conditions_check.lua"], - get_time: lua["get_time.lua"] - }; - exports2.allKeys = function(id) { - return [ - /* - HASH - */ - `b_${id}_settings`, - /* - HASH - job index -> weight - */ - `b_${id}_job_weights`, - /* - ZSET - job index -> expiration - */ - `b_${id}_job_expirations`, - /* - HASH - job index -> client - */ - `b_${id}_job_clients`, - /* - ZSET - client -> sum running - */ - `b_${id}_client_running`, - /* - HASH - client -> num queued - */ - `b_${id}_client_num_queued`, - /* - ZSET - client -> last job registered - */ - `b_${id}_client_last_registered`, - /* - ZSET - client -> last seen - */ - `b_${id}_client_last_seen` - ]; + var { EventEmitter } = __require2("node:events"); + var { + lsCacheSym, + levelValSym, + setLevelSym, + getLevelSym, + chindingsSym, + parsedChindingsSym, + mixinSym, + asJsonSym, + writeSym, + mixinMergeStrategySym, + timeSym, + timeSliceIndexSym, + streamSym, + serializersSym, + formattersSym, + errorKeySym, + messageKeySym, + useOnlyCustomLevelsSym, + needsMetadataGsym, + redactFmtSym, + stringifySym, + formatOptsSym, + stringifiersSym, + msgPrefixSym + } = require_symbols(); + var { + getLevel, + setLevel, + isLevelEnabled, + mappings, + initialLsCache, + genLsCache, + assertNoLevelCollisions + } = require_levels(); + var { + asChindings, + asJson, + buildFormatters, + stringify: stringify2 + } = require_tools(); + var { + version: version3 + } = require_meta(); + var redaction = require_redaction(); + var constructor = class Pino { }; - templates = { - init: { - keys: exports2.allKeys, - headers: ["process_tick"], - refresh_expiration: true, - code: lua["init.lua"] - }, - group_check: { - keys: exports2.allKeys, - headers: [], - refresh_expiration: false, - code: lua["group_check.lua"] - }, - register_client: { - keys: exports2.allKeys, - headers: ["validate_keys"], - refresh_expiration: false, - code: lua["register_client.lua"] - }, - blacklist_client: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client"], - refresh_expiration: false, - code: lua["blacklist_client.lua"] - }, - heartbeat: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick"], - refresh_expiration: false, - code: lua["heartbeat.lua"] - }, - update_settings: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick"], - refresh_expiration: true, - code: lua["update_settings.lua"] - }, - running: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick"], - refresh_expiration: false, - code: lua["running.lua"] - }, - queued: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client"], - refresh_expiration: false, - code: lua["queued.lua"] - }, - done: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick"], - refresh_expiration: false, - code: lua["done.lua"] - }, - check: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"], - refresh_expiration: false, - code: lua["check.lua"] - }, - submit: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"], - refresh_expiration: true, - code: lua["submit.lua"] - }, - register: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick", "conditions_check"], - refresh_expiration: true, - code: lua["register.lua"] - }, - free: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick"], - refresh_expiration: true, - code: lua["free.lua"] + var prototype = { + constructor, + child, + bindings, + setBindings, + flush, + isLevelEnabled, + version: version3, + get level() { + return this[getLevelSym](); }, - current_reservoir: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick"], - refresh_expiration: false, - code: lua["current_reservoir.lua"] + set level(lvl) { + this[setLevelSym](lvl); }, - increment_reservoir: { - keys: exports2.allKeys, - headers: ["validate_keys", "validate_client", "process_tick"], - refresh_expiration: true, - code: lua["increment_reservoir.lua"] - } - }; - exports2.names = Object.keys(templates); - exports2.keys = function(name, id) { - return templates[name].keys(id); + get levelVal() { + return this[levelValSym]; + }, + set levelVal(n) { + throw Error("levelVal is read-only"); + }, + [lsCacheSym]: initialLsCache, + [writeSym]: write, + [asJsonSym]: asJson, + [getLevelSym]: getLevel, + [setLevelSym]: setLevel }; - exports2.payload = function(name) { - var template; - template = templates[name]; - return Array.prototype.concat(headers.refs, template.headers.map(function(h2) { - return headers[h2]; - }), template.refresh_expiration ? headers.refresh_expiration : "", template.code).join("\n"); + Object.setPrototypeOf(prototype, EventEmitter.prototype); + module14.exports = function() { + return Object.create(prototype); }; + var resetChildingsFormatter = (bindings2) => bindings2; + function child(bindings2, options2) { + if (!bindings2) { + throw Error("missing bindings for child Pino"); + } + options2 = options2 || {}; + const serializers = this[serializersSym]; + const formatters = this[formattersSym]; + const instance = Object.create(this); + if (options2.hasOwnProperty("serializers") === true) { + instance[serializersSym] = /* @__PURE__ */ Object.create(null); + for (const k in serializers) { + instance[serializersSym][k] = serializers[k]; + } + const parentSymbols = Object.getOwnPropertySymbols(serializers); + for (var i2 = 0; i2 < parentSymbols.length; i2++) { + const ks = parentSymbols[i2]; + instance[serializersSym][ks] = serializers[ks]; + } + for (const bk in options2.serializers) { + instance[serializersSym][bk] = options2.serializers[bk]; + } + const bindingsSymbols = Object.getOwnPropertySymbols(options2.serializers); + for (var bi = 0; bi < bindingsSymbols.length; bi++) { + const bks = bindingsSymbols[bi]; + instance[serializersSym][bks] = options2.serializers[bks]; + } + } else instance[serializersSym] = serializers; + if (options2.hasOwnProperty("formatters")) { + const { level, bindings: chindings, log: log2 } = options2.formatters; + instance[formattersSym] = buildFormatters( + level || formatters.level, + chindings || resetChildingsFormatter, + log2 || formatters.log + ); + } else { + instance[formattersSym] = buildFormatters( + formatters.level, + resetChildingsFormatter, + formatters.log + ); + } + if (options2.hasOwnProperty("customLevels") === true) { + assertNoLevelCollisions(this.levels, options2.customLevels); + instance.levels = mappings(options2.customLevels, instance[useOnlyCustomLevelsSym]); + genLsCache(instance); + } + if (typeof options2.redact === "object" && options2.redact !== null || Array.isArray(options2.redact)) { + instance.redact = options2.redact; + const stringifiers = redaction(instance.redact, stringify2); + const formatOpts = { stringify: stringifiers[redactFmtSym] }; + instance[stringifySym] = stringify2; + instance[stringifiersSym] = stringifiers; + instance[formatOptsSym] = formatOpts; + } + if (typeof options2.msgPrefix === "string") { + instance[msgPrefixSym] = (this[msgPrefixSym] || "") + options2.msgPrefix; + } + instance[chindingsSym] = asChindings(instance, bindings2); + const childLevel = options2.level || this.level; + instance[setLevelSym](childLevel); + this.onChild(instance); + return instance; + } + function bindings() { + const chindings = this[chindingsSym]; + const chindingsJson = `{${chindings.substr(1)}}`; + const bindingsFromJson = JSON.parse(chindingsJson); + delete bindingsFromJson.pid; + delete bindingsFromJson.hostname; + return bindingsFromJson; + } + function setBindings(newBindings) { + const chindings = asChindings(this, newBindings); + this[chindingsSym] = chindings; + delete this[parsedChindingsSym]; + } + function defaultMixinMergeStrategy(mergeObject, mixinObject) { + return Object.assign(mixinObject, mergeObject); + } + function write(_obj, msg, num) { + const t = this[timeSym](); + const mixin3 = this[mixinSym]; + const errorKey = this[errorKeySym]; + const messageKey = this[messageKeySym]; + const mixinMergeStrategy = this[mixinMergeStrategySym] || defaultMixinMergeStrategy; + let obj; + if (_obj === void 0 || _obj === null) { + obj = {}; + } else if (_obj instanceof Error) { + obj = { [errorKey]: _obj }; + if (msg === void 0) { + msg = _obj.message; + } + } else { + obj = _obj; + if (msg === void 0 && _obj[messageKey] === void 0 && _obj[errorKey]) { + msg = _obj[errorKey].message; + } + } + if (mixin3) { + obj = mixinMergeStrategy(obj, mixin3(obj, num, this)); + } + const s = this[asJsonSym](obj, msg, num, t); + const stream = this[streamSym]; + if (stream[needsMetadataGsym] === true) { + stream.lastLevel = num; + stream.lastObj = obj; + stream.lastMsg = msg; + stream.lastTime = t.slice(this[timeSliceIndexSym]); + stream.lastLogger = this; + } + stream.write(s); + } + function noop() { + } + function flush(cb) { + if (cb != null && typeof cb !== "function") { + throw Error("callback must be a function"); + } + const stream = this[streamSym]; + if (typeof stream.flush === "function") { + stream.flush(cb || noop); + } else if (cb) cb(); + } } }); -var require_RedisConnection = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/RedisConnection.js"(exports, module) { +var require_safe_stable_stringify = __commonJS({ + "node_modules/.deno/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports2, module14) { "use strict"; - function asyncGeneratorStep(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); - return; + var { hasOwnProperty } = Object.prototype; + var stringify2 = configure(); + stringify2.configure = configure; + stringify2.stringify = stringify2; + stringify2.default = stringify2; + exports2.stringify = stringify2; + exports2.configure = configure; + module14.exports = stringify2; + var strEscapeSequencesRegExp = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/; + function strEscape(str) { + if (str.length < 5e3 && !strEscapeSequencesRegExp.test(str)) { + return `"${str}"`; } - if (info.done) { - resolve82(value); - } else { - Promise.resolve(value).then(_next, _throw); + return JSON.stringify(str); + } + function sort(array2, comparator) { + if (array2.length > 200 || comparator) { + return array2.sort(comparator); + } + for (let i2 = 1; i2 < array2.length; i2++) { + const currentValue = array2[i2]; + let position = i2; + while (position !== 0 && array2[position - 1] > currentValue) { + array2[position] = array2[position - 1]; + position--; + } + array2[position] = currentValue; } + return array2; } - function _asyncToGenerator(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "next", value); - } - function _throw(err) { - asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "throw", err); - } - _next(void 0); - }); - }; + var typedArrayPrototypeGetSymbolToStringTag = Object.getOwnPropertyDescriptor( + Object.getPrototypeOf( + Object.getPrototypeOf( + new Int8Array() + ) + ), + Symbol.toStringTag + ).get; + function isTypedArrayWithEntries(value) { + return typedArrayPrototypeGetSymbolToStringTag.call(value) !== void 0 && value.length !== 0; } - var Events; - var RedisConnection; - var Scripts; - var parser; - parser = require_parser2(); - Events = require_Events(); - Scripts = require_Scripts(); - RedisConnection = function() { - class RedisConnection { - constructor(options = {}) { - parser.load(options, this.defaults, this); - if (this.Redis == null) { - this.Redis = eval("require")("redis"); - } - if (this.Events == null) { - this.Events = new Events(this); - } - this.terminated = false; - if (this.client == null) { - this.client = this.Redis.createClient(this.clientOptions); - } - this.subscriber = this.client.duplicate(); - this.limiters = {}; - this.shas = {}; - this.ready = this.Promise.all([this._setup(this.client, false), this._setup(this.subscriber, true)]).then(() => { - return this._loadScripts(); - }).then(() => { - return { - client: this.client, - subscriber: this.subscriber - }; - }); + function stringifyTypedArray(array2, separator, maximumBreadth) { + if (array2.length < maximumBreadth) { + maximumBreadth = array2.length; + } + const whitespace = separator === "," ? "" : " "; + let res = `"0":${whitespace}${array2[0]}`; + for (let i2 = 1; i2 < maximumBreadth; i2++) { + res += `${separator}"${i2}":${whitespace}${array2[i2]}`; + } + return res; + } + function getCircularValueOption(options2) { + if (hasOwnProperty.call(options2, "circularValue")) { + const circularValue = options2.circularValue; + if (typeof circularValue === "string") { + return `"${circularValue}"`; } - _setup(client, sub) { - client.setMaxListeners(0); - return new this.Promise((resolve82, reject) => { - client.on("error", (e2) => { - return this.Events.trigger("error", e2); - }); - if (sub) { - client.on("message", (channel, message) => { - var ref; - return (ref = this.limiters[channel]) != null ? ref._store.onMessage(channel, message) : void 0; - }); - } - if (client.ready) { - return resolve82(); - } else { - return client.once("ready", resolve82); + if (circularValue == null) { + return circularValue; + } + if (circularValue === Error || circularValue === TypeError) { + return { + toString() { + throw new TypeError("Converting circular structure to JSON"); } - }); + }; } - _loadScript(name) { - return new this.Promise((resolve82, reject) => { - var payload; - payload = Scripts.payload(name); - return this.client.multi([["script", "load", payload]]).exec((err, replies) => { - if (err != null) { - return reject(err); - } - this.shas[name] = replies[0]; - return resolve82(replies[0]); - }); - }); + throw new TypeError('The "circularValue" argument must be of type string or the value null or undefined'); + } + return '"[Circular]"'; + } + function getDeterministicOption(options2) { + let value; + if (hasOwnProperty.call(options2, "deterministic")) { + value = options2.deterministic; + if (typeof value !== "boolean" && typeof value !== "function") { + throw new TypeError('The "deterministic" argument must be of type boolean or comparator function'); } - _loadScripts() { - return this.Promise.all(Scripts.names.map((k) => { - return this._loadScript(k); - })); + } + return value === void 0 ? true : value; + } + function getBooleanOption(options2, key) { + let value; + if (hasOwnProperty.call(options2, key)) { + value = options2[key]; + if (typeof value !== "boolean") { + throw new TypeError(`The "${key}" argument must be of type boolean`); } - __runCommand__(cmd) { - var _this = this; - return _asyncToGenerator(function* () { - yield _this.ready; - return new _this.Promise((resolve82, reject) => { - return _this.client.multi([cmd]).exec_atomic(function(err, replies) { - if (err != null) { - return reject(err); - } else { - return resolve82(replies[0]); - } - }); - }); - })(); + } + return value === void 0 ? true : value; + } + function getPositiveIntegerOption(options2, key) { + let value; + if (hasOwnProperty.call(options2, key)) { + value = options2[key]; + if (typeof value !== "number") { + throw new TypeError(`The "${key}" argument must be of type number`); } - __addLimiter__(instance) { - return this.Promise.all([instance.channel(), instance.channel_client()].map((channel) => { - return new this.Promise((resolve82, reject) => { - var handler; - handler = (chan) => { - if (chan === channel) { - this.subscriber.removeListener("subscribe", handler); - this.limiters[channel] = instance; - return resolve82(); - } - }; - this.subscriber.on("subscribe", handler); - return this.subscriber.subscribe(channel); - }); - })); + if (!Number.isInteger(value)) { + throw new TypeError(`The "${key}" argument must be an integer`); } - __removeLimiter__(instance) { - var _this2 = this; - return this.Promise.all([instance.channel(), instance.channel_client()].map( - /* @__PURE__ */ function() { - var _ref = _asyncToGenerator(function* (channel) { - if (!_this2.terminated) { - yield new _this2.Promise((resolve82, reject) => { - return _this2.subscriber.unsubscribe(channel, function(err, chan) { - if (err != null) { - return reject(err); - } - if (chan === channel) { - return resolve82(); - } - }); - }); - } - return delete _this2.limiters[channel]; - }); - return function(_x) { - return _ref.apply(this, arguments); - }; - }() - )); + if (value < 1) { + throw new RangeError(`The "${key}" argument must be >= 1`); } - __scriptArgs__(name, id, args, cb) { - var keys; - keys = Scripts.keys(name, id); - return [this.shas[name], keys.length].concat(keys, args, cb); + } + return value === void 0 ? Infinity : value; + } + function getItemCount(number3) { + if (number3 === 1) { + return "1 item"; + } + return `${number3} items`; + } + function getUniqueReplacerSet(replacerArray) { + const replacerSet = /* @__PURE__ */ new Set(); + for (const value of replacerArray) { + if (typeof value === "string" || typeof value === "number") { + replacerSet.add(String(value)); } - __scriptFn__(name) { - return this.client.evalsha.bind(this.client); + } + return replacerSet; + } + function getStrictOption(options2) { + if (hasOwnProperty.call(options2, "strict")) { + const value = options2.strict; + if (typeof value !== "boolean") { + throw new TypeError('The "strict" argument must be of type boolean'); } - disconnect(flush = true) { - var i2, k, len, ref; - ref = Object.keys(this.limiters); - for (i2 = 0, len = ref.length; i2 < len; i2++) { - k = ref[i2]; - clearInterval(this.limiters[k]._store.heartbeat); + if (value) { + return (value2) => { + let message = `Object can not safely be stringified. Received type ${typeof value2}`; + if (typeof value2 !== "function") message += ` (${value2.toString()})`; + throw new Error(message); + }; + } + } + } + function configure(options2) { + options2 = { ...options2 }; + const fail = getStrictOption(options2); + if (fail) { + if (options2.bigint === void 0) { + options2.bigint = false; + } + if (!("circularValue" in options2)) { + options2.circularValue = Error; + } + } + const circularValue = getCircularValueOption(options2); + const bigint2 = getBooleanOption(options2, "bigint"); + const deterministic = getDeterministicOption(options2); + const comparator = typeof deterministic === "function" ? deterministic : void 0; + const maximumDepth = getPositiveIntegerOption(options2, "maximumDepth"); + const maximumBreadth = getPositiveIntegerOption(options2, "maximumBreadth"); + function stringifyFnReplacer(key, parent, stack, replacer, spacer, indentation) { + let value = parent[key]; + if (typeof value === "object" && value !== null && typeof value.toJSON === "function") { + value = value.toJSON(key); + } + value = replacer.call(parent, key, value); + switch (typeof value) { + case "string": + return strEscape(value); + case "object": { + if (value === null) { + return "null"; + } + if (stack.indexOf(value) !== -1) { + return circularValue; + } + let res = ""; + let join10 = ","; + const originalIndentation = indentation; + if (Array.isArray(value)) { + if (value.length === 0) { + return "[]"; + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"'; + } + stack.push(value); + if (spacer !== "") { + indentation += spacer; + res += ` +${indentation}`; + join10 = `, +${indentation}`; + } + const maximumValuesToStringify = Math.min(value.length, maximumBreadth); + let i2 = 0; + for (; i2 < maximumValuesToStringify - 1; i2++) { + const tmp2 = stringifyFnReplacer(String(i2), value, stack, replacer, spacer, indentation); + res += tmp2 !== void 0 ? tmp2 : "null"; + res += join10; + } + const tmp = stringifyFnReplacer(String(i2), value, stack, replacer, spacer, indentation); + res += tmp !== void 0 ? tmp : "null"; + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1; + res += `${join10}"... ${getItemCount(removedKeys)} not stringified"`; + } + if (spacer !== "") { + res += ` +${originalIndentation}`; + } + stack.pop(); + return `[${res}]`; + } + let keys = Object.keys(value); + const keyLength = keys.length; + if (keyLength === 0) { + return "{}"; + } + if (maximumDepth < stack.length + 1) { + return '"[Object]"'; + } + let whitespace = ""; + let separator = ""; + if (spacer !== "") { + indentation += spacer; + join10 = `, +${indentation}`; + whitespace = " "; + } + const maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth); + if (deterministic && !isTypedArrayWithEntries(value)) { + keys = sort(keys, comparator); + } + stack.push(value); + for (let i2 = 0; i2 < maximumPropertiesToStringify; i2++) { + const key2 = keys[i2]; + const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation); + if (tmp !== void 0) { + res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`; + separator = join10; + } + } + if (keyLength > maximumBreadth) { + const removedKeys = keyLength - maximumBreadth; + res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`; + separator = join10; + } + if (spacer !== "" && separator.length > 1) { + res = ` +${indentation}${res} +${originalIndentation}`; + } + stack.pop(); + return `{${res}}`; } - this.limiters = {}; - this.terminated = true; - this.client.end(flush); - this.subscriber.end(flush); - return this.Promise.resolve(); + case "number": + return isFinite(value) ? String(value) : fail ? fail(value) : "null"; + case "boolean": + return value === true ? "true" : "false"; + case "undefined": + return void 0; + case "bigint": + if (bigint2) { + return String(value); + } + // fallthrough + default: + return fail ? fail(value) : void 0; } } - ; - RedisConnection.prototype.datastore = "redis"; - RedisConnection.prototype.defaults = { - Redis: null, - clientOptions: {}, - client: null, - Promise, - Events: null - }; - return RedisConnection; - }.call(void 0); - module.exports = RedisConnection; - } -}); -var require_IORedisConnection = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/IORedisConnection.js"(exports, module) { - "use strict"; - function _slicedToArray(arr, i2) { - return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i2) || _nonIterableRest(); - } - function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - function _iterableToArrayLimit(arr, i2) { - var _arr = []; - var _n = true; - var _d = false; - var _e = void 0; - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - if (i2 && _arr.length === i2) break; + function stringifyArrayReplacer(key, value, stack, replacer, spacer, indentation) { + if (typeof value === "object" && value !== null && typeof value.toJSON === "function") { + value = value.toJSON(key); } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; + switch (typeof value) { + case "string": + return strEscape(value); + case "object": { + if (value === null) { + return "null"; + } + if (stack.indexOf(value) !== -1) { + return circularValue; + } + const originalIndentation = indentation; + let res = ""; + let join10 = ","; + if (Array.isArray(value)) { + if (value.length === 0) { + return "[]"; + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"'; + } + stack.push(value); + if (spacer !== "") { + indentation += spacer; + res += ` +${indentation}`; + join10 = `, +${indentation}`; + } + const maximumValuesToStringify = Math.min(value.length, maximumBreadth); + let i2 = 0; + for (; i2 < maximumValuesToStringify - 1; i2++) { + const tmp2 = stringifyArrayReplacer(String(i2), value[i2], stack, replacer, spacer, indentation); + res += tmp2 !== void 0 ? tmp2 : "null"; + res += join10; + } + const tmp = stringifyArrayReplacer(String(i2), value[i2], stack, replacer, spacer, indentation); + res += tmp !== void 0 ? tmp : "null"; + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1; + res += `${join10}"... ${getItemCount(removedKeys)} not stringified"`; + } + if (spacer !== "") { + res += ` +${originalIndentation}`; + } + stack.pop(); + return `[${res}]`; + } + stack.push(value); + let whitespace = ""; + if (spacer !== "") { + indentation += spacer; + join10 = `, +${indentation}`; + whitespace = " "; + } + let separator = ""; + for (const key2 of replacer) { + const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation); + if (tmp !== void 0) { + res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`; + separator = join10; + } + } + if (spacer !== "" && separator.length > 1) { + res = ` +${indentation}${res} +${originalIndentation}`; + } + stack.pop(); + return `{${res}}`; + } + case "number": + return isFinite(value) ? String(value) : fail ? fail(value) : "null"; + case "boolean": + return value === true ? "true" : "false"; + case "undefined": + return void 0; + case "bigint": + if (bigint2) { + return String(value); + } + // fallthrough + default: + return fail ? fail(value) : void 0; } } - return _arr; - } - function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; - } - function asyncGeneratorStep(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); - return; - } - if (info.done) { - resolve82(value); - } else { - Promise.resolve(value).then(_next, _throw); - } - } - function _asyncToGenerator(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "next", value); - } - function _throw(err) { - asyncGeneratorStep(gen, resolve82, reject, _next, _throw, "throw", err); - } - _next(void 0); - }); - }; - } - var Events; - var IORedisConnection; - var Scripts; - var parser; - parser = require_parser2(); - Events = require_Events(); - Scripts = require_Scripts(); - IORedisConnection = function() { - class IORedisConnection { - constructor(options = {}) { - parser.load(options, this.defaults, this); - if (this.Redis == null) { - this.Redis = eval("require")("ioredis"); - } - if (this.Events == null) { - this.Events = new Events(this); - } - this.terminated = false; - if (this.clusterNodes != null) { - this.client = new this.Redis.Cluster(this.clusterNodes, this.clientOptions); - this.subscriber = new this.Redis.Cluster(this.clusterNodes, this.clientOptions); - } else if (this.client != null && this.client.duplicate == null) { - this.subscriber = new this.Redis.Cluster(this.client.startupNodes, this.client.options); - } else { - if (this.client == null) { - this.client = new this.Redis(this.clientOptions); + function stringifyIndent(key, value, stack, spacer, indentation) { + switch (typeof value) { + case "string": + return strEscape(value); + case "object": { + if (value === null) { + return "null"; } - this.subscriber = this.client.duplicate(); + if (typeof value.toJSON === "function") { + value = value.toJSON(key); + if (typeof value !== "object") { + return stringifyIndent(key, value, stack, spacer, indentation); + } + if (value === null) { + return "null"; + } + } + if (stack.indexOf(value) !== -1) { + return circularValue; + } + const originalIndentation = indentation; + if (Array.isArray(value)) { + if (value.length === 0) { + return "[]"; + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"'; + } + stack.push(value); + indentation += spacer; + let res2 = ` +${indentation}`; + const join11 = `, +${indentation}`; + const maximumValuesToStringify = Math.min(value.length, maximumBreadth); + let i2 = 0; + for (; i2 < maximumValuesToStringify - 1; i2++) { + const tmp2 = stringifyIndent(String(i2), value[i2], stack, spacer, indentation); + res2 += tmp2 !== void 0 ? tmp2 : "null"; + res2 += join11; + } + const tmp = stringifyIndent(String(i2), value[i2], stack, spacer, indentation); + res2 += tmp !== void 0 ? tmp : "null"; + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1; + res2 += `${join11}"... ${getItemCount(removedKeys)} not stringified"`; + } + res2 += ` +${originalIndentation}`; + stack.pop(); + return `[${res2}]`; + } + let keys = Object.keys(value); + const keyLength = keys.length; + if (keyLength === 0) { + return "{}"; + } + if (maximumDepth < stack.length + 1) { + return '"[Object]"'; + } + indentation += spacer; + const join10 = `, +${indentation}`; + let res = ""; + let separator = ""; + let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth); + if (isTypedArrayWithEntries(value)) { + res += stringifyTypedArray(value, join10, maximumBreadth); + keys = keys.slice(value.length); + maximumPropertiesToStringify -= value.length; + separator = join10; + } + if (deterministic) { + keys = sort(keys, comparator); + } + stack.push(value); + for (let i2 = 0; i2 < maximumPropertiesToStringify; i2++) { + const key2 = keys[i2]; + const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation); + if (tmp !== void 0) { + res += `${separator}${strEscape(key2)}: ${tmp}`; + separator = join10; + } + } + if (keyLength > maximumBreadth) { + const removedKeys = keyLength - maximumBreadth; + res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`; + separator = join10; + } + if (separator !== "") { + res = ` +${indentation}${res} +${originalIndentation}`; + } + stack.pop(); + return `{${res}}`; } - this.limiters = {}; - this.ready = this.Promise.all([this._setup(this.client, false), this._setup(this.subscriber, true)]).then(() => { - this._loadScripts(); - return { - client: this.client, - subscriber: this.subscriber - }; - }); + case "number": + return isFinite(value) ? String(value) : fail ? fail(value) : "null"; + case "boolean": + return value === true ? "true" : "false"; + case "undefined": + return void 0; + case "bigint": + if (bigint2) { + return String(value); + } + // fallthrough + default: + return fail ? fail(value) : void 0; } - _setup(client, sub) { - client.setMaxListeners(0); - return new this.Promise((resolve82, reject) => { - client.on("error", (e2) => { - return this.Events.trigger("error", e2); - }); - if (sub) { - client.on("message", (channel, message) => { - var ref; - return (ref = this.limiters[channel]) != null ? ref._store.onMessage(channel, message) : void 0; - }); + } + function stringifySimple(key, value, stack) { + switch (typeof value) { + case "string": + return strEscape(value); + case "object": { + if (value === null) { + return "null"; } - if (client.status === "ready") { - return resolve82(); - } else { - return client.once("ready", resolve82); + if (typeof value.toJSON === "function") { + value = value.toJSON(key); + if (typeof value !== "object") { + return stringifySimple(key, value, stack); + } + if (value === null) { + return "null"; + } } - }); - } - _loadScripts() { - return Scripts.names.forEach((name) => { - return this.client.defineCommand(name, { - lua: Scripts.payload(name) - }); - }); - } - __runCommand__(cmd) { - var _this = this; - return _asyncToGenerator(function* () { - var _, deleted; - yield _this.ready; - var _ref = yield _this.client.pipeline([cmd]).exec(); - var _ref2 = _slicedToArray(_ref, 1); - var _ref2$ = _slicedToArray(_ref2[0], 2); - _ = _ref2$[0]; - deleted = _ref2$[1]; - return deleted; - })(); - } - __addLimiter__(instance) { - return this.Promise.all([instance.channel(), instance.channel_client()].map((channel) => { - return new this.Promise((resolve82, reject) => { - return this.subscriber.subscribe(channel, () => { - this.limiters[channel] = instance; - return resolve82(); - }); - }); - })); - } - __removeLimiter__(instance) { - var _this2 = this; - return [instance.channel(), instance.channel_client()].forEach( - /* @__PURE__ */ function() { - var _ref3 = _asyncToGenerator(function* (channel) { - if (!_this2.terminated) { - yield _this2.subscriber.unsubscribe(channel); - } - return delete _this2.limiters[channel]; - }); - return function(_x) { - return _ref3.apply(this, arguments); - }; - }() - ); - } - __scriptArgs__(name, id, args, cb) { - var keys; - keys = Scripts.keys(name, id); - return [keys.length].concat(keys, args, cb); - } - __scriptFn__(name) { - return this.client[name].bind(this.client); + if (stack.indexOf(value) !== -1) { + return circularValue; + } + let res = ""; + const hasLength = value.length !== void 0; + if (hasLength && Array.isArray(value)) { + if (value.length === 0) { + return "[]"; + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"'; + } + stack.push(value); + const maximumValuesToStringify = Math.min(value.length, maximumBreadth); + let i2 = 0; + for (; i2 < maximumValuesToStringify - 1; i2++) { + const tmp2 = stringifySimple(String(i2), value[i2], stack); + res += tmp2 !== void 0 ? tmp2 : "null"; + res += ","; + } + const tmp = stringifySimple(String(i2), value[i2], stack); + res += tmp !== void 0 ? tmp : "null"; + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1; + res += `,"... ${getItemCount(removedKeys)} not stringified"`; + } + stack.pop(); + return `[${res}]`; + } + let keys = Object.keys(value); + const keyLength = keys.length; + if (keyLength === 0) { + return "{}"; + } + if (maximumDepth < stack.length + 1) { + return '"[Object]"'; + } + let separator = ""; + let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth); + if (hasLength && isTypedArrayWithEntries(value)) { + res += stringifyTypedArray(value, ",", maximumBreadth); + keys = keys.slice(value.length); + maximumPropertiesToStringify -= value.length; + separator = ","; + } + if (deterministic) { + keys = sort(keys, comparator); + } + stack.push(value); + for (let i2 = 0; i2 < maximumPropertiesToStringify; i2++) { + const key2 = keys[i2]; + const tmp = stringifySimple(key2, value[key2], stack); + if (tmp !== void 0) { + res += `${separator}${strEscape(key2)}:${tmp}`; + separator = ","; + } + } + if (keyLength > maximumBreadth) { + const removedKeys = keyLength - maximumBreadth; + res += `${separator}"...":"${getItemCount(removedKeys)} not stringified"`; + } + stack.pop(); + return `{${res}}`; + } + case "number": + return isFinite(value) ? String(value) : fail ? fail(value) : "null"; + case "boolean": + return value === true ? "true" : "false"; + case "undefined": + return void 0; + case "bigint": + if (bigint2) { + return String(value); + } + // fallthrough + default: + return fail ? fail(value) : void 0; } - disconnect(flush = true) { - var i2, k, len, ref; - ref = Object.keys(this.limiters); - for (i2 = 0, len = ref.length; i2 < len; i2++) { - k = ref[i2]; - clearInterval(this.limiters[k]._store.heartbeat); + } + function stringify3(value, replacer, space) { + if (arguments.length > 1) { + let spacer = ""; + if (typeof space === "number") { + spacer = " ".repeat(Math.min(space, 10)); + } else if (typeof space === "string") { + spacer = space.slice(0, 10); + } + if (replacer != null) { + if (typeof replacer === "function") { + return stringifyFnReplacer("", { "": value }, [], replacer, spacer, ""); + } + if (Array.isArray(replacer)) { + return stringifyArrayReplacer("", value, [], getUniqueReplacerSet(replacer), spacer, ""); + } } - this.limiters = {}; - this.terminated = true; - if (flush) { - return this.Promise.all([this.client.quit(), this.subscriber.quit()]); - } else { - this.client.disconnect(); - this.subscriber.disconnect(); - return this.Promise.resolve(); + if (spacer.length !== 0) { + return stringifyIndent("", value, [], spacer, ""); } } + return stringifySimple("", value, []); } - ; - IORedisConnection.prototype.datastore = "ioredis"; - IORedisConnection.prototype.defaults = { - Redis: null, - clientOptions: {}, - clusterNodes: null, - client: null, - Promise, - Events: null - }; - return IORedisConnection; - }.call(void 0); - module.exports = IORedisConnection; + return stringify3; + } } }); -var require_RedisDatastore = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/RedisDatastore.js"(exports2, module14) { +var require_multistream = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/multistream.js"(exports2, module14) { "use strict"; - function _slicedToArray2(arr, i2) { - return _arrayWithHoles2(arr) || _iterableToArrayLimit2(arr, i2) || _nonIterableRest2(); - } - function _nonIterableRest2() { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - function _iterableToArrayLimit2(arr, i2) { - var _arr = []; - var _n = true; - var _d = false; - var _e = void 0; - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - if (i2 && _arr.length === i2) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - return _arr; - } - function _arrayWithHoles2(arr) { - if (Array.isArray(arr)) return arr; - } - function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); - return; + var metadata = Symbol.for("pino.metadata"); + var { DEFAULT_LEVELS } = require_constants(); + var DEFAULT_INFO_LEVEL = DEFAULT_LEVELS.info; + function multistream(streamsArray, opts) { + let counter = 0; + streamsArray = streamsArray || []; + opts = opts || { dedupe: false }; + const streamLevels = Object.create(DEFAULT_LEVELS); + streamLevels.silent = Infinity; + if (opts.levels && typeof opts.levels === "object") { + Object.keys(opts.levels).forEach((i2) => { + streamLevels[i2] = opts.levels[i2]; + }); } - if (info.done) { - resolve82(value); + const res = { + write, + add, + flushSync, + end, + minLevel: 0, + streams: [], + clone: clone2, + [metadata]: true, + streamLevels + }; + if (Array.isArray(streamsArray)) { + streamsArray.forEach(add, res); } else { - Promise.resolve(value).then(_next, _throw); + add.call(res, streamsArray); } - } - function _asyncToGenerator2(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); - } - function _throw(err) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + streamsArray = null; + return res; + function write(data) { + let dest; + const level = this.lastLevel; + const { streams } = this; + let recordedLevel = 0; + let stream; + for (let i2 = initLoopVar(streams.length, opts.dedupe); checkLoopVar(i2, streams.length, opts.dedupe); i2 = adjustLoopVar(i2, opts.dedupe)) { + dest = streams[i2]; + if (dest.level <= level) { + if (recordedLevel !== 0 && recordedLevel !== dest.level) { + break; + } + stream = dest.stream; + if (stream[metadata]) { + const { lastTime, lastMsg, lastObj, lastLogger } = this; + stream.lastLevel = level; + stream.lastTime = lastTime; + stream.lastMsg = lastMsg; + stream.lastObj = lastObj; + stream.lastLogger = lastLogger; + } + stream.write(data); + if (opts.dedupe) { + recordedLevel = dest.level; + } + } else if (!opts.dedupe) { + break; } - _next(void 0); - }); - }; - } - var BottleneckError; - var IORedisConnection2; - var RedisConnection2; - var RedisDatastore; - var parser3; - parser3 = require_parser2(); - BottleneckError = require_BottleneckError(); - RedisConnection2 = require_RedisConnection(); - IORedisConnection2 = require_IORedisConnection(); - RedisDatastore = class RedisDatastore { - constructor(instance, storeOptions, storeInstanceOptions) { - this.instance = instance; - this.storeOptions = storeOptions; - this.originalId = this.instance.id; - this.clientId = this.instance._randomIndex(); - parser3.load(storeInstanceOptions, storeInstanceOptions, this); - this.clients = {}; - this.capacityPriorityCounters = {}; - this.sharedConnection = this.connection != null; - if (this.connection == null) { - this.connection = this.instance.datastore === "redis" ? new RedisConnection2({ - Redis: this.Redis, - clientOptions: this.clientOptions, - Promise: this.Promise, - Events: this.instance.Events - }) : this.instance.datastore === "ioredis" ? new IORedisConnection2({ - Redis: this.Redis, - clientOptions: this.clientOptions, - clusterNodes: this.clusterNodes, - Promise: this.Promise, - Events: this.instance.Events - }) : void 0; } - this.instance.connection = this.connection; - this.instance.datastore = this.connection.datastore; - this.ready = this.connection.ready.then((clients) => { - this.clients = clients; - return this.runScript("init", this.prepareInitSettings(this.clearDatastore)); - }).then(() => { - return this.connection.__addLimiter__(this.instance); - }).then(() => { - return this.runScript("register_client", [this.instance.queued()]); - }).then(() => { - var base2; - if (typeof (base2 = this.heartbeat = setInterval(() => { - return this.runScript("heartbeat", []).catch((e2) => { - return this.instance.Events.trigger("error", e2); - }); - }, this.heartbeatInterval)).unref === "function") { - base2.unref(); - } - return this.clients; - }); - } - __publish__(message) { - var _this = this; - return _asyncToGenerator2(function* () { - var client; - var _ref = yield _this.ready; - client = _ref.client; - return client.publish(_this.instance.channel(), `message:${message.toString()}`); - })(); } - onMessage(channel, message) { - var _this2 = this; - return _asyncToGenerator2(function* () { - var capacity, counter, data, drained, e2, newCapacity, pos, priorityClient, rawCapacity, type; - try { - pos = message.indexOf(":"); - var _ref2 = [message.slice(0, pos), message.slice(pos + 1)]; - type = _ref2[0]; - data = _ref2[1]; - if (type === "capacity") { - return yield _this2.instance._drainAll(data.length > 0 ? ~~data : void 0); - } else if (type === "capacity-priority") { - var _data$split = data.split(":"); - var _data$split2 = _slicedToArray2(_data$split, 3); - rawCapacity = _data$split2[0]; - priorityClient = _data$split2[1]; - counter = _data$split2[2]; - capacity = rawCapacity.length > 0 ? ~~rawCapacity : void 0; - if (priorityClient === _this2.clientId) { - drained = yield _this2.instance._drainAll(capacity); - newCapacity = capacity != null ? capacity - (drained || 0) : ""; - return yield _this2.clients.client.publish(_this2.instance.channel(), `capacity-priority:${newCapacity}::${counter}`); - } else if (priorityClient === "") { - clearTimeout(_this2.capacityPriorityCounters[counter]); - delete _this2.capacityPriorityCounters[counter]; - return _this2.instance._drainAll(capacity); - } else { - return _this2.capacityPriorityCounters[counter] = setTimeout( - /* @__PURE__ */ _asyncToGenerator2(function* () { - var e3; - try { - delete _this2.capacityPriorityCounters[counter]; - yield _this2.runScript("blacklist_client", [priorityClient]); - return yield _this2.instance._drainAll(capacity); - } catch (error2) { - e3 = error2; - return _this2.instance.Events.trigger("error", e3); - } - }), - 1e3 - ); - } - } else if (type === "message") { - return _this2.instance.Events.trigger("message", data); - } else if (type === "blocked") { - return yield _this2.instance._dropAllQueued(); - } - } catch (error2) { - e2 = error2; - return _this2.instance.Events.trigger("error", e2); + function flushSync() { + for (const { stream } of this.streams) { + if (typeof stream.flushSync === "function") { + stream.flushSync(); } - })(); + } } - __disconnect__(flush) { - clearInterval(this.heartbeat); - if (this.sharedConnection) { - return this.connection.__removeLimiter__(this.instance); + function add(dest) { + if (!dest) { + return res; + } + const isStream = typeof dest.write === "function" || dest.stream; + const stream_ = dest.write ? dest : dest.stream; + if (!isStream) { + throw Error("stream object needs to implement either StreamEntry or DestinationStream interface"); + } + const { streams, streamLevels: streamLevels2 } = this; + let level; + if (typeof dest.levelVal === "number") { + level = dest.levelVal; + } else if (typeof dest.level === "string") { + level = streamLevels2[dest.level]; + } else if (typeof dest.level === "number") { + level = dest.level; } else { - return this.connection.disconnect(flush); + level = DEFAULT_INFO_LEVEL; } + const dest_ = { + stream: stream_, + level, + levelVal: void 0, + id: counter++ + }; + streams.unshift(dest_); + streams.sort(compareByLevel); + this.minLevel = streams[0].level; + return res; } - runScript(name, args) { - var _this3 = this; - return _asyncToGenerator2(function* () { - if (!(name === "init" || name === "register_client")) { - yield _this3.ready; + function end() { + for (const { stream } of this.streams) { + if (typeof stream.flushSync === "function") { + stream.flushSync(); } - return new _this3.Promise((resolve82, reject) => { - var all_args, arr; - all_args = [Date.now(), _this3.clientId].concat(args); - _this3.instance.Events.trigger("debug", `Calling Redis script: ${name}.lua`, all_args); - arr = _this3.connection.__scriptArgs__(name, _this3.originalId, all_args, function(err, replies) { - if (err != null) { - return reject(err); - } - return resolve82(replies); - }); - return _this3.connection.__scriptFn__(name)(...arr); - }).catch((e2) => { - if (e2.message === "SETTINGS_KEY_NOT_FOUND") { - if (name === "heartbeat") { - return _this3.Promise.resolve(); - } else { - return _this3.runScript("init", _this3.prepareInitSettings(false)).then(() => { - return _this3.runScript(name, args); - }); - } - } else if (e2.message === "UNKNOWN_CLIENT") { - return _this3.runScript("register_client", [_this3.instance.queued()]).then(() => { - return _this3.runScript(name, args); - }); - } else { - return _this3.Promise.reject(e2); - } - }); - })(); + stream.end(); + } } - prepareArray(arr) { - var i2, len, results, x3; - results = []; - for (i2 = 0, len = arr.length; i2 < len; i2++) { - x3 = arr[i2]; - results.push(x3 != null ? x3.toString() : ""); + function clone2(level) { + const streams = new Array(this.streams.length); + for (let i2 = 0; i2 < streams.length; i2++) { + streams[i2] = { + level, + stream: this.streams[i2].stream + }; } - return results; + return { + write, + add, + minLevel: level, + streams, + clone: clone2, + flushSync, + [metadata]: true + }; } - prepareObject(obj) { - var arr, k, v2; - arr = []; - for (k in obj) { - v2 = obj[k]; - arr.push(k, v2 != null ? v2.toString() : ""); + } + function compareByLevel(a, b) { + return a.level - b.level; + } + function initLoopVar(length2, dedupe) { + return dedupe ? length2 - 1 : 0; + } + function adjustLoopVar(i2, dedupe) { + return dedupe ? i2 - 1 : i2 + 1; + } + function checkLoopVar(i2, length2, dedupe) { + return dedupe ? i2 >= 0 : i2 < length2; + } + module14.exports = multistream; + } +}); +var require_pino = __commonJS({ + "node_modules/.deno/pino@8.19.0/node_modules/pino/pino.js"(exports2, module14) { + "use strict"; + var os = __require2("node:os"); + var stdSerializers = require_pino_std_serializers(); + var caller = require_caller(); + var redaction = require_redaction(); + var time3 = require_time(); + var proto3 = require_proto(); + var symbols2 = require_symbols(); + var { configure } = require_safe_stable_stringify(); + var { assertDefaultLevelFound, mappings, genLsCache, genLevelComparison, assertLevelComparison } = require_levels(); + var { DEFAULT_LEVELS, SORTING_ORDER } = require_constants(); + var { + createArgsNormalizer, + asChindings, + buildSafeSonicBoom, + buildFormatters, + stringify: stringify2, + normalizeDestFileDescriptor, + noop + } = require_tools(); + var { version: version3 } = require_meta(); + var { + chindingsSym, + redactFmtSym, + serializersSym, + timeSym, + timeSliceIndexSym, + streamSym, + stringifySym, + stringifySafeSym, + stringifiersSym, + setLevelSym, + endSym, + formatOptsSym, + messageKeySym, + errorKeySym, + nestedKeySym, + mixinSym, + levelCompSym, + useOnlyCustomLevelsSym, + formattersSym, + hooksSym, + nestedKeyStrSym, + mixinMergeStrategySym, + msgPrefixSym + } = symbols2; + var { epochTime, nullTime } = time3; + var { pid } = process; + var hostname2 = os.hostname(); + var defaultErrorSerializer = stdSerializers.err; + var defaultOptions4 = { + level: "info", + levelComparison: SORTING_ORDER.ASC, + levels: DEFAULT_LEVELS, + messageKey: "msg", + errorKey: "err", + nestedKey: null, + enabled: true, + base: { pid, hostname: hostname2 }, + serializers: Object.assign(/* @__PURE__ */ Object.create(null), { + err: defaultErrorSerializer + }), + formatters: Object.assign(/* @__PURE__ */ Object.create(null), { + bindings(bindings) { + return bindings; + }, + level(label, number3) { + return { level: number3 }; + } + }), + hooks: { + logMethod: void 0 + }, + timestamp: epochTime, + name: void 0, + redact: null, + customLevels: null, + useOnlyCustomLevels: false, + depthLimit: 5, + edgeLimit: 100 + }; + var normalize32 = createArgsNormalizer(defaultOptions4); + var serializers = Object.assign(/* @__PURE__ */ Object.create(null), stdSerializers); + function pino2(...args) { + const instance = {}; + const { opts, stream } = normalize32(instance, caller(), ...args); + const { + redact, + crlf, + serializers: serializers2, + timestamp, + messageKey, + errorKey, + nestedKey, + base: base2, + name, + level, + customLevels, + levelComparison, + mixin: mixin3, + mixinMergeStrategy, + useOnlyCustomLevels, + formatters, + hooks, + depthLimit, + edgeLimit, + onChild, + msgPrefix + } = opts; + const stringifySafe = configure({ + maximumDepth: depthLimit, + maximumBreadth: edgeLimit + }); + const allFormatters = buildFormatters( + formatters.level, + formatters.bindings, + formatters.log + ); + const stringifyFn = stringify2.bind({ + [stringifySafeSym]: stringifySafe + }); + const stringifiers = redact ? redaction(redact, stringifyFn) : {}; + const formatOpts = redact ? { stringify: stringifiers[redactFmtSym] } : { stringify: stringifyFn }; + const end = "}" + (crlf ? "\r\n" : "\n"); + const coreChindings = asChindings.bind(null, { + [chindingsSym]: "", + [serializersSym]: serializers2, + [stringifiersSym]: stringifiers, + [stringifySym]: stringify2, + [stringifySafeSym]: stringifySafe, + [formattersSym]: allFormatters + }); + let chindings = ""; + if (base2 !== null) { + if (name === void 0) { + chindings = coreChindings(base2); + } else { + chindings = coreChindings(Object.assign({}, base2, { name })); } - return arr; - } - prepareInitSettings(clear) { - var args; - args = this.prepareObject(Object.assign({}, this.storeOptions, { - id: this.originalId, - version: this.instance.version, - groupTimeout: this.timeout, - clientTimeout: this.clientTimeout - })); - args.unshift(clear ? 1 : 0, this.instance.version); - return args; - } - convertBool(b) { - return !!b; - } - __updateSettings__(options2) { - var _this4 = this; - return _asyncToGenerator2(function* () { - yield _this4.runScript("update_settings", _this4.prepareObject(options2)); - return parser3.overwrite(options2, options2, _this4.storeOptions); - })(); - } - __running__() { - return this.runScript("running", []); - } - __queued__() { - return this.runScript("queued", []); - } - __done__() { - return this.runScript("done", []); - } - __groupCheck__() { - var _this5 = this; - return _asyncToGenerator2(function* () { - return _this5.convertBool(yield _this5.runScript("group_check", [])); - })(); - } - __incrementReservoir__(incr) { - return this.runScript("increment_reservoir", [incr]); - } - __currentReservoir__() { - return this.runScript("current_reservoir", []); - } - __check__(weight) { - var _this6 = this; - return _asyncToGenerator2(function* () { - return _this6.convertBool(yield _this6.runScript("check", _this6.prepareArray([weight]))); - })(); - } - __register__(index, weight, expiration) { - var _this7 = this; - return _asyncToGenerator2(function* () { - var reservoir, success, wait; - var _ref4 = yield _this7.runScript("register", _this7.prepareArray([index, weight, expiration])); - var _ref5 = _slicedToArray2(_ref4, 3); - success = _ref5[0]; - wait = _ref5[1]; - reservoir = _ref5[2]; - return { - success: _this7.convertBool(success), - wait, - reservoir - }; - })(); - } - __submit__(queueLength, weight) { - var _this8 = this; - return _asyncToGenerator2(function* () { - var blocked, e2, maxConcurrent, overweight, reachedHWM, strategy; - try { - var _ref6 = yield _this8.runScript("submit", _this8.prepareArray([queueLength, weight])); - var _ref7 = _slicedToArray2(_ref6, 3); - reachedHWM = _ref7[0]; - blocked = _ref7[1]; - strategy = _ref7[2]; - return { - reachedHWM: _this8.convertBool(reachedHWM), - blocked: _this8.convertBool(blocked), - strategy - }; - } catch (error2) { - e2 = error2; - if (e2.message.indexOf("OVERWEIGHT") === 0) { - var _e$message$split = e2.message.split(":"); - var _e$message$split2 = _slicedToArray2(_e$message$split, 3); - overweight = _e$message$split2[0]; - weight = _e$message$split2[1]; - maxConcurrent = _e$message$split2[2]; - throw new BottleneckError(`Impossible to add a job having a weight of ${weight} to a limiter having a maxConcurrent setting of ${maxConcurrent}`); - } else { - throw e2; - } - } - })(); } - __free__(index, weight) { - var _this9 = this; - return _asyncToGenerator2(function* () { - var running; - running = yield _this9.runScript("free", _this9.prepareArray([index])); - return { - running - }; - })(); + const time4 = timestamp instanceof Function ? timestamp : timestamp ? epochTime : nullTime; + const timeSliceIndex = time4().indexOf(":") + 1; + if (useOnlyCustomLevels && !customLevels) throw Error("customLevels is required if useOnlyCustomLevels is set true"); + if (mixin3 && typeof mixin3 !== "function") throw Error(`Unknown mixin type "${typeof mixin3}" - expected "function"`); + if (msgPrefix && typeof msgPrefix !== "string") throw Error(`Unknown msgPrefix type "${typeof msgPrefix}" - expected "string"`); + assertDefaultLevelFound(level, customLevels, useOnlyCustomLevels); + const levels = mappings(customLevels, useOnlyCustomLevels); + assertLevelComparison(levelComparison); + const levelCompFunc = genLevelComparison(levelComparison); + Object.assign(instance, { + levels, + [levelCompSym]: levelCompFunc, + [useOnlyCustomLevelsSym]: useOnlyCustomLevels, + [streamSym]: stream, + [timeSym]: time4, + [timeSliceIndexSym]: timeSliceIndex, + [stringifySym]: stringify2, + [stringifySafeSym]: stringifySafe, + [stringifiersSym]: stringifiers, + [endSym]: end, + [formatOptsSym]: formatOpts, + [messageKeySym]: messageKey, + [errorKeySym]: errorKey, + [nestedKeySym]: nestedKey, + // protect against injection + [nestedKeyStrSym]: nestedKey ? `,${JSON.stringify(nestedKey)}:{` : "", + [serializersSym]: serializers2, + [mixinSym]: mixin3, + [mixinMergeStrategySym]: mixinMergeStrategy, + [chindingsSym]: chindings, + [formattersSym]: allFormatters, + [hooksSym]: hooks, + silent: noop, + onChild, + [msgPrefixSym]: msgPrefix + }); + Object.setPrototypeOf(instance, proto3()); + genLsCache(instance); + instance[setLevelSym](level); + return instance; + } + module14.exports = pino2; + module14.exports.destination = (dest = process.stdout.fd) => { + if (typeof dest === "object") { + dest.dest = normalizeDestFileDescriptor(dest.dest || process.stdout.fd); + return buildSafeSonicBoom(dest); + } else { + return buildSafeSonicBoom({ dest: normalizeDestFileDescriptor(dest), minLength: 0 }); } }; - module14.exports = RedisDatastore; + module14.exports.transport = require_transport(); + module14.exports.multistream = require_multistream(); + module14.exports.levels = mappings(); + module14.exports.stdSerializers = serializers; + module14.exports.stdTimeFunctions = Object.assign({}, time3); + module14.exports.symbols = symbols2; + module14.exports.version = version3; + module14.exports.default = pino2; + module14.exports.pino = pino2; } }); -var require_States = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/States.js"(exports2, module14) { +var require_stream = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/stream.js"(exports2, module14) { "use strict"; - var BottleneckError; - var States; - BottleneckError = require_BottleneckError(); - States = class States { - constructor(status1) { - this.status = status1; - this._jobs = {}; - this.counts = this.status.map(function() { - return 0; - }); - } - next(id) { - var current, next; - current = this._jobs[id]; - next = current + 1; - if (current != null && next < this.status.length) { - this.counts[current]--; - this.counts[next]++; - return this._jobs[id]++; - } else if (current != null) { - this.counts[current]--; - return delete this._jobs[id]; - } + var { Duplex } = __require2("node:stream"); + function emitClose(stream) { + stream.emit("close"); + } + function duplexOnEnd() { + if (!this.destroyed && this._writableState.finished) { + this.destroy(); } - start(id) { - var initial; - initial = 0; - this._jobs[id] = initial; - return this.counts[initial]++; + } + function duplexOnError(err) { + this.removeListener("error", duplexOnError); + this.destroy(); + if (this.listenerCount("error") === 0) { + this.emit("error", err); } - remove(id) { - var current; - current = this._jobs[id]; - if (current != null) { - this.counts[current]--; - delete this._jobs[id]; + } + function createWebSocketStream2(ws, options2) { + let terminateOnDestroy = true; + const duplex = new Duplex({ + ...options2, + autoDestroy: false, + emitClose: false, + objectMode: false, + writableObjectMode: false + }); + ws.on("message", function message(msg, isBinary) { + const data = !isBinary && duplex._readableState.objectMode ? msg.toString() : msg; + if (!duplex.push(data)) ws.pause(); + }); + ws.once("error", function error2(err) { + if (duplex.destroyed) return; + terminateOnDestroy = false; + duplex.destroy(err); + }); + ws.once("close", function close() { + if (duplex.destroyed) return; + duplex.push(null); + }); + duplex._destroy = function(err, callback) { + if (ws.readyState === ws.CLOSED) { + callback(err); + process.nextTick(emitClose, duplex); + return; } - return current != null; - } - jobStatus(id) { - var ref; - return (ref = this.status[this._jobs[id]]) != null ? ref : null; - } - statusJobs(status) { - var k, pos, ref, results, v2; - if (status != null) { - pos = this.status.indexOf(status); - if (pos < 0) { - throw new BottleneckError(`status must be one of ${this.status.join(", ")}`); - } - ref = this._jobs; - results = []; - for (k in ref) { - v2 = ref[k]; - if (v2 === pos) { - results.push(k); - } - } - return results; + let called = false; + ws.once("error", function error2(err2) { + called = true; + callback(err2); + }); + ws.once("close", function close() { + if (!called) callback(err); + process.nextTick(emitClose, duplex); + }); + if (terminateOnDestroy) ws.terminate(); + }; + duplex._final = function(callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once("open", function open2() { + duplex._final(callback); + }); + return; + } + if (ws._socket === null) return; + if (ws._socket._writableState.finished) { + callback(); + if (duplex._readableState.endEmitted) duplex.destroy(); } else { - return Object.keys(this._jobs); + ws._socket.once("finish", function finish() { + callback(); + }); + ws.close(); } - } - statusCounts() { - return this.counts.reduce((acc, v2, i2) => { - acc[this.status[i2]] = v2; - return acc; - }, {}); + }; + duplex._read = function() { + if (ws.isPaused) ws.resume(); + }; + duplex._write = function(chunk, encoding, callback) { + if (ws.readyState === ws.CONNECTING) { + ws.once("open", function open2() { + duplex._write(chunk, encoding, callback); + }); + return; + } + ws.send(chunk, callback); + }; + duplex.on("end", duplexOnEnd); + duplex.on("error", duplexOnError); + return duplex; + } + module14.exports = createWebSocketStream2; + } +}); +var require_constants2 = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/constants.js"(exports2, module14) { + "use strict"; + module14.exports = { + BINARY_TYPES: ["nodebuffer", "arraybuffer", "fragments"], + EMPTY_BUFFER: Buffer.alloc(0), + GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", + kForOnEventAttribute: Symbol("kIsForOnEventAttribute"), + kListener: Symbol("kListener"), + kStatusCode: Symbol("status-code"), + kWebSocket: Symbol("websocket"), + NOOP: () => { } }; - module14.exports = States; } }); -var require_Sync = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Sync.js"(exports2, module14) { +var require_buffer_util = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/buffer-util.js"(exports2, module14) { "use strict"; - function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); - return; + var { EMPTY_BUFFER } = require_constants2(); + function concat2(list, totalLength) { + if (list.length === 0) return EMPTY_BUFFER; + if (list.length === 1) return list[0]; + const target = Buffer.allocUnsafe(totalLength); + let offset = 0; + for (let i2 = 0; i2 < list.length; i2++) { + const buf2 = list[i2]; + target.set(buf2, offset); + offset += buf2.length; } - if (info.done) { - resolve82(value); + if (offset < totalLength) return target.slice(0, offset); + return target; + } + function _mask(source, mask, output, offset, length2) { + for (let i2 = 0; i2 < length2; i2++) { + output[offset + i2] = source[i2] ^ mask[i2 & 3]; + } + } + function _unmask(buffer, mask) { + for (let i2 = 0; i2 < buffer.length; i2++) { + buffer[i2] ^= mask[i2 & 3]; + } + } + function toArrayBuffer(buf2) { + if (buf2.byteLength === buf2.buffer.byteLength) { + return buf2.buffer; + } + return buf2.buffer.slice(buf2.byteOffset, buf2.byteOffset + buf2.byteLength); + } + function toBuffer(data) { + toBuffer.readOnly = true; + if (Buffer.isBuffer(data)) return data; + let buf2; + if (data instanceof ArrayBuffer) { + buf2 = Buffer.from(data); + } else if (ArrayBuffer.isView(data)) { + buf2 = Buffer.from(data.buffer, data.byteOffset, data.byteLength); } else { - Promise.resolve(value).then(_next, _throw); + buf2 = Buffer.from(data); + toBuffer.readOnly = false; } + return buf2; } - function _asyncToGenerator2(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); - } - function _throw(err) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); - } - _next(void 0); - }); + try { + const bufferUtil = __require2("bufferutil"); + module14.exports = { + concat: concat2, + mask(source, mask, output, offset, length2) { + if (length2 < 48) _mask(source, mask, output, offset, length2); + else bufferUtil.mask(source, mask, output, offset, length2); + }, + toArrayBuffer, + toBuffer, + unmask(buffer, mask) { + if (buffer.length < 32) _unmask(buffer, mask); + else bufferUtil.unmask(buffer, mask); + } + }; + } catch (e2) { + module14.exports = { + concat: concat2, + mask: _mask, + toArrayBuffer, + toBuffer, + unmask: _unmask }; } - var DLList; - var Sync; - DLList = require_DLList(); - Sync = class Sync { - constructor(name, Promise2) { - this.schedule = this.schedule.bind(this); - this.name = name; - this.Promise = Promise2; - this._running = 0; - this._queue = new DLList(); - } - isEmpty() { - return this._queue.length === 0; + } +}); +var require_limiter = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/limiter.js"(exports2, module14) { + "use strict"; + var kDone = Symbol("kDone"); + var kRun = Symbol("kRun"); + var Limiter = class { + /** + * Creates a new `Limiter`. + * + * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed + * to run concurrently + */ + constructor(concurrency) { + this[kDone] = () => { + this.pending--; + this[kRun](); + }; + this.concurrency = concurrency || Infinity; + this.jobs = []; + this.pending = 0; } - _tryToRun() { - var _this = this; - return _asyncToGenerator2(function* () { - var args, cb, error2, reject, resolve82, returned, task; - if (_this._running < 1 && _this._queue.length > 0) { - _this._running++; - var _this$_queue$shift = _this._queue.shift(); - task = _this$_queue$shift.task; - args = _this$_queue$shift.args; - resolve82 = _this$_queue$shift.resolve; - reject = _this$_queue$shift.reject; - cb = yield _asyncToGenerator2(function* () { - try { - returned = yield task(...args); - return function() { - return resolve82(returned); - }; - } catch (error1) { - error2 = error1; - return function() { - return reject(error2); - }; - } - })(); - _this._running--; - _this._tryToRun(); - return cb(); - } - })(); + /** + * Adds a job to the queue. + * + * @param {Function} job The job to run + * @public + */ + add(job) { + this.jobs.push(job); + this[kRun](); } - schedule(task, ...args) { - var promise, reject, resolve82; - resolve82 = reject = null; - promise = new this.Promise(function(_resolve, _reject) { - resolve82 = _resolve; - return reject = _reject; - }); - this._queue.push({ - task, - args, - resolve: resolve82, - reject - }); - this._tryToRun(); - return promise; + /** + * Removes a job from the queue and runs it if possible. + * + * @private + */ + [kRun]() { + if (this.pending === this.concurrency) return; + if (this.jobs.length) { + const job = this.jobs.shift(); + this.pending++; + job(this[kDone]); + } } }; - module14.exports = Sync; - } -}); -var require_version = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/version.json"(exports2, module14) { - module14.exports = { version: "2.19.5" }; + module14.exports = Limiter; } }); -var require_Group = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Group.js"(exports2, module14) { +var require_permessage_deflate = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/permessage-deflate.js"(exports2, module14) { "use strict"; - function _slicedToArray2(arr, i2) { - return _arrayWithHoles2(arr) || _iterableToArrayLimit2(arr, i2) || _nonIterableRest2(); - } - function _nonIterableRest2() { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - function _iterableToArrayLimit2(arr, i2) { - var _arr = []; - var _n = true; - var _d = false; - var _e = void 0; - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - if (i2 && _arr.length === i2) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; + var zlib = __require2("node:zlib"); + var bufferUtil = require_buffer_util(); + var Limiter = require_limiter(); + var { kStatusCode } = require_constants2(); + var TRAILER = Buffer.from([0, 0, 255, 255]); + var kPerMessageDeflate = Symbol("permessage-deflate"); + var kTotalLength = Symbol("total-length"); + var kCallback = Symbol("callback"); + var kBuffers = Symbol("buffers"); + var kError = Symbol("error"); + var zlibLimiter; + var PerMessageDeflate = class { + /** + * Creates a PerMessageDeflate instance. + * + * @param {Object} [options] Configuration options + * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support + * for, or request, a custom client window size + * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/ + * acknowledge disabling of client context takeover + * @param {Number} [options.concurrencyLimit=10] The number of concurrent + * calls to zlib + * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the + * use of a custom server window size + * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept + * disabling of server context takeover + * @param {Number} [options.threshold=1024] Size (in bytes) below which + * messages should not be compressed if context takeover is disabled + * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on + * deflate + * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on + * inflate + * @param {Boolean} [isServer=false] Create the instance in either server or + * client mode + * @param {Number} [maxPayload=0] The maximum allowed message length + */ + constructor(options2, isServer, maxPayload) { + this._maxPayload = maxPayload | 0; + this._options = options2 || {}; + this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024; + this._isServer = !!isServer; + this._deflate = null; + this._inflate = null; + this.params = null; + if (!zlibLimiter) { + const concurrency = this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10; + zlibLimiter = new Limiter(concurrency); } } - return _arr; - } - function _arrayWithHoles2(arr) { - if (Array.isArray(arr)) return arr; - } - function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); - return; + /** + * @type {String} + */ + static get extensionName() { + return "permessage-deflate"; } - if (info.done) { - resolve82(value); - } else { - Promise.resolve(value).then(_next, _throw); + /** + * Create an extension negotiation offer. + * + * @return {Object} Extension parameters + * @public + */ + offer() { + const params = {}; + if (this._options.serverNoContextTakeover) { + params.server_no_context_takeover = true; + } + if (this._options.clientNoContextTakeover) { + params.client_no_context_takeover = true; + } + if (this._options.serverMaxWindowBits) { + params.server_max_window_bits = this._options.serverMaxWindowBits; + } + if (this._options.clientMaxWindowBits) { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } else if (this._options.clientMaxWindowBits == null) { + params.client_max_window_bits = true; + } + return params; } - } - function _asyncToGenerator2(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); + /** + * Accept an extension negotiation offer/response. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Object} Accepted configuration + * @public + */ + accept(configurations) { + configurations = this.normalizeParams(configurations); + this.params = this._isServer ? this.acceptAsServer(configurations) : this.acceptAsClient(configurations); + return this.params; + } + /** + * Releases all resources used by the extension. + * + * @public + */ + cleanup() { + if (this._inflate) { + this._inflate.close(); + this._inflate = null; + } + if (this._deflate) { + const callback = this._deflate[kCallback]; + this._deflate.close(); + this._deflate = null; + if (callback) { + callback( + new Error( + "The deflate stream was closed while data was being processed" + ) + ); } - function _throw(err) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); + } + } + /** + * Accept an extension negotiation offer. + * + * @param {Array} offers The extension negotiation offers + * @return {Object} Accepted configuration + * @private + */ + acceptAsServer(offers) { + const opts = this._options; + const accepted = offers.find((params) => { + if (opts.serverNoContextTakeover === false && params.server_no_context_takeover || params.server_max_window_bits && (opts.serverMaxWindowBits === false || typeof opts.serverMaxWindowBits === "number" && opts.serverMaxWindowBits > params.server_max_window_bits) || typeof opts.clientMaxWindowBits === "number" && !params.client_max_window_bits) { + return false; } - _next(void 0); + return true; }); - }; - } - var Events2; - var Group; - var IORedisConnection2; - var RedisConnection2; - var Scripts2; - var parser3; - parser3 = require_parser2(); - Events2 = require_Events(); - RedisConnection2 = require_RedisConnection(); - IORedisConnection2 = require_IORedisConnection(); - Scripts2 = require_Scripts(); - Group = function() { - class Group2 { - constructor(limiterOptions = {}) { - this.deleteKey = this.deleteKey.bind(this); - this.limiterOptions = limiterOptions; - parser3.load(this.limiterOptions, this.defaults, this); - this.Events = new Events2(this); - this.instances = {}; - this.Bottleneck = require_Bottleneck(); - this._startAutoCleanup(); - this.sharedConnection = this.connection != null; - if (this.connection == null) { - if (this.limiterOptions.datastore === "redis") { - this.connection = new RedisConnection2(Object.assign({}, this.limiterOptions, { - Events: this.Events - })); - } else if (this.limiterOptions.datastore === "ioredis") { - this.connection = new IORedisConnection2(Object.assign({}, this.limiterOptions, { - Events: this.Events - })); - } - } + if (!accepted) { + throw new Error("None of the extension offers can be accepted"); } - key(key = "") { - var ref; - return (ref = this.instances[key]) != null ? ref : (() => { - var limiter; - limiter = this.instances[key] = new this.Bottleneck(Object.assign(this.limiterOptions, { - id: `${this.id}-${key}`, - timeout: this.timeout, - connection: this.connection - })); - this.Events.trigger("created", limiter, key); - return limiter; - })(); + if (opts.serverNoContextTakeover) { + accepted.server_no_context_takeover = true; } - deleteKey(key = "") { - var _this = this; - return _asyncToGenerator2(function* () { - var deleted, instance; - instance = _this.instances[key]; - if (_this.connection) { - deleted = yield _this.connection.__runCommand__(["del", ...Scripts2.allKeys(`${_this.id}-${key}`)]); - } - if (instance != null) { - delete _this.instances[key]; - yield instance.disconnect(); - } - return instance != null || deleted > 0; - })(); + if (opts.clientNoContextTakeover) { + accepted.client_no_context_takeover = true; } - limiters() { - var k, ref, results, v2; - ref = this.instances; - results = []; - for (k in ref) { - v2 = ref[k]; - results.push({ - key: k, - limiter: v2 - }); - } - return results; + if (typeof opts.serverMaxWindowBits === "number") { + accepted.server_max_window_bits = opts.serverMaxWindowBits; } - keys() { - return Object.keys(this.instances); + if (typeof opts.clientMaxWindowBits === "number") { + accepted.client_max_window_bits = opts.clientMaxWindowBits; + } else if (accepted.client_max_window_bits === true || opts.clientMaxWindowBits === false) { + delete accepted.client_max_window_bits; } - clusterKeys() { - var _this2 = this; - return _asyncToGenerator2(function* () { - var cursor, end, found, i2, k, keys, len, next, start; - if (_this2.connection == null) { - return _this2.Promise.resolve(_this2.keys()); + return accepted; + } + /** + * Accept the extension negotiation response. + * + * @param {Array} response The extension negotiation response + * @return {Object} Accepted configuration + * @private + */ + acceptAsClient(response) { + const params = response[0]; + if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) { + throw new Error('Unexpected parameter "client_no_context_takeover"'); + } + if (!params.client_max_window_bits) { + if (typeof this._options.clientMaxWindowBits === "number") { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } + } else if (this._options.clientMaxWindowBits === false || typeof this._options.clientMaxWindowBits === "number" && params.client_max_window_bits > this._options.clientMaxWindowBits) { + throw new Error( + 'Unexpected or invalid parameter "client_max_window_bits"' + ); + } + return params; + } + /** + * Normalize parameters. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Array} The offers/response with normalized parameters + * @private + */ + normalizeParams(configurations) { + configurations.forEach((params) => { + Object.keys(params).forEach((key) => { + let value = params[key]; + if (value.length > 1) { + throw new Error(`Parameter "${key}" must have only a single value`); } - keys = []; - cursor = null; - start = `b_${_this2.id}-`.length; - end = "_settings".length; - while (cursor !== 0) { - var _ref = yield _this2.connection.__runCommand__(["scan", cursor != null ? cursor : 0, "match", `b_${_this2.id}-*_settings`, "count", 1e4]); - var _ref2 = _slicedToArray2(_ref, 2); - next = _ref2[0]; - found = _ref2[1]; - cursor = ~~next; - for (i2 = 0, len = found.length; i2 < len; i2++) { - k = found[i2]; - keys.push(k.slice(start, -end)); + value = value[0]; + if (key === "client_max_window_bits") { + if (value !== true) { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if (!this._isServer) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + } else if (key === "server_max_window_bits") { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") { + if (value !== true) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); } + } else { + throw new Error(`Unknown parameter "${key}"`); } - return keys; - })(); + params[key] = value; + }); + }); + return configurations; + } + /** + * Decompress data. Concurrency limited. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + decompress(data, fin, callback) { + zlibLimiter.add((done) => { + this._decompress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + /** + * Compress data. Concurrency limited. + * + * @param {(Buffer|String)} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + compress(data, fin, callback) { + zlibLimiter.add((done) => { + this._compress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + /** + * Decompress data. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _decompress(data, fin, callback) { + const endpoint = this._isServer ? "client" : "server"; + if (!this._inflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; + this._inflate = zlib.createInflateRaw({ + ...this._options.zlibInflateOptions, + windowBits + }); + this._inflate[kPerMessageDeflate] = this; + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + this._inflate.on("error", inflateOnError); + this._inflate.on("data", inflateOnData); } - _startAutoCleanup() { - var _this3 = this; - var base2; - clearInterval(this.interval); - return typeof (base2 = this.interval = setInterval( - /* @__PURE__ */ _asyncToGenerator2(function* () { - var e2, k, ref, results, time3, v2; - time3 = Date.now(); - ref = _this3.instances; - results = []; - for (k in ref) { - v2 = ref[k]; - try { - if (yield v2._store.__groupCheck__(time3)) { - results.push(_this3.deleteKey(k)); - } else { - results.push(void 0); - } - } catch (error2) { - e2 = error2; - results.push(v2.Events.trigger("error", e2)); - } - } - return results; - }), - this.timeout / 2 - )).unref === "function" ? base2.unref() : void 0; + this._inflate[kCallback] = callback; + this._inflate.write(data); + if (fin) this._inflate.write(TRAILER); + this._inflate.flush(() => { + const err = this._inflate[kError]; + if (err) { + this._inflate.close(); + this._inflate = null; + callback(err); + return; + } + const data2 = bufferUtil.concat( + this._inflate[kBuffers], + this._inflate[kTotalLength] + ); + if (this._inflate._readableState.endEmitted) { + this._inflate.close(); + this._inflate = null; + } else { + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._inflate.reset(); + } + } + callback(null, data2); + }); + } + /** + * Compress data. + * + * @param {(Buffer|String)} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _compress(data, fin, callback) { + const endpoint = this._isServer ? "server" : "client"; + if (!this._deflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = typeof this.params[key] !== "number" ? zlib.Z_DEFAULT_WINDOWBITS : this.params[key]; + this._deflate = zlib.createDeflateRaw({ + ...this._options.zlibDeflateOptions, + windowBits + }); + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + this._deflate.on("data", deflateOnData); } - updateSettings(options2 = {}) { - parser3.overwrite(options2, this.defaults, this); - parser3.overwrite(options2, options2, this.limiterOptions); - if (options2.timeout != null) { - return this._startAutoCleanup(); + this._deflate[kCallback] = callback; + this._deflate.write(data); + this._deflate.flush(zlib.Z_SYNC_FLUSH, () => { + if (!this._deflate) { + return; } - } - disconnect(flush = true) { - var ref; - if (!this.sharedConnection) { - return (ref = this.connection) != null ? ref.disconnect(flush) : void 0; + let data2 = bufferUtil.concat( + this._deflate[kBuffers], + this._deflate[kTotalLength] + ); + if (fin) data2 = data2.slice(0, data2.length - 4); + this._deflate[kCallback] = null; + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + if (fin && this.params[`${endpoint}_no_context_takeover`]) { + this._deflate.reset(); } - } + callback(null, data2); + }); } - ; - Group2.prototype.defaults = { - timeout: 1e3 * 60 * 5, - connection: null, - Promise, - id: "group-key" - }; - return Group2; - }.call(void 0); - module14.exports = Group; + }; + module14.exports = PerMessageDeflate; + function deflateOnData(chunk) { + this[kBuffers].push(chunk); + this[kTotalLength] += chunk.length; + } + function inflateOnData(chunk) { + this[kTotalLength] += chunk.length; + if (this[kPerMessageDeflate]._maxPayload < 1 || this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload) { + this[kBuffers].push(chunk); + return; + } + this[kError] = new RangeError("Max payload size exceeded"); + this[kError].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"; + this[kError][kStatusCode] = 1009; + this.removeListener("data", inflateOnData); + this.reset(); + } + function inflateOnError(err) { + this[kPerMessageDeflate]._inflate = null; + err[kStatusCode] = 1007; + this[kCallback](err); + } } }); -var require_Batcher = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Batcher.js"(exports2, module14) { +var require_validation = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/validation.js"(exports2, module14) { "use strict"; - var Batcher; - var Events2; - var parser3; - parser3 = require_parser2(); - Events2 = require_Events(); - Batcher = function() { - class Batcher2 { - constructor(options2 = {}) { - this.options = options2; - parser3.load(this.options, this.defaults, this); - this.Events = new Events2(this); - this._arr = []; - this._resetPromise(); - this._lastFlush = Date.now(); - } - _resetPromise() { - return this._promise = new this.Promise((res, rej) => { - return this._resolve = res; - }); - } - _flush() { - clearTimeout(this._timeout); - this._lastFlush = Date.now(); - this._resolve(); - this.Events.trigger("batch", this._arr); - this._arr = []; - return this._resetPromise(); - } - add(data) { - var ret; - this._arr.push(data); - ret = this._promise; - if (this._arr.length === this.maxSize) { - this._flush(); - } else if (this.maxTime != null && this._arr.length === 1) { - this._timeout = setTimeout(() => { - return this._flush(); - }, this.maxTime); + var tokenChars = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 0 - 15 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + // 16 - 31 + 0, + 1, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + // 32 - 47 + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + // 48 - 63 + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + // 64 - 79 + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + // 80 - 95 + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + // 96 - 111 + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 0, + 1, + 0 + // 112 - 127 + ]; + function isValidStatusCode(code2) { + return code2 >= 1e3 && code2 <= 1014 && code2 !== 1004 && code2 !== 1005 && code2 !== 1006 || code2 >= 3e3 && code2 <= 4999; + } + function _isValidUTF8(buf2) { + const len = buf2.length; + let i2 = 0; + while (i2 < len) { + if ((buf2[i2] & 128) === 0) { + i2++; + } else if ((buf2[i2] & 224) === 192) { + if (i2 + 1 === len || (buf2[i2 + 1] & 192) !== 128 || (buf2[i2] & 254) === 192) { + return false; } - return ret; + i2 += 2; + } else if ((buf2[i2] & 240) === 224) { + if (i2 + 2 >= len || (buf2[i2 + 1] & 192) !== 128 || (buf2[i2 + 2] & 192) !== 128 || buf2[i2] === 224 && (buf2[i2 + 1] & 224) === 128 || // Overlong + buf2[i2] === 237 && (buf2[i2 + 1] & 224) === 160) { + return false; + } + i2 += 3; + } else if ((buf2[i2] & 248) === 240) { + if (i2 + 3 >= len || (buf2[i2 + 1] & 192) !== 128 || (buf2[i2 + 2] & 192) !== 128 || (buf2[i2 + 3] & 192) !== 128 || buf2[i2] === 240 && (buf2[i2 + 1] & 240) === 128 || // Overlong + buf2[i2] === 244 && buf2[i2 + 1] > 143 || buf2[i2] > 244) { + return false; + } + i2 += 4; + } else { + return false; } } - ; - Batcher2.prototype.defaults = { - maxTime: null, - maxSize: null, - Promise + return true; + } + try { + const isValidUTF8 = __require2("utf-8-validate"); + module14.exports = { + isValidStatusCode, + isValidUTF8(buf2) { + return buf2.length < 150 ? _isValidUTF8(buf2) : isValidUTF8(buf2); + }, + tokenChars }; - return Batcher2; - }.call(void 0); - module14.exports = Batcher; + } catch (e2) { + module14.exports = { + isValidStatusCode, + isValidUTF8: _isValidUTF8, + tokenChars + }; + } } }); -var require_Bottleneck = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/Bottleneck.js"(exports2, module14) { +var require_receiver = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/receiver.js"(exports2, module14) { "use strict"; - function _slicedToArray2(arr, i2) { - return _arrayWithHoles2(arr) || _iterableToArrayLimit2(arr, i2) || _nonIterableRest2(); - } - function _iterableToArrayLimit2(arr, i2) { - var _arr = []; - var _n = true; - var _d = false; - var _e = void 0; - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - if (i2 && _arr.length === i2) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - return _arr; - } - function _toArray(arr) { - return _arrayWithHoles2(arr) || _iterableToArray(arr) || _nonIterableRest2(); - } - function _nonIterableRest2() { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - function _iterableToArray(iter) { - if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); - } - function _arrayWithHoles2(arr) { - if (Array.isArray(arr)) return arr; - } - function asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error2) { - reject(error2); - return; + var { Writable } = __require2("node:stream"); + var PerMessageDeflate = require_permessage_deflate(); + var { + BINARY_TYPES, + EMPTY_BUFFER, + kStatusCode, + kWebSocket + } = require_constants2(); + var { concat: concat2, toArrayBuffer, unmask } = require_buffer_util(); + var { isValidStatusCode, isValidUTF8 } = require_validation(); + var GET_INFO = 0; + var GET_PAYLOAD_LENGTH_16 = 1; + var GET_PAYLOAD_LENGTH_64 = 2; + var GET_MASK = 3; + var GET_DATA = 4; + var INFLATING = 5; + var Receiver2 = class extends Writable { + /** + * Creates a Receiver instance. + * + * @param {Object} [options] Options object + * @param {String} [options.binaryType=nodebuffer] The type for binary data + * @param {Object} [options.extensions] An object containing the negotiated + * extensions + * @param {Boolean} [options.isServer=false] Specifies whether to operate in + * client or server mode + * @param {Number} [options.maxPayload=0] The maximum allowed message length + * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or + * not to skip UTF-8 validation for text and close messages + */ + constructor(options2 = {}) { + super(); + this._binaryType = options2.binaryType || BINARY_TYPES[0]; + this._extensions = options2.extensions || {}; + this._isServer = !!options2.isServer; + this._maxPayload = options2.maxPayload | 0; + this._skipUTF8Validation = !!options2.skipUTF8Validation; + this[kWebSocket] = void 0; + this._bufferedBytes = 0; + this._buffers = []; + this._compressed = false; + this._payloadLength = 0; + this._mask = void 0; + this._fragmented = 0; + this._masked = false; + this._fin = false; + this._opcode = 0; + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragments = []; + this._state = GET_INFO; + this._loop = false; } - if (info.done) { - resolve82(value); - } else { - Promise.resolve(value).then(_next, _throw); + /** + * Implements `Writable.prototype._write()`. + * + * @param {Buffer} chunk The chunk of data to write + * @param {String} encoding The character encoding of `chunk` + * @param {Function} cb Callback + * @private + */ + _write(chunk, encoding, cb) { + if (this._opcode === 8 && this._state == GET_INFO) return cb(); + this._bufferedBytes += chunk.length; + this._buffers.push(chunk); + this.startLoop(cb); } - } - function _asyncToGenerator2(fn) { - return function() { - var self2 = this, args = arguments; - return new Promise(function(resolve82, reject) { - var gen = fn.apply(self2, args); - function _next(value) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "next", value); - } - function _throw(err) { - asyncGeneratorStep2(gen, resolve82, reject, _next, _throw, "throw", err); - } - _next(void 0); - }); - }; - } - var Bottleneck2; - var DEFAULT_PRIORITY; - var Events2; - var Job; - var LocalDatastore; - var NUM_PRIORITIES; - var Queues; - var RedisDatastore; - var States; - var Sync; - var parser3; - var splice = [].splice; - NUM_PRIORITIES = 10; - DEFAULT_PRIORITY = 5; - parser3 = require_parser2(); - Queues = require_Queues(); - Job = require_Job(); - LocalDatastore = require_LocalDatastore(); - RedisDatastore = require_RedisDatastore(); - Events2 = require_Events(); - States = require_States(); - Sync = require_Sync(); - Bottleneck2 = function() { - class Bottleneck3 { - constructor(options2 = {}, ...invalid) { - var storeInstanceOptions, storeOptions; - this._addToQueue = this._addToQueue.bind(this); - this._validateOptions(options2, invalid); - parser3.load(options2, this.instanceDefaults, this); - this._queues = new Queues(NUM_PRIORITIES); - this._scheduled = {}; - this._states = new States(["RECEIVED", "QUEUED", "RUNNING", "EXECUTING"].concat(this.trackDoneStatus ? ["DONE"] : [])); - this._limiter = null; - this.Events = new Events2(this); - this._submitLock = new Sync("submit", this.Promise); - this._registerLock = new Sync("register", this.Promise); - storeOptions = parser3.load(options2, this.storeDefaults, {}); - this._store = function() { - if (this.datastore === "redis" || this.datastore === "ioredis" || this.connection != null) { - storeInstanceOptions = parser3.load(options2, this.redisStoreDefaults, {}); - return new RedisDatastore(this, storeOptions, storeInstanceOptions); - } else if (this.datastore === "local") { - storeInstanceOptions = parser3.load(options2, this.localStoreDefaults, {}); - return new LocalDatastore(this, storeOptions, storeInstanceOptions); - } else { - throw new Bottleneck3.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`); - } - }.call(this); - this._queues.on("leftzero", () => { - var ref; - return (ref = this._store.heartbeat) != null ? typeof ref.ref === "function" ? ref.ref() : void 0 : void 0; - }); - this._queues.on("zero", () => { - var ref; - return (ref = this._store.heartbeat) != null ? typeof ref.unref === "function" ? ref.unref() : void 0 : void 0; - }); - } - _validateOptions(options2, invalid) { - if (!(options2 != null && typeof options2 === "object" && invalid.length === 0)) { - throw new Bottleneck3.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1."); - } - } - ready() { - return this._store.ready; - } - clients() { - return this._store.clients; - } - channel() { - return `b_${this.id}`; - } - channel_client() { - return `b_${this.id}_${this._store.clientId}`; - } - publish(message) { - return this._store.__publish__(message); - } - disconnect(flush = true) { - return this._store.__disconnect__(flush); - } - chain(_limiter) { - this._limiter = _limiter; - return this; - } - queued(priority) { - return this._queues.queued(priority); - } - clusterQueued() { - return this._store.__queued__(); + /** + * Consumes `n` bytes from the buffered data. + * + * @param {Number} n The number of bytes to consume + * @return {Buffer} The consumed bytes + * @private + */ + consume(n) { + this._bufferedBytes -= n; + if (n === this._buffers[0].length) return this._buffers.shift(); + if (n < this._buffers[0].length) { + const buf2 = this._buffers[0]; + this._buffers[0] = buf2.slice(n); + return buf2.slice(0, n); } - empty() { - return this.queued() === 0 && this._submitLock.isEmpty(); + const dst = Buffer.allocUnsafe(n); + do { + const buf2 = this._buffers[0]; + const offset = dst.length - n; + if (n >= buf2.length) { + dst.set(this._buffers.shift(), offset); + } else { + dst.set(new Uint8Array(buf2.buffer, buf2.byteOffset, n), offset); + this._buffers[0] = buf2.slice(n); + } + n -= buf2.length; + } while (n > 0); + return dst; + } + /** + * Starts the parsing loop. + * + * @param {Function} cb Callback + * @private + */ + startLoop(cb) { + let err; + this._loop = true; + do { + switch (this._state) { + case GET_INFO: + err = this.getInfo(); + break; + case GET_PAYLOAD_LENGTH_16: + err = this.getPayloadLength16(); + break; + case GET_PAYLOAD_LENGTH_64: + err = this.getPayloadLength64(); + break; + case GET_MASK: + this.getMask(); + break; + case GET_DATA: + err = this.getData(cb); + break; + default: + this._loop = false; + return; + } + } while (this._loop); + cb(err); + } + /** + * Reads the first two bytes of a frame. + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getInfo() { + if (this._bufferedBytes < 2) { + this._loop = false; + return; } - running() { - return this._store.__running__(); + const buf2 = this.consume(2); + if ((buf2[0] & 48) !== 0) { + this._loop = false; + return error2( + RangeError, + "RSV2 and RSV3 must be clear", + true, + 1002, + "WS_ERR_UNEXPECTED_RSV_2_3" + ); } - done() { - return this._store.__done__(); + const compressed = (buf2[0] & 64) === 64; + if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { + this._loop = false; + return error2( + RangeError, + "RSV1 must be clear", + true, + 1002, + "WS_ERR_UNEXPECTED_RSV_1" + ); } - jobStatus(id) { - return this._states.jobStatus(id); + this._fin = (buf2[0] & 128) === 128; + this._opcode = buf2[0] & 15; + this._payloadLength = buf2[1] & 127; + if (this._opcode === 0) { + if (compressed) { + this._loop = false; + return error2( + RangeError, + "RSV1 must be clear", + true, + 1002, + "WS_ERR_UNEXPECTED_RSV_1" + ); + } + if (!this._fragmented) { + this._loop = false; + return error2( + RangeError, + "invalid opcode 0", + true, + 1002, + "WS_ERR_INVALID_OPCODE" + ); + } + this._opcode = this._fragmented; + } else if (this._opcode === 1 || this._opcode === 2) { + if (this._fragmented) { + this._loop = false; + return error2( + RangeError, + `invalid opcode ${this._opcode}`, + true, + 1002, + "WS_ERR_INVALID_OPCODE" + ); + } + this._compressed = compressed; + } else if (this._opcode > 7 && this._opcode < 11) { + if (!this._fin) { + this._loop = false; + return error2( + RangeError, + "FIN must be set", + true, + 1002, + "WS_ERR_EXPECTED_FIN" + ); + } + if (compressed) { + this._loop = false; + return error2( + RangeError, + "RSV1 must be clear", + true, + 1002, + "WS_ERR_UNEXPECTED_RSV_1" + ); + } + if (this._payloadLength > 125) { + this._loop = false; + return error2( + RangeError, + `invalid payload length ${this._payloadLength}`, + true, + 1002, + "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH" + ); + } + } else { + this._loop = false; + return error2( + RangeError, + `invalid opcode ${this._opcode}`, + true, + 1002, + "WS_ERR_INVALID_OPCODE" + ); } - jobs(status) { - return this._states.statusJobs(status); + if (!this._fin && !this._fragmented) this._fragmented = this._opcode; + this._masked = (buf2[1] & 128) === 128; + if (this._isServer) { + if (!this._masked) { + this._loop = false; + return error2( + RangeError, + "MASK must be set", + true, + 1002, + "WS_ERR_EXPECTED_MASK" + ); + } + } else if (this._masked) { + this._loop = false; + return error2( + RangeError, + "MASK must be clear", + true, + 1002, + "WS_ERR_UNEXPECTED_MASK" + ); } - counts() { - return this._states.statusCounts(); + if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16; + else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64; + else return this.haveLength(); + } + /** + * Gets extended payload length (7+16). + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getPayloadLength16() { + if (this._bufferedBytes < 2) { + this._loop = false; + return; } - _randomIndex() { - return Math.random().toString(36).slice(2); + this._payloadLength = this.consume(2).readUInt16BE(0); + return this.haveLength(); + } + /** + * Gets extended payload length (7+64). + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getPayloadLength64() { + if (this._bufferedBytes < 8) { + this._loop = false; + return; } - check(weight = 1) { - return this._store.__check__(weight); + const buf2 = this.consume(8); + const num = buf2.readUInt32BE(0); + if (num > Math.pow(2, 53 - 32) - 1) { + this._loop = false; + return error2( + RangeError, + "Unsupported WebSocket frame: payload length > 2^53 - 1", + false, + 1009, + "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH" + ); } - _clearGlobalState(index) { - if (this._scheduled[index] != null) { - clearTimeout(this._scheduled[index].expiration); - delete this._scheduled[index]; - return true; - } else { - return false; + this._payloadLength = num * Math.pow(2, 32) + buf2.readUInt32BE(4); + return this.haveLength(); + } + /** + * Payload length has been read. + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + haveLength() { + if (this._payloadLength && this._opcode < 8) { + this._totalPayloadLength += this._payloadLength; + if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { + this._loop = false; + return error2( + RangeError, + "Max payload size exceeded", + false, + 1009, + "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH" + ); } } - _free(index, job, options2, eventInfo) { - var _this = this; - return _asyncToGenerator2(function* () { - var e2, running; - try { - var _ref = yield _this._store.__free__(index, options2.weight); - running = _ref.running; - _this.Events.trigger("debug", `Freed ${options2.id}`, eventInfo); - if (running === 0 && _this.empty()) { - return _this.Events.trigger("idle"); - } - } catch (error1) { - e2 = error1; - return _this.Events.trigger("error", e2); - } - })(); - } - _run(index, job, wait) { - var clearGlobalState, free, run2; - job.doRun(); - clearGlobalState = this._clearGlobalState.bind(this, index); - run2 = this._run.bind(this, index, job); - free = this._free.bind(this, index, job); - return this._scheduled[index] = { - timeout: setTimeout(() => { - return job.doExecute(this._limiter, clearGlobalState, run2, free); - }, wait), - expiration: job.options.expiration != null ? setTimeout(function() { - return job.doExpire(clearGlobalState, run2, free); - }, wait + job.options.expiration) : void 0, - job - }; - } - _drainOne(capacity) { - return this._registerLock.schedule(() => { - var args, index, next, options2, queue; - if (this.queued() === 0) { - return this.Promise.resolve(null); - } - queue = this._queues.getFirst(); - var _next2 = next = queue.first(); - options2 = _next2.options; - args = _next2.args; - if (capacity != null && options2.weight > capacity) { - return this.Promise.resolve(null); - } - this.Events.trigger("debug", `Draining ${options2.id}`, { - args, - options: options2 - }); - index = this._randomIndex(); - return this._store.__register__(index, options2.weight, options2.expiration).then(({ - success, - wait, - reservoir - }) => { - var empty2; - this.Events.trigger("debug", `Drained ${options2.id}`, { - success, - args, - options: options2 - }); - if (success) { - queue.shift(); - empty2 = this.empty(); - if (empty2) { - this.Events.trigger("empty"); - } - if (reservoir === 0) { - this.Events.trigger("depleted", empty2); - } - this._run(index, next, wait); - return this.Promise.resolve(options2.weight); - } else { - return this.Promise.resolve(null); - } - }); - }); + if (this._masked) this._state = GET_MASK; + else this._state = GET_DATA; + } + /** + * Reads mask bytes. + * + * @private + */ + getMask() { + if (this._bufferedBytes < 4) { + this._loop = false; + return; } - _drainAll(capacity, total = 0) { - return this._drainOne(capacity).then((drained) => { - var newCapacity; - if (drained != null) { - newCapacity = capacity != null ? capacity - drained : capacity; - return this._drainAll(newCapacity, total + drained); - } else { - return this.Promise.resolve(total); - } - }).catch((e2) => { - return this.Events.trigger("error", e2); - }); + this._mask = this.consume(4); + this._state = GET_DATA; + } + /** + * Reads data bytes. + * + * @param {Function} cb Callback + * @return {(Error|RangeError|undefined)} A possible error + * @private + */ + getData(cb) { + let data = EMPTY_BUFFER; + if (this._payloadLength) { + if (this._bufferedBytes < this._payloadLength) { + this._loop = false; + return; + } + data = this.consume(this._payloadLength); + if (this._masked && (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0) { + unmask(data, this._mask); + } } - _dropAllQueued(message) { - return this._queues.shiftAll(function(job) { - return job.doDrop({ - message - }); - }); + if (this._opcode > 7) return this.controlMessage(data); + if (this._compressed) { + this._state = INFLATING; + this.decompress(data, cb); + return; } - stop(options2 = {}) { - var done, waitForExecuting; - options2 = parser3.load(options2, this.stopDefaults); - waitForExecuting = (at) => { - var finished; - finished = () => { - var counts; - counts = this._states.counts; - return counts[0] + counts[1] + counts[2] + counts[3] === at; - }; - return new this.Promise((resolve82, reject) => { - if (finished()) { - return resolve82(); - } else { - return this.on("done", () => { - if (finished()) { - this.removeAllListeners("done"); - return resolve82(); - } - }); - } - }); - }; - done = options2.dropWaitingJobs ? (this._run = function(index, next) { - return next.doDrop({ - message: options2.dropErrorMessage - }); - }, this._drainOne = () => { - return this.Promise.resolve(null); - }, this._registerLock.schedule(() => { - return this._submitLock.schedule(() => { - var k, ref, v2; - ref = this._scheduled; - for (k in ref) { - v2 = ref[k]; - if (this.jobStatus(v2.job.options.id) === "RUNNING") { - clearTimeout(v2.timeout); - clearTimeout(v2.expiration); - v2.job.doDrop({ - message: options2.dropErrorMessage - }); - } - } - this._dropAllQueued(options2.dropErrorMessage); - return waitForExecuting(0); - }); - })) : this.schedule({ - priority: NUM_PRIORITIES - 1, - weight: 0 - }, () => { - return waitForExecuting(1); - }); - this._receive = function(job) { - return job._reject(new Bottleneck3.prototype.BottleneckError(options2.enqueueErrorMessage)); - }; - this.stop = () => { - return this.Promise.reject(new Bottleneck3.prototype.BottleneckError("stop() has already been called")); - }; - return done; + if (data.length) { + this._messageLength = this._totalPayloadLength; + this._fragments.push(data); } - _addToQueue(job) { - var _this2 = this; - return _asyncToGenerator2(function* () { - var args, blocked, error2, options2, reachedHWM, shifted, strategy; - args = job.args; - options2 = job.options; - try { - var _ref2 = yield _this2._store.__submit__(_this2.queued(), options2.weight); - reachedHWM = _ref2.reachedHWM; - blocked = _ref2.blocked; - strategy = _ref2.strategy; - } catch (error1) { - error2 = error1; - _this2.Events.trigger("debug", `Could not queue ${options2.id}`, { - args, - options: options2, - error: error2 - }); - job.doDrop({ - error: error2 - }); - return false; - } - if (blocked) { - job.doDrop(); - return true; - } else if (reachedHWM) { - shifted = strategy === Bottleneck3.prototype.strategy.LEAK ? _this2._queues.shiftLastFrom(options2.priority) : strategy === Bottleneck3.prototype.strategy.OVERFLOW_PRIORITY ? _this2._queues.shiftLastFrom(options2.priority + 1) : strategy === Bottleneck3.prototype.strategy.OVERFLOW ? job : void 0; - if (shifted != null) { - shifted.doDrop(); - } - if (shifted == null || strategy === Bottleneck3.prototype.strategy.OVERFLOW) { - if (shifted == null) { - job.doDrop(); - } - return reachedHWM; - } + return this.dataMessage(); + } + /** + * Decompresses data. + * + * @param {Buffer} data Compressed data + * @param {Function} cb Callback + * @private + */ + decompress(data, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + perMessageDeflate.decompress(data, this._fin, (err, buf2) => { + if (err) return cb(err); + if (buf2.length) { + this._messageLength += buf2.length; + if (this._messageLength > this._maxPayload && this._maxPayload > 0) { + return cb( + error2( + RangeError, + "Max payload size exceeded", + false, + 1009, + "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH" + ) + ); } - job.doQueue(reachedHWM, blocked); - _this2._queues.push(job); - yield _this2._drainAll(); - return reachedHWM; - })(); - } - _receive(job) { - if (this._states.jobStatus(job.options.id) != null) { - job._reject(new Bottleneck3.prototype.BottleneckError(`A job with the same id already exists (id=${job.options.id})`)); - return false; - } else { - job.doReceive(); - return this._submitLock.schedule(this._addToQueue, job); - } - } - submit(...args) { - var cb, fn, job, options2, ref, ref1, task; - if (typeof args[0] === "function") { - var _ref3, _ref4, _splice$call, _splice$call2; - ref = args, _ref3 = ref, _ref4 = _toArray(_ref3), fn = _ref4[0], args = _ref4.slice(1), _ref3, _splice$call = splice.call(args, -1), _splice$call2 = _slicedToArray2(_splice$call, 1), cb = _splice$call2[0], _splice$call; - options2 = parser3.load({}, this.jobDefaults); - } else { - var _ref5, _ref6, _splice$call3, _splice$call4; - ref1 = args, _ref5 = ref1, _ref6 = _toArray(_ref5), options2 = _ref6[0], fn = _ref6[1], args = _ref6.slice(2), _ref5, _splice$call3 = splice.call(args, -1), _splice$call4 = _slicedToArray2(_splice$call3, 1), cb = _splice$call4[0], _splice$call3; - options2 = parser3.load(options2, this.jobDefaults); + this._fragments.push(buf2); } - task = (...args2) => { - return new this.Promise(function(resolve82, reject) { - return fn(...args2, function(...args3) { - return (args3[0] != null ? reject : resolve82)(args3); - }); - }); - }; - job = new Job(task, args, options2, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); - job.promise.then(function(args2) { - return typeof cb === "function" ? cb(...args2) : void 0; - }).catch(function(args2) { - if (Array.isArray(args2)) { - return typeof cb === "function" ? cb(...args2) : void 0; + const er = this.dataMessage(); + if (er) return cb(er); + this.startLoop(cb); + }); + } + /** + * Handles a data message. + * + * @return {(Error|undefined)} A possible error + * @private + */ + dataMessage() { + if (this._fin) { + const messageLength = this._messageLength; + const fragments = this._fragments; + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragmented = 0; + this._fragments = []; + if (this._opcode === 2) { + let data; + if (this._binaryType === "nodebuffer") { + data = concat2(fragments, messageLength); + } else if (this._binaryType === "arraybuffer") { + data = toArrayBuffer(concat2(fragments, messageLength)); } else { - return typeof cb === "function" ? cb(args2) : void 0; + data = fragments; } - }); - return this._receive(job); - } - schedule(...args) { - var job, options2, task; - if (typeof args[0] === "function") { - var _args = args; - var _args2 = _toArray(_args); - task = _args2[0]; - args = _args2.slice(1); - options2 = {}; + this.emit("message", data, true); } else { - var _args3 = args; - var _args4 = _toArray(_args3); - options2 = _args4[0]; - task = _args4[1]; - args = _args4.slice(2); + const buf2 = concat2(fragments, messageLength); + if (!this._skipUTF8Validation && !isValidUTF8(buf2)) { + this._loop = false; + return error2( + Error, + "invalid UTF-8 sequence", + true, + 1007, + "WS_ERR_INVALID_UTF8" + ); + } + this.emit("message", buf2, false); } - job = new Job(task, args, options2, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); - this._receive(job); - return job.promise; - } - wrap(fn) { - var schedule, wrapped; - schedule = this.schedule.bind(this); - wrapped = function wrapped2(...args) { - return schedule(fn.bind(this), ...args); - }; - wrapped.withOptions = function(options2, ...args) { - return schedule(options2, fn, ...args); - }; - return wrapped; - } - updateSettings(options2 = {}) { - var _this3 = this; - return _asyncToGenerator2(function* () { - yield _this3._store.__updateSettings__(parser3.overwrite(options2, _this3.storeDefaults)); - parser3.overwrite(options2, _this3.instanceDefaults, _this3); - return _this3; - })(); - } - currentReservoir() { - return this._store.__currentReservoir__(); } - incrementReservoir(incr = 0) { - return this._store.__incrementReservoir__(incr); + this._state = GET_INFO; + } + /** + * Handles a control message. + * + * @param {Buffer} data Data to handle + * @return {(Error|RangeError|undefined)} A possible error + * @private + */ + controlMessage(data) { + if (this._opcode === 8) { + this._loop = false; + if (data.length === 0) { + this.emit("conclude", 1005, EMPTY_BUFFER); + this.end(); + } else if (data.length === 1) { + return error2( + RangeError, + "invalid payload length 1", + true, + 1002, + "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH" + ); + } else { + const code2 = data.readUInt16BE(0); + if (!isValidStatusCode(code2)) { + return error2( + RangeError, + `invalid status code ${code2}`, + true, + 1002, + "WS_ERR_INVALID_CLOSE_CODE" + ); + } + const buf2 = data.slice(2); + if (!this._skipUTF8Validation && !isValidUTF8(buf2)) { + return error2( + Error, + "invalid UTF-8 sequence", + true, + 1007, + "WS_ERR_INVALID_UTF8" + ); + } + this.emit("conclude", code2, buf2); + this.end(); + } + } else if (this._opcode === 9) { + this.emit("ping", data); + } else { + this.emit("pong", data); } + this._state = GET_INFO; } - ; - Bottleneck3.default = Bottleneck3; - Bottleneck3.Events = Events2; - Bottleneck3.version = Bottleneck3.prototype.version = require_version().version; - Bottleneck3.strategy = Bottleneck3.prototype.strategy = { - LEAK: 1, - OVERFLOW: 2, - OVERFLOW_PRIORITY: 4, - BLOCK: 3 - }; - Bottleneck3.BottleneckError = Bottleneck3.prototype.BottleneckError = require_BottleneckError(); - Bottleneck3.Group = Bottleneck3.prototype.Group = require_Group(); - Bottleneck3.RedisConnection = Bottleneck3.prototype.RedisConnection = require_RedisConnection(); - Bottleneck3.IORedisConnection = Bottleneck3.prototype.IORedisConnection = require_IORedisConnection(); - Bottleneck3.Batcher = Bottleneck3.prototype.Batcher = require_Batcher(); - Bottleneck3.prototype.jobDefaults = { - priority: DEFAULT_PRIORITY, - weight: 1, - expiration: null, - id: "" - }; - Bottleneck3.prototype.storeDefaults = { - maxConcurrent: null, - minTime: 0, - highWater: null, - strategy: Bottleneck3.prototype.strategy.LEAK, - penalty: null, - reservoir: null, - reservoirRefreshInterval: null, - reservoirRefreshAmount: null, - reservoirIncreaseInterval: null, - reservoirIncreaseAmount: null, - reservoirIncreaseMaximum: null - }; - Bottleneck3.prototype.localStoreDefaults = { - Promise, - timeout: null, - heartbeatInterval: 250 - }; - Bottleneck3.prototype.redisStoreDefaults = { - Promise, - timeout: null, - heartbeatInterval: 5e3, - clientTimeout: 1e4, - Redis: null, - clientOptions: {}, - clusterNodes: null, - clearDatastore: false, - connection: null - }; - Bottleneck3.prototype.instanceDefaults = { - datastore: "local", - connection: null, - id: "", - rejectOnDrop: true, - trackDoneStatus: false, - Promise - }; - Bottleneck3.prototype.stopDefaults = { - enqueueErrorMessage: "This limiter has been stopped and cannot accept new jobs.", - dropWaitingJobs: true, - dropErrorMessage: "This limiter has been stopped." - }; - return Bottleneck3; - }.call(void 0); - module14.exports = Bottleneck2; + }; + module14.exports = Receiver2; + function error2(ErrorCtor, message, prefix, statusCode, errorCode) { + const err = new ErrorCtor( + prefix ? `Invalid WebSocket frame: ${message}` : message + ); + Error.captureStackTrace(err, error2); + err.code = errorCode; + err[kStatusCode] = statusCode; + return err; + } } }); -var require_lib36 = __commonJS({ - "node_modules/.deno/bottleneck@2.19.5/node_modules/bottleneck/lib/index.js"(exports2, module14) { +var require_sender = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/sender.js"(exports2, module14) { "use strict"; - module14.exports = require_Bottleneck(); - } -}); -var require_package7 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/package.json"(exports2, module14) { - module14.exports = { - name: "joi", - description: "Object schema validation", - version: "18.0.1", - repository: { - url: "git://github.com/hapijs/joi", - type: "git" - }, - engines: { - node: ">= 20" - }, - main: "lib/index.js", - types: "lib/index.d.ts", - browser: "dist/joi-browser.min.js", - files: [ - "lib/**/*", - "dist/*" - ], - keywords: [ - "schema", - "validation" - ], - dependencies: { - "@hapi/address": "^5.1.1", - "@hapi/formula": "^3.0.2", - "@hapi/hoek": "^11.0.7", - "@hapi/pinpoint": "^2.0.1", - "@hapi/tlds": "^1.1.1", - "@hapi/topo": "^6.0.2", - "@standard-schema/spec": "^1.0.0" - }, - devDependencies: { - "@hapi/bourne": "^3.0.0", - "@hapi/code": "^9.0.3", - "@hapi/eslint-plugin": "^7.0.0", - "@hapi/joi-legacy-test": "npm:@hapi/joi@15.x.x", - "@hapi/lab": "^26.0.0", - "@types/node": "^20.17.47", - typescript: "^5.8.3" - }, - scripts: { - prepublishOnly: "cd browser && npm install && npm run build", - test: "lab -t 100 -a @hapi/code -L -Y", - "test-cov-html": "lab -r html -o coverage.html -a @hapi/code" - }, - license: "BSD-3-Clause" - }; - } -}); -var require_schemas2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/schemas.js"(exports2) { - "use strict"; - var Joi2 = require_lib39(); - var internals = {}; - internals.wrap = Joi2.string().min(1).max(2).allow(false); - exports2.preferences = Joi2.object({ - allowUnknown: Joi2.boolean(), - abortEarly: Joi2.boolean(), - artifacts: Joi2.boolean(), - cache: Joi2.boolean(), - context: Joi2.object(), - convert: Joi2.boolean(), - dateFormat: Joi2.valid("date", "iso", "string", "time", "utc"), - debug: Joi2.boolean(), - errors: { - escapeHtml: Joi2.boolean(), - label: Joi2.valid("path", "key", false), - language: [ - Joi2.string(), - Joi2.object().ref() - ], - render: Joi2.boolean(), - stack: Joi2.boolean(), - wrap: { - label: internals.wrap, - array: internals.wrap, - string: internals.wrap - } - }, - externals: Joi2.boolean(), - messages: Joi2.object(), - noDefaults: Joi2.boolean(), - nonEnumerables: Joi2.boolean(), - presence: Joi2.valid("required", "optional", "forbidden"), - skipFunctions: Joi2.boolean(), - stripUnknown: Joi2.object({ - arrays: Joi2.boolean(), - objects: Joi2.boolean() - }).or("arrays", "objects").allow(true, false), - warnings: Joi2.boolean() - }).strict(); - internals.nameRx = /^[a-zA-Z0-9]\w*$/; - internals.rule = Joi2.object({ - alias: Joi2.array().items(Joi2.string().pattern(internals.nameRx)).single(), - args: Joi2.array().items( - Joi2.string(), - Joi2.object({ - name: Joi2.string().pattern(internals.nameRx).required(), - ref: Joi2.boolean(), - assert: Joi2.alternatives([ - Joi2.function(), - Joi2.object().schema() - ]).conditional("ref", { is: true, then: Joi2.required() }), - normalize: Joi2.function(), - message: Joi2.string().when("assert", { is: Joi2.function(), then: Joi2.required() }) - }) - ), - convert: Joi2.boolean(), - manifest: Joi2.boolean(), - method: Joi2.function().allow(false), - multi: Joi2.boolean(), - validate: Joi2.function() - }); - exports2.extension = Joi2.object({ - type: Joi2.alternatives([ - Joi2.string(), - Joi2.object().regex() - ]).required(), - args: Joi2.function(), - cast: Joi2.object().pattern(internals.nameRx, Joi2.object({ - from: Joi2.function().maxArity(1).required(), - to: Joi2.function().minArity(1).maxArity(2).required() - })), - base: Joi2.object().schema().when("type", { is: Joi2.object().regex(), then: Joi2.forbidden() }), - coerce: [ - Joi2.function().maxArity(3), - Joi2.object({ method: Joi2.function().maxArity(3).required(), from: Joi2.array().items(Joi2.string()).single() }) - ], - flags: Joi2.object().pattern(internals.nameRx, Joi2.object({ - setter: Joi2.string(), - default: Joi2.any() - })), - manifest: { - build: Joi2.function().arity(2) - }, - messages: [Joi2.object(), Joi2.string()], - modifiers: Joi2.object().pattern(internals.nameRx, Joi2.function().minArity(1).maxArity(2)), - overrides: Joi2.object().pattern(internals.nameRx, Joi2.function()), - prepare: Joi2.function().maxArity(3), - rebuild: Joi2.function().arity(1), - rules: Joi2.object().pattern(internals.nameRx, internals.rule), - terms: Joi2.object().pattern(internals.nameRx, Joi2.object({ - init: Joi2.array().allow(null).required(), - manifest: Joi2.object().pattern(/.+/, [ - Joi2.valid("schema", "single"), - Joi2.object({ - mapped: Joi2.object({ - from: Joi2.string().required(), - to: Joi2.string().required() - }).required() - }) - ]) - })), - validate: Joi2.function().maxArity(3) - }).strict(); - exports2.extensions = Joi2.array().items(Joi2.object(), Joi2.function().arity(1)).strict(); - internals.desc = { - buffer: Joi2.object({ - buffer: Joi2.string() - }), - func: Joi2.object({ - function: Joi2.function().required(), - options: { - literal: true + var net = __require2("node:net"); + var tls = __require2("node:tls"); + var { randomFillSync } = __require2("node:crypto"); + var PerMessageDeflate = require_permessage_deflate(); + var { EMPTY_BUFFER } = require_constants2(); + var { isValidStatusCode } = require_validation(); + var { mask: applyMask, toBuffer } = require_buffer_util(); + var kByteLength = Symbol("kByteLength"); + var maskBuffer = Buffer.alloc(4); + var Sender2 = class _Sender { + /** + * Creates a Sender instance. + * + * @param {(net.Socket|tls.Socket)} socket The connection socket + * @param {Object} [extensions] An object containing the negotiated extensions + * @param {Function} [generateMask] The function used to generate the masking + * key + */ + constructor(socket, extensions, generateMask) { + this._extensions = extensions || {}; + if (generateMask) { + this._generateMask = generateMask; + this._maskBuffer = Buffer.alloc(4); } - }), - override: Joi2.object({ - override: true - }), - ref: Joi2.object({ - ref: Joi2.object({ - type: Joi2.valid("value", "global", "local"), - path: Joi2.array().required(), - separator: Joi2.string().length(1).allow(false), - ancestor: Joi2.number().min(0).integer().allow("root"), - map: Joi2.array().items(Joi2.array().length(2)).min(1), - adjust: Joi2.function(), - iterables: Joi2.boolean(), - in: Joi2.boolean(), - render: Joi2.boolean() - }).required() - }), - regex: Joi2.object({ - regex: Joi2.string().min(3) - }), - special: Joi2.object({ - special: Joi2.valid("deep").required() - }), - template: Joi2.object({ - template: Joi2.string().required(), - options: Joi2.object() - }), - value: Joi2.object({ - value: Joi2.alternatives([Joi2.object(), Joi2.array()]).required() - }) - }; - internals.desc.entity = Joi2.alternatives([ - Joi2.array().items(Joi2.link("...")), - Joi2.boolean(), - Joi2.function(), - Joi2.number(), - Joi2.string(), - internals.desc.buffer, - internals.desc.func, - internals.desc.ref, - internals.desc.regex, - internals.desc.special, - internals.desc.template, - internals.desc.value, - Joi2.link("/") - ]); - internals.desc.values = Joi2.array().items( - null, - Joi2.boolean(), - Joi2.function(), - Joi2.number().allow(Infinity, -Infinity), - Joi2.string().allow(""), - Joi2.symbol(), - internals.desc.buffer, - internals.desc.func, - internals.desc.override, - internals.desc.ref, - internals.desc.regex, - internals.desc.template, - internals.desc.value - ); - internals.desc.messages = Joi2.object().pattern(/.+/, [ - Joi2.string(), - internals.desc.template, - Joi2.object().pattern(/.+/, [Joi2.string(), internals.desc.template]) - ]); - exports2.description = Joi2.object({ - type: Joi2.string().required(), - flags: Joi2.object({ - cast: Joi2.string(), - default: Joi2.any(), - description: Joi2.string(), - empty: Joi2.link("/"), - failover: internals.desc.entity, - id: Joi2.string(), - label: Joi2.string(), - only: true, - presence: ["optional", "required", "forbidden"], - result: ["raw", "strip"], - strip: Joi2.boolean(), - unit: Joi2.string() - }).unknown(), - preferences: { - allowUnknown: Joi2.boolean(), - abortEarly: Joi2.boolean(), - artifacts: Joi2.boolean(), - cache: Joi2.boolean(), - convert: Joi2.boolean(), - dateFormat: ["date", "iso", "string", "time", "utc"], - errors: { - escapeHtml: Joi2.boolean(), - label: ["path", "key"], - language: [ - Joi2.string(), - internals.desc.ref - ], - wrap: { - label: internals.wrap, - array: internals.wrap + this._socket = socket; + this._firstFragment = true; + this._compress = false; + this._bufferedBytes = 0; + this._deflating = false; + this._queue = []; + } + /** + * Frames a piece of data according to the HyBi WebSocket protocol. + * + * @param {(Buffer|String)} data The data to frame + * @param {Object} options Options object + * @param {Boolean} [options.fin=false] Specifies whether or not to set the + * FIN bit + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Buffer} [options.maskBuffer] The buffer used to store the masking + * key + * @param {Number} options.opcode The opcode + * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be + * modified + * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the + * RSV1 bit + * @return {(Buffer|String)[]} The framed data + * @public + */ + static frame(data, options2) { + let mask; + let merge3 = false; + let offset = 2; + let skipMasking = false; + if (options2.mask) { + mask = options2.maskBuffer || maskBuffer; + if (options2.generateMask) { + options2.generateMask(mask); + } else { + randomFillSync(mask, 0, 4); } - }, - externals: Joi2.boolean(), - messages: internals.desc.messages, - noDefaults: Joi2.boolean(), - nonEnumerables: Joi2.boolean(), - presence: ["required", "optional", "forbidden"], - skipFunctions: Joi2.boolean(), - stripUnknown: Joi2.object({ - arrays: Joi2.boolean(), - objects: Joi2.boolean() - }).or("arrays", "objects").allow(true, false), - warnings: Joi2.boolean() - }, - allow: internals.desc.values, - invalid: internals.desc.values, - rules: Joi2.array().min(1).items({ - name: Joi2.string().required(), - args: Joi2.object().min(1), - keep: Joi2.boolean(), - message: [ - Joi2.string(), - internals.desc.messages - ], - warn: Joi2.boolean() - }), - // Terms - keys: Joi2.object().pattern(/.*/, Joi2.link("/")), - link: internals.desc.ref - }).pattern(/^[a-z]\w*$/, Joi2.any()); - } -}); -var require_lib37 = __commonJS({ - "node_modules/.deno/@hapi+formula@3.0.2/node_modules/@hapi/formula/lib/index.js"(exports2) { - "use strict"; - var internals = { - operators: ["!", "^", "*", "/", "%", "+", "-", "<", "<=", ">", ">=", "==", "!=", "&&", "||", "??"], - operatorCharacters: ["!", "^", "*", "/", "%", "+", "-", "<", "=", ">", "&", "|", "?"], - operatorsOrder: [["^"], ["*", "/", "%"], ["+", "-"], ["<", "<=", ">", ">="], ["==", "!="], ["&&"], ["||", "??"]], - operatorsPrefix: ["!", "n"], - literals: { - '"': '"', - "`": "`", - "'": "'", - "[": "]" - }, - numberRx: /^(?:[0-9]*(\.[0-9]*)?){1}$/, - tokenRx: /^[\w\$\#\.\@\:\{\}]+$/, - symbol: Symbol("formula"), - settings: Symbol("settings") - }; - exports2.Parser = class { - constructor(string3, options2 = {}) { - if (!options2[internals.settings] && options2.constants) { - for (const constant in options2.constants) { - const value = options2.constants[constant]; - if (value !== null && !["boolean", "number", "string"].includes(typeof value)) { - throw new Error(`Formula constant ${constant} contains invalid ${typeof value} value type`); - } + skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0; + offset = 6; + } + let dataLength; + if (typeof data === "string") { + if ((!options2.mask || skipMasking) && options2[kByteLength] !== void 0) { + dataLength = options2[kByteLength]; + } else { + data = Buffer.from(data); + dataLength = data.length; } + } else { + dataLength = data.length; + merge3 = options2.mask && options2.readOnly && !skipMasking; + } + let payloadLength = dataLength; + if (dataLength >= 65536) { + offset += 8; + payloadLength = 127; + } else if (dataLength > 125) { + offset += 2; + payloadLength = 126; } - this.settings = options2[internals.settings] ? options2 : Object.assign({ [internals.settings]: true, constants: {}, functions: {} }, options2); - this.single = null; - this._parts = null; - this._parse(string3); + const target = Buffer.allocUnsafe(merge3 ? dataLength + offset : offset); + target[0] = options2.fin ? options2.opcode | 128 : options2.opcode; + if (options2.rsv1) target[0] |= 64; + target[1] = payloadLength; + if (payloadLength === 126) { + target.writeUInt16BE(dataLength, 2); + } else if (payloadLength === 127) { + target[2] = target[3] = 0; + target.writeUIntBE(dataLength, 4, 6); + } + if (!options2.mask) return [target, data]; + target[1] |= 128; + target[offset - 4] = mask[0]; + target[offset - 3] = mask[1]; + target[offset - 2] = mask[2]; + target[offset - 1] = mask[3]; + if (skipMasking) return [target, data]; + if (merge3) { + applyMask(data, mask, target, offset, dataLength); + return [target]; + } + applyMask(data, mask, data, 0, dataLength); + return [target, data]; } - _parse(string3) { - let parts = []; - let current = ""; - let parenthesis = 0; - let literal = false; - const flush = (inner) => { - if (parenthesis) { - throw new Error("Formula missing closing parenthesis"); - } - const last = parts.length ? parts[parts.length - 1] : null; - if (!literal && !current && !inner) { - return; - } - if (last && last.type === "reference" && inner === ")") { - last.type = "function"; - last.value = this._subFormula(current, last.value); - current = ""; - return; + /** + * Sends a close message to the other peer. + * + * @param {Number} [code] The status code component of the body + * @param {(String|Buffer)} [data] The message component of the body + * @param {Boolean} [mask=false] Specifies whether or not to mask the message + * @param {Function} [cb] Callback + * @public + */ + close(code2, data, mask, cb) { + let buf2; + if (code2 === void 0) { + buf2 = EMPTY_BUFFER; + } else if (typeof code2 !== "number" || !isValidStatusCode(code2)) { + throw new TypeError("First argument must be a valid error code number"); + } else if (data === void 0 || !data.length) { + buf2 = Buffer.allocUnsafe(2); + buf2.writeUInt16BE(code2, 0); + } else { + const length2 = Buffer.byteLength(data); + if (length2 > 123) { + throw new RangeError("The message must not be greater than 123 bytes"); } - if (inner === ")") { - const sub = new exports2.Parser(current, this.settings); - parts.push({ type: "segment", value: sub }); - } else if (literal) { - if (literal === "]") { - parts.push({ type: "reference", value: current }); - current = ""; - return; - } - parts.push({ type: "literal", value: current }); - } else if (internals.operatorCharacters.includes(current)) { - if (last && last.type === "operator" && internals.operators.includes(last.value + current)) { - last.value += current; - } else { - parts.push({ type: "operator", value: current }); - } - } else if (current.match(internals.numberRx)) { - parts.push({ type: "constant", value: parseFloat(current) }); - } else if (this.settings.constants[current] !== void 0) { - parts.push({ type: "constant", value: this.settings.constants[current] }); + buf2 = Buffer.allocUnsafe(2 + length2); + buf2.writeUInt16BE(code2, 0); + if (typeof data === "string") { + buf2.write(data, 2); } else { - if (!current.match(internals.tokenRx)) { - throw new Error(`Formula contains invalid token: ${current}`); - } - parts.push({ type: "reference", value: current }); + buf2.set(data, 2); } - current = ""; + } + const options2 = { + [kByteLength]: buf2.length, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 8, + readOnly: false, + rsv1: false }; - for (const c of string3) { - if (literal) { - if (c === literal) { - flush(); - literal = false; - } else { - current += c; - } - } else if (parenthesis) { - if (c === "(") { - current += c; - ++parenthesis; - } else if (c === ")") { - --parenthesis; - if (!parenthesis) { - flush(c); - } else { - current += c; - } - } else { - current += c; - } - } else if (c in internals.literals) { - literal = internals.literals[c]; - } else if (c === "(") { - flush(); - ++parenthesis; - } else if (internals.operatorCharacters.includes(c)) { - flush(); - current = c; - flush(); - } else if (c !== " ") { - current += c; - } else { - flush(); - } + if (this._deflating) { + this.enqueue([this.dispatch, buf2, false, options2, cb]); + } else { + this.sendFrame(_Sender.frame(buf2, options2), cb); + } + } + /** + * Sends a ping message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback + * @public + */ + ping(data, mask, cb) { + let byteLength; + let readOnly; + if (typeof data === "string") { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; + } + if (byteLength > 125) { + throw new RangeError("The data size must not be greater than 125 bytes"); + } + const options2 = { + [kByteLength]: byteLength, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 9, + readOnly, + rsv1: false + }; + if (this._deflating) { + this.enqueue([this.dispatch, data, false, options2, cb]); + } else { + this.sendFrame(_Sender.frame(data, options2), cb); + } + } + /** + * Sends a pong message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} [mask=false] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback + * @public + */ + pong(data, mask, cb) { + let byteLength; + let readOnly; + if (typeof data === "string") { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; } - flush(); - parts = parts.map((part, i2) => { - if (part.type !== "operator" || part.value !== "-" || i2 && parts[i2 - 1].type !== "operator") { - return part; - } - return { type: "operator", value: "n" }; - }); - let operator = false; - for (const part of parts) { - if (part.type === "operator") { - if (internals.operatorsPrefix.includes(part.value)) { - continue; - } - if (!operator) { - throw new Error("Formula contains an operator in invalid position"); - } - if (!internals.operators.includes(part.value)) { - throw new Error(`Formula contains an unknown operator ${part.value}`); - } - } else if (operator) { - throw new Error("Formula missing expected operator"); - } - operator = !operator; + if (byteLength > 125) { + throw new RangeError("The data size must not be greater than 125 bytes"); } - if (!operator) { - throw new Error("Formula contains invalid trailing operator"); + const options2 = { + [kByteLength]: byteLength, + fin: true, + generateMask: this._generateMask, + mask, + maskBuffer: this._maskBuffer, + opcode: 10, + readOnly, + rsv1: false + }; + if (this._deflating) { + this.enqueue([this.dispatch, data, false, options2, cb]); + } else { + this.sendFrame(_Sender.frame(data, options2), cb); } - if (parts.length === 1 && ["reference", "literal", "constant"].includes(parts[0].type)) { - this.single = { type: parts[0].type === "reference" ? "reference" : "value", value: parts[0].value }; + } + /** + * Sends a data message to the other peer. + * + * @param {*} data The message to send + * @param {Object} options Options object + * @param {Boolean} [options.binary=false] Specifies whether `data` is binary + * or text + * @param {Boolean} [options.compress=false] Specifies whether or not to + * compress `data` + * @param {Boolean} [options.fin=false] Specifies whether the fragment is the + * last one + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Function} [cb] Callback + * @public + */ + send(data, options2, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + let opcode = options2.binary ? 2 : 1; + let rsv1 = options2.compress; + let byteLength; + let readOnly; + if (typeof data === "string") { + byteLength = Buffer.byteLength(data); + readOnly = false; + } else { + data = toBuffer(data); + byteLength = data.length; + readOnly = toBuffer.readOnly; } - this._parts = parts.map((part) => { - if (part.type === "operator") { - return internals.operatorsPrefix.includes(part.value) ? part : part.value; - } - if (part.type !== "reference") { - return part.value; - } - if (this.settings.tokenRx && !this.settings.tokenRx.test(part.value)) { - throw new Error(`Formula contains invalid reference ${part.value}`); - } - if (this.settings.reference) { - return this.settings.reference(part.value); + if (this._firstFragment) { + this._firstFragment = false; + if (rsv1 && perMessageDeflate && perMessageDeflate.params[perMessageDeflate._isServer ? "server_no_context_takeover" : "client_no_context_takeover"]) { + rsv1 = byteLength >= perMessageDeflate._threshold; } - return internals.reference(part.value); - }); - } - _subFormula(string3, name) { - const method = this.settings.functions[name]; - if (typeof method !== "function") { - throw new Error(`Formula contains unknown function ${name}`); - } - let args = []; - if (string3) { - let current = ""; - let parenthesis = 0; - let literal = false; - const flush = () => { - if (!current) { - throw new Error(`Formula contains function ${name} with invalid arguments ${string3}`); - } - args.push(current); - current = ""; + this._compress = rsv1; + } else { + rsv1 = false; + opcode = 0; + } + if (options2.fin) this._firstFragment = true; + if (perMessageDeflate) { + const opts = { + [kByteLength]: byteLength, + fin: options2.fin, + generateMask: this._generateMask, + mask: options2.mask, + maskBuffer: this._maskBuffer, + opcode, + readOnly, + rsv1 }; - for (let i2 = 0; i2 < string3.length; ++i2) { - const c = string3[i2]; - if (literal) { - current += c; - if (c === literal) { - literal = false; - } - } else if (c in internals.literals && !parenthesis) { - current += c; - literal = internals.literals[c]; - } else if (c === "," && !parenthesis) { - flush(); - } else { - current += c; - if (c === "(") { - ++parenthesis; - } else if (c === ")") { - --parenthesis; - } - } + if (this._deflating) { + this.enqueue([this.dispatch, data, this._compress, opts, cb]); + } else { + this.dispatch(data, this._compress, opts, cb); } - flush(); + } else { + this.sendFrame( + _Sender.frame(data, { + [kByteLength]: byteLength, + fin: options2.fin, + generateMask: this._generateMask, + mask: options2.mask, + maskBuffer: this._maskBuffer, + opcode, + readOnly, + rsv1: false + }), + cb + ); } - args = args.map((arg) => new exports2.Parser(arg, this.settings)); - return function(context) { - const innerValues = []; - for (const arg of args) { - innerValues.push(arg.evaluate(context)); - } - return method.call(context, ...innerValues); - }; } - evaluate(context) { - const parts = this._parts.slice(); - for (let i2 = parts.length - 2; i2 >= 0; --i2) { - const part = parts[i2]; - if (part && part.type === "operator") { - const current = parts[i2 + 1]; - parts.splice(i2 + 1, 1); - const value = internals.evaluate(current, context); - parts[i2] = internals.single(part.value, value); - } - } - internals.operatorsOrder.forEach((set) => { - for (let i2 = 1; i2 < parts.length - 1; ) { - if (set.includes(parts[i2])) { - const operator = parts[i2]; - const left2 = internals.evaluate(parts[i2 - 1], context); - const right2 = internals.evaluate(parts[i2 + 1], context); - parts.splice(i2, 2); - const result = internals.calculate(operator, left2, right2); - parts[i2 - 1] = result === 0 ? 0 : result; - } else { - i2 += 2; + /** + * Dispatches a message. + * + * @param {(Buffer|String)} data The message to send + * @param {Boolean} [compress=false] Specifies whether or not to compress + * `data` + * @param {Object} options Options object + * @param {Boolean} [options.fin=false] Specifies whether or not to set the + * FIN bit + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Boolean} [options.mask=false] Specifies whether or not to mask + * `data` + * @param {Buffer} [options.maskBuffer] The buffer used to store the masking + * key + * @param {Number} options.opcode The opcode + * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be + * modified + * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the + * RSV1 bit + * @param {Function} [cb] Callback + * @private + */ + dispatch(data, compress, options2, cb) { + if (!compress) { + this.sendFrame(_Sender.frame(data, options2), cb); + return; + } + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + this._bufferedBytes += options2[kByteLength]; + this._deflating = true; + perMessageDeflate.compress(data, options2.fin, (_, buf2) => { + if (this._socket.destroyed) { + const err = new Error( + "The socket was closed while data was being compressed" + ); + if (typeof cb === "function") cb(err); + for (let i2 = 0; i2 < this._queue.length; i2++) { + const params = this._queue[i2]; + const callback = params[params.length - 1]; + if (typeof callback === "function") callback(err); } + return; } + this._bufferedBytes -= options2[kByteLength]; + this._deflating = false; + options2.readOnly = false; + this.sendFrame(_Sender.frame(buf2, options2), cb); + this.dequeue(); }); - return internals.evaluate(parts[0], context); + } + /** + * Executes queued send operations. + * + * @private + */ + dequeue() { + while (!this._deflating && this._queue.length) { + const params = this._queue.shift(); + this._bufferedBytes -= params[3][kByteLength]; + Reflect.apply(params[0], this, params.slice(1)); + } + } + /** + * Enqueues a send operation. + * + * @param {Array} params Send operation parameters. + * @private + */ + enqueue(params) { + this._bufferedBytes += params[3][kByteLength]; + this._queue.push(params); + } + /** + * Sends a frame. + * + * @param {Buffer[]} list The frame to send + * @param {Function} [cb] Callback + * @private + */ + sendFrame(list, cb) { + if (list.length === 2) { + this._socket.cork(); + this._socket.write(list[0]); + this._socket.write(list[1], cb); + this._socket.uncork(); + } else { + this._socket.write(list[0], cb); + } } }; - exports2.Parser.prototype[internals.symbol] = true; - internals.reference = function(name) { - return function(context) { - return context && context[name] !== void 0 ? context[name] : null; - }; + module14.exports = Sender2; + } +}); +var require_event_target = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/event-target.js"(exports2, module14) { + "use strict"; + var { kForOnEventAttribute, kListener } = require_constants2(); + var kCode = Symbol("kCode"); + var kData = Symbol("kData"); + var kError = Symbol("kError"); + var kMessage = Symbol("kMessage"); + var kReason = Symbol("kReason"); + var kTarget = Symbol("kTarget"); + var kType = Symbol("kType"); + var kWasClean = Symbol("kWasClean"); + var Event = class { + /** + * Create a new `Event`. + * + * @param {String} type The name of the event + * @throws {TypeError} If the `type` argument is not specified + */ + constructor(type) { + this[kTarget] = null; + this[kType] = type; + } + /** + * @type {*} + */ + get target() { + return this[kTarget]; + } + /** + * @type {String} + */ + get type() { + return this[kType]; + } }; - internals.evaluate = function(part, context) { - if (part === null) { - return null; + Object.defineProperty(Event.prototype, "target", { enumerable: true }); + Object.defineProperty(Event.prototype, "type", { enumerable: true }); + var CloseEvent = class extends Event { + /** + * Create a new `CloseEvent`. + * + * @param {String} type The name of the event + * @param {Object} [options] A dictionary object that allows for setting + * attributes via object members of the same name + * @param {Number} [options.code=0] The status code explaining why the + * connection was closed + * @param {String} [options.reason=''] A human-readable string explaining why + * the connection was closed + * @param {Boolean} [options.wasClean=false] Indicates whether or not the + * connection was cleanly closed + */ + constructor(type, options2 = {}) { + super(type); + this[kCode] = options2.code === void 0 ? 0 : options2.code; + this[kReason] = options2.reason === void 0 ? "" : options2.reason; + this[kWasClean] = options2.wasClean === void 0 ? false : options2.wasClean; + } + /** + * @type {Number} + */ + get code() { + return this[kCode]; } - if (typeof part === "function") { - return part(context); + /** + * @type {String} + */ + get reason() { + return this[kReason]; } - if (part[internals.symbol]) { - return part.evaluate(context); + /** + * @type {Boolean} + */ + get wasClean() { + return this[kWasClean]; } - return part; }; - internals.single = function(operator, value) { - if (operator === "!") { - return value ? false : true; + Object.defineProperty(CloseEvent.prototype, "code", { enumerable: true }); + Object.defineProperty(CloseEvent.prototype, "reason", { enumerable: true }); + Object.defineProperty(CloseEvent.prototype, "wasClean", { enumerable: true }); + var ErrorEvent = class extends Event { + /** + * Create a new `ErrorEvent`. + * + * @param {String} type The name of the event + * @param {Object} [options] A dictionary object that allows for setting + * attributes via object members of the same name + * @param {*} [options.error=null] The error that generated this event + * @param {String} [options.message=''] The error message + */ + constructor(type, options2 = {}) { + super(type); + this[kError] = options2.error === void 0 ? null : options2.error; + this[kMessage] = options2.message === void 0 ? "" : options2.message; } - const negative = -value; - if (negative === 0) { - return 0; + /** + * @type {*} + */ + get error() { + return this[kError]; + } + /** + * @type {String} + */ + get message() { + return this[kMessage]; } - return negative; }; - internals.calculate = function(operator, left2, right2) { - if (operator === "??") { - return internals.exists(left2) ? left2 : right2; + Object.defineProperty(ErrorEvent.prototype, "error", { enumerable: true }); + Object.defineProperty(ErrorEvent.prototype, "message", { enumerable: true }); + var MessageEvent2 = class extends Event { + /** + * Create a new `MessageEvent`. + * + * @param {String} type The name of the event + * @param {Object} [options] A dictionary object that allows for setting + * attributes via object members of the same name + * @param {*} [options.data=null] The message content + */ + constructor(type, options2 = {}) { + super(type); + this[kData] = options2.data === void 0 ? null : options2.data; + } + /** + * @type {*} + */ + get data() { + return this[kData]; } - if (typeof left2 === "string" || typeof right2 === "string") { - if (operator === "+") { - left2 = internals.exists(left2) ? left2 : ""; - right2 = internals.exists(right2) ? right2 : ""; - return left2 + right2; + }; + Object.defineProperty(MessageEvent2.prototype, "data", { enumerable: true }); + var EventTarget2 = { + /** + * Register an event listener. + * + * @param {String} type A string representing the event type to listen for + * @param {Function} listener The listener to add + * @param {Object} [options] An options object specifies characteristics about + * the event listener + * @param {Boolean} [options.once=false] A `Boolean` indicating that the + * listener should be invoked at most once after being added. If `true`, + * the listener would be automatically removed when invoked. + * @public + */ + addEventListener(type, listener, options2 = {}) { + let wrapper3; + if (type === "message") { + wrapper3 = function onMessage(data, isBinary) { + const event = new MessageEvent2("message", { + data: isBinary ? data : data.toString() + }); + event[kTarget] = this; + listener.call(this, event); + }; + } else if (type === "close") { + wrapper3 = function onClose(code2, message) { + const event = new CloseEvent("close", { + code: code2, + reason: message.toString(), + wasClean: this._closeFrameReceived && this._closeFrameSent + }); + event[kTarget] = this; + listener.call(this, event); + }; + } else if (type === "error") { + wrapper3 = function onError(error2) { + const event = new ErrorEvent("error", { + error: error2, + message: error2.message + }); + event[kTarget] = this; + listener.call(this, event); + }; + } else if (type === "open") { + wrapper3 = function onOpen() { + const event = new Event("open"); + event[kTarget] = this; + listener.call(this, event); + }; + } else { + return; + } + wrapper3[kForOnEventAttribute] = !!options2[kForOnEventAttribute]; + wrapper3[kListener] = listener; + if (options2.once) { + this.once(type, wrapper3); + } else { + this.on(type, wrapper3); + } + }, + /** + * Remove an event listener. + * + * @param {String} type A string representing the event type to remove + * @param {Function} handler The listener to remove + * @public + */ + removeEventListener(type, handler) { + for (const listener of this.listeners(type)) { + if (listener[kListener] === handler && !listener[kForOnEventAttribute]) { + this.removeListener(type, listener); + break; + } } - } else { - switch (operator) { - case "^": - return Math.pow(left2, right2); - case "*": - return left2 * right2; - case "/": - return left2 / right2; - case "%": - return left2 % right2; - case "+": - return left2 + right2; - case "-": - return left2 - right2; - } - } - switch (operator) { - case "<": - return left2 < right2; - case "<=": - return left2 <= right2; - case ">": - return left2 > right2; - case ">=": - return left2 >= right2; - case "==": - return left2 === right2; - case "!=": - return left2 !== right2; - case "&&": - return left2 && right2; - case "||": - return left2 || right2; } - return null; }; - internals.exists = function(value) { - return value !== null && value !== void 0; + module14.exports = { + CloseEvent, + ErrorEvent, + Event, + EventTarget: EventTarget2, + MessageEvent: MessageEvent2 }; } }); -var require_annotate2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/annotate.js"(exports2) { +var require_extension = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/extension.js"(exports2, module14) { "use strict"; - var { clone: clone2 } = require_lib(); - var Common = require_common3(); - var internals = { - annotations: Symbol("annotations") - }; - exports2.error = function(stripColorCodes) { - if (!this._original || typeof this._original !== "object") { - return this.details[0].message; - } - const redFgEscape = stripColorCodes ? "" : "\x1B[31m"; - const redBgEscape = stripColorCodes ? "" : "\x1B[41m"; - const endColor = stripColorCodes ? "" : "\x1B[0m"; - const obj = clone2(this._original); - for (let i2 = this.details.length - 1; i2 >= 0; --i2) { - const pos = i2 + 1; - const error2 = this.details[i2]; - const path8 = error2.path; - let node = obj; - for (let j = 0; ; ++j) { - const seg = path8[j]; - if (Common.isSchema(node)) { - node = node.clone(); - } - if (j + 1 < path8.length && typeof node[seg] !== "string") { - node = node[seg]; - } else { - const refAnnotations = node[internals.annotations] || { errors: {}, missing: {} }; - node[internals.annotations] = refAnnotations; - const cacheKey = seg || error2.context.key; - if (node[seg] !== void 0) { - refAnnotations.errors[cacheKey] = refAnnotations.errors[cacheKey] || []; - refAnnotations.errors[cacheKey].push(pos); + var { tokenChars } = require_validation(); + function push(dest, name, elem) { + if (dest[name] === void 0) dest[name] = [elem]; + else dest[name].push(elem); + } + function parse62(header) { + const offers = /* @__PURE__ */ Object.create(null); + let params = /* @__PURE__ */ Object.create(null); + let mustUnescape = false; + let isEscaping = false; + let inQuotes = false; + let extensionName; + let paramName; + let start = -1; + let code2 = -1; + let end = -1; + let i2 = 0; + for (; i2 < header.length; i2++) { + code2 = header.charCodeAt(i2); + if (extensionName === void 0) { + if (end === -1 && tokenChars[code2] === 1) { + if (start === -1) start = i2; + } else if (i2 !== 0 && (code2 === 32 || code2 === 9)) { + if (end === -1 && start !== -1) end = i2; + } else if (code2 === 59 || code2 === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i2}`); + } + if (end === -1) end = i2; + const name = header.slice(start, end); + if (code2 === 44) { + push(offers, name, params); + params = /* @__PURE__ */ Object.create(null); } else { - refAnnotations.missing[cacheKey] = pos; + extensionName = name; } - break; - } - } - } - const replacers = { - key: /_\$key\$_([, \d]+)_\$end\$_"/g, - missing: /"_\$miss\$_([^|]+)\|(\d+)_\$end\$_": "__missing__"/g, - arrayIndex: /\s*"_\$idx\$_([, \d]+)_\$end\$_",?\n(.*)/g, - specials: /"\[(NaN|Symbol.*|-?Infinity|function.*|\(.*)]"/g - }; - let message = internals.safeStringify(obj, 2).replace(replacers.key, ($0, $1) => `" ${redFgEscape}[${$1}]${endColor}`).replace(replacers.missing, ($0, $1, $2) => `${redBgEscape}"${$1}"${endColor}${redFgEscape} [${$2}]: -- missing --${endColor}`).replace(replacers.arrayIndex, ($0, $1, $2) => ` -${$2} ${redFgEscape}[${$1}]${endColor}`).replace(replacers.specials, ($0, $1) => $1); - message = `${message} -${redFgEscape}`; - for (let i2 = 0; i2 < this.details.length; ++i2) { - const pos = i2 + 1; - message = `${message} -[${pos}] ${this.details[i2].message}`; - } - message = message + endColor; - return message; - }; - internals.safeStringify = function(obj, spaces) { - return JSON.stringify(obj, internals.serializer(), spaces); - }; - internals.serializer = function() { - const keys = []; - const stack = []; - const cycleReplacer = (key, value) => { - if (stack[0] === value) { - return "[Circular ~]"; - } - return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"; - }; - return function(key, value) { - if (stack.length > 0) { - const thisPos = stack.indexOf(this); - if (~thisPos) { - stack.length = thisPos + 1; - keys.length = thisPos + 1; - keys[thisPos] = key; + start = end = -1; } else { - stack.push(this); - keys.push(key); + throw new SyntaxError(`Unexpected character at index ${i2}`); } - if (~stack.indexOf(value)) { - value = cycleReplacer.call(this, key, value); + } else if (paramName === void 0) { + if (end === -1 && tokenChars[code2] === 1) { + if (start === -1) start = i2; + } else if (code2 === 32 || code2 === 9) { + if (end === -1 && start !== -1) end = i2; + } else if (code2 === 59 || code2 === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i2}`); + } + if (end === -1) end = i2; + push(params, header.slice(start, end), true); + if (code2 === 44) { + push(offers, extensionName, params); + params = /* @__PURE__ */ Object.create(null); + extensionName = void 0; + } + start = end = -1; + } else if (code2 === 61 && start !== -1 && end === -1) { + paramName = header.slice(start, i2); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i2}`); } } else { - stack.push(value); - } - if (value) { - const annotations = value[internals.annotations]; - if (annotations) { - if (Array.isArray(value)) { - const annotated = []; - for (let i2 = 0; i2 < value.length; ++i2) { - if (annotations.errors[i2]) { - annotated.push(`_$idx$_${annotations.errors[i2].sort().join(", ")}_$end$_`); - } - annotated.push(value[i2]); - } - value = annotated; + if (isEscaping) { + if (tokenChars[code2] !== 1) { + throw new SyntaxError(`Unexpected character at index ${i2}`); + } + if (start === -1) start = i2; + else if (!mustUnescape) mustUnescape = true; + isEscaping = false; + } else if (inQuotes) { + if (tokenChars[code2] === 1) { + if (start === -1) start = i2; + } else if (code2 === 34 && start !== -1) { + inQuotes = false; + end = i2; + } else if (code2 === 92) { + isEscaping = true; } else { - for (const errorKey in annotations.errors) { - value[`${errorKey}_$key$_${annotations.errors[errorKey].sort().join(", ")}_$end$_`] = value[errorKey]; - value[errorKey] = void 0; - } - for (const missingKey in annotations.missing) { - value[`_$miss$_${missingKey}|${annotations.missing[missingKey]}_$end$_`] = "__missing__"; - } + throw new SyntaxError(`Unexpected character at index ${i2}`); + } + } else if (code2 === 34 && header.charCodeAt(i2 - 1) === 61) { + inQuotes = true; + } else if (end === -1 && tokenChars[code2] === 1) { + if (start === -1) start = i2; + } else if (start !== -1 && (code2 === 32 || code2 === 9)) { + if (end === -1) end = i2; + } else if (code2 === 59 || code2 === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i2}`); + } + if (end === -1) end = i2; + let value = header.slice(start, end); + if (mustUnescape) { + value = value.replace(/\\/g, ""); + mustUnescape = false; } - return value; - } - } - if (value === Infinity || value === -Infinity || Number.isNaN(value) || typeof value === "function" || typeof value === "symbol") { - return "[" + value.toString() + "]"; - } - return value; - }; - }; - } -}); -var require_errors3 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/errors.js"(exports2) { - "use strict"; - var Annotate = require_annotate2(); - var Common = require_common3(); - var Template = require_template2(); - exports2.Report = class { - constructor(code2, value, local, flags, messages, state, prefs) { - this.code = code2; - this.flags = flags; - this.messages = messages; - this.path = state.path; - this.prefs = prefs; - this.state = state; - this.value = value; - this.message = null; - this.template = null; - this.local = local || {}; - this.local.label = exports2.label(this.flags, this.state, this.prefs, this.messages); - if (this.value !== void 0 && !this.local.hasOwnProperty("value")) { - this.local.value = this.value; - } - if (this.path.length) { - const key = this.path[this.path.length - 1]; - if (typeof key !== "object") { - this.local.key = key; + push(params, paramName, value); + if (code2 === 44) { + push(offers, extensionName, params); + params = /* @__PURE__ */ Object.create(null); + extensionName = void 0; + } + paramName = void 0; + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i2}`); } } } - _setTemplate(template) { - this.template = template; - if (!this.flags.label && this.path.length === 0) { - const localized = this._template(this.template, "root"); - if (localized) { - this.local.label = localized; - } - } + if (start === -1 || inQuotes || code2 === 32 || code2 === 9) { + throw new SyntaxError("Unexpected end of input"); } - toString() { - if (this.message) { - return this.message; - } - const code2 = this.code; - if (!this.prefs.errors.render) { - return this.code; - } - const template = this._template(this.template) || this._template(this.prefs.messages) || this._template(this.messages); - if (template === void 0) { - return `Error code "${code2}" is not defined, your custom type is missing the correct messages definition`; - } - this.message = template.render(this.value, this.state, this.prefs, this.local, { errors: this.prefs.errors, messages: [this.prefs.messages, this.messages] }); - if (!this.prefs.errors.label) { - this.message = this.message.replace(/^"" /, "").trim(); + if (end === -1) end = i2; + const token = header.slice(start, end); + if (extensionName === void 0) { + push(offers, token, params); + } else { + if (paramName === void 0) { + push(params, token, true); + } else if (mustUnescape) { + push(params, paramName, token.replace(/\\/g, "")); + } else { + push(params, paramName, token); } - return this.message; - } - _template(messages, code2) { - return exports2.template(this.value, messages, code2 || this.code, this.state, this.prefs); + push(offers, extensionName, params); } - }; - exports2.path = function(path8) { - let label = ""; - for (const segment of path8) { - if (typeof segment === "object") { - continue; - } - if (typeof segment === "string") { - if (label) { - label += "."; + return offers; + } + function format52(extensions) { + return Object.keys(extensions).map((extension) => { + let configurations = extensions[extension]; + if (!Array.isArray(configurations)) configurations = [configurations]; + return configurations.map((params) => { + return [extension].concat( + Object.keys(params).map((k) => { + let values = params[k]; + if (!Array.isArray(values)) values = [values]; + return values.map((v2) => v2 === true ? k : `${k}=${v2}`).join("; "); + }) + ).join("; "); + }).join(", "); + }).join(", "); + } + module14.exports = { format: format52, parse: parse62 }; + } +}); +var require_websocket = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/websocket.js"(exports2, module14) { + "use strict"; + var EventEmitter = __require2("node:events"); + var https = __require2("node:https"); + var http = __require2("node:http"); + var net = __require2("node:net"); + var tls = __require2("node:tls"); + var { randomBytes: randomBytes3, createHash } = __require2("node:crypto"); + var { Readable: Readable4 } = __require2("node:stream"); + var { URL: URL2 } = __require2("node:url"); + var PerMessageDeflate = require_permessage_deflate(); + var Receiver2 = require_receiver(); + var Sender2 = require_sender(); + var { + BINARY_TYPES, + EMPTY_BUFFER, + GUID, + kForOnEventAttribute, + kListener, + kStatusCode, + kWebSocket, + NOOP + } = require_constants2(); + var { + EventTarget: { addEventListener: addEventListener2, removeEventListener } + } = require_event_target(); + var { format: format52, parse: parse62 } = require_extension(); + var { toBuffer } = require_buffer_util(); + var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"]; + var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/; + var protocolVersions = [8, 13]; + var closeTimeout = 30 * 1e3; + var WebSocket3 = class _WebSocket extends EventEmitter { + /** + * Create a new `WebSocket`. + * + * @param {(String|URL)} address The URL to which to connect + * @param {(String|String[])} [protocols] The subprotocols + * @param {Object} [options] Connection options + */ + constructor(address, protocols, options2) { + super(); + this._binaryType = BINARY_TYPES[0]; + this._closeCode = 1006; + this._closeFrameReceived = false; + this._closeFrameSent = false; + this._closeMessage = EMPTY_BUFFER; + this._closeTimer = null; + this._extensions = {}; + this._paused = false; + this._protocol = ""; + this._readyState = _WebSocket.CONNECTING; + this._receiver = null; + this._sender = null; + this._socket = null; + if (address !== null) { + this._bufferedAmount = 0; + this._isServer = false; + this._redirects = 0; + if (protocols === void 0) { + protocols = []; + } else if (!Array.isArray(protocols)) { + if (typeof protocols === "object" && protocols !== null) { + options2 = protocols; + protocols = []; + } else { + protocols = [protocols]; + } } - label += segment; + initAsClient(this, address, protocols, options2); } else { - label += `[${segment}]`; + this._isServer = true; } } - return label; - }; - exports2.template = function(value, messages, code2, state, prefs) { - if (!messages) { - return; - } - if (Template.isTemplate(messages)) { - return code2 !== "root" ? messages : null; + /** + * This deviates from the WHATWG interface since ws doesn't support the + * required default "blob" type (instead we define a custom "nodebuffer" + * type). + * + * @type {String} + */ + get binaryType() { + return this._binaryType; } - let lang = prefs.errors.language; - if (Common.isResolvable(lang)) { - lang = lang.resolve(value, state, prefs); + set binaryType(type) { + if (!BINARY_TYPES.includes(type)) return; + this._binaryType = type; + if (this._receiver) this._receiver._binaryType = type; } - if (lang && messages[lang]) { - if (messages[lang][code2] !== void 0) { - return messages[lang][code2]; - } - if (messages[lang]["*"] !== void 0) { - return messages[lang]["*"]; - } + /** + * @type {Number} + */ + get bufferedAmount() { + if (!this._socket) return this._bufferedAmount; + return this._socket._writableState.length + this._sender._bufferedBytes; } - if (!messages[code2]) { - return messages["*"]; + /** + * @type {String} + */ + get extensions() { + return Object.keys(this._extensions).join(); } - return messages[code2]; - }; - exports2.label = function(flags, state, prefs, messages) { - if (!prefs.errors.label) { - return ""; + /** + * @type {Boolean} + */ + get isPaused() { + return this._paused; } - if (flags.label) { - return flags.label; + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onclose() { + return null; } - let path8 = state.path; - if (prefs.errors.label === "key" && state.path.length > 1) { - path8 = state.path.slice(-1); + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onerror() { + return null; } - const normalized = exports2.path(path8); - if (normalized) { - return normalized; + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onopen() { + return null; } - return exports2.template(null, prefs.messages, "root", state, prefs) || messages && exports2.template(null, messages, "root", state, prefs) || "value"; - }; - exports2.process = function(errors, original, prefs) { - if (!errors) { + /** + * @type {Function} + */ + /* istanbul ignore next */ + get onmessage() { return null; } - const { override, message, details } = exports2.details(errors); - if (override) { - return override; - } - if (prefs.errors.stack) { - return new exports2.ValidationError(message, details, original); - } - const limit = Error.stackTraceLimit; - Error.stackTraceLimit = 0; - const validationError = new exports2.ValidationError(message, details, original); - Error.stackTraceLimit = limit; - return validationError; - }; - exports2.details = function(errors, options2 = {}) { - let messages = []; - const details = []; - for (const item of errors) { - if (item instanceof Error) { - if (options2.override !== false) { - return { override: item }; - } - const message2 = item.toString(); - messages.push(message2); - details.push({ - message: message2, - type: "override", - context: { error: item } - }); - continue; - } - const message = item.toString(); - messages.push(message); - details.push({ - message, - path: item.path.filter((v2) => typeof v2 !== "object"), - type: item.code, - context: item.local - }); + /** + * @type {String} + */ + get protocol() { + return this._protocol; } - if (messages.length > 1) { - messages = [...new Set(messages)]; + /** + * @type {Number} + */ + get readyState() { + return this._readyState; } - return { message: messages.join(". "), details }; - }; - exports2.ValidationError = class extends Error { - constructor(message, details, original) { - super(message); - this._original = original; - this.details = details; - } - static isError(err) { - return err instanceof exports2.ValidationError; - } - }; - exports2.ValidationError.prototype.isJoi = true; - exports2.ValidationError.prototype.name = "ValidationError"; - exports2.ValidationError.prototype.annotate = Annotate.error; - } -}); -var require_ref2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/ref.js"(exports2) { - "use strict"; - var { assert: assert2, clone: clone2, reach } = require_lib(); - var Common = require_common3(); - var Template; - var internals = { - symbol: Symbol("ref"), - // Used to internally identify references (shared with other joi versions) - defaults: { - adjust: null, - in: false, - iterables: null, - map: null, - separator: ".", - type: "value" - } - }; - exports2.create = function(key, options2 = {}) { - assert2(typeof key === "string", "Invalid reference key:", key); - Common.assertOptions(options2, ["adjust", "ancestor", "in", "iterables", "map", "prefix", "render", "separator"]); - assert2(!options2.prefix || typeof options2.prefix === "object", "options.prefix must be of type object"); - const ref = Object.assign({}, internals.defaults, options2); - delete ref.prefix; - const separator = ref.separator; - const context = internals.context(key, separator, options2.prefix); - ref.type = context.type; - key = context.key; - if (ref.type === "value") { - if (context.root) { - assert2(!separator || key[0] !== separator, "Cannot specify relative path with root prefix"); - ref.ancestor = "root"; - if (!key) { - key = null; - } - } - if (separator && separator === key) { - key = null; - ref.ancestor = 0; - } else { - if (ref.ancestor !== void 0) { - assert2(!separator || !key || key[0] !== separator, "Cannot combine prefix with ancestor option"); - } else { - const [ancestor, slice] = internals.ancestor(key, separator); - if (slice) { - key = key.slice(slice); - if (key === "") { - key = null; - } - } - ref.ancestor = ancestor; - } - } + /** + * @type {String} + */ + get url() { + return this._url; } - ref.path = separator ? key === null ? [] : key.split(separator) : [key]; - return new internals.Ref(ref); - }; - exports2.in = function(key, options2 = {}) { - return exports2.create(key, { ...options2, in: true }); - }; - exports2.isRef = function(ref) { - return ref ? !!ref[Common.symbols.ref] : false; - }; - internals.Ref = class { - constructor(options2) { - assert2(typeof options2 === "object", "Invalid reference construction"); - Common.assertOptions(options2, [ - "adjust", - "ancestor", - "in", - "iterables", - "map", - "path", - "render", - "separator", - "type", - // Copied - "depth", - "key", - "root", - "display" - // Overridden - ]); - assert2([false, void 0].includes(options2.separator) || typeof options2.separator === "string" && options2.separator.length === 1, "Invalid separator"); - assert2(!options2.adjust || typeof options2.adjust === "function", "options.adjust must be a function"); - assert2(!options2.map || Array.isArray(options2.map), "options.map must be an array"); - assert2(!options2.map || !options2.adjust, "Cannot set both map and adjust options"); - Object.assign(this, internals.defaults, options2); - assert2(this.type === "value" || this.ancestor === void 0, "Non-value references cannot reference ancestors"); - if (Array.isArray(this.map)) { - this.map = new Map(this.map); - } - this.depth = this.path.length; - this.key = this.path.length ? this.path.join(this.separator) : null; - this.root = this.path[0]; - this.updateDisplay(); + /** + * Set up the socket and the internal resources. + * + * @param {(net.Socket|tls.Socket)} socket The network socket between the + * server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Object} options Options object + * @param {Function} [options.generateMask] The function used to generate the + * masking key + * @param {Number} [options.maxPayload=0] The maximum allowed message size + * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or + * not to skip UTF-8 validation for text and close messages + * @private + */ + setSocket(socket, head, options2) { + const receiver = new Receiver2({ + binaryType: this.binaryType, + extensions: this._extensions, + isServer: this._isServer, + maxPayload: options2.maxPayload, + skipUTF8Validation: options2.skipUTF8Validation + }); + this._sender = new Sender2(socket, this._extensions, options2.generateMask); + this._receiver = receiver; + this._socket = socket; + receiver[kWebSocket] = this; + socket[kWebSocket] = this; + receiver.on("conclude", receiverOnConclude); + receiver.on("drain", receiverOnDrain); + receiver.on("error", receiverOnError); + receiver.on("message", receiverOnMessage); + receiver.on("ping", receiverOnPing); + receiver.on("pong", receiverOnPong); + socket.setTimeout(0); + socket.setNoDelay(); + if (head.length > 0) socket.unshift(head); + socket.on("close", socketOnClose); + socket.on("data", socketOnData); + socket.on("end", socketOnEnd); + socket.on("error", socketOnError); + this._readyState = _WebSocket.OPEN; + this.emit("open"); } - resolve(value, state, prefs, local, options2 = {}) { - assert2(!this.in || options2.in, "Invalid in() reference usage"); - if (this.type === "global") { - return this._resolve(prefs.context, state, options2); - } - if (this.type === "local") { - return this._resolve(local, state, options2); - } - if (!this.ancestor) { - return this._resolve(value, state, options2); + /** + * Emit the `'close'` event. + * + * @private + */ + emitClose() { + if (!this._socket) { + this._readyState = _WebSocket.CLOSED; + this.emit("close", this._closeCode, this._closeMessage); + return; } - if (this.ancestor === "root") { - return this._resolve(state.ancestors[state.ancestors.length - 1], state, options2); + if (this._extensions[PerMessageDeflate.extensionName]) { + this._extensions[PerMessageDeflate.extensionName].cleanup(); } - assert2(this.ancestor <= state.ancestors.length, "Invalid reference exceeds the schema root:", this.display); - return this._resolve(state.ancestors[this.ancestor - 1], state, options2); + this._receiver.removeAllListeners(); + this._readyState = _WebSocket.CLOSED; + this.emit("close", this._closeCode, this._closeMessage); } - _resolve(target, state, options2) { - let resolved; - if (this.type === "value" && state.mainstay.shadow && options2.shadow !== false) { - resolved = state.mainstay.shadow.get(this.absolute(state)); - } - if (resolved === void 0) { - resolved = reach(target, this.path, { iterables: this.iterables, functions: true }); - } - if (this.adjust) { - resolved = this.adjust(resolved); + /** + * Start a closing handshake. + * + * +----------+ +-----------+ +----------+ + * - - -|ws.close()|-->|close frame|-->|ws.close()|- - - + * | +----------+ +-----------+ +----------+ | + * +----------+ +-----------+ | + * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING + * +----------+ +-----------+ | + * | | | +---+ | + * +------------------------+-->|fin| - - - - + * | +---+ | +---+ + * - - - - -|fin|<---------------------+ + * +---+ + * + * @param {Number} [code] Status code explaining why the connection is closing + * @param {(String|Buffer)} [data] The reason why the connection is + * closing + * @public + */ + close(code2, data) { + if (this.readyState === _WebSocket.CLOSED) return; + if (this.readyState === _WebSocket.CONNECTING) { + const msg = "WebSocket was closed before the connection was established"; + return abortHandshake(this, this._req, msg); } - if (this.map) { - const mapped = this.map.get(resolved); - if (mapped !== void 0) { - resolved = mapped; + if (this.readyState === _WebSocket.CLOSING) { + if (this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted)) { + this._socket.end(); } + return; } - if (state.mainstay) { - state.mainstay.tracer.resolve(state, this, resolved); - } - return resolved; - } - toString() { - return this.display; - } - absolute(state) { - return [...state.path.slice(0, -this.ancestor), ...this.path]; + this._readyState = _WebSocket.CLOSING; + this._sender.close(code2, data, !this._isServer, (err) => { + if (err) return; + this._closeFrameSent = true; + if (this._closeFrameReceived || this._receiver._writableState.errorEmitted) { + this._socket.end(); + } + }); + this._closeTimer = setTimeout( + this._socket.destroy.bind(this._socket), + closeTimeout + ); } - clone() { - return new internals.Ref(this); + /** + * Pause the socket. + * + * @public + */ + pause() { + if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) { + return; + } + this._paused = true; + this._socket.pause(); } - describe() { - const ref = { path: this.path }; - if (this.type !== "value") { - ref.type = this.type; + /** + * Send a ping. + * + * @param {*} [data] The data to send + * @param {Boolean} [mask] Indicates whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when the ping is sent + * @public + */ + ping(data, mask, cb) { + if (this.readyState === _WebSocket.CONNECTING) { + throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); } - if (this.separator !== ".") { - ref.separator = this.separator; + if (typeof data === "function") { + cb = data; + data = mask = void 0; + } else if (typeof mask === "function") { + cb = mask; + mask = void 0; } - if (this.type === "value" && this.ancestor !== 1) { - ref.ancestor = this.ancestor; + if (typeof data === "number") data = data.toString(); + if (this.readyState !== _WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; } - if (this.map) { - ref.map = [...this.map]; + if (mask === void 0) mask = !this._isServer; + this._sender.ping(data || EMPTY_BUFFER, mask, cb); + } + /** + * Send a pong. + * + * @param {*} [data] The data to send + * @param {Boolean} [mask] Indicates whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when the pong is sent + * @public + */ + pong(data, mask, cb) { + if (this.readyState === _WebSocket.CONNECTING) { + throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); } - for (const key of ["adjust", "iterables", "render"]) { - if (this[key] !== null && this[key] !== void 0) { - ref[key] = this[key]; - } + if (typeof data === "function") { + cb = data; + data = mask = void 0; + } else if (typeof mask === "function") { + cb = mask; + mask = void 0; } - if (this.in !== false) { - ref.in = true; + if (typeof data === "number") data = data.toString(); + if (this.readyState !== _WebSocket.OPEN) { + sendAfterClose(this, data, cb); + return; } - return { ref }; + if (mask === void 0) mask = !this._isServer; + this._sender.pong(data || EMPTY_BUFFER, mask, cb); } - updateDisplay() { - const key = this.key !== null ? this.key : ""; - if (this.type !== "value") { - this.display = `ref:${this.type}:${key}`; + /** + * Resume the socket. + * + * @public + */ + resume() { + if (this.readyState === _WebSocket.CONNECTING || this.readyState === _WebSocket.CLOSED) { return; } - if (!this.separator) { - this.display = `ref:${key}`; - return; + this._paused = false; + if (!this._receiver._writableState.needDrain) this._socket.resume(); + } + /** + * Send a data message. + * + * @param {*} data The message to send + * @param {Object} [options] Options object + * @param {Boolean} [options.binary] Specifies whether `data` is binary or + * text + * @param {Boolean} [options.compress] Specifies whether or not to compress + * `data` + * @param {Boolean} [options.fin=true] Specifies whether the fragment is the + * last one + * @param {Boolean} [options.mask] Specifies whether or not to mask `data` + * @param {Function} [cb] Callback which is executed when data is written out + * @public + */ + send(data, options2, cb) { + if (this.readyState === _WebSocket.CONNECTING) { + throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); } - if (!this.ancestor) { - this.display = `ref:${this.separator}${key}`; - return; + if (typeof options2 === "function") { + cb = options2; + options2 = {}; } - if (this.ancestor === "root") { - this.display = `ref:root:${key}`; + if (typeof data === "number") data = data.toString(); + if (this.readyState !== _WebSocket.OPEN) { + sendAfterClose(this, data, cb); return; } - if (this.ancestor === 1) { - this.display = `ref:${key || ".."}`; - return; + const opts = { + binary: typeof data !== "string", + mask: !this._isServer, + compress: true, + fin: true, + ...options2 + }; + if (!this._extensions[PerMessageDeflate.extensionName]) { + opts.compress = false; } - const lead = new Array(this.ancestor + 1).fill(this.separator).join(""); - this.display = `ref:${lead}${key || ""}`; - } - }; - internals.Ref.prototype[Common.symbols.ref] = true; - exports2.build = function(desc) { - desc = Object.assign({}, internals.defaults, desc); - if (desc.type === "value" && desc.ancestor === void 0) { - desc.ancestor = 1; + this._sender.send(data || EMPTY_BUFFER, opts, cb); } - return new internals.Ref(desc); - }; - internals.context = function(key, separator, prefix = {}) { - key = key.trim(); - if (prefix) { - const globalp = prefix.global === void 0 ? "$" : prefix.global; - if (globalp !== separator && key.startsWith(globalp)) { - return { key: key.slice(globalp.length), type: "global" }; - } - const local = prefix.local === void 0 ? "#" : prefix.local; - if (local !== separator && key.startsWith(local)) { - return { key: key.slice(local.length), type: "local" }; + /** + * Forcibly close the connection. + * + * @public + */ + terminate() { + if (this.readyState === _WebSocket.CLOSED) return; + if (this.readyState === _WebSocket.CONNECTING) { + const msg = "WebSocket was closed before the connection was established"; + return abortHandshake(this, this._req, msg); } - const root = prefix.root === void 0 ? "/" : prefix.root; - if (root !== separator && key.startsWith(root)) { - return { key: key.slice(root.length), type: "value", root: true }; + if (this._socket) { + this._readyState = _WebSocket.CLOSING; + this._socket.destroy(); } } - return { key, type: "value" }; - }; - internals.ancestor = function(key, separator) { - if (!separator) { - return [1, 0]; - } - if (key[0] !== separator) { - return [1, 0]; - } - if (key[1] !== separator) { - return [0, 1]; - } - let i2 = 2; - while (key[i2] === separator) { - ++i2; - } - return [i2 - 1, i2]; }; - exports2.toSibling = 0; - exports2.toParent = 1; - exports2.Manager = class { - constructor() { - this.refs = []; - } - register(source, target) { - if (!source) { - return; - } - target = target === void 0 ? exports2.toParent : target; - if (Array.isArray(source)) { - for (const ref of source) { - this.register(ref, target); + Object.defineProperty(WebSocket3, "CONNECTING", { + enumerable: true, + value: readyStates.indexOf("CONNECTING") + }); + Object.defineProperty(WebSocket3.prototype, "CONNECTING", { + enumerable: true, + value: readyStates.indexOf("CONNECTING") + }); + Object.defineProperty(WebSocket3, "OPEN", { + enumerable: true, + value: readyStates.indexOf("OPEN") + }); + Object.defineProperty(WebSocket3.prototype, "OPEN", { + enumerable: true, + value: readyStates.indexOf("OPEN") + }); + Object.defineProperty(WebSocket3, "CLOSING", { + enumerable: true, + value: readyStates.indexOf("CLOSING") + }); + Object.defineProperty(WebSocket3.prototype, "CLOSING", { + enumerable: true, + value: readyStates.indexOf("CLOSING") + }); + Object.defineProperty(WebSocket3, "CLOSED", { + enumerable: true, + value: readyStates.indexOf("CLOSED") + }); + Object.defineProperty(WebSocket3.prototype, "CLOSED", { + enumerable: true, + value: readyStates.indexOf("CLOSED") + }); + [ + "binaryType", + "bufferedAmount", + "extensions", + "isPaused", + "protocol", + "readyState", + "url" + ].forEach((property) => { + Object.defineProperty(WebSocket3.prototype, property, { enumerable: true }); + }); + ["open", "error", "close", "message"].forEach((method) => { + Object.defineProperty(WebSocket3.prototype, `on${method}`, { + enumerable: true, + get() { + for (const listener of this.listeners(method)) { + if (listener[kForOnEventAttribute]) return listener[kListener]; } - return; - } - if (Common.isSchema(source)) { - for (const item of source._refs.refs) { - if (item.ancestor - target >= 0) { - this.refs.push({ ancestor: item.ancestor - target, root: item.root }); + return null; + }, + set(handler) { + for (const listener of this.listeners(method)) { + if (listener[kForOnEventAttribute]) { + this.removeListener(method, listener); + break; } } - return; - } - if (exports2.isRef(source) && source.type === "value" && source.ancestor - target >= 0) { - this.refs.push({ ancestor: source.ancestor - target, root: source.root }); - } - Template = Template || require_template2(); - if (Template.isTemplate(source)) { - this.register(source.refs(), target); - } - } - get length() { - return this.refs.length; - } - clone() { - const copy2 = new exports2.Manager(); - copy2.refs = clone2(this.refs); - return copy2; - } - reset() { - this.refs = []; - } - roots() { - return this.refs.filter((ref) => !ref.ancestor).map((ref) => ref.root); - } - }; - } -}); -var require_template2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/template.js"(exports2, module14) { - "use strict"; - var { assert: assert2, clone: clone2, escapeHtml } = require_lib(); - var Formula = require_lib37(); - var Common = require_common3(); - var Errors = require_errors3(); - var Ref = require_ref2(); - var internals = { - symbol: Symbol("template"), - opens: new Array(1e3).join("\0"), - closes: new Array(1e3).join(""), - dateFormat: { - date: Date.prototype.toDateString, - iso: Date.prototype.toISOString, - string: Date.prototype.toString, - time: Date.prototype.toTimeString, - utc: Date.prototype.toUTCString - } - }; - module14.exports = exports2 = internals.Template = class { - constructor(source, options2) { - assert2(typeof source === "string", "Template source must be a string"); - assert2(!source.includes("\0") && !source.includes(""), "Template source cannot contain reserved control characters"); - this.source = source; - this.rendered = source; - this._template = null; - if (options2) { - const { functions, ...opts } = options2; - this._settings = Object.keys(opts).length ? clone2(opts) : void 0; - this._functions = functions; - if (this._functions) { - assert2(Object.keys(this._functions).every((key) => typeof key === "string"), "Functions keys must be strings"); - assert2(Object.values(this._functions).every((key) => typeof key === "function"), "Functions values must be functions"); - } - } else { - this._settings = void 0; - this._functions = void 0; - } - this._parse(); - } - _parse() { - if (!this.source.includes("{")) { - return; - } - const encoded = internals.encode(this.source); - const parts = internals.split(encoded); - let refs = false; - const processed = []; - const head = parts.shift(); - if (head) { - processed.push(head); - } - for (const part of parts) { - const raw = part[0] !== "{"; - const ender = raw ? "}" : "}}"; - const end = part.indexOf(ender); - if (end === -1 || // Ignore non-matching closing - part[1] === "{") { - processed.push(`{${internals.decode(part)}`); - continue; - } - let variable = part.slice(raw ? 0 : 1, end); - const wrapped = variable[0] === ":"; - if (wrapped) { - variable = variable.slice(1); - } - const dynamic = this._ref(internals.decode(variable), { raw, wrapped }); - processed.push(dynamic); - if (typeof dynamic !== "string") { - refs = true; - } - const rest = part.slice(end + ender.length); - if (rest) { - processed.push(internals.decode(rest)); - } - } - if (!refs) { - this.rendered = processed.join(""); - return; + if (typeof handler !== "function") return; + this.addEventListener(method, handler, { + [kForOnEventAttribute]: true + }); } - this._template = processed; - } - static date(date3, prefs) { - return internals.dateFormat[prefs.dateFormat].call(date3); + }); + }); + WebSocket3.prototype.addEventListener = addEventListener2; + WebSocket3.prototype.removeEventListener = removeEventListener; + module14.exports = WebSocket3; + function initAsClient(websocket, address, protocols, options2) { + const opts = { + protocolVersion: protocolVersions[1], + maxPayload: 100 * 1024 * 1024, + skipUTF8Validation: false, + perMessageDeflate: true, + followRedirects: false, + maxRedirects: 10, + ...options2, + createConnection: void 0, + socketPath: void 0, + hostname: void 0, + protocol: void 0, + timeout: void 0, + method: void 0, + host: void 0, + path: void 0, + port: void 0 + }; + if (!protocolVersions.includes(opts.protocolVersion)) { + throw new RangeError( + `Unsupported protocol version: ${opts.protocolVersion} (supported versions: ${protocolVersions.join(", ")})` + ); } - describe(options2 = {}) { - if (!this._settings && options2.compact) { - return this.source; - } - const desc = { template: this.source }; - if (this._settings) { - desc.options = this._settings; - } - if (this._functions) { - desc.functions = this._functions; + let parsedUrl; + if (address instanceof URL2) { + parsedUrl = address; + websocket._url = address.href; + } else { + try { + parsedUrl = new URL2(address); + } catch (e2) { + throw new SyntaxError(`Invalid URL: ${address}`); } - return desc; - } - static build(desc) { - return new internals.Template(desc.template, desc.options || desc.functions ? { ...desc.options, functions: desc.functions } : void 0); - } - isDynamic() { - return !!this._template; + websocket._url = address; } - static isTemplate(template) { - return template ? !!template[Common.symbols.template] : false; + const isSecure = parsedUrl.protocol === "wss:"; + const isUnixSocket = parsedUrl.protocol === "ws+unix:"; + let invalidURLMessage; + if (parsedUrl.protocol !== "ws:" && !isSecure && !isUnixSocket) { + invalidURLMessage = `The URL's protocol must be one of "ws:", "wss:", or "ws+unix:"`; + } else if (isUnixSocket && !parsedUrl.pathname) { + invalidURLMessage = "The URL's pathname is empty"; + } else if (parsedUrl.hash) { + invalidURLMessage = "The URL contains a fragment identifier"; } - refs() { - if (!this._template) { + if (invalidURLMessage) { + const err = new SyntaxError(invalidURLMessage); + if (websocket._redirects === 0) { + throw err; + } else { + emitErrorAndClose(websocket, err); return; } - const refs = []; - for (const part of this._template) { - if (typeof part !== "string") { - refs.push(...part.refs); - } - } - return refs; - } - resolve(value, state, prefs, local) { - if (this._template && this._template.length === 1) { - return this._part( - this._template[0], - /* context -> [*/ - value, - state, - prefs, - local, - {} - /*] */ - ); - } - return this.render(value, state, prefs, local); } - _part(part, ...args) { - if (part.ref) { - return part.ref.resolve(...args); - } - return part.formula.evaluate(args); + const defaultPort = isSecure ? 443 : 80; + const key = randomBytes3(16).toString("base64"); + const get2 = isSecure ? https.get : http.get; + const protocolSet = /* @__PURE__ */ new Set(); + let perMessageDeflate; + opts.createConnection = isSecure ? tlsConnect : netConnect; + opts.defaultPort = opts.defaultPort || defaultPort; + opts.port = parsedUrl.port || defaultPort; + opts.host = parsedUrl.hostname.startsWith("[") ? parsedUrl.hostname.slice(1, -1) : parsedUrl.hostname; + opts.headers = { + "Sec-WebSocket-Version": opts.protocolVersion, + "Sec-WebSocket-Key": key, + Connection: "Upgrade", + Upgrade: "websocket", + ...opts.headers + }; + opts.path = parsedUrl.pathname + parsedUrl.search; + opts.timeout = opts.handshakeTimeout; + if (opts.perMessageDeflate) { + perMessageDeflate = new PerMessageDeflate( + opts.perMessageDeflate !== true ? opts.perMessageDeflate : {}, + false, + opts.maxPayload + ); + opts.headers["Sec-WebSocket-Extensions"] = format52({ + [PerMessageDeflate.extensionName]: perMessageDeflate.offer() + }); } - render(value, state, prefs, local, options2 = {}) { - if (!this.isDynamic()) { - return this.rendered; - } - const parts = []; - for (const part of this._template) { - if (typeof part === "string") { - parts.push(part); - } else { - const rendered = this._part( - part, - /* context -> [*/ - value, - state, - prefs, - local, - options2 - /*] */ + if (protocols.length) { + for (const protocol of protocols) { + if (typeof protocol !== "string" || !subprotocolRegex.test(protocol) || protocolSet.has(protocol)) { + throw new SyntaxError( + "An invalid or duplicated subprotocol was specified" ); - const string3 = internals.stringify(rendered, value, state, prefs, local, options2); - if (string3 !== void 0) { - const result = part.raw || (options2.errors && options2.errors.escapeHtml) === false ? string3 : escapeHtml(string3); - parts.push(internals.wrap(result, part.wrapped && prefs.errors.wrap.label)); - } - } - } - return parts.join(""); - } - _ref(content, { raw, wrapped }) { - const refs = []; - const reference = (variable) => { - const ref = Ref.create(variable, this._settings); - refs.push(ref); - return (context) => { - const resolved = ref.resolve(...context); - return resolved !== void 0 ? resolved : null; - }; - }; - try { - const functions = this._functions ? { ...internals.functions, ...this._functions } : internals.functions; - var formula = new Formula.Parser(content, { reference, functions, constants: internals.constants }); - } catch (err) { - err.message = `Invalid template variable "${content}" fails due to: ${err.message}`; - throw err; - } - if (formula.single) { - if (formula.single.type === "reference") { - const ref = refs[0]; - return { ref, raw, refs, wrapped: wrapped || ref.type === "local" && ref.key === "label" }; } - return internals.stringify(formula.single.value); + protocolSet.add(protocol); } - return { formula, raw, refs }; - } - toString() { - return this.source; + opts.headers["Sec-WebSocket-Protocol"] = protocols.join(","); } - }; - internals.Template.prototype[Common.symbols.template] = true; - internals.Template.prototype.isImmutable = true; - internals.encode = function(string3) { - return string3.replace(/\\(\{+)/g, ($0, $1) => { - return internals.opens.slice(0, $1.length); - }).replace(/\\(\}+)/g, ($0, $1) => { - return internals.closes.slice(0, $1.length); - }); - }; - internals.decode = function(string3) { - return string3.replace(/\u0000/g, "{").replace(/\u0001/g, "}"); - }; - internals.split = function(string3) { - const parts = []; - let current = ""; - for (let i2 = 0; i2 < string3.length; ++i2) { - const char = string3[i2]; - if (char === "{") { - let next = ""; - while (i2 + 1 < string3.length && string3[i2 + 1] === "{") { - next += "{"; - ++i2; - } - parts.push(current); - current = next; + if (opts.origin) { + if (opts.protocolVersion < 13) { + opts.headers["Sec-WebSocket-Origin"] = opts.origin; } else { - current += char; - } - } - parts.push(current); - return parts; - }; - internals.wrap = function(value, ends) { - if (!ends) { - return value; - } - if (ends.length === 1) { - return `${ends}${value}${ends}`; - } - return `${ends[0]}${value}${ends[1]}`; - }; - internals.stringify = function(value, original, state, prefs, local, options2 = {}) { - const type = typeof value; - const wrap2 = prefs && prefs.errors && prefs.errors.wrap || {}; - let skipWrap = false; - if (Ref.isRef(value) && value.render) { - skipWrap = value.in; - value = value.resolve(original, state, prefs, local, { in: value.in, ...options2 }); - } - if (value === null) { - return "null"; - } - if (type === "string") { - return internals.wrap(value, options2.arrayItems && wrap2.string); - } - if (type === "number" || type === "function" || type === "symbol") { - return value.toString(); - } - if (type !== "object") { - return JSON.stringify(value); - } - if (value instanceof Date) { - return internals.Template.date(value, prefs); - } - if (value instanceof Map) { - const pairs = []; - for (const [key, sym] of value.entries()) { - pairs.push(`${key.toString()} -> ${sym.toString()}`); + opts.headers.Origin = opts.origin; } - value = pairs; } - if (!Array.isArray(value)) { - return value.toString(); + if (parsedUrl.username || parsedUrl.password) { + opts.auth = `${parsedUrl.username}:${parsedUrl.password}`; } - const values = []; - for (const item of value) { - values.push(internals.stringify(item, original, state, prefs, local, { arrayItems: true, ...options2 })); + if (isUnixSocket) { + const parts = opts.path.split(":"); + opts.socketPath = parts[0]; + opts.path = parts[1]; } - return internals.wrap(values.join(", "), !skipWrap && wrap2.array); - }; - internals.constants = { - true: true, - false: false, - null: null, - second: 1e3, - minute: 60 * 1e3, - hour: 60 * 60 * 1e3, - day: 24 * 60 * 60 * 1e3 - }; - internals.functions = { - if(condition, then, otherwise) { - return condition ? then : otherwise; - }, - length(item) { - if (typeof item === "string") { - return item.length; - } - if (!item || typeof item !== "object") { - return null; - } - if (Array.isArray(item)) { - return item.length; - } - return Object.keys(item).length; - }, - msg(code2) { - const [value, state, prefs, local, options2] = this; - const messages = options2.messages; - if (!messages) { - return ""; - } - const template = Errors.template(value, messages[0], code2, state, prefs) || Errors.template(value, messages[1], code2, state, prefs); - if (!template) { - return ""; - } - return template.render(value, state, prefs, local, options2); - }, - number(value) { - if (typeof value === "number") { - return value; - } - if (typeof value === "string") { - return parseFloat(value); - } - if (typeof value === "boolean") { - return value ? 1 : 0; + if (opts.followRedirects) { + if (websocket._redirects === 0) { + websocket._originalHost = parsedUrl.host; + const headers = options2 && options2.headers; + options2 = { ...options2, headers: {} }; + if (headers) { + for (const [key2, value] of Object.entries(headers)) { + options2.headers[key2.toLowerCase()] = value; + } + } + } else if (parsedUrl.host !== websocket._originalHost) { + delete opts.headers.authorization; + delete opts.headers.cookie; + delete opts.headers.host; + opts.auth = void 0; } - if (value instanceof Date) { - return value.getTime(); + if (opts.auth && !options2.headers.authorization) { + options2.headers.authorization = "Basic " + Buffer.from(opts.auth).toString("base64"); } - return null; - } - }; - } -}); -var require_messages2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/messages.js"(exports2) { - "use strict"; - var { assert: assert2, clone: clone2 } = require_lib(); - var Template = require_template2(); - exports2.compile = function(messages, target) { - if (typeof messages === "string") { - assert2(!target, "Cannot set single message string"); - return new Template(messages); } - if (Template.isTemplate(messages)) { - assert2(!target, "Cannot set single message template"); - return messages; + let req = websocket._req = get2(opts); + if (opts.timeout) { + req.on("timeout", () => { + abortHandshake(websocket, req, "Opening handshake has timed out"); + }); } - assert2(typeof messages === "object" && !Array.isArray(messages), "Invalid message options"); - target = target ? clone2(target) : {}; - for (let code2 in messages) { - const message = messages[code2]; - if (code2 === "root" || Template.isTemplate(message)) { - target[code2] = message; - continue; + req.on("error", (err) => { + if (req === null || req.aborted) return; + req = websocket._req = null; + emitErrorAndClose(websocket, err); + }); + req.on("response", (res) => { + const location = res.headers.location; + const statusCode = res.statusCode; + if (location && opts.followRedirects && statusCode >= 300 && statusCode < 400) { + if (++websocket._redirects > opts.maxRedirects) { + abortHandshake(websocket, req, "Maximum redirects exceeded"); + return; + } + req.abort(); + let addr; + try { + addr = new URL2(location, address); + } catch (e2) { + const err = new SyntaxError(`Invalid URL: ${location}`); + emitErrorAndClose(websocket, err); + return; + } + initAsClient(websocket, addr, protocols, options2); + } else if (!websocket.emit("unexpected-response", req, res)) { + abortHandshake( + websocket, + req, + `Unexpected server response: ${res.statusCode}` + ); } - if (typeof message === "string") { - target[code2] = new Template(message); - continue; + }); + req.on("upgrade", (res, socket, head) => { + websocket.emit("upgrade", res); + if (websocket.readyState !== WebSocket3.CONNECTING) return; + req = websocket._req = null; + const digest = createHash("sha1").update(key + GUID).digest("base64"); + if (res.headers["sec-websocket-accept"] !== digest) { + abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header"); + return; } - assert2(typeof message === "object" && !Array.isArray(message), "Invalid message for", code2); - const language = code2; - target[language] = target[language] || {}; - for (code2 in message) { - const localized = message[code2]; - if (code2 === "root" || Template.isTemplate(localized)) { - target[language][code2] = localized; - continue; + const serverProt = res.headers["sec-websocket-protocol"]; + let protError; + if (serverProt !== void 0) { + if (!protocolSet.size) { + protError = "Server sent a subprotocol but none was requested"; + } else if (!protocolSet.has(serverProt)) { + protError = "Server sent an invalid subprotocol"; } - assert2(typeof localized === "string", "Invalid message for", code2, "in", language); - target[language][code2] = new Template(localized); - } - } - return target; - }; - exports2.decompile = function(messages) { - const target = {}; - for (let code2 in messages) { - const message = messages[code2]; - if (code2 === "root") { - target.root = message; - continue; + } else if (protocolSet.size) { + protError = "Server sent no subprotocol"; } - if (Template.isTemplate(message)) { - target[code2] = message.describe({ compact: true }); - continue; + if (protError) { + abortHandshake(websocket, socket, protError); + return; } - const language = code2; - target[language] = {}; - for (code2 in message) { - const localized = message[code2]; - if (code2 === "root") { - target[language].root = localized; - continue; + if (serverProt) websocket._protocol = serverProt; + const secWebSocketExtensions = res.headers["sec-websocket-extensions"]; + if (secWebSocketExtensions !== void 0) { + if (!perMessageDeflate) { + const message = "Server sent a Sec-WebSocket-Extensions header but no extension was requested"; + abortHandshake(websocket, socket, message); + return; + } + let extensions; + try { + extensions = parse62(secWebSocketExtensions); + } catch (err) { + const message = "Invalid Sec-WebSocket-Extensions header"; + abortHandshake(websocket, socket, message); + return; + } + const extensionNames = Object.keys(extensions); + if (extensionNames.length !== 1 || extensionNames[0] !== PerMessageDeflate.extensionName) { + const message = "Server indicated an extension that was not requested"; + abortHandshake(websocket, socket, message); + return; + } + try { + perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]); + } catch (err) { + const message = "Invalid Sec-WebSocket-Extensions header"; + abortHandshake(websocket, socket, message); + return; } - target[language][code2] = localized.describe({ compact: true }); + websocket._extensions[PerMessageDeflate.extensionName] = perMessageDeflate; } + websocket.setSocket(socket, head, { + generateMask: opts.generateMask, + maxPayload: opts.maxPayload, + skipUTF8Validation: opts.skipUTF8Validation + }); + }); + } + function emitErrorAndClose(websocket, err) { + websocket._readyState = WebSocket3.CLOSING; + websocket.emit("error", err); + websocket.emitClose(); + } + function netConnect(options2) { + options2.path = options2.socketPath; + return net.connect(options2); + } + function tlsConnect(options2) { + options2.path = void 0; + if (!options2.servername && options2.servername !== "") { + options2.servername = net.isIP(options2.host) ? "" : options2.host; } - return target; - }; - exports2.merge = function(base2, extended) { - if (!base2) { - return exports2.compile(extended); - } - if (!extended) { - return base2; - } - if (typeof extended === "string") { - return new Template(extended); - } - if (Template.isTemplate(extended)) { - return extended; - } - const target = clone2(base2); - for (let code2 in extended) { - const message = extended[code2]; - if (code2 === "root" || Template.isTemplate(message)) { - target[code2] = message; - continue; - } - if (typeof message === "string") { - target[code2] = new Template(message); - continue; - } - assert2(typeof message === "object" && !Array.isArray(message), "Invalid message for", code2); - const language = code2; - target[language] = target[language] || {}; - for (code2 in message) { - const localized = message[code2]; - if (code2 === "root" || Template.isTemplate(localized)) { - target[language][code2] = localized; - continue; - } - assert2(typeof localized === "string", "Invalid message for", code2, "in", language); - target[language][code2] = new Template(localized); + return tls.connect(options2); + } + function abortHandshake(websocket, stream, message) { + websocket._readyState = WebSocket3.CLOSING; + const err = new Error(message); + Error.captureStackTrace(err, abortHandshake); + if (stream.setHeader) { + stream.abort(); + if (stream.socket && !stream.socket.destroyed) { + stream.socket.destroy(); } + stream.once("abort", websocket.emitClose.bind(websocket)); + websocket.emit("error", err); + } else { + stream.destroy(err); + stream.once("error", websocket.emit.bind(websocket, "error")); + stream.once("close", websocket.emitClose.bind(websocket)); } - return target; - }; - } -}); -var require_common3 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/common.js"(exports2) { - "use strict"; - var { assert: Assert, AssertError } = require_lib(); - var Pkg = require_package7(); - var Messages; - var Schemas; - var internals = { - isoDate: /^(?:[-+]\d{2})?(?:\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?![T]$|[T][\d]+Z$)(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24\:?00)(?:[.,]\d+(?!:))?)(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[Z]|(?:[+-])(?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?)?$/ - }; - exports2.version = Pkg.version; - exports2.defaults = { - abortEarly: true, - allowUnknown: false, - artifacts: false, - cache: true, - context: null, - convert: true, - dateFormat: "iso", - errors: { - escapeHtml: false, - label: "path", - language: null, - render: true, - stack: false, - wrap: { - label: '"', - array: "[]" - } - }, - externals: true, - messages: {}, - nonEnumerables: false, - noDefaults: false, - presence: "optional", - skipFunctions: false, - stripUnknown: false, - warnings: false - }; - exports2.symbols = { - any: Symbol.for("@hapi/joi/schema"), - // Used to internally identify any-based types (shared with other joi versions) - arraySingle: Symbol("arraySingle"), - deepDefault: Symbol("deepDefault"), - errors: Symbol("errors"), - literal: Symbol("literal"), - override: Symbol("override"), - parent: Symbol("parent"), - prefs: Symbol("prefs"), - ref: Symbol("ref"), - template: Symbol("template"), - values: Symbol("values") - }; - exports2.assertOptions = function(options2, keys, name = "Options") { - Assert(options2 && typeof options2 === "object" && !Array.isArray(options2), "Options must be of type object"); - const unknownKeys = Object.keys(options2).filter((k) => !keys.includes(k)); - Assert(unknownKeys.length === 0, `${name} contain unknown keys: ${unknownKeys}`); - }; - exports2.checkPreferences = function(prefs) { - Schemas = Schemas || require_schemas2(); - const result = Schemas.preferences.validate(prefs); - if (result.error) { - throw new AssertError([result.error.details[0].message]); - } - }; - exports2.compare = function(a, b, operator) { - switch (operator) { - case "=": - return a === b; - case ">": - return a > b; - case "<": - return a < b; - case ">=": - return a >= b; - case "<=": - return a <= b; - } - }; - exports2.default = function(value, defaultValue) { - return value === void 0 ? defaultValue : value; - }; - exports2.isIsoDate = function(date3) { - return internals.isoDate.test(date3); - }; - exports2.isNumber = function(value) { - return typeof value === "number" && !isNaN(value); - }; - exports2.isResolvable = function(obj) { - if (!obj) { - return false; + } + function sendAfterClose(websocket, data, cb) { + if (data) { + const length2 = toBuffer(data).length; + if (websocket._socket) websocket._sender._bufferedBytes += length2; + else websocket._bufferedAmount += length2; } - return obj[exports2.symbols.ref] || obj[exports2.symbols.template]; - }; - exports2.isSchema = function(schema, options2 = {}) { - const any = schema && schema[exports2.symbols.any]; - if (!any) { - return false; + if (cb) { + const err = new Error( + `WebSocket is not open: readyState ${websocket.readyState} (${readyStates[websocket.readyState]})` + ); + cb(err); } - Assert(options2.legacy || any.version === exports2.version, "Cannot mix different versions of joi schemas"); - return true; - }; - exports2.isValues = function(obj) { - return obj[exports2.symbols.values]; - }; - exports2.limit = function(value) { - return Number.isSafeInteger(value) && value >= 0; - }; - exports2.preferences = function(target, source) { - Messages = Messages || require_messages2(); - target = target || {}; - source = source || {}; - const merged = Object.assign({}, target, source); - if (source.errors && target.errors) { - merged.errors = Object.assign({}, target.errors, source.errors); - merged.errors.wrap = Object.assign({}, target.errors.wrap, source.errors.wrap); + } + function receiverOnConclude(code2, reason) { + const websocket = this[kWebSocket]; + websocket._closeFrameReceived = true; + websocket._closeMessage = reason; + websocket._closeCode = code2; + if (websocket._socket[kWebSocket] === void 0) return; + websocket._socket.removeListener("data", socketOnData); + process.nextTick(resume, websocket._socket); + if (code2 === 1005) websocket.close(); + else websocket.close(code2, reason); + } + function receiverOnDrain() { + const websocket = this[kWebSocket]; + if (!websocket.isPaused) websocket._socket.resume(); + } + function receiverOnError(err) { + const websocket = this[kWebSocket]; + if (websocket._socket[kWebSocket] !== void 0) { + websocket._socket.removeListener("data", socketOnData); + process.nextTick(resume, websocket._socket); + websocket.close(err[kStatusCode]); } - if (source.messages) { - merged.messages = Messages.compile(source.messages, target.messages); + websocket.emit("error", err); + } + function receiverOnFinish() { + this[kWebSocket].emitClose(); + } + function receiverOnMessage(data, isBinary) { + this[kWebSocket].emit("message", data, isBinary); + } + function receiverOnPing(data) { + const websocket = this[kWebSocket]; + websocket.pong(data, !websocket._isServer, NOOP); + websocket.emit("ping", data); + } + function receiverOnPong(data) { + this[kWebSocket].emit("pong", data); + } + function resume(stream) { + stream.resume(); + } + function socketOnClose() { + const websocket = this[kWebSocket]; + this.removeListener("close", socketOnClose); + this.removeListener("data", socketOnData); + this.removeListener("end", socketOnEnd); + websocket._readyState = WebSocket3.CLOSING; + let chunk; + if (!this._readableState.endEmitted && !websocket._closeFrameReceived && !websocket._receiver._writableState.errorEmitted && (chunk = websocket._socket.read()) !== null) { + websocket._receiver.write(chunk); } - delete merged[exports2.symbols.prefs]; - return merged; - }; - exports2.tryWithPath = function(fn, key, options2 = {}) { - try { - return fn(); - } catch (err) { - if (err.path !== void 0) { - err.path = key + "." + err.path; - } else { - err.path = key; - } - if (options2.append) { - err.message = `${err.message} (${err.path})`; - } - throw err; + websocket._receiver.end(); + this[kWebSocket] = void 0; + clearTimeout(websocket._closeTimer); + if (websocket._receiver._writableState.finished || websocket._receiver._writableState.errorEmitted) { + websocket.emitClose(); + } else { + websocket._receiver.on("error", receiverOnFinish); + websocket._receiver.on("finish", receiverOnFinish); } - }; - exports2.validateArg = function(value, label, { assert: assert2, message }) { - if (exports2.isSchema(assert2)) { - const result = assert2.validate(value); - if (!result.error) { - return; - } - return result.error.message; - } else if (!assert2(value)) { - return label ? `${label} ${message}` : message; + } + function socketOnData(chunk) { + if (!this[kWebSocket]._receiver.write(chunk)) { + this.pause(); } - }; - exports2.verifyFlat = function(args, method) { - for (const arg of args) { - Assert(!Array.isArray(arg), "Method no longer accepts array arguments:", method); + } + function socketOnEnd() { + const websocket = this[kWebSocket]; + websocket._readyState = WebSocket3.CLOSING; + websocket._receiver.end(); + this.end(); + } + function socketOnError() { + const websocket = this[kWebSocket]; + this.removeListener("error", socketOnError); + this.on("error", NOOP); + if (websocket) { + websocket._readyState = WebSocket3.CLOSING; + this.destroy(); } - }; + } } }); -var require_cache2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/cache.js"(exports2) { - "use strict"; - var { assert: assert2, clone: clone2 } = require_lib(); - var Common = require_common3(); - var internals = { - max: 1e3, - supported: /* @__PURE__ */ new Set(["undefined", "boolean", "number", "string"]) - }; - exports2.provider = { - provision(options2) { - return new internals.Cache(options2); - } - }; - internals.Cache = class { - constructor(options2 = {}) { - Common.assertOptions(options2, ["max"]); - assert2(options2.max === void 0 || options2.max && options2.max > 0 && isFinite(options2.max), "Invalid max cache size"); - this._max = options2.max || internals.max; - this._map = /* @__PURE__ */ new Map(); - this._list = new internals.List(); - } - get length() { - return this._map.size; - } - set(key, value) { - if (key !== null && !internals.supported.has(typeof key)) { - return; - } - let node = this._map.get(key); - if (node) { - node.value = value; - this._list.first(node); - return; - } - node = this._list.unshift({ key, value }); - this._map.set(key, node); - this._compact(); - } - get(key) { - const node = this._map.get(key); - if (node) { - this._list.first(node); - return clone2(node.value); - } - } - _compact() { - if (this._map.size > this._max) { - const node = this._list.pop(); - this._map.delete(node.key); - } - } - }; - internals.List = class { - constructor() { - this.tail = null; - this.head = null; - } - unshift(node) { - node.next = null; - node.prev = this.head; - if (this.head) { - this.head.next = node; - } - this.head = node; - if (!this.tail) { - this.tail = node; - } - return node; - } - first(node) { - if (node === this.head) { - return; +var require_subprotocol = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/subprotocol.js"(exports2, module14) { + "use strict"; + var { tokenChars } = require_validation(); + function parse62(header) { + const protocols = /* @__PURE__ */ new Set(); + let start = -1; + let end = -1; + let i2 = 0; + for (i2; i2 < header.length; i2++) { + const code2 = header.charCodeAt(i2); + if (end === -1 && tokenChars[code2] === 1) { + if (start === -1) start = i2; + } else if (i2 !== 0 && (code2 === 32 || code2 === 9)) { + if (end === -1 && start !== -1) end = i2; + } else if (code2 === 44) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i2}`); + } + if (end === -1) end = i2; + const protocol2 = header.slice(start, end); + if (protocols.has(protocol2)) { + throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`); + } + protocols.add(protocol2); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i2}`); } - this._remove(node); - this.unshift(node); } - pop() { - return this._remove(this.tail); + if (start === -1 || end !== -1) { + throw new SyntaxError("Unexpected end of input"); } - _remove(node) { - const { next, prev } = node; - next.prev = prev; - if (prev) { - prev.next = next; - } - if (node === this.tail) { - this.tail = next; - } - node.prev = null; - node.next = null; - return node; + const protocol = header.slice(start, i2); + if (protocols.has(protocol)) { + throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`); } - }; + protocols.add(protocol); + return protocols; + } + module14.exports = { parse: parse62 }; } }); -var require_compile2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/compile.js"(exports2) { +var require_websocket_server = __commonJS({ + "node_modules/.deno/ws@8.5.0/node_modules/ws/lib/websocket-server.js"(exports2, module14) { "use strict"; - var { assert: assert2 } = require_lib(); - var Common = require_common3(); - var Ref = require_ref2(); - var internals = {}; - exports2.schema = function(Joi2, config2, options2 = {}) { - Common.assertOptions(options2, ["appendPath", "override"]); - try { - return internals.schema(Joi2, config2, options2); - } catch (err) { - if (options2.appendPath && err.path !== void 0) { - err.message = `${err.message} (${err.path})`; + var EventEmitter = __require2("node:events"); + var http = __require2("node:http"); + var https = __require2("node:https"); + var net = __require2("node:net"); + var tls = __require2("node:tls"); + var { createHash } = __require2("node:crypto"); + var extension = require_extension(); + var PerMessageDeflate = require_permessage_deflate(); + var subprotocol = require_subprotocol(); + var WebSocket3 = require_websocket(); + var { GUID, kWebSocket } = require_constants2(); + var keyRegex = /^[+/0-9A-Za-z]{22}==$/; + var RUNNING = 0; + var CLOSING = 1; + var CLOSED = 2; + var WebSocketServer2 = class extends EventEmitter { + /** + * Create a `WebSocketServer` instance. + * + * @param {Object} options Configuration options + * @param {Number} [options.backlog=511] The maximum length of the queue of + * pending connections + * @param {Boolean} [options.clientTracking=true] Specifies whether or not to + * track clients + * @param {Function} [options.handleProtocols] A hook to handle protocols + * @param {String} [options.host] The hostname where to bind the server + * @param {Number} [options.maxPayload=104857600] The maximum allowed message + * size + * @param {Boolean} [options.noServer=false] Enable no server mode + * @param {String} [options.path] Accept only connections matching this path + * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable + * permessage-deflate + * @param {Number} [options.port] The port where to bind the server + * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S + * server to use + * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or + * not to skip UTF-8 validation for text and close messages + * @param {Function} [options.verifyClient] A hook to reject connections + * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket` + * class to use. It must be the `WebSocket` class or class that extends it + * @param {Function} [callback] A listener for the `listening` event + */ + constructor(options2, callback) { + super(); + options2 = { + maxPayload: 100 * 1024 * 1024, + skipUTF8Validation: false, + perMessageDeflate: false, + handleProtocols: null, + clientTracking: true, + verifyClient: null, + noServer: false, + backlog: null, + // use default (511 as implemented in net.js) + server: null, + host: null, + path: null, + port: null, + WebSocket: WebSocket3, + ...options2 + }; + if (options2.port == null && !options2.server && !options2.noServer || options2.port != null && (options2.server || options2.noServer) || options2.server && options2.noServer) { + throw new TypeError( + 'One and only one of the "port", "server", or "noServer" options must be specified' + ); } - throw err; - } - }; - internals.schema = function(Joi2, config2, options2) { - assert2(config2 !== void 0, "Invalid undefined schema"); - if (Array.isArray(config2)) { - assert2(config2.length, "Invalid empty array schema"); - if (config2.length === 1) { - config2 = config2[0]; + if (options2.port != null) { + this._server = http.createServer((req, res) => { + const body = http.STATUS_CODES[426]; + res.writeHead(426, { + "Content-Length": body.length, + "Content-Type": "text/plain" + }); + res.end(body); + }); + this._server.listen( + options2.port, + options2.host, + options2.backlog, + callback + ); + } else if (options2.server) { + this._server = options2.server; } - } - const valid = (base2, ...values) => { - if (options2.override !== false) { - return base2.valid(Joi2.override, ...values); + if (this._server) { + const emitConnection = this.emit.bind(this, "connection"); + this._removeListeners = addListeners(this._server, { + listening: this.emit.bind(this, "listening"), + error: this.emit.bind(this, "error"), + upgrade: (req, socket, head) => { + this.handleUpgrade(req, socket, head, emitConnection); + } + }); } - return base2.valid(...values); - }; - if (internals.simple(config2)) { - return valid(Joi2, config2); - } - if (typeof config2 === "function") { - return Joi2.custom(config2); - } - assert2(typeof config2 === "object", "Invalid schema content:", typeof config2); - if (Common.isResolvable(config2)) { - return valid(Joi2, config2); + if (options2.perMessageDeflate === true) options2.perMessageDeflate = {}; + if (options2.clientTracking) { + this.clients = /* @__PURE__ */ new Set(); + this._shouldEmitClose = false; + } + this.options = options2; + this._state = RUNNING; } - if (Common.isSchema(config2)) { - return config2; + /** + * Returns the bound address, the address family name, and port of the server + * as reported by the operating system if listening on an IP socket. + * If the server is listening on a pipe or UNIX domain socket, the name is + * returned as a string. + * + * @return {(Object|String|null)} The address of the server + * @public + */ + address() { + if (this.options.noServer) { + throw new Error('The server is operating in "noServer" mode'); + } + if (!this._server) return null; + return this._server.address(); } - if (Array.isArray(config2)) { - for (const item of config2) { - if (!internals.simple(item)) { - return Joi2.alternatives().try(...config2); + /** + * Stop the server from accepting new connections and emit the `'close'` event + * when all existing connections are closed. + * + * @param {Function} [cb] A one-time listener for the `'close'` event + * @public + */ + close(cb) { + if (this._state === CLOSED) { + if (cb) { + this.once("close", () => { + cb(new Error("The server is not running")); + }); } + process.nextTick(emitClose, this); + return; } - return valid(Joi2, ...config2); - } - if (config2 instanceof RegExp) { - return Joi2.string().regex(config2); - } - if (config2 instanceof Date) { - return valid(Joi2.date(), config2); - } - assert2(Object.getPrototypeOf(config2) === Object.getPrototypeOf({}), "Schema can only contain plain objects"); - return Joi2.object().keys(config2); - }; - exports2.ref = function(id, options2) { - return Ref.isRef(id) ? id : Ref.create(id, options2); - }; - exports2.compile = function(root, schema, options2 = {}) { - Common.assertOptions(options2, ["legacy"]); - const any = schema && schema[Common.symbols.any]; - if (any) { - assert2(options2.legacy || any.version === Common.version, "Cannot mix different versions of joi schemas:", any.version, Common.version); - return schema; - } - if (typeof schema !== "object" || !options2.legacy) { - return exports2.schema(root, schema, { appendPath: true }); - } - const compiler = internals.walk(schema); - if (!compiler) { - return exports2.schema(root, schema, { appendPath: true }); - } - return compiler.compile(compiler.root, schema); - }; - internals.walk = function(schema) { - if (typeof schema !== "object") { - return null; - } - if (Array.isArray(schema)) { - for (const item of schema) { - const compiler = internals.walk(item); - if (compiler) { - return compiler; + if (cb) this.once("close", cb); + if (this._state === CLOSING) return; + this._state = CLOSING; + if (this.options.noServer || this.options.server) { + if (this._server) { + this._removeListeners(); + this._removeListeners = this._server = null; + } + if (this.clients) { + if (!this.clients.size) { + process.nextTick(emitClose, this); + } else { + this._shouldEmitClose = true; + } + } else { + process.nextTick(emitClose, this); } + } else { + const server = this._server; + this._removeListeners(); + this._removeListeners = this._server = null; + server.close(() => { + emitClose(this); + }); } - return null; } - const any = schema[Common.symbols.any]; - if (any) { - return { root: schema[any.root], compile: any.compile }; - } - assert2(Object.getPrototypeOf(schema) === Object.getPrototypeOf({}), "Schema can only contain plain objects"); - for (const key in schema) { - const compiler = internals.walk(schema[key]); - if (compiler) { - return compiler; + /** + * See if a given request should be handled by this server instance. + * + * @param {http.IncomingMessage} req Request object to inspect + * @return {Boolean} `true` if the request is valid, else `false` + * @public + */ + shouldHandle(req) { + if (this.options.path) { + const index = req.url.indexOf("?"); + const pathname = index !== -1 ? req.url.slice(0, index) : req.url; + if (pathname !== this.options.path) return false; } + return true; } - return null; - }; - internals.simple = function(value) { - return value === null || ["boolean", "string", "number"].includes(typeof value); - }; - exports2.when = function(schema, condition, options2) { - if (options2 === void 0) { - assert2(condition && typeof condition === "object", "Missing options"); - options2 = condition; - condition = Ref.create("."); - } - if (Array.isArray(options2)) { - options2 = { switch: options2 }; - } - Common.assertOptions(options2, ["is", "not", "then", "otherwise", "switch", "break"]); - if (Common.isSchema(condition)) { - assert2(options2.is === void 0, '"is" can not be used with a schema condition'); - assert2(options2.not === void 0, '"not" can not be used with a schema condition'); - assert2(options2.switch === void 0, '"switch" can not be used with a schema condition'); - return internals.condition(schema, { is: condition, then: options2.then, otherwise: options2.otherwise, break: options2.break }); - } - assert2(Ref.isRef(condition) || typeof condition === "string", "Invalid condition:", condition); - assert2(options2.not === void 0 || options2.is === void 0, 'Cannot combine "is" with "not"'); - if (options2.switch === void 0) { - let rule2 = options2; - if (options2.not !== void 0) { - rule2 = { is: options2.not, then: options2.otherwise, otherwise: options2.then, break: options2.break }; - } - let is = rule2.is !== void 0 ? schema.$_compile(rule2.is) : schema.$_root.invalid(null, false, 0, "").required(); - assert2(rule2.then !== void 0 || rule2.otherwise !== void 0, 'options must have at least one of "then", "otherwise", or "switch"'); - assert2(rule2.break === void 0 || rule2.then === void 0 || rule2.otherwise === void 0, "Cannot specify then, otherwise, and break all together"); - if (options2.is !== void 0 && !Ref.isRef(options2.is) && !Common.isSchema(options2.is)) { - is = is.required(); - } - return internals.condition(schema, { ref: exports2.ref(condition), is, then: rule2.then, otherwise: rule2.otherwise, break: rule2.break }); - } - assert2(Array.isArray(options2.switch), '"switch" must be an array'); - assert2(options2.is === void 0, 'Cannot combine "switch" with "is"'); - assert2(options2.not === void 0, 'Cannot combine "switch" with "not"'); - assert2(options2.then === void 0, 'Cannot combine "switch" with "then"'); - const rule = { - ref: exports2.ref(condition), - switch: [], - break: options2.break - }; - for (let i2 = 0; i2 < options2.switch.length; ++i2) { - const test = options2.switch[i2]; - const last = i2 === options2.switch.length - 1; - Common.assertOptions(test, last ? ["is", "then", "otherwise"] : ["is", "then"]); - assert2(test.is !== void 0, 'Switch statement missing "is"'); - assert2(test.then !== void 0, 'Switch statement missing "then"'); - const item = { - is: schema.$_compile(test.is), - then: schema.$_compile(test.then) - }; - if (!Ref.isRef(test.is) && !Common.isSchema(test.is)) { - item.is = item.is.required(); + /** + * Handle a HTTP Upgrade request. + * + * @param {http.IncomingMessage} req The request object + * @param {(net.Socket|tls.Socket)} socket The network socket between the + * server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @public + */ + handleUpgrade(req, socket, head, cb) { + socket.on("error", socketOnError); + const key = req.headers["sec-websocket-key"] !== void 0 ? req.headers["sec-websocket-key"] : false; + const version3 = +req.headers["sec-websocket-version"]; + if (req.method !== "GET" || req.headers.upgrade.toLowerCase() !== "websocket" || !key || !keyRegex.test(key) || version3 !== 8 && version3 !== 13 || !this.shouldHandle(req)) { + return abortHandshake(socket, 400); } - if (last) { - assert2(options2.otherwise === void 0 || test.otherwise === void 0, 'Cannot specify "otherwise" inside and outside a "switch"'); - const otherwise = options2.otherwise !== void 0 ? options2.otherwise : test.otherwise; - if (otherwise !== void 0) { - assert2(rule.break === void 0, "Cannot specify both otherwise and break"); - item.otherwise = schema.$_compile(otherwise); + const secWebSocketProtocol = req.headers["sec-websocket-protocol"]; + let protocols = /* @__PURE__ */ new Set(); + if (secWebSocketProtocol !== void 0) { + try { + protocols = subprotocol.parse(secWebSocketProtocol); + } catch (err) { + return abortHandshake(socket, 400); } } - rule.switch.push(item); - } - return rule; - }; - internals.condition = function(schema, condition) { - for (const key of ["then", "otherwise"]) { - if (condition[key] === void 0) { - delete condition[key]; - } else { - condition[key] = schema.$_compile(condition[key]); - } - } - return condition; - }; - } -}); -var require_extend2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/extend.js"(exports2) { - "use strict"; - var { assert: assert2, clone: clone2 } = require_lib(); - var Common = require_common3(); - var Messages = require_messages2(); - var internals = {}; - exports2.type = function(from3, options2) { - const base2 = Object.getPrototypeOf(from3); - const prototype = clone2(base2); - const schema = from3._assign(Object.create(prototype)); - const def = Object.assign({}, options2); - delete def.base; - prototype._definition = def; - const parent = base2._definition || {}; - def.messages = Messages.merge(parent.messages, def.messages); - def.properties = Object.assign({}, parent.properties, def.properties); - schema.type = def.type; - def.flags = Object.assign({}, parent.flags, def.flags); - const terms = Object.assign({}, parent.terms); - if (def.terms) { - for (const name in def.terms) { - const term = def.terms[name]; - assert2(schema.$_terms[name] === void 0, "Invalid term override for", def.type, name); - schema.$_terms[name] = term.init; - terms[name] = term; - } - } - def.terms = terms; - if (!def.args) { - def.args = parent.args; - } - def.prepare = internals.prepare(def.prepare, parent.prepare); - if (def.coerce) { - if (typeof def.coerce === "function") { - def.coerce = { method: def.coerce }; - } - if (def.coerce.from && !Array.isArray(def.coerce.from)) { - def.coerce = { method: def.coerce.method, from: [].concat(def.coerce.from) }; - } - } - def.coerce = internals.coerce(def.coerce, parent.coerce); - def.validate = internals.validate(def.validate, parent.validate); - const rules = Object.assign({}, parent.rules); - if (def.rules) { - for (const name in def.rules) { - const rule = def.rules[name]; - assert2(typeof rule === "object", "Invalid rule definition for", def.type, name); - let method = rule.method; - if (method === void 0) { - method = function() { - return this.$_addRule(name); - }; - } - if (method) { - assert2(!prototype[name], "Rule conflict in", def.type, name); - prototype[name] = method; - } - assert2(!rules[name], "Rule conflict in", def.type, name); - rules[name] = rule; - if (rule.alias) { - const aliases = [].concat(rule.alias); - for (const alias of aliases) { - prototype[alias] = rule.method; + const secWebSocketExtensions = req.headers["sec-websocket-extensions"]; + const extensions = {}; + if (this.options.perMessageDeflate && secWebSocketExtensions !== void 0) { + const perMessageDeflate = new PerMessageDeflate( + this.options.perMessageDeflate, + true, + this.options.maxPayload + ); + try { + const offers = extension.parse(secWebSocketExtensions); + if (offers[PerMessageDeflate.extensionName]) { + perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]); + extensions[PerMessageDeflate.extensionName] = perMessageDeflate; } - } - if (rule.args) { - rule.argsByName = /* @__PURE__ */ new Map(); - rule.args = rule.args.map((arg) => { - if (typeof arg === "string") { - arg = { name: arg }; - } - assert2(!rule.argsByName.has(arg.name), "Duplicated argument name", arg.name); - if (Common.isSchema(arg.assert)) { - arg.assert = arg.assert.strict().label(arg.name); - } - rule.argsByName.set(arg.name, arg); - return arg; - }); + } catch (err) { + return abortHandshake(socket, 400); } } - } - def.rules = rules; - const modifiers = Object.assign({}, parent.modifiers); - if (def.modifiers) { - for (const name in def.modifiers) { - assert2(!prototype[name], "Rule conflict in", def.type, name); - const modifier = def.modifiers[name]; - assert2(typeof modifier === "function", "Invalid modifier definition for", def.type, name); - const method = function(arg) { - return this.rule({ [name]: arg }); + if (this.options.verifyClient) { + const info = { + origin: req.headers[`${version3 === 8 ? "sec-websocket-origin" : "origin"}`], + secure: !!(req.socket.authorized || req.socket.encrypted), + req }; - prototype[name] = method; - modifiers[name] = modifier; - } - } - def.modifiers = modifiers; - if (def.overrides) { - prototype._super = base2; - schema.$_super = {}; - for (const override in def.overrides) { - assert2(base2[override], "Cannot override missing", override); - def.overrides[override][Common.symbols.parent] = base2[override]; - schema.$_super[override] = base2[override].bind(schema); - } - Object.assign(prototype, def.overrides); - } - def.cast = Object.assign({}, parent.cast, def.cast); - const manifest2 = Object.assign({}, parent.manifest, def.manifest); - manifest2.build = internals.build(def.manifest && def.manifest.build, parent.manifest && parent.manifest.build); - def.manifest = manifest2; - def.rebuild = internals.rebuild(def.rebuild, parent.rebuild); - return schema; - }; - internals.build = function(child, parent) { - if (!child || !parent) { - return child || parent; - } - return function(obj, desc) { - return parent(child(obj, desc), desc); - }; - }; - internals.coerce = function(child, parent) { - if (!child || !parent) { - return child || parent; - } - return { - from: child.from && parent.from ? [.../* @__PURE__ */ new Set([...child.from, ...parent.from])] : null, - method(value, helpers) { - let coerced; - if (!parent.from || parent.from.includes(typeof value)) { - coerced = parent.method(value, helpers); - if (coerced) { - if (coerced.errors || coerced.value === void 0) { - return coerced; + if (this.options.verifyClient.length === 2) { + this.options.verifyClient(info, (verified, code2, message, headers) => { + if (!verified) { + return abortHandshake(socket, code2 || 401, message, headers); } - value = coerced.value; - } - } - if (!child.from || child.from.includes(typeof value)) { - const own = child.method(value, helpers); - if (own) { - return own; - } + this.completeUpgrade( + extensions, + key, + protocols, + req, + socket, + head, + cb + ); + }); + return; } - return coerced; + if (!this.options.verifyClient(info)) return abortHandshake(socket, 401); } - }; - }; - internals.prepare = function(child, parent) { - if (!child || !parent) { - return child || parent; + this.completeUpgrade(extensions, key, protocols, req, socket, head, cb); } - return function(value, helpers) { - const prepared = child(value, helpers); - if (prepared) { - if (prepared.errors || prepared.value === void 0) { - return prepared; + /** + * Upgrade the connection to WebSocket. + * + * @param {Object} extensions The accepted extensions + * @param {String} key The value of the `Sec-WebSocket-Key` header + * @param {Set} protocols The subprotocols + * @param {http.IncomingMessage} req The request object + * @param {(net.Socket|tls.Socket)} socket The network socket between the + * server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @throws {Error} If called more than once with the same socket + * @private + */ + completeUpgrade(extensions, key, protocols, req, socket, head, cb) { + if (!socket.readable || !socket.writable) return socket.destroy(); + if (socket[kWebSocket]) { + throw new Error( + "server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration" + ); + } + if (this._state > RUNNING) return abortHandshake(socket, 503); + const digest = createHash("sha1").update(key + GUID).digest("base64"); + const headers = [ + "HTTP/1.1 101 Switching Protocols", + "Upgrade: websocket", + "Connection: Upgrade", + `Sec-WebSocket-Accept: ${digest}` + ]; + const ws = new this.options.WebSocket(null); + if (protocols.size) { + const protocol = this.options.handleProtocols ? this.options.handleProtocols(protocols, req) : protocols.values().next().value; + if (protocol) { + headers.push(`Sec-WebSocket-Protocol: ${protocol}`); + ws._protocol = protocol; } - value = prepared.value; } - return parent(value, helpers) || prepared; - }; - }; - internals.rebuild = function(child, parent) { - if (!child || !parent) { - return child || parent; + if (extensions[PerMessageDeflate.extensionName]) { + const params = extensions[PerMessageDeflate.extensionName].params; + const value = extension.format({ + [PerMessageDeflate.extensionName]: [params] + }); + headers.push(`Sec-WebSocket-Extensions: ${value}`); + ws._extensions = extensions; + } + this.emit("headers", headers, req); + socket.write(headers.concat("\r\n").join("\r\n")); + socket.removeListener("error", socketOnError); + ws.setSocket(socket, head, { + maxPayload: this.options.maxPayload, + skipUTF8Validation: this.options.skipUTF8Validation + }); + if (this.clients) { + this.clients.add(ws); + ws.on("close", () => { + this.clients.delete(ws); + if (this._shouldEmitClose && !this.clients.size) { + process.nextTick(emitClose, this); + } + }); + } + cb(ws, req); } - return function(schema) { - parent(schema); - child(schema); - }; }; - internals.validate = function(child, parent) { - if (!child || !parent) { - return child || parent; - } - return function(value, helpers) { - const result = parent(value, helpers); - if (result) { - if (result.errors && (!Array.isArray(result.errors) || result.errors.length)) { - return result; - } - value = result.value; + module14.exports = WebSocketServer2; + function addListeners(server, map) { + for (const event of Object.keys(map)) server.on(event, map[event]); + return function removeListeners() { + for (const event of Object.keys(map)) { + server.removeListener(event, map[event]); } - return child(value, helpers) || result; }; - }; + } + function emitClose(server) { + server._state = CLOSED; + server.emit("close"); + } + function socketOnError() { + this.destroy(); + } + function abortHandshake(socket, code2, message, headers) { + if (socket.writable) { + message = message || http.STATUS_CODES[code2]; + headers = { + Connection: "close", + "Content-Type": "text/html", + "Content-Length": Buffer.byteLength(message), + ...headers + }; + socket.write( + `HTTP/1.1 ${code2} ${http.STATUS_CODES[code2]}\r +` + Object.keys(headers).map((h2) => `${h2}: ${headers[h2]}`).join("\r\n") + "\r\n\r\n" + message + ); + } + socket.removeListener("error", socketOnError); + socket.destroy(); + } + } +}); +var import_npm_nconf7 = __toESM(require_nconf()); +function getLineColFromPtr(string3, ptr) { + let lines = string3.slice(0, ptr).split(/\r\n|\n|\r/g); + return [lines.length, lines.pop().length + 1]; +} +function makeCodeBlock(string3, line, column) { + let lines = string3.split(/\r\n|\n|\r/g); + let codeblock = ""; + let numberLen = (Math.log10(line + 1) | 0) + 1; + for (let i2 = line - 1; i2 <= line + 1; i2++) { + let l = lines[i2 - 1]; + if (!l) + continue; + codeblock += i2.toString().padEnd(numberLen, " "); + codeblock += ": "; + codeblock += l; + codeblock += "\n"; + if (i2 === line) { + codeblock += " ".repeat(numberLen + column + 2); + codeblock += "^\n"; + } + } + return codeblock; +} +var TomlError = class extends Error { + line; + column; + codeblock; + constructor(message, options2) { + const [line, column] = getLineColFromPtr(options2.toml, options2.ptr); + const codeblock = makeCodeBlock(options2.toml, line, column); + super(`Invalid TOML document: ${message} + +${codeblock}`, options2); + this.line = line; + this.column = column; + this.codeblock = codeblock; + } +}; +function isEscaped(str, ptr) { + let i2 = 0; + while (str[ptr - ++i2] === "\\") + ; + return --i2 && i2 % 2; +} +function indexOfNewline(str, start = 0, end = str.length) { + let idx = str.indexOf("\n", start); + if (str[idx - 1] === "\r") + idx--; + return idx <= end ? idx : -1; +} +function skipComment(str, ptr) { + for (let i2 = ptr; i2 < str.length; i2++) { + let c = str[i2]; + if (c === "\n") + return i2; + if (c === "\r" && str[i2 + 1] === "\n") + return i2 + 1; + if (c < " " && c !== " " || c === "\x7F") { + throw new TomlError("control characters are not allowed in comments", { + toml: str, + ptr + }); + } + } + return str.length; +} +function skipVoid(str, ptr, banNewLines, banComments) { + let c; + while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n")) + ptr++; + return banComments || c !== "#" ? ptr : skipVoid(str, skipComment(str, ptr), banNewLines); +} +function skipUntil(str, ptr, sep, end, banNewLines = false) { + if (!end) { + ptr = indexOfNewline(str, ptr); + return ptr < 0 ? str.length : ptr; + } + for (let i2 = ptr; i2 < str.length; i2++) { + let c = str[i2]; + if (c === "#") { + i2 = indexOfNewline(str, i2); + } else if (c === sep) { + return i2 + 1; + } else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i2 + 1] === "\n")) { + return i2; + } + } + throw new TomlError("cannot find end of structure", { + toml: str, + ptr + }); +} +function getStringEnd(str, seek) { + let first = str[seek]; + let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2] ? str.slice(seek, seek + 3) : first; + seek += target.length - 1; + do + seek = str.indexOf(target, ++seek); + while (seek > -1 && first !== "'" && isEscaped(str, seek)); + if (seek > -1) { + seek += target.length; + if (target.length > 1) { + if (str[seek] === first) + seek++; + if (str[seek] === first) + seek++; + } } -}); -var require_manifest = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/manifest.js"(exports2) { - "use strict"; - var { assert: assert2, clone: clone2 } = require_lib(); - var Common = require_common3(); - var Messages = require_messages2(); - var Ref = require_ref2(); - var Template = require_template2(); - var Schemas; - var internals = {}; - exports2.describe = function(schema) { - const def = schema._definition; - const desc = { - type: schema.type, - flags: {}, - rules: [] - }; - for (const flag in schema._flags) { - if (flag[0] !== "_") { - desc.flags[flag] = internals.describe(schema._flags[flag]); - } - } - if (!Object.keys(desc.flags).length) { - delete desc.flags; - } - if (schema._preferences) { - desc.preferences = clone2(schema._preferences, { shallow: ["messages"] }); - delete desc.preferences[Common.symbols.prefs]; - if (desc.preferences.messages) { - desc.preferences.messages = Messages.decompile(desc.preferences.messages); - } - } - if (schema._valids) { - desc.allow = schema._valids.describe(); - } - if (schema._invalids) { - desc.invalid = schema._invalids.describe(); - } - for (const rule of schema._rules) { - const ruleDef = def.rules[rule.name]; - if (ruleDef.manifest === false) { - continue; - } - const item = { name: rule.name }; - for (const custom in def.modifiers) { - if (rule[custom] !== void 0) { - item[custom] = internals.describe(rule[custom]); - } + return seek; +} +var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}:\d{2}(?:\.\d+)?)?(Z|[-+]\d{2}:\d{2})?$/i; +var TomlDate = class _TomlDate extends Date { + #hasDate = false; + #hasTime = false; + #offset = null; + constructor(date3) { + let hasDate = true; + let hasTime = true; + let offset = "Z"; + if (typeof date3 === "string") { + let match2 = date3.match(DATE_TIME_RE); + if (match2) { + if (!match2[1]) { + hasDate = false; + date3 = `0000-01-01T${date3}`; } - if (rule.args) { - item.args = {}; - for (const key in rule.args) { - const arg = rule.args[key]; - if (key === "options" && !Object.keys(arg).length) { - continue; - } - item.args[key] = internals.describe(arg, { assign: key }); - } - if (!Object.keys(item.args).length) { - delete item.args; - } + hasTime = !!match2[2]; + hasTime && date3[10] === " " && (date3 = date3.replace(" ", "T")); + if (match2[2] && +match2[2] > 23) { + date3 = ""; + } else { + offset = match2[3] || null; + date3 = date3.toUpperCase(); + if (!offset && hasTime) + date3 += "Z"; } - desc.rules.push(item); + } else { + date3 = ""; } - if (!desc.rules.length) { - delete desc.rules; + } + super(date3); + if (!isNaN(this.getTime())) { + this.#hasDate = hasDate; + this.#hasTime = hasTime; + this.#offset = offset; + } + } + isDateTime() { + return this.#hasDate && this.#hasTime; + } + isLocal() { + return !this.#hasDate || !this.#hasTime || !this.#offset; + } + isDate() { + return this.#hasDate && !this.#hasTime; + } + isTime() { + return this.#hasTime && !this.#hasDate; + } + isValid() { + return this.#hasDate || this.#hasTime; + } + toISOString() { + let iso = super.toISOString(); + if (this.isDate()) + return iso.slice(0, 10); + if (this.isTime()) + return iso.slice(11, 23); + if (this.#offset === null) + return iso.slice(0, -1); + if (this.#offset === "Z") + return iso; + let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6); + offset = this.#offset[0] === "-" ? offset : -offset; + let offsetDate = new Date(this.getTime() - offset * 6e4); + return offsetDate.toISOString().slice(0, -1) + this.#offset; + } + static wrapAsOffsetDateTime(jsDate, offset = "Z") { + let date3 = new _TomlDate(jsDate); + date3.#offset = offset; + return date3; + } + static wrapAsLocalDateTime(jsDate) { + let date3 = new _TomlDate(jsDate); + date3.#offset = null; + return date3; + } + static wrapAsLocalDate(jsDate) { + let date3 = new _TomlDate(jsDate); + date3.#hasTime = false; + date3.#offset = null; + return date3; + } + static wrapAsLocalTime(jsDate) { + let date3 = new _TomlDate(jsDate); + date3.#hasDate = false; + date3.#offset = null; + return date3; + } +}; +var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/; +var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/; +var LEADING_ZERO = /^[+-]?0[0-9_]/; +var ESCAPE_REGEX = /^[0-9a-f]{4,8}$/i; +var ESC_MAP = { + b: "\b", + t: " ", + n: "\n", + f: "\f", + r: "\r", + '"': '"', + "\\": "\\" +}; +function parseString(str, ptr = 0, endPtr = str.length) { + let isLiteral = str[ptr] === "'"; + let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1]; + if (isMultiline) { + endPtr -= 2; + if (str[ptr += 2] === "\r") + ptr++; + if (str[ptr] === "\n") + ptr++; + } + let tmp = 0; + let isEscape; + let parsed = ""; + let sliceStart = ptr; + while (ptr < endPtr - 1) { + let c = str[ptr++]; + if (c === "\n" || c === "\r" && str[ptr] === "\n") { + if (!isMultiline) { + throw new TomlError("newlines are not allowed in strings", { + toml: str, + ptr: ptr - 1 + }); } - for (const term in schema.$_terms) { - if (term[0] === "_") { - continue; - } - assert2(!desc[term], "Cannot describe schema due to internal name conflict with", term); - const items = schema.$_terms[term]; - if (!items) { - continue; - } - if (items instanceof Map) { - if (items.size) { - desc[term] = [...items.entries()]; - } - continue; - } - if (Common.isValues(items)) { - desc[term] = items.describe(); - continue; - } - assert2(def.terms[term], "Term", term, "missing configuration"); - const manifest2 = def.terms[term].manifest; - const mapped = typeof manifest2 === "object"; - if (!items.length && !mapped) { - continue; - } - const normalized = []; - for (const item of items) { - normalized.push(internals.describe(item)); - } - if (mapped) { - const { from: from3, to } = manifest2.mapped; - desc[term] = {}; - for (const item of normalized) { - desc[term][item[to]] = item[from3]; - } - continue; + } else if (c < " " && c !== " " || c === "\x7F") { + throw new TomlError("control characters are not allowed in strings", { + toml: str, + ptr: ptr - 1 + }); + } + if (isEscape) { + isEscape = false; + if (c === "u" || c === "U") { + let code2 = str.slice(ptr, ptr += c === "u" ? 4 : 8); + if (!ESCAPE_REGEX.test(code2)) { + throw new TomlError("invalid unicode escape", { + toml: str, + ptr: tmp + }); } - if (manifest2 === "single") { - assert2(normalized.length === 1, "Term", term, "contains more than one item"); - desc[term] = normalized[0]; - continue; + try { + parsed += String.fromCodePoint(parseInt(code2, 16)); + } catch { + throw new TomlError("invalid unicode escape", { + toml: str, + ptr: tmp + }); } - desc[term] = normalized; - } - internals.validate(schema.$_root, desc); - return desc; - }; - internals.describe = function(item, options2 = {}) { - if (Array.isArray(item)) { - return item.map(internals.describe); - } - if (item === Common.symbols.deepDefault) { - return { special: "deep" }; - } - if (typeof item !== "object" || item === null) { - return item; - } - if (options2.assign === "options") { - return clone2(item); - } - if (Buffer && Buffer.isBuffer(item)) { - return { buffer: item.toString("binary") }; - } - if (item instanceof Date) { - return item.toISOString(); - } - if (item instanceof Error) { - return item; - } - if (item instanceof RegExp) { - if (options2.assign === "regex") { - return item.toString(); + } else if (isMultiline && (c === "\n" || c === " " || c === " " || c === "\r")) { + ptr = skipVoid(str, ptr - 1, true); + if (str[ptr] !== "\n" && str[ptr] !== "\r") { + throw new TomlError("invalid escape: only line-ending whitespace may be escaped", { + toml: str, + ptr: tmp + }); } - return { regex: item.toString() }; - } - if (item[Common.symbols.literal]) { - return { function: item.literal }; + ptr = skipVoid(str, ptr); + } else if (c in ESC_MAP) { + parsed += ESC_MAP[c]; + } else { + throw new TomlError("unrecognized escape sequence", { + toml: str, + ptr: tmp + }); } - if (typeof item.describe === "function") { - if (options2.assign === "ref") { - return item.describe().ref; - } - return item.describe(); + sliceStart = ptr; + } else if (!isLiteral && c === "\\") { + tmp = ptr - 1; + isEscape = true; + parsed += str.slice(sliceStart, tmp); + } + } + return parsed + str.slice(sliceStart, endPtr - 1); +} +function parseValue(value, toml, ptr, integersAsBigInt) { + if (value === "true") + return true; + if (value === "false") + return false; + if (value === "-inf") + return -Infinity; + if (value === "inf" || value === "+inf") + return Infinity; + if (value === "nan" || value === "+nan" || value === "-nan") + return NaN; + if (value === "-0") + return integersAsBigInt ? 0n : 0; + let isInt = INT_REGEX.test(value); + if (isInt || FLOAT_REGEX.test(value)) { + if (LEADING_ZERO.test(value)) { + throw new TomlError("leading zeroes are not allowed", { + toml, + ptr + }); + } + value = value.replace(/_/g, ""); + let numeric = +value; + if (isNaN(numeric)) { + throw new TomlError("invalid number", { + toml, + ptr + }); + } + if (isInt) { + if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) { + throw new TomlError("integer value cannot be represented losslessly", { + toml, + ptr + }); } - const normalized = {}; - for (const key in item) { - const value = item[key]; - if (value === void 0) { - continue; - } - normalized[key] = internals.describe(value, { assign: key }); + if (isInt || integersAsBigInt === true) + numeric = BigInt(value); + } + return numeric; + } + const date3 = new TomlDate(value); + if (!date3.isValid()) { + throw new TomlError("invalid value", { + toml, + ptr + }); + } + return date3; +} +function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) { + let value = str.slice(startPtr, endPtr); + let commentIdx = value.indexOf("#"); + if (commentIdx > -1) { + skipComment(str, commentIdx); + value = value.slice(0, commentIdx); + } + let trimmed = value.trimEnd(); + if (!allowNewLines) { + let newlineIdx = value.indexOf("\n", trimmed.length); + if (newlineIdx > -1) { + throw new TomlError("newlines are not allowed in inline tables", { + toml: str, + ptr: startPtr + newlineIdx + }); + } + } + return [trimmed, commentIdx]; +} +function extractValue(str, ptr, end, depth, integersAsBigInt) { + if (depth === 0) { + throw new TomlError("document contains excessively nested structures. aborting.", { + toml: str, + ptr + }); + } + let c = str[ptr]; + if (c === "[" || c === "{") { + let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt); + let newPtr = end ? skipUntil(str, endPtr2, ",", end) : endPtr2; + if (endPtr2 - newPtr && end === "}") { + let nextNewLine = indexOfNewline(str, endPtr2, newPtr); + if (nextNewLine > -1) { + throw new TomlError("newlines are not allowed in inline tables", { + toml: str, + ptr: nextNewLine + }); } - return normalized; - }; - exports2.build = function(joi, desc) { - const builder = new internals.Builder(joi); - return builder.parse(desc); - }; - internals.Builder = class { - constructor(joi) { - this.joi = joi; + } + return [value, newPtr]; + } + let endPtr; + if (c === '"' || c === "'") { + endPtr = getStringEnd(str, ptr); + let parsed = parseString(str, ptr, endPtr); + if (end) { + endPtr = skipVoid(str, endPtr, end !== "]"); + if (str[endPtr] && str[endPtr] !== "," && str[endPtr] !== end && str[endPtr] !== "\n" && str[endPtr] !== "\r") { + throw new TomlError("unexpected character encountered", { + toml: str, + ptr: endPtr + }); } - parse(desc) { - internals.validate(this.joi, desc); - let schema = this.joi[desc.type]()._bare(); - const def = schema._definition; - if (desc.flags) { - for (const flag in desc.flags) { - const setter = def.flags[flag] && def.flags[flag].setter || flag; - assert2(typeof schema[setter] === "function", "Invalid flag", flag, "for type", desc.type); - schema = schema[setter](this.build(desc.flags[flag])); - } - } - if (desc.preferences) { - schema = schema.preferences(this.build(desc.preferences)); + endPtr += +(str[endPtr] === ","); + } + return [parsed, endPtr]; + } + endPtr = skipUntil(str, ptr, ",", end); + let slice = sliceAndTrimEndOf(str, ptr, endPtr - +(str[endPtr - 1] === ","), end === "]"); + if (!slice[0]) { + throw new TomlError("incomplete key-value declaration: no value specified", { + toml: str, + ptr + }); + } + if (end && slice[1] > -1) { + endPtr = skipVoid(str, ptr + slice[1]); + endPtr += +(str[endPtr] === ","); + } + return [ + parseValue(slice[0], str, ptr, integersAsBigInt), + endPtr + ]; +} +var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/; +function parseKey(str, ptr, end = "=") { + let dot = ptr - 1; + let parsed = []; + let endPtr = str.indexOf(end, ptr); + if (endPtr < 0) { + throw new TomlError("incomplete key-value: cannot find end of key", { + toml: str, + ptr + }); + } + do { + let c = str[ptr = ++dot]; + if (c !== " " && c !== " ") { + if (c === '"' || c === "'") { + if (c === str[ptr + 1] && c === str[ptr + 2]) { + throw new TomlError("multiline strings are not allowed in keys", { + toml: str, + ptr + }); } - if (desc.allow) { - schema = schema.allow(...this.build(desc.allow)); + let eos = getStringEnd(str, ptr); + if (eos < 0) { + throw new TomlError("unfinished string encountered", { + toml: str, + ptr + }); } - if (desc.invalid) { - schema = schema.invalid(...this.build(desc.invalid)); + dot = str.indexOf(".", eos); + let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot); + let newLine = indexOfNewline(strEnd); + if (newLine > -1) { + throw new TomlError("newlines are not allowed in keys", { + toml: str, + ptr: ptr + dot + newLine + }); } - if (desc.rules) { - for (const rule of desc.rules) { - assert2(typeof schema[rule.name] === "function", "Invalid rule", rule.name, "for type", desc.type); - const args = []; - if (rule.args) { - const built = {}; - for (const key in rule.args) { - built[key] = this.build(rule.args[key], { assign: key }); - } - const keys = Object.keys(built); - const definition = def.rules[rule.name].args; - if (definition) { - assert2(keys.length <= definition.length, "Invalid number of arguments for", desc.type, rule.name, "(expected up to", definition.length, ", found", keys.length, ")"); - for (const { name } of definition) { - args.push(built[name]); - } - } else { - assert2(keys.length === 1, "Invalid number of arguments for", desc.type, rule.name, "(expected up to 1, found", keys.length, ")"); - args.push(built[keys[0]]); - } - } - schema = schema[rule.name](...args); - const options2 = {}; - for (const custom in def.modifiers) { - if (rule[custom] !== void 0) { - options2[custom] = this.build(rule[custom]); - } - } - if (Object.keys(options2).length) { - schema = schema.rule(options2); - } - } + if (strEnd.trimStart()) { + throw new TomlError("found extra tokens after the string part", { + toml: str, + ptr: eos + }); } - const terms = {}; - for (const key in desc) { - if (["allow", "flags", "invalid", "whens", "preferences", "rules", "type"].includes(key)) { - continue; - } - assert2(def.terms[key], "Term", key, "missing configuration"); - const manifest2 = def.terms[key].manifest; - if (manifest2 === "schema") { - terms[key] = desc[key].map((item) => this.parse(item)); - continue; - } - if (manifest2 === "values") { - terms[key] = desc[key].map((item) => this.build(item)); - continue; - } - if (manifest2 === "single") { - terms[key] = this.build(desc[key]); - continue; - } - if (typeof manifest2 === "object") { - terms[key] = {}; - for (const name in desc[key]) { - const value = desc[key][name]; - terms[key][name] = this.parse(value); - } - continue; + if (endPtr < eos) { + endPtr = str.indexOf(end, eos); + if (endPtr < 0) { + throw new TomlError("incomplete key-value: cannot find end of key", { + toml: str, + ptr + }); } - terms[key] = this.build(desc[key]); } - if (desc.whens) { - terms.whens = desc.whens.map((when) => this.build(when)); + parsed.push(parseString(str, ptr, eos)); + } else { + dot = str.indexOf(".", ptr); + let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot); + if (!KEY_PART_RE.test(part)) { + throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", { + toml: str, + ptr + }); } - schema = def.manifest.build(schema, terms); - schema.$_temp.ruleset = false; - return schema; + parsed.push(part.trimEnd()); } - build(desc, options2 = {}) { - if (desc === null) { - return null; - } - if (Array.isArray(desc)) { - return desc.map((item) => this.build(item)); - } - if (desc instanceof Error) { - return desc; - } - if (options2.assign === "options") { - return clone2(desc); - } - if (options2.assign === "regex") { - return internals.regex(desc); - } - if (options2.assign === "ref") { - return Ref.build(desc); - } - if (typeof desc !== "object") { - return desc; - } - if (Object.keys(desc).length === 1) { - if (desc.buffer) { - assert2(Buffer, "Buffers are not supported"); - return Buffer && Buffer.from(desc.buffer, "binary"); - } - if (desc.function) { - return { [Common.symbols.literal]: true, literal: desc.function }; - } - if (desc.override) { - return Common.symbols.override; - } - if (desc.ref) { - return Ref.build(desc.ref); - } - if (desc.regex) { - return internals.regex(desc.regex); - } - if (desc.special) { - assert2(["deep"].includes(desc.special), "Unknown special value", desc.special); - return Common.symbols.deepDefault; - } - if (desc.value) { - return clone2(desc.value); - } - } - if (desc.type) { - return this.parse(desc); - } - if (desc.template) { - return Template.build(desc); + } + } while (dot + 1 && dot < endPtr); + return [parsed, skipVoid(str, endPtr + 1, true, true)]; +} +function parseInlineTable(str, ptr, depth, integersAsBigInt) { + let res = {}; + let seen = /* @__PURE__ */ new Set(); + let c; + let comma = 0; + ptr++; + while ((c = str[ptr++]) !== "}" && c) { + let err = { toml: str, ptr: ptr - 1 }; + if (c === "\n") { + throw new TomlError("newlines are not allowed in inline tables", err); + } else if (c === "#") { + throw new TomlError("inline tables cannot contain comments", err); + } else if (c === ",") { + throw new TomlError("expected key-value, found comma", err); + } else if (c !== " " && c !== " ") { + let k; + let t = res; + let hasOwn = false; + let [key, keyEndPtr] = parseKey(str, ptr - 1); + for (let i2 = 0; i2 < key.length; i2++) { + if (i2) + t = hasOwn ? t[k] : t[k] = {}; + k = key[i2]; + if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) { + throw new TomlError("trying to redefine an already defined value", { + toml: str, + ptr + }); } - const normalized = {}; - for (const key in desc) { - normalized[key] = this.build(desc[key], { assign: key }); + if (!hasOwn && k === "__proto__") { + Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true }); } - return normalized; } - }; - internals.regex = function(string3) { - const end = string3.lastIndexOf("/"); - const exp = string3.slice(1, end); - const flags = string3.slice(end + 1); - return new RegExp(exp, flags); - }; - internals.validate = function(joi, desc) { - Schemas = Schemas || require_schemas2(); - joi.assert(desc, Schemas.description); - }; + if (hasOwn) { + throw new TomlError("trying to redefine an already defined value", { + toml: str, + ptr + }); + } + let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt); + seen.add(value); + t[k] = value; + ptr = valueEndPtr; + comma = str[ptr - 1] === "," ? ptr - 1 : 0; + } } -}); -var require_lib38 = __commonJS({ - "node_modules/.deno/@hapi+pinpoint@2.0.1/node_modules/@hapi/pinpoint/lib/index.js"(exports2) { - "use strict"; - exports2.location = function(depth = 0) { - const orig = Error.prepareStackTrace; - Error.prepareStackTrace = (ignore, stack) => stack; - const capture = {}; - Error.captureStackTrace(capture, this); - const line = capture.stack[depth + 1]; - Error.prepareStackTrace = orig; - return { - filename: line.getFileName(), - line: line.getLineNumber() - }; - }; + if (comma) { + throw new TomlError("trailing commas are not allowed in inline tables", { + toml: str, + ptr: comma + }); + } + if (!c) { + throw new TomlError("unfinished table encountered", { + toml: str, + ptr + }); + } + return [res, ptr]; +} +function parseArray(str, ptr, depth, integersAsBigInt) { + let res = []; + let c; + ptr++; + while ((c = str[ptr++]) !== "]" && c) { + if (c === ",") { + throw new TomlError("expected value, found comma", { + toml: str, + ptr: ptr - 1 + }); + } else if (c === "#") + ptr = skipComment(str, ptr); + else if (c !== " " && c !== " " && c !== "\n" && c !== "\r") { + let e2 = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt); + res.push(e2[0]); + ptr = e2[1]; + } } -}); -var require_trace = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/trace.js"(exports2) { - "use strict"; - var { deepEqual } = require_lib(); - var Pinpoint = require_lib38(); - var Errors = require_errors3(); - var internals = { - codes: { - error: 1, - pass: 2, - full: 3 - }, - labels: { - 0: "never used", - 1: "always error", - 2: "always pass" - } - }; - exports2.setup = function(root) { - const trace = function() { - root._tracer = root._tracer || new internals.Tracer(); - return root._tracer; - }; - root.trace = trace; - root[Symbol.for("@hapi/lab/coverage/initialize")] = trace; - root.untrace = () => { - root._tracer = null; - }; - }; - exports2.location = function(schema) { - return schema.$_setFlag("_tracerLocation", Pinpoint.location(2)); - }; - internals.Tracer = class { - constructor() { - this.name = "Joi"; - this._schemas = /* @__PURE__ */ new Map(); + if (!c) { + throw new TomlError("unfinished array encountered", { + toml: str, + ptr + }); + } + return [res, ptr]; +} +function peekTable(key, table, meta, type) { + let t = table; + let m3 = meta; + let k; + let hasOwn = false; + let state; + for (let i2 = 0; i2 < key.length; i2++) { + if (i2) { + t = hasOwn ? t[k] : t[k] = {}; + m3 = (state = m3[k]).c; + if (type === 0 && (state.t === 1 || state.t === 2)) { + return null; } - _register(schema) { - const existing = this._schemas.get(schema); - if (existing) { - return existing.store; - } - const store = new internals.Store(schema); - const { filename, line } = schema._flags._tracerLocation || Pinpoint.location(5); - this._schemas.set(schema, { filename, line, store }); - return store; + if (state.t === 2) { + let l = t.length - 1; + t = t[l]; + m3 = m3[l].c; } - _combine(merged, sources) { - for (const { store } of this._schemas.values()) { - store._combine(merged, sources); - } + } + k = key[i2]; + if ((hasOwn = Object.hasOwn(t, k)) && m3[k]?.t === 0 && m3[k]?.d) { + return null; + } + if (!hasOwn) { + if (k === "__proto__") { + Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true }); + Object.defineProperty(m3, k, { enumerable: true, configurable: true, writable: true }); } - report(file) { - const coverage = []; - for (const { filename, line, store } of this._schemas.values()) { - if (file && file !== filename) { - continue; - } - const missing = []; - const skipped = []; - for (const [schema, log2] of store._sources.entries()) { - if (internals.sub(log2.paths, skipped)) { - continue; - } - if (!log2.entry) { - missing.push({ - status: "never reached", - paths: [...log2.paths] - }); - skipped.push(...log2.paths); - continue; - } - for (const type of ["valid", "invalid"]) { - const set = schema[`_${type}s`]; - if (!set) { - continue; - } - const values = new Set(set._values); - const refs = new Set(set._refs); - for (const { value, ref } of log2[type]) { - values.delete(value); - refs.delete(ref); - } - if (values.size || refs.size) { - missing.push({ - status: [...values, ...[...refs].map((ref) => ref.display)], - rule: `${type}s` - }); - } - } - const rules = schema._rules.map((rule) => rule.name); - for (const type of ["default", "failover"]) { - if (schema._flags[type] !== void 0) { - rules.push(type); - } - } - for (const name of rules) { - const status = internals.labels[log2.rule[name] || 0]; - if (status) { - const report = { rule: name, status }; - if (log2.paths.size) { - report.paths = [...log2.paths]; - } - missing.push(report); - } - } - } - if (missing.length) { - coverage.push({ - filename, - line, - missing, - severity: "error", - message: `Schema missing tests for ${missing.map(internals.message).join(", ")}` - }); - } + m3[k] = { + t: i2 < key.length - 1 && type === 2 ? 3 : type, + d: false, + i: 0, + c: {} + }; + } + } + state = m3[k]; + if (state.t !== type && !(type === 1 && state.t === 3)) { + return null; + } + if (type === 2) { + if (!state.d) { + state.d = true; + t[k] = []; + } + t[k].push(t = {}); + state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} }; + } + if (state.d) { + return null; + } + state.d = true; + if (type === 1) { + t = hasOwn ? t[k] : t[k] = {}; + } else if (type === 0 && hasOwn) { + return null; + } + return [k, t, state.c]; +} +function parse8(toml, { maxDepth = 1e3, integersAsBigInt } = {}) { + let res = {}; + let meta = {}; + let tbl = res; + let m3 = meta; + for (let ptr = skipVoid(toml, 0); ptr < toml.length; ) { + if (toml[ptr] === "[") { + let isTableArray = toml[++ptr] === "["; + let k = parseKey(toml, ptr += +isTableArray, "]"); + if (isTableArray) { + if (toml[k[1] - 1] !== "]") { + throw new TomlError("expected end of table declaration", { + toml, + ptr: k[1] - 1 + }); } - return coverage.length ? coverage : null; - } - }; - internals.Store = class { - constructor(schema) { - this.active = true; - this._sources = /* @__PURE__ */ new Map(); - this._combos = /* @__PURE__ */ new Map(); - this._scan(schema); - } - debug(state, source, name, result) { - state.mainstay.debug && state.mainstay.debug.push({ type: source, name, result, path: state.path }); - } - entry(schema, state) { - internals.debug(state, { type: "entry" }); - this._record(schema, (log2) => { - log2.entry = true; - }); + k[1]++; } - filter(schema, state, source, value) { - internals.debug(state, { type: source, ...value }); - this._record(schema, (log2) => { - log2[source].add(value); + let p = peekTable( + k[0], + res, + meta, + isTableArray ? 2 : 1 + /* Type.EXPLICIT */ + ); + if (!p) { + throw new TomlError("trying to redefine an already defined table or value", { + toml, + ptr }); } - log(schema, state, source, name, result) { - internals.debug(state, { type: source, name, result: result === "full" ? "pass" : result }); - this._record(schema, (log2) => { - log2[source][name] = log2[source][name] || 0; - log2[source][name] |= internals.codes[result]; + m3 = p[2]; + tbl = p[1]; + ptr = k[1]; + } else { + let k = parseKey(toml, ptr); + let p = peekTable( + k[0], + tbl, + m3, + 0 + /* Type.DOTTED */ + ); + if (!p) { + throw new TomlError("trying to redefine an already defined table or value", { + toml, + ptr }); } - resolve(state, ref, to) { - if (!state.mainstay.debug) { - return; - } - const log2 = { type: "resolve", ref: ref.display, to, path: state.path }; - state.mainstay.debug.push(log2); - } - value(state, by, from3, to, name) { - if (!state.mainstay.debug || deepEqual(from3, to)) { - return; - } - const log2 = { type: "value", by, from: from3, to, path: state.path }; - if (name) { - log2.name = name; - } - state.mainstay.debug.push(log2); - } - _record(schema, each) { - const log2 = this._sources.get(schema); - if (log2) { - each(log2); - return; - } - const sources = this._combos.get(schema); - for (const source of sources) { - this._record(source, each); - } - } - _scan(schema, _path) { - const path8 = _path || []; - let log2 = this._sources.get(schema); - if (!log2) { - log2 = { - paths: /* @__PURE__ */ new Set(), - entry: false, - rule: {}, - valid: /* @__PURE__ */ new Set(), - invalid: /* @__PURE__ */ new Set() - }; - this._sources.set(schema, log2); - } - if (path8.length) { - log2.paths.add(path8); - } - const each = (sub, source) => { - const subId = internals.id(sub, source); - this._scan(sub, path8.concat(subId)); - }; - schema.$_modify({ each, ref: false }); + let v2 = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt); + p[1][p[0]] = v2[0]; + ptr = v2[1]; + } + ptr = skipVoid(toml, ptr, true); + if (toml[ptr] && toml[ptr] !== "\n" && toml[ptr] !== "\r") { + throw new TomlError("each key-value declaration must be followed by an end-of-line", { + toml, + ptr + }); + } + ptr = skipVoid(toml, ptr); + } + return res; +} +var BARE_KEY = /^[a-z0-9-_]+$/i; +function extendedTypeOf(obj) { + let type = typeof obj; + if (type === "object") { + if (Array.isArray(obj)) + return "array"; + if (obj instanceof Date) + return "date"; + } + return type; +} +function isArrayOfTables(obj) { + for (let i2 = 0; i2 < obj.length; i2++) { + if (extendedTypeOf(obj[i2]) !== "object") + return false; + } + return obj.length != 0; +} +function formatString(s) { + return JSON.stringify(s).replace(/\x7f/g, "\\u007f"); +} +function stringifyValue(val, type, depth, numberAsFloat) { + if (depth === 0) { + throw new Error("Could not stringify the object: maximum object depth exceeded"); + } + if (type === "number") { + if (isNaN(val)) + return "nan"; + if (val === Infinity) + return "inf"; + if (val === -Infinity) + return "-inf"; + if (numberAsFloat && Number.isInteger(val)) + return val.toFixed(1); + return val.toString(); + } + if (type === "bigint" || type === "boolean") { + return val.toString(); + } + if (type === "string") { + return formatString(val); + } + if (type === "date") { + if (isNaN(val.getTime())) { + throw new TypeError("cannot serialize invalid date"); + } + return val.toISOString(); + } + if (type === "object") { + return stringifyInlineTable(val, depth, numberAsFloat); + } + if (type === "array") { + return stringifyArray(val, depth, numberAsFloat); + } +} +function stringifyInlineTable(obj, depth, numberAsFloat) { + let keys = Object.keys(obj); + if (keys.length === 0) + return "{}"; + let res = "{ "; + for (let i2 = 0; i2 < keys.length; i2++) { + let k = keys[i2]; + if (i2) + res += ", "; + res += BARE_KEY.test(k) ? k : formatString(k); + res += " = "; + res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat); + } + return res + " }"; +} +function stringifyArray(array2, depth, numberAsFloat) { + if (array2.length === 0) + return "[]"; + let res = "[ "; + for (let i2 = 0; i2 < array2.length; i2++) { + if (i2) + res += ", "; + if (array2[i2] === null || array2[i2] === void 0) { + throw new TypeError("arrays cannot contain null or undefined values"); + } + res += stringifyValue(array2[i2], extendedTypeOf(array2[i2]), depth - 1, numberAsFloat); + } + return res + " ]"; +} +function stringifyArrayTable(array2, key, depth, numberAsFloat) { + if (depth === 0) { + throw new Error("Could not stringify the object: maximum object depth exceeded"); + } + let res = ""; + for (let i2 = 0; i2 < array2.length; i2++) { + res += `[[${key}]] +`; + res += stringifyTable(array2[i2], key, depth, numberAsFloat); + res += "\n\n"; + } + return res; +} +function stringifyTable(obj, prefix, depth, numberAsFloat) { + if (depth === 0) { + throw new Error("Could not stringify the object: maximum object depth exceeded"); + } + let preamble = ""; + let tables = ""; + let keys = Object.keys(obj); + for (let i2 = 0; i2 < keys.length; i2++) { + let k = keys[i2]; + if (obj[k] !== null && obj[k] !== void 0) { + let type = extendedTypeOf(obj[k]); + if (type === "symbol" || type === "function") { + throw new TypeError(`cannot serialize values of type '${type}'`); } - _combine(merged, sources) { - this._combos.set(merged, sources); + let key = BARE_KEY.test(k) ? k : formatString(k); + if (type === "array" && isArrayOfTables(obj[k])) { + tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat); + } else if (type === "object") { + let tblKey = prefix ? `${prefix}.${key}` : key; + tables += `[${tblKey}] +`; + tables += stringifyTable(obj[k], tblKey, depth - 1, numberAsFloat); + tables += "\n\n"; + } else { + preamble += key; + preamble += " = "; + preamble += stringifyValue(obj[k], type, depth, numberAsFloat); + preamble += "\n"; } + } + } + return `${preamble} +${tables}`.trim(); +} +function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) { + if (extendedTypeOf(obj) !== "object") { + throw new TypeError("stringify can only be called with an object"); + } + return stringifyTable(obj, "", maxDepth, numbersAsFloat); +} +var commands_exports = {}; +__export(commands_exports, { + deploy: () => module3, + eventsAfter: () => module4, + get: () => module5, + hash: () => module6, + keygen: () => module7, + manifest: () => module8, + migrate: () => module9, + pin: () => module10, + serve: () => module11, + upload: () => module2, + verifySignature: () => module12, + version: () => module13 +}); +init_zod(); +init_functions(); +init_esm(); +init_esm2(); +init_esm(); +init_esm3(); +var listenKey = (evt) => `events/${evt}/listeners`; +var esm_default4 = esm_default("sbp/selectors/register", { + "okTurtles.events/_init": function() { + this.errorHandler = (event, e2) => { + console.error(`[okTurtles.events] Error at handler for ${event}`, e2); }; - internals.message = function(item) { - const path8 = item.paths ? Errors.path(item.paths[0]) + (item.rule ? ":" : "") : ""; - return `${path8}${item.rule || ""} (${item.status})`; + }, + "okTurtles.events/on": function(event, handler) { + esm_default("okTurtles.data/add", listenKey(event), handler); + return () => esm_default("okTurtles.events/off", event, handler); + }, + "okTurtles.events/once": function(event, handler) { + const cbWithOff = (...args) => { + handler(...args); + esm_default("okTurtles.events/off", event, cbWithOff); }; - internals.id = function(schema, { source, name, path: path8, key }) { - if (schema._flags.id) { - return schema._flags.id; - } - if (key) { - return key; + return esm_default("okTurtles.events/on", event, cbWithOff); + }, + "okTurtles.events/emit": function(event, ...data) { + var _a2; + for (const listener of esm_default("okTurtles.data/get", listenKey(event)) || []) { + try { + listener(...data); + } catch (e2) { + (_a2 = this.errorHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, event, e2); } - name = `@${name}`; - if (source === "terms") { - return [name, path8[Math.min(path8.length - 1, 1)]]; + } + }, + // almost identical to Vue.prototype.$off, except we require `event` argument + "okTurtles.events/off": function(event, handler) { + if (handler) { + esm_default("okTurtles.data/remove", listenKey(event), handler); + } else { + esm_default("okTurtles.data/delete", listenKey(event)); + } + }, + "okTurtles.events/setErrorHandler": function(errorHandler2) { + this.errorHandler = errorHandler2; + } +}); +init_esm(); +init_esm4(); +init_functions(); +init_esm(); +init_esm4(); +var NOTIFICATION_TYPE = Object.freeze({ + ENTRY: "entry", + DELETION: "deletion", + KV: "kv", + KV_FILTER: "kv_filter", + PING: "ping", + PONG: "pong", + PUB: "pub", + SUB: "sub", + UNSUB: "unsub", + VERSION_INFO: "version_info" +}); +var REQUEST_TYPE = Object.freeze({ + PUB: "pub", + SUB: "sub", + UNSUB: "unsub", + PUSH_ACTION: "push_action", + KV_FILTER: "kv_filter" +}); +var RESPONSE_TYPE = Object.freeze({ + ERROR: "error", + OK: "ok" +}); +var PUSH_SERVER_ACTION_TYPE = Object.freeze({ + SEND_PUBLIC_KEY: "send-public-key", + STORE_SUBSCRIPTION: "store-subscription", + DELETE_SUBSCRIPTION: "delete-subscription", + SEND_PUSH_NOTIFICATION: "send-push-notification" +}); +var defaultOptions = { + logPingMessages: !process.env.CI, + pingTimeout: 45e3, + maxReconnectionDelay: 6e4, + maxRetries: 10, + minReconnectionDelay: 500, + reconnectOnDisconnection: true, + reconnectOnOnline: true, + // Defaults to false to avoid reconnection attempts in case the server doesn't + // respond because of a failed authentication. + reconnectOnTimeout: false, + reconnectionDelayGrowFactor: 2, + timeout: 6e4, + maxOpRetries: 4, + opRetryInterval: 2e3 +}; +var PUBSUB_ERROR = "pubsub-error"; +var PUBSUB_RECONNECTION_ATTEMPT = "pubsub-reconnection-attempt"; +var PUBSUB_RECONNECTION_FAILED = "pubsub-reconnection-failed"; +var PUBSUB_RECONNECTION_SCHEDULED = "pubsub-reconnection-scheduled"; +var PUBSUB_RECONNECTION_SUCCEEDED = "pubsub-reconnection-succeeded"; +var PUBSUB_SUBSCRIPTION_SUCCEEDED = "pubsub-subscription-succeeded"; +var TieredMap = class extends Map { + tGet(k1, k2) { + return this.get(k1)?.get(k2); + } + tHas(k1, k2) { + return !!this.get(k1)?.has(k2); + } + tSet(k1, k2, v2) { + let submap = this.get(k1); + if (!submap) { + submap = /* @__PURE__ */ new Map(); + this.set(k1, submap); + } + return submap.set(k2, v2); + } + tDelete(k1, k2) { + const submap = this.get(k1); + if (submap) { + const result = submap.delete(k2); + if (submap.size === 0) { + this.delete(k1); } - return name; - }; - internals.sub = function(paths, skipped) { - for (const path8 of paths) { - for (const skip of skipped) { - if (deepEqual(path8.slice(0, skip.length), skip)) { - return true; - } + return result; + } + return false; + } + tClear(k1) { + this.delete(k1); + } +}; +var isKvFilterFresh = (ourKvFilter, theirKvFilter) => { + if (!ourKvFilter !== !theirKvFilter) { + return false; + } else if (ourKvFilter && theirKvFilter) { + if (ourKvFilter.length !== theirKvFilter.length) { + return false; + } else { + const sortedA = [...ourKvFilter].sort(); + const sortedB = [...theirKvFilter].sort(); + for (let i2 = 0; i2 < sortedA.length; i2++) { + if (sortedA[i2] !== sortedB[i2]) { + return false; } } - return false; - }; - internals.debug = function(state, event) { - if (state.mainstay.debug) { - event.path = state.debug ? [...state.path, state.debug] : state.path; - state.mainstay.debug.push(event); + } + } + return true; +}; +var pubPayloadFactory = (client, channelID) => () => { + const kvFilter = client.kvFilter.get(channelID); + return kvFilter ? { kvFilter, channelID } : { channelID }; +}; +function runWithRetry(client, channelID, type, getPayload) { + let attemptNo = 0; + const { socket, options: options2 } = client; + const instance = {}; + client.pendingOperations.tSet(type, channelID, instance); + const send = () => { + if (client.socket !== socket || socket?.readyState !== WebSocket.OPEN) + return; + const currentInstance = client.pendingOperations.tGet(type, channelID); + if (currentInstance !== instance) + return; + if (attemptNo++ > options2.maxOpRetries) { + console.warn(`[pubsub] Giving up ${type} for channel`, channelID); + client.pendingOperations.tDelete(type, channelID); + return; + } + const payload = getPayload(); + socket.send(createRequest(type, payload)); + const minDelay = (attemptNo - 1) * options2.opRetryInterval; + const jitter = randomIntFromRange(0, options2.opRetryInterval); + const delay2 = Math.min(200, minDelay) + jitter; + setTimeout(send, delay2); + }; + send(); +} +function createClient(url2, options2 = {}) { + const client = { + customEventHandlers: options2.handlers || {}, + // The current number of connection attempts that failed. + // Reset to 0 upon successful connection. + // Used to compute how long to wait before the next reconnection attempt. + failedConnectionAttempts: 0, + isLocal: /\/\/(localhost|127\.0\.0\.1)([:?/]|$)/.test(url2), + // True if this client has never been connected yet. + isNew: true, + listeners: /* @__PURE__ */ Object.create(null), + messageHandlers: { ...defaultMessageHandlers, ...options2.messageHandlers }, + nextConnectionAttemptDelayID: void 0, + options: { ...defaultOptions, ...options2 }, + pendingOperations: new TieredMap(), + pingTimeoutID: void 0, + shouldReconnect: true, + // The underlying WebSocket object. + // A new one is necessary for every connection or reconnection attempt. + socket: null, + subscriptionSet: /* @__PURE__ */ new Set(), + kvFilter: /* @__PURE__ */ new Map(), + connectionTimeoutID: void 0, + url: url2.replace(/^http/, "ws"), + ...publicMethods + }; + for (const name of Object.keys(defaultClientEventHandlers)) { + client.listeners[name] = (event) => { + try { + defaultClientEventHandlers[name].call(client, event); + client.customEventHandlers[name]?.call(client, event); + } catch (error2) { + esm_default("okTurtles.events/emit", PUBSUB_ERROR, client, error2?.message); } }; } -}); -var require_modify2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/modify.js"(exports2) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Common = require_common3(); - var Ref = require_ref2(); - var internals = {}; - exports2.Ids = internals.Ids = class { - constructor() { - this._byId = /* @__PURE__ */ new Map(); - this._byKey = /* @__PURE__ */ new Map(); - this._schemaChain = false; - } - clone() { - const clone2 = new internals.Ids(); - clone2._byId = new Map(this._byId); - clone2._byKey = new Map(this._byKey); - clone2._schemaChain = this._schemaChain; - return clone2; - } - concat(source) { - if (source._schemaChain) { - this._schemaChain = true; - } - for (const [id, value] of source._byId.entries()) { - assert2(!this._byKey.has(id), "Schema id conflicts with existing key:", id); - this._byId.set(id, value); - } - for (const [key, value] of source._byKey.entries()) { - assert2(!this._byId.has(key), "Schema key conflicts with existing id:", key); - this._byKey.set(key, value); - } - } - fork(path8, adjuster, root) { - const chain = this._collect(path8); - chain.push({ schema: root }); - const tail = chain.shift(); - let adjusted = { id: tail.id, schema: adjuster(tail.schema) }; - assert2(Common.isSchema(adjusted.schema), "adjuster function failed to return a joi schema type"); - for (const node of chain) { - adjusted = { id: node.id, schema: internals.fork(node.schema, adjusted.id, adjusted.schema) }; - } - return adjusted.schema; - } - labels(path8, behind = []) { - const current = path8[0]; - const node = this._get(current); - if (!node) { - return [...behind, ...path8].join("."); + if (typeof self === "object" && self instanceof EventTarget) { + for (const name of globalEventNames) { + globalEventMap.set(name, client.listeners[name]); + } + } + if (!client.options.manual) { + client.connect(); + } + return client; +} +function createMessage(type, data, meta) { + const message = { ...meta, type, data }; + let string3; + const stringify2 = function() { + if (!string3) + string3 = JSON.stringify(this); + return string3; + }; + Object.defineProperties(message, { + [Symbol.toPrimitive]: { + value: stringify2 + } + }); + return message; +} +function createKvMessage(channelID, key, data) { + return JSON.stringify({ type: NOTIFICATION_TYPE.KV, channelID, key, data }); +} +function createPubMessage(channelID, data) { + return JSON.stringify({ type: NOTIFICATION_TYPE.PUB, channelID, data }); +} +function createRequest(type, data) { + return JSON.stringify(Object.assign({ type }, data)); +} +var defaultClientEventHandlers = { + // Emitted when the connection is closed. + close(event) { + const client = this; + console.debug("[pubsub] Event: close", event.code, event.reason); + client.failedConnectionAttempts++; + if (client.socket) { + for (const name of socketEventNames) { + client.socket.removeEventListener(name, client.listeners[name]); + } + } + client.socket = null; + client.clearAllTimers(); + if (client.shouldReconnect) { + const pendingSubscriptionMap = client.pendingOperations.get(REQUEST_TYPE.SUB); + if (pendingSubscriptionMap) { + for (const [channelID] of pendingSubscriptionMap) { + pendingSubscriptionMap.set(channelID, {}); + } + } + client.subscriptionSet.forEach((channelID) => { + if (!client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID)) { + client.pendingOperations.tSet(REQUEST_TYPE.SUB, channelID, {}); } - const forward = path8.slice(1); - behind = [...behind, node.schema._flags.label || current]; - if (!forward.length) { - return behind.join("."); + }); + } + client.subscriptionSet.clear(); + client.pendingOperations.tClear(REQUEST_TYPE.UNSUB); + client.pendingOperations.tClear(REQUEST_TYPE.KV_FILTER); + if (client.shouldReconnect && client.options.reconnectOnDisconnection) { + if (client.failedConnectionAttempts > client.options.maxRetries) { + esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_FAILED, client); + } else { + if (!isDefinetelyOffline() || client.isLocal) { + client.scheduleConnectionAttempt(); } - return node.schema._ids.labels(forward, behind); } - reach(path8, behind = []) { - const current = path8[0]; - const node = this._get(current); - assert2(node, "Schema does not contain path", [...behind, ...path8].join(".")); - const forward = path8.slice(1); - if (!forward.length) { - return node.schema; - } - return node.schema._ids.reach(forward, [...behind, current]); + } + }, + // Emitted when an error has occured. + // The socket will be closed automatically by the engine if necessary. + error(event) { + const client = this; + console.warn("[pubsub] Event: error", event); + clearTimeout(client.pingTimeoutID); + }, + // Emitted when a message is received. + // The connection will be terminated if the message is malformed or has an + // unexpected data type (e.g. binary instead of text). + message(event) { + const client = this; + const { data } = event; + if (typeof data !== "string") { + esm_default("okTurtles.events/emit", PUBSUB_ERROR, client, { + message: `Wrong data type: ${typeof data}` + }); + return client.destroy(); + } + let msg = { type: "" }; + try { + msg = messageParser(data); + } catch (error2) { + esm_default("okTurtles.events/emit", PUBSUB_ERROR, client, { + message: `Malformed message: ${error2?.message}` + }); + return client.destroy(); + } + const handler = client.messageHandlers[msg.type]; + if (handler) { + handler.call(client, msg); + } else { + throw new Error(`Unhandled message type: ${msg.type}`); + } + }, + offline() { + console.info("[pubsub] Event: offline"); + const client = this; + client.clearAllTimers(); + client.failedConnectionAttempts = 0; + client.socket?.close(); + }, + online() { + console.info("[pubsub] Event: online"); + const client = this; + if (client.options.reconnectOnOnline && client.shouldReconnect) { + if (!client.socket) { + client.failedConnectionAttempts = 0; + client.scheduleConnectionAttempt(); } - register(schema, { key } = {}) { - if (!schema || !Common.isSchema(schema)) { - return; - } - if (schema.$_property("schemaChain") || schema._ids._schemaChain) { - this._schemaChain = true; - } - const id = schema._flags.id; - if (id) { - const existing = this._byId.get(id); - assert2(!existing || existing.schema === schema, "Cannot add different schemas with the same id:", id); - assert2(!this._byKey.has(id), "Schema id conflicts with existing key:", id); - this._byId.set(id, { schema, id }); - } - if (key) { - assert2(!this._byKey.has(key), "Schema already contains key:", key); - assert2(!this._byId.has(key), "Schema key conflicts with existing id:", key); - this._byKey.set(key, { schema, id: key }); - } + } + }, + // Emitted when the connection is established. + open() { + console.debug("[pubsub] Event: open"); + const client = this; + const { options: options2 } = this; + client.connectionTimeUsed = void 0; + client.clearAllTimers(); + esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_SUCCEEDED, client); + client.failedConnectionAttempts = -1; + client.isNew = false; + if (options2.pingTimeout > 0 && options2.pingTimeout < Infinity) { + client.pingTimeoutID = setTimeout(() => { + client.socket?.close(); + }, options2.pingTimeout); + } + for (const [channelID] of client.pendingOperations.get(REQUEST_TYPE.SUB) || []) { + runWithRetry(client, channelID, REQUEST_TYPE.SUB, pubPayloadFactory(client, channelID)); + } + }, + "reconnection-attempt"() { + console.info("[pubsub] Trying to reconnect..."); + }, + "reconnection-succeeded"() { + console.info("[pubsub] Connection re-established"); + }, + "reconnection-failed"() { + console.warn("[pubsub] Reconnection failed"); + const client = this; + client.destroy(); + }, + "reconnection-scheduled"(event) { + const { delay: delay2, nth } = event.detail; + console.info(`[pubsub] Scheduled connection attempt ${nth} in ~${delay2} ms`); + }, + "subscription-succeeded"(event) { + const { channelID } = event.detail; + console.debug(`[pubsub] Subscribed to channel ${channelID}`); + } +}; +var defaultMessageHandlers = { + [NOTIFICATION_TYPE.ENTRY](msg) { + console.debug("[pubsub] Received ENTRY:", msg); + }, + [NOTIFICATION_TYPE.PING]({ data }) { + const client = this; + if (client.options.logPingMessages) { + console.debug(`[pubsub] Ping received in ${Date.now() - Number(data)} ms`); + } + client.socket?.send(createMessage(NOTIFICATION_TYPE.PONG, data)); + clearTimeout(client.pingTimeoutID); + client.pingTimeoutID = setTimeout(() => { + client.socket?.close(); + }, client.options.pingTimeout); + }, + [NOTIFICATION_TYPE.PUB]({ channelID, data }) { + console.log(`[pubsub] Received data from channel ${channelID}:`, data); + }, + [NOTIFICATION_TYPE.KV]({ channelID, key, data }) { + console.log(`[pubsub] Received KV update from channel ${channelID} ${key}:`, data); + }, + [NOTIFICATION_TYPE.SUB](msg) { + console.debug(`[pubsub] Ignoring ${msg.type} message:`, msg.data); + }, + [NOTIFICATION_TYPE.UNSUB](msg) { + console.debug(`[pubsub] Ignoring ${msg.type} message:`, msg.data); + }, + [RESPONSE_TYPE.ERROR]({ data }) { + const { type, channelID, reason } = data; + console.warn(`[pubsub] Received ERROR response for ${type} request to ${channelID}`); + const client = this; + switch (type) { + case REQUEST_TYPE.SUB: { + console.warn(`[pubsub] Could not subscribe to ${channelID}: ${reason}`); + client.pendingOperations.tDelete(REQUEST_TYPE.SUB, channelID); + break; } - reset() { - this._byId = /* @__PURE__ */ new Map(); - this._byKey = /* @__PURE__ */ new Map(); - this._schemaChain = false; + case REQUEST_TYPE.UNSUB: { + console.warn(`[pubsub] Could not unsubscribe from ${channelID}: ${reason}`); + client.pendingOperations.tDelete(REQUEST_TYPE.UNSUB, channelID); + break; } - _collect(path8, behind = [], nodes = []) { - const current = path8[0]; - const node = this._get(current); - assert2(node, "Schema does not contain path", [...behind, ...path8].join(".")); - nodes = [node, ...nodes]; - const forward = path8.slice(1); - if (!forward.length) { - return nodes; - } - return node.schema._ids._collect(forward, [...behind, current], nodes); + case REQUEST_TYPE.PUSH_ACTION: { + const { actionType, message } = data; + console.warn(`[pubsub] Received ERROR for PUSH_ACTION request with the action type '${actionType}' and the following message: ${message}`); + break; } - _get(id) { - return this._byId.get(id) || this._byKey.get(id); + case REQUEST_TYPE.KV_FILTER: { + console.warn(`[pubsub] Could not set KV filter for ${channelID}: ${reason}`); + client.pendingOperations.tDelete(REQUEST_TYPE.KV_FILTER, channelID); + break; } - }; - internals.fork = function(schema, id, replacement) { - const each = (item, { key }) => { - if (id === (item._flags.id || key)) { - return replacement; - } - }; - const obj = exports2.schema(schema, { each, ref: false }); - return obj ? obj.$_mutateRebuild() : schema; - }; - exports2.schema = function(schema, options2) { - let obj; - for (const name in schema._flags) { - if (name[0] === "_") { - continue; - } - const result = internals.scan(schema._flags[name], { source: "flags", name }, options2); - if (result !== void 0) { - obj = obj || schema.clone(); - obj._flags[name] = result; - } + default: { + console.error(`[pubsub] Malformed response: invalid request type ${type}`); } - for (let i2 = 0; i2 < schema._rules.length; ++i2) { - const rule = schema._rules[i2]; - const result = internals.scan(rule.args, { source: "rules", name: rule.name }, options2); - if (result !== void 0) { - obj = obj || schema.clone(); - const clone2 = Object.assign({}, rule); - clone2.args = result; - obj._rules[i2] = clone2; - const existingUnique = obj._singleRules.get(rule.name); - if (existingUnique === rule) { - obj._singleRules.set(rule.name, clone2); + } + }, + [RESPONSE_TYPE.OK]({ data: { type, channelID, kvFilter } }) { + const client = this; + switch (type) { + case REQUEST_TYPE.SUB: { + if (client.pendingOperations.tHas(REQUEST_TYPE.SUB, channelID)) { + client.pendingOperations.tDelete(REQUEST_TYPE.SUB, channelID); + client.subscriptionSet.add(channelID); + esm_default("okTurtles.events/emit", PUBSUB_SUBSCRIPTION_SUCCEEDED, client, { channelID }); + const ourKvFilter = client.kvFilter.get(channelID); + if (!isKvFilterFresh(ourKvFilter, kvFilter)) { + console.debug(`[pubsub] Subscribed to ${channelID}, need to set new KV filter`); + this.setKvFilter(channelID, ourKvFilter); } + } else { + console.debug(`[pubsub] Received unexpected sub for ${channelID}`); } + break; } - for (const name in schema.$_terms) { - if (name[0] === "_") { - continue; - } - const result = internals.scan(schema.$_terms[name], { source: "terms", name }, options2); - if (result !== void 0) { - obj = obj || schema.clone(); - obj.$_terms[name] = result; + case REQUEST_TYPE.UNSUB: { + if (client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID)) { + console.debug(`[pubsub] Unsubscribed from ${channelID}`); + client.pendingOperations.tDelete(REQUEST_TYPE.UNSUB, channelID); + client.subscriptionSet.delete(channelID); + } else { + console.debug(`[pubsub] Received unexpected unsub for ${channelID}`); } + break; } - return obj; - }; - internals.scan = function(item, source, options2, _path, _key) { - const path8 = _path || []; - if (item === null || typeof item !== "object") { - return; - } - let clone2; - if (Array.isArray(item)) { - for (let i2 = 0; i2 < item.length; ++i2) { - const key = source.source === "terms" && source.name === "keys" && item[i2].key; - const result = internals.scan(item[i2], source, options2, [i2, ...path8], key); - if (result !== void 0) { - clone2 = clone2 || item.slice(); - clone2[i2] = result; + case REQUEST_TYPE.KV_FILTER: { + if (client.pendingOperations.tHas(REQUEST_TYPE.KV_FILTER, channelID)) { + const ourKvFilter = client.kvFilter.get(channelID); + if (isKvFilterFresh(ourKvFilter, kvFilter)) { + console.debug(`[pubsub] Set KV filter for ${channelID}`, kvFilter); + client.pendingOperations.tDelete(REQUEST_TYPE.KV_FILTER, channelID); + } else { + console.debug(`[pubsub] Received stale KV filter ack for ${channelID}`, kvFilter, ourKvFilter); } + } else { + console.debug(`[pubsub] Received unexpected kv-filter for ${channelID}`); } - return clone2; - } - if (options2.schema !== false && Common.isSchema(item) || options2.ref !== false && Ref.isRef(item)) { - const result = options2.each(item, { ...source, path: path8, key: _key }); - if (result === item) { - return; - } - return result; + break; } - for (const key in item) { - if (key[0] === "_") { - continue; - } - const result = internals.scan(item[key], source, options2, [key, ...path8], _key); - if (result !== void 0) { - clone2 = clone2 || Object.assign({}, item); - clone2[key] = result; - } + default: { + console.error(`[pubsub] Malformed response: invalid request type ${type}`); } - return clone2; - }; + } } -}); -var require_state3 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/state.js"(exports2, module14) { - "use strict"; - var { clone: clone2, reach } = require_lib(); - var Common = require_common3(); - var internals = { - value: Symbol("value") +}; +var globalEventNames = ["offline", "online"]; +var socketEventNames = ["close", "error", "message", "open"]; +var globalEventMap = /* @__PURE__ */ new Map(); +if (typeof self === "object" && self instanceof EventTarget) { + for (const name of globalEventNames) { + const handler = (ev) => { + const h2 = globalEventMap.get(name); + return h2?.(ev); }; - module14.exports = internals.State = class { - constructor(path8, ancestors, state) { - this.path = path8; - this.ancestors = ancestors; - this.mainstay = state.mainstay; - this.schemas = state.schemas; - this.debug = null; + self.addEventListener(name, handler, false); + } +} +var isDefinetelyOffline = () => typeof navigator === "object" && navigator.onLine === false; +var messageParser = (data) => { + const msg = JSON.parse(data); + if (typeof msg !== "object" || msg === null) { + throw new TypeError("Message is null or not an object"); + } + const { type } = msg; + if (typeof type !== "string" || type === "") { + throw new TypeError("Message type must be a non-empty string"); + } + return msg; +}; +var publicMethods = { + clearAllTimers() { + const client = this; + clearTimeout(client.connectionTimeoutID); + clearTimeout(client.nextConnectionAttemptDelayID); + clearTimeout(client.pingTimeoutID); + client.connectionTimeoutID = void 0; + client.nextConnectionAttemptDelayID = void 0; + client.pingTimeoutID = void 0; + }, + // Performs a connection or reconnection attempt. + connect() { + const client = this; + if (client.socket !== null) { + throw new Error("connect() can only be called if there is no current socket."); + } + if (client.nextConnectionAttemptDelayID) { + throw new Error("connect() must not be called during a reconnection delay."); + } + if (!client.shouldReconnect) { + throw new Error("connect() should no longer be called on this instance."); + } + client.socket = new WebSocket(client.url); + client.socket.send = function(data) { + const send = WebSocket.prototype.send.bind(this); + if (typeof data === "object" && typeof data[Symbol.toPrimitive] === "function") { + return send(data[Symbol.toPrimitive]()); } - localize(path8, ancestors = null, schema = null) { - const state = new internals.State(path8, ancestors, this); - if (schema && state.schemas) { - state.schemas = [internals.schemas(schema), ...state.schemas]; + return send(data); + }; + if (client.options.timeout) { + const start = performance.now(); + client.connectionTimeoutID = setTimeout(() => { + client.connectionTimeoutID = void 0; + if (client.options.reconnectOnTimeout) { + client.connectionTimeUsed = performance.now() - start; } - return state; + client.socket?.close(4e3, "timeout"); + }, client.options.timeout); + } + for (const name of socketEventNames) { + client.socket.addEventListener(name, client.listeners[name]); + } + }, + /** + * Immediately close the socket, stop listening for events and clear any cache. + * + * This method is used in unit tests. + * - In particular, no 'close' event handler will be called. + * - Any incoming or outgoing buffered data will be discarded. + * - Any pending messages will be discarded. + */ + destroy() { + const client = this; + client.clearAllTimers(); + client.pendingOperations.clear(); + client.subscriptionSet.clear(); + if (typeof self === "object" && self instanceof EventTarget) { + for (const name of globalEventNames) { + globalEventMap.delete(name); } - nest(schema, debug) { - const state = new internals.State(this.path, this.ancestors, this); - state.schemas = state.schemas && [internals.schemas(schema), ...state.schemas]; - state.debug = debug; - return state; + } + if (client.socket) { + for (const name of socketEventNames) { + client.socket.removeEventListener(name, client.listeners[name]); + } + client.socket.close(); + } + client.listeners = /* @__PURE__ */ Object.create(null); + client.socket = null; + client.shouldReconnect = false; + }, + getNextRandomDelay() { + const client = this; + const { maxReconnectionDelay, minReconnectionDelay, reconnectionDelayGrowFactor } = client.options; + const minDelay = minReconnectionDelay * reconnectionDelayGrowFactor ** client.failedConnectionAttempts; + const maxDelay = minDelay * reconnectionDelayGrowFactor; + const connectionTimeUsed = client.connectionTimeUsed; + client.connectionTimeUsed = void 0; + return Math.min( + // See issue #1943: Have the connection time used 'eat into' the + // reconnection time used + Math.max(minReconnectionDelay, connectionTimeUsed ? maxReconnectionDelay - connectionTimeUsed : maxReconnectionDelay), + Math.round(minDelay + (0, Math.random)() * (maxDelay - minDelay)) + ); + }, + // Schedules a connection attempt to happen after a delay computed according to + // a randomized exponential backoff algorithm variant. + scheduleConnectionAttempt() { + const client = this; + if (!client.shouldReconnect) { + throw new Error("Cannot call `scheduleConnectionAttempt()` when `shouldReconnect` is false."); + } + if (client.nextConnectionAttemptDelayID) { + return console.warn("[pubsub] A reconnection attempt is already scheduled."); + } + const delay2 = client.getNextRandomDelay(); + const nth = client.failedConnectionAttempts + 1; + client.nextConnectionAttemptDelayID = setTimeout(() => { + esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_ATTEMPT, client); + client.nextConnectionAttemptDelayID = void 0; + client.connect(); + }, delay2); + esm_default("okTurtles.events/emit", PUBSUB_RECONNECTION_SCHEDULED, client, { delay: delay2, nth }); + }, + // Can be used to send ephemeral messages outside of any contract log. + // Does nothing if the socket is not in the OPEN state. + pub(channelID, data) { + if (this.socket?.readyState === WebSocket.OPEN) { + this.socket.send(createPubMessage(channelID, data)); + } + }, + /** + * Sends a SUB request to the server as soon as possible. + * + * - The given channel ID will be cached until we get a relevant server + * response, allowing us to resend the same request if necessary. + * - Any identical UNSUB request that has not been sent yet will be cancelled. + * - Calling this method again before the server has responded has no effect. + * @param channelID - The ID of the channel whose updates we want to subscribe to. + */ + sub(channelID) { + const client = this; + if (!client.pendingOperations.tHas(REQUEST_TYPE.SUB, channelID) && !client.subscriptionSet.has(channelID)) { + client.pendingOperations.tDelete(REQUEST_TYPE.UNSUB, channelID); + runWithRetry(client, channelID, REQUEST_TYPE.SUB, pubPayloadFactory(client, channelID)); + } + }, + /** + * Sends a KV_FILTER request to the server as soon as possible. + */ + setKvFilter(channelID, kvFilter) { + const client = this; + if (kvFilter) { + client.kvFilter.set(channelID, kvFilter); + } else { + client.kvFilter.delete(channelID); + } + if (client.subscriptionSet.has(channelID) && !client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID)) { + runWithRetry(client, channelID, REQUEST_TYPE.KV_FILTER, pubPayloadFactory(client, channelID)); + } + }, + /** + * Sends an UNSUB request to the server as soon as possible. + * + * - The given channel ID will be cached until we get a relevant server + * response, allowing us to resend the same request if necessary. + * - Any identical SUB request that has not been sent yet will be cancelled. + * - Calling this method again before the server has responded has no effect. + * @param channelID - The ID of the channel whose updates we want to unsubscribe from. + */ + unsub(channelID) { + const client = this; + if (!client.pendingOperations.tHas(REQUEST_TYPE.UNSUB, channelID) && (client.subscriptionSet.has(channelID) || client.pendingOperations.tHas(REQUEST_TYPE.SUB, channelID))) { + client.pendingOperations.tDelete(REQUEST_TYPE.SUB, channelID); + client.kvFilter.delete(channelID); + runWithRetry(client, channelID, REQUEST_TYPE.UNSUB, () => ({ channelID })); + } + } +}; +for (const name of Object.keys(defaultClientEventHandlers)) { + if (name === "error" || !socketEventNames.includes(name)) { + esm_default("okTurtles.events/on", `pubsub-${name}`, (target, detail) => { + const ev = new CustomEvent(name, { detail }); + target.listeners[name].call(target, ev); + }); + } +} +init_esm6(); +init_errors3(); +var CHELONIA_RESET = "chelonia-reset"; +var CONTRACT_IS_SYNCING = "contract-is-syncing"; +var CONTRACTS_MODIFIED = "contracts-modified"; +var EVENT_HANDLED = "event-handled"; +var EVENT_PUBLISHED = "event-published"; +var EVENT_PUBLISHING_ERROR = "event-publishing-error"; +var CONTRACT_REGISTERED = "contract-registered"; +var CONTRACT_IS_PENDING_KEY_REQUESTS = "contract-is-pending-key-requests"; +var CONTRACT_HAS_RECEIVED_KEYS = "contract-has-received-keys"; +var PERSISTENT_ACTION_FAILURE = "persistent-action-failure"; +var PERSISTENT_ACTION_SUCCESS = "persistent-action-success"; +var PERSISTENT_ACTION_TOTAL_FAILURE = "persistent-action-total_failure"; +init_SPMessage(); +init_esm(); +var chelonia_utils_default = esm_default("sbp/selectors/register", { + // This selector is a wrapper for the `chelonia/kv/set` selector that uses + // the contract queue and allows referring to keys by name, with default key + // names set to `csk` and `cek` for signatures and encryption, respectively. + // For most 'simple' use cases, this selector is a better choice than + // `chelonia/kv/set`. However, the `chelonia/kv/set` primitive is needed if + // the queueing logic needs to be more advanced, the key to use requires + // custom logic or _if the `onconflict` callback also needs to be queued_. + "chelonia/kv/queuedSet": ({ contractID, key, data, onconflict, ifMatch, encryptionKeyName = "cek", signingKeyName = "csk" }) => { + return esm_default("chelonia/queueInvocation", contractID, () => { + return esm_default("chelonia/kv/set", contractID, key, data, { + ifMatch, + encryptionKeyId: esm_default("chelonia/contract/currentKeyIdByName", contractID, encryptionKeyName), + signingKeyId: esm_default("chelonia/contract/currentKeyIdByName", contractID, signingKeyName), + onconflict + }); + }); + } +}); +init_encryptedData(); +var m = /;\s*boundary=(?:"([0-9a-zA-Z'()+_,\-./:=? ]{0,69}[0-9a-zA-Z'()+_,\-./:=?])"|([0-9a-zA-Z'+_\-.]{0,69}[0-9a-zA-Z'+_\-.]))/; +var M = (a) => new ReadableStream({ pull(r) { + if (ArrayBuffer.isView(a)) r.enqueue(a.buffer.slice(a.byteOffset, a.byteOffset + a.byteLength)); + else if (a instanceof ArrayBuffer) r.enqueue(a); + else throw new TypeError("Expected ArrayBuffer or an ArrayBuffer view."); + r.close(); +} }); +var u = M; +var T = /;\s*boundary=(?:"([^"]+)"|([^;",]+))/; +var h = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-."; +var A = () => { + let a = new Uint8Array(24); + return globalThis.crypto.getRandomValues(a), Array.from(a).map((s) => h[s % h.length]).join(""); +}; +var i = { preventClose: true }; +async function* g(a, s, r) { + let d = new TextEncoder(), y = d.encode(`\r +--${a}`); + if (Array.isArray(s) && s.length < 1) { + await r.abort(Error("At least one part is required")); + return; + } + let l = 0; + for await (let e2 of s) { + l++; + let n, t; + if (!e2.body && e2.parts) if (t = e2.headers.get("content-type"), !t) n = A(), t = `multipart/mixed; boundary="${n}"`; + else if (!t.startsWith("multipart/") || !T.test(t)) { + await r.abort(Error("Invalid multipart content type: " + t)); + return; + } else { + let o2 = t.match(m); + (!o2 || !(n = o2[1] || o2[2])) && (n = A(), t = t.replace(T, `; boundary="${n}"`)); + } + await u(y).pipeTo(r, i), yield; + { + let o2 = [""]; + if (t) { + let p = false; + e2.headers.forEach((f, c) => { + c !== "content-type" ? o2.push(`${c}: ${f}`) : (p = true, o2.push(`${c}: ${t}`)); + }), p || o2.push(`content-type: ${t}`); + } else e2.headers.forEach((p, f) => { + o2.push(`${f}: ${p}`); + }); + e2.parts || !e2.body ? o2.push("") : o2.push("", ""); + let B3 = d.encode(o2.join(`\r +`)); + o2.length = 0, await u(B3).pipeTo(r, i), yield; + } + if (e2.body) { + if (e2.body instanceof ArrayBuffer || ArrayBuffer.isView(e2.body)) await u(e2.body).pipeTo(r, i); + else if (e2.body instanceof Blob) await e2.body.stream().pipeTo(r, i); + else if (e2.body instanceof ReadableStream) await e2.body.pipeTo(r, i); + else { + await r.abort(Error("Invalid body type")); + return; } - shadow(value, reason) { - this.mainstay.shadow = this.mainstay.shadow || new internals.Shadow(); - this.mainstay.shadow.set(this.path, value, reason); + yield; + } else if (e2.parts) { + if (!n) { + await r.abort(Error("Runtime exception: undefined part boundary")); + return; } - snapshot() { - if (this.mainstay.shadow) { - this._snapshot = clone2(this.mainstay.shadow.node(this.path)); + yield* g(n, e2.parts, r), yield; + } + } + if (!l) { + await r.abort(Error("At least one part is required")); + return; + } + let b = d.encode(`\r +--${a}--`); + await u(b).pipeTo(r, i); +} +var w = (a, s) => { + let r = new TransformStream(), d = g(a, s, r.writable), y = false, l = r.readable.getReader(); + return new ReadableStream({ start(e2) { + (async () => { + for (; ; ) try { + let n = await l.read(); + if (n.done) { + let t = new Uint8Array([13, 10]); + e2.enqueue(t.buffer.slice(t.byteOffset, t.byteOffset + t.byteLength)), e2.close(); + return; } - this.mainstay.snapshot(); + e2.enqueue(n.value); + } catch (n) { + e2.error(n); + return; } - restore() { - if (this.mainstay.shadow) { - this.mainstay.shadow.override(this.path, this._snapshot); - this._snapshot = void 0; + })().catch(() => { + }); + }, async pull() { + if (y) return; + (await d.next()).done && (y = true, await r.writable.close()); + } }); +}; +var x = w; +var v = async (n, T2, w3, L) => { + let u2 = await globalThis.crypto.subtle.importKey("raw", T2, "HKDF", false, ["deriveKey", "deriveBits"]), d = await globalThis.crypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", info: n.cek_info, salt: w3 }, u2, n.params, false, L), A2 = await globalThis.crypto.subtle.deriveBits({ name: "HKDF", hash: "SHA-256", info: n.nonce_info, salt: w3 }, u2, n.nonce_length << 3); + return [d, function* () { + let s = new ArrayBuffer(n.nonce_length), e2 = new DataView(s), y = new Uint8Array(s), i2 = new Uint8Array(A2), b = 4294967295, f = (n.nonce_length >> 2) - 1, l = new Array(f).fill(0); + for (; ; ) { + for (let a = 0; a <= b; a++) { + e2.setUint32(e2.byteLength - 4, a, false); + let t = new Uint8Array(n.nonce_length); + for (let r = 0; r < t.length; r++) t[r] = i2[r] ^ y[r]; + yield t; + } + for (let a = 0; a < f; a++) { + if (a === f - 1 && l[a] === b) throw new RangeError("Maximum number of segments exceeded"); + if (l[a] = (l[a] + 1) % (b + 1), e2.setUint32(e2.byteLength - 4 * (a + 2), l[a], false), l[a] !== 0) break; + } + } + }()]; +}; +var I = v; +var B = (n) => ArrayBuffer.isView(n) ? new Uint8Array(n.buffer).subarray(n.byteOffset, n.byteOffset + n.byteLength) : new Uint8Array(n); +var m2 = B; +var o = { salt: {}, recordSize: {}, keyIdLen: {}, keyId: {}, payload: {}, done: {} }; +var R = (n, T2, w3, L) => { + let u2 = new Uint8Array(16), d, A2, E2, s = 0, e2 = 0, y = new Uint8Array(256), i2 = o.salt, b = new TransformStream({ start: () => { + }, transform: async (f, l) => { + let a = m2(f), t = 0; + for (; t < f.byteLength; ) switch (i2) { + case o.salt: { + let r = a.subarray(t, t + u2.byteLength - e2); + if (u2.set(r, e2), e2 += r.byteLength, t += r.byteLength, e2 === u2.byteLength) { + e2 = 0, i2 = o.recordSize; + continue; } - this.mainstay.restore(); + break; } - commit() { - if (this.mainstay.shadow) { - this.mainstay.shadow.override(this.path, this._snapshot); - this._snapshot = void 0; + case o.recordSize: { + let r = a.subarray(t, t + 4 - e2), g2 = new ArrayBuffer(4), h2 = new Uint8Array(g2), c = new DataView(g2); + if (h2.set(r, e2), s |= c.getUint32(0, false), e2 += r.byteLength, t += r.byteLength, e2 === 4) { + if (s <= n.tag_length + 1 || s > (L == null ? 4294967295 : Math.min(4294967295, L))) throw new RangeError("Invalid record size: " + s); + e2 = 0, i2 = o.keyIdLen; + continue; } - this.mainstay.commit(); - } - }; - internals.schemas = function(schema) { - if (Common.isSchema(schema)) { - return { schema }; - } - return schema; - }; - internals.Shadow = class { - constructor() { - this._values = null; + break; } - set(path8, value, reason) { - if (!path8.length) { - return; - } - if (reason === "strip" && typeof path8[path8.length - 1] === "number") { - return; - } - this._values = this._values || /* @__PURE__ */ new Map(); - let node = this._values; - for (let i2 = 0; i2 < path8.length; ++i2) { - const segment = path8[i2]; - let next = node.get(segment); - if (!next) { - next = /* @__PURE__ */ new Map(); - node.set(segment, next); - } - node = next; - } - node[internals.value] = value; + case o.keyIdLen: { + y[0] = a[t++], i2 = o.keyId; + continue; } - get(path8) { - const node = this.node(path8); - if (node) { - return node[internals.value]; + case o.keyId: { + let r = a.subarray(t, t + y[0] - e2); + if (y.set(r, 1 + e2), e2 += r.byteLength, t += r.byteLength, e2 === y[0]) { + let g2 = await w3(y.subarray(1, 1 + y[0])); + w3 = void 0; + let h2 = await I(n, g2, u2, ["decrypt"]); + A2 = h2[0], E2 = h2[1], d = new Uint8Array(s), e2 = 0, i2 = o.payload; + continue; } + break; } - node(path8) { - if (!this._values) { - return; + case o.payload: { + let r = a.subarray(t, t + s - e2); + if (d.set(r, e2), e2 += r.byteLength, t += r.byteLength, e2 === s) { + let h2 = E2.next().value, c = m2(await globalThis.crypto.subtle.decrypt({ name: n.params.name, iv: h2, tagLength: n.tag_length << 3 }, A2, d.subarray(0, e2))), p = c.byteLength - 1; + for (; p > 0 && c[p] === 0; p--) ; + if (c[p] === 2) { + if (t !== f.byteLength) throw new Error("Unexpected terminal padding delimiter"); + i2 = o.done; + } else if (c[p] !== 1) throw new Error("Invalid padding delimiter"); + l.enqueue(c.buffer.slice(0, p)), c.fill(0), e2 = 0; + continue; } - return reach(this._values, path8, { iterables: true }); + break; } - override(path8, node) { - if (!this._values) { - return; - } - const parents = path8.slice(0, -1); - const own = path8[path8.length - 1]; - const parent = reach(this._values, parents, { iterables: true }); - if (node) { - parent.set(own, node); - return; - } - if (parent) { - parent.delete(own); - } + default: + throw new Error("Invalid state"); + } + }, flush: async (f) => { + switch (i2) { + case o.done: + return; + case o.payload: { + if (e2 < 1 + n.tag_length) throw new Error("Unexpected end of data"); + let a = E2.next().value, t = m2(await globalThis.crypto.subtle.decrypt({ name: n.params.name, iv: a, tagLength: n.tag_length << 3 }, A2, d.subarray(0, e2))), r = t.byteLength - 1; + for (; r > 0 && t[r] === 0; r--) ; + if (t[r] !== 2) throw new Error("Unexpected non-terminal padding delimiter"); + f.enqueue(t.buffer.slice(0, r)), t.fill(0); + return; } - }; + default: + throw new Error("Invalid state"); + } + } }); + return T2.pipeThrough(b), b.readable; +}; +var S = R; +var x2 = { params: { name: "AES-GCM", length: 128 }, get cek_info() { + return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 97, 101, 115, 49, 50, 56, 103, 99, 109, 0]); +}, get nonce_info() { + return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 110, 111, 110, 99, 101, 0]); +}, block_size: 16, tag_length: 16, nonce_length: 12 }; +var e = { params: { name: "AES-GCM", length: 256 }, get cek_info() { + return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 97, 101, 115, 50, 53, 54, 103, 99, 109, 0]); +}, get nonce_info() { + return new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, 32, 110, 111, 110, 99, 101, 0]); +}, block_size: 16, tag_length: 16, nonce_length: 12 }; +var R2 = async (e2, b, f, i2) => { + let A2 = await globalThis.crypto.subtle.importKey("raw", b, "HKDF", false, ["deriveKey", "deriveBits"]), y = await globalThis.crypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", info: e2.cek_info, salt: f }, A2, e2.params, false, i2), u2 = await globalThis.crypto.subtle.deriveBits({ name: "HKDF", hash: "SHA-256", info: e2.nonce_info, salt: f }, A2, e2.nonce_length << 3); + return [y, function* () { + let L = new ArrayBuffer(e2.nonce_length), c = new DataView(L), h2 = new Uint8Array(L), a = new Uint8Array(u2), g2 = 4294967295, o2 = (e2.nonce_length >> 2) - 1, s = new Array(o2).fill(0); + for (; ; ) { + for (let t = 0; t <= g2; t++) { + c.setUint32(c.byteLength - 4, t, false); + let n = new Uint8Array(e2.nonce_length); + for (let r = 0; r < n.length; r++) n[r] = a[r] ^ h2[r]; + yield n; + } + for (let t = 0; t < o2; t++) { + if (t === o2 - 1 && s[t] === g2) throw new RangeError("Maximum number of segments exceeded"); + if (s[t] = (s[t] + 1) % (g2 + 1), c.setUint32(c.byteLength - 4 * (t + 2), s[t], false), s[t] !== 0) break; + } + } + }()]; +}; +var E = R2; +var B2 = (e2) => ArrayBuffer.isView(e2) ? new Uint8Array(e2.buffer).subarray(e2.byteOffset, e2.byteOffset + e2.byteLength) : new Uint8Array(e2); +var w2 = B2; +var N = () => { + let e2 = new Uint8Array(16); + return globalThis.crypto.getRandomValues(e2), e2; +}; +var U = async (e2, b, f, i2, A2, y) => { + if (f <= e2.tag_length + 1 || f > 4294967295) throw new RangeError("Invalid record size: " + f); + if (i2.byteLength > 255) throw new RangeError("Key ID too long"); + if (y && y.byteLength !== 16) throw new RangeError("Invald salt length: " + y.byteLength); + let u2 = f - e2.tag_length - 1, l = y ? w2(y) : N(), [L, c] = await E(e2, A2, l, ["encrypt"]); + A2 = void 0; + let h2 = new Uint8Array(u2), a = 0, g2 = new TransformStream({ start: (o2) => { + let s = l.byteLength + 4 + 1 + i2.byteLength, t = new ArrayBuffer(s); + new Uint8Array(t, 0, l.byteLength).set(l); + let r = new DataView(t, l.byteLength, 5); + r.setUint32(0, f, false), r.setUint8(4, i2.byteLength); + let d = new Uint8Array(t, l.byteLength + 4 + 1, i2.byteLength), m3 = w2(i2); + d.set(m3), o2.enqueue(t); + }, transform: async (o2, s) => { + let t = w2(o2), n = 0; + for (; n < o2.byteLength; ) { + let r = t.subarray(n, n + u2 - a); + if (h2.set(r, a), a += r.byteLength, n += r.byteLength, a === u2) { + let m3 = c.next().value, p = new Uint8Array(u2 + 1); + p.set(h2.subarray(0, a)), p[a] = 1; + let T2 = await globalThis.crypto.subtle.encrypt({ name: e2.params.name, iv: m3, tagLength: e2.tag_length << 3 }, L, p); + s.enqueue(T2), a = 0; + } + } + }, flush: async (o2) => { + let t = c.next().value, n = new Uint8Array(a + 1); + n.set(h2.subarray(0, a)), n[a] = 2; + let r = await globalThis.crypto.subtle.encrypt({ name: e2.params.name, iv: t, tagLength: e2.tag_length << 3 }, L, n); + o2.enqueue(r), h2.fill(0), n.fill(0); + } }); + return b.pipeThrough(g2), g2.readable; +}; +var K = U; +init_esm6(); +init_bytes(); +init_esm(); +init_esm4(); +init_functions(); +init_esm6(); +init_esm(); +init_esm4(); +init_SPMessage(); +init_esm7(); +var wm = /* @__PURE__ */ new WeakMap(); +var Secret = class { + static [serdesDeserializeSymbol](secret) { + return new this(secret); } -}); -var require_validator3 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/validator.js"(exports2) { - "use strict"; - var { assert: assert2, clone: clone2, ignore, reach } = require_lib(); - var Common = require_common3(); - var Errors = require_errors3(); - var State = require_state3(); - var internals = { - result: Symbol("result") - }; - exports2.entry = function(value, schema, prefs) { - let settings = Common.defaults; - if (prefs) { - assert2(prefs.warnings === void 0, "Cannot override warnings preference in synchronous validation"); - assert2(prefs.artifacts === void 0, "Cannot override artifacts preference in synchronous validation"); - settings = Common.preferences(Common.defaults, prefs); - } - const result = internals.entry(value, schema, settings); - assert2(!result.mainstay.externals.length, "Schema with external rules must use validateAsync()"); - const outcome = { value: result.value }; - if (result.error) { - outcome.error = result.error; - } - if (result.mainstay.warnings.length) { - outcome.warning = Errors.details(result.mainstay.warnings); - } - if (result.mainstay.debug) { - outcome.debug = result.mainstay.debug; - } - if (result.mainstay.artifacts) { - outcome.artifacts = result.mainstay.artifacts; + static [serdesSerializeSymbol](secret) { + return wm.get(secret); + } + static get [serdesTagSymbol]() { + return "__chelonia_Secret"; + } + constructor(value) { + wm.set(this, value); + } + valueOf() { + return wm.get(this); + } +}; +var INVITE_STATUS = { + REVOKED: "revoked", + VALID: "valid", + USED: "used" +}; +init_errors3(); +init_functions(); +init_signedData(); +var MAX_EVENTS_AFTER = Number.parseInt(process.env.MAX_EVENTS_AFTER || "", 10) || Infinity; +var copiedExistingData = Symbol("copiedExistingData"); +var findKeyIdByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).find((k) => k.name === name && k._notAfterHeight == null)?.id; +var findForeignKeysByContractID = (state, contractID) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.foreignKey?.includes(contractID)).map((k) => k.id); +var findRevokedKeyIdsByName = (state, name) => state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys || {}).filter((k) => k.name === name && k._notAfterHeight != null).map((k) => k.id); +var findSuitableSecretKeyId = (state, permissions, purposes, ringLevel, allowedActions) => { + return state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => { + return k._notAfterHeight == null && k.ringLevel <= (ringLevel ?? Number.POSITIVE_INFINITY) && esm_default("chelonia/haveSecretKey", k.id) && (Array.isArray(permissions) ? permissions.reduce((acc, permission) => acc && (k.permissions === "*" || k.permissions.includes(permission)), true) : permissions === k.permissions) && purposes.reduce((acc, purpose) => acc && k.purpose.includes(purpose), true) && (Array.isArray(allowedActions) ? allowedActions.reduce((acc, action) => acc && (k.allowedActions === "*" || !!k.allowedActions?.includes(action)), true) : allowedActions ? allowedActions === k.allowedActions : true); + }).sort((a, b) => b.ringLevel - a.ringLevel)[0]?.id; +}; +var findSuitablePublicKeyIds = (state, permissions, purposes, ringLevel) => { + return state._vm?.authorizedKeys && Object.values(state._vm.authorizedKeys).filter((k) => k._notAfterHeight == null && k.ringLevel <= (ringLevel ?? Number.POSITIVE_INFINITY) && (Array.isArray(permissions) ? permissions.reduce((acc, permission) => acc && (k.permissions === "*" || k.permissions.includes(permission)), true) : permissions === k.permissions) && purposes.reduce((acc, purpose) => acc && k.purpose.includes(purpose), true)).sort((a, b) => b.ringLevel - a.ringLevel).map((k) => k.id); +}; +var validateActionPermissions = (msg, signingKey, state, opT, opV) => { + const data = isSignedData(opV) ? opV.valueOf() : opV; + if (signingKey.allowedActions !== "*" && (!Array.isArray(signingKey.allowedActions) || !signingKey.allowedActions.includes(data.action))) { + logEvtError(msg, `Signing key ${signingKey.id} is not allowed for action ${data.action}`); + return false; + } + if (isSignedData(opV)) { + const s = opV; + const innerSigningKey = state._vm?.authorizedKeys?.[s.signingKeyId]; + if (!innerSigningKey && msg._direction === "outgoing") + return true; + if (!innerSigningKey || !Array.isArray(innerSigningKey.purpose) || !innerSigningKey.purpose.includes("sig") || innerSigningKey.permissions !== "*" && (!Array.isArray(innerSigningKey.permissions) || !innerSigningKey.permissions.includes(opT + "#inner"))) { + logEvtError(msg, `Signing key ${s.signingKeyId} is missing permissions for operation ${opT}`); + return false; + } + if (innerSigningKey.allowedActions !== "*" && (!Array.isArray(innerSigningKey.allowedActions) || !innerSigningKey.allowedActions.includes(data.action + "#inner"))) { + logEvtError(msg, `Signing key ${innerSigningKey.id} is not allowed for action ${data.action}`); + return false; + } + } + return true; +}; +var validateKeyPermissions = (msg, config2, state, signingKeyId, opT, opV) => { + const signingKey = state._vm?.authorizedKeys?.[signingKeyId]; + if (!signingKey || !Array.isArray(signingKey.purpose) || !signingKey.purpose.includes("sig") || signingKey.permissions !== "*" && (!Array.isArray(signingKey.permissions) || !signingKey.permissions.includes(opT))) { + logEvtError(msg, `Signing key ${signingKeyId} is missing permissions for operation ${opT}`); + return false; + } + if (opT === SPMessage.OP_ACTION_UNENCRYPTED && !validateActionPermissions(msg, signingKey, state, opT, opV)) { + return false; + } + if (!config2.skipActionProcessing && opT === SPMessage.OP_ACTION_ENCRYPTED && !validateActionPermissions(msg, signingKey, state, opT, opV.valueOf())) { + return false; + } + return true; +}; +var validateKeyAddPermissions = function(contractID, signingKey, state, v2, skipPrivateCheck) { + const signingKeyPermissions = Array.isArray(signingKey.permissions) ? new Set(signingKey.permissions) : signingKey.permissions; + const signingKeyAllowedActions = Array.isArray(signingKey.allowedActions) ? new Set(signingKey.allowedActions) : signingKey.allowedActions; + if (!state._vm?.authorizedKeys?.[signingKey.id]) { + throw new Error("Singing key for OP_KEY_ADD or OP_KEY_UPDATE must exist in _vm.authorizedKeys. contractID=" + contractID + " signingKeyId=" + signingKey.id); + } + const localSigningKey = state._vm.authorizedKeys[signingKey.id]; + v2.forEach((wk) => { + const data = this.config.unwrapMaybeEncryptedData(wk); + if (!data) + return; + const k = data.data; + if (!skipPrivateCheck && signingKey._private && !data.encryptionKeyId) { + throw new Error("Signing key is private but it tried adding a public key"); + } + if (!Number.isSafeInteger(k.ringLevel) || k.ringLevel < localSigningKey.ringLevel) { + throw new Error("Signing key has ringLevel " + localSigningKey.ringLevel + " but attempted to add or update a key with ringLevel " + k.ringLevel); + } + if (signingKeyPermissions !== "*") { + if (!Array.isArray(k.permissions) || !k.permissions.reduce((acc, cv) => acc && signingKeyPermissions.has(cv), true)) { + throw new Error("Unable to add or update a key with more permissions than the signing key. signingKey permissions: " + String(signingKey?.permissions) + "; key add permissions: " + String(k.permissions)); } - return outcome; - }; - exports2.entryAsync = async function(value, schema, prefs) { - let settings = Common.defaults; - if (prefs) { - settings = Common.preferences(Common.defaults, prefs); + } + if (signingKeyAllowedActions !== "*" && k.allowedActions) { + if (!signingKeyAllowedActions || !Array.isArray(k.allowedActions) || !k.allowedActions.reduce((acc, cv) => acc && signingKeyAllowedActions.has(cv), true)) { + throw new Error("Unable to add or update a key with more allowed actions than the signing key. signingKey allowed actions: " + String(signingKey?.allowedActions) + "; key add allowed actions: " + String(k.allowedActions)); } - const result = internals.entry(value, schema, settings); - const mainstay = result.mainstay; - if (result.error) { - if (mainstay.debug) { - result.error.debug = mainstay.debug; - } - throw result.error; + } + }); +}; +var validateKeyDelPermissions = function(contractID, signingKey, state, v2) { + if (!state._vm?.authorizedKeys?.[signingKey.id]) { + throw new Error("Singing key for OP_KEY_DEL must exist in _vm.authorizedKeys. contractID=" + contractID + " signingKeyId=" + signingKey.id); + } + const localSigningKey = state._vm.authorizedKeys[signingKey.id]; + v2.forEach((wid) => { + const data = this.config.unwrapMaybeEncryptedData(wid); + if (!data) + return; + const id = data.data; + const k = state._vm.authorizedKeys[id]; + if (!k) { + throw new Error("Nonexisting key ID " + id); + } + if (signingKey._private) { + throw new Error("Signing key is private"); + } + if (!k._private !== !data.encryptionKeyId) { + throw new Error("_private attribute must be preserved"); + } + if (!Number.isSafeInteger(k.ringLevel) || k.ringLevel < localSigningKey.ringLevel) { + throw new Error("Signing key has ringLevel " + localSigningKey.ringLevel + " but attempted to remove a key with ringLevel " + k.ringLevel); + } + }); +}; +var validateKeyUpdatePermissions = function(contractID, signingKey, state, v2) { + const updatedMap = /* @__PURE__ */ Object.create(null); + const keys = v2.map((wuk) => { + const data = this.config.unwrapMaybeEncryptedData(wuk); + if (!data) + return void 0; + const uk = data.data; + const existingKey = state._vm.authorizedKeys[uk.oldKeyId]; + if (!existingKey) { + throw new ChelErrorWarning("Missing old key ID " + uk.oldKeyId); + } + if (!existingKey._private !== !data.encryptionKeyId) { + throw new Error("_private attribute must be preserved"); + } + if (uk.name !== existingKey.name) { + throw new Error("Name cannot be updated"); + } + if (!uk.id !== !uk.data) { + throw new Error("Both or none of the id and data attributes must be provided. Old key ID: " + uk.oldKeyId); + } + if (uk.data && existingKey.meta?.private && !uk.meta?.private) { + throw new Error("Missing private key. Old key ID: " + uk.oldKeyId); + } + if (uk.id && uk.id !== uk.oldKeyId) { + updatedMap[uk.id] = uk.oldKeyId; + } + const updatedKey = omit2(existingKey, [ + "_notAfterHeight", + "_notBeforeHeight" + ]); + if (uk.permissions) { + updatedKey.permissions = uk.permissions; + } + if (uk.allowedActions) { + updatedKey.allowedActions = uk.allowedActions; + } + if (uk.purpose) { + updatedKey.purpose = uk.purpose; + } + if (uk.meta) { + updatedKey.meta = uk.meta; + } else if (updatedKey.meta) { + Object.defineProperty(updatedKey.meta, copiedExistingData, { value: true }); + } + if (uk.id) { + updatedKey.id = uk.id; + } + if (uk.data) { + updatedKey.data = uk.data; + } + return updatedKey; + }).filter(Boolean); + validateKeyAddPermissions.call(this, contractID, signingKey, state, keys, true); + return [keys, updatedMap]; +}; +var keyAdditionProcessor = function(_msg, hash3, keys, state, contractID, _signingKey, internalSideEffectStack) { + const decryptedKeys = []; + const keysToPersist = []; + const storeSecretKey = (key, decryptedKey) => { + const decryptedDeserializedKey = deserializeKey(decryptedKey); + const transient = !!key.meta?.private?.transient; + esm_default("chelonia/storeSecretKeys", new Secret([ + { + key: decryptedDeserializedKey, + // We always set this to true because this could be done from + // an outgoing message + transient: true } - if (mainstay.externals.length) { - let root = result.value; - const errors = []; - for (const external of mainstay.externals) { - const path8 = external.state.path; - const linked = external.schema.type === "link" ? mainstay.links.get(external.schema) : null; - let node = root; - let key; - let parent; - const ancestors = path8.length ? [root] : []; - const original = path8.length ? reach(value, path8) : value; - if (path8.length) { - key = path8[path8.length - 1]; - let current = root; - for (const segment of path8.slice(0, -1)) { - current = current[segment]; - ancestors.unshift(current); - } - parent = ancestors[0]; - node = parent[key]; - } - try { - const createError = (code2, local) => (linked || external.schema).$_createError(code2, node, local, external.state, settings); - const output = await external.method(node, { - schema: external.schema, - linked, - state: external.state, - prefs, - original, - error: createError, - errorsArray: internals.errorsArray, - warn: (code2, local) => mainstay.warnings.push((linked || external.schema).$_createError(code2, node, local, external.state, settings)), - message: (messages, local) => (linked || external.schema).$_createError("external", node, local, external.state, settings, { messages }) - }); - if (output === void 0 || output === node) { - continue; + ])); + if (!transient) { + keysToPersist.push({ key: decryptedDeserializedKey, transient }); + } + }; + for (const wkey of keys) { + const data = this.config.unwrapMaybeEncryptedData(wkey); + if (!data) + continue; + const key = data.data; + let decryptedKey; + if (key.meta?.private?.content && !has(key.meta, copiedExistingData)) { + if (key.id && !esm_default("chelonia/haveSecretKey", key.id, !key.meta.private.transient)) { + const decryptedKeyResult = this.config.unwrapMaybeEncryptedData(key.meta.private.content); + if (decryptedKeyResult) { + if (decryptedKeyResult.encryptionKeyId == null) { + throw new Error("Expected encrypted data but got unencrypted data for key with ID: " + key.id); + } + decryptedKey = decryptedKeyResult.data; + decryptedKeys.push([key.id, decryptedKey]); + storeSecretKey(key, decryptedKey); + } + } + } + if (key.name === "#sak") { + if (data.encryptionKeyId) { + throw new Error("#sak may not be encrypted"); + } + if (key.permissions && (!Array.isArray(key.permissions) || key.permissions.length !== 0)) { + throw new Error("#sak may not have permissions"); + } + if (!Array.isArray(key.purpose) || key.purpose.length !== 1 || key.purpose[0] !== "sak") { + throw new Error("#sak must have exactly one purpose: 'sak'"); + } + if (key.ringLevel !== 0) { + throw new Error("#sak must have ringLevel 0"); + } + } + if (key.name.startsWith("#inviteKey-")) { + if (!state._vm.invites) + state._vm.invites = /* @__PURE__ */ Object.create(null); + const inviteSecret = decryptedKey || (has(this.transientSecretKeys, key.id) ? serializeKey(this.transientSecretKeys[key.id], true) : void 0); + state._vm.invites[key.id] = { + status: INVITE_STATUS.VALID, + initialQuantity: key.meta.quantity, + quantity: key.meta.quantity, + expires: key.meta.expires, + inviteSecret, + responses: [] + }; + } + if (key.meta?.keyRequest?.contractID && findSuitableSecretKeyId(state, [SPMessage.OP_KEY_ADD], ["sig"])) { + const data2 = this.config.unwrapMaybeEncryptedData(key.meta.keyRequest.contractID); + if (data2 && internalSideEffectStack) { + const keyRequestContractID = data2.data; + const reference = this.config.unwrapMaybeEncryptedData(key.meta.keyRequest.reference); + internalSideEffectStack.push(() => { + esm_default("chelonia/private/queueEvent", keyRequestContractID, () => { + const rootState = esm_default(this.config.stateSelector); + const originatingContractState = rootState[contractID]; + if (esm_default("chelonia/contract/hasKeyShareBeenRespondedBy", originatingContractState, keyRequestContractID, reference)) { + return; } - if (output instanceof Errors.Report) { - mainstay.tracer.log(external.schema, external.state, "rule", "external", "error"); - errors.push(output); - if (settings.abortEarly) { - break; - } - continue; + if (!has(rootState, keyRequestContractID)) { + this.config.reactiveSet(rootState, keyRequestContractID, /* @__PURE__ */ Object.create(null)); } - if (Array.isArray(output) && output[Common.symbols.errors]) { - mainstay.tracer.log(external.schema, external.state, "rule", "external", "error"); - errors.push(...output); - if (settings.abortEarly) { - break; - } - continue; + const targetState = rootState[keyRequestContractID]; + if (!targetState._volatile) { + this.config.reactiveSet(targetState, "_volatile", /* @__PURE__ */ Object.create(null)); } - if (parent) { - mainstay.tracer.value(external.state, "rule", node, output, "external"); - parent[key] = output; - } else { - mainstay.tracer.value(external.state, "rule", root, output, "external"); - root = output; + if (!targetState._volatile.pendingKeyRequests) { + this.config.reactiveSet(rootState[keyRequestContractID]._volatile, "pendingKeyRequests", []); } - } catch (err) { - if (settings.errors.label) { - err.message += ` (${external.label})`; + if (targetState._volatile.pendingKeyRequests.some((pkr) => { + return pkr && pkr.contractID === contractID && pkr.hash === hash3; + })) { + return; } - throw err; - } - } - result.value = root; - if (errors.length) { - result.error = Errors.process(errors, value, settings); - if (mainstay.debug) { - result.error.debug = mainstay.debug; - } - throw result.error; - } - } - if (!settings.warnings && !settings.debug && !settings.artifacts) { - return result.value; - } - const outcome = { value: result.value }; - if (mainstay.warnings.length) { - outcome.warning = Errors.details(mainstay.warnings); - } - if (mainstay.debug) { - outcome.debug = mainstay.debug; - } - if (mainstay.artifacts) { - outcome.artifacts = mainstay.artifacts; - } - return outcome; - }; - exports2.standard = function(value, schema) { - if (schema.isAsync()) { - return exports2.entryAsync(value, schema); - } - return exports2.entry(value, schema); - }; - internals.Mainstay = class { - constructor(tracer, debug, links) { - this.externals = []; - this.warnings = []; - this.tracer = tracer; - this.debug = debug; - this.links = links; - this.shadow = null; - this.artifacts = null; - this._snapshots = []; - } - snapshot() { - this._snapshots.push({ - externals: this.externals.slice(), - warnings: this.warnings.slice() + targetState._volatile.pendingKeyRequests.push({ + contractID, + name: key.name, + hash: hash3, + reference: reference?.data + }); + this.setPostSyncOp(contractID, "pending-keys-for-" + keyRequestContractID, [ + "okTurtles.events/emit", + CONTRACT_IS_PENDING_KEY_REQUESTS, + { contractID: keyRequestContractID } + ]); + }).catch((e2) => { + console.error("Error while setting or updating pendingKeyRequests", { contractID, keyRequestContractID, reference }, e2); + }); }); } - restore() { - const snapshot = this._snapshots.pop(); - this.externals = snapshot.externals; - this.warnings = snapshot.warnings; - } - commit() { - this._snapshots.pop(); - } - }; - internals.entry = function(value, schema, prefs) { - const { tracer, cleanup } = internals.tracer(schema, prefs); - const debug = prefs.debug ? [] : null; - const links = schema._ids._schemaChain ? /* @__PURE__ */ new Map() : null; - const mainstay = new internals.Mainstay(tracer, debug, links); - const schemas = schema._ids._schemaChain ? [{ schema }] : null; - const state = new State([], [], { mainstay, schemas }); - const result = exports2.validate(value, schema, state, prefs); - if (cleanup) { - schema.$_root.untrace(); - } - const error2 = Errors.process(result.errors, value, prefs); - return { value: result.value, error: error2, mainstay }; - }; - internals.tracer = function(schema, prefs) { - if (schema.$_root._tracer) { - return { tracer: schema.$_root._tracer._register(schema) }; - } - if (prefs.debug) { - assert2(schema.$_root.trace, "Debug mode not supported"); - return { tracer: schema.$_root.trace()._register(schema), cleanup: true }; - } - return { tracer: internals.ignore }; - }; - exports2.validate = function(value, schema, state, prefs, overrides = {}) { - if (schema.$_terms.whens) { - schema = schema._generate(value, state, prefs).schema; - } - if (schema._preferences) { - prefs = internals.prefs(schema, prefs); - } - if (schema._cache && prefs.cache) { - const result = schema._cache.get(value); - state.mainstay.tracer.debug(state, "validate", "cached", !!result); - if (result) { - return result; - } - } - const createError = (code2, local, localState) => schema.$_createError(code2, value, local, localState || state, prefs); - const helpers = { - original: value, - prefs, - schema, - state, - error: createError, - errorsArray: internals.errorsArray, - warn: (code2, local, localState) => state.mainstay.warnings.push(createError(code2, local, localState)), - message: (messages, local) => schema.$_createError("custom", value, local, state, prefs, { messages }) - }; - state.mainstay.tracer.entry(schema, state); - const def = schema._definition; - if (def.prepare && value !== void 0 && prefs.convert) { - const prepared = def.prepare(value, helpers); - if (prepared) { - state.mainstay.tracer.value(state, "prepare", value, prepared.value); - if (prepared.errors) { - return internals.finalize(prepared.value, [].concat(prepared.errors), helpers); - } - value = prepared.value; - } - } - if (def.coerce && value !== void 0 && prefs.convert && (!def.coerce.from || def.coerce.from.includes(typeof value))) { - const coerced = def.coerce.method(value, helpers); - if (coerced) { - state.mainstay.tracer.value(state, "coerced", value, coerced.value); - if (coerced.errors) { - return internals.finalize(coerced.value, [].concat(coerced.errors), helpers); - } - value = coerced.value; - } - } - const empty2 = schema._flags.empty; - if (empty2 && empty2.$_match(internals.trim(value, schema), state.nest(empty2), Common.defaults)) { - state.mainstay.tracer.value(state, "empty", value, void 0); - value = void 0; - } - const presence = overrides.presence || schema._flags.presence || (schema._flags._endedSwitch ? null : prefs.presence); - if (value === void 0) { - if (presence === "forbidden") { - return internals.finalize(value, null, helpers); - } - if (presence === "required") { - return internals.finalize(value, [schema.$_createError("any.required", value, null, state, prefs)], helpers); - } - if (presence === "optional") { - if (schema._flags.default !== Common.symbols.deepDefault) { - return internals.finalize(value, null, helpers); - } - state.mainstay.tracer.value(state, "default", value, {}); - value = {}; - } - } else if (presence === "forbidden") { - return internals.finalize(value, [schema.$_createError("any.unknown", value, null, state, prefs)], helpers); - } - const errors = []; - if (schema._valids) { - const match = schema._valids.get(value, state, prefs, schema._flags.insensitive); - if (match) { - if (prefs.convert) { - state.mainstay.tracer.value(state, "valids", value, match.value); - value = match.value; - } - state.mainstay.tracer.filter(schema, state, "valid", match); - return internals.finalize(value, null, helpers); - } - if (schema._flags.only) { - const report = schema.$_createError("any.only", value, { valids: schema._valids.values({ display: true }) }, state, prefs); - if (prefs.abortEarly) { - return internals.finalize(value, [report], helpers); - } - errors.push(report); - } - } - if (schema._invalids) { - const match = schema._invalids.get(value, state, prefs, schema._flags.insensitive); - if (match) { - state.mainstay.tracer.filter(schema, state, "invalid", match); - const report = schema.$_createError("any.invalid", value, { invalids: schema._invalids.values({ display: true }) }, state, prefs); - if (prefs.abortEarly) { - return internals.finalize(value, [report], helpers); - } - errors.push(report); - } - } - if (def.validate) { - const base2 = def.validate(value, helpers); - if (base2) { - state.mainstay.tracer.value(state, "base", value, base2.value); - value = base2.value; - if (base2.errors) { - if (!Array.isArray(base2.errors)) { - errors.push(base2.errors); - return internals.finalize(value, errors, helpers); - } - if (base2.errors.length) { - errors.push(...base2.errors); - return internals.finalize(value, errors, helpers); - } - } - } - } - if (!schema._rules.length) { - return internals.finalize(value, errors, helpers); + } + } + if (keysToPersist.length) { + internalSideEffectStack?.push(() => { + esm_default("chelonia/storeSecretKeys", new Secret(keysToPersist)); + }); + } + internalSideEffectStack?.push(() => subscribeToForeignKeyContracts.call(this, contractID, state)); +}; +var subscribeToForeignKeyContracts = function(contractID, state) { + try { + Object.values(state._vm.authorizedKeys).filter((key) => !!key.foreignKey && findKeyIdByName(state, key.name) != null).forEach((key) => { + const foreignKey = String(key.foreignKey); + const fkUrl = new URL(foreignKey); + const foreignContract = fkUrl.pathname; + const foreignKeyName = fkUrl.searchParams.get("keyName"); + if (!foreignContract || !foreignKeyName) { + console.warn("Invalid foreign key: missing contract or key name", { + contractID, + keyId: key.id + }); + return; } - return internals.rules(value, errors, helpers); - }; - internals.rules = function(value, errors, helpers) { - const { schema, state, prefs } = helpers; - for (const rule of schema._rules) { - const definition = schema._definition.rules[rule.method]; - if (definition.convert && prefs.convert) { - state.mainstay.tracer.log(schema, state, "rule", rule.name, "full"); - continue; - } - let ret; - let args = rule.args; - if (rule._resolve.length) { - args = Object.assign({}, args); - for (const key of rule._resolve) { - const resolver = definition.argsByName.get(key); - const resolved = args[key].resolve(value, state, prefs); - const normalized = resolver.normalize ? resolver.normalize(resolved) : resolved; - const invalid = Common.validateArg(normalized, null, resolver); - if (invalid) { - ret = schema.$_createError("any.ref", resolved, { arg: key, ref: args[key], reason: invalid }, state, prefs); - break; - } - args[key] = normalized; - } - } - ret = ret || definition.validate(value, helpers, args, rule); - const result = internals.rule(ret, rule); - if (result.errors) { - state.mainstay.tracer.log(schema, state, "rule", rule.name, "error"); - if (rule.warn) { - state.mainstay.warnings.push(...result.errors); - continue; - } - if (prefs.abortEarly) { - return internals.finalize(value, result.errors, helpers); - } - errors.push(...result.errors); - } else { - state.mainstay.tracer.log(schema, state, "rule", rule.name, "pass"); - state.mainstay.tracer.value(state, "rule", value, result.value, rule.name); - value = result.value; + const rootState = esm_default(this.config.stateSelector); + const signingKey = findSuitableSecretKeyId(state, [SPMessage.OP_KEY_DEL], ["sig"], key.ringLevel); + const canMirrorOperations = !!signingKey; + if (!canMirrorOperations) + return; + if (Array.isArray(rootState?.[foreignContract]?._volatile?.watch)) { + if (rootState[foreignContract]._volatile.watch.find((v2) => v2[0] === key.name && v2[1] === contractID)) { + return; } } - return internals.finalize(value, errors, helpers); - }; - internals.rule = function(ret, rule) { - if (ret instanceof Errors.Report) { - internals.error(ret, rule); - return { errors: [ret], value: null }; - } - if (Array.isArray(ret) && ret[Common.symbols.errors]) { - ret.forEach((report) => internals.error(report, rule)); - return { errors: ret, value: null }; + if (!has(state._vm, "pendingWatch")) { + this.config.reactiveSet(state._vm, "pendingWatch", /* @__PURE__ */ Object.create(null)); } - return { errors: null, value: ret }; - }; - internals.error = function(report, rule) { - if (rule.message) { - report._setTemplate(rule.message); + if (!has(state._vm.pendingWatch, foreignContract)) { + this.config.reactiveSet(state._vm.pendingWatch, foreignContract, []); } - return report; - }; - internals.finalize = function(value, errors, helpers) { - errors = errors || []; - const { schema, state, prefs } = helpers; - if (errors.length) { - const failover = internals.default("failover", void 0, errors, helpers); - if (failover !== void 0) { - state.mainstay.tracer.value(state, "failover", value, failover); - value = failover; - errors = []; - } + if (!state._vm.pendingWatch[foreignContract].find(([n]) => n === foreignKeyName)) { + state._vm.pendingWatch[foreignContract].push([foreignKeyName, key.id]); } - if (errors.length && schema._flags.error) { - if (typeof schema._flags.error === "function") { - errors = schema._flags.error(errors); - if (!Array.isArray(errors)) { - errors = [errors]; - } - for (const error2 of errors) { - assert2(error2 instanceof Error || error2 instanceof Errors.Report, "error() must return an Error object"); - } + this.setPostSyncOp(contractID, `watchForeignKeys-${contractID}`, [ + "chelonia/private/watchForeignKeys", + contractID + ]); + }); + } catch (e2) { + console.warn("Error at subscribeToForeignKeyContracts: " + (e2.message || e2)); + } +}; +var recreateEvent = (entry, state, contractsState, disableAutoDedup) => { + const { HEAD: previousHEAD, height: previousHeight, previousKeyOp } = contractsState || {}; + if (!previousHEAD) { + throw new Error("recreateEvent: Giving up because the contract has been removed"); + } + const head = entry.head(); + const [opT, rawOpV] = entry.rawOp(); + const recreateOperation = (opT2, rawOpV2) => { + const opV = rawOpV2.valueOf(); + const recreateOperationInternal = (opT3, opV2) => { + let newOpV2; + if (opT3 === SPMessage.OP_KEY_ADD) { + if (!Array.isArray(opV2)) + throw new Error("Invalid message format"); + newOpV2 = opV2.filter((k) => { + const kId = k.valueOf().id; + return !has(state._vm.authorizedKeys, kId) || state._vm.authorizedKeys[kId]._notAfterHeight != null; + }); + if (newOpV2.length === 0) { + console.info("Omitting empty OP_KEY_ADD", { head }); + } else if (newOpV2.length === opV2.length) { + return opV2; + } + } else if (opT3 === SPMessage.OP_KEY_DEL) { + if (!Array.isArray(opV2)) + throw new Error("Invalid message format"); + newOpV2 = opV2.filter((keyId2) => { + const kId = Object(keyId2).valueOf(); + return has(state._vm.authorizedKeys, kId) && state._vm.authorizedKeys[kId]._notAfterHeight == null; + }); + if (newOpV2.length === 0) { + console.info("Omitting empty OP_KEY_DEL", { head }); + } else if (newOpV2.length === opV2.length) { + return opV2; + } + } else if (opT3 === SPMessage.OP_KEY_UPDATE) { + if (!Array.isArray(opV2)) + throw new Error("Invalid message format"); + newOpV2 = opV2.filter((k) => { + const oKId = k.valueOf().oldKeyId; + const nKId = k.valueOf().id; + return nKId == null || has(state._vm.authorizedKeys, oKId) && state._vm.authorizedKeys[oKId]._notAfterHeight == null; + }); + if (newOpV2.length === 0) { + console.info("Omitting empty OP_KEY_UPDATE", { head }); + } else if (newOpV2.length === opV2.length) { + return opV2; + } + } else if (opT3 === SPMessage.OP_ATOMIC) { + if (!Array.isArray(opV2)) + throw new Error("Invalid message format"); + newOpV2 = opV2.map(([t, v2]) => [t, recreateOperationInternal(t, v2)]).filter(([, v2]) => !!v2); + if (newOpV2.length === 0) { + console.info("Omitting empty OP_ATOMIC", { head }); + } else if (newOpV2.length === opV2.length && newOpV2.reduce((acc, cv, i2) => acc && cv === opV2[i2], true)) { + return opV2; } else { - errors = [schema._flags.error]; - } - } - if (value === void 0) { - const defaulted = internals.default("default", value, errors, helpers); - state.mainstay.tracer.value(state, "default", value, defaulted); - value = defaulted; - } - if (schema._flags.cast && value !== void 0) { - const caster = schema._definition.cast[schema._flags.cast]; - if (caster.from(value)) { - const casted = caster.to(value, helpers); - state.mainstay.tracer.value(state, "cast", value, casted, schema._flags.cast); - value = casted; - } - } - if (schema.$_terms.externals && prefs.externals && prefs._externals !== false) { - for (const { method } of schema.$_terms.externals) { - state.mainstay.externals.push({ method, schema, state, label: Errors.label(schema._flags, state, prefs) }); - } - } - const result = { value, errors: errors.length ? errors : null }; - if (schema._flags.result) { - result.value = schema._flags.result === "strip" ? void 0 : ( - /* raw */ - helpers.original - ); - state.mainstay.tracer.value(state, schema._flags.result, value, result.value); - state.shadow(value, schema._flags.result); - } - if (schema._cache && prefs.cache !== false && !schema._refs.length) { - schema._cache.set(helpers.original, result); - } - if (value !== void 0 && !result.errors && schema._flags.artifact !== void 0) { - state.mainstay.artifacts = state.mainstay.artifacts || /* @__PURE__ */ new Map(); - if (!state.mainstay.artifacts.has(schema._flags.artifact)) { - state.mainstay.artifacts.set(schema._flags.artifact, []); - } - state.mainstay.artifacts.get(schema._flags.artifact).push(state.path); - } - return result; - }; - internals.prefs = function(schema, prefs) { - const isDefaultOptions = prefs === Common.defaults; - if (isDefaultOptions && schema._preferences[Common.symbols.prefs]) { - return schema._preferences[Common.symbols.prefs]; - } - prefs = Common.preferences(prefs, schema._preferences); - if (isDefaultOptions) { - schema._preferences[Common.symbols.prefs] = prefs; - } - return prefs; - }; - internals.default = function(flag, value, errors, helpers) { - const { schema, state, prefs } = helpers; - const source = schema._flags[flag]; - if (prefs.noDefaults || source === void 0) { - return value; - } - state.mainstay.tracer.log(schema, state, "rule", flag, "full"); - if (!source) { - return source; - } - if (typeof source === "function") { - const args = source.length ? [clone2(state.ancestors[0]), helpers] : []; - try { - return source(...args); - } catch (err) { - errors.push(schema.$_createError(`any.${flag}`, null, { error: err }, state, prefs)); - return; + return newOpV2; } + } else { + return opV2; } - if (typeof source !== "object") { - return source; - } - if (source[Common.symbols.literal]) { - return source.literal; - } - if (Common.isResolvable(source)) { - return source.resolve(value, state, prefs); - } - return clone2(source); - }; - internals.trim = function(value, schema) { - if (typeof value !== "string") { - return value; - } - const trim = schema.$_getRule("trim"); - if (!trim || !trim.args.enabled) { - return value; - } - return value.trim(); - }; - internals.ignore = { - active: false, - debug: ignore, - entry: ignore, - filter: ignore, - log: ignore, - resolve: ignore, - value: ignore - }; - internals.errorsArray = function() { - const errors = []; - errors[Common.symbols.errors] = true; - return errors; }; + const newOpV = recreateOperationInternal(opT2, opV); + if (newOpV === opV) { + return rawOpV2; + } else if (newOpV === void 0) { + return; + } + if (typeof rawOpV2.recreate !== "function") { + throw new Error("Unable to recreate operation"); + } + return rawOpV2.recreate(newOpV); + }; + const newRawOpV = disableAutoDedup ? rawOpV : recreateOperation(opT, rawOpV); + if (!newRawOpV) + return; + const newOp = [opT, newRawOpV]; + entry = SPMessage.cloneWith(head, newOp, { + previousKeyOp, + previousHEAD, + height: previousHeight + 1 + }); + return entry; +}; +var getContractIDfromKeyId = (contractID, signingKeyId, state) => { + if (!signingKeyId) + return; + return signingKeyId && state._vm?.authorizedKeys?.[signingKeyId]?.foreignKey ? new URL(state._vm.authorizedKeys[signingKeyId].foreignKey).pathname : contractID; +}; +function eventsAfter(contractID, { sinceHeight, limit, sinceHash, stream = true }) { + if (!contractID) { + throw new Error("Missing contract ID"); } -}); -var require_values2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/values.js"(exports2, module14) { - "use strict"; - var { assert: assert2, deepEqual } = require_lib(); - var Common = require_common3(); - var internals = {}; - module14.exports = internals.Values = class { - constructor(values, refs) { - this._values = new Set(values); - this._refs = new Set(refs); - this._lowercase = internals.lowercases(values); - this._override = false; - } - get length() { - return this._values.size + this._refs.size; - } - add(value, refs) { - if (Common.isResolvable(value)) { - if (!this._refs.has(value)) { - this._refs.add(value); - if (refs) { - refs.register(value); - } - } - return; - } - if (!this.has(value, null, null, false)) { - this._values.add(value); - if (typeof value === "string") { - this._lowercase.set(value.toLowerCase(), value); - } - } - } - static merge(target, source, remove) { - target = target || new internals.Values(); - if (source) { - if (source._override) { - return source.clone(); - } - for (const item of [...source._values, ...source._refs]) { - target.add(item); - } - } - if (remove) { - for (const item of [...remove._values, ...remove._refs]) { - target.remove(item); - } - } - return target.length ? target : null; - } - remove(value) { - if (Common.isResolvable(value)) { - this._refs.delete(value); - return; - } - this._values.delete(value); - if (typeof value === "string") { - this._lowercase.delete(value.toLowerCase()); - } - } - has(value, state, prefs, insensitive) { - return !!this.get(value, state, prefs, insensitive); + let lastUrl; + const fetchEventsStreamReader = async () => { + requestLimit = Math.min(limit ?? MAX_EVENTS_AFTER, remainingEvents); + lastUrl = `${this.config.connectionURL}/eventsAfter/${contractID}/${sinceHeight}${Number.isInteger(requestLimit) ? `/${requestLimit}` : ""}`; + const eventsResponse = await this.config.fetch(lastUrl, { signal }); + if (!eventsResponse.ok) { + const msg = `${eventsResponse.status}: ${eventsResponse.statusText}`; + if (eventsResponse.status === 404 || eventsResponse.status === 410) { + throw new ChelErrorResourceGone(msg, { cause: eventsResponse.status }); } - get(value, state, prefs, insensitive) { - if (!this.length) { - return false; - } - if (this._values.has(value)) { - return { value }; - } - if (typeof value === "string" && value && insensitive) { - const found = this._lowercase.get(value.toLowerCase()); - if (found) { - return { value: found }; - } - } - if (!this._refs.size && typeof value !== "object") { - return false; - } - if (typeof value === "object") { - for (const item of this._values) { - if (deepEqual(item, value)) { - return { value: item }; - } - } - } - if (state) { - for (const ref of this._refs) { - const resolved = ref.resolve(value, state, prefs, null, { in: true }); - if (resolved === void 0) { - continue; + throw new ChelErrorUnexpectedHttpResponseCode(msg, { cause: eventsResponse.status }); + } + if (!eventsResponse.body) + throw new Error("Missing body"); + latestHeight = parseInt(eventsResponse.headers.get("shelter-headinfo-height"), 10); + if (!Number.isSafeInteger(latestHeight)) + throw new Error("Invalid latest height"); + requestCount++; + return eventsResponse.body.getReader(); + }; + if (!Number.isSafeInteger(sinceHeight) || sinceHeight < 0) { + throw new TypeError("Invalid since height value. Expected positive integer."); + } + const signal = this.abortController.signal; + let requestCount = 0; + let remainingEvents = limit ?? Number.POSITIVE_INFINITY; + let eventsStreamReader; + let latestHeight; + let state = "fetch"; + let requestLimit; + let count; + let buffer = ""; + let currentEvent; + const s = new ReadableStream({ + // The pull function is called whenever the internal buffer of the stream + // becomes empty and needs more data. + async pull(controller) { + try { + for (; ; ) { + switch (state) { + // When in 'fetch' state, initiate a new fetch request to obtain a + // stream reader for events. + case "fetch": { + eventsStreamReader = await fetchEventsStreamReader(); + state = "read-new-response"; + count = 0; + break; } - const items = !ref.in || typeof resolved !== "object" ? [resolved] : Array.isArray(resolved) ? resolved : Object.keys(resolved); - for (const item of items) { - if (typeof item !== typeof value) { - continue; + case "read-eos": + // End of stream case + case "read-new-response": + // Just started reading a new response + case "read": { + const { done, value } = await eventsStreamReader.read(); + if (done) { + if (remainingEvents === 0 || sinceHeight >= latestHeight) { + controller.close(); + return; + } else if (state === "read-new-response" || buffer) { + throw new Error("Invalid response: done too early"); + } else { + state = "fetch"; + break; + } + } + if (!value) { + throw new Error("Invalid response: missing body"); } - if (insensitive && value && typeof value === "string") { - if (item.toLowerCase() === value.toLowerCase()) { - return { value: item, ref }; + buffer = buffer + Buffer3.from(value).toString().trim(); + if (!buffer) + break; + if (state === "read-new-response") { + if (buffer[0] !== "[") { + throw new Error("Invalid response: no array start delimiter"); } - } else { - if (deepEqual(item, value)) { - return { value: item, ref }; + buffer = buffer.slice(1); + } else if (state === "read-eos") { + throw new Error("Invalid data at the end of response"); + } + state = "events"; + break; + } + case "events": { + const nextIdx = buffer.search(/(?<=\s*)[,\]]/); + if (nextIdx < 0) { + state = "read"; + break; + } + let enqueued = false; + try { + const eventValue = buffer.slice(0, nextIdx).trim(); + if (eventValue) { + if (count === requestLimit) { + throw new Error("Received too many events"); + } + currentEvent = JSON.parse(b64ToStr(JSON.parse(eventValue))).message; + if (count === 0) { + const hash3 = SPMessage.deserializeHEAD(currentEvent).hash; + const height = SPMessage.deserializeHEAD(currentEvent).head.height; + if (height !== sinceHeight || sinceHash && sinceHash !== hash3) { + if (height === sinceHeight && sinceHash && sinceHash !== hash3) { + throw new ChelErrorForkedChain(`Forked chain: hash(${hash3}) !== since(${sinceHash})`); + } else { + throw new Error(`Unexpected data: hash(${hash3}) !== since(${sinceHash || ""}) or height(${height}) !== since(${sinceHeight})`); + } + } + } + if (count++ !== 0 || requestCount !== 0) { + controller.enqueue(currentEvent); + enqueued = true; + remainingEvents--; + } + } + if (buffer[nextIdx] === "]") { + if (currentEvent) { + const deserialized = SPMessage.deserializeHEAD(currentEvent); + sinceHeight = deserialized.head.height; + sinceHash = deserialized.hash; + state = "read-eos"; + } else { + state = "eod"; + } + buffer = buffer.slice(nextIdx + 1).trim(); + } else if (currentEvent) { + buffer = buffer.slice(nextIdx + 1).trimStart(); + } else { + throw new Error("Missing end delimiter"); } + if (enqueued) { + return; + } + } catch (e2) { + console.error("[chelonia] Error during event parsing", e2); + throw e2; } + break; } - } - } - return false; - } - override() { - this._override = true; - } - values(options2) { - if (options2 && options2.display) { - const values = []; - for (const item of [...this._values, ...this._refs]) { - if (item !== void 0) { - values.push(item); + case "eod": { + if (remainingEvents === 0 || sinceHeight >= latestHeight) { + controller.close(); + } else { + throw new Error("Unexpected end of data"); + } + return; } } - return values; } - return Array.from([...this._values, ...this._refs]); - } - clone() { - const set = new internals.Values(this._values, this._refs); - set._override = this._override; - return set; - } - concat(source) { - assert2(!source._override, "Cannot concat override set of values"); - const set = new internals.Values([...this._values, ...source._values], [...this._refs, ...source._refs]); - set._override = this._override; - return set; + } catch (e2) { + console.error("[eventsAfter] Error", { lastUrl }, e2); + eventsStreamReader?.cancel("Error during pull").catch((e22) => { + console.error("Error canceling underlying event stream reader on error", e2, e22); + }); + throw e2; } - describe() { - const normalized = []; - if (this._override) { - normalized.push({ override: true }); - } - for (const value of this._values.values()) { - normalized.push(value && typeof value === "object" ? { value } : value); - } - for (const value of this._refs.values()) { - normalized.push(value.describe()); - } - return normalized; + } + }); + if (stream) + return s; + return collectEventStream(s); +} +function buildShelterAuthorizationHeader(contractID, state) { + if (!state) + state = esm_default(this.config.stateSelector)[contractID]; + const SAKid = findKeyIdByName(state, "#sak"); + if (!SAKid) { + throw new Error(`Missing #sak in ${contractID}`); + } + const SAK = this.transientSecretKeys[SAKid]; + if (!SAK) { + throw new Error(`Missing secret #sak (${SAKid}) in ${contractID}`); + } + const deserializedSAK = typeof SAK === "string" ? deserializeKey(SAK) : SAK; + const nonceBytes = new Uint8Array(15); + globalThis.crypto.getRandomValues(nonceBytes); + const data = `${contractID} ${esm_default("chelonia/time")}.${Buffer3.from(nonceBytes).toString("base64")}`; + return `shelter ${data}.${sign(deserializedSAK, data)}`; +} +function verifyShelterAuthorizationHeader(authorization, rootState) { + const regex = /^shelter (([a-zA-Z0-9]+) ([0-9]+)\.([a-zA-Z0-9+/=]{20}))\.([a-zA-Z0-9+/=]+)$/i; + if (authorization.length > 1024) { + throw new Error("Authorization header too long"); + } + const matches = authorization.match(regex); + if (!matches) { + throw new Error("Unable to parse shelter authorization header"); + } + const [, data, contractID, timestamp, , signature] = matches; + if (Math.abs(parseInt(timestamp) - Date.now()) > 6e4) { + throw new Error("Invalid signature time range"); + } + if (!rootState) + rootState = esm_default("chelonia/rootState"); + if (!has(rootState, contractID)) { + throw new Error(`Contract ${contractID} from shelter authorization header not found`); + } + const SAKid = findKeyIdByName(rootState[contractID], "#sak"); + if (!SAKid) { + throw new Error(`Missing #sak in ${contractID}`); + } + const SAK = rootState[contractID]._vm.authorizedKeys[SAKid].data; + if (!SAK) { + throw new Error(`Missing secret #sak (${SAKid}) in ${contractID}`); + } + const deserializedSAK = deserializeKey(SAK); + verifySignature(deserializedSAK, data, signature); + return contractID; +} +var clearObject = (o2) => { + Object.keys(o2).forEach((k) => delete o2[k]); +}; +var reactiveClearObject = (o2, fn) => { + Object.keys(o2).forEach((k) => fn(o2, k)); +}; +var checkCanBeGarbageCollected = function(id) { + const rootState = esm_default(this.config.stateSelector); + return ( + // Check persistent references + (!has(rootState.contracts, id) || !rootState.contracts[id] || !has(rootState.contracts[id], "references")) && // Check ephemeral references + !has(this.ephemeralReferenceCount, id) && // Check foreign keys (i.e., that no keys from this contract are being watched) + (!has(rootState, id) || !has(rootState[id], "_volatile") || !has(rootState[id]._volatile, "watch") || rootState[id]._volatile.watch.length === 0 || rootState[id]._volatile.watch.filter(([, cID]) => this.subscriptionSet.has(cID)).length === 0) + ); +}; +var collectEventStream = async (s) => { + const reader = s.getReader(); + const r = []; + for (; ; ) { + const { done, value } = await reader.read(); + if (done) + break; + r.push(value); + } + return r; +}; +var logEvtError = (msg, ...args) => { + if (msg._direction === "outgoing") { + console.warn(...args); + } else { + console.error(...args); + } +}; +var handleFetchResult = (type) => { + return function(r) { + if (!r.ok) { + const msg = `${r.status}: ${r.statusText}`; + if (r.status === 404 || r.status === 410) { + throw new ChelErrorResourceGone(msg, { cause: r.status }); } - }; - internals.Values.prototype[Common.symbols.values] = true; - internals.Values.prototype.slice = internals.Values.prototype.clone; - internals.lowercases = function(from3) { - const map = /* @__PURE__ */ new Map(); - if (from3) { - for (const value of from3) { - if (typeof value === "string") { - map.set(value.toLowerCase(), value); - } + throw new ChelErrorUnexpectedHttpResponseCode(msg, { cause: r.status }); + } + return r[type](); + }; +}; +var supportsRequestStreams = typeof window !== "object" || (() => { + let duplexAccessed = false; + const hasContentType = new Request("", { + body: new ReadableStream(), + method: "POST", + get duplex() { + duplexAccessed = true; + return "half"; + } + }).headers.has("content-type"); + return duplexAccessed && !hasContentType; +})(); +var streamToUint8Array = async (s) => { + const reader = s.getReader(); + const chunks = []; + let length2 = 0; + for (; ; ) { + const result = await reader.read(); + if (result.done) + break; + chunks.push(coerce(result.value)); + length2 += result.value.byteLength; + } + const body = new Uint8Array(length2); + chunks.reduce((offset, chunk) => { + body.set(chunk, offset); + return offset + chunk.byteLength; + }, 0); + return body; +}; +var ArrayBufferToUint8ArrayStream = async function(connectionURL, s) { + if (supportsRequestStreams === true) { + await this.config.fetch(`${connectionURL}/streams-test`, { + method: "POST", + body: new ReadableStream({ + start(c) { + c.enqueue(Buffer4.from("ok")); + c.close(); } - } - return map; - }; + }), + duplex: "half" + }).then((r) => { + if (!r.ok) + throw new Error("Unexpected response"); + supportsRequestStreams = 2; + }).catch(() => { + console.info("files: Disabling streams support because the streams test failed"); + supportsRequestStreams = false; + }); } -}); -var require_base2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/base.js"(exports2, module14) { - "use strict"; - var { assert: assert2, clone: clone2, deepEqual, merge: merge3 } = require_lib(); - var Cache = require_cache2(); - var Common = require_common3(); - var Compile = require_compile2(); - var Errors = require_errors3(); - var Extend = require_extend2(); - var Manifest = require_manifest(); - var Messages = require_messages2(); - var Modify = require_modify2(); - var Ref = require_ref2(); - var Trace = require_trace(); - var Validator = require_validator3(); - var Values = require_values2(); - var internals = {}; - internals.Base = class { - constructor(type) { - this.type = type; - this.$_root = null; - this._definition = {}; - this._reset(); - } - _reset() { - this._ids = new Modify.Ids(); - this._preferences = null; - this._refs = new Ref.Manager(); - this._cache = null; - this._valids = null; - this._invalids = null; - this._flags = {}; - this._rules = []; - this._singleRules = /* @__PURE__ */ new Map(); - this.$_terms = {}; - this.$_temp = { - // Runtime state (not cloned) - ruleset: null, - // null: use last, false: error, number: start position - whens: {} - // Runtime cache of generated whens - }; - } - // Manifest - describe() { - assert2(typeof Manifest.describe === "function", "Manifest functionality disabled"); - return Manifest.describe(this); - } - // Rules - allow(...values) { - Common.verifyFlat(values, "allow"); - return this._values(values, "_valids"); - } - alter(targets) { - assert2(targets && typeof targets === "object" && !Array.isArray(targets), "Invalid targets argument"); - assert2(!this._inRuleset(), "Cannot set alterations inside a ruleset"); - const obj = this.clone(); - obj.$_terms.alterations = obj.$_terms.alterations || []; - for (const target in targets) { - const adjuster = targets[target]; - assert2(typeof adjuster === "function", "Alteration adjuster for", target, "must be a function"); - obj.$_terms.alterations.push({ target, adjuster }); - } - obj.$_temp.ruleset = false; - return obj; - } - artifact(id) { - assert2(id !== void 0, "Artifact cannot be undefined"); - assert2(!this._cache, "Cannot set an artifact with a rule cache"); - return this.$_setFlag("artifact", id); - } - cast(to) { - assert2(to === false || typeof to === "string", "Invalid to value"); - assert2(to === false || this._definition.cast[to], "Type", this.type, "does not support casting to", to); - return this.$_setFlag("cast", to === false ? void 0 : to); - } - default(value, options2) { - return this._default("default", value, options2); - } - description(desc) { - assert2(desc && typeof desc === "string", "Description must be a non-empty string"); - return this.$_setFlag("description", desc); - } - empty(schema) { - const obj = this.clone(); - if (schema !== void 0) { - schema = obj.$_compile(schema, { override: false }); - } - return obj.$_setFlag("empty", schema, { clone: false }); - } - error(err) { - assert2(err, "Missing error"); - assert2(err instanceof Error || typeof err === "function", "Must provide a valid Error object or a function"); - return this.$_setFlag("error", err); - } - example(example, options2 = {}) { - assert2(example !== void 0, "Missing example"); - Common.assertOptions(options2, ["override"]); - return this._inner("examples", example, { single: true, override: options2.override }); - } - external(method, description) { - if (typeof method === "object") { - assert2(!description, "Cannot combine options with description"); - description = method.description; - method = method.method; - } - assert2(typeof method === "function", "Method must be a function"); - assert2(description === void 0 || description && typeof description === "string", "Description must be a non-empty string"); - return this._inner("externals", { method, description }, { single: true }); - } - failover(value, options2) { - return this._default("failover", value, options2); - } - forbidden() { - return this.presence("forbidden"); - } - id(id) { - if (!id) { - return this.$_setFlag("id", void 0); - } - assert2(typeof id === "string", "id must be a non-empty string"); - assert2(/^[^\.]+$/.test(id), "id cannot contain period character"); - return this.$_setFlag("id", id); - } - invalid(...values) { - return this._values(values, "_invalids"); - } - label(name) { - assert2(name && typeof name === "string", "Label name must be a non-empty string"); - return this.$_setFlag("label", name); - } - meta(meta) { - assert2(meta !== void 0, "Meta cannot be undefined"); - return this._inner("metas", meta, { single: true }); - } - note(...notes) { - assert2(notes.length, "Missing notes"); - for (const note of notes) { - assert2(note && typeof note === "string", "Notes must be non-empty strings"); - } - return this._inner("notes", notes); - } - only(mode = true) { - assert2(typeof mode === "boolean", "Invalid mode:", mode); - return this.$_setFlag("only", mode); - } - optional() { - return this.presence("optional"); - } - prefs(prefs) { - assert2(prefs, "Missing preferences"); - assert2(prefs.context === void 0, "Cannot override context"); - assert2(prefs.externals === void 0, "Cannot override externals"); - assert2(prefs.warnings === void 0, "Cannot override warnings"); - assert2(prefs.debug === void 0, "Cannot override debug"); - Common.checkPreferences(prefs); - const obj = this.clone(); - obj._preferences = Common.preferences(obj._preferences, prefs); - return obj; - } - presence(mode) { - assert2(["optional", "required", "forbidden"].includes(mode), "Unknown presence mode", mode); - return this.$_setFlag("presence", mode); - } - raw(enabled2 = true) { - return this.$_setFlag("result", enabled2 ? "raw" : void 0); - } - result(mode) { - assert2(["raw", "strip"].includes(mode), "Unknown result mode", mode); - return this.$_setFlag("result", mode); - } - required() { - return this.presence("required"); - } - strict(enabled2) { - const obj = this.clone(); - const convert = enabled2 === void 0 ? false : !enabled2; - obj._preferences = Common.preferences(obj._preferences, { convert }); - return obj; + if (!supportsRequestStreams) { + return await streamToUint8Array(s); + } + return s.pipeThrough( + // eslint-disable-next-line no-undef + new TransformStream({ + transform(chunk, controller) { + controller.enqueue(coerce(chunk)); } - strip(enabled2 = true) { - return this.$_setFlag("result", enabled2 ? "strip" : void 0); + }) + ); +}; +var computeChunkDescriptors = (inStream) => { + let length2 = 0; + const [lengthStream, cidStream] = inStream.tee(); + const lengthPromise = new Promise((resolve82, reject) => { + lengthStream.pipeTo(new WritableStream({ + write(chunk) { + length2 += chunk.byteLength; + }, + close() { + resolve82(length2); + }, + abort(reason) { + reject(reason); } - tag(...tags) { - assert2(tags.length, "Missing tags"); - for (const tag3 of tags) { - assert2(tag3 && typeof tag3 === "string", "Tags must be non-empty strings"); + })); + }); + const cidPromise = createCIDfromStream(cidStream, multicodes.SHELTER_FILE_CHUNK); + return Promise.all([lengthPromise, cidPromise]); +}; +var fileStream = (chelonia, manifest2) => { + const dataGenerator = async function* () { + let readSize = 0; + for (const chunk of manifest2.chunks) { + if (!Array.isArray(chunk) || typeof chunk[0] !== "number" || typeof chunk[1] !== "string") { + throw new Error("Invalid chunk descriptor"); + } + const chunkResponse = await chelonia.config.fetch(`${chelonia.config.connectionURL}/file/${chunk[1]}`, { + method: "GET", + signal: chelonia.abortController.signal + }); + if (!chunkResponse.ok) { + throw new Error("Unable to retrieve manifest"); + } + const chunkBinary = await chunkResponse.arrayBuffer(); + if (chunkBinary.byteLength !== chunk[0]) + throw new Error("mismatched chunk size"); + readSize += chunkBinary.byteLength; + if (readSize > manifest2.size) + throw new Error("read size exceeds declared size"); + if (createCID(coerce(chunkBinary), multicodes.SHELTER_FILE_CHUNK) !== chunk[1]) { + throw new Error("mismatched chunk hash"); + } + yield chunkBinary; + } + if (readSize !== manifest2.size) + throw new Error("mismatched size"); + }; + const dataIterator = dataGenerator(); + return new ReadableStream({ + async pull(controller) { + try { + const chunk = await dataIterator.next(); + if (chunk.done) { + controller.close(); + return; } - return this._inner("tags", tags); - } - unit(name) { - assert2(name && typeof name === "string", "Unit name must be a non-empty string"); - return this.$_setFlag("unit", name); - } - valid(...values) { - Common.verifyFlat(values, "valid"); - const obj = this.allow(...values); - obj.$_setFlag("only", !!obj._valids, { clone: false }); - return obj; + controller.enqueue(chunk.value); + } catch (e2) { + controller.error(e2); } - when(condition, options2) { - const obj = this.clone(); - if (!obj.$_terms.whens) { - obj.$_terms.whens = []; - } - const when = Compile.when(obj, condition, options2); - if (!["any", "link"].includes(obj.type)) { - const conditions = when.is ? [when] : when.switch; - for (const item of conditions) { - assert2(!item.then || item.then.type === "any" || item.then.type === obj.type, "Cannot combine", obj.type, "with", item.then && item.then.type); - assert2(!item.otherwise || item.otherwise.type === "any" || item.otherwise.type === obj.type, "Cannot combine", obj.type, "with", item.otherwise && item.otherwise.type); - } - } - obj.$_terms.whens.push(when); - return obj.$_mutateRebuild(); - } - // Helpers - cache(cache2) { - assert2(!this._inRuleset(), "Cannot set caching inside a ruleset"); - assert2(!this._cache, "Cannot override schema cache"); - assert2(this._flags.artifact === void 0, "Cannot cache a rule with an artifact"); - const obj = this.clone(); - obj._cache = cache2 || Cache.provider.provision(); - obj.$_temp.ruleset = false; - return obj; + } + }); +}; +var aes256gcmHandlers = { + upload: (_chelonia, manifestOptions) => { + const params = manifestOptions["cipher-params"]; + let IKM = params?.IKM; + const recordSize = params?.rs ?? 1 << 16; + if (!IKM) { + IKM = new Uint8Array(33); + self.crypto.getRandomValues(IKM); + } + const keyId2 = blake32Hash("aes256gcm-keyId" + blake32Hash(IKM)).slice(-8); + const binaryKeyId = Buffer4.from(keyId2); + return { + cipherParams: { + keyId: keyId2 + }, + streamHandler: async (stream) => { + return await K(e, stream, recordSize, binaryKeyId, IKM); + }, + downloadParams: { + IKM: Buffer4.from(IKM).toString("base64"), + rs: recordSize } - clone() { - const obj = Object.create(Object.getPrototypeOf(this)); - return this._assign(obj); - } - concat(source) { - assert2(Common.isSchema(source), "Invalid schema object"); - assert2(this.type === "any" || source.type === "any" || source.type === this.type, "Cannot merge type", this.type, "with another type:", source.type); - assert2(!this._inRuleset(), "Cannot concatenate onto a schema with open ruleset"); - assert2(!source._inRuleset(), "Cannot concatenate a schema with open ruleset"); - let obj = this.clone(); - if (this.type === "any" && source.type !== "any") { - const tmpObj = source.clone(); - for (const key of Object.keys(obj)) { - if (key !== "type") { - tmpObj[key] = obj[key]; - } - } - obj = tmpObj; - } - obj._ids.concat(source._ids); - obj._refs.register(source, Ref.toSibling); - obj._preferences = obj._preferences ? Common.preferences(obj._preferences, source._preferences) : source._preferences; - obj._valids = Values.merge(obj._valids, source._valids, source._invalids); - obj._invalids = Values.merge(obj._invalids, source._invalids, source._valids); - for (const name of source._singleRules.keys()) { - if (obj._singleRules.has(name)) { - obj._rules = obj._rules.filter((target) => target.keep || target.name !== name); - obj._singleRules.delete(name); - } - } - for (const test of source._rules) { - if (!source._definition.rules[test.method].multi) { - obj._singleRules.set(test.name, test); - } - obj._rules.push(test); - } - if (obj._flags.empty && source._flags.empty) { - obj._flags.empty = obj._flags.empty.concat(source._flags.empty); - const flags = Object.assign({}, source._flags); - delete flags.empty; - merge3(obj._flags, flags); - } else if (source._flags.empty) { - obj._flags.empty = source._flags.empty; - const flags = Object.assign({}, source._flags); - delete flags.empty; - merge3(obj._flags, flags); - } else { - merge3(obj._flags, source._flags); - } - for (const key in source.$_terms) { - const terms = source.$_terms[key]; - if (!terms) { - if (!obj.$_terms[key]) { - obj.$_terms[key] = terms; - } - continue; - } - if (!obj.$_terms[key]) { - obj.$_terms[key] = terms.slice(); - continue; + }; + }, + download: (chelonia, downloadParams, manifest2) => { + const IKMb64 = downloadParams.IKM; + if (!IKMb64) { + throw new Error("Missing IKM in downloadParams"); + } + const IKM = Buffer4.from(IKMb64, "base64"); + const keyId2 = blake32Hash("aes256gcm-keyId" + blake32Hash(IKM)).slice(-8); + if (!manifest2["cipher-params"] || !manifest2["cipher-params"].keyId) { + throw new Error("Missing cipher-params"); + } + if (keyId2 !== manifest2["cipher-params"].keyId) { + throw new Error("Key ID mismatch"); + } + const maxRecordSize = downloadParams.rs ?? 1 << 27; + return { + payloadHandler: async () => { + const bytes = await streamToUint8Array(S(e, fileStream(chelonia, manifest2), (actualKeyId) => { + if (Buffer4.from(actualKeyId).toString() !== keyId2) { + throw new Error("Invalid key ID"); } - obj.$_terms[key] = obj.$_terms[key].concat(terms); - } - if (this.$_root._tracer) { - this.$_root._tracer._combine(obj, [this, source]); - } - return obj.$_mutateRebuild(); - } - extend(options2) { - assert2(!options2.base, "Cannot extend type with another base"); - return Extend.type(this, options2); + return IKM; + }, maxRecordSize)); + return new Blob([bytes], { type: manifest2.type || "application/octet-stream" }); } - extract(path8) { - path8 = Array.isArray(path8) ? path8 : path8.split("."); - return this._ids.reach(path8); - } - fork(paths, adjuster) { - assert2(!this._inRuleset(), "Cannot fork inside a ruleset"); - let obj = this; - for (let path8 of [].concat(paths)) { - path8 = Array.isArray(path8) ? path8 : path8.split("."); - obj = obj._ids.fork(path8, adjuster, obj); - } - obj.$_temp.ruleset = false; - return obj; + }; + } +}; +var noneHandlers = { + upload: () => { + return { + cipherParams: void 0, + streamHandler: (stream) => { + return stream; + }, + downloadParams: void 0 + }; + }, + download: (chelonia, _downloadParams, manifest2) => { + return { + payloadHandler: async () => { + const bytes = await streamToUint8Array(fileStream(chelonia, manifest2)); + return new Blob([bytes], { type: manifest2.type || "application/octet-stream" }); } - isAsync() { - if (Boolean(this.$_terms.externals?.length)) { - return true; - } - if (this.$_terms.whens) { - for (const when of this.$_terms.whens) { - if (when.then?.isAsync()) { - return true; - } - if (when.otherwise?.isAsync()) { - return true; - } - if (when.switch) { - for (const item of when.switch) { - if (item.then?.isAsync()) { - return true; - } - if (item.otherwise?.isAsync()) { - return true; - } - } - } - } + }; + } +}; +var cipherHandlers = { + aes256gcm: aes256gcmHandlers, + none: noneHandlers +}; +var files_default = esm_default("sbp/selectors/register", { + "chelonia/fileUpload": async function(chunks, manifestOptions, { billableContractID } = {}) { + if (!Array.isArray(chunks)) + chunks = [chunks]; + const chunkDescriptors = []; + const cipherHandler = await cipherHandlers[manifestOptions.cipher]?.upload?.(this, manifestOptions); + if (!cipherHandler) + throw new Error("Unsupported cipher"); + const cipherParams = cipherHandler.cipherParams; + const transferParts = await Promise.all(chunks.map(async (chunk, i2) => { + const stream2 = chunk.stream(); + const encryptedStream = await cipherHandler.streamHandler(stream2); + const [body, s] = encryptedStream.tee(); + chunkDescriptors.push(computeChunkDescriptors(s)); + return { + headers: new Headers([ + ["content-disposition", `form-data; name="${i2}"; filename="${i2}"`], + ["content-type", "application/octet-stream"] + ]), + body + }; + })); + transferParts.push({ + headers: new Headers([ + ["content-disposition", 'form-data; name="manifest"; filename="manifest.json"'], + ["content-type", "application/vnd.shelter.filemanifest"] + ]), + body: new ReadableStream({ + async start(controller) { + const chunks2 = await Promise.all(chunkDescriptors); + const manifest2 = { + version: "1.0.0", + // ?? undefined coerces null and undefined to undefined + // This ensures that null or undefined values don't make it to the + // JSON (otherwise, null values _would_ be stringified as 'null') + type: manifestOptions.type ?? void 0, + meta: manifestOptions.meta ?? void 0, + cipher: manifestOptions.cipher, + "cipher-params": cipherParams, + size: chunks2.reduce((acc, [cv]) => acc + cv, 0), + chunks: chunks2, + "name-map": manifestOptions["name-map"] ?? void 0, + alternatives: manifestOptions.alternatives ?? void 0 + }; + controller.enqueue(Buffer4.from(JSON.stringify(manifest2))); + controller.close(); } + }) + }); + const boundary = typeof self.crypto?.randomUUID === "function" ? self.crypto.randomUUID() : new Array(36).fill("").map(() => "abcdefghijklmnopqrstuvwxyz"[(0, Math.random)() * 26 | 0]).join(""); + const stream = x(boundary, transferParts); + const deletionToken = "deletionToken" + generateSalt(); + const deletionTokenHash = blake32Hash(deletionToken); + const uploadResponse = await this.config.fetch(`${this.config.connectionURL}/file`, { + method: "POST", + signal: this.abortController.signal, + body: await ArrayBufferToUint8ArrayStream.call(this, this.config.connectionURL, stream), + headers: new Headers([ + ...billableContractID ? [["authorization", buildShelterAuthorizationHeader.call(this, billableContractID)]] : [], + ["content-type", `multipart/form-data; boundary=${boundary}`], + ["shelter-deletion-token-digest", deletionTokenHash] + ]), + duplex: "half" + }); + if (!uploadResponse.ok) + throw new Error("Error uploading file"); + return { + download: { + manifestCid: await uploadResponse.text(), + downloadParams: cipherHandler.downloadParams + }, + delete: deletionToken + }; + }, + "chelonia/fileDownload": async function(downloadOptions, manifestChecker) { + const { manifestCid, downloadParams } = downloadOptions.valueOf(); + const manifestResponse = await this.config.fetch(`${this.config.connectionURL}/file/${manifestCid}`, { + method: "GET", + signal: this.abortController.signal + }); + if (!manifestResponse.ok) { + throw new Error("Unable to retrieve manifest"); + } + const manifestBinary = await manifestResponse.arrayBuffer(); + if (createCID(coerce(manifestBinary), multicodes.SHELTER_FILE_MANIFEST) !== manifestCid) { + throw new Error("mismatched manifest hash"); + } + const manifest2 = JSON.parse(Buffer4.from(manifestBinary).toString()); + if (typeof manifest2 !== "object") + throw new Error("manifest format is invalid"); + if (manifest2.version !== "1.0.0") + throw new Error("unsupported manifest version"); + if (!Array.isArray(manifest2.chunks)) + throw new Error("missing required field: chunks"); + if (manifestChecker) { + const proceed = await manifestChecker?.(manifest2); + if (!proceed) return false; + } + const cipherHandler = await cipherHandlers[manifest2.cipher]?.download?.(this, downloadParams, manifest2); + if (!cipherHandler) + throw new Error("Unsupported cipher"); + return cipherHandler.payloadHandler(); + }, + "chelonia/fileDelete": async function(manifestCid, credentials = {}) { + if (!manifestCid) { + throw new TypeError("A manifest CID must be provided"); + } + if (!Array.isArray(manifestCid)) + manifestCid = [manifestCid]; + return await Promise.allSettled(manifestCid.map(async (cid) => { + const hasCredential = has(credentials, cid); + const hasToken = has(credentials[cid], "token") && credentials[cid].token; + const hasBillableContractID = has(credentials[cid], "billableContractID") && credentials[cid].billableContractID; + if (!hasCredential || hasToken === hasBillableContractID) { + throw new TypeError(`Either a token or a billable contract ID must be provided for ${cid}`); + } + const response = await this.config.fetch(`${this.config.connectionURL}/deleteFile/${cid}`, { + method: "POST", + signal: this.abortController.signal, + headers: new Headers([ + [ + "authorization", + hasToken ? `bearer ${credentials[cid].token.valueOf()}` : buildShelterAuthorizationHeader.call(this, credentials[cid].billableContractID) + ] + ]) + }); + if (!response.ok) { + throw new Error(`Unable to delete file ${cid}`); } - rule(options2) { - const def = this._definition; - Common.assertOptions(options2, Object.keys(def.modifiers)); - assert2(this.$_temp.ruleset !== false, "Cannot apply rules to empty ruleset or the last rule added does not support rule properties"); - const start = this.$_temp.ruleset === null ? this._rules.length - 1 : this.$_temp.ruleset; - assert2(start >= 0 && start < this._rules.length, "Cannot apply rules to empty ruleset"); - const obj = this.clone(); - for (let i2 = start; i2 < obj._rules.length; ++i2) { - const original = obj._rules[i2]; - const rule = clone2(original); - for (const name in options2) { - def.modifiers[name](rule, options2[name]); - assert2(rule.name === original.name, "Cannot change rule name"); - } - obj._rules[i2] = rule; - if (obj._singleRules.get(rule.name) === original) { - obj._singleRules.set(rule.name, rule); - } - } - obj.$_temp.ruleset = false; - return obj.$_mutateRebuild(); - } - get ruleset() { - assert2(!this._inRuleset(), "Cannot start a new ruleset without closing the previous one"); - const obj = this.clone(); - obj.$_temp.ruleset = obj._rules.length; - return obj; - } - get $() { - return this.ruleset; - } - tailor(targets) { - targets = [].concat(targets); - assert2(!this._inRuleset(), "Cannot tailor inside a ruleset"); - let obj = this; - if (this.$_terms.alterations) { - for (const { target, adjuster } of this.$_terms.alterations) { - if (targets.includes(target)) { - obj = adjuster(obj); - assert2(Common.isSchema(obj), "Alteration adjuster for", target, "failed to return a schema object"); - } - } - } - obj = obj.$_modify({ each: (item) => item.tailor(targets), ref: false }); - obj.$_temp.ruleset = false; - return obj.$_mutateRebuild(); - } - tracer() { - return Trace.location ? Trace.location(this) : this; - } - validate(value, options2) { - return Validator.entry(value, this, options2); - } - validateAsync(value, options2) { - return Validator.entryAsync(value, this, options2); - } - // Extensions - $_addRule(options2) { - if (typeof options2 === "string") { - options2 = { name: options2 }; - } - assert2(options2 && typeof options2 === "object", "Invalid options"); - assert2(options2.name && typeof options2.name === "string", "Invalid rule name"); - for (const key in options2) { - assert2(key[0] !== "_", "Cannot set private rule properties"); - } - const rule = Object.assign({}, options2); - rule._resolve = []; - rule.method = rule.method || rule.name; - const definition = this._definition.rules[rule.method]; - const args = rule.args; - assert2(definition, "Unknown rule", rule.method); - const obj = this.clone(); - if (args) { - assert2(Object.keys(args).length === 1 || Object.keys(args).length === this._definition.rules[rule.name].args.length, "Invalid rule definition for", this.type, rule.name); - for (const key in args) { - let arg = args[key]; - if (definition.argsByName) { - const resolver = definition.argsByName.get(key); - if (resolver.ref && Common.isResolvable(arg)) { - rule._resolve.push(key); - obj.$_mutateRegister(arg); - } else { - if (resolver.normalize) { - arg = resolver.normalize(arg); - args[key] = arg; - } - if (resolver.assert) { - const error2 = Common.validateArg(arg, key, resolver); - assert2(!error2, error2, "or reference"); - } - } - } - if (arg === void 0) { - delete args[key]; - continue; - } - args[key] = arg; - } - } - if (!definition.multi) { - obj._ruleRemove(rule.name, { clone: false }); - obj._singleRules.set(rule.name, rule); - } - if (obj.$_temp.ruleset === false) { - obj.$_temp.ruleset = null; - } - if (definition.priority) { - obj._rules.unshift(rule); + })); + } +}); +init_esm(); +init_functions(); +init_esm4(); +init_SPMessage(); +init_esm6(); +init_db(); +init_encryptedData(); +init_errors3(); +init_signedData(); +var missingDecryptionKeyIdsMap = /* @__PURE__ */ new WeakMap(); +var getMsgMeta = function(message, contractID, state, index) { + const signingKeyId = message.signingKeyId(); + let innerSigningKeyId = null; + const config2 = this.config; + const result = { + signingKeyId, + get signingContractID() { + return getContractIDfromKeyId(contractID, signingKeyId, state); + }, + get innerSigningKeyId() { + if (innerSigningKeyId === null) { + const value = message.message(); + const data = config2.unwrapMaybeEncryptedData(value); + if (data?.data && isSignedData(data.data)) { + innerSigningKeyId = data.data.signingKeyId; } else { - obj._rules.push(rule); - } - return obj; - } - $_compile(schema, options2) { - return Compile.schema(this.$_root, schema, options2); - } - $_createError(code2, value, local, state, prefs, options2 = {}) { - const flags = options2.flags !== false ? this._flags : {}; - const messages = options2.messages ? Messages.merge(this._definition.messages, options2.messages) : this._definition.messages; - return new Errors.Report(code2, value, local, flags, messages, state, prefs); - } - $_getFlag(name) { - return this._flags[name]; - } - $_getRule(name) { - return this._singleRules.get(name); - } - $_mapLabels(path8) { - path8 = Array.isArray(path8) ? path8 : path8.split("."); - return this._ids.labels(path8); - } - $_match(value, state, prefs, overrides) { - prefs = Object.assign({}, prefs); - prefs.abortEarly = true; - prefs._externals = false; - state.snapshot(); - const result = !Validator.validate(value, this, state, prefs, overrides).errors; - state.restore(); - return result; - } - $_modify(options2) { - Common.assertOptions(options2, ["each", "once", "ref", "schema"]); - return Modify.schema(this, options2) || this; - } - $_mutateRebuild() { - assert2(!this._inRuleset(), "Cannot add this rule inside a ruleset"); - this._refs.reset(); - this._ids.reset(); - const each = (item, { source, name, path: path8, key }) => { - const family = this._definition[source][name] && this._definition[source][name].register; - if (family !== false) { - this.$_mutateRegister(item, { family, key }); - } - }; - this.$_modify({ each }); - if (this._definition.rebuild) { - this._definition.rebuild(this); + innerSigningKeyId = void 0; } - this.$_temp.ruleset = false; - return this; + return innerSigningKeyId; } - $_mutateRegister(schema, { family, key } = {}) { - this._refs.register(schema, family); - this._ids.register(schema, { key }); + }, + get innerSigningContractID() { + return getContractIDfromKeyId(contractID, result.innerSigningKeyId, state); + }, + index + }; + return result; +}; +var keysToMap = function(keys_, height, authorizedKeys) { + const keys = keys_.map((key) => { + const data = this.config.unwrapMaybeEncryptedData(key); + if (!data) + return void 0; + if (data.encryptionKeyId) { + data.data._private = data.encryptionKeyId; + } + return data.data; + }).filter(Boolean); + const keysCopy = cloneDeep(keys); + return Object.fromEntries(keysCopy.map((key) => { + key._notBeforeHeight = height; + if (authorizedKeys?.[key.id]) { + if (authorizedKeys[key.id]._notAfterHeight == null) { + throw new ChelErrorKeyAlreadyExists(`Cannot set existing unrevoked key: ${key.id}`); + } + key._notBeforeHeight = Math.min(height, authorizedKeys[key.id]._notBeforeHeight ?? 0); + } else { + key._notBeforeHeight = height; + } + delete key._notAfterHeight; + return [key.id, key]; + })); +}; +var keyRotationHelper = (contractID, state, config2, updatedKeysMap, requiredPermissions, outputSelector, outputMapper, internalSideEffectStack) => { + if (!internalSideEffectStack || !Array.isArray(state._volatile?.watch)) + return; + const rootState = esm_default(config2.stateSelector); + const watchMap = /* @__PURE__ */ Object.create(null); + state._volatile.watch.forEach(([name, cID]) => { + if (!updatedKeysMap[name] || watchMap[cID] === null) { + return; + } + if (!watchMap[cID]) { + if (!rootState.contracts[cID]?.type || !findSuitableSecretKeyId(rootState[cID], [SPMessage.OP_KEY_UPDATE], ["sig"])) { + watchMap[cID] = null; + return; } - $_property(name) { - return this._definition.properties[name]; + watchMap[cID] = []; + } + watchMap[cID].push(name); + }); + Object.entries(watchMap).forEach(([cID, names]) => { + if (!Array.isArray(names) || !names.length) + return; + const [keyNamesToUpdate, signingKeyId] = names.map((name) => { + const foreignContractKey = rootState[cID]?._vm?.authorizedKeys?.[updatedKeysMap[name].oldKeyId]; + if (!foreignContractKey) + return void 0; + const signingKeyId2 = findSuitableSecretKeyId(rootState[cID], requiredPermissions, ["sig"], foreignContractKey.ringLevel); + if (signingKeyId2) { + return [ + [name, foreignContractKey.name], + signingKeyId2, + rootState[cID]._vm.authorizedKeys[signingKeyId2].ringLevel + ]; } - $_reach(path8) { - return this._ids.reach(path8); + return void 0; + }).filter(Boolean).reduce((acc, [name, signingKeyId2, ringLevel]) => { + acc[0].push(name); + return ringLevel < acc[2] ? [acc[0], signingKeyId2, ringLevel] : acc; + }, [[], void 0, Number.POSITIVE_INFINITY]); + if (!signingKeyId) + return; + const contractName = rootState.contracts[cID]?.type; + internalSideEffectStack?.push(() => { + esm_default(outputSelector, { + contractID: cID, + contractName, + data: keyNamesToUpdate.map(outputMapper).map((v2) => { + return v2; + }), + signingKeyId + }).catch((e2) => { + console.warn(`Error mirroring key operation (${outputSelector}) from ${contractID} to ${cID}: ${e2?.message || e2}`); + }); + }); + }); +}; +var internals_default = esm_default("sbp/selectors/register", { + // DO NOT CALL ANY OF THESE YOURSELF! + "chelonia/private/state": function() { + return this.state; + }, + "chelonia/private/invoke": function(instance, invocation) { + if (this._instance !== instance) { + console.info("['chelonia/private/invoke] Not proceeding with invocation as Chelonia was restarted", { invocation }); + return; + } + if (Array.isArray(invocation)) { + return esm_default(...invocation); + } else if (typeof invocation === "function") { + return invocation(); + } else { + throw new TypeError(`[chelonia/private/invoke] Expected invocation to be an array or a function. Saw ${typeof invocation} instead.`); + } + }, + "chelonia/private/queueEvent": function(queueName, invocation) { + return esm_default("okTurtles.eventQueue/queueEvent", queueName, [ + "chelonia/private/invoke", + this._instance, + invocation + ]); + }, + "chelonia/private/verifyManifestSignature": function(contractName, manifestHash, manifest2) { + if (!has(manifest2, "signature") || typeof manifest2.signature.keyId !== "string" || typeof manifest2.signature.value !== "string") { + throw new Error(`Invalid or missing signature field for manifest ${manifestHash} (named ${contractName})`); + } + const rootState = esm_default(this.config.stateSelector); + if (!has(rootState, "contractSigningKeys")) { + this.config.reactiveSet(rootState, "contractSigningKeys", /* @__PURE__ */ Object.create(null)); + } + const contractNameLookupKey = `name:${contractName}`; + let signatureValidated = false; + if (process.env.UNSAFE_TRUST_ALL_MANIFEST_SIGNING_KEYS !== "true" && has(rootState.contractSigningKeys, contractNameLookupKey)) { + console.info(`[chelonia] verifying signature for ${manifestHash} with an existing key`); + if (!has(rootState.contractSigningKeys[contractNameLookupKey], manifest2.signature.keyId)) { + console.error(`The manifest with ${manifestHash} (named ${contractName}) claims to be signed with a key with ID ${manifest2.signature.keyId}, which is not trusted. The trusted key IDs for this name are:`, Object.keys(rootState.contractSigningKeys[contractNameLookupKey])); + throw new Error(`Invalid or missing signature in manifest ${manifestHash} (named ${contractName}). It claims to be signed with a key with ID ${manifest2.signature.keyId}, which has not been authorized for this contract before.`); + } + const signingKey = rootState.contractSigningKeys[contractNameLookupKey][manifest2.signature.keyId]; + verifySignature(signingKey, manifest2.body + manifest2.head, manifest2.signature.value); + console.info(`[chelonia] successful signature verification for ${manifestHash} (named ${contractName}) using the already-trusted key ${manifest2.signature.keyId}.`); + signatureValidated = true; + } + const body = JSON.parse(manifest2.body); + if (!signatureValidated) { + console.info(`[chelonia] verifying signature for ${manifestHash} (named ${contractName}) for the first time`); + if (!has(body, "signingKeys") || !Array.isArray(body.signingKeys)) { + throw new Error(`Invalid manifest file ${manifestHash} (named ${contractName}). Its body doesn't contain a 'signingKeys' list'`); + } + let contractSigningKeys; + try { + contractSigningKeys = Object.fromEntries(body.signingKeys.map((serializedKey) => { + return [keyId(serializedKey), serializedKey]; + })); + } catch (e2) { + console.error(`[chelonia] Error parsing the public keys list for ${manifestHash} (named ${contractName})`, e2); + throw e2; } - $_rootReferences() { - return this._refs.roots(); + if (!has(contractSigningKeys, manifest2.signature.keyId)) { + throw new Error(`Invalid or missing signature in manifest ${manifestHash} (named ${contractName}). It claims to be signed with a key with ID ${manifest2.signature.keyId}, which is not listed in its 'signingKeys' field.`); } - $_setFlag(name, value, options2 = {}) { - assert2(name[0] === "_" || !this._inRuleset(), "Cannot set flag inside a ruleset"); - const flag = this._definition.flags[name] || {}; - if (deepEqual(value, flag.default)) { - value = void 0; - } - if (deepEqual(value, this._flags[name])) { - return this; - } - const obj = options2.clone !== false ? this.clone() : this; - if (value !== void 0) { - obj._flags[name] = value; - obj.$_mutateRegister(value); - } else { - delete obj._flags[name]; - } - if (name[0] !== "_") { - obj.$_temp.ruleset = false; - } - return obj; + verifySignature(contractSigningKeys[manifest2.signature.keyId], manifest2.body + manifest2.head, manifest2.signature.value); + console.info(`[chelonia] successful signature verification for ${manifestHash} (named ${contractName}) using ${manifest2.signature.keyId}. The following key IDs will now be trusted for this contract name`, Object.keys(contractSigningKeys)); + signatureValidated = true; + rootState.contractSigningKeys[contractNameLookupKey] = contractSigningKeys; + } + return body; + }, + "chelonia/private/loadManifest": async function(contractName, manifestHash) { + if (!contractName || typeof contractName !== "string") { + throw new Error("Invalid or missing contract name"); + } + if (this.manifestToContract[manifestHash]) { + console.warn("[chelonia]: already loaded manifest", manifestHash); + return; + } + const manifestSource = await esm_default("chelonia/out/fetchResource", manifestHash, { + code: multicodes.SHELTER_CONTRACT_MANIFEST + }); + const manifest2 = JSON.parse(manifestSource); + const body = esm_default("chelonia/private/verifyManifestSignature", contractName, manifestHash, manifest2); + if (body.name !== contractName) { + throw new Error(`Mismatched contract name. Expected ${contractName} but got ${body.name}`); + } + const contractInfo = this.config.contracts.defaults.preferSlim && body.contractSlim || body.contract; + console.info(`[chelonia] loading contract '${contractInfo.file}'@'${body.version}' from manifest: ${manifestHash}`); + const source = await esm_default("chelonia/out/fetchResource", contractInfo.hash, { + code: multicodes.SHELTER_CONTRACT_TEXT + }); + const reduceAllow = (acc, v2) => { + acc[v2] = true; + return acc; + }; + const allowedSels = [ + "okTurtles.events/on", + "chelonia/defineContract", + "chelonia/out/keyRequest" + ].concat(this.config.contracts.defaults.allowedSelectors).reduce(reduceAllow, {}); + const allowedDoms = this.config.contracts.defaults.allowedDomains.reduce(reduceAllow, {}); + const contractSBP = (selector, ...args) => { + const domain = domainFromSelector(selector); + if (selector.startsWith(contractName + "/")) { + selector = `${manifestHash}/${selector}`; + } + if (allowedSels[selector] || allowedDoms[domain]) { + return esm_default(selector, ...args); + } else { + console.error("[chelonia] selector not on allowlist", { + selector, + allowedSels, + allowedDoms + }); + throw new Error(`[chelonia] selector not on allowlist: '${selector}'`); } - $_parent(method, ...args) { - return this[method][Common.symbols.parent].call(this, ...args); - } - $_validate(value, state, prefs) { - return Validator.validate(value, this, state, prefs); - } - // Internals - _assign(target) { - target.type = this.type; - target.$_root = this.$_root; - target.$_temp = Object.assign({}, this.$_temp); - target.$_temp.whens = {}; - target._ids = this._ids.clone(); - target._preferences = this._preferences; - target._valids = this._valids && this._valids.clone(); - target._invalids = this._invalids && this._invalids.clone(); - target._rules = this._rules.slice(); - target._singleRules = clone2(this._singleRules, { shallow: true }); - target._refs = this._refs.clone(); - target._flags = Object.assign({}, this._flags); - target._cache = null; - target.$_terms = {}; - for (const key in this.$_terms) { - target.$_terms[key] = this.$_terms[key] ? this.$_terms[key].slice() : null; - } - target.$_super = {}; - for (const override in this.$_super) { - target.$_super[override] = this._super[override].bind(target); - } - return target; - } - _bare() { - const obj = this.clone(); - obj._reset(); - const terms = obj._definition.terms; - for (const name in terms) { - const term = terms[name]; - obj.$_terms[name] = term.init; - } - return obj.$_mutateRebuild(); - } - _default(flag, value, options2 = {}) { - Common.assertOptions(options2, "literal"); - assert2(value !== void 0, "Missing", flag, "value"); - assert2(typeof value === "function" || !options2.literal, "Only function value supports literal option"); - if (typeof value === "function" && options2.literal) { - value = { - [Common.symbols.literal]: true, - literal: value - }; + }; + const saferEval = new Function(` + return function (globals) { + // almost a real sandbox + // stops (() => this)().fetch + // needs additional step of locking down Function constructor to stop: + // new (()=>{}).constructor("console.log(typeof this.fetch)")() + globals.self = globals + globals.globalThis = globals + with (new Proxy(globals, { + get (o, p) { return o[p] }, + has (o, p) { /* console.log('has', p); */ return true } + })) { + (function () { + 'use strict' + ${source} + })() } - const obj = this.$_setFlag(flag, value); - return obj; } - _generate(value, state, prefs) { - if (!this.$_terms.whens) { - return { schema: this }; - } - const whens = []; - const ids = []; - for (let i2 = 0; i2 < this.$_terms.whens.length; ++i2) { - const when = this.$_terms.whens[i2]; - if (when.concat) { - whens.push(when.concat); - ids.push(`${i2}.concat`); - continue; - } - const input = when.ref ? when.ref.resolve(value, state, prefs) : value; - const tests = when.is ? [when] : when.switch; - const before = ids.length; - for (let j = 0; j < tests.length; ++j) { - const { is, then, otherwise } = tests[j]; - const baseId = `${i2}${when.switch ? "." + j : ""}`; - if (is.$_match(input, state.nest(is, `${baseId}.is`), prefs)) { - if (then) { - const localState = state.localize([...state.path, `${baseId}.then`], state.ancestors, state.schemas); - const { schema: generated, id: id2 } = then._generate(value, localState, prefs); - whens.push(generated); - ids.push(`${baseId}.then${id2 ? `(${id2})` : ""}`); - break; - } - } else if (otherwise) { - const localState = state.localize([...state.path, `${baseId}.otherwise`], state.ancestors, state.schemas); - const { schema: generated, id: id2 } = otherwise._generate(value, localState, prefs); - whens.push(generated); - ids.push(`${baseId}.otherwise${id2 ? `(${id2})` : ""}`); - break; - } - } - if (when.break && ids.length > before) { - break; + `)(); + this.defContractSBP = contractSBP; + this.defContractManifest = manifestHash; + saferEval({ + // pass in globals that we want access to by default in the sandbox + // note: you can undefine these by setting them to undefined in exposedGlobals + crypto: { + getRandomValues: (v2) => globalThis.crypto.getRandomValues(v2) + }, + ...typeof window === "object" && window && { + alert: window.alert.bind(window), + confirm: window.confirm.bind(window), + prompt: window.prompt.bind(window) + }, + isNaN, + console, + Object, + Error, + TypeError, + RangeError, + Math, + Symbol, + Date, + Array, + BigInt, + Boolean, + String, + Number, + Int8Array, + Int16Array, + Int32Array, + Uint8Array, + Uint16Array, + Uint32Array, + Float32Array, + Float64Array, + ArrayBuffer, + JSON, + RegExp, + parseFloat, + parseInt, + Promise, + Function, + Map, + WeakMap, + ...this.config.contracts.defaults.exposedGlobals, + require: (dep) => { + return dep === "@sbp/sbp" ? contractSBP : this.config.contracts.defaults.modules[dep]; + }, + sbp: contractSBP, + fetchServerTime: async (fallback = true) => { + try { + const response = await this.config.fetch(`${this.config.connectionURL}/time`, { + signal: this.abortController.signal + }); + return handleFetchResult("text")(response); + } catch (e2) { + console.warn("[fetchServerTime] Error", e2); + if (fallback) { + return new Date(esm_default("chelonia/time")).toISOString(); } + throw new ChelErrorFetchServerTimeFailed("Can not fetch server time. Please check your internet connection."); } - const id = ids.join(", "); - state.mainstay.tracer.debug(state, "rule", "when", id); - if (!id) { - return { schema: this }; - } - if (!state.mainstay.tracer.active && this.$_temp.whens[id]) { - return { schema: this.$_temp.whens[id], id }; - } - let obj = this; - if (this._definition.generate) { - obj = this._definition.generate(this, value, state, prefs); - } - for (const when of whens) { - obj = obj.concat(when); - } - if (this.$_root._tracer) { - this.$_root._tracer._combine(obj, [this, ...whens]); - } - this.$_temp.whens[id] = obj; - return { schema: obj, id }; } - _inner(type, values, options2 = {}) { - assert2(!this._inRuleset(), `Cannot set ${type} inside a ruleset`); - const obj = this.clone(); - if (!obj.$_terms[type] || options2.override) { - obj.$_terms[type] = []; - } - if (options2.single) { - obj.$_terms[type].push(values); - } else { - obj.$_terms[type].push(...values); + }); + if (contractName !== this.defContract.name) { + throw new Error(`Invalid contract name for manifest ${manifestHash}. Expected ${contractName} but got ${this.defContract.name}`); + } + this.defContractSelectors.forEach((s) => { + allowedSels[s] = true; + }); + this.manifestToContract[manifestHash] = { + slim: contractInfo === body.contractSlim, + info: contractInfo, + contract: this.defContract + }; + }, + // Warning: avoid using this unless you know what you're doing. Prefer using /remove. + "chelonia/private/removeImmediately": function(contractID, params) { + const state = esm_default(this.config.stateSelector); + const contractName = state.contracts[contractID]?.type; + if (!contractName) { + console.error("[chelonia/private/removeImmediately] Missing contract name for contract", { + contractID + }); + return; + } + const manifestHash = this.config.contracts.manifests[contractName]; + if (manifestHash) { + const destructor = `${manifestHash}/${contractName}/_cleanup`; + if (esm_default("sbp/selectors/fn", destructor)) { + try { + esm_default(destructor, { contractID, resync: !!params?.resync, state: state[contractID] }); + } catch (e2) { + console.error(`[chelonia/private/removeImmediately] Error at destructor for ${contractID}`, e2); } - obj.$_temp.ruleset = false; - return obj; } - _inRuleset() { - return this.$_temp.ruleset !== null && this.$_temp.ruleset !== false; + } + if (params?.resync) { + Object.keys(state.contracts[contractID]).filter((k) => k !== "references").forEach((k) => this.config.reactiveDel(state.contracts[contractID], k)); + Object.keys(state[contractID]).filter((k) => k !== "_volatile").forEach((k) => this.config.reactiveDel(state[contractID], k)); + if (state[contractID]._volatile) { + Object.keys(state[contractID]._volatile).filter((k) => k !== "watch").forEach((k) => this.config.reactiveDel(state[contractID]._volatile, k)); } - _ruleRemove(name, options2 = {}) { - if (!this._singleRules.has(name)) { - return this; - } - const obj = options2.clone !== false ? this.clone() : this; - obj._singleRules.delete(name); - const filtered = []; - for (let i2 = 0; i2 < obj._rules.length; ++i2) { - const test = obj._rules[i2]; - if (test.name === name && !test.keep) { - if (obj._inRuleset() && i2 < obj.$_temp.ruleset) { - --obj.$_temp.ruleset; - } - continue; - } - filtered.push(test); - } - obj._rules = filtered; - return obj; + } else { + delete this.ephemeralReferenceCount[contractID]; + if (params?.permanent) { + this.config.reactiveSet(state.contracts, contractID, null); + } else { + this.config.reactiveDel(state.contracts, contractID); } - _values(values, key) { - Common.verifyFlat(values, key.slice(1, -1)); - const obj = this.clone(); - const override = values[0] === Common.symbols.override; - if (override) { - values = values.slice(1); - } - if (!obj[key] && values.length) { - obj[key] = new Values(); - } else if (override) { - obj[key] = values.length ? new Values() : null; - obj.$_mutateRebuild(); - } - if (!obj[key]) { - return obj; - } - if (override) { - obj[key].override(); - } - for (const value of values) { - assert2(value !== void 0, "Cannot call allow/valid/invalid with undefined"); - assert2(value !== Common.symbols.override, "Override must be the first value"); - const other = key === "_invalids" ? "_valids" : "_invalids"; - if (obj[other]) { - obj[other].remove(value); - if (!obj[other].length) { - assert2(key === "_valids" || !obj._flags.only, "Setting invalid value", value, "leaves schema rejecting all values due to previous valid rule"); - obj[other] = null; - } - } - obj[key].add(value, obj._refs); + this.config.reactiveDel(state, contractID); + } + this.subscriptionSet.delete(contractID); + esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { + added: [], + removed: [contractID], + permanent: params?.permanent, + resync: params?.resync + }); + }, + // used by, e.g. 'chelonia/contract/wait' + "chelonia/private/noop": function() { + }, + "chelonia/private/out/sync": function(contractIDs, params) { + const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; + const forcedSync = !!params?.force; + return Promise.all(listOfIds.map((contractID) => { + if (!forcedSync && this.subscriptionSet.has(contractID)) { + const rootState = esm_default(this.config.stateSelector); + if (!rootState[contractID]?._volatile?.dirty) { + return esm_default("chelonia/private/queueEvent", contractID, ["chelonia/private/noop"]); } - return obj; - } - // Standard Schema - get "~standard"() { - const mapToStandardError = (error2) => { - let issues; - if (Errors.ValidationError.isError(error2)) { - issues = error2.details.map(({ message, path: path8 }) => ({ - message, - path: path8 - })); - } else { - issues = [{ - message: error2.message - }]; - } - return { - issues - }; - }; - const mapToStandardValue = (value) => ({ value }); - return { - version: 1, - vendor: "joi", - validate: (value) => { - const result = Validator.standard(value, this); - if (result instanceof Promise) { - return result.then(mapToStandardValue, mapToStandardError); - } - if (!result.error) { - return mapToStandardValue(result.value); - } - return mapToStandardError(result.error); - } - }; } - }; - internals.Base.prototype[Common.symbols.any] = { - version: Common.version, - compile: Compile.compile, - root: "$_root" - }; - internals.Base.prototype.isImmutable = true; - internals.Base.prototype.deny = internals.Base.prototype.invalid; - internals.Base.prototype.disallow = internals.Base.prototype.invalid; - internals.Base.prototype.equal = internals.Base.prototype.valid; - internals.Base.prototype.exist = internals.Base.prototype.required; - internals.Base.prototype.not = internals.Base.prototype.invalid; - internals.Base.prototype.options = internals.Base.prototype.prefs; - internals.Base.prototype.preferences = internals.Base.prototype.prefs; - module14.exports = new internals.Base(); - } -}); -var require_any2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/any.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Base = require_base2(); - var Common = require_common3(); - var Messages = require_messages2(); - module14.exports = Base.extend({ - type: "any", - flags: { - only: { default: false } - }, - terms: { - alterations: { init: null }, - examples: { init: null }, - externals: { init: null }, - metas: { init: [] }, - notes: { init: [] }, - shared: { init: null }, - tags: { init: [] }, - whens: { init: null } - }, - rules: { - custom: { - method(method, description) { - assert2(typeof method === "function", "Method must be a function"); - assert2(description === void 0 || description && typeof description === "string", "Description must be a non-empty string"); - return this.$_addRule({ name: "custom", args: { method, description } }); - }, - validate(value, helpers, { method }) { - try { - return method(value, helpers); - } catch (err) { - return helpers.error("any.custom", { error: err }); - } - }, - args: ["method", "description"], - multi: true - }, - messages: { - method(messages) { - return this.prefs({ messages }); - } - }, - shared: { - method(schema) { - assert2(Common.isSchema(schema) && schema._flags.id, "Schema must be a schema with an id"); - const obj = this.clone(); - obj.$_terms.shared = obj.$_terms.shared || []; - obj.$_terms.shared.push(schema); - obj.$_mutateRegister(schema); - return obj; - } - }, - warning: { - method(code2, local) { - assert2(code2 && typeof code2 === "string", "Invalid warning code"); - return this.$_addRule({ name: "warning", args: { code: code2, local }, warn: true }); - }, - validate(value, helpers, { code: code2, local }) { - return helpers.error(code2, local); - }, - args: ["code", "local"], - multi: true - } - }, - modifiers: { - keep(rule, enabled2 = true) { - rule.keep = enabled2; - }, - message(rule, message) { - rule.message = Messages.compile(message); - }, - warn(rule, enabled2 = true) { - rule.warn = enabled2; - } - }, - manifest: { - build(obj, desc) { - for (const key in desc) { - const values = desc[key]; - if (["examples", "externals", "metas", "notes", "tags"].includes(key)) { - for (const value of values) { - obj = obj[key.slice(0, -1)](value); - } - continue; - } - if (key === "alterations") { - const alter = {}; - for (const { target, adjuster } of values) { - alter[target] = adjuster; - } - obj = obj.alter(alter); - continue; - } - if (key === "whens") { - for (const value of values) { - const { ref, is, not, then, otherwise, concat: concat2 } = value; - if (concat2) { - obj = obj.concat(concat2); - } else if (ref) { - obj = obj.when(ref, { is, not, then, otherwise, switch: value.switch, break: value.break }); - } else { - obj = obj.when(is, { then, otherwise, break: value.break }); - } - } - continue; - } - if (key === "shared") { - for (const value of values) { - obj = obj.shared(value); - } - } - } - return obj; + return esm_default("chelonia/private/queueEvent", contractID, [ + "chelonia/private/in/syncContract", + contractID, + params + ]).catch((err) => { + console.error(`[chelonia] failed to sync ${contractID}:`, err); + throw err; + }); + })); + }, + "chelonia/private/out/publishEvent": function(entry, { maxAttempts = 5, headers, billableContractID, bearer, disableAutoDedup } = {}, hooks) { + const contractID = entry.contractID(); + const originalEntry = entry; + return esm_default("chelonia/private/queueEvent", `publish:${contractID}`, async () => { + let attempt = 1; + let lastAttemptedHeight; + await hooks?.prepublish?.(entry); + const onreceivedHandler = (_contractID, message) => { + if (entry.hash() === message.hash()) { + esm_default("okTurtles.events/off", EVENT_HANDLED, onreceivedHandler); + hooks.onprocessed(entry); } - }, - messages: { - "any.custom": "{{#label}} failed custom validation because {{#error.message}}", - "any.default": "{{#label}} threw an error when running default method", - "any.failover": "{{#label}} threw an error when running failover method", - "any.invalid": "{{#label}} contains an invalid value", - "any.only": '{{#label}} must be {if(#valids.length == 1, "", "one of ")}{{#valids}}', - "any.ref": "{{#label}} {{#arg}} references {{:#ref}} which {{#reason}}", - "any.required": "{{#label}} is required", - "any.unknown": "{{#label}} is not allowed" + }; + if (typeof hooks?.onprocessed === "function") { + esm_default("okTurtles.events/on", EVENT_HANDLED, onreceivedHandler); } - }); - } -}); -var require_alternatives2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/alternatives.js"(exports2, module14) { - "use strict"; - var { assert: assert2, merge: merge3 } = require_lib(); - var Any = require_any2(); - var Common = require_common3(); - var Compile = require_compile2(); - var Errors = require_errors3(); - var Ref = require_ref2(); - var internals = {}; - module14.exports = Any.extend({ - type: "alternatives", - flags: { - match: { default: "any" } - // 'any', 'one', 'all' - }, - terms: { - matches: { init: [], register: Ref.toSibling } - }, - args(schema, ...schemas) { - if (schemas.length === 1) { - if (Array.isArray(schemas[0])) { - return schema.try(...schemas[0]); - } - } - return schema.try(...schemas); - }, - validate(value, helpers) { - const { schema, error: error2, state, prefs } = helpers; - if (schema._flags.match) { - const matched = []; - const failed = []; - for (let i2 = 0; i2 < schema.$_terms.matches.length; ++i2) { - const item = schema.$_terms.matches[i2]; - const localState = state.nest(item.schema, `match.${i2}`); - localState.snapshot(); - const result = item.schema.$_validate(value, localState, prefs); - if (!result.errors) { - matched.push(result.value); - localState.commit(); - } else { - failed.push(result.errors); - localState.restore(); - } - } - if (matched.length === 0) { - const context = { - details: failed.map((f) => Errors.details(f, { override: false })) - }; - return { errors: error2("alternatives.any", context) }; - } - if (schema._flags.match === "one") { - return matched.length === 1 ? { value: matched[0] } : { errors: error2("alternatives.one") }; - } - if (matched.length !== schema.$_terms.matches.length) { - const context = { - details: failed.map((f) => Errors.details(f, { override: false })) - }; - return { errors: error2("alternatives.all", context) }; + while (true) { + lastAttemptedHeight = entry.height(); + const newEntry = await esm_default("chelonia/private/queueEvent", contractID, async () => { + const rootState = esm_default(this.config.stateSelector); + const state = rootState[contractID]; + const isFirstMessage = entry.isFirstMessage(); + if (!state && !isFirstMessage) { + console.info(`[chelonia] Not sending message as contract state has been removed: ${entry.description()}`); + return; } - const isAnyObj = (alternative) => { - return alternative.$_terms.matches.some((v2) => { - return v2.schema.type === "object" || v2.schema.type === "alternatives" && isAnyObj(v2.schema); - }); - }; - return isAnyObj(schema) ? { value: matched.reduce((acc, v2) => merge3(acc, v2, { mergeArrays: false })) } : { value: matched[matched.length - 1] }; - } - const errors = []; - for (let i2 = 0; i2 < schema.$_terms.matches.length; ++i2) { - const item = schema.$_terms.matches[i2]; - if (item.schema) { - const localState = state.nest(item.schema, `match.${i2}`); - localState.snapshot(); - const result = item.schema.$_validate(value, localState, prefs); - if (!result.errors) { - localState.commit(); - return result; + if (hooks?.preSendCheck) { + if (!await hooks.preSendCheck(entry, state)) { + console.info(`[chelonia] Not sending message as preSendCheck hook returned non-truish value: ${entry.description()}`); + return; } - localState.restore(); - errors.push({ schema: item.schema, reports: result.errors }); - continue; } - const input = item.ref ? item.ref.resolve(value, state, prefs) : value; - const tests = item.is ? [item] : item.switch; - for (let j = 0; j < tests.length; ++j) { - const test = tests[j]; - const { is, then, otherwise } = test; - const id = `match.${i2}${item.switch ? "." + j : ""}`; - if (!is.$_match(input, state.nest(is, `${id}.is`), prefs)) { - if (otherwise) { - return otherwise.$_validate(value, state.nest(otherwise, `${id}.otherwise`), prefs); - } - } else if (then) { - return then.$_validate(value, state.nest(then, `${id}.then`), prefs); - } + await esm_default("chelonia/private/in/processMessage", entry, cloneDeep(state || {})); + if (!isFirstMessage) { + return recreateEvent(entry, state, rootState.contracts[contractID], disableAutoDedup); } + return entry; + }); + if (!newEntry) + return; + await hooks?.beforeRequest?.(newEntry, entry); + entry = newEntry; + const r = await this.config.fetch(`${this.config.connectionURL}/event`, { + method: "POST", + body: entry.serialize(), + headers: { + ...headers, + ...bearer && { + Authorization: `Bearer ${bearer}` + }, + ...billableContractID && { + Authorization: buildShelterAuthorizationHeader.call(this, billableContractID) + }, + "Content-Type": "text/plain" + }, + signal: this.abortController.signal + }); + if (r.ok) { + await hooks?.postpublish?.(entry); + return entry; } - return internals.errors(errors, helpers); - }, - rules: { - conditional: { - method(condition, options2) { - assert2(!this._flags._endedSwitch, "Unreachable condition"); - assert2(!this._flags.match, "Cannot combine match mode", this._flags.match, "with conditional rule"); - assert2(options2.break === void 0, "Cannot use break option with alternatives conditional"); - const obj = this.clone(); - const match = Compile.when(obj, condition, options2); - const conditions = match.is ? [match] : match.switch; - for (const item of conditions) { - if (item.then && item.otherwise) { - obj.$_setFlag("_endedSwitch", true, { clone: false }); - break; - } - } - obj.$_terms.matches.push(match); - return obj.$_mutateRebuild(); - } - }, - match: { - method(mode) { - assert2(["any", "one", "all"].includes(mode), "Invalid alternatives match mode", mode); - if (mode !== "any") { - for (const match of this.$_terms.matches) { - assert2(match.schema, "Cannot combine match mode", mode, "with conditional rules"); - } - } - return this.$_setFlag("match", mode); - } - }, - try: { - method(...schemas) { - assert2(schemas.length, "Missing alternative schemas"); - Common.verifyFlat(schemas, "try"); - assert2(!this._flags._endedSwitch, "Unreachable condition"); - const obj = this.clone(); - for (const schema of schemas) { - obj.$_terms.matches.push({ schema: obj.$_compile(schema) }); + try { + if (r.status === 409) { + if (attempt + 1 > maxAttempts) { + console.error(`[chelonia] failed to publish ${entry.description()} after ${attempt} attempts`, entry); + throw new Error(`publishEvent: ${r.status} - ${r.statusText}. attempt ${attempt}`); + } + const randDelay = randomIntFromRange(0, 1500); + console.warn(`[chelonia] publish attempt ${attempt} of ${maxAttempts} failed. Waiting ${randDelay} msec before resending ${entry.description()}`); + attempt += 1; + await delay(randDelay); + if (!entry.isFirstMessage() && entry.height() === lastAttemptedHeight) { + await esm_default("chelonia/private/out/sync", contractID, { force: true }); } - return obj.$_mutateRebuild(); + } else { + const message = (await r.json())?.message; + console.error(`[chelonia] ERROR: failed to publish ${entry.description()}: ${r.status} - ${r.statusText}: ${message}`, entry); + throw new Error(`publishEvent: ${r.status} - ${r.statusText}: ${message}`); } + } catch (e2) { + esm_default("okTurtles.events/off", EVENT_HANDLED, onreceivedHandler); + throw e2; } - }, - overrides: { - label(name) { - const obj = this.$_parent("label", name); - const each = (item, source) => { - return source.path[0] !== "is" && typeof item._flags.label !== "string" ? item.label(name) : void 0; - }; - return obj.$_modify({ each, ref: false }); - }, - isAsync() { - if (this.$_terms.externals?.length) { - return true; + } + }).then((entry2) => { + esm_default("okTurtles.events/emit", EVENT_PUBLISHED, { + contractID, + message: entry2, + originalMessage: originalEntry + }); + return entry2; + }).catch((e2) => { + esm_default("okTurtles.events/emit", EVENT_PUBLISHING_ERROR, { + contractID, + message: entry, + originalMessage: originalEntry, + error: e2 + }); + throw e2; + }); + }, + "chelonia/private/out/latestHEADinfo": function(contractID) { + return this.config.fetch(`${this.config.connectionURL}/latestHEADinfo/${contractID}`, { + cache: "no-store", + signal: this.abortController.signal + }).then(handleFetchResult("json")); + }, + "chelonia/private/postKeyShare": function(contractID, previousVolatileState, signingKey) { + const cheloniaState = esm_default(this.config.stateSelector); + const targetState = cheloniaState[contractID]; + if (!targetState) + return; + if (previousVolatileState && has(previousVolatileState, "watch")) { + if (!targetState._volatile) { + this.config.reactiveSet(targetState, "_volatile", /* @__PURE__ */ Object.create(null)); + } + if (!targetState._volatile.watch) { + this.config.reactiveSet(targetState._volatile, "watch", previousVolatileState.watch); + } else if (targetState._volatile.watch !== previousVolatileState.watch) { + previousVolatileState.watch.forEach((pWatch) => { + if (!targetState._volatile.watch.some((tWatch) => { + return tWatch[0] === pWatch[0] && tWatch[1] === pWatch[1]; + })) { + targetState._volatile.watch.push(pWatch); } - for (const match of this.$_terms.matches) { - if (match.schema?.isAsync()) { - return true; - } - if (match.then?.isAsync()) { - return true; - } - if (match.otherwise?.isAsync()) { - return true; + }); + } + } + if (!Array.isArray(targetState._volatile?.pendingKeyRequests)) + return; + this.config.reactiveSet(targetState._volatile, "pendingKeyRequests", targetState._volatile.pendingKeyRequests.filter((pkr) => pkr?.name !== signingKey.name)); + }, + "chelonia/private/in/processMessage": async function(message, state, internalSideEffectStack, contractName) { + const [opT, opV] = message.op(); + const hash3 = message.hash(); + const height = message.height(); + const contractID = message.contractID(); + const manifestHash = message.manifest(); + const signingKeyId = message.signingKeyId(); + const direction = message.direction(); + const config2 = this.config; + const self2 = this; + const opName = Object.entries(SPMessage).find(([, y]) => y === opT)?.[0]; + console.debug("PROCESSING OPCODE:", opName, "to", contractID); + if (state?._volatile?.dirty) { + console.debug("IGNORING OPCODE BECAUSE CONTRACT STATE IS MARKED AS DIRTY.", "OPCODE:", opName, "CONTRACT:", contractID); + return; + } + if (!state._vm) + state._vm = /* @__PURE__ */ Object.create(null); + const opFns = { + /* + There are two types of "errors" that we need to consider: + 1. "Ignoring" errors + 2. "Failure" errors + Example: OP_KEY_ADD + 1. IGNORING: an error is thrown because we wanted to add a key but the + key we wanted to add is already there. This is not a hard error, it's an + ignoring error. We don't care that the operation failed in this case because the intent was accomplished. + 2. FAILURE: an error is thrown while attempting to add a key that doesn't exist. + Example: OP_ACTION_ENCRYPTED + 1. IGNORING: An error is thrown because we don't have the key to decrypt the action. We ignore it. + 2. FAILURE: An error is thrown by the process function during processing. + Handling these in OP_ATOMIC + • ALL errors of class "IGNORING" should be ignored. They should not + impact our ability to process the rest of the operations in the OP_ATOMIC. + No matter how many of these are thrown, it doesn't affect the rest of the operations. + • ANY error of class "FAILURE" will call the rest of the operations to + fail and the state to be reverted to prior to the OP_ATOMIC. No side-effects should be run. Because an intention failed. + */ + async [SPMessage.OP_ATOMIC](v2) { + for (let i2 = 0; i2 < v2.length; i2++) { + const u2 = v2[i2]; + try { + if (u2[0] === SPMessage.OP_ATOMIC) + throw new Error("Cannot nest OP_ATOMIC"); + if (!validateKeyPermissions(message, config2, state, signingKeyId, u2[0], u2[1])) { + throw new Error("Inside OP_ATOMIC: no matching signing key was defined"); } - } - return false; - } - }, - rebuild(schema) { - const each = (item) => { - if (Common.isSchema(item) && item.type === "array") { - schema.$_setFlag("_arrayItems", true, { clone: false }); - } - }; - schema.$_modify({ each }); - }, - manifest: { - build(obj, desc) { - if (desc.matches) { - for (const match of desc.matches) { - const { schema, ref, is, not, then, otherwise } = match; - if (schema) { - obj = obj.try(schema); - } else if (ref) { - obj = obj.conditional(ref, { is, then, not, otherwise, switch: match.switch }); + await opFns[u2[0]](u2[1]); + } catch (e_) { + const e2 = e_; + if (e2 && typeof e2 === "object") { + if (e2.name === "ChelErrorDecryptionKeyNotFound") { + console.warn(`[chelonia] [OP_ATOMIC] WARN '${e2.name}' in processMessage for ${message.description()}: ${e2.message}`, e2, message.serialize()); + if (e2.cause) { + const missingDecryptionKeyIds = missingDecryptionKeyIdsMap.get(message); + if (missingDecryptionKeyIds) { + missingDecryptionKeyIds.add(e2.cause); + } else { + missingDecryptionKeyIdsMap.set(message, /* @__PURE__ */ new Set([e2.cause])); + } + } + continue; } else { - obj = obj.conditional(is, { then, otherwise }); + logEvtError(message, `[chelonia] [OP_ATOMIC] ERROR '${e2.name}' in processMessage for ${message.description()}: ${e2.message || e2}`, e2, message.serialize()); } + console.warn(`[chelonia] [OP_ATOMIC] Error processing ${message.description()}: ${message.serialize()}. Any side effects will be skipped!`); + if (config2.strictProcessing) { + throw e2; + } + config2.hooks.processError?.(e2, message, getMsgMeta.call(self2, message, contractID, state)); + if (e2.name === "ChelErrorWarning") + continue; + } else { + logEvtError(message, "Inside OP_ATOMIC: Non-object or null error thrown", contractID, message, i2, e2); } + throw e2; } - return obj; } }, - messages: { - "alternatives.all": "{{#label}} does not match all of the required types", - "alternatives.any": "{{#label}} does not match any of the allowed types", - "alternatives.match": "{{#label}} does not match any of the allowed types", - "alternatives.one": "{{#label}} matches more than one allowed type", - "alternatives.types": "{{#label}} must be one of {{#types}}" - } - }); - internals.errors = function(failures, { error: error2, state }) { - if (!failures.length) { - return { errors: error2("alternatives.any") }; - } - if (failures.length === 1) { - return { errors: failures[0].reports }; - } - const valids = /* @__PURE__ */ new Set(); - const complex = []; - for (const { reports, schema } of failures) { - if (reports.length > 1) { - return internals.unmatched(failures, error2); - } - const report = reports[0]; - if (report instanceof Errors.Report === false) { - return internals.unmatched(failures, error2); - } - if (report.state.path.length !== state.path.length) { - complex.push({ type: schema.type, report }); - continue; - } - if (report.code === "any.only") { - for (const valid of report.local.valids) { - valids.add(valid); + [SPMessage.OP_CONTRACT](v2) { + state._vm.type = v2.type; + const keys = keysToMap.call(self2, v2.keys, height); + state._vm.authorizedKeys = keys; + keyAdditionProcessor.call(self2, message, hash3, v2.keys, state, contractID, signingKey, internalSideEffectStack); + }, + [SPMessage.OP_ACTION_ENCRYPTED](v2) { + if (config2.skipActionProcessing) { + if (!config2.skipDecryptionAttempts) { + console.log("OP_ACTION_ENCRYPTED: skipped action processing"); } - continue; - } - const [type, code2] = report.code.split("."); - if (code2 !== "base") { - complex.push({ type: schema.type, report }); - } else if (report.code === "object.base") { - valids.add(report.local.type); - } else { - valids.add(type); + return; } - } - if (!complex.length) { - return { errors: error2("alternatives.types", { types: [...valids] }) }; - } - if (complex.length === 1) { - return { errors: complex[0].report }; - } - return internals.unmatched(failures, error2); - }; - internals.unmatched = function(failures, error2) { - const errors = []; - for (const failure of failures) { - errors.push(...failure.reports); - } - return { errors: error2("alternatives.match", Errors.details(errors, { override: false })) }; - }; - } -}); -var require_array2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/array.js"(exports2, module14) { - "use strict"; - var { assert: assert2, deepEqual, reach } = require_lib(); - var Any = require_any2(); - var Common = require_common3(); - var Compile = require_compile2(); - var internals = {}; - module14.exports = Any.extend({ - type: "array", - flags: { - single: { default: false }, - sparse: { default: false } - }, - terms: { - items: { init: [], manifest: "schema" }, - ordered: { init: [], manifest: "schema" }, - _exclusions: { init: [] }, - _inclusions: { init: [] }, - _requireds: { init: [] } + return opFns[SPMessage.OP_ACTION_UNENCRYPTED](v2.valueOf()); }, - coerce: { - from: "object", - method(value, { schema, state, prefs }) { - if (!Array.isArray(value)) { - return; + async [SPMessage.OP_ACTION_UNENCRYPTED](v2) { + if (!config2.skipActionProcessing) { + let innerSigningKeyId; + if (isSignedData(v2)) { + innerSigningKeyId = v2.signingKeyId; + v2 = v2.valueOf(); } - const sort = schema.$_getRule("sort"); - if (!sort) { - return; + const { data, meta, action } = v2; + if (!config2.whitelisted(action)) { + throw new Error(`chelonia: action not whitelisted: '${action}'`); } - return internals.sort(schema, value, sort.args.options, state, prefs); + await esm_default(`${manifestHash}/${action}/process`, { + data, + meta, + hash: hash3, + height, + contractID, + direction: message.direction(), + signingKeyId, + get signingContractID() { + return getContractIDfromKeyId(contractID, signingKeyId, state); + }, + innerSigningKeyId, + get innerSigningContractID() { + return getContractIDfromKeyId(contractID, innerSigningKeyId, state); + } + }, state); } }, - validate(value, { schema, error: error2 }) { - if (!Array.isArray(value)) { - if (schema._flags.single) { - const single = [value]; - single[Common.symbols.arraySingle] = true; - return { value: single }; + [SPMessage.OP_KEY_SHARE](wv) { + const data = config2.unwrapMaybeEncryptedData(wv); + if (!data) + return; + const v2 = data.data; + for (const key of v2.keys) { + if (key.id && key.meta?.private?.content) { + if (!has(state._vm, "sharedKeyIds")) + state._vm.sharedKeyIds = []; + if (!state._vm.sharedKeyIds.some((sK) => sK.id === key.id)) { + state._vm.sharedKeyIds.push({ + id: key.id, + contractID: v2.contractID, + height, + keyRequestHash: v2.keyRequestHash, + keyRequestHeight: v2.keyRequestHeight + }); + } } - return { errors: error2("array.base") }; } - if (!schema.$_getRule("items") && !schema.$_terms.externals) { - return; + if (has(v2, "keyRequestHash") && state._vm.authorizedKeys[signingKeyId].meta?.keyRequest) { + state._vm.authorizedKeys[signingKeyId].meta.keyRequest.responded = hash3; } - return { value: value.slice() }; - }, - rules: { - has: { - method(schema) { - schema = this.$_compile(schema, { appendPath: true }); - const obj = this.$_addRule({ name: "has", args: { schema } }); - obj.$_mutateRegister(schema); - return obj; - }, - validate(value, { state, prefs, error: error2 }, { schema: has2 }) { - const ancestors = [value, ...state.ancestors]; - for (let i2 = 0; i2 < value.length; ++i2) { - const localState = state.localize([...state.path, i2], ancestors, has2); - if (has2.$_match(value[i2], localState, prefs)) { - return value; - } - } - const patternLabel = has2._flags.label; - if (patternLabel) { - return error2("array.hasKnown", { patternLabel }); - } - return error2("array.hasUnknown", null); - }, - multi: true - }, - items: { - method(...schemas) { - Common.verifyFlat(schemas, "items"); - const obj = this.$_addRule("items"); - for (let i2 = 0; i2 < schemas.length; ++i2) { - const type = Common.tryWithPath(() => this.$_compile(schemas[i2]), i2, { append: true }); - obj.$_terms.items.push(type); - } - return obj.$_mutateRebuild(); - }, - validate(value, { schema, error: error2, state, prefs, errorsArray }) { - const requireds = schema.$_terms._requireds.slice(); - const ordereds = schema.$_terms.ordered.slice(); - const inclusions = [...schema.$_terms._inclusions, ...requireds]; - const wasArray = !value[Common.symbols.arraySingle]; - delete value[Common.symbols.arraySingle]; - const errors = errorsArray(); - let il = value.length; - for (let i2 = 0; i2 < il; ++i2) { - const item = value[i2]; - let errored = false; - let isValid = false; - const key = wasArray ? i2 : new Number(i2); - const path8 = [...state.path, key]; - if (!schema._flags.sparse && item === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - ordereds.shift(); - continue; - } - const ancestors = [value, ...state.ancestors]; - for (const exclusion of schema.$_terms._exclusions) { - if (!exclusion.$_match(item, state.localize(path8, ancestors, exclusion), prefs, { presence: "ignore" })) { - continue; - } - errors.push(error2("array.excludes", { pos: i2, value: item }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - errored = true; - ordereds.shift(); - break; - } - if (errored) { - continue; - } - if (schema.$_terms.ordered.length) { - if (ordereds.length) { - const ordered = ordereds.shift(); - const res = ordered.$_validate(item, state.localize(path8, ancestors, ordered), prefs); - if (!res.errors) { - if (ordered._flags.result === "strip") { - internals.fastSplice(value, i2); - --i2; - --il; - } else if (!schema._flags.sparse && res.value === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } - continue; - } else { - value[i2] = res.value; - } - } else { - errors.push(...res.errors); - if (prefs.abortEarly) { - return errors; + internalSideEffectStack?.push(async () => { + delete self2.postSyncOperations[contractID]?.["pending-keys-for-" + v2.contractID]; + const cheloniaState = esm_default(self2.config.stateSelector); + const targetState = cheloniaState[v2.contractID]; + const missingDecryptionKeyIds = cheloniaState.contracts[v2.contractID]?.missingDecryptionKeyIds; + let newestEncryptionKeyHeight = Number.POSITIVE_INFINITY; + for (const key of v2.keys) { + if (key.id && key.meta?.private?.content) { + const transient = direction === "outgoing" || key.meta.private.transient; + if (!esm_default("chelonia/haveSecretKey", key.id, !transient)) { + try { + const decrypted = key.meta.private.content.valueOf(); + esm_default("chelonia/storeSecretKeys", new Secret([ + { + key: deserializeKey(decrypted), + transient } + ])); + if (missingDecryptionKeyIds?.includes(key.id)) { + newestEncryptionKeyHeight = Number.NEGATIVE_INFINITY; + } else if ( + // Otherwise, we make an educated guess on whether a re-sync + // is needed based on the height. + targetState?._vm?.authorizedKeys?.[key.id]?._notBeforeHeight != null && Array.isArray(targetState._vm.authorizedKeys[key.id].purpose) && targetState._vm.authorizedKeys[key.id].purpose.includes("enc") + ) { + newestEncryptionKeyHeight = Math.min(newestEncryptionKeyHeight, targetState._vm.authorizedKeys[key.id]._notBeforeHeight); } - continue; - } else if (!schema.$_terms.items.length) { - errors.push(error2("array.orderedLength", { pos: i2, limit: schema.$_terms.ordered.length })); - if (prefs.abortEarly) { - return errors; - } - break; - } - } - const requiredChecks = []; - let jl = requireds.length; - for (let j = 0; j < jl; ++j) { - const localState = state.localize(path8, ancestors, requireds[j]); - localState.snapshot(); - const res = requireds[j].$_validate(item, localState, prefs); - requiredChecks[j] = res; - if (!res.errors) { - localState.commit(); - value[i2] = res.value; - isValid = true; - internals.fastSplice(requireds, j); - --j; - --jl; - if (!schema._flags.sparse && res.value === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; - } + } catch (e_) { + const e2 = e_; + if (e2?.name === "ChelErrorDecryptionKeyNotFound") { + console.warn(`OP_KEY_SHARE (${hash3} of ${contractID}) missing secret key: ${e2.message}`, e2); + } else { + console.error(`OP_KEY_SHARE (${hash3} of ${contractID}) error '${e2.message || e2}':`, e2); } - break; } - localState.restore(); } - if (isValid) { - continue; + } + } + const mustResync = !!(newestEncryptionKeyHeight < cheloniaState.contracts[v2.contractID]?.height); + if (mustResync) { + if (!has(targetState, "_volatile")) { + config2.reactiveSet(targetState, "_volatile", /* @__PURE__ */ Object.create(null)); + } + config2.reactiveSet(targetState._volatile, "dirty", true); + if (!Object.keys(targetState).some((k) => k !== "_volatile")) { + return; + } + const keyDict = /* @__PURE__ */ Object.create(null); + targetState._volatile?.watch?.forEach(([keyName, contractID2]) => { + if (!keyDict[keyName]) { + keyDict[keyName] = [contractID2]; + return; } - const stripUnknown = prefs.stripUnknown && !!prefs.stripUnknown.arrays || false; - jl = inclusions.length; - for (const inclusion of inclusions) { - let res; - const previousCheck = requireds.indexOf(inclusion); - if (previousCheck !== -1) { - res = requiredChecks[previousCheck]; - } else { - const localState = state.localize(path8, ancestors, inclusion); - localState.snapshot(); - res = inclusion.$_validate(item, localState, prefs); - if (!res.errors) { - localState.commit(); - if (inclusion._flags.result === "strip") { - internals.fastSplice(value, i2); - --i2; - --il; - } else if (!schema._flags.sparse && res.value === void 0) { - errors.push(error2("array.sparse", { key, path: path8, pos: i2, value: void 0 }, state.localize(path8))); - errored = true; - } else { - value[i2] = res.value; - } - isValid = true; - break; - } - localState.restore(); - } - if (jl === 1) { - if (stripUnknown) { - internals.fastSplice(value, i2); - --i2; - --il; - isValid = true; - break; - } - errors.push(...res.errors); - if (prefs.abortEarly) { - return errors; - } - errored = true; - break; - } + keyDict[keyName].push(contractID2); + }); + const contractIdsToUpdate = Array.from(new Set(Object.entries(keyDict).flatMap(([keyName, contractIDs]) => { + const keyId2 = findKeyIdByName(targetState, keyName); + if ( + // Does the key exist? (i.e., is it a current key) + keyId2 && // Is it an encryption key? (signing keys don't build up a + // potentially invalid state because the private key isn't + // required for validation; however, missing encryption keys + // prevent message processing) + targetState._vm.authorizedKeys[keyId2].purpose.includes("enc") && // Is this a newly set key? (avoid re-syncing contracts that + // haven't been affected by the `OP_KEY_SHARE`) + targetState._vm.authorizedKeys[keyId2]._notBeforeHeight >= newestEncryptionKeyHeight + ) { + return contractIDs; } - if (errored) { - continue; + return []; + }))); + contractIdsToUpdate.forEach((contractID2) => { + const targetState2 = cheloniaState[contractID2]; + if (!targetState2) + return; + if (!has(targetState2, "_volatile")) { + config2.reactiveSet(targetState2, "_volatile", /* @__PURE__ */ Object.create(null)); } - if ((schema.$_terms._inclusions.length || schema.$_terms._requireds.length) && !isValid) { - if (stripUnknown) { - internals.fastSplice(value, i2); - --i2; - --il; - continue; - } - errors.push(error2("array.includes", { pos: i2, value: item }, state.localize(path8))); - if (prefs.abortEarly) { - return errors; + config2.reactiveSet(targetState2._volatile, "dirty", true); + }); + if (self2.subscriptionSet.has(v2.contractID)) { + const resync = esm_default("chelonia/private/queueEvent", v2.contractID, [ + "chelonia/private/in/syncContract", + v2.contractID + ]).then(() => { + esm_default("chelonia/private/out/sync", contractIdsToUpdate.filter((contractID2) => { + return self2.subscriptionSet.has(contractID2); + }), { force: true, resync: true }).catch((e2) => { + console.error("[chelonia] Error resyncing contracts with foreign key references after key rotation", e2); + }); + }).catch((e2) => { + console.error(`[chelonia] Error during sync for ${v2.contractID} during OP_KEY_SHARE for ${contractID}`); + if (v2.contractID === contractID) { + throw e2; } + }); + if (v2.contractID !== contractID) { + await resync; } } - if (requireds.length) { - internals.fillMissedErrors(schema, errors, requireds, value, state, prefs); - } - if (ordereds.length) { - internals.fillOrderedErrors(schema, errors, ordereds, value, state, prefs); - if (!errors.length) { - internals.fillDefault(ordereds, value, state, prefs); - } - } - return errors.length ? errors : value; - }, - priority: true, - manifest: false - }, - length: { - method(limit) { - return this.$_addRule({ name: "length", args: { limit }, operator: "=" }); - }, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(value.length, limit, operator)) { - return value; - } - return helpers.error("array." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - } - ] - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "length", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "length", args: { limit }, operator: ">=" }); } - }, - ordered: { - method(...schemas) { - Common.verifyFlat(schemas, "ordered"); - const obj = this.$_addRule("items"); - for (let i2 = 0; i2 < schemas.length; ++i2) { - const type = Common.tryWithPath(() => this.$_compile(schemas[i2]), i2, { append: true }); - internals.validateSingle(type, obj); - obj.$_mutateRegister(type); - obj.$_terms.ordered.push(type); + const previousVolatileState = targetState?._volatile; + esm_default("chelonia/private/queueEvent", v2.contractID, [ + "chelonia/private/postKeyShare", + v2.contractID, + mustResync ? previousVolatileState : null, + signingKey + ]).then(() => { + esm_default("chelonia/private/queueEvent", contractID, () => { + esm_default("okTurtles.events/emit", CONTRACT_HAS_RECEIVED_KEYS, { + contractID: v2.contractID, + sharedWithContractID: contractID, + signingKeyId, + get signingKeyName() { + return state._vm?.authorizedKeys?.[signingKeyId]?.name; + } + }); + }).catch((e2) => { + console.error(`[chelonia] Error while emitting the CONTRACT_HAS_RECEIVED_KEYS event for ${contractID}`, e2); + }); + }); + }); + }, + [SPMessage.OP_KEY_REQUEST](wv) { + const data = config2.unwrapMaybeEncryptedData(wv); + const v2 = data?.data || { + contractID: "(private)", + replyWith: { context: void 0 }, + request: "*" + }; + const originatingContractID = v2.contractID; + if (state._vm?.invites?.[signingKeyId]?.quantity != null) { + if (state._vm.invites[signingKeyId].quantity > 0) { + if (--state._vm.invites[signingKeyId].quantity <= 0) { + state._vm.invites[signingKeyId].status = INVITE_STATUS.USED; } - return obj.$_mutateRebuild(); - } - }, - single: { - method(enabled2) { - const value = enabled2 === void 0 ? true : !!enabled2; - assert2(!value || !this._flags._arrayItems, "Cannot specify single rule when array has array items"); - return this.$_setFlag("single", value); + } else { + logEvtError(message, "Ignoring OP_KEY_REQUEST because it exceeds allowed quantity: " + originatingContractID); + return; } - }, - sort: { - method(options2 = {}) { - Common.assertOptions(options2, ["by", "order"]); - const settings = { - order: options2.order || "ascending" - }; - if (options2.by) { - settings.by = Compile.ref(options2.by, { ancestor: 0 }); - assert2(!settings.by.ancestor, "Cannot sort by ancestor"); - } - return this.$_addRule({ name: "sort", args: { options: settings } }); - }, - validate(value, { error: error2, state, prefs, schema }, { options: options2 }) { - const { value: sorted, errors } = internals.sort(schema, value, options2, state, prefs); - if (errors) { - return errors; - } - for (let i2 = 0; i2 < value.length; ++i2) { - if (value[i2] !== sorted[i2]) { - return error2("array.sort", { order: options2.order, by: options2.by ? options2.by.key : "value" }); - } - } - return value; - }, - convert: true - }, - sparse: { - method(enabled2) { - const value = enabled2 === void 0 ? true : !!enabled2; - if (this._flags.sparse === value) { - return this; - } - const obj = value ? this.clone() : this.$_addRule("items"); - return obj.$_setFlag("sparse", value, { clone: false }); + } + if (state._vm?.invites?.[signingKeyId]?.expires != null) { + if (state._vm.invites[signingKeyId].expires < Date.now()) { + logEvtError(message, "Ignoring OP_KEY_REQUEST because it expired at " + state._vm.invites[signingKeyId].expires + ": " + originatingContractID); + return; } - }, - unique: { - method(comparator, options2 = {}) { - assert2(!comparator || typeof comparator === "function" || typeof comparator === "string", "comparator must be a function or a string"); - Common.assertOptions(options2, ["ignoreUndefined", "separator"]); - const rule = { name: "unique", args: { options: options2, comparator } }; - if (comparator) { - if (typeof comparator === "string") { - const separator = Common.default(options2.separator, "."); - rule.path = separator ? comparator.split(separator) : [comparator]; - } else { - rule.comparator = comparator; - } - } - return this.$_addRule(rule); - }, - validate(value, { state, error: error2, schema }, { comparator: raw, options: options2 }, { comparator, path: path8 }) { - const found = { - string: /* @__PURE__ */ Object.create(null), - number: /* @__PURE__ */ Object.create(null), - undefined: /* @__PURE__ */ Object.create(null), - boolean: /* @__PURE__ */ Object.create(null), - bigint: /* @__PURE__ */ Object.create(null), - object: /* @__PURE__ */ new Map(), - function: /* @__PURE__ */ new Map(), - custom: /* @__PURE__ */ new Map() - }; - const compare = comparator || deepEqual; - const ignoreUndefined = options2.ignoreUndefined; - for (let i2 = 0; i2 < value.length; ++i2) { - const item = path8 ? reach(value[i2], path8) : value[i2]; - const records = comparator ? found.custom : found[typeof item]; - assert2(records, "Failed to find unique map container for type", typeof item); - if (records instanceof Map) { - const entries = records.entries(); - let current; - while (!(current = entries.next()).done) { - if (compare(current.value[0], item)) { - const localState = state.localize([...state.path, i2], [value, ...state.ancestors]); - const context = { - pos: i2, - value: value[i2], - dupePos: current.value[1], - dupeValue: value[current.value[1]] - }; - if (path8) { - context.path = raw; - } - return error2("array.unique", context, localState); - } - } - records.set(item, i2); - } else { - if ((!ignoreUndefined || item !== void 0) && records[item] !== void 0) { - const context = { - pos: i2, - value: value[i2], - dupePos: records[item], - dupeValue: value[records[item]] - }; - if (path8) { - context.path = raw; - } - const localState = state.localize([...state.path, i2], [value, ...state.ancestors]); - return error2("array.unique", context, localState); - } - records[item] = i2; - } + } + if (config2.skipActionProcessing || direction === "outgoing") { + return; + } + if (!has(v2.replyWith, "context")) { + logEvtError(message, "Ignoring OP_KEY_REQUEST because it is missing the context attribute"); + return; + } + const context = v2.replyWith.context; + if (data && (!Array.isArray(context) || context[0] !== originatingContractID)) { + logEvtError(message, "Ignoring OP_KEY_REQUEST because it is signed by the wrong contract"); + return; + } + if (v2.request !== "*") { + logEvtError(message, "Ignoring OP_KEY_REQUEST because it has an unsupported request attribute", v2.request); + return; + } + if (!state._vm.pendingKeyshares) + state._vm.pendingKeyshares = /* @__PURE__ */ Object.create(null); + state._vm.pendingKeyshares[message.hash()] = context ? [ + // Full-encryption (i.e., KRS encryption) requires that this request + // was encrypted and that the invite is marked as private + !!data?.encryptionKeyId, + message.height(), + signingKeyId, + context + ] : [!!data?.encryptionKeyId, message.height(), signingKeyId]; + if (data) { + internalSideEffectStack?.push(() => { + self2.setPostSyncOp(contractID, "respondToAllKeyRequests-" + message.contractID(), [ + "chelonia/private/respondToAllKeyRequests", + contractID + ]); + }); + } + }, + [SPMessage.OP_KEY_REQUEST_SEEN](wv) { + if (config2.skipActionProcessing) { + return; + } + const data = config2.unwrapMaybeEncryptedData(wv); + if (!data) + return; + const v2 = data.data; + if (state._vm.pendingKeyshares && v2.keyRequestHash in state._vm.pendingKeyshares) { + const hash4 = v2.keyRequestHash; + const pending = state._vm.pendingKeyshares[hash4]; + delete state._vm.pendingKeyshares[hash4]; + if (pending.length !== 4) + return; + const keyId2 = pending[2]; + const originatingContractID = pending[3][0]; + if (Array.isArray(state._vm?.invites?.[keyId2]?.responses)) { + state._vm?.invites?.[keyId2]?.responses.push(originatingContractID); + } + if (!has(state._vm, "keyshares")) + state._vm.keyshares = /* @__PURE__ */ Object.create(null); + const success = v2.success; + state._vm.keyshares[hash4] = { + contractID: originatingContractID, + height, + success, + ...success && { + hash: v2.keyShareHash } - return value; - }, - args: ["comparator", "options"], - multi: true + }; } }, - overrides: { - isAsync() { - if (this.$_terms.externals?.length) { - return true; + [SPMessage.OP_PROP_DEL]: notImplemented, + [SPMessage.OP_PROP_SET](v2) { + if (!state._vm.props) + state._vm.props = {}; + state._vm.props[v2.key] = v2.value; + }, + [SPMessage.OP_KEY_ADD](v2) { + const keys = keysToMap.call(self2, v2, height, state._vm.authorizedKeys); + const keysArray = Object.values(v2); + keysArray.forEach((k) => { + if (has(state._vm.authorizedKeys, k.id) && state._vm.authorizedKeys[k.id]._notAfterHeight == null) { + throw new ChelErrorWarning("Cannot use OP_KEY_ADD on existing keys. Key ID: " + k.id); } - for (const item of this.$_terms.items) { - if (item.isAsync()) { - return true; - } + }); + validateKeyAddPermissions.call(self2, contractID, signingKey, state, v2); + state._vm.authorizedKeys = { ...state._vm.authorizedKeys, ...keys }; + keyAdditionProcessor.call(self2, message, hash3, v2, state, contractID, signingKey, internalSideEffectStack); + }, + [SPMessage.OP_KEY_DEL](v2) { + if (!state._vm.authorizedKeys) + state._vm.authorizedKeys = /* @__PURE__ */ Object.create(null); + if (!state._volatile) + state._volatile = /* @__PURE__ */ Object.create(null); + if (!state._volatile.pendingKeyRevocations) { + state._volatile.pendingKeyRevocations = /* @__PURE__ */ Object.create(null); + } + validateKeyDelPermissions.call(self2, contractID, signingKey, state, v2); + const keyIds = v2.map((k) => { + const data = config2.unwrapMaybeEncryptedData(k); + if (!data) + return void 0; + return data.data; + }).filter((keyId2) => { + if (!keyId2 || typeof keyId2 !== "string") + return false; + if (!has(state._vm.authorizedKeys, keyId2) || state._vm.authorizedKeys[keyId2]._notAfterHeight != null) { + console.warn("Attempted to delete non-existent key from contract", { + contractID, + keyId: keyId2 + }); + return false; } - for (const item of this.$_terms.ordered) { - if (item.isAsync()) { - return true; + return true; + }); + keyIds.forEach((keyId2) => { + const key = state._vm.authorizedKeys[keyId2]; + state._vm.authorizedKeys[keyId2]._notAfterHeight = height; + if (has(state._volatile.pendingKeyRevocations, keyId2)) { + delete state._volatile.pendingKeyRevocations[keyId2]; + } + if (key.foreignKey) { + const fkUrl = new URL(key.foreignKey); + const foreignContract = fkUrl.pathname; + const foreignKeyName = fkUrl.searchParams.get("keyName"); + if (!foreignContract || !foreignKeyName) { + throw new Error("Invalid foreign key: missing contract or key name"); + } + internalSideEffectStack?.push(() => { + esm_default("chelonia/private/queueEvent", foreignContract, () => { + const rootState = esm_default(config2.stateSelector); + if (Array.isArray(rootState[foreignContract]?._volatile?.watch)) { + const oldWatch = rootState[foreignContract]._volatile.watch; + rootState[foreignContract]._volatile.watch = oldWatch.filter(([name, cID]) => name !== foreignKeyName || cID !== contractID); + if (oldWatch.length !== rootState[foreignContract]._volatile.watch.length) { + esm_default("chelonia/contract/release", foreignContract, { try: true }).catch((e2) => { + console.error(`[chelonia] Error at OP_KEY_DEL internalSideEffectStack while attempting to release foreign contract ${foreignContract}`, e2); + }); + } + } + }).catch((e2) => { + console.error("Error stopping watching events after removing key", { contractID, foreignContract, foreignKeyName, fkUrl }, e2); + }); + }); + const pendingWatch = state._vm.pendingWatch?.[foreignContract]; + if (pendingWatch) { + state._vm.pendingWatch[foreignContract] = pendingWatch.filter(([, kId]) => kId !== keyId2); } } - return false; + if (key.name.startsWith("#inviteKey-") && state._vm.invites[key.id]) { + state._vm.invites[key.id].status = INVITE_STATUS.REVOKED; + } + }); + if (Array.isArray(state._volatile?.watch)) { + const updatedKeysMap = /* @__PURE__ */ Object.create(null); + keyIds.forEach((keyId2) => { + updatedKeysMap[state._vm.authorizedKeys[keyId2].name] = { + name: state._vm.authorizedKeys[keyId2].name, + oldKeyId: keyId2 + }; + }); + keyRotationHelper(contractID, state, config2, updatedKeysMap, [SPMessage.OP_KEY_DEL], "chelonia/out/keyDel", (name) => updatedKeysMap[name[0]].oldKeyId, internalSideEffectStack); } }, - cast: { - set: { - from: Array.isArray, - to(value, helpers) { - return new Set(value); + [SPMessage.OP_KEY_UPDATE](v2) { + if (!state._volatile) + state._volatile = /* @__PURE__ */ Object.create(null); + if (!state._volatile.pendingKeyRevocations) { + state._volatile.pendingKeyRevocations = /* @__PURE__ */ Object.create(null); + } + const [updatedKeys, updatedMap] = validateKeyUpdatePermissions.call(self2, contractID, signingKey, state, v2); + const keysToDelete = Object.values(updatedMap); + for (const keyId2 of keysToDelete) { + if (has(state._volatile.pendingKeyRevocations, keyId2)) { + delete state._volatile.pendingKeyRevocations[keyId2]; } + state._vm.authorizedKeys[keyId2]._notAfterHeight = height; } - }, - rebuild(schema) { - schema.$_terms._inclusions = []; - schema.$_terms._exclusions = []; - schema.$_terms._requireds = []; - for (const type of schema.$_terms.items) { - internals.validateSingle(type, schema); - if (type._flags.presence === "required") { - schema.$_terms._requireds.push(type); - } else if (type._flags.presence === "forbidden") { - schema.$_terms._exclusions.push(type); - } else { - schema.$_terms._inclusions.push(type); + for (const key of updatedKeys) { + if (!has(state._vm.authorizedKeys, key.id)) { + key._notBeforeHeight = height; + state._vm.authorizedKeys[key.id] = cloneDeep(key); } } - for (const type of schema.$_terms.ordered) { - internals.validateSingle(type, schema); + keyAdditionProcessor.call(self2, message, hash3, updatedKeys, state, contractID, signingKey, internalSideEffectStack); + if (Array.isArray(state._volatile?.watch)) { + const updatedKeysMap = /* @__PURE__ */ Object.create(null); + updatedKeys.forEach((key) => { + if (key.data) { + updatedKeysMap[key.name] = cloneDeep(key); + updatedKeysMap[key.name].oldKeyId = updatedMap[key.id]; + } + }); + keyRotationHelper(contractID, state, config2, updatedKeysMap, [SPMessage.OP_KEY_UPDATE], "chelonia/out/keyUpdate", (name) => ({ + name: name[1], + oldKeyId: updatedKeysMap[name[0]].oldKeyId, + id: updatedKeysMap[name[0]].id, + data: updatedKeysMap[name[0]].data + }), internalSideEffectStack); } }, - manifest: { - build(obj, desc) { - if (desc.items) { - obj = obj.items(...desc.items); + [SPMessage.OP_PROTOCOL_UPGRADE]: notImplemented + }; + if (!this.config.skipActionProcessing && !this.manifestToContract[manifestHash]) { + const rootState = esm_default(this.config.stateSelector); + if (!contractName) { + contractName = has(rootState.contracts, contractID) && rootState.contracts[contractID] && has(rootState.contracts[contractID], "type") ? rootState.contracts[contractID].type : opT === SPMessage.OP_CONTRACT ? opV.type : ""; + } + if (!contractName) { + throw new Error(`Unable to determine the name for a contract and refusing to load it (contract ID was ${contractID} and its manifest hash was ${manifestHash})`); + } + await esm_default("chelonia/private/loadManifest", contractName, manifestHash); + } + let processOp = true; + if (config2.preOp) { + processOp = config2.preOp(message, state) !== false && processOp; + } + let signingKey; + { + const stateForValidation = opT === SPMessage.OP_CONTRACT && !state?._vm?.authorizedKeys ? { + _vm: { + authorizedKeys: keysToMap.call(this, opV.keys, height) + } + } : state; + if (!validateKeyPermissions(message, config2, stateForValidation, signingKeyId, opT, opV)) { + throw new Error("No matching signing key was defined"); + } + signingKey = stateForValidation._vm.authorizedKeys[signingKeyId]; + } + if (config2[`preOp_${opT}`]) { + processOp = config2[`preOp_${opT}`](message, state) !== false && processOp; + } + if (processOp) { + await opFns[opT](opV); + config2.postOp?.(message, state); + config2[`postOp_${opT}`]?.(message, state); + } + }, + "chelonia/private/in/enqueueHandleEvent": function(contractID, event) { + return esm_default("chelonia/private/queueEvent", contractID, async () => { + await esm_default("chelonia/private/in/handleEvent", contractID, event); + esm_default("chelonia/private/enqueuePostSyncOps", contractID); + }); + }, + "chelonia/private/in/syncContract": async function(contractID, params) { + const state = esm_default(this.config.stateSelector); + if (state.contracts[contractID] === null) { + throw new ChelErrorResourceGone("Cannot sync permanently deleted contract " + contractID); + } + try { + this.currentSyncs[contractID] = { firstSync: !state.contracts[contractID]?.type }; + esm_default("okTurtles.events/emit", CONTRACT_IS_SYNCING, contractID, true); + const currentVolatileState = state[contractID]?._volatile || /* @__PURE__ */ Object.create(null); + if (currentVolatileState?.dirty || params?.resync) { + delete currentVolatileState.dirty; + currentVolatileState.resyncing = true; + esm_default("chelonia/private/removeImmediately", contractID, { resync: true }); + this.config.reactiveSet(state, contractID, /* @__PURE__ */ Object.create(null)); + this.config.reactiveSet(state[contractID], "_volatile", currentVolatileState); + } + const { HEAD: latestHEAD } = await esm_default("chelonia/out/latestHEADInfo", contractID); + console.debug(`[chelonia] syncContract: ${contractID} latestHash is: ${latestHEAD}`); + const { HEAD: recentHEAD, height: recentHeight } = state.contracts[contractID] || {}; + const isSubscribed = this.subscriptionSet.has(contractID); + if (!isSubscribed) { + const entry = this.pending.find((entry2) => entry2?.contractID === contractID); + if (!entry) { + this.pending.push({ contractID }); + } + } + this.postSyncOperations[contractID] = this.postSyncOperations[contractID] ?? /* @__PURE__ */ Object.create(null); + if (latestHEAD !== recentHEAD) { + console.debug(`[chelonia] Synchronizing Contract ${contractID}: our recent was ${recentHEAD || "undefined"} but the latest is ${latestHEAD}`); + const eventsStream = esm_default("chelonia/out/eventsAfter", contractID, { + sinceHeight: recentHeight ?? 0, + sinceHash: recentHEAD ?? contractID + }); + let latestHashFound = false; + const eventReader = eventsStream.getReader(); + for (let skip = has(state.contracts, contractID) && has(state.contracts[contractID], "HEAD"); ; skip = false) { + const { done, value: event } = await eventReader.read(); + if (done) { + if (!latestHashFound) { + throw new ChelErrorForkedChain(`expected hash ${latestHEAD} in list of events for contract ${contractID}`); + } + break; } - if (desc.ordered) { - obj = obj.ordered(...desc.ordered); + if (!latestHashFound) { + latestHashFound = SPMessage.deserializeHEAD(event).hash === latestHEAD; } - return obj; + if (skip) + continue; + await esm_default("chelonia/private/in/handleEvent", contractID, event); } - }, - messages: { - "array.base": "{{#label}} must be an array", - "array.excludes": "{{#label}} contains an excluded value", - "array.hasKnown": "{{#label}} does not contain at least one required match for type {:#patternLabel}", - "array.hasUnknown": "{{#label}} does not contain at least one required match", - "array.includes": "{{#label}} does not match any of the allowed types", - "array.includesRequiredBoth": "{{#label}} does not contain {{#knownMisses}} and {{#unknownMisses}} other required value(s)", - "array.includesRequiredKnowns": "{{#label}} does not contain {{#knownMisses}}", - "array.includesRequiredUnknowns": "{{#label}} does not contain {{#unknownMisses}} required value(s)", - "array.length": "{{#label}} must contain {{#limit}} items", - "array.max": "{{#label}} must contain less than or equal to {{#limit}} items", - "array.min": "{{#label}} must contain at least {{#limit}} items", - "array.orderedLength": "{{#label}} must contain at most {{#limit}} items", - "array.sort": "{{#label}} must be sorted in {#order} order by {{#by}}", - "array.sort.mismatching": "{{#label}} cannot be sorted due to mismatching types", - "array.sort.unsupported": "{{#label}} cannot be sorted due to unsupported type {#type}", - "array.sparse": "{{#label}} must not be a sparse array item", - "array.unique": "{{#label}} contains a duplicate value" + } else if (!isSubscribed) { + this.subscriptionSet.add(contractID); + esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { + added: [contractID], + removed: [] + }); + const entryIndex = this.pending.findIndex((entry) => entry?.contractID === contractID); + if (entryIndex !== -1) { + this.pending.splice(entryIndex, 1); + } + console.debug(`[chelonia] added already synchronized ${contractID} to subscription set`); + } else { + console.debug(`[chelonia] contract ${contractID} was already synchronized`); } + esm_default("chelonia/private/enqueuePostSyncOps", contractID); + } catch (e2) { + console.error(`[chelonia] syncContract error: ${e2.message || e2}`, e2); + this.config.hooks.syncContractError?.(e2, contractID); + throw e2; + } finally { + if (state[contractID]?._volatile?.resyncing) { + this.config.reactiveDel(state[contractID]._volatile, "resyncing"); + } + delete this.currentSyncs[contractID]; + esm_default("okTurtles.events/emit", CONTRACT_IS_SYNCING, contractID, false); + } + }, + "chelonia/private/enqueuePostSyncOps": function(contractID) { + if (!has(this.postSyncOperations, contractID)) + return; + Object.entries(this.postSyncOperations[contractID]).forEach(([key, op]) => { + delete this.postSyncOperations[contractID][key]; + esm_default("chelonia/private/queueEvent", contractID, op).catch((e2) => { + console.error(`Post-sync operation for ${contractID} failed`, { contractID, op, error: e2 }); + }); }); - internals.fillMissedErrors = function(schema, errors, requireds, value, state, prefs) { - const knownMisses = []; - let unknownMisses = 0; - for (const required2 of requireds) { - const label = required2._flags.label; - if (label) { - knownMisses.push(label); - } else { - ++unknownMisses; + }, + "chelonia/private/watchForeignKeys": function(externalContractID) { + const state = esm_default(this.config.stateSelector); + const externalContractState = state[externalContractID]; + const pendingWatch = externalContractState?._vm?.pendingWatch; + if (!pendingWatch || !Object.keys(pendingWatch).length) + return; + const signingKey = findSuitableSecretKeyId(externalContractState, [SPMessage.OP_KEY_DEL], ["sig"]); + const canMirrorOperations = !!signingKey; + if (!canMirrorOperations) { + console.info("[chelonia/private/watchForeignKeys]: Returning as operations cannot be mirrored", { externalContractID }); + return; + } + Object.entries(pendingWatch).forEach(([contractID, keys]) => { + if (!Array.isArray(keys) || // Check that the keys exist and haven't been revoked + !keys.reduce((acc, [, id]) => { + return acc || has(externalContractState._vm.authorizedKeys, id); + }, false)) { + console.info("[chelonia/private/watchForeignKeys]: Skipping as none of the keys to watch exist", { + externalContractID, + contractID + }); + return; + } + esm_default("chelonia/private/queueEvent", contractID, [ + "chelonia/private/in/syncContractAndWatchKeys", + contractID, + externalContractID + ]).catch((e2) => { + console.error(`Error at syncContractAndWatchKeys for contractID ${contractID} and externalContractID ${externalContractID}`, e2); + }); + }); + }, + "chelonia/private/in/syncContractAndWatchKeys": async function(contractID, externalContractID) { + const rootState = esm_default(this.config.stateSelector); + const externalContractState = rootState[externalContractID]; + const pendingWatch = externalContractState?._vm?.pendingWatch?.[contractID]?.splice(0); + if (!Array.isArray(pendingWatch) || // Check that the keys exist and haven't been revoked + !pendingWatch.reduce((acc, [, id]) => { + return acc || has(externalContractState._vm.authorizedKeys, id) && findKeyIdByName(externalContractState, externalContractState._vm.authorizedKeys[id].name) != null; + }, false)) { + console.info("[chelonia/private/syncContractAndWatchKeys]: Skipping as none of the keys to watch exist", { + externalContractID, + contractID + }); + return; + } + if (!this.subscriptionSet.has(contractID)) { + await esm_default("chelonia/private/in/syncContract", contractID); + } + const contractState = rootState[contractID]; + const keysToDelete = []; + const keysToUpdate = []; + pendingWatch.forEach(([keyName, externalId]) => { + const keyId2 = findKeyIdByName(contractState, keyName); + if (!keyId2) { + keysToDelete.push(externalId); + return; + } else if (keyId2 !== externalId) { + keysToUpdate.push(externalId); + } + if (!contractState._volatile) { + this.config.reactiveSet(contractState, "_volatile", Object.create(null, { + watch: { + value: [[keyName, externalContractID]], + configurable: true, + enumerable: true, + writable: true + } + })); + } else { + if (!contractState._volatile.watch) { + this.config.reactiveSet(contractState._volatile, "watch", [ + [keyName, externalContractID] + ]); + } + if (Array.isArray(contractState._volatile.watch) && !contractState._volatile.watch.find((v2) => v2[0] === keyName && v2[1] === externalContractID)) { + contractState._volatile.watch.push([keyName, externalContractID]); } } - if (knownMisses.length) { - if (unknownMisses) { - errors.push(schema.$_createError("array.includesRequiredBoth", value, { knownMisses, unknownMisses }, state, prefs)); - } else { - errors.push(schema.$_createError("array.includesRequiredKnowns", value, { knownMisses }, state, prefs)); + }); + if (keysToDelete.length || keysToUpdate.length) { + if (!externalContractState._volatile) { + this.config.reactiveSet(externalContractState, "_volatile", /* @__PURE__ */ Object.create(null)); + } + if (!externalContractState._volatile.pendingKeyRevocations) { + this.config.reactiveSet(externalContractState._volatile, "pendingKeyRevocations", /* @__PURE__ */ Object.create(null)); + } + keysToDelete.forEach((id) => this.config.reactiveSet(externalContractState._volatile.pendingKeyRevocations, id, "del")); + keysToUpdate.forEach((id) => this.config.reactiveSet(externalContractState._volatile.pendingKeyRevocations, id, true)); + esm_default("chelonia/private/queueEvent", externalContractID, [ + "chelonia/private/deleteOrRotateRevokedKeys", + externalContractID + ]).catch((e2) => { + console.error(`Error at deleteOrRotateRevokedKeys for contractID ${contractID} and externalContractID ${externalContractID}`, e2); + }); + } + }, + // The following function gets called when we start watching a contract for + // foreign keys for the first time, and it ensures that, at the point the + // watching starts, keys are in sync between the two contracts (later on, + // this will be handled automatically for incoming OP_KEY_DEL and + // OP_KEY_UPDATE). + // For any given foreign key, there are three possible states: + // 1. The key is in sync with the foreign contract. In this case, there's + // nothing left to do. + // 2. The key has been rotated in the foreign contract (replaced by another + // key of the same name). We need to mirror this operation manually + // since watching only affects new messages we receive. + // 3. The key has been removed in the foreign contract. We also need to + // mirror the operation. + "chelonia/private/deleteOrRotateRevokedKeys": function(contractID) { + const rootState = esm_default(this.config.stateSelector); + const contractState = rootState[contractID]; + const pendingKeyRevocations = contractState?._volatile?.pendingKeyRevocations; + if (!pendingKeyRevocations || Object.keys(pendingKeyRevocations).length === 0) + return; + const keysToUpdate = Object.entries(pendingKeyRevocations).filter(([, v2]) => v2 === true).map(([id]) => id); + const [, keyUpdateSigningKeyId, keyUpdateArgs] = keysToUpdate.reduce((acc, keyId2) => { + const key = contractState._vm?.authorizedKeys?.[keyId2]; + if (!key || !key.foreignKey) + return acc; + const foreignKey = String(key.foreignKey); + const fkUrl = new URL(foreignKey); + const foreignContractID = fkUrl.pathname; + const foreignKeyName = fkUrl.searchParams.get("keyName"); + if (!foreignKeyName) + throw new Error("Missing foreign key name"); + const foreignState = rootState[foreignContractID]; + if (!foreignState) + return acc; + const fKeyId = findKeyIdByName(foreignState, foreignKeyName); + if (!fKeyId) { + if (pendingKeyRevocations[keyId2] === true) { + this.config.reactiveSet(pendingKeyRevocations, keyId2, "del"); } - } else { - errors.push(schema.$_createError("array.includesRequiredUnknowns", value, { unknownMisses }, state, prefs)); + return acc; } - }; - internals.fillOrderedErrors = function(schema, errors, ordereds, value, state, prefs) { - const requiredOrdereds = []; - for (const ordered of ordereds) { - if (ordered._flags.presence === "required") { - requiredOrdereds.push(ordered); + const [currentRingLevel, currentSigningKeyId, currentKeyArgs] = acc; + const ringLevel = Math.min(currentRingLevel, key.ringLevel ?? Number.POSITIVE_INFINITY); + if (ringLevel >= currentRingLevel) { + currentKeyArgs.push({ + name: key.name, + oldKeyId: keyId2, + id: fKeyId, + data: foreignState._vm.authorizedKeys[fKeyId].data + }); + return [currentRingLevel, currentSigningKeyId, currentKeyArgs]; + } else if (Number.isFinite(ringLevel)) { + const signingKeyId = findSuitableSecretKeyId(contractState, [SPMessage.OP_KEY_UPDATE], ["sig"], ringLevel); + if (signingKeyId) { + currentKeyArgs.push({ + name: key.name, + oldKeyId: keyId2, + id: fKeyId, + data: foreignState._vm.authorizedKeys[fKeyId].data + }); + return [ringLevel, signingKeyId, currentKeyArgs]; } } - if (requiredOrdereds.length) { - internals.fillMissedErrors(schema, errors, requiredOrdereds, value, state, prefs); + return acc; + }, [ + Number.POSITIVE_INFINITY, + "", + [] + ]); + if (keyUpdateArgs.length !== 0) { + const contractName = contractState._vm.type; + esm_default("chelonia/out/keyUpdate", { + contractID, + contractName, + data: keyUpdateArgs, + signingKeyId: keyUpdateSigningKeyId + }).catch((e2) => { + console.error(`[chelonia/private/deleteOrRotateRevokedKeys] Error sending OP_KEY_UPDATE for ${contractID}`, e2.message); + }); + } + const keysToDelete = Object.entries(pendingKeyRevocations).filter(([, v2]) => v2 === "del").map(([id]) => id); + const [, keyDelSigningKeyId, keyIdsToDelete] = keysToDelete.reduce((acc, keyId2) => { + const [currentRingLevel, currentSigningKeyId, currentKeyIds] = acc; + const ringLevel = Math.min(currentRingLevel, contractState._vm?.authorizedKeys?.[keyId2]?.ringLevel ?? Number.POSITIVE_INFINITY); + if (ringLevel >= currentRingLevel) { + currentKeyIds.push(keyId2); + return [currentRingLevel, currentSigningKeyId, currentKeyIds]; + } else if (Number.isFinite(ringLevel)) { + const signingKeyId = findSuitableSecretKeyId(contractState, [SPMessage.OP_KEY_DEL], ["sig"], ringLevel); + if (signingKeyId) { + currentKeyIds.push(keyId2); + return [ringLevel, signingKeyId, currentKeyIds]; + } } - }; - internals.fillDefault = function(ordereds, value, state, prefs) { - const overrides = []; - let trailingUndefined = true; - for (let i2 = ordereds.length - 1; i2 >= 0; --i2) { - const ordered = ordereds[i2]; - const ancestors = [value, ...state.ancestors]; - const override = ordered.$_validate(void 0, state.localize(state.path, ancestors, ordered), prefs).value; - if (trailingUndefined) { - if (override === void 0) { - continue; + return acc; + }, [Number.POSITIVE_INFINITY, "", []]); + if (keyIdsToDelete.length !== 0) { + const contractName = contractState._vm.type; + esm_default("chelonia/out/keyDel", { + contractID, + contractName, + data: keyIdsToDelete, + signingKeyId: keyDelSigningKeyId + }).catch((e2) => { + console.error(`[chelonia/private/deleteRevokedKeys] Error sending OP_KEY_DEL for ${contractID}`, e2.message); + }); + } + }, + "chelonia/private/respondToAllKeyRequests": function(contractID) { + const state = esm_default(this.config.stateSelector); + const contractState = state[contractID] ?? {}; + const pending = contractState?._vm?.pendingKeyshares; + if (!pending) + return; + const signingKeyId = findSuitableSecretKeyId(contractState, [SPMessage.OP_ATOMIC, SPMessage.OP_KEY_REQUEST_SEEN, SPMessage.OP_KEY_SHARE], ["sig"]); + if (!signingKeyId) { + console.log("Unable to respond to key request because there is no suitable secret key with OP_KEY_REQUEST_SEEN permission"); + return; + } + Object.entries(pending).map(([hash3, entry]) => { + if (!Array.isArray(entry) || entry.length !== 4) { + return void 0; + } + const [, , , [originatingContractID]] = entry; + return esm_default("chelonia/private/queueEvent", originatingContractID, [ + "chelonia/private/respondToKeyRequest", + contractID, + signingKeyId, + hash3 + ]).catch((e2) => { + console.error(`respondToAllKeyRequests: Error responding to key request ${hash3} from ${originatingContractID} to ${contractID}`, e2); + }); + }); + }, + "chelonia/private/respondToKeyRequest": async function(contractID, signingKeyId, hash3) { + const state = esm_default(this.config.stateSelector); + const contractState = state[contractID]; + const entry = contractState?._vm?.pendingKeyshares?.[hash3]; + const instance = this._instance; + if (!Array.isArray(entry) || entry.length !== 4) { + return; + } + const [keyShareEncryption, height, , [originatingContractID, rv, originatingContractHeight, headJSON]] = entry; + entry.pop(); + const krsEncryption = !!contractState._vm.authorizedKeys?.[signingKeyId]?._private; + await esm_default("chelonia/private/in/syncContract", originatingContractID); + if (instance !== this._instance) + return; + const originatingState = state[originatingContractID]; + const contractName = state.contracts[contractID].type; + const originatingContractName = originatingState._vm.type; + const v2 = signedIncomingData(originatingContractID, originatingState, rv, originatingContractHeight, headJSON).valueOf(); + const { encryptionKeyId } = v2; + const responseKey = encryptedIncomingData(contractID, contractState, v2.responseKey, height, this.transientSecretKeys, headJSON).valueOf(); + const deserializedResponseKey = deserializeKey(responseKey); + const responseKeyId = keyId(deserializedResponseKey); + Promise.resolve().then(() => { + if (instance !== this._instance) + return; + if (!has(originatingState._vm.authorizedKeys, responseKeyId) || originatingState._vm.authorizedKeys[responseKeyId]._notAfterHeight != null) { + throw new Error(`Unable to respond to key request for ${originatingContractID}. Key ${responseKeyId} is not valid.`); + } + esm_default("chelonia/storeSecretKeys", new Secret([{ key: deserializedResponseKey }])); + const keys = pick2(state.secretKeys, Object.entries(contractState._vm.authorizedKeys).filter(([, key]) => !!key.meta?.private?.shareable).map(([kId]) => kId)); + if (!keys || Object.keys(keys).length === 0) { + console.info("respondToAllKeyRequests: no keys to share", { + contractID, + originatingContractID + }); + return; + } + const keySharePayload = { + contractID, + keys: Object.entries(keys).map(([keyId2, key]) => ({ + id: keyId2, + meta: { + private: { + content: encryptedOutgoingData(originatingContractID, encryptionKeyId, key), + shareable: true + } + } + })), + keyRequestHash: hash3, + keyRequestHeight: height + }; + if (!contractState?._vm?.pendingKeyshares?.[hash3]) { + return; + } + return keySharePayload; + }).then((keySharePayload) => { + if (instance !== this._instance || !keySharePayload) + return; + return esm_default("chelonia/out/keyShare", { + contractID: originatingContractID, + contractName: originatingContractName, + data: keyShareEncryption ? encryptedOutgoingData(originatingContractID, findSuitablePublicKeyIds(originatingState, [SPMessage.OP_KEY_SHARE], ["enc"])?.[0] || "", keySharePayload) : keySharePayload, + signingKeyId: responseKeyId + }).then((msg) => { + if (instance !== this._instance) + return; + const payload = { keyRequestHash: hash3, keyShareHash: msg.hash(), success: true }; + const connectionKeyPayload = { + contractID: originatingContractID, + keys: [ + { + id: responseKeyId, + meta: { + private: { + content: encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_REQUEST_SEEN], ["enc"])?.[0] || "", responseKey), + shareable: true + } + } + } + ] + }; + esm_default("chelonia/out/atomic", { + contractID, + contractName, + signingKeyId, + data: [ + [ + "chelonia/out/keyRequestResponse", + { + data: krsEncryption ? encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_REQUEST_SEEN], ["enc"])?.[0] || "", payload) : payload + } + ], + [ + // Upon successful key share, we want to share deserializedResponseKey + // with ourselves + "chelonia/out/keyShare", + { + data: keyShareEncryption ? encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_SHARE], ["enc"])?.[0] || "", connectionKeyPayload) : connectionKeyPayload + } + ] + ] + }).catch((e2) => { + console.error("Error at respondToKeyRequest while sending keyRequestResponse", e2); + }); + }); + }).catch((e2) => { + console.error("Error at respondToKeyRequest", e2); + const payload = { keyRequestHash: hash3, success: false }; + if (!contractState?._vm?.pendingKeyshares?.[hash3]) { + return; + } + esm_default("chelonia/out/keyRequestResponse", { + contractID, + contractName, + signingKeyId, + data: krsEncryption ? encryptedOutgoingData(contractID, findSuitablePublicKeyIds(contractState, [SPMessage.OP_KEY_REQUEST_SEEN], ["enc"])?.[0] || "", payload) : payload + }).catch((e3) => { + console.error("Error at respondToKeyRequest while sending keyRequestResponse in error handler", e3); + }); + }); + }, + "chelonia/private/in/handleEvent": async function(contractID, rawMessage) { + const state = esm_default(this.config.stateSelector); + const { preHandleEvent, postHandleEvent, handleEventError } = this.config.hooks; + let processingErrored = false; + let message; + try { + if (!this.config.acceptAllMessages && !this.pending.some((entry) => entry?.contractID === contractID) && !this.subscriptionSet.has(contractID)) { + console.warn(`[chelonia] WARN: ignoring unexpected event for ${contractID}:`, rawMessage); + return; + } + const contractStateCopy = state[contractID] ? cloneDeep(state[contractID]) : /* @__PURE__ */ Object.create(null); + message = SPMessage.deserialize(rawMessage, this.transientSecretKeys, contractStateCopy, this.config.unwrapMaybeEncryptedData); + if (message.contractID() !== contractID) { + throw new Error(`[chelonia] Wrong contract ID. Expected ${contractID} but got ${message.contractID()}`); + } + if (!message.isFirstMessage() && (!has(state.contracts, contractID) || !has(state, contractID))) { + throw new ChelErrorUnrecoverable("The event is not for a first message but the contract state is missing"); + } + preHandleEvent?.(message); + const proceed = handleEvent.checkMessageOrdering.call(this, message); + if (proceed === false) + return; + if (state[contractID]?._volatile?.dirty) { + console.info(`[chelonia] Ignoring message ${message.description()} as the contract is marked as dirty`); + return; + } + const internalSideEffectStack = !this.config.skipSideEffects ? [] : void 0; + missingDecryptionKeyIdsMap.delete(message); + try { + await handleEvent.processMutation.call(this, message, contractStateCopy, internalSideEffectStack); + } catch (e_) { + const e2 = e_; + if (e2?.name === "ChelErrorDecryptionKeyNotFound") { + console.warn(`[chelonia] WARN '${e2.name}' in processMutation for ${message.description()}: ${e2.message}`, e2, message.serialize()); + if (e2.cause) { + const missingDecryptionKeyIds = missingDecryptionKeyIdsMap.get(message); + if (missingDecryptionKeyIds) { + missingDecryptionKeyIds.add(e2.cause); + } else { + missingDecryptionKeyIdsMap.set(message, /* @__PURE__ */ new Set([e2.cause])); + } } - trailingUndefined = false; + } else { + console.error(`[chelonia] ERROR '${e2.name}' in processMutation for ${message.description()}: ${e2.message || e2}`, e2, message.serialize()); + } + console.warn(`[chelonia] Error processing ${message.description()}: ${message.serialize()}. Any side effects will be skipped!`); + if (this.config.strictProcessing) { + throw e2; + } + processingErrored = e2?.name !== "ChelErrorWarning"; + this.config.hooks.processError?.(e2, message, getMsgMeta.call(this, message, contractID, contractStateCopy)); + if (e2.name === "ChelErrorUnrecoverable" || e2.name === "ChelErrorForkedChain" || message.isFirstMessage()) { + throw e2; } - overrides.unshift(override); } - if (overrides.length) { - value.push(...overrides); + if (!processingErrored) { + if (Array.isArray(internalSideEffectStack) && internalSideEffectStack.length > 0) { + await Promise.all(internalSideEffectStack.map((fn) => Promise.resolve(fn({ state: contractStateCopy, message })).catch((e_) => { + const e2 = e_; + console.error(`[chelonia] ERROR '${e2.name}' in internal side effect for ${message.description()}: ${e2.message}`, e2, { message: message.serialize() }); + }))); + } + if (!this.config.skipActionProcessing && !this.config.skipSideEffects) { + await handleEvent.processSideEffects.call(this, message, contractStateCopy)?.catch((e_) => { + const e2 = e_; + console.error(`[chelonia] ERROR '${e2.name}' in sideEffect for ${message.description()}: ${e2.message}`, e2, { message: message.serialize() }); + this.config.hooks.sideEffectError?.(e2, message); + }); + } + } + try { + const state2 = esm_default(this.config.stateSelector); + await handleEvent.applyProcessResult.call(this, { + message, + state: state2, + contractState: contractStateCopy, + processingErrored, + postHandleEvent + }); + } catch (e_) { + const e2 = e_; + console.error(`[chelonia] ERROR '${e2.name}' for ${message.description()} marking the event as processed: ${e2.message}`, e2, { message: message.serialize() }); + } + } catch (e_) { + const e2 = e_; + console.error(`[chelonia] ERROR in handleEvent: ${e2.message || e2}`, e2); + try { + handleEventError?.(e2, message); + } catch (e22) { + console.error("[chelonia] Ignoring user error in handleEventError hook:", e22); + } + throw e2; + } finally { + if (message) { + missingDecryptionKeyIdsMap.delete(message); + } + } + } +}); +var eventsToReingest = []; +var reprocessDebounced = debounce((contractID) => esm_default("chelonia/private/out/sync", contractID, { force: true }).catch((e2) => { + console.error(`[chelonia] Error at reprocessDebounced for ${contractID}`, e2); +}), 1e3); +var handleEvent = { + checkMessageOrdering(message) { + const contractID = message.contractID(); + const hash3 = message.hash(); + const height = message.height(); + const state = esm_default(this.config.stateSelector); + const latestProcessedHeight = state.contracts[contractID]?.height; + if (!Number.isSafeInteger(height)) { + throw new ChelErrorDBBadPreviousHEAD(`Message ${hash3} in contract ${contractID} has an invalid height.`); + } + if (message.isFirstMessage() ? latestProcessedHeight != null : !(latestProcessedHeight < height)) { + if (!this.config.strictOrdering) { + return false; + } + throw new ChelErrorAlreadyProcessed(`Message ${hash3} with height ${height} in contract ${contractID} has already been processed. Current height: ${latestProcessedHeight}.`); + } + if (latestProcessedHeight + 1 < height) { + if (this.config.strictOrdering) { + throw new ChelErrorDBBadPreviousHEAD(`Unexpected message ${hash3} with height ${height} in contract ${contractID}: height is too high. Current height: ${latestProcessedHeight}.`); + } + if (eventsToReingest.length > 100) { + throw new ChelErrorUnrecoverable("more than 100 different bad previousHEAD errors"); } - }; - internals.fastSplice = function(arr, i2) { - let pos = i2; - while (pos < arr.length) { - arr[pos++] = arr[pos]; + if (!eventsToReingest.includes(hash3)) { + console.warn(`[chelonia] WARN bad previousHEAD for ${message.description()}, will attempt to re-sync contract to reingest message`); + eventsToReingest.push(hash3); + reprocessDebounced(contractID); + return false; + } else { + console.error(`[chelonia] ERROR already attempted to reingest ${message.description()}, will not attempt again!`); + throw new ChelErrorDBBadPreviousHEAD(`Already attempted to reingest ${hash3}`); } - --arr.length; - }; - internals.validateSingle = function(type, obj) { - if (type.type === "array" || type._flags._arrayItems) { - assert2(!obj._flags.single, "Cannot specify array item with single rule enabled"); - obj.$_setFlag("_arrayItems", true, { clone: false }); + } + const reprocessIdx = eventsToReingest.indexOf(hash3); + if (reprocessIdx !== -1) { + console.warn(`[chelonia] WARN: successfully reingested ${message.description()}`); + eventsToReingest.splice(reprocessIdx, 1); + } + }, + async processMutation(message, state, internalSideEffectStack) { + const contractID = message.contractID(); + if (message.isFirstMessage()) { + if (Object.keys(state).some((k) => k !== "_volatile")) { + throw new ChelErrorUnrecoverable(`state for ${contractID} is already set`); } - }; - internals.sort = function(schema, value, settings, state, prefs) { - const order = settings.order === "ascending" ? 1 : -1; - const aFirst = -1 * order; - const bFirst = order; - const sort = (a, b) => { - let compare = internals.compare(a, b, aFirst, bFirst); - if (compare !== null) { - return compare; - } - if (settings.by) { - a = settings.by.resolve(a, state, prefs); - b = settings.by.resolve(b, state, prefs); - } - compare = internals.compare(a, b, aFirst, bFirst); - if (compare !== null) { - return compare; - } - const type = typeof a; - if (type !== typeof b) { - throw schema.$_createError("array.sort.mismatching", value, null, state, prefs); - } - if (type !== "number" && type !== "string") { - throw schema.$_createError("array.sort.unsupported", value, { type }, state, prefs); - } - if (type === "number") { - return (a - b) * order; + } + await esm_default("chelonia/private/in/processMessage", message, state, internalSideEffectStack); + }, + processSideEffects(message, state) { + const opT = message.opType(); + if (![ + SPMessage.OP_ATOMIC, + SPMessage.OP_ACTION_ENCRYPTED, + SPMessage.OP_ACTION_UNENCRYPTED + ].includes(opT)) { + return; + } + const contractID = message.contractID(); + const manifestHash = message.manifest(); + const hash3 = message.hash(); + const height = message.height(); + const signingKeyId = message.signingKeyId(); + const callSideEffect = async (field) => { + const wv = this.config.unwrapMaybeEncryptedData(field); + if (!wv) + return; + let v2 = wv.data; + let innerSigningKeyId; + if (isSignedData(v2)) { + innerSigningKeyId = v2.signingKeyId; + v2 = v2.valueOf(); + } + const { action, data, meta } = v2; + const mutation = { + data, + meta, + hash: hash3, + height, + contractID, + description: message.description(), + direction: message.direction(), + signingKeyId, + get signingContractID() { + return getContractIDfromKeyId(contractID, signingKeyId, state); + }, + innerSigningKeyId, + get innerSigningContractID() { + return getContractIDfromKeyId(contractID, innerSigningKeyId, state); } - return a < b ? aFirst : bFirst; }; - try { - return { value: value.slice().sort(sort) }; - } catch (err) { - return { errors: err }; - } + return await esm_default(`${manifestHash}/${action}/sideEffect`, mutation, state); }; - internals.compare = function(a, b, aFirst, bFirst) { - if (a === b) { - return 0; + const msg = Object(message.message()); + if (opT !== SPMessage.OP_ATOMIC) { + return callSideEffect(msg); + } + const reducer = (acc, [opT2, opV]) => { + if ([SPMessage.OP_ACTION_ENCRYPTED, SPMessage.OP_ACTION_UNENCRYPTED].includes(opT2)) { + acc.push(Object(opV)); } - if (a === void 0) { - return 1; + return acc; + }; + const actionsOpV = msg.reduce(reducer, []); + return Promise.allSettled(actionsOpV.map((action) => callSideEffect(action))).then((results) => { + const errors2 = results.filter((r) => r.status === "rejected").map((r) => r.reason); + if (errors2.length > 0) { + console.error("Side-effect errors", contractID, errors2); + throw new AggregateError(errors2, `Error at side effects for ${contractID}`); } - if (b === void 0) { - return -1; + }); + }, + async applyProcessResult({ message, state, contractState, processingErrored, postHandleEvent }) { + const contractID = message.contractID(); + const hash3 = message.hash(); + const height = message.height(); + await esm_default("chelonia/db/addEntry", message); + if (!processingErrored) { + this.config.reactiveSet(state, contractID, contractState); + try { + postHandleEvent?.(message); + } catch (e2) { + console.error(`[chelonia] ERROR '${e2.name}' for ${message.description()} in event post-handling: ${e2.message}`, e2, { message: message.serialize() }); } - if (a === null) { - return bFirst; + } + if (message.isFirstMessage()) { + const { type } = message.opValue(); + if (!has(state.contracts, contractID)) { + this.config.reactiveSet(state.contracts, contractID, /* @__PURE__ */ Object.create(null)); } - if (b === null) { - return aFirst; + this.config.reactiveSet(state.contracts[contractID], "type", type); + console.debug(`contract ${type} registered for ${contractID}`); + } + if (message.isKeyOp()) { + this.config.reactiveSet(state.contracts[contractID], "previousKeyOp", hash3); + } + this.config.reactiveSet(state.contracts[contractID], "HEAD", hash3); + this.config.reactiveSet(state.contracts[contractID], "height", height); + const missingDecryptionKeyIdsForMessage = missingDecryptionKeyIdsMap.get(message); + if (missingDecryptionKeyIdsForMessage) { + let missingDecryptionKeyIds = state.contracts[contractID].missingDecryptionKeyIds; + if (!missingDecryptionKeyIds) { + missingDecryptionKeyIds = []; + this.config.reactiveSet(state.contracts[contractID], "missingDecryptionKeyIds", missingDecryptionKeyIds); } - return null; - }; - } -}); -var require_boolean2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/boolean.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Any = require_any2(); - var Common = require_common3(); - var Values = require_values2(); - var internals = {}; - internals.isBool = function(value) { - return typeof value === "boolean"; - }; - module14.exports = Any.extend({ - type: "boolean", - flags: { - sensitive: { default: false } - }, - terms: { - falsy: { - init: null, - manifest: "values" - }, - truthy: { - init: null, - manifest: "values" - } - }, - coerce(value, { schema }) { - if (typeof value === "boolean") { + missingDecryptionKeyIdsForMessage.forEach((keyId2) => { + if (missingDecryptionKeyIds.includes(keyId2)) return; + missingDecryptionKeyIds.push(keyId2); + }); + } + if (!this.subscriptionSet.has(contractID)) { + const entry = this.pending.find((entry2) => entry2?.contractID === contractID); + if (entry) { + const index = this.pending.indexOf(entry); + if (index !== -1) { + this.pending.splice(index, 1); } - if (typeof value === "string") { - const normalized = schema._flags.sensitive ? value : value.toLowerCase(); - value = normalized === "true" ? true : normalized === "false" ? false : value; - } - if (typeof value !== "boolean") { - value = schema.$_terms.truthy && schema.$_terms.truthy.has(value, null, null, !schema._flags.sensitive) || (schema.$_terms.falsy && schema.$_terms.falsy.has(value, null, null, !schema._flags.sensitive) ? false : value); - } - return { value }; - }, - validate(value, { error: error2 }) { - if (typeof value !== "boolean") { - return { value, errors: error2("boolean.base") }; - } - }, - rules: { - truthy: { - method(...values) { - Common.verifyFlat(values, "truthy"); - const obj = this.clone(); - obj.$_terms.truthy = obj.$_terms.truthy || new Values(); - for (let i2 = 0; i2 < values.length; ++i2) { - const value = values[i2]; - assert2(value !== void 0, "Cannot call truthy with undefined"); - obj.$_terms.truthy.add(value); - } - return obj; - } - }, - falsy: { - method(...values) { - Common.verifyFlat(values, "falsy"); - const obj = this.clone(); - obj.$_terms.falsy = obj.$_terms.falsy || new Values(); - for (let i2 = 0; i2 < values.length; ++i2) { - const value = values[i2]; - assert2(value !== void 0, "Cannot call falsy with undefined"); - obj.$_terms.falsy.add(value); - } - return obj; - } - }, - sensitive: { - method(enabled2 = true) { - return this.$_setFlag("sensitive", enabled2); - } - } - }, - cast: { - number: { - from: internals.isBool, - to(value, helpers) { - return value ? 1 : 0; + } + this.subscriptionSet.add(contractID); + esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { + added: [contractID], + removed: [] + }); + } + if (!processingErrored) { + esm_default("okTurtles.events/emit", hash3, contractID, message); + esm_default("okTurtles.events/emit", EVENT_HANDLED, contractID, message); + } + } +}; +var notImplemented = (v2) => { + throw new Error(`chelonia: action not implemented to handle: ${JSON.stringify(v2)}.`); +}; +init_signedData(); +init_esm(); +var wallBase = Date.now(); +var monotonicBase = performance.now(); +var resyncTimeout; +var watchdog; +var syncServerTime = async function() { + const startTime = performance.now(); + const time3 = await this.config.fetch(`${this.config.connectionURL}/time`, { + signal: this.abortController.signal + }); + const requestTimeElapsed = performance.now(); + if (requestTimeElapsed - startTime > 8e3) { + throw new Error("Error fetching server time: request took too long"); + } + if (!time3.ok) + throw new Error("Error fetching server time"); + const serverTime = new Date(await time3.text()).valueOf(); + if (Number.isNaN(serverTime)) + throw new Error("Unable to parse server time"); + const newMonotonicBase = performance.now(); + wallBase = serverTime + (requestTimeElapsed - startTime) / 2 + // Also take into account the time elapsed between `requestTimeElapsed` + // and this line (which should be very little) + (newMonotonicBase - requestTimeElapsed); + monotonicBase = newMonotonicBase; +}; +var time_sync_default = esm_default("sbp/selectors/register", { + "chelonia/private/startClockSync": function() { + if (resyncTimeout !== void 0) { + throw new Error("chelonia/private/startClockSync has already been called"); + } + const resync = (delay2 = 3e5) => { + if (resyncTimeout !== null) + return; + const timeout = setTimeout(() => { + syncServerTime.call(this).then(() => { + if (resyncTimeout === timeout) + resyncTimeout = null; + resync(); + }).catch((e2) => { + if (resyncTimeout === timeout) { + resyncTimeout = null; + console.error("Error re-syncing server time; will re-attempt in 5s", e2); + setTimeout(() => resync(0), 5e3); + } else { + console.error("Error re-syncing server time; another attempt is in progress", e2); } + }); + }, delay2); + resyncTimeout = timeout; + }; + let wallLast = Date.now(); + let monotonicLast = performance.now(); + watchdog = setInterval(() => { + const wallNow = Date.now(); + const monotonicNow = performance.now(); + const difference2 = Math.abs(Math.abs(wallNow - wallLast) - Math.abs(monotonicNow - monotonicLast)); + if (difference2 > 10) { + if (resyncTimeout != null) + clearTimeout(resyncTimeout); + resyncTimeout = null; + resync(0); + } + wallLast = wallNow; + monotonicLast = monotonicNow; + }, 1e4); + resyncTimeout = null; + resync(0); + }, + "chelonia/private/stopClockSync": () => { + if (resyncTimeout !== void 0) { + if (watchdog != null) + clearInterval(watchdog); + if (resyncTimeout != null) + clearTimeout(resyncTimeout); + watchdog = void 0; + resyncTimeout = void 0; + } + }, + // Get an estimate of the server's current time based on the time elapsed as + // measured locally (using a monotonic clock), which is used as an offset, and + // a previously retrieved server time. The time value is returned as a UNIX + // _millisecond_ timestamp (milliseconds since 1 Jan 1970 00:00:00 UTC) + "chelonia/time": function() { + const monotonicNow = performance.now(); + const wallNow = wallBase - monotonicBase + monotonicNow; + return Math.round(wallNow); + } +}); +var ACTION_REGEX = /^((([\w.]+)\/([^/]+))(?:\/(?:([^/]+)\/)?)?)\w*/; +var chelonia_default = esm_default("sbp/selectors/register", { + // https://www.wordnik.com/words/chelonia + // https://gitlab.okturtles.org/okturtles/group-income/-/wikis/E2E-Protocol/Framework.md#alt-names + "chelonia/_init": function() { + this.config = { + // TODO: handle connecting to multiple servers for federation + get connectionURL() { + throw new Error("Invalid use of connectionURL before initialization"); + }, + // override! + set connectionURL(value) { + Object.defineProperty(this, "connectionURL", { value, writable: true }); + }, + stateSelector: "chelonia/private/state", + // override to integrate with, for example, vuex + contracts: { + defaults: { + modules: {}, + // '' => resolved module import + exposedGlobals: {}, + allowedDomains: [], + allowedSelectors: [], + preferSlim: false }, - string: { - from: internals.isBool, - to(value, helpers) { - return value ? "true" : "false"; - } - } + overrides: {}, + // override default values per-contract + manifests: {} + // override! contract names => manifest hashes + }, + whitelisted: (action) => !!this.whitelistedActions[action], + reactiveSet: (obj, key, value) => { + obj[key] = value; + return value; }, - manifest: { - build(obj, desc) { - if (desc.truthy) { - obj = obj.truthy(...desc.truthy); - } - if (desc.falsy) { - obj = obj.falsy(...desc.falsy); - } - return obj; - } + // example: set to Vue.set + fetch: (...args) => fetch(...args), + reactiveDel: (obj, key) => { + delete obj[key]; + }, + // acceptAllMessages disables checking whether we are expecting a message + // or not for processing + acceptAllMessages: false, + skipActionProcessing: false, + skipDecryptionAttempts: false, + skipSideEffects: false, + // Strict processing will treat all processing errors as unrecoverable + // This is useful, e.g., in the server, to prevent invalid messages from + // being added to the database + strictProcessing: false, + // Strict ordering will throw on past events with ChelErrorAlreadyProcessed + // Similarly, future events will not be reingested and will throw + // with ChelErrorDBBadPreviousHEAD + strictOrdering: false, + connectionOptions: { + maxRetries: Infinity, + // See https://github.com/okTurtles/group-income/issues/1183 + reconnectOnTimeout: true + // can be enabled since we are not doing auth via web sockets }, - messages: { - "boolean.base": "{{#label}} must be a boolean" + hooks: { + preHandleEvent: null, + // async (message: SPMessage) => {} + postHandleEvent: null, + // async (message: SPMessage) => {} + processError: null, + // (e: Error, message: SPMessage) => {} + sideEffectError: null, + // (e: Error, message: SPMessage) => {} + handleEventError: null, + // (e: Error, message: SPMessage) => {} + syncContractError: null, + // (e: Error, contractID: string) => {} + pubsubError: null + // (e:Error, socket: Socket) + }, + unwrapMaybeEncryptedData + }; + this._instance = /* @__PURE__ */ Object.create(null); + this.abortController = new AbortController(); + this.state = { + contracts: {}, + // contractIDs => { type, HEAD } (contracts we've subscribed to) + pending: [] + // prevents processing unexpected data from a malicious server + }; + this.manifestToContract = {}; + this.whitelistedActions = {}; + this.currentSyncs = /* @__PURE__ */ Object.create(null); + this.postSyncOperations = /* @__PURE__ */ Object.create(null); + this.sideEffectStacks = /* @__PURE__ */ Object.create(null); + this.sideEffectStack = (contractID) => { + let stack = this.sideEffectStacks[contractID]; + if (!stack) { + this.sideEffectStacks[contractID] = stack = []; + } + return stack; + }; + this.setPostSyncOp = (contractID, key, op) => { + this.postSyncOperations[contractID] = this.postSyncOperations[contractID] || /* @__PURE__ */ Object.create(null); + this.postSyncOperations[contractID][key] = op; + }; + const secretKeyGetter = (o2, p) => { + if (has(o2, p)) + return o2[p]; + const rootState = esm_default(this.config.stateSelector); + if (rootState?.secretKeys && has(rootState.secretKeys, p)) { + const key = deserializeKey(rootState.secretKeys[p]); + o2[p] = key; + return key; } + }; + const secretKeyList = (o2) => { + const rootState = esm_default(this.config.stateSelector); + const stateKeys = Object.keys(rootState?.secretKeys || {}); + return Array.from(/* @__PURE__ */ new Set([...Object.keys(o2), ...stateKeys])); + }; + this.transientSecretKeys = new Proxy(/* @__PURE__ */ Object.create(null), { + get: secretKeyGetter, + ownKeys: secretKeyList }); - } -}); -var require_date2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/date.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Any = require_any2(); - var Common = require_common3(); - var Template = require_template2(); - var internals = {}; - internals.isDate = function(value) { - return value instanceof Date; + this.ephemeralReferenceCount = /* @__PURE__ */ Object.create(null); + this.subscriptionSet = /* @__PURE__ */ new Set(); + this.pending = []; + }, + "chelonia/config": function() { + return { + ...cloneDeep(this.config), + fetch: this.config.fetch, + reactiveSet: this.config.reactiveSet, + reactiveDel: this.config.reactiveDel }; - module14.exports = Any.extend({ - type: "date", - coerce: { - from: ["number", "string"], - method(value, { schema }) { - return { value: internals.parse(value, schema._flags.format) || value }; - } - }, - validate(value, { schema, error: error2, prefs }) { - if (value instanceof Date && !isNaN(value.getTime())) { - return; - } - const format52 = schema._flags.format; - if (!prefs.convert || !format52 || typeof value !== "string") { - return { value, errors: error2("date.base") }; - } - return { value, errors: error2("date.format", { format: format52 }) }; - }, - rules: { - compare: { - method: false, - validate(value, helpers, { date: date3 }, { name, operator, args }) { - const to = date3 === "now" ? Date.now() : date3.getTime(); - if (Common.compare(value.getTime(), to, operator)) { - return value; - } - return helpers.error("date." + name, { limit: args.date, value }); - }, - args: [ - { - name: "date", - ref: true, - normalize: (date3) => { - return date3 === "now" ? date3 : internals.parse(date3); - }, - assert: (date3) => date3 !== null, - message: "must have a valid date format" - } - ] - }, - format: { - method(format52) { - assert2(["iso", "javascript", "unix"].includes(format52), "Unknown date format", format52); - return this.$_setFlag("format", format52); - } - }, - greater: { - method(date3) { - return this.$_addRule({ name: "greater", method: "compare", args: { date: date3 }, operator: ">" }); - } - }, - iso: { - method() { - return this.format("iso"); - } - }, - less: { - method(date3) { - return this.$_addRule({ name: "less", method: "compare", args: { date: date3 }, operator: "<" }); - } - }, - max: { - method(date3) { - return this.$_addRule({ name: "max", method: "compare", args: { date: date3 }, operator: "<=" }); - } - }, - min: { - method(date3) { - return this.$_addRule({ name: "min", method: "compare", args: { date: date3 }, operator: ">=" }); + }, + "chelonia/configure": async function(config2) { + merge2(this.config, config2); + Object.assign(this.config.hooks, config2.hooks || {}); + if (config2.contracts) { + Object.assign(this.config.contracts.defaults, config2.contracts.defaults || {}); + const manifests = this.config.contracts.manifests; + console.debug("[chelonia] preloading manifests:", Object.keys(manifests)); + for (const contractName in manifests) { + await esm_default("chelonia/private/loadManifest", contractName, manifests[contractName]); + } + } + if (has(config2, "skipDecryptionAttempts")) { + if (config2.skipDecryptionAttempts) { + this.config.unwrapMaybeEncryptedData = (data) => { + if (data == null) + return; + if (!isEncryptedData(data)) { + return { + encryptionKeyId: null, + data + }; } - }, - timestamp: { - method(type = "javascript") { - assert2(["javascript", "unix"].includes(type), '"type" must be one of "javascript, unix"'); - return this.format(type); + }; + } else { + this.config.unwrapMaybeEncryptedData = unwrapMaybeEncryptedData; + } + } + }, + "chelonia/reset": async function(newState, postCleanupFn) { + if (typeof newState === "function" && typeof postCleanupFn === "undefined") { + postCleanupFn = newState; + newState = void 0; + } + if (this.pubsub) { + esm_default("chelonia/private/stopClockSync"); + } + Object.keys(this.postSyncOperations).forEach((cID) => { + esm_default("chelonia/private/enqueuePostSyncOps", cID); + }); + await esm_default("chelonia/contract/waitPublish"); + await esm_default("chelonia/contract/wait"); + Object.keys(this.postSyncOperations).forEach((cID) => { + esm_default("chelonia/private/enqueuePostSyncOps", cID); + }); + await esm_default("chelonia/contract/waitPublish"); + await esm_default("chelonia/contract/wait"); + const result = await postCleanupFn?.(); + const rootState = esm_default(this.config.stateSelector); + this._instance = /* @__PURE__ */ Object.create(null); + this.abortController.abort(); + this.abortController = new AbortController(); + reactiveClearObject(rootState, this.config.reactiveDel); + this.config.reactiveSet(rootState, "contracts", /* @__PURE__ */ Object.create(null)); + clearObject(this.ephemeralReferenceCount); + this.pending.splice(0); + clearObject(this.currentSyncs); + clearObject(this.postSyncOperations); + clearObject(this.sideEffectStacks); + const removedContractIDs = Array.from(this.subscriptionSet); + this.subscriptionSet.clear(); + esm_default("chelonia/clearTransientSecretKeys"); + esm_default("okTurtles.events/emit", CHELONIA_RESET); + esm_default("okTurtles.events/emit", CONTRACTS_MODIFIED, Array.from(this.subscriptionSet), { + added: [], + removed: removedContractIDs + }); + if (this.pubsub) { + esm_default("chelonia/private/startClockSync"); + } + if (newState) { + Object.entries(newState).forEach(([key, value]) => { + this.config.reactiveSet(rootState, key, value); + }); + } + return result; + }, + "chelonia/storeSecretKeys": function(wkeys) { + const rootState = esm_default(this.config.stateSelector); + if (!rootState.secretKeys) { + this.config.reactiveSet(rootState, "secretKeys", /* @__PURE__ */ Object.create(null)); + } + let keys = wkeys.valueOf(); + if (!keys) + return; + if (!Array.isArray(keys)) + keys = [keys]; + keys.forEach(({ key, transient }) => { + if (!key) + return; + if (typeof key === "string") { + key = deserializeKey(key); + } + const id = keyId(key); + if (!has(this.transientSecretKeys, id)) { + this.transientSecretKeys[id] = key; + } + if (transient) + return; + if (!has(rootState.secretKeys, id)) { + this.config.reactiveSet(rootState.secretKeys, id, serializeKey(key, true)); + } + }); + }, + "chelonia/clearTransientSecretKeys": function(ids) { + if (Array.isArray(ids)) { + ids.forEach((id) => { + delete this.transientSecretKeys[id]; + }); + } else { + Object.keys(this.transientSecretKeys).forEach((id) => { + delete this.transientSecretKeys[id]; + }); + } + }, + "chelonia/haveSecretKey": function(keyId2, persistent) { + if (!persistent && has(this.transientSecretKeys, keyId2)) + return true; + const rootState = esm_default(this.config.stateSelector); + return !!rootState?.secretKeys && has(rootState.secretKeys, keyId2); + }, + "chelonia/contract/isResyncing": function(contractIDOrState) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + return !!contractIDOrState?._volatile?.dirty || !!contractIDOrState?._volatile?.resyncing; + }, + "chelonia/contract/hasKeyShareBeenRespondedBy": function(contractIDOrState, requestedToContractID, reference) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + const result = Object.values(contractIDOrState?._vm.authorizedKeys || {}).some((r) => { + return r?.meta?.keyRequest?.responded && r.meta.keyRequest.contractID === requestedToContractID && (!reference || r.meta.keyRequest.reference === reference); + }); + return result; + }, + "chelonia/contract/waitingForKeyShareTo": function(contractIDOrState, requestingContractID, reference) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + const result = contractIDOrState._volatile?.pendingKeyRequests?.filter((r) => { + return r && (!requestingContractID || r.contractID === requestingContractID) && (!reference || r.reference === reference); + })?.map(({ name }) => name); + if (!result?.length) + return null; + return result; + }, + "chelonia/contract/successfulKeySharesByContractID": function(contractIDOrState, requestingContractID) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + const keyShares = Object.values(contractIDOrState._vm.keyshares || {}); + if (!keyShares?.length) + return; + const result = /* @__PURE__ */ Object.create(null); + keyShares.forEach((kS) => { + if (!kS.success) + return; + if (requestingContractID && kS.contractID !== requestingContractID) + return; + if (!result[kS.contractID]) + result[kS.contractID] = []; + result[kS.contractID].push({ height: kS.height, hash: kS.hash }); + }); + Object.keys(result).forEach((cID) => { + result[cID].sort((a, b) => { + return b.height - a.height; + }); + }); + return result; + }, + "chelonia/contract/hasKeysToPerformOperation": function(contractIDOrState, operation) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + const op = operation !== "*" ? [operation] : operation; + return !!findSuitableSecretKeyId(contractIDOrState, op, ["sig"]); + }, + // Did sourceContractIDOrState receive an OP_KEY_SHARE to perform the given + // operation on contractIDOrState? + "chelonia/contract/receivedKeysToPerformOperation": function(sourceContractIDOrState, contractIDOrState, operation) { + const rootState = esm_default(this.config.stateSelector); + if (typeof sourceContractIDOrState === "string") { + sourceContractIDOrState = rootState[sourceContractIDOrState]; + } + if (typeof contractIDOrState === "string") { + contractIDOrState = rootState[contractIDOrState]; + } + const op = operation !== "*" ? [operation] : operation; + const keyId2 = findSuitableSecretKeyId(contractIDOrState, op, ["sig"]); + return sourceContractIDOrState?._vm?.sharedKeyIds?.some((sK) => sK.id === keyId2); + }, + "chelonia/contract/currentKeyIdByName": function(contractIDOrState, name, requireSecretKey) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + const currentKeyId = findKeyIdByName(contractIDOrState, name); + if (requireSecretKey && !esm_default("chelonia/haveSecretKey", currentKeyId)) { + return; + } + return currentKeyId; + }, + "chelonia/contract/foreignKeysByContractID": function(contractIDOrState, foreignContractID) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + return findForeignKeysByContractID(contractIDOrState, foreignContractID); + }, + "chelonia/contract/historicalKeyIdsByName": function(contractIDOrState, name) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + const currentKeyId = findKeyIdByName(contractIDOrState, name); + const revokedKeyIds = findRevokedKeyIdsByName(contractIDOrState, name); + return currentKeyId ? [currentKeyId, ...revokedKeyIds] : revokedKeyIds; + }, + "chelonia/contract/suitableSigningKey": function(contractIDOrState, permissions, purposes, ringLevel, allowedActions) { + if (typeof contractIDOrState === "string") { + const rootState = esm_default(this.config.stateSelector); + contractIDOrState = rootState[contractIDOrState]; + } + const keyId2 = findSuitableSecretKeyId(contractIDOrState, permissions, purposes, ringLevel, allowedActions); + return keyId2; + }, + "chelonia/contract/setPendingKeyRevocation": function(contractID, names) { + const rootState = esm_default(this.config.stateSelector); + const state = rootState[contractID]; + if (!state._volatile) + this.config.reactiveSet(state, "_volatile", /* @__PURE__ */ Object.create(null)); + if (!state._volatile.pendingKeyRevocations) { + this.config.reactiveSet(state._volatile, "pendingKeyRevocations", /* @__PURE__ */ Object.create(null)); + } + for (const name of names) { + const keyId2 = findKeyIdByName(state, name); + if (keyId2) { + this.config.reactiveSet(state._volatile.pendingKeyRevocations, keyId2, true); + } else { + console.warn("[setPendingKeyRevocation] Unable to find keyId for name", { + contractID, + name + }); + } + } + }, + "chelonia/shelterAuthorizationHeader"(contractID) { + return buildShelterAuthorizationHeader.call(this, contractID); + }, + // The purpose of the 'chelonia/crypto/*' selectors is so that they can be called + // from contracts without including the crypto code (i.e., importing crypto.js) + // This function takes a function as a parameter that returns a string + // It does not a string directly to prevent accidentally logging the value, + // which is a secret + "chelonia/crypto/keyId": (inKey) => { + return keyId(inKey.valueOf()); + }, + // TODO: allow connecting to multiple servers at once + "chelonia/connect": function(options2 = {}) { + if (!this.config.connectionURL) + throw new Error("config.connectionURL missing"); + if (!this.config.connectionOptions) + throw new Error("config.connectionOptions missing"); + if (this.pubsub) { + this.pubsub.destroy(); + } + let pubsubURL = this.config.connectionURL; + if (true) { + pubsubURL += `?debugID=${randomHexString(6)}`; + } + if (this.pubsub) { + esm_default("chelonia/private/stopClockSync"); + } + esm_default("chelonia/private/startClockSync"); + this.pubsub = createClient(pubsubURL, { + ...this.config.connectionOptions, + handlers: { + ...options2.handlers, + // Every time we get a REQUEST_TYPE.SUB response, which happens for + // 'new' subscriptions as well as every time the connection is reset + "subscription-succeeded": function(event) { + const { channelID } = event.detail; + if (this.subscriptionSet.has(channelID)) { + esm_default("chelonia/private/out/sync", channelID, { force: true }).catch((err) => { + console.warn(`[chelonia] Syncing contract ${channelID} failed: ${err.message}`); + }); } + options2.handlers?.["subscription-succeeded"]?.call(this, event); } }, - cast: { - number: { - from: internals.isDate, - to(value, helpers) { - return value.getTime(); - } - }, - string: { - from: internals.isDate, - to(value, { prefs }) { - return Template.date(value, prefs); + // Map message handlers to transparently handle encryption and signatures + messageHandlers: { + ...Object.fromEntries(Object.entries(options2.messageHandlers || {}).map(([k, v2]) => { + switch (k) { + case NOTIFICATION_TYPE.PUB: + return [ + k, + (msg) => { + if (!msg.channelID) { + console.info("[chelonia] Discarding pub event without channelID"); + return; + } + if (!this.subscriptionSet.has(msg.channelID)) { + console.info(`[chelonia] Discarding pub event for ${msg.channelID} because it's not in the current subscriptionSet`); + return; + } + esm_default("chelonia/queueInvocation", msg.channelID, () => { + v2.call(this.pubsub, parseEncryptedOrUnencryptedMessage(this, { + contractID: msg.channelID, + serializedData: msg.data + })); + }).catch((e2) => { + console.error(`[chelonia] Error processing pub event for ${msg.channelID}`, e2); + }); + } + ]; + case NOTIFICATION_TYPE.KV: + return [ + k, + (msg) => { + if (!msg.channelID || !msg.key) { + console.info("[chelonia] Discarding kv event without channelID or key"); + return; + } + if (!this.subscriptionSet.has(msg.channelID)) { + console.info(`[chelonia] Discarding kv event for ${msg.channelID} because it's not in the current subscriptionSet`); + return; + } + esm_default("chelonia/queueInvocation", msg.channelID, () => { + v2.call(this.pubsub, [ + msg.key, + parseEncryptedOrUnencryptedMessage(this, { + contractID: msg.channelID, + meta: msg.key, + serializedData: JSON.parse(Buffer6.from(msg.data).toString()) + }) + ]); + }).catch((e2) => { + console.error(`[chelonia] Error processing kv event for ${msg.channelID} and key ${msg.key}`, msg, e2); + }); + } + ]; + case NOTIFICATION_TYPE.DELETION: + return [ + k, + (msg) => v2.call(this.pubsub, msg.data) + ]; + default: + return [k, v2]; } + })), + [NOTIFICATION_TYPE.ENTRY](msg) { + const { contractID } = SPMessage.deserializeHEAD(msg.data); + esm_default("chelonia/private/in/enqueueHandleEvent", contractID, msg.data); } - }, - messages: { - "date.base": "{{#label}} must be a valid date", - "date.format": '{{#label}} must be in {msg("date.format." + #format) || #format} format', - "date.greater": "{{#label}} must be greater than {{:#limit}}", - "date.less": "{{#label}} must be less than {{:#limit}}", - "date.max": "{{#label}} must be less than or equal to {{:#limit}}", - "date.min": "{{#label}} must be greater than or equal to {{:#limit}}", - // Messages used in date.format - "date.format.iso": "ISO 8601 date", - "date.format.javascript": "timestamp or number of milliseconds", - "date.format.unix": "timestamp or number of seconds" } }); - internals.parse = function(value, format52) { - if (value instanceof Date) { - return value; - } - if (typeof value !== "string" && (isNaN(value) || !isFinite(value))) { - return null; - } - if (/^\s*$/.test(value)) { - return null; + if (!this.contractsModifiedListener) { + this.contractsModifiedListener = () => esm_default("chelonia/pubsub/update"); + esm_default("okTurtles.events/on", CONTRACTS_MODIFIED, this.contractsModifiedListener); + } + return this.pubsub; + }, + // This selector is defined primarily for ingesting web push notifications, + // although it can be used as a general-purpose API to process events received + // from other external sources that are not managed by Chelonia itself (i.e. sources + // other than the Chelonia-managed websocket connection and RESTful API). + "chelonia/handleEvent": async function(event) { + const { contractID } = SPMessage.deserializeHEAD(event); + return await esm_default("chelonia/private/in/enqueueHandleEvent", contractID, event); + }, + "chelonia/defineContract": function(contract) { + if (!ACTION_REGEX.exec(contract.name)) + throw new Error(`bad contract name: ${contract.name}`); + if (!contract.metadata) + contract.metadata = { validate() { + }, create: () => ({}) }; + if (!contract.getters) + contract.getters = {}; + contract.state = (contractID) => esm_default(this.config.stateSelector)[contractID]; + contract.manifest = this.defContractManifest; + contract.sbp = this.defContractSBP; + this.defContractSelectors = []; + this.defContract = contract; + this.defContractSelectors.push(...esm_default("sbp/selectors/register", { + // expose getters for Vuex integration and other conveniences + [`${contract.manifest}/${contract.name}/getters`]: () => contract.getters, + // 2 ways to cause sideEffects to happen: by defining a sideEffect function in the + // contract, or by calling /pushSideEffect w/async SBP call. Can also do both. + [`${contract.manifest}/${contract.name}/pushSideEffect`]: (contractID, asyncSbpCall) => { + const [sel] = asyncSbpCall; + if (sel.startsWith(contract.name + "/")) { + asyncSbpCall[0] = `${contract.manifest}/${sel}`; + } + this.sideEffectStack(contractID).push(asyncSbpCall); } - if (format52 === "iso") { - if (!Common.isIsoDate(value)) { - return null; + })); + for (const action in contract.actions) { + contractNameFromAction(action); + this.whitelistedActions[action] = true; + this.defContractSelectors.push(...esm_default("sbp/selectors/register", { + [`${contract.manifest}/${action}/process`]: async (message, state) => { + const { meta, data, contractID } = message; + state = state || contract.state(contractID); + const gProxy = gettersProxy(state, contract.getters); + await contract.metadata.validate(meta, { state, ...gProxy, contractID }); + await contract.actions[action].validate(data, { + state, + ...gProxy, + meta, + message, + contractID + }); + this.sideEffectStacks[contractID] = []; + await contract.actions[action].process(message, { state, ...gProxy }); + }, + // 'mutation' is an object that's similar to 'message', but not identical + [`${contract.manifest}/${action}/sideEffect`]: async (mutation, state) => { + if (contract.actions[action].sideEffect) { + state = state || contract.state(mutation.contractID); + if (!state) { + console.warn(`[${contract.manifest}/${action}/sideEffect]: Skipping side-effect since there is no contract state for contract ${mutation.contractID}`); + return; + } + const stateCopy = cloneDeep(state); + const gProxy = gettersProxy(stateCopy, contract.getters); + await contract.actions[action].sideEffect(mutation, { state: stateCopy, ...gProxy }); + } + const sideEffects = this.sideEffectStack(mutation.contractID); + while (sideEffects.length > 0) { + const sideEffect = sideEffects.shift(); + try { + await contract.sbp(...sideEffect); + } catch (e_) { + const e2 = e_; + console.error(`[chelonia] ERROR: '${e2.name}' ${e2.message}, for pushed sideEffect of ${mutation.description}:`, sideEffect); + this.sideEffectStacks[mutation.contractID] = []; + throw e2; + } + } } - return internals.date(value.toString()); + })); + } + for (const method in contract.methods) { + this.defContractSelectors.push(...esm_default("sbp/selectors/register", { + [`${contract.manifest}/${method}`]: contract.methods[method] + })); + } + esm_default("okTurtles.events/emit", CONTRACT_REGISTERED, contract); + }, + "chelonia/queueInvocation": (contractID, sbpInvocation) => { + return esm_default("chelonia/private/queueEvent", contractID, ["chelonia/private/noop"]).then(() => esm_default("chelonia/private/queueEvent", "public:" + contractID, sbpInvocation)); + }, + "chelonia/begin": async (...invocations) => { + for (const invocation of invocations) { + await esm_default(...invocation); + } + }, + // call this manually to resubscribe/unsubscribe from contracts as needed + // if you are using a custom stateSelector and reload the state (e.g. upon login) + "chelonia/pubsub/update": function() { + const client = this.pubsub; + const subscribedIDs = [...client.subscriptionSet]; + const currentIDs = Array.from(this.subscriptionSet); + const leaveSubscribed = intersection2(subscribedIDs, currentIDs); + const toUnsubscribe = difference(subscribedIDs, leaveSubscribed); + const toSubscribe = difference(currentIDs, leaveSubscribed); + try { + for (const contractID of toUnsubscribe) { + client.unsub(contractID); } - const original = value; - if (typeof value === "string" && /^[+-]?\d+(\.\d+)?$/.test(value)) { - value = parseFloat(value); + for (const contractID of toSubscribe) { + client.sub(contractID); } - if (format52) { - if (format52 === "javascript") { - return internals.date(1 * value); - } - if (format52 === "unix") { - return internals.date(1e3 * value); - } - if (typeof original === "string") { - return null; + } catch (e2) { + console.error(`[chelonia] pubsub/update: error ${e2.name}: ${e2.message}`, { toUnsubscribe, toSubscribe }, e2); + this.config.hooks.pubsubError?.(e2, client); + } + }, + // resolves when all pending actions for these contractID(s) finish + "chelonia/contract/wait": function(contractIDs) { + const listOfIds = contractIDs ? typeof contractIDs === "string" ? [contractIDs] : contractIDs : Object.keys(esm_default(this.config.stateSelector).contracts); + return Promise.all(listOfIds.flatMap((cID) => { + return esm_default("chelonia/queueInvocation", cID, ["chelonia/private/noop"]); + })); + }, + // resolves when all pending *writes* for these contractID(s) finish + "chelonia/contract/waitPublish": function(contractIDs) { + const listOfIds = contractIDs ? typeof contractIDs === "string" ? [contractIDs] : contractIDs : Object.keys(esm_default(this.config.stateSelector).contracts); + return Promise.all(listOfIds.flatMap((cID) => { + return esm_default("chelonia/private/queueEvent", `publish:${cID}`, ["chelonia/private/noop"]); + })); + }, + // 'chelonia/contract' - selectors related to injecting remote data and monitoring contracts + // TODO: add an optional parameter to "retain" the contract (see #828) + // eslint-disable-next-line require-await + "chelonia/contract/sync": async function(contractIDs, params) { + const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; + listOfIds.forEach((id) => { + if (checkCanBeGarbageCollected.call(this, id)) { + if (process.env.CI) { + Promise.reject(new Error("[chelonia] Missing reference count for contract " + id)); } + console.error("[chelonia] Missing reference count for contract " + id); + throw new Error("Missing reference count for contract"); } - return internals.date(value); - }; - internals.date = function(value) { - const date3 = new Date(value); - if (!isNaN(date3.getTime())) { - return date3; - } - return null; - }; - } -}); -var require_keys2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/keys.js"(exports2, module14) { - "use strict"; - var { applyToDefaults, assert: assert2, clone: Clone } = require_lib(); - var Topo = require_lib8(); - var Any = require_any2(); - var Common = require_common3(); - var Compile = require_compile2(); - var Errors = require_errors3(); - var Ref = require_ref2(); - var Template = require_template2(); - var internals = { - renameDefaults: { - alias: false, - // Keep old value in place - multiple: false, - // Allow renaming multiple keys into the same target - override: false - // Overrides an existing key + }); + return esm_default("chelonia/private/out/sync", listOfIds, { ...params, force: true }); + }, + "chelonia/contract/isSyncing": function(contractID, { firstSync = false } = {}) { + const isSyncing = !!this.currentSyncs[contractID]; + return firstSync ? isSyncing && this.currentSyncs[contractID].firstSync : isSyncing; + }, + "chelonia/contract/currentSyncs": function() { + return Object.keys(this.currentSyncs); + }, + // Because `/remove` is done asynchronously and a contract might be removed + // much later than when the call to remove was made, an optional callback + // can be passed to verify whether to proceed with removal. This is used as + // part of the `/release` mechanism to prevent removing contracts that have + // acquired new references since the call to `/remove`. + "chelonia/contract/remove": function(contractIDs, { confirmRemovalCallback, permanent } = {}) { + const rootState = esm_default(this.config.stateSelector); + const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; + return Promise.all(listOfIds.map((contractID) => { + if (!rootState?.contracts?.[contractID]) { + return void 0; } - }; - module14.exports = Any.extend({ - type: "_keys", - properties: { - typeof: "object" - }, - flags: { - unknown: { default: void 0 } - }, - terms: { - dependencies: { init: null }, - keys: { init: null, manifest: { mapped: { from: "schema", to: "key" } } }, - patterns: { init: null }, - renames: { init: null } - }, - args(schema, keys) { - return schema.keys(keys); - }, - validate(value, { schema, error: error2, state, prefs }) { - if (!value || typeof value !== schema.$_property("typeof") || Array.isArray(value)) { - return { value, errors: error2("object.base", { type: schema.$_property("typeof") }) }; - } - if (!schema.$_terms.renames && !schema.$_terms.dependencies && !schema.$_terms.keys && // null allows any keys - !schema.$_terms.patterns && !schema.$_terms.externals) { + return esm_default("chelonia/private/queueEvent", contractID, () => { + if (confirmRemovalCallback && !confirmRemovalCallback(contractID)) { return; } - value = internals.clone(value, prefs); - const errors = []; - if (schema.$_terms.renames && !internals.rename(schema, value, state, prefs, errors)) { - return { value, errors }; - } - if (!schema.$_terms.keys && // null allows any keys - !schema.$_terms.patterns && !schema.$_terms.dependencies) { - return { value, errors }; - } - const unprocessed = new Set(Object.keys(value)); - if (schema.$_terms.keys) { - const ancestors = [value, ...state.ancestors]; - for (const child of schema.$_terms.keys) { - const key = child.key; - const item = value[key]; - unprocessed.delete(key); - const localState = state.localize([...state.path, key], ancestors, child); - const result = child.schema.$_validate(item, localState, prefs); - if (result.errors) { - if (prefs.abortEarly) { - return { value, errors: result.errors }; - } - if (result.value !== void 0) { - value[key] = result.value; - } - errors.push(...result.errors); - } else if (child.schema._flags.result === "strip" || result.value === void 0 && item !== void 0) { - delete value[key]; - } else if (result.value !== void 0) { - value[key] = result.value; - } - } - } - if (unprocessed.size || schema._flags._hasPatternMatch) { - const early = internals.unknown(schema, value, unprocessed, errors, state, prefs); - if (early) { - return early; + const rootState2 = esm_default(this.config.stateSelector); + const fkContractIDs = Array.from(new Set(Object.values(rootState2[contractID]?._vm?.authorizedKeys ?? {}).filter((k) => { + return !!k.foreignKey; + }).map((k) => { + try { + const fkUrl = new URL(k.foreignKey); + return fkUrl.pathname; + } catch { + return void 0; } + }).filter(Boolean))); + esm_default("chelonia/private/removeImmediately", contractID, { permanent }); + if (fkContractIDs.length) { + esm_default("chelonia/contract/release", fkContractIDs, { try: true }).catch((e2) => { + console.error("[chelonia] Error attempting to release foreign key contracts", e2); + }); } - if (schema.$_terms.dependencies) { - for (const dep of schema.$_terms.dependencies) { - if (dep.key !== null && internals.isPresent(dep.options)(dep.key.resolve(value, state, prefs, null, { shadow: false })) === false) { - continue; - } - const failed = internals.dependencies[dep.rel](schema, dep, value, state, prefs); - if (failed) { - const report = schema.$_createError(failed.code, value, failed.context, state, prefs); - if (prefs.abortEarly) { - return { value, errors: report }; - } - errors.push(report); - } - } + }); + })); + }, + "chelonia/contract/retain": async function(contractIDs, params) { + const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; + const rootState = esm_default(this.config.stateSelector); + if (listOfIds.length === 0) + return Promise.resolve(); + const checkIfDeleted = (id) => { + if (rootState.contracts[id] === null) { + console.error("[chelonia/contract/retain] Called /retain on permanently deleted contract.", id); + throw new ChelErrorResourceGone("Unable to retain permanently deleted contract " + id); + } + }; + if (!params?.ephemeral) { + listOfIds.forEach((id) => { + checkIfDeleted(id); + if (!has(rootState.contracts, id)) { + this.config.reactiveSet(rootState.contracts, id, /* @__PURE__ */ Object.create(null)); + } + this.config.reactiveSet(rootState.contracts[id], "references", (rootState.contracts[id].references ?? 0) + 1); + }); + } else { + listOfIds.forEach((id) => { + checkIfDeleted(id); + if (!has(this.ephemeralReferenceCount, id)) { + this.ephemeralReferenceCount[id] = 1; + } else { + this.ephemeralReferenceCount[id] = this.ephemeralReferenceCount[id] + 1; } - return { value, errors }; - }, - rules: { - and: { - method(...peers) { - Common.verifyFlat(peers, "and"); - return internals.dependency(this, "and", null, peers); - } - }, - append: { - method(schema) { - if (schema === null || schema === void 0 || Object.keys(schema).length === 0) { - return this; - } - return this.keys(schema); - } - }, - assert: { - method(subject, schema, message) { - if (!Template.isTemplate(subject)) { - subject = Compile.ref(subject); - } - assert2(message === void 0 || typeof message === "string", "Message must be a string"); - schema = this.$_compile(schema, { appendPath: true }); - const obj = this.$_addRule({ name: "assert", args: { subject, schema, message } }); - obj.$_mutateRegister(subject); - obj.$_mutateRegister(schema); - return obj; - }, - validate(value, { error: error2, prefs, state }, { subject, schema, message }) { - const about = subject.resolve(value, state, prefs); - const path8 = Ref.isRef(subject) ? subject.absolute(state) : []; - if (schema.$_match(about, state.localize(path8, [value, ...state.ancestors], schema), prefs)) { - return value; - } - return error2("object.assert", { subject, message }); - }, - args: ["subject", "schema", "message"], - multi: true - }, - instance: { - method(constructor, name) { - assert2(typeof constructor === "function", "constructor must be a function"); - name = name || constructor.name; - return this.$_addRule({ name: "instance", args: { constructor, name } }); - }, - validate(value, helpers, { constructor, name }) { - if (value instanceof constructor) { - return value; - } - return helpers.error("object.instance", { type: name, value }); - }, - args: ["constructor", "name"] - }, - keys: { - method(schema) { - assert2(schema === void 0 || typeof schema === "object", "Object schema must be a valid object"); - assert2(!Common.isSchema(schema), "Object schema cannot be a joi schema"); - const obj = this.clone(); - if (!schema) { - obj.$_terms.keys = null; - } else if (!Object.keys(schema).length) { - obj.$_terms.keys = new internals.Keys(); - } else { - obj.$_terms.keys = obj.$_terms.keys ? obj.$_terms.keys.filter((child) => !schema.hasOwnProperty(child.key)) : new internals.Keys(); - for (const key in schema) { - Common.tryWithPath(() => obj.$_terms.keys.push({ key, schema: this.$_compile(schema[key]) }), key); - } - } - return obj.$_mutateRebuild(); - } - }, - length: { - method(limit) { - return this.$_addRule({ name: "length", args: { limit }, operator: "=" }); - }, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(Object.keys(value).length, limit, operator)) { - return value; - } - return helpers.error("object." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - } - ] - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "length", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "length", args: { limit }, operator: ">=" }); - } - }, - nand: { - method(...peers) { - Common.verifyFlat(peers, "nand"); - return internals.dependency(this, "nand", null, peers); - } - }, - or: { - method(...peers) { - Common.verifyFlat(peers, "or"); - return internals.dependency(this, "or", null, peers); - } - }, - oxor: { - method(...peers) { - return internals.dependency(this, "oxor", null, peers); + }); + } + return await esm_default("chelonia/private/out/sync", listOfIds); + }, + // the `try` parameter does not affect (ephemeral or persistent) reference + // counts, but rather removes a contract if the reference count is zero + // and the contract isn't being monitored for foreign keys. This parameter + // is meant mostly for internal chelonia use, so that removing or releasing + // a contract can also remove other contracts that this first contract + // was monitoring. + "chelonia/contract/release": async function(contractIDs, params) { + const listOfIds = typeof contractIDs === "string" ? [contractIDs] : contractIDs; + const rootState = esm_default(this.config.stateSelector); + if (!params?.try) { + if (!params?.ephemeral) { + listOfIds.forEach((id) => { + if (rootState.contracts[id] === null) { + console.warn("[chelonia/contract/release] Called /release on permanently deleted contract. This has no effect.", id); + return; } - }, - pattern: { - method(pattern, schema, options2 = {}) { - const isRegExp = pattern instanceof RegExp; - if (!isRegExp) { - pattern = this.$_compile(pattern, { appendPath: true }); - } - assert2(schema !== void 0, "Invalid rule"); - Common.assertOptions(options2, ["fallthrough", "matches"]); - if (isRegExp) { - assert2(!pattern.flags.includes("g") && !pattern.flags.includes("y"), "pattern should not use global or sticky mode"); - } - schema = this.$_compile(schema, { appendPath: true }); - const obj = this.clone(); - obj.$_terms.patterns = obj.$_terms.patterns || []; - const config2 = { [isRegExp ? "regex" : "schema"]: pattern, rule: schema }; - if (options2.matches) { - config2.matches = this.$_compile(options2.matches); - if (config2.matches.type !== "array") { - config2.matches = config2.matches.$_root.array().items(config2.matches); + if (has(rootState.contracts, id) && has(rootState.contracts[id], "references")) { + const current = rootState.contracts[id].references; + if (current === 0) { + console.error("[chelonia/contract/release] Invalid negative reference count for", id); + if (process.env.CI) { + Promise.reject(new Error("Invalid negative reference count: " + id)); } - obj.$_mutateRegister(config2.matches); - obj.$_setFlag("_hasPatternMatch", true, { clone: false }); + throw new Error("Invalid negative reference count"); } - if (options2.fallthrough) { - config2.fallthrough = true; + if (current <= 1) { + this.config.reactiveDel(rootState.contracts[id], "references"); + } else { + this.config.reactiveSet(rootState.contracts[id], "references", current - 1); } - obj.$_terms.patterns.push(config2); - obj.$_mutateRegister(schema); - return obj; - } - }, - ref: { - method() { - return this.$_addRule("ref"); - }, - validate(value, helpers) { - if (Ref.isRef(value)) { - return value; + } else { + console.error("[chelonia/contract/release] Invalid negative reference count for", id); + if (process.env.CI) { + Promise.reject(new Error("Invalid negative reference count: " + id)); } - return helpers.error("object.refType", { value }); + throw new Error("Invalid negative reference count"); } - }, - regex: { - method() { - return this.$_addRule("regex"); - }, - validate(value, helpers) { - if (value instanceof RegExp) { - return value; - } - return helpers.error("object.regex", { value }); + }); + } else { + listOfIds.forEach((id) => { + if (rootState.contracts[id] === null) { + console.warn("[chelonia/contract/release] Called /release on permanently deleted contract. This has no effect.", id); + return; } - }, - rename: { - method(from3, to, options2 = {}) { - assert2(typeof from3 === "string" || from3 instanceof RegExp, "Rename missing the from argument"); - assert2(typeof to === "string" || to instanceof Template, "Invalid rename to argument"); - assert2(to !== from3, "Cannot rename key to same name:", from3); - Common.assertOptions(options2, ["alias", "ignoreUndefined", "override", "multiple"]); - const obj = this.clone(); - obj.$_terms.renames = obj.$_terms.renames || []; - for (const rename of obj.$_terms.renames) { - assert2(rename.from !== from3, "Cannot rename the same key multiple times"); - } - if (to instanceof Template) { - obj.$_mutateRegister(to); + if (has(this.ephemeralReferenceCount, id)) { + const current = this.ephemeralReferenceCount[id] ?? 0; + if (current <= 1) { + delete this.ephemeralReferenceCount[id]; + } else { + this.ephemeralReferenceCount[id] = current - 1; } - obj.$_terms.renames.push({ - from: from3, - to, - options: applyToDefaults(internals.renameDefaults, options2) - }); - return obj; - } - }, - schema: { - method(type = "any") { - return this.$_addRule({ name: "schema", args: { type } }); - }, - validate(value, helpers, { type }) { - if (Common.isSchema(value) && (type === "any" || value.type === type)) { - return value; + } else { + console.error("[chelonia/contract/release] Invalid negative ephemeral reference count for", id); + if (process.env.CI) { + Promise.reject(new Error("Invalid negative ephemeral reference count: " + id)); } - return helpers.error("object.schema", { type }); - } - }, - unknown: { - method(allow) { - return this.$_setFlag("unknown", allow !== false); - } - }, - with: { - method(key, peers, options2 = {}) { - return internals.dependency(this, "with", key, peers, options2); - } - }, - without: { - method(key, peers, options2 = {}) { - return internals.dependency(this, "without", key, peers, options2); - } - }, - xor: { - method(...peers) { - Common.verifyFlat(peers, "xor"); - return internals.dependency(this, "xor", null, peers); + throw new Error("Invalid negative ephemeral reference count"); } + }); + } + } + const boundCheckCanBeGarbageCollected = checkCanBeGarbageCollected.bind(this); + const idsToRemove = listOfIds.filter(boundCheckCanBeGarbageCollected); + return idsToRemove.length ? await esm_default("chelonia/contract/remove", idsToRemove, { + confirmRemovalCallback: boundCheckCanBeGarbageCollected + }) : void 0; + }, + "chelonia/contract/disconnect": async function(contractID, contractIDToDisconnect) { + const state = esm_default(this.config.stateSelector); + const contractState = state[contractID]; + const keyIds = Object.values(contractState._vm.authorizedKeys).filter((k) => { + return k._notAfterHeight == null && k.meta?.keyRequest?.contractID === contractIDToDisconnect; + }).map((k) => k.id); + if (!keyIds.length) + return; + return await esm_default("chelonia/out/keyDel", { + contractID, + contractName: contractState._vm.type, + data: keyIds, + signingKeyId: findSuitableSecretKeyId(contractState, [SPMessage.OP_KEY_DEL], ["sig"]) + }); + }, + "chelonia/in/processMessage": function(messageOrRawMessage, state) { + const stateCopy = cloneDeep(state); + const message = typeof messageOrRawMessage === "string" ? SPMessage.deserialize(messageOrRawMessage, this.transientSecretKeys, stateCopy, this.config.unwrapMaybeEncryptedData) : messageOrRawMessage; + return esm_default("chelonia/private/in/processMessage", message, stateCopy).then(() => stateCopy).catch((e2) => { + console.warn(`chelonia/in/processMessage: reverting mutation ${message.description()}: ${message.serialize()}`, e2); + return state; + }); + }, + "chelonia/out/fetchResource": async function(cid, { code: code2 } = {}) { + const parsedCID = parseCID(cid); + if (code2 != null) { + if (parsedCID.code !== code2) { + throw new Error(`Invalid CID content type. Expected ${code2}, got ${parsedCID.code}`); + } + } + const local = await esm_default("chelonia.db/get", cid); + if (local != null) + return local; + const url2 = `${this.config.connectionURL}/file/${cid}`; + const data = await this.config.fetch(url2, { signal: this.abortController.signal }).then(handleFetchResult("text")); + const ourHash = createCID(data, parsedCID.code); + if (ourHash !== cid) { + throw new Error(`expected hash ${cid}. Got: ${ourHash}`); + } + await esm_default("chelonia.db/set", cid, data); + return data; + }, + "chelonia/out/latestHEADInfo": function(contractID) { + return this.config.fetch(`${this.config.connectionURL}/latestHEADinfo/${contractID}`, { + cache: "no-store", + signal: this.abortController.signal + }).then(handleFetchResult("json")); + }, + "chelonia/out/deserializedHEAD": async function(hash3, { contractID } = {}) { + const message = await esm_default("chelonia/out/fetchResource", hash3, { + code: multicodes.SHELTER_CONTRACT_DATA + }); + const deserializedHEAD = SPMessage.deserializeHEAD(message); + if (contractID && deserializedHEAD.contractID !== contractID) { + throw new Error("chelonia/out/deserializedHEAD: Mismatched contract ID"); + } + return deserializedHEAD; + }, + "chelonia/out/eventsAfter": eventsAfter, + "chelonia/out/eventsBefore": function(contractID, { beforeHeight, limit, stream }) { + if (limit <= 0) { + console.error('[chelonia] invalid params error: "limit" needs to be positive integer'); + } + const offset = Math.max(0, beforeHeight - limit + 1); + const eventsAfterLimit = Math.min(beforeHeight + 1, limit); + return esm_default("chelonia/out/eventsAfter", contractID, { + sinceHeight: offset, + limit: eventsAfterLimit, + stream + }); + }, + "chelonia/out/eventsBetween": function(contractID, { startHash, endHeight = Number.POSITIVE_INFINITY, offset = 0, limit = 0, stream = true }) { + if (offset < 0) { + console.error('[chelonia] invalid params error: "offset" needs to be positive integer or zero'); + return; + } + let reader; + const s = new ReadableStream({ + start: async (controller) => { + const deserializedHEAD = await esm_default("chelonia/out/deserializedHEAD", startHash, { contractID }); + const startOffset = Math.max(0, deserializedHEAD.head.height - offset); + const ourLimit = limit ? Math.min(endHeight - startOffset + 1, limit) : endHeight - startOffset + 1; + if (ourLimit < 1) { + controller.close(); + return; } + reader = esm_default("chelonia/out/eventsAfter", contractID, { + sinceHeight: startOffset, + limit: ourLimit + }).getReader(); }, - overrides: { - default(value, options2) { - if (value === void 0) { - value = Common.symbols.deepDefault; - } - return this.$_parent("default", value, options2); - }, - isAsync() { - if (this.$_terms.externals?.length) { - return true; - } - if (this.$_terms.keys?.length) { - for (const key of this.$_terms.keys) { - if (key.schema.isAsync()) { - return true; - } - } + async pull(controller) { + const { done, value } = await reader.read(); + if (done) { + controller.close(); + } else { + controller.enqueue(value); + } + } + }); + if (stream) + return s; + return collectEventStream(s); + }, + "chelonia/rootState": function() { + return esm_default(this.config.stateSelector); + }, + "chelonia/latestContractState": async function(contractID, options2 = { forceSync: false }) { + const rootState = esm_default(this.config.stateSelector); + if (rootState.contracts[contractID] === null) { + throw new ChelErrorResourceGone("Permanently deleted contract " + contractID); + } + if (!options2.forceSync && rootState[contractID] && Object.keys(rootState[contractID]).some((x3) => x3 !== "_volatile")) { + return cloneDeep(rootState[contractID]); + } + let state = /* @__PURE__ */ Object.create(null); + let contractName = rootState.contracts[contractID]?.type; + const eventsStream = esm_default("chelonia/out/eventsAfter", contractID, { + sinceHeight: 0, + sinceHash: contractID + }); + const eventsStreamReader = eventsStream.getReader(); + if (rootState[contractID]) + state._volatile = rootState[contractID]._volatile; + for (; ; ) { + const { value: event, done } = await eventsStreamReader.read(); + if (done) + return state; + const stateCopy = cloneDeep(state); + try { + await esm_default("chelonia/private/in/processMessage", SPMessage.deserialize(event, this.transientSecretKeys, state, this.config.unwrapMaybeEncryptedData), state, void 0, contractName); + if (!contractName && state._vm) { + contractName = state._vm.type; + } + } catch (e2) { + console.warn(`[chelonia] latestContractState: '${e2.name}': ${e2.message} processing:`, event, e2.stack); + if (e2 instanceof ChelErrorUnrecoverable) + throw e2; + state = stateCopy; + } + } + }, + "chelonia/contract/state": function(contractID, height) { + const state = esm_default(this.config.stateSelector)[contractID]; + const stateCopy = state && cloneDeep(state); + if (stateCopy?._vm && height != null) { + Object.keys(stateCopy._vm.authorizedKeys).forEach((keyId2) => { + if (stateCopy._vm.authorizedKeys[keyId2]._notBeforeHeight > height) { + delete stateCopy._vm.authorizedKeys[keyId2]; + } + }); + } + return stateCopy; + }, + "chelonia/contract/fullState": function(contractID) { + const rootState = esm_default(this.config.stateSelector); + if (Array.isArray(contractID)) { + return Object.fromEntries(contractID.map((contractID2) => { + return [ + contractID2, + { + contractState: rootState[contractID2], + cheloniaState: rootState.contracts[contractID2] } - if (this.$_terms.patterns?.length) { - for (const pattern of this.$_terms.patterns) { - if (pattern.rule.isAsync()) { - return true; + ]; + })); + } + return { + contractState: rootState[contractID], + cheloniaState: rootState.contracts[contractID] + }; + }, + // 'chelonia/out' - selectors that send data out to the server + "chelonia/out/registerContract": async function(params) { + const { contractName, keys, hooks, publishOptions, signingKeyId, actionSigningKeyId, actionEncryptionKeyId } = params; + const manifestHash = this.config.contracts.manifests[contractName]; + const contractInfo = this.manifestToContract[manifestHash]; + if (!contractInfo) + throw new Error(`contract not defined: ${contractName}`); + const signingKey = this.transientSecretKeys[signingKeyId]; + if (!signingKey) + throw new Error(`Signing key ${signingKeyId} is not defined`); + const payload = { + type: contractName, + keys + }; + const contractMsg = SPMessage.createV1_0({ + contractID: null, + height: 0, + op: [ + SPMessage.OP_CONTRACT, + signedOutgoingDataWithRawKey(signingKey, payload) + ], + manifest: manifestHash + }); + const contractID = contractMsg.hash(); + await esm_default("chelonia/private/out/publishEvent", contractMsg, params.namespaceRegistration ? { + ...publishOptions, + headers: { + ...publishOptions?.headers, + "shelter-namespace-registration": params.namespaceRegistration + } + } : publishOptions, hooks && { + prepublish: hooks.prepublishContract, + postpublish: hooks.postpublishContract + }); + await esm_default("chelonia/private/out/sync", contractID); + const msg = await esm_default(actionEncryptionKeyId ? "chelonia/out/actionEncrypted" : "chelonia/out/actionUnencrypted", { + action: contractName, + contractID, + data: params.data, + signingKeyId: actionSigningKeyId ?? signingKeyId, + encryptionKeyId: actionEncryptionKeyId, + hooks, + publishOptions + }); + return msg; + }, + "chelonia/out/ownResources": async function(contractID) { + if (!contractID) { + throw new TypeError("A contract ID must be provided"); + } + const response = await this.config.fetch(`${this.config.connectionURL}/ownResources`, { + method: "GET", + signal: this.abortController.signal, + headers: new Headers([ + ["authorization", buildShelterAuthorizationHeader.call(this, contractID)] + ]) + }); + if (!response.ok) { + console.error("Unable to fetch own resources", contractID, response.status); + throw new Error(`Unable to fetch own resources for ${contractID}: ${response.status}`); + } + return response.json(); + }, + "chelonia/out/deleteContract": async function(contractID, credentials = {}) { + if (!contractID) { + throw new TypeError("A contract ID must be provided"); + } + if (!Array.isArray(contractID)) + contractID = [contractID]; + return await Promise.allSettled(contractID.map(async (cid) => { + const hasCredential = has(credentials, cid); + const hasToken = has(credentials[cid], "token") && credentials[cid].token; + const hasBillableContractID = has(credentials[cid], "billableContractID") && credentials[cid].billableContractID; + if (!hasCredential || hasToken === hasBillableContractID) { + throw new TypeError(`Either a token or a billable contract ID must be provided for ${cid}`); + } + const response = await this.config.fetch(`${this.config.connectionURL}/deleteContract/${cid}`, { + method: "POST", + signal: this.abortController.signal, + headers: new Headers([ + [ + "authorization", + hasToken ? `bearer ${credentials[cid].token.valueOf()}` : buildShelterAuthorizationHeader.call(this, credentials[cid].billableContractID) + ] + ]) + }); + if (!response.ok) { + if (response.status === 404 || response.status === 410) { + console.warn("Contract appears to have been deleted already", cid, response.status); + return; + } + console.error("Unable to delete contract", cid, response.status); + throw new Error(`Unable to delete contract ${cid}: ${response.status}`); + } + })); + }, + // all of these functions will do both the creation of the SPMessage + // and the sending of it via 'chelonia/private/out/publishEvent' + "chelonia/out/actionEncrypted": function(params) { + return outEncryptedOrUnencryptedAction.call(this, SPMessage.OP_ACTION_ENCRYPTED, params); + }, + "chelonia/out/actionUnencrypted": function(params) { + return outEncryptedOrUnencryptedAction.call(this, SPMessage.OP_ACTION_UNENCRYPTED, params); + }, + "chelonia/out/keyShare": async function(params) { + const { atomic, originatingContractName, originatingContractID, contractName, contractID, data, hooks, publishOptions } = params; + const originatingManifestHash = this.config.contracts.manifests[originatingContractName]; + const destinationManifestHash = this.config.contracts.manifests[contractName]; + const originatingContract = originatingContractID ? this.manifestToContract[originatingManifestHash]?.contract : void 0; + const destinationContract = this.manifestToContract[destinationManifestHash]?.contract; + if (originatingContractID && !originatingContract || !destinationContract) { + throw new Error("Contract name not found"); + } + const payload = data; + if (!params.signingKeyId && !params.signingKey) { + throw new TypeError("Either signingKeyId or signingKey must be specified"); + } + let msg = SPMessage.createV1_0({ + contractID, + op: [ + SPMessage.OP_KEY_SHARE, + params.signingKeyId ? signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) : signedOutgoingDataWithRawKey(params.signingKey, payload) + ], + manifest: destinationManifestHash + }); + if (!atomic) { + msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); + } + return msg; + }, + "chelonia/out/keyAdd": async function(params) { + const { atomic, contractID, contractName, data, hooks, publishOptions } = params; + const manifestHash = this.config.contracts.manifests[contractName]; + const contract = this.manifestToContract[manifestHash]?.contract; + if (!contract) { + throw new Error("Contract name not found"); + } + const state = contract.state(contractID); + const payload = params.skipExistingKeyCheck ? data : data.filter((wk) => { + const k = isEncryptedData(wk) ? wk.valueOf() : wk; + if (has(state._vm.authorizedKeys, k.id)) { + if (state._vm.authorizedKeys[k.id]._notAfterHeight == null) { + return false; + } + } + return true; + }); + if (payload.length === 0) + return; + let msg = SPMessage.createV1_0({ + contractID, + op: [ + SPMessage.OP_KEY_ADD, + signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) + ], + manifest: manifestHash + }); + if (!atomic) { + msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); + } + return msg; + }, + "chelonia/out/keyDel": async function(params) { + const { atomic, contractID, contractName, data, hooks, publishOptions } = params; + const manifestHash = this.config.contracts.manifests[contractName]; + const contract = this.manifestToContract[manifestHash]?.contract; + if (!contract) { + throw new Error("Contract name not found"); + } + const state = contract.state(contractID); + const payload = data.map((keyId2) => { + if (isEncryptedData(keyId2)) + return keyId2; + if (!has(state._vm.authorizedKeys, keyId2) || state._vm.authorizedKeys[keyId2]._notAfterHeight != null) { + return void 0; + } + if (state._vm.authorizedKeys[keyId2]._private) { + return encryptedOutgoingData(contractID, state._vm.authorizedKeys[keyId2]._private, keyId2); + } else { + return keyId2; + } + }).filter(Boolean); + let msg = SPMessage.createV1_0({ + contractID, + op: [ + SPMessage.OP_KEY_DEL, + signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) + ], + manifest: manifestHash + }); + if (!atomic) { + msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); + } + return msg; + }, + "chelonia/out/keyUpdate": async function(params) { + const { atomic, contractID, contractName, data, hooks, publishOptions } = params; + const manifestHash = this.config.contracts.manifests[contractName]; + const contract = this.manifestToContract[manifestHash]?.contract; + if (!contract) { + throw new Error("Contract name not found"); + } + const state = contract.state(contractID); + const payload = data.map((key) => { + if (isEncryptedData(key)) + return key; + const { oldKeyId } = key; + if (state._vm.authorizedKeys[oldKeyId]._private) { + return encryptedOutgoingData(contractID, state._vm.authorizedKeys[oldKeyId]._private, key); + } else { + return key; + } + }); + let msg = SPMessage.createV1_0({ + contractID, + op: [ + SPMessage.OP_KEY_UPDATE, + signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) + ], + manifest: manifestHash + }); + if (!atomic) { + msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); + } + return msg; + }, + "chelonia/out/keyRequest": async function(params) { + const { originatingContractID, originatingContractName, contractID, contractName, hooks, publishOptions, innerSigningKeyId, encryptionKeyId, innerEncryptionKeyId, encryptKeyRequestMetadata, reference } = params; + const manifestHash = this.config.contracts.manifests[contractName]; + const originatingManifestHash = this.config.contracts.manifests[originatingContractName]; + const contract = this.manifestToContract[manifestHash]?.contract; + const originatingContract = this.manifestToContract[originatingManifestHash]?.contract; + if (!contract) { + throw new Error("Contract name not found"); + } + const rootState = esm_default(this.config.stateSelector); + try { + await esm_default("chelonia/contract/retain", contractID, { ephemeral: true }); + const state = contract.state(contractID); + const originatingState = originatingContract.state(originatingContractID); + const havePendingKeyRequest = Object.values(originatingState._vm.authorizedKeys).findIndex((k) => { + return k._notAfterHeight == null && k.meta?.keyRequest?.contractID === contractID && state?._volatile?.pendingKeyRequests?.some((pkr) => pkr.name === k.name); + }) !== -1; + if (havePendingKeyRequest) { + return; + } + const keyRequestReplyKey = keygen(EDWARDS25519SHA512BATCH); + const keyRequestReplyKeyId = keyId(keyRequestReplyKey); + const keyRequestReplyKeyP = serializeKey(keyRequestReplyKey, false); + const keyRequestReplyKeyS = serializeKey(keyRequestReplyKey, true); + const signingKeyId = findSuitableSecretKeyId(originatingState, [SPMessage.OP_KEY_ADD], ["sig"]); + if (!signingKeyId) { + throw new ChelErrorUnexpected(`Unable to send key request. Originating contract is missing a key with OP_KEY_ADD permission. contractID=${contractID} originatingContractID=${originatingContractID}`); + } + const keyAddOp = () => esm_default("chelonia/out/keyAdd", { + contractID: originatingContractID, + contractName: originatingContractName, + data: [ + { + id: keyRequestReplyKeyId, + name: "#krrk-" + keyRequestReplyKeyId, + purpose: ["sig"], + ringLevel: Number.MAX_SAFE_INTEGER, + permissions: params.permissions === "*" ? "*" : Array.isArray(params.permissions) ? [...params.permissions, SPMessage.OP_KEY_SHARE] : [SPMessage.OP_KEY_SHARE], + allowedActions: params.allowedActions, + meta: { + private: { + content: encryptedOutgoingData(originatingContractID, encryptionKeyId, keyRequestReplyKeyS), + shareable: false + }, + keyRequest: { + ...reference && { + reference: encryptKeyRequestMetadata ? encryptedOutgoingData(originatingContractID, encryptionKeyId, reference) : reference + }, + contractID: encryptKeyRequestMetadata ? encryptedOutgoingData(originatingContractID, encryptionKeyId, contractID) : contractID } - } - } - return false; - } - }, - rebuild(schema) { - if (schema.$_terms.keys) { - const topo = new Topo.Sorter(); - for (const child of schema.$_terms.keys) { - Common.tryWithPath(() => topo.add(child, { after: child.schema.$_rootReferences(), group: child.key }), child.key); + }, + data: keyRequestReplyKeyP } - schema.$_terms.keys = new internals.Keys(...topo.nodes); + ], + signingKeyId + }).catch((e2) => { + console.error(`[chelonia] Error sending OP_KEY_ADD for ${originatingContractID} during key request to ${contractID}`, e2); + throw e2; + }); + const payload = { + contractID: originatingContractID, + height: rootState.contracts[originatingContractID].height, + replyWith: signedOutgoingData(originatingContractID, innerSigningKeyId, { + encryptionKeyId, + responseKey: encryptedOutgoingData(contractID, innerEncryptionKeyId, keyRequestReplyKeyS) + }, this.transientSecretKeys), + request: "*" + }; + let msg = SPMessage.createV1_0({ + contractID, + op: [ + SPMessage.OP_KEY_REQUEST, + signedOutgoingData(contractID, params.signingKeyId, encryptKeyRequestMetadata ? encryptedOutgoingData(contractID, innerEncryptionKeyId, payload) : payload, this.transientSecretKeys) + ], + manifest: manifestHash + }); + msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, { + ...hooks, + // We ensure that both messages are placed into the publish queue + prepublish: (...args) => { + return keyAddOp().then(() => hooks?.prepublish?.(...args)); } - }, - manifest: { - build(obj, desc) { - if (desc.keys) { - obj = obj.keys(desc.keys); - } - if (desc.dependencies) { - for (const { rel, key = null, peers, options: options2 } of desc.dependencies) { - obj = internals.dependency(obj, rel, key, peers, options2); - } - } - if (desc.patterns) { - for (const { regex, schema, rule, fallthrough, matches } of desc.patterns) { - obj = obj.pattern(regex || schema, rule, { fallthrough, matches }); - } - } - if (desc.renames) { - for (const { from: from3, to, options: options2 } of desc.renames) { - obj = obj.rename(from3, to, options2); - } - } - return obj; - } - }, - messages: { - "object.and": "{{#label}} contains {{#presentWithLabels}} without its required peers {{#missingWithLabels}}", - "object.assert": '{{#label}} is invalid because {if(#subject.key, `"` + #subject.key + `" failed to ` + (#message || "pass the assertion test"), #message || "the assertion failed")}', - "object.base": "{{#label}} must be of type {{#type}}", - "object.instance": "{{#label}} must be an instance of {{:#type}}", - "object.length": '{{#label}} must have {{#limit}} key{if(#limit == 1, "", "s")}', - "object.max": '{{#label}} must have less than or equal to {{#limit}} key{if(#limit == 1, "", "s")}', - "object.min": '{{#label}} must have at least {{#limit}} key{if(#limit == 1, "", "s")}', - "object.missing": "{{#label}} must contain at least one of {{#peersWithLabels}}", - "object.nand": "{{:#mainWithLabel}} must not exist simultaneously with {{#peersWithLabels}}", - "object.oxor": "{{#label}} contains a conflict between optional exclusive peers {{#peersWithLabels}}", - "object.pattern.match": "{{#label}} keys failed to match pattern requirements", - "object.refType": "{{#label}} must be a Joi reference", - "object.regex": "{{#label}} must be a RegExp object", - "object.rename.multiple": "{{#label}} cannot rename {{:#from}} because multiple renames are disabled and another key was already renamed to {{:#to}}", - "object.rename.override": "{{#label}} cannot rename {{:#from}} because override is disabled and target {{:#to}} exists", - "object.schema": "{{#label}} must be a Joi schema of {{#type}} type", - "object.unknown": "{{#label}} is not allowed", - "object.with": "{{:#mainWithLabel}} missing required peer {{:#peerWithLabel}}", - "object.without": "{{:#mainWithLabel}} conflict with forbidden peer {{:#peerWithLabel}}", - "object.xor": "{{#label}} contains a conflict between exclusive peers {{#peersWithLabels}}" - } + }); + return msg; + } finally { + await esm_default("chelonia/contract/release", contractID, { ephemeral: true }); + } + }, + "chelonia/out/keyRequestResponse": async function(params) { + const { atomic, contractID, contractName, data, hooks, publishOptions } = params; + const manifestHash = this.config.contracts.manifests[contractName]; + const contract = this.manifestToContract[manifestHash]?.contract; + if (!contract) { + throw new Error("Contract name not found"); + } + const payload = data; + let message = SPMessage.createV1_0({ + contractID, + op: [ + SPMessage.OP_KEY_REQUEST_SEEN, + signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) + ], + manifest: manifestHash }); - internals.clone = function(value, prefs) { - if (typeof value === "object") { - if (prefs.nonEnumerables) { - return Clone(value, { shallow: true }); - } - const clone3 = Object.create(Object.getPrototypeOf(value)); - Object.assign(clone3, value); - return clone3; + if (!atomic) { + message = await esm_default("chelonia/private/out/publishEvent", message, publishOptions, hooks); + } + return message; + }, + "chelonia/out/atomic": async function(params) { + const { contractID, contractName, data, hooks, publishOptions } = params; + const manifestHash = this.config.contracts.manifests[contractName]; + const contract = this.manifestToContract[manifestHash]?.contract; + if (!contract) { + throw new Error("Contract name not found"); + } + const payload = (await Promise.all(data.map(([selector, opParams]) => { + if (![ + "chelonia/out/actionEncrypted", + "chelonia/out/actionUnencrypted", + "chelonia/out/keyAdd", + "chelonia/out/keyDel", + "chelonia/out/keyUpdate", + "chelonia/out/keyRequestResponse", + "chelonia/out/keyShare" + ].includes(selector)) { + throw new Error("Selector not allowed in OP_ATOMIC: " + selector); + } + return esm_default(selector, { + ...opParams, + ...params, + data: opParams.data, + atomic: true + }); + }))).flat().filter(Boolean).map((msg2) => { + return [msg2.opType(), msg2.opValue()]; + }); + let msg = SPMessage.createV1_0({ + contractID, + op: [ + SPMessage.OP_ATOMIC, + signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) + ], + manifest: manifestHash + }); + msg = await esm_default("chelonia/private/out/publishEvent", msg, publishOptions, hooks); + return msg; + }, + "chelonia/out/protocolUpgrade": async function() { + }, + "chelonia/out/propSet": async function() { + }, + "chelonia/out/propDel": async function() { + }, + "chelonia/out/encryptedOrUnencryptedPubMessage": function({ contractID, innerSigningKeyId, encryptionKeyId, signingKeyId, data }) { + const serializedData = outputEncryptedOrUnencryptedMessage.call(this, { + contractID, + innerSigningKeyId, + encryptionKeyId, + signingKeyId, + data + }); + this.pubsub.pub(contractID, serializedData); + }, + // Note: This is a bare-bones function designed for precise control. In many + // situations, the `chelonia/kv/queuedSet` selector (in chelonia-utils.js) + // will be simpler and more appropriate to use. + // In most situations, you want to use some queuing strategy (which this + // selector doesn't provide) alongside writing to the KV store. Therefore, as + // a general rule, you shouldn't be calling this selector directly unless + // you're building a utility library or if you have very specific needs. In + // this case, see if `chelonia/kv/queuedSet` covers your needs. + // `data` is allowed to be falsy, in which case a fetch will occur first and + // the `onconflict` handler will be called. + "chelonia/kv/set": async function(contractID, key, data, { ifMatch, innerSigningKeyId, encryptionKeyId, signingKeyId, maxAttempts, onconflict }) { + maxAttempts = maxAttempts ?? 3; + const url2 = `${this.config.connectionURL}/kv/${encodeURIComponent(contractID)}/${encodeURIComponent(key)}`; + const hasOnconflict = typeof onconflict === "function"; + let response; + const resolveData = async () => { + let currentValue; + if (response.ok || response.status === 409 || response.status === 412) { + const serializedDataText = await response.text(); + currentValue = serializedDataText ? parseEncryptedOrUnencryptedMessage(this, { + contractID, + serializedData: JSON.parse(serializedDataText), + meta: key + }) : void 0; + } else if (response.status !== 404 && response.status !== 410) { + throw new ChelErrorUnexpectedHttpResponseCode("[kv/set] Invalid response code: " + response.status); } - const clone2 = function(...args) { - return value.apply(this, args); - }; - clone2.prototype = Clone(value.prototype); - Object.defineProperty(clone2, "name", { value: value.name, writable: false }); - Object.defineProperty(clone2, "length", { value: value.length, writable: false }); - Object.assign(clone2, value); - return clone2; - }; - internals.dependency = function(schema, rel, key, peers, options2) { - assert2(key === null || typeof key === "string", rel, "key must be a strings"); - if (!options2) { - options2 = peers.length > 1 && typeof peers[peers.length - 1] === "object" ? peers.pop() : {}; - } - Common.assertOptions(options2, ["separator", "isPresent"]); - peers = [].concat(peers); - const separator = Common.default(options2.separator, "."); - const paths = []; - for (const peer of peers) { - assert2(typeof peer === "string", rel, "peers must be strings"); - paths.push(Compile.ref(peer, { separator, ancestor: 0, prefix: false })); - } - if (key !== null) { - key = Compile.ref(key, { separator, ancestor: 0, prefix: false }); - } - const obj = schema.clone(); - obj.$_terms.dependencies = obj.$_terms.dependencies || []; - obj.$_terms.dependencies.push(new internals.Dependency(rel, key, paths, peers, options2)); - return obj; + const result = await onconflict({ + contractID, + key, + failedData: data, + status: response.status, + // If no x-cid or etag header was returned, `ifMatch` would likely be + // returned as undefined, which will then use the `''` fallback value + // when writing. This allows 404 / 410 responses to work even if no + // etag is explicitly given + etag: response.headers.get("x-cid") || response.headers.get("etag"), + get currentData() { + return currentValue?.data; + }, + currentValue + }); + if (!result) + return false; + data = result[0]; + ifMatch = result[1]; + return true; }; - internals.dependencies = { - and(schema, dep, value, state, prefs) { - const missing = []; - const present = []; - const count = dep.peers.length; - const isPresent = internals.isPresent(dep.options); - for (const peer of dep.peers) { - if (isPresent(peer.resolve(value, state, prefs, null, { shadow: false })) === false) { - missing.push(peer.key); - } else { - present.push(peer.key); - } - } - if (missing.length !== count && present.length !== count) { - return { - code: "object.and", - context: { - present, - presentWithLabels: internals.keysToLabels(schema, present), - missing, - missingWithLabels: internals.keysToLabels(schema, missing) - } - }; - } - }, - nand(schema, dep, value, state, prefs) { - const present = []; - const isPresent = internals.isPresent(dep.options); - for (const peer of dep.peers) { - if (isPresent(peer.resolve(value, state, prefs, null, { shadow: false }))) { - present.push(peer.key); - } + for (; ; ) { + if (data !== void 0) { + const serializedData = outputEncryptedOrUnencryptedMessage.call(this, { + contractID, + innerSigningKeyId, + encryptionKeyId, + signingKeyId, + data, + meta: key + }); + response = await this.config.fetch(url2, { + headers: new Headers([ + ["authorization", buildShelterAuthorizationHeader.call(this, contractID)], + ["if-match", ifMatch || '""'] + ]), + method: "POST", + body: JSON.stringify(serializedData), + signal: this.abortController.signal + }); + } else { + if (!hasOnconflict) { + throw TypeError("onconflict required with empty data"); } - if (present.length !== dep.peers.length) { - return; + response = await this.config.fetch(url2, { + headers: new Headers([ + ["authorization", buildShelterAuthorizationHeader.call(this, contractID)] + ]), + signal: this.abortController.signal + }); + if (await resolveData()) { + continue; + } else { + break; } - const main = dep.paths[0]; - const values = dep.paths.slice(1); - return { - code: "object.nand", - context: { - main, - mainWithLabel: internals.keysToLabels(schema, main), - peers: values, - peersWithLabels: internals.keysToLabels(schema, values) + } + if (!response.ok) { + if (response.status === 409 || response.status === 412) { + if (--maxAttempts <= 0) { + throw new Error("kv/set conflict setting KV value"); } - }; - }, - or(schema, dep, value, state, prefs) { - const isPresent = internals.isPresent(dep.options); - for (const peer of dep.peers) { - if (isPresent(peer.resolve(value, state, prefs, null, { shadow: false }))) { - return; + await delay(randomIntFromRange(0, 1500)); + if (hasOnconflict) { + if (await resolveData()) { + continue; + } else { + break; + } + } else { + throw new Error(`kv/set failed with status ${response.status} and no onconflict handler was provided`); } } - return { - code: "object.missing", - context: { - peers: dep.paths, - peersWithLabels: internals.keysToLabels(schema, dep.paths) - } - }; - }, - oxor(schema, dep, value, state, prefs) { - const present = []; - const isPresent = internals.isPresent(dep.options); - for (const peer of dep.peers) { - if (isPresent(peer.resolve(value, state, prefs, null, { shadow: false }))) { - present.push(peer.key); + throw new ChelErrorUnexpectedHttpResponseCode("kv/set invalid response status: " + response.status); + } + break; + } + }, + "chelonia/kv/get": async function(contractID, key) { + const response = await this.config.fetch(`${this.config.connectionURL}/kv/${encodeURIComponent(contractID)}/${encodeURIComponent(key)}`, { + headers: new Headers([ + ["authorization", buildShelterAuthorizationHeader.call(this, contractID)] + ]), + signal: this.abortController.signal + }); + if (response.status === 404) { + return null; + } + if (!response.ok) { + throw new Error("Invalid response status: " + response.status); + } + const data = await response.json(); + return parseEncryptedOrUnencryptedMessage(this, { + contractID, + serializedData: data, + meta: key + }); + }, + // To set filters for a contract, call with `filter` set to an array of KV + // keys to receive updates for over the WebSocket. An empty array means that + // no KV updates will be sent. + // Calling with a single argument (the contract ID) will remove filters, + // meaning that KV updates will be sent for _any_ KV key. + // The last call takes precedence, so, for example, calling with filter + // set to `['foo', 'bar']` and then with `['baz']` means that KV updates will + // be received for `baz` only, not for `foo`, `bar` or any other keys. + "chelonia/kv/setFilter": function(contractID, filter) { + this.pubsub.setKvFilter(contractID, filter); + }, + "chelonia/parseEncryptedOrUnencryptedDetachedMessage": function({ contractID, serializedData, meta }) { + return parseEncryptedOrUnencryptedMessage(this, { + contractID, + serializedData, + meta + }); + } +}); +function contractNameFromAction(action) { + const regexResult = ACTION_REGEX.exec(action); + const contractName = regexResult?.[2]; + if (!contractName) + throw new Error(`Poorly named action '${action}': missing contract name.`); + return contractName; +} +function outputEncryptedOrUnencryptedMessage({ contractID, innerSigningKeyId, encryptionKeyId, signingKeyId, data, meta }) { + const state = esm_default(this.config.stateSelector)[contractID]; + const signedMessage = innerSigningKeyId ? state._vm.authorizedKeys[innerSigningKeyId] && state._vm.authorizedKeys[innerSigningKeyId]?._notAfterHeight == null ? signedOutgoingData(contractID, innerSigningKeyId, data, this.transientSecretKeys) : signedOutgoingDataWithRawKey(this.transientSecretKeys[innerSigningKeyId], data) : data; + const payload = !encryptionKeyId ? signedMessage : encryptedOutgoingData(contractID, encryptionKeyId, signedMessage); + const message = signedOutgoingData(contractID, signingKeyId, payload, this.transientSecretKeys); + const rootState = esm_default(this.config.stateSelector); + const height = String(rootState.contracts[contractID].height); + const serializedData = { ...message.serialize((meta ?? "") + height), height }; + return serializedData; +} +function parseEncryptedOrUnencryptedMessage(ctx, { contractID, serializedData, meta }) { + if (!serializedData) { + throw new TypeError("[chelonia] parseEncryptedOrUnencryptedMessage: serializedData is required"); + } + const state = esm_default(ctx.config.stateSelector)[contractID]; + const numericHeight = parseInt(serializedData.height); + const rootState = esm_default(ctx.config.stateSelector); + const currentHeight = rootState.contracts[contractID].height; + if (!(numericHeight >= 0) || !(numericHeight <= currentHeight)) { + throw new Error(`[chelonia] parseEncryptedOrUnencryptedMessage: Invalid height ${serializedData.height}; it must be between 0 and ${currentHeight}`); + } + const aad = (meta ?? "") + serializedData.height; + const v2 = signedIncomingData(contractID, state, serializedData, numericHeight, aad, (message) => { + return maybeEncryptedIncomingData(contractID, state, message, numericHeight, ctx.transientSecretKeys, aad, void 0); + }); + let encryptionKeyId; + let innerSigningKeyId; + const unwrap2 = /* @__PURE__ */ (() => { + let result2; + return () => { + if (!result2) { + try { + let unwrapped; + unwrapped = v2.valueOf(); + if (isEncryptedData(unwrapped)) { + encryptionKeyId = unwrapped.encryptionKeyId; + unwrapped = unwrapped.valueOf(); + if (isSignedData(unwrapped)) { + innerSigningKeyId = unwrapped.signingKeyId; + unwrapped = unwrapped.valueOf(); + } else { + innerSigningKeyId = null; + } + } else { + encryptionKeyId = null; + innerSigningKeyId = null; } + result2 = [unwrapped]; + } catch (e2) { + result2 = [void 0, e2]; } - if (!present.length || present.length === 1) { - return; + } + if (result2.length === 2) { + throw result2[1]; + } + return result2[0]; + }; + })(); + const result = { + get contractID() { + return contractID; + }, + get innerSigningKeyId() { + if (innerSigningKeyId === void 0) { + try { + unwrap2(); + } catch { } - const context = { peers: dep.paths, peersWithLabels: internals.keysToLabels(schema, dep.paths) }; - context.present = present; - context.presentWithLabels = internals.keysToLabels(schema, present); - return { code: "object.oxor", context }; - }, - with(schema, dep, value, state, prefs) { - const isPresent = internals.isPresent(dep.options); - for (const peer of dep.peers) { - if (isPresent(peer.resolve(value, state, prefs, null, { shadow: false })) === false) { - return { - code: "object.with", - context: { - main: dep.key.key, - mainWithLabel: internals.keysToLabels(schema, dep.key.key), - peer: peer.key, - peerWithLabel: internals.keysToLabels(schema, peer.key) - } - }; - } + } + return innerSigningKeyId; + }, + get encryptionKeyId() { + if (encryptionKeyId === void 0) { + try { + unwrap2(); + } catch { } - }, - without(schema, dep, value, state, prefs) { - const isPresent = internals.isPresent(dep.options); - for (const peer of dep.peers) { - if (isPresent(peer.resolve(value, state, prefs, null, { shadow: false }))) { - return { - code: "object.without", - context: { - main: dep.key.key, - mainWithLabel: internals.keysToLabels(schema, dep.key.key), - peer: peer.key, - peerWithLabel: internals.keysToLabels(schema, peer.key) - } - }; - } + } + return encryptionKeyId; + }, + get signingKeyId() { + return v2.signingKeyId; + }, + get data() { + return unwrap2(); + }, + get signingContractID() { + return getContractIDfromKeyId(contractID, result.signingKeyId, state); + }, + get innerSigningContractID() { + return getContractIDfromKeyId(contractID, result.innerSigningKeyId, state); + } + }; + return result; +} +async function outEncryptedOrUnencryptedAction(opType, params) { + const { atomic, action, contractID, data, hooks, publishOptions } = params; + const contractName = contractNameFromAction(action); + const manifestHash = this.config.contracts.manifests[contractName]; + const { contract } = this.manifestToContract[manifestHash]; + const state = contract.state(contractID); + const meta = await contract.metadata.create(); + const unencMessage = { action, data, meta }; + const signedMessage = params.innerSigningKeyId ? state._vm.authorizedKeys[params.innerSigningKeyId] && state._vm.authorizedKeys[params.innerSigningKeyId]?._notAfterHeight == null ? signedOutgoingData(contractID, params.innerSigningKeyId, unencMessage, this.transientSecretKeys) : signedOutgoingDataWithRawKey(this.transientSecretKeys[params.innerSigningKeyId], unencMessage) : unencMessage; + if (opType === SPMessage.OP_ACTION_ENCRYPTED && !params.encryptionKeyId) { + throw new Error("OP_ACTION_ENCRYPTED requires an encryption key ID be given"); + } + if (params.encryptionKey) { + if (params.encryptionKeyId !== keyId(params.encryptionKey)) { + throw new Error("OP_ACTION_ENCRYPTED raw encryption key does not match encryptionKeyId"); + } + } + const payload = opType === SPMessage.OP_ACTION_UNENCRYPTED ? signedMessage : params.encryptionKey ? encryptedOutgoingDataWithRawKey(params.encryptionKey, signedMessage) : encryptedOutgoingData(contractID, params.encryptionKeyId, signedMessage); + let message = SPMessage.createV1_0({ + contractID, + op: [ + opType, + signedOutgoingData(contractID, params.signingKeyId, payload, this.transientSecretKeys) + ], + manifest: manifestHash + }); + if (!atomic) { + message = await esm_default("chelonia/private/out/publishEvent", message, publishOptions, hooks); + } + return message; +} +function gettersProxy(state, getters) { + const proxyGetters = new Proxy({}, { + get(_target, prop) { + return getters[prop](state, proxyGetters); + } + }); + return { getters: proxyGetters }; +} +esm_default("sbp/domains/lock", ["chelonia"]); +init_db(); +init_db(); +init_functions(); +init_esm(); +var import_npm_lru_cache = __toESM(require_lru_cache()); +init_errors3(); +var BackendErrorNotFound = ChelErrorGenerator("BackendErrorNotFound"); +var BackendErrorGone = ChelErrorGenerator("BackendErrorGone"); +var BackendErrorBadData = ChelErrorGenerator("BackendErrorBadData"); +var BackendErrorConflict = ChelErrorGenerator("BackendErrorConflict"); +init_esm(); +var import_npm_nconf = __toESM(require_nconf()); +var vapidPublicKey; +var vapidPrivateKey; +var vapid; +var initVapid = async () => { + const vapidEmail = import_npm_nconf.default.get("server:vapid:email"); + if (!vapidEmail) { + console.warn('Missing VAPID identification. Please set `server:vapid:email` to a value like "some@domain.example".'); + } + vapid = { VAPID_EMAIL: vapidEmail?.replace(/^mailto:/i, "") || "test@example.com" }; + const vapidKeyPair = await esm_default("chelonia.db/get", "_private_immutable_vapid_key").then(async (vapidKeyPair2) => { + if (!vapidKeyPair2) { + console.info("Generating new VAPID keypair..."); + const keyPair = await crypto.subtle.generateKey( + { + name: "ECDSA", + namedCurve: "P-256" + // Use P-256 curve + }, + true, + // Whether the key is extractable + ["sign", "verify"] + // Usages + ); + const serializedKeyPair2 = await Promise.all([ + crypto.subtle.exportKey("jwk", keyPair.privateKey), + crypto.subtle.exportKey("raw", keyPair.publicKey).then( + (key) => Buffer7.from(key).toString("base64url") + ) + ]); + return esm_default("chelonia.db/set", "_private_immutable_vapid_key", JSON.stringify(serializedKeyPair2)).then(() => { + console.info("Successfully saved newly generated VAPID keys"); + return [keyPair.privateKey, serializedKeyPair2[1]]; + }); + } + const serializedKeyPair = JSON.parse(vapidKeyPair2); + return [ + await crypto.subtle.importKey( + "jwk", + serializedKeyPair[0], + { name: "ECDSA", namedCurve: "P-256" }, + false, + ["sign"] + ), + serializedKeyPair[1] + ]; + }); + vapidPrivateKey = vapidKeyPair[0]; + vapidPublicKey = vapidKeyPair[1]; +}; +var generateJwt = async (endpoint) => { + const now = Date.now() / 1e3 | 0; + const audience = endpoint.origin; + const header = Buffer7.from(JSON.stringify( + Object.fromEntries([["typ", "JWT"], ["alg", "ES256"]]) + )).toString("base64url"); + const body = Buffer7.from(JSON.stringify( + // We're expecting to use the JWT immediately. We set a 10-minute window + // for using the JWT (5 minutes into the past, 5 minutes into the future) + // to account for potential network delays and clock drift. + Object.fromEntries([ + // token audience + ["aud", audience], + // 'expiry' / 'not after' value for the token + ["exp", now + 300], + // (optional) issuance time for the token + ["iat", now], + // 'not before' value for the JWT + ["nbf", now - 300], + // URI used for identifying ourselves. This can be used by the push + // provider to get in touch in case of issues. + ["sub", `mailto:${vapid.VAPID_EMAIL}`] + ]) + )).toString("base64url"); + const signature = Buffer7.from( + await crypto.subtle.sign( + { name: "ECDSA", hash: "SHA-256" }, + vapidPrivateKey, + Buffer7.from([header, body].join(".")) + ) + ).toString("base64url"); + return [header, body, signature].join("."); +}; +var getVapidPublicKey = () => vapidPublicKey; +var vapidAuthorization = async (endpoint) => { + const jwt = await generateJwt(endpoint); + return `vapid t=${jwt}, k=${vapidPublicKey}`; +}; +var import_scrypt_async2 = __toESM(require_scrypt_async(), 1); +var import_tweetnacl2 = __toESM(require_nacl_fast(), 1); +var AUTHSALT = "AUTHSALT"; +var CONTRACTSALT = "CONTRACTSALT"; +var CS = "CS"; +var SU = "SU"; +var SALT_LENGTH_IN_OCTETS = 24; +var base64ToBase64url = (s) => s.replace(/\//g, "_").replace(/\+/g, "-").replace(/=*$/, ""); +var base64urlToBase64 = (s) => s.replace(/_/g, "/").replace(/-/g, "+") + "=".repeat((4 - s.length % 4) % 4); +var hashStringArray = (...args) => { + return import_tweetnacl2.default.hash(Buffer8.concat(args.map((s) => import_tweetnacl2.default.hash(Buffer8.from(s))))); +}; +var hashRawStringArray = (...args) => { + return import_tweetnacl2.default.hash(Buffer8.concat(args.map((s) => Buffer8.from(s)))); +}; +var randomNonce = () => { + return base64ToBase64url(Buffer8.from(import_tweetnacl2.default.randomBytes(12)).toString("base64")); +}; +var hash2 = (v2) => { + return base64ToBase64url(Buffer8.from(import_tweetnacl2.default.hash(Buffer8.from(v2))).toString("base64")); +}; +var computeCAndHc = (r, s, h2) => { + const \u0127 = hashStringArray(r, s); + const c = hashStringArray(h2, \u0127); + const hc = import_tweetnacl2.default.hash(c); + return [c, hc]; +}; +var encryptContractSalt = (c, contractSalt) => { + const encryptionKey = hashRawStringArray(CS, c).slice(0, import_tweetnacl2.default.secretbox.keyLength); + const nonce = import_tweetnacl2.default.randomBytes(import_tweetnacl2.default.secretbox.nonceLength); + const encryptedContractSalt = import_tweetnacl2.default.secretbox(Buffer8.from(contractSalt), nonce, encryptionKey); + return base64ToBase64url(Buffer8.concat([nonce, encryptedContractSalt]).toString("base64")); +}; +var encryptSaltUpdate = (secret, recordId, record2) => { + const nonce = import_tweetnacl2.default.randomBytes(import_tweetnacl2.default.secretbox.nonceLength); + const encryptionKey = hashRawStringArray(SU, secret, nonce, recordId).slice(0, import_tweetnacl2.default.secretbox.keyLength); + const encryptedRecord = import_tweetnacl2.default.secretbox(Buffer8.from(record2), nonce, encryptionKey); + return base64ToBase64url(Buffer8.concat([nonce, encryptedRecord]).toString("base64")); +}; +var decryptSaltUpdate = (secret, recordId, encryptedRecordBox) => { + const encryptedRecordBoxBuf = Buffer8.from(base64urlToBase64(encryptedRecordBox), "base64"); + const nonce = encryptedRecordBoxBuf.subarray(0, import_tweetnacl2.default.secretbox.nonceLength); + const encryptionKey = hashRawStringArray(SU, secret, nonce, recordId).slice(0, import_tweetnacl2.default.secretbox.keyLength); + const encryptedRecord = encryptedRecordBoxBuf.subarray(import_tweetnacl2.default.secretbox.nonceLength); + const decrypted = import_tweetnacl2.default.secretbox.open(encryptedRecord, nonce, encryptionKey); + if (!decrypted) + throw new Error("Failed to decrypt salt update"); + return Buffer8.from(decrypted).toString(); +}; +var boxKeyPair = () => { + return import_tweetnacl2.default.box.keyPair(); +}; +var saltAgreement = (publicKey, secretKey) => { + const publicKeyBuf = Buffer8.from(base64urlToBase64(publicKey), "base64"); + const dhKey = import_tweetnacl2.default.box.before(publicKeyBuf, secretKey); + if (!publicKeyBuf || publicKeyBuf.byteLength !== import_tweetnacl2.default.box.publicKeyLength) { + return false; + } + const authSalt = Buffer8.from(hashStringArray(AUTHSALT, dhKey)).subarray(0, SALT_LENGTH_IN_OCTETS).toString("base64"); + const contractSalt = Buffer8.from(hashStringArray(CONTRACTSALT, dhKey)).subarray(0, SALT_LENGTH_IN_OCTETS).toString("base64"); + return [authSalt, contractSalt]; +}; +var parseRegisterSalt = (publicKey, secretKey, encryptedHashedPassword) => { + const saltAgreementRes = saltAgreement(publicKey, secretKey); + if (!saltAgreementRes) { + return false; + } + const [authSalt, contractSalt] = saltAgreementRes; + const encryptionKey = import_tweetnacl2.default.hash(Buffer8.from(authSalt + contractSalt)).slice(0, import_tweetnacl2.default.secretbox.keyLength); + const encryptedHashedPasswordBuf = Buffer8.from(base64urlToBase64(encryptedHashedPassword), "base64"); + const hashedPasswordBuf = import_tweetnacl2.default.secretbox.open(encryptedHashedPasswordBuf.subarray(import_tweetnacl2.default.box.nonceLength), encryptedHashedPasswordBuf.subarray(0, import_tweetnacl2.default.box.nonceLength), encryptionKey); + if (!hashedPasswordBuf) { + return false; + } + return [authSalt, contractSalt, hashedPasswordBuf, encryptionKey]; +}; +init_esm(); +var import_npm_tweetnacl = __toESM(require_nacl_fast()); +var nacl3 = import_npm_tweetnacl.default; +var recordSecret; +var challengeSecret; +var registrationSecret; +var hashUpdateSecret; +var initZkpp = async () => { + const IKM = await esm_default("chelonia.db/get", "_private_immutable_zkpp_ikm").then((IKM2) => { + if (!IKM2) { + const secret = randomBytes2(33).toString("base64"); + return esm_default("chelonia.db/set", "_private_immutable_zkpp_ikm", secret).then(() => { + return secret; + }); + } + return IKM2; + }); + recordSecret = Buffer9.from(hashStringArray("private/recordSecret", IKM)).toString("base64"); + challengeSecret = Buffer9.from(hashStringArray("private/challengeSecret", IKM)).toString("base64"); + registrationSecret = Buffer9.from(hashStringArray("private/registrationSecret", IKM)).toString("base64"); + hashUpdateSecret = Buffer9.from(hashStringArray("private/hashUpdateSecret", IKM)).toString("base64"); +}; +var maxAge = 30; +var computeZkppSaltRecordId = async (contractID) => { + const recordId = `_private_rid_${contractID}`; + const record2 = await esm_default("chelonia.db/get", recordId); + if (!record2) { + return null; + } + const recordBuf = Buffer9.concat([Buffer9.from(contractID), Buffer9.from(record2)]); + return hash2(recordBuf); +}; +var getZkppSaltRecord = async (contractID) => { + const recordId = `_private_rid_${contractID}`; + const record2 = await esm_default("chelonia.db/get", recordId); + if (record2) { + const encryptionKey = hashStringArray("REK", contractID, recordSecret).slice(0, nacl3.secretbox.keyLength); + const recordBuf = Buffer9.from(base64urlToBase64(record2), "base64"); + const nonce = recordBuf.slice(0, nacl3.secretbox.nonceLength); + const recordCiphertext = recordBuf.slice(nacl3.secretbox.nonceLength); + const recordPlaintext = nacl3.secretbox.open(recordCiphertext, nonce, encryptionKey); + if (!recordPlaintext) { + return null; + } + const recordString = Buffer9.from(recordPlaintext).toString("utf-8"); + try { + const recordObj = JSON.parse(recordString); + if (!Array.isArray(recordObj) || recordObj.length !== 3 && recordObj.length !== 4 || recordObj.slice(0, 3).some((r) => !r || typeof r !== "string") || recordObj[3] != null && typeof recordObj[3] !== "string") { + console.error("Error validating encrypted JSON object " + recordId); + return null; + } + const [hashedPassword, authSalt, contractSalt, cid] = recordObj; + return { + hashedPassword, + authSalt, + contractSalt, + cid + }; + } catch { + console.error("Error parsing encrypted JSON object " + recordId); + } + } + return null; +}; +var setZkppSaltRecord = async (contractID, hashedPassword, authSalt, contractSalt, cid) => { + const recordId = `_private_rid_${contractID}`; + const encryptionKey = hashStringArray("REK", contractID, recordSecret).slice(0, nacl3.secretbox.keyLength); + const nonce = nacl3.randomBytes(nacl3.secretbox.nonceLength); + const recordPlaintext = JSON.stringify([hashedPassword, authSalt, contractSalt, cid]); + const recordCiphertext = nacl3.secretbox(Buffer9.from(recordPlaintext), nonce, encryptionKey); + const recordBuf = Buffer9.concat([nonce, recordCiphertext]); + const record2 = base64ToBase64url(recordBuf.toString("base64")); + await esm_default("chelonia.db/set", recordId, record2); +}; +var getChallenge = async (contract, b) => { + const record2 = await getZkppSaltRecord(contract); + if (!record2) { + console.debug("getChallenge: Error obtaining ZKPP salt record for contract ID " + contract); + return false; + } + const { authSalt } = record2; + const s = randomNonce(); + const now = (Date.now() / 1e3 | 0).toString(16); + const sig = [now, base64ToBase64url(Buffer9.from(hashStringArray(contract, b, s, now, challengeSecret)).toString("base64"))].join(","); + return { + authSalt, + s, + sig + }; +}; +var verifyChallenge = (contractID, r, s, userSig) => { + if (!/^[a-fA-F0-9]{1,11},[a-zA-Z0-9_-]{86}(?:==)?$/.test(userSig)) { + console.info(`wrong signature format for challenge for contract: ${contractID}`); + return false; + } + const [then, mac] = userSig.split(","); + const now = Date.now() / 1e3 | 0; + const iThen = Number.parseInt(then, 16); + if (!(iThen <= now) || !(iThen >= now - maxAge)) { + return false; + } + const b = hash2(r); + const sig = hashStringArray(contractID, b, s, then, challengeSecret); + const macBuf = Buffer9.from(base64urlToBase64(mac), "base64"); + return sig.byteLength === macBuf.byteLength && timingSafeEqual(sig, macBuf); +}; +var registrationKey = (provisionalId, b) => { + const encryptionKey = hashStringArray("REG", provisionalId, registrationSecret).slice(0, nacl3.secretbox.keyLength); + const nonce = nacl3.randomBytes(nacl3.secretbox.nonceLength); + const keyPair = boxKeyPair(); + const s = base64ToBase64url(Buffer9.concat([nonce, nacl3.secretbox(keyPair.secretKey, nonce, encryptionKey)]).toString("base64")); + const now = (Date.now() / 1e3 | 0).toString(16); + const sig = [now, base64ToBase64url(Buffer9.from(hashStringArray(provisionalId, b, s, now, challengeSecret)).toString("base64"))].join(","); + return { + s, + p: base64ToBase64url(Buffer9.from(keyPair.publicKey).toString("base64")), + sig + }; +}; +var register = (provisionalId, clientPublicKey, encryptedSecretKey, userSig, encryptedHashedPassword) => { + if (!verifyChallenge(provisionalId, clientPublicKey, encryptedSecretKey, userSig)) { + console.warn("register: Error validating challenge: " + JSON.stringify({ contract: provisionalId, clientPublicKey, userSig })); + throw new Error("register: Invalid challenge"); + } + const encryptedSecretKeyBuf = Buffer9.from(base64urlToBase64(encryptedSecretKey), "base64"); + const encryptionKey = hashStringArray("REG", provisionalId, registrationSecret).slice(0, nacl3.secretbox.keyLength); + const secretKeyBuf = nacl3.secretbox.open(encryptedSecretKeyBuf.slice(nacl3.secretbox.nonceLength), encryptedSecretKeyBuf.slice(0, nacl3.secretbox.nonceLength), encryptionKey); + if (!secretKeyBuf) { + console.warn(`register: Error decrypting arguments for contract ID ${provisionalId} (${JSON.stringify({ clientPublicKey, userSig })})`); + return false; + } + const parseRegisterSaltRes = parseRegisterSalt(clientPublicKey, secretKeyBuf, encryptedHashedPassword); + if (!parseRegisterSaltRes) { + console.warn(`register: Error parsing registration salt for contract ID ${provisionalId} (${JSON.stringify({ clientPublicKey, userSig })})`); + return false; + } + const [authSalt, contractSalt, hashedPasswordBuf, sharedEncryptionKey] = parseRegisterSaltRes; + const token = encryptSaltUpdate( + hashUpdateSecret, + provisionalId, + JSON.stringify([Date.now(), Buffer9.from(hashedPasswordBuf).toString(), authSalt, contractSalt]) + ); + return encryptContractSalt(sharedEncryptionKey, token); +}; +var contractSaltVerifyC = (h2, r, s, userHc) => { + const [c, hc] = computeCAndHc(r, s, h2); + const userHcBuf = Buffer9.from(base64urlToBase64(userHc), "base64"); + if (hc.byteLength === userHcBuf.byteLength && timingSafeEqual(hc, userHcBuf)) { + return c; + } + return false; +}; +var getContractSalt = async (contract, r, s, sig, hc) => { + if (!verifyChallenge(contract, r, s, sig)) { + console.debug("getContractSalt: Error validating challenge: " + JSON.stringify({ contract, r, s, sig })); + throw new Error("getContractSalt: Bad challenge"); + } + const record2 = await getZkppSaltRecord(contract); + if (!record2) { + console.error("getContractSalt: Error obtaining ZKPP salt record for contract ID " + contract); + return false; + } + const { hashedPassword, contractSalt, cid } = record2; + const c = contractSaltVerifyC(hashedPassword, r, s, hc); + if (!c) { + console.error(`getContractSalt: Error verifying challenge for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); + throw new Error("getContractSalt: Bad challenge"); + } + return encryptContractSalt(c, JSON.stringify([contractSalt, cid])); +}; +var updateContractSalt = async (contract, r, s, sig, hc, encryptedArgs) => { + if (!verifyChallenge(contract, r, s, sig)) { + console.warn("update: Error validating challenge: " + JSON.stringify({ contract, r, s, sig })); + throw new Error("update: Bad challenge"); + } + const record2 = await getZkppSaltRecord(contract); + if (!record2) { + console.error("update: Error obtaining ZKPP salt record for contract ID " + contract); + return false; + } + const { hashedPassword, contractSalt: oldContractSalt } = record2; + const c = contractSaltVerifyC(hashedPassword, r, s, hc); + if (!c) { + console.error(`update: Error verifying challenge for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); + throw new Error("update: Bad challenge"); + } + const encryptionKey = hashRawStringArray(SU, c).slice(0, nacl3.secretbox.keyLength); + const encryptedArgsBuf = Buffer9.from(base64urlToBase64(encryptedArgs), "base64"); + const nonce = encryptedArgsBuf.slice(0, nacl3.secretbox.nonceLength); + const encryptedArgsCiphertext = encryptedArgsBuf.slice(nacl3.secretbox.nonceLength); + const args = nacl3.secretbox.open(encryptedArgsCiphertext, nonce, encryptionKey); + if (!args) { + console.error(`update: Error decrypting arguments for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); + return false; + } + try { + const hashedPassword2 = Buffer9.from(args).toString(); + const recordId = await computeZkppSaltRecordId(contract); + if (!recordId) { + console.error(`update: Error obtaining record ID for contract ID ${contract}`); + return false; + } + const authSalt = Buffer9.from(hashStringArray(AUTHSALT, c)).slice(0, SALT_LENGTH_IN_OCTETS).toString("base64"); + const contractSalt = Buffer9.from(hashStringArray(CONTRACTSALT, c)).slice(0, SALT_LENGTH_IN_OCTETS).toString("base64"); + const token = encryptSaltUpdate( + hashUpdateSecret, + recordId, + JSON.stringify([Date.now(), hashedPassword2, authSalt, contractSalt]) + ); + return encryptContractSalt(c, JSON.stringify([oldContractSalt, token])); + } catch { + console.error(`update: Error parsing encrypted arguments for contract ID ${contract} (${JSON.stringify({ r, s, hc })})`); + } + return false; +}; +var redeemSaltRegistrationToken = async (provisoryRegistrationKey, contract, token) => { + const decryptedToken = decryptSaltUpdate( + hashUpdateSecret, + provisoryRegistrationKey, + token + ); + const [timestamp, hashedPassword, authSalt, contractSalt] = JSON.parse(decryptedToken); + if (timestamp < Date.now() - 18e4) { + throw new Error("ZKPP token expired"); + } + await setZkppSaltRecord(contract, hashedPassword, authSalt, contractSalt); +}; +var redeemSaltUpdateToken = async (contract, token) => { + const recordId = await computeZkppSaltRecordId(contract); + if (!recordId) { + throw new Error("Record ID not found"); + } + const decryptedToken = decryptSaltUpdate( + hashUpdateSecret, + recordId, + token + ); + const [timestamp, hashedPassword, authSalt, contractSalt] = JSON.parse(decryptedToken); + if (timestamp < Date.now() - 18e4) { + throw new Error("ZKPP token expired"); + } + return (cid) => { + return setZkppSaltRecord(contract, hashedPassword, authSalt, contractSalt, cid); + }; +}; +var import_npm_nconf2 = __toESM(require_nconf()); +init_esm(); +var KEYOP_SEGMENT_LENGTH = 1e4; +var updateSize = async (resourceID, sizeKey, size, skipIfDeleted) => { + if (!Number.isSafeInteger(size)) { + throw new TypeError(`Invalid given size ${size} for ${resourceID}`); + } + await esm_default("okTurtles.eventQueue/queueEvent", sizeKey, async () => { + const storedSize = await esm_default("chelonia.db/get", sizeKey, { bypassCache: true }); + if (skipIfDeleted && storedSize == null) return; + const existingSize = parseInt(storedSize ?? "0", 10); + if (!(existingSize >= 0)) { + throw new TypeError(`Invalid stored size ${existingSize} for ${resourceID}`); + } + const updatedSize = existingSize + size; + if (!(updatedSize >= 0)) { + throw new TypeError(`Invalid stored updated size ${updatedSize} for ${resourceID}`); + } + await esm_default("chelonia.db/set", sizeKey, updatedSize.toString(10)); + }); +}; +function namespaceKey(name) { + return "name=" + name; +} +var appendToIndexFactory = (key) => { + return (value) => { + return esm_default("okTurtles.eventQueue/queueEvent", key, async () => { + const currentIndex = await esm_default("chelonia.db/get", key, { bypassCache: true }); + if (currentIndex) { + if ( + // Check if the value is at the end + currentIndex.endsWith("\0" + value) || // Check if the value is at the start + currentIndex.startsWith(value + "\0") || // Check if the current index is exactly the value + currentIndex === value || // Check if the value is in the middle + currentIndex.includes("\0" + value + "\0") + ) { + return; } - }, - xor(schema, dep, value, state, prefs) { - const present = []; - const isPresent = internals.isPresent(dep.options); - for (const peer of dep.peers) { - if (isPresent(peer.resolve(value, state, prefs, null, { shadow: false }))) { - present.push(peer.key); - } + await esm_default("chelonia.db/set", key, `${currentIndex}\0${value}`); + return; + } + await esm_default("chelonia.db/set", key, value); + }); + }; +}; +var appendToNamesIndex = appendToIndexFactory("_private_names_index"); +var removeFromIndexFactory = (key) => { + return (values) => { + return esm_default("okTurtles.eventQueue/queueEvent", key, async () => { + let existingEntries = await esm_default("chelonia.db/get", key, { bypassCache: true }); + if (!existingEntries) return; + if (!Array.isArray(values)) { + values = [values]; + } + for (const value of values) { + if (existingEntries.endsWith("\0" + value)) { + existingEntries = existingEntries.slice(0, -value.length - 1); + continue; } - if (present.length === 1) { - return; + if (existingEntries.startsWith(value + "\0")) { + existingEntries = existingEntries.slice(value.length + 1); + continue; } - const context = { peers: dep.paths, peersWithLabels: internals.keysToLabels(schema, dep.paths) }; - if (present.length === 0) { - return { code: "object.missing", context }; + if (existingEntries === value) { + existingEntries = void 0; + break; } - context.present = present; - context.presentWithLabels = internals.keysToLabels(schema, present); - return { code: "object.xor", context }; + const entryIndex = existingEntries.indexOf("\0" + value + "\0"); + if (entryIndex === -1) continue; + existingEntries = existingEntries.slice(0, entryIndex) + existingEntries.slice(entryIndex + value.length + 1); } - }; - internals.keysToLabels = function(schema, keys) { - if (Array.isArray(keys)) { - return keys.map((key) => schema.$_mapLabels(key)); + if (existingEntries) { + await esm_default("chelonia.db/set", key, existingEntries); + } else { + await esm_default("chelonia.db/delete", key); } - return schema.$_mapLabels(keys); - }; - internals.isPresent = function(options2) { - return typeof options2.isPresent === "function" ? options2.isPresent : (resolved) => resolved !== void 0; - }; - internals.rename = function(schema, value, state, prefs, errors) { - const renamed = {}; - for (const rename of schema.$_terms.renames) { - const matches = []; - const pattern = typeof rename.from !== "string"; - if (!pattern) { - if (Object.prototype.hasOwnProperty.call(value, rename.from) && (value[rename.from] !== void 0 || !rename.options.ignoreUndefined)) { - matches.push(rename); - } - } else { - for (const from3 in value) { - if (value[from3] === void 0 && rename.options.ignoreUndefined) { - continue; - } - if (from3 === rename.to) { - continue; - } - const match = rename.from.exec(from3); - if (!match) { - continue; - } - matches.push({ from: from3, to: rename.to, match }); - } - } - for (const match of matches) { - const from3 = match.from; - let to = match.to; - if (to instanceof Template) { - to = to.render(value, state, prefs, match.match); - } - if (from3 === to) { - continue; - } - if (!rename.options.multiple && renamed[to]) { - errors.push(schema.$_createError("object.rename.multiple", value, { from: from3, to, pattern }, state, prefs)); - if (prefs.abortEarly) { - return false; - } - } - if (Object.prototype.hasOwnProperty.call(value, to) && !rename.options.override && !renamed[to]) { - errors.push(schema.$_createError("object.rename.override", value, { from: from3, to, pattern }, state, prefs)); - if (prefs.abortEarly) { + }); + }; +}; +var lookupUltimateOwner = async (resourceID) => { + let ownerID = resourceID; + for (let depth = 128; depth >= 0; depth--) { + const newOwnerID = await esm_default("chelonia.db/get", `_private_owner_${ownerID}`, { bypassCache: true }); + if (!newOwnerID) break; + if (!depth) { + throw new Error("Exceeded max depth looking up owner for " + resourceID); + } + ownerID = newOwnerID; + } + return ownerID; +}; +var globImport_database_ts2 = __glob({ + "./database-fs.ts": () => Promise.resolve().then(() => (init_database_fs(), database_fs_exports)), + "./database-redis.ts": () => Promise.resolve().then(() => (init_database_redis(), database_redis_exports)), + "./database-router.test.ts": () => Promise.resolve().then(() => (init_database_router_test(), database_router_test_exports)), + "./database-router.ts": () => Promise.resolve().then(() => (init_database_router(), database_router_exports)), + "./database-sqlite.ts": () => Promise.resolve().then(() => (init_database_sqlite(), database_sqlite_exports)) +}); +var production = process2.env.NODE_ENV === "production"; +var currentBackend = null; +var currentCache = null; +var isClosing = false; +var baseSelectorsInstalled = false; +function installBaseSelectorsOnce() { + if (baseSelectorsInstalled) return; + baseSelectorsInstalled = true; + esm_default("sbp/selectors/register", { + "backend/db/streamEntriesAfter": async function(contractID, height, requestedLimit, options2 = {}) { + const batchMaxSize = import_npm_nconf2.default.get("server:maxEventsBatchSize") ?? 500; + const limit = Math.min(requestedLimit ?? Number.POSITIVE_INFINITY, batchMaxSize); + const latestHEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); + if (latestHEADinfo === "") { + throw new BackendErrorGone(`contractID ${contractID} has been deleted!`); + } + if (!latestHEADinfo) { + throw new BackendErrorNotFound(`contractID ${contractID} doesn't exist!`); + } + let counter = 0; + let currentHeight = height; + let currentHash, serverMeta; + let prefix = ""; + const nextKeyOp = /* @__PURE__ */ (() => { + let index; + return async () => { + if (!index) { + index = (await esm_default("chelonia.db/get", `_private_keyop_idx_${contractID}_${currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH}`))?.split("\0"); + } + const value = index?.find((h2, i2) => { + if (Number(h2) >= currentHeight) { + index = index.slice(i2 + 1); + return true; + } else { return false; } - } - if (value[from3] === void 0) { - delete value[to]; + }); + if (value != null) { + const newHeight = Number(value); + currentHeight = newHeight; } else { - value[to] = value[from3]; - } - renamed[to] = true; - if (!rename.options.alias) { - delete value[from3]; - } - } - } - return true; - }; - internals.unknown = function(schema, value, unprocessed, errors, state, prefs) { - if (schema.$_terms.patterns) { - let hasMatches = false; - const matches = schema.$_terms.patterns.map((pattern) => { - if (pattern.matches) { - hasMatches = true; - return []; - } - }); - const ancestors = [value, ...state.ancestors]; - for (const key of unprocessed) { - const item = value[key]; - const path8 = [...state.path, key]; - for (let i2 = 0; i2 < schema.$_terms.patterns.length; ++i2) { - const pattern = schema.$_terms.patterns[i2]; - if (pattern.regex) { - const match = pattern.regex.test(key); - state.mainstay.tracer.debug(state, "rule", `pattern.${i2}`, match ? "pass" : "error"); - if (!match) { - continue; - } + currentHeight = currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH + KEYOP_SEGMENT_LENGTH; + index = void 0; + if (currentHeight > latestHEADinfo.height) { + return false; } else { - if (!pattern.schema.$_match(key, state.nest(pattern.schema, `pattern.${i2}`), prefs)) { - continue; - } - } - unprocessed.delete(key); - const localState = state.localize(path8, ancestors, { schema: pattern.rule, key }); - const result = pattern.rule.$_validate(item, localState, prefs); - if (result.errors) { - if (prefs.abortEarly) { - return { value, errors: result.errors }; - } - errors.push(...result.errors); - } - if (pattern.matches) { - matches[i2].push(key); - } - value[key] = result.value; - if (!pattern.fallthrough) { - break; + return null; } } + return true; + }; + })(); + const fetchMeta = async () => { + if (currentHeight > latestHEADinfo.height) { + return false; } - if (hasMatches) { - for (let i2 = 0; i2 < matches.length; ++i2) { - const match = matches[i2]; - if (!match) { - continue; - } - const stpm = schema.$_terms.patterns[i2].matches; - const localState = state.localize(state.path, ancestors, stpm); - const result = stpm.$_validate(match, localState, prefs); - if (result.errors) { - const details = Errors.details(result.errors, { override: false }); - details.matches = match; - const report = schema.$_createError("object.pattern.match", value, details, state, prefs); - if (prefs.abortEarly) { - return { value, errors: report }; - } - errors.push(report); - } + const meta = await esm_default("chelonia/db/getEntryMeta", contractID, currentHeight); + if (!meta) { + return false; + } + const { hash: newCurrentHash, ...newServerMeta } = meta; + currentHash = newCurrentHash; + serverMeta = newServerMeta; + return true; + }; + const stream = Readable.from(async function* () { + yield "["; + await fetchMeta(); + while (serverMeta && counter < limit) { + try { + const entry = await esm_default("chelonia/db/getEntry", currentHash); + if (!entry) break; + const currentPrefix = prefix; + prefix = ","; + counter++; + yield `${currentPrefix}"${strToB64( + JSON.stringify({ serverMeta, message: entry.serialize() }) + )}"`; + currentHeight++; + currentHash = void 0; + serverMeta = void 0; + if (options2.keyOps) { + while (await nextKeyOp() === null) ; + } + await fetchMeta(); + } catch (e2) { + console.error(e2, "[backend] streamEntriesAfter: read()"); + break; } } - } - if (!unprocessed.size || !schema.$_terms.keys && !schema.$_terms.patterns) { - return; - } - if (prefs.stripUnknown && typeof schema._flags.unknown === "undefined" || prefs.skipFunctions) { - const stripUnknown = prefs.stripUnknown ? prefs.stripUnknown === true ? true : !!prefs.stripUnknown.objects : false; - for (const key of unprocessed) { - if (stripUnknown) { - delete value[key]; - unprocessed.delete(key); - } else if (typeof value[key] === "function") { - unprocessed.delete(key); + yield "]"; + }(), { encoding: "utf-8", objectMode: false }); + stream.headers = { + "shelter-headinfo-head": String(latestHEADinfo.HEAD), + "shelter-headinfo-height": String(latestHEADinfo.height) + }; + return stream; + }, + // ======================= + // wrapper methods to add / lookup names + // ======================= + "backend/db/registerName": async function(name, value) { + const exists = await esm_default("backend/db/lookupName", name); + if (exists) { + throw new BackendErrorConflict("exists"); + } + await esm_default("chelonia.db/set", namespaceKey(name), value); + await esm_default("chelonia.db/set", `_private_cid2name_${value}`, name); + await appendToNamesIndex(name); + return { name, value }; + }, + "backend/db/lookupName": async function(name) { + const value = await esm_default("chelonia.db/get", namespaceKey(name)); + return value; + } + }); +} +var initedDB = false; +var initDB = async ({ skipDbPreloading } = {}) => { + installBaseSelectorsOnce(); + if (!initedDB) { + const backend = import_npm_nconf2.default.get("database:backend"); + const persistence = backend || (production ? "fs" : void 0); + const options2 = import_npm_nconf2.default.get("database:backendOptions"); + const ARCHIVE_MODE = import_npm_nconf2.default.get("server:archiveMode"); + if (persistence && persistence !== "mem") { + const Ctor = (await globImport_database_ts2(`./database-${persistence}.ts`)).default; + const instance = new Ctor(options2[persistence]); + await instance.init(); + currentBackend = instance; + currentCache = new import_npm_lru_cache.default({ + max: import_npm_nconf2.default.get("database:lruNumItems") ?? 1e4 + }); + const prefixes = Object.keys(prefixHandlers); + esm_default("sbp/selectors/overwrite", { + "chelonia.db/get": async function(prefixableKey, { bypassCache } = {}) { + const cache2 = currentCache; + if (!bypassCache) { + const lookupValue = cache2.get(prefixableKey); + if (lookupValue !== void 0) { + return lookupValue; + } + } + const [prefix, key] = parsePrefixableKey(prefixableKey); + let value = await currentBackend.readData(key); + if (value === void 0) { + return; } + value = prefixHandlers[prefix](value); + cache2.set(prefixableKey, value); + return value; + }, + "chelonia.db/set": async function(key, value) { + if (ARCHIVE_MODE) throw new Error("Unable to write in archive mode"); + checkKey(key); + if (key.startsWith("_private_immutable")) { + const existingValue = await currentBackend.readData(key); + if (existingValue !== void 0) { + throw new Error("Cannot set already set immutable key"); + } + } + await currentBackend.writeData(key, value); + const cache2 = currentCache; + prefixes.forEach((prefix) => { + cache2.delete(prefix + key); + }); + }, + "chelonia.db/delete": async function(key) { + if (ARCHIVE_MODE) throw new Error("Unable to write in archive mode"); + checkKey(key); + if (key.startsWith("_private_immutable")) { + throw new Error("Cannot delete immutable key"); + } + await currentBackend.deleteData(key); + const cache2 = currentCache; + prefixes.forEach((prefix) => { + cache2.delete(prefix + key); + }); + }, + "chelonia.db/iterKeys": () => { + return currentBackend.iterKeys(); + }, + "chelonia.db/keyCount": () => { + return currentBackend.keyCount(); } + }); + } + initedDB = true; + if (true) { + esm_default("sbp/selectors/lock", ["chelonia.db/get", "chelonia.db/set", "chelonia.db/delete", "chelonia.db/iterKeys"]); + } + } + if (skipDbPreloading || initedDB === "preloaded") return; + await Promise.all([initVapid(), initZkpp()]); + initedDB = "preloaded"; +}; +async function closeDB() { + if (isClosing) return; + isClosing = true; + try { + if (currentBackend) { + try { + await currentBackend.close(); + } catch (e2) { + console.error(e2, "Error closing DB"); } - const forbidUnknown = !Common.default(schema._flags.unknown, prefs.allowUnknown); - if (forbidUnknown) { - for (const unprocessedKey of unprocessed) { - const localState = state.localize([...state.path, unprocessedKey], []); - const report = schema.$_createError("object.unknown", value[unprocessedKey], { child: unprocessedKey }, localState, prefs, { flags: false }); - if (prefs.abortEarly) { - return { value, errors: report }; - } - errors.push(report); + currentBackend = null; + } + currentCache?.clear(); + currentCache = null; + if (false) { + initedDB = false; + } + } finally { + isClosing = false; + } +} +init_functions(); +async function createEntryFromFile(filepath, multicode) { + const buffer = await Deno.readFile(filepath); + const key = createCID(buffer, multicode); + return [key, buffer]; +} +function exit(x3, internal = false) { + const msg = x3 instanceof Error ? x3.message : String(x3); + if (internal) throw new Error(msg); + console.error("[chel]", red("Error:"), msg); + Deno.exit(1); +} +function isValidKey(key) { + return !/[\x00-\x1f\x7f\t\\/]/.test(key); +} +async function readRemoteData(src2, key) { + const buffer = await fetch(`${src2}/file/${key}`).then(async (r) => r.ok ? await r.arrayBuffer() : await Promise.reject(new Error(`failed network request to ${src2}: ${r.status} - ${r.statusText}`))); + return new Uint8Array(buffer); +} +async function revokeNet() { + await Deno.permissions.revoke({ name: "net" }); +} +var readJsonFile = async (file) => { + const contents = await Deno.readTextFile(resolve8(String(file))); + return JSON.parse(contents); +}; +var findManifestFiles = async (path8) => { + const visited = /* @__PURE__ */ new Set(); + const internal = async (path9) => { + if (visited.has(path9)) { + return /* @__PURE__ */ new Set(); + } + visited.add(path9); + const entries = Deno.readDir(path9); + const manifests = /* @__PURE__ */ new Set(); + for await (const entry of entries) { + const realPath2 = await Deno.realPath(join32(path9, entry.name)); + const info = await Deno.lstat(realPath2); + if (info.isDirectory) { + const subitems = await internal(realPath2); + for (const item of subitems) { + manifests.add(item); } + } else if (entry.name.toLowerCase().endsWith(".manifest.json")) { + manifests.add(join32(path9, entry.name)); } - }; - internals.Dependency = class { - constructor(rel, key, peers, paths, options2) { - this.rel = rel; - this.key = key; - this.peers = peers; - this.paths = paths; - this.options = options2; - } - describe() { - const desc = { - rel: this.rel, - peers: this.paths - }; - if (this.key !== null) { - desc.key = this.key.key; - } - if (this.peers[0].separator !== ".") { - desc.options = { ...desc.options, separator: this.peers[0].separator }; - } - if (this.options.isPresent) { - desc.options = { ...desc.options, isPresent: this.options.isPresent }; + } + return manifests; + }; + const realPath = await Deno.realPath(path8); + return internal(realPath); +}; +async function upload(args, internal = false) { + const { url: url2, files } = args; + let dbOpen = false; + if (!url2) { + await initDB({ skipDbPreloading: true }); + dbOpen = true; + } + try { + const uploaded = []; + const uploaderFn = url2 ? uploadEntryToURL : uploadEntryToDB; + for (const filepath_ of files) { + let type = multicodes.RAW; + let filepath = filepath_; + if (internal) { + if (filepath_[1] !== "|") throw new Error("Invalid path format"); + switch (filepath_[0]) { + case "r": + break; + case "m": + type = multicodes.SHELTER_CONTRACT_MANIFEST; + break; + case "t": + type = multicodes.SHELTER_CONTRACT_TEXT; + break; + default: + throw new Error("Unknown file type: " + filepath_[0]); } - return desc; + filepath = filepath_.slice(2); } - }; - internals.Keys = class extends Array { - concat(source) { - const result = this.slice(); - const keys = /* @__PURE__ */ new Map(); - for (let i2 = 0; i2 < result.length; ++i2) { - keys.set(result[i2].key, i2); - } - for (const item of source) { - const key = item.key; - const pos = keys.get(key); - if (pos !== void 0) { - result[pos] = { key, schema: result[pos].schema.concat(item.schema) }; - } else { - result.push(item); - } - } - return result; + const entry = await createEntryFromFile(filepath, type); + const destination = await uploaderFn(entry, url2); + if (!internal) { + console.log(green("uploaded:"), destination); + } else { + console.log(green(`${relative7(".", filepath)}:`), destination); } - }; + uploaded.push([filepath, destination]); + } + return uploaded; + } finally { + if (dbOpen) { + await closeDB(); + } } -}); -var require_function2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/function.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Keys = require_keys2(); - module14.exports = Keys.extend({ - type: "function", - properties: { - typeof: "function" - }, - rules: { - arity: { - method(n) { - assert2(Number.isSafeInteger(n) && n >= 0, "n must be a positive integer"); - return this.$_addRule({ name: "arity", args: { n } }); - }, - validate(value, helpers, { n }) { - if (value.length === n) { - return value; - } - return helpers.error("function.arity", { n }); - } - }, - class: { - method() { - return this.$_addRule("class"); - }, - validate(value, helpers) { - if (/^\s*class\s/.test(value.toString())) { - return value; - } - return helpers.error("function.class", { value }); - } - }, - minArity: { - method(n) { - assert2(Number.isSafeInteger(n) && n > 0, "n must be a strict positive integer"); - return this.$_addRule({ name: "minArity", args: { n } }); - }, - validate(value, helpers, { n }) { - if (value.length >= n) { - return value; - } - return helpers.error("function.minArity", { n }); - } - }, - maxArity: { - method(n) { - assert2(Number.isSafeInteger(n) && n >= 0, "n must be a positive integer"); - return this.$_addRule({ name: "maxArity", args: { n } }); - }, - validate(value, helpers, { n }) { - if (value.length <= n) { - return value; - } - return helpers.error("function.maxArity", { n }); - } - } - }, - messages: { - "function.arity": "{{#label}} must have an arity of {{#n}}", - "function.class": "{{#label}} must be a class", - "function.maxArity": "{{#label}} must have an arity lesser or equal to {{#n}}", - "function.minArity": "{{#label}} must have an arity greater or equal to {{#n}}" - } +} +async function uploadEntryToURL([cid, buffer], url2) { + const form = new FormData(); + form.append("hash", cid); + form.append("data", new Blob([buffer])); + return await fetch(`${url2}/dev-file`, { method: "POST", body: form }).then(handleFetchResult2("text")).then((r) => { + if (r !== `/file/${cid}`) { + throw new Error(`server returned bad URL: ${r}`); + } + return `${url2}${r}`; + }); +} +function uploadEntryToDB([cid, buffer]) { + return esm_default("chelonia.db/set", cid, Buffer12.from(buffer)).then(() => cid); +} +function handleFetchResult2(type) { + return async function(r) { + if (!r.ok) throw new Error(`${r.status}: ${r.statusText}`); + return await r[type](); + }; +} +var module2 = { + builder: (yargs) => { + return yargs.option("url", { + describe: "URL of a remote server", + requiresArg: true, + string: true + }).positional("files", { + describe: "Files to upload", + demandOption: true, + array: true, + type: "string" }); + }, + command: "upload ", + describe: "Requires read and write access to the destination.", + postHandler: (argv) => { + return void upload(argv); } +}; +var CONTRACT_TEXT_PREFIX = "t|"; +var CONTRACT_MANIFEST_PREFIX = "m|"; +var ContractBodySchema = object({ + contract: object({ file: string2() }), + contractSlim: object({ file: string2() }).optional() }); -var require_link2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/link.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Any = require_any2(); - var Common = require_common3(); - var Compile = require_compile2(); - var Errors = require_errors3(); - var internals = {}; - module14.exports = Any.extend({ - type: "link", - properties: { - schemaChain: true - }, - terms: { - link: { init: null, manifest: "single", register: false } - }, - args(schema, ref) { - return schema.ref(ref); - }, - validate(value, { schema, state, prefs }) { - assert2(schema.$_terms.link, "Uninitialized link schema"); - const linked = internals.generate(schema, value, state, prefs); - const ref = schema.$_terms.link[0].ref; - return linked.$_validate(value, state.nest(linked, `link:${ref.display}:${linked.type}`), prefs); - }, - generate(schema, value, state, prefs) { - return internals.generate(schema, value, state, prefs); - }, - rules: { - ref: { - method(ref) { - assert2(!this.$_terms.link, "Cannot reinitialize schema"); - ref = Compile.ref(ref); - assert2(ref.type === "value" || ref.type === "local", "Invalid reference type:", ref.type); - assert2(ref.type === "local" || ref.ancestor === "root" || ref.ancestor > 0, "Link cannot reference itself"); - const obj = this.clone(); - obj.$_terms.link = [{ ref }]; - return obj; - } - }, - relative: { - method(enabled2 = true) { - return this.$_setFlag("relative", enabled2); - } - } - }, - overrides: { - concat(source) { - assert2(this.$_terms.link, "Uninitialized link schema"); - assert2(Common.isSchema(source), "Invalid schema object"); - assert2(source.type !== "link", "Cannot merge type link with another link"); - const obj = this.clone(); - if (!obj.$_terms.whens) { - obj.$_terms.whens = []; - } - obj.$_terms.whens.push({ concat: source }); - return obj.$_mutateRebuild(); - } - }, - manifest: { - build(obj, desc) { - assert2(desc.link, "Invalid link description missing link"); - return obj.ref(desc.link); +async function deploy(args) { + const { manifests } = args; + const toUpload = []; + const manifestSet = /* @__PURE__ */ new Set(); + for (const manifestPath of manifests) { + try { + const realPath = await Deno.realPath(manifestPath); + const info = await Deno.lstat(realPath); + if (info.isDirectory) { + const items = await findManifestFiles(realPath); + for (const item of items) { + manifestSet.add(item); } + } else { + manifestSet.add(realPath); } + } catch { + console.warn(`Skipping invalid path: ${manifestPath}`); + continue; + } + } + for (const manifestPath of manifestSet) { + const manifestText = await Deno.readTextFile(manifestPath); + const json = JSON.parse(manifestText); + const body = ContractBodySchema.parse(JSON.parse(json.body)); + const dirname82 = dirname8(manifestPath); + toUpload.push(CONTRACT_TEXT_PREFIX + join8(dirname82, body.contract.file)); + if (body.contractSlim) { + toUpload.push(CONTRACT_TEXT_PREFIX + join8(dirname82, body.contractSlim.file)); + } + toUpload.push(CONTRACT_MANIFEST_PREFIX + manifestPath); + } + await upload({ ...args, files: toUpload }, true); +} +var module3 = { + builder: (yargs) => { + return yargs.option("url", { + describe: "URL of a remote server", + requiresArg: true, + string: true + }).positional("manifests", { + describe: "Manifest files to deploy (if a directory is passed in, all manifests in that directory, and sub-directories, will be added)", + demandOption: true, + array: true, + type: "string" }); - internals.generate = function(schema, value, state, prefs) { - let linked = state.mainstay.links.get(schema); - if (linked) { - return linked._generate(value, state, prefs).schema; - } - const ref = schema.$_terms.link[0].ref; - const { perspective, path: path8 } = internals.perspective(ref, state); - internals.assert(perspective, "which is outside of schema boundaries", ref, schema, state, prefs); - try { - linked = path8.length ? perspective.$_reach(path8) : perspective; - } catch { - internals.assert(false, "to non-existing schema", ref, schema, state, prefs); - } - internals.assert(linked.type !== "link", "which is another link", ref, schema, state, prefs); - if (!schema._flags.relative) { - state.mainstay.links.set(schema, linked); + }, + command: "deploy ", + describe: "", + postHandler: (argv) => { + return deploy(argv); + } +}; +init_esm(); +async function eventsAfter2({ limit, url: url2, contractID, height }) { + let dbOpen = false; + try { + let messages; + if (url2) { + messages = await getRemoteMessagesSince(url2, contractID, height, limit); + } else { + await initDB({ skipDbPreloading: true }); + dbOpen = true; + messages = await getMessagesSince(contractID, height, limit); + } + console.log(JSON.stringify(messages, null, 2)); + } catch (error2) { + exit(error2); + } finally { + if (dbOpen) { + await closeDB(); + } + } +} +async function getMessagesSince(contractID, sinceHeight, limit) { + const readable = await esm_default("backend/db/streamEntriesAfter", contractID, sinceHeight, limit); + return new Promise((resolve82, reject) => { + const data = []; + readable.on("readable", () => { + let chunk; + while (null !== (chunk = readable.read())) { + data.push(chunk); } - return linked._generate(value, state, prefs).schema; - }; - internals.perspective = function(ref, state) { - if (ref.type === "local") { - for (const { schema, key } of state.schemas) { - const id = schema._flags.id || key; - if (id === ref.path[0]) { - return { perspective: schema, path: ref.path.slice(1) }; - } - if (schema.$_terms.shared) { - for (const shared of schema.$_terms.shared) { - if (shared._flags.id === ref.path[0]) { - return { perspective: shared, path: ref.path.slice(1) }; - } - } - } + }); + readable.on("error", reject); + readable.on("end", () => { + const events = JSON.parse(data.join("")).map((s) => { + return JSON.parse(new TextDecoder().decode(decodeBase64(s))); + }); + resolve82(events); + }); + }); +} +async function getRemoteMessagesSince(src2, contractID, sinceHeight, limit) { + const response = await fetch(`${src2}/eventsAfter/${contractID}/${sinceHeight}`); + if (!response.ok) { + const bodyText = await response.text().catch(() => "") || ""; + throw new Error(`failed network request to ${src2}: ${response.status} - ${response.statusText} - '${bodyText}'`); + } + const b64messages = await response.json(); + if (b64messages.length > limit) { + b64messages.length = limit; + } + return b64messages.map((b64str) => JSON.parse(new TextDecoder().decode(decodeBase64(b64str)))); +} +var module4 = { + builder: (yargs) => { + return yargs.option("limit", { + describe: "Limit", + default: 50, + number: true, + requiresArg: true, + coerce(v2) { + if (!Number.isSafeInteger(v2) || v2 < 0) { + throw new Error("--limit must be a valid non-negative integer"); } - return { perspective: null, path: null }; - } - if (ref.ancestor === "root") { - return { perspective: state.schemas[state.schemas.length - 1].schema, path: ref.path }; - } - return { perspective: state.schemas[ref.ancestor] && state.schemas[ref.ancestor].schema, path: ref.path }; - }; - internals.assert = function(condition, message, ref, schema, state, prefs) { - if (condition) { - return; + return v2; } - assert2(false, `"${Errors.label(schema._flags, state, prefs)}" contains link reference "${ref.display}" ${message}`); - }; + }).option("url", { + describe: "URL of a remote server", + string: true + }).positional("contractID", { + describe: "Contract ID", + demandOption: true, + type: "string" + }).positional("height", { + describe: "Height", + demandOption: true, + type: "number" + }); + }, + command: "eventsAfter ", + describe: "Displays a JSON array of the first LIMIT events that happened in a given contract, since a given entry identified by its hash.\n\n- Older events are displayed first.\n- The output is parseable with tools such as 'jq'.\n- If --url is given, then its /eventsAfter REST endpoint will be called.\n", + postHandler: (argv) => { + return eventsAfter2(argv); } -}); -var require_number2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/number.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Any = require_any2(); - var Common = require_common3(); - var internals = { - numberRx: /^\s*[+-]?(?:(?:\d+(?:\.\d*)?)|(?:\.\d+))(?:e([+-]?\d+))?\s*$/i, - precisionRx: /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/, - exponentialPartRegex: /[eE][+-]?\d+$/, - leadingSignAndZerosRegex: /^[+-]?(0*)?/, - dotRegex: /\./, - trailingZerosRegex: /0+$/, - decimalPlaces(value) { - const str = value.toString(); - const dindex = str.indexOf("."); - const eindex = str.indexOf("e"); - return (dindex < 0 ? 0 : (eindex < 0 ? str.length : eindex) - dindex - 1) + (eindex < 0 ? 0 : Math.max(0, -parseInt(str.slice(eindex + 1)))); - } - }; - module14.exports = Any.extend({ - type: "number", - flags: { - unsafe: { default: false } - }, - coerce: { - from: "string", - method(value, { schema, error: error2 }) { - const matches = value.match(internals.numberRx); - if (!matches) { - return; - } - value = value.trim(); - const result = { value: parseFloat(value) }; - if (result.value === 0) { - result.value = 0; - } - if (!schema._flags.unsafe) { - if (value.match(/e/i)) { - if (internals.extractSignificantDigits(value) !== internals.extractSignificantDigits(String(result.value))) { - result.errors = error2("number.unsafe"); - return result; - } - } else { - const string3 = result.value.toString(); - if (string3.match(/e/i)) { - return result; - } - if (string3 !== internals.normalizeDecimal(value)) { - result.errors = error2("number.unsafe"); - return result; - } - } - } - return result; - } - }, - validate(value, { schema, error: error2, prefs }) { - if (value === Infinity || value === -Infinity) { - return { value, errors: error2("number.infinity") }; - } - if (!Common.isNumber(value)) { - return { value, errors: error2("number.base") }; - } - const result = { value }; - if (prefs.convert) { - const rule = schema.$_getRule("precision"); - if (rule) { - const precision = Math.pow(10, rule.args.limit); - result.value = Math.round(result.value * precision) / precision; - } - } - if (result.value === 0) { - result.value = 0; - } - if (!schema._flags.unsafe && (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER)) { - result.errors = error2("number.unsafe"); - } - return result; - }, - rules: { - compare: { - method: false, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(value, limit, operator)) { - return value; - } - return helpers.error("number." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.isNumber, - message: "must be a number" - } - ] - }, - greater: { - method(limit) { - return this.$_addRule({ name: "greater", method: "compare", args: { limit }, operator: ">" }); - } - }, - integer: { - method() { - return this.$_addRule("integer"); - }, - validate(value, helpers) { - if (Math.trunc(value) - value === 0) { - return value; - } - return helpers.error("number.integer"); - } - }, - less: { - method(limit) { - return this.$_addRule({ name: "less", method: "compare", args: { limit }, operator: "<" }); - } - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "compare", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "compare", args: { limit }, operator: ">=" }); - } - }, - multiple: { - method(base2) { - const baseDecimalPlace = typeof base2 === "number" ? internals.decimalPlaces(base2) : null; - const pfactor = Math.pow(10, baseDecimalPlace); - return this.$_addRule({ - name: "multiple", - args: { - base: base2, - baseDecimalPlace, - pfactor - } - }); - }, - validate(value, helpers, { base: base2, baseDecimalPlace, pfactor }, options2) { - const valueDecimalPlace = internals.decimalPlaces(value); - if (valueDecimalPlace > baseDecimalPlace) { - return helpers.error("number.multiple", { multiple: options2.args.base, value }); - } - return Math.round(pfactor * value) % Math.round(pfactor * base2) === 0 ? value : helpers.error("number.multiple", { multiple: options2.args.base, value }); - }, - args: [ - { - name: "base", - ref: true, - assert: (value) => typeof value === "number" && isFinite(value) && value > 0, - message: "must be a positive number" - }, - "baseDecimalPlace", - "pfactor" - ], - multi: true - }, - negative: { - method() { - return this.sign("negative"); - } - }, - port: { - method() { - return this.$_addRule("port"); - }, - validate(value, helpers) { - if (Number.isSafeInteger(value) && value >= 0 && value <= 65535) { - return value; - } - return helpers.error("number.port"); - } - }, - positive: { - method() { - return this.sign("positive"); - } - }, - precision: { - method(limit) { - assert2(Number.isSafeInteger(limit), "limit must be an integer"); - return this.$_addRule({ name: "precision", args: { limit } }); - }, - validate(value, helpers, { limit }) { - const places = value.toString().match(internals.precisionRx); - const decimals = Math.max((places[1] ? places[1].length : 0) - (places[2] ? parseInt(places[2], 10) : 0), 0); - if (decimals <= limit) { - return value; - } - return helpers.error("number.precision", { limit, value }); - }, - convert: true - }, - sign: { - method(sign2) { - assert2(["negative", "positive"].includes(sign2), "Invalid sign", sign2); - return this.$_addRule({ name: "sign", args: { sign: sign2 } }); - }, - validate(value, helpers, { sign: sign2 }) { - if (sign2 === "negative" && value < 0 || sign2 === "positive" && value > 0) { - return value; - } - return helpers.error(`number.${sign2}`); - } - }, - unsafe: { - method(enabled2 = true) { - assert2(typeof enabled2 === "boolean", "enabled must be a boolean"); - return this.$_setFlag("unsafe", enabled2); - } +}; +init_esm(); +async function get({ key, url: url2 }) { + let dbOpen = false; + if (!url2) { + await initDB({ skipDbPreloading: true }); + dbOpen = true; + } + try { + const data = url2 ? await readRemoteData(url2, key) : await esm_default("chelonia.db/get", key); + if (data === void 0) exit(`no entry found for ${key}`); + if (typeof data === "string") { + console.log(data); + } else { + await writeAll(Deno.stdout, data); + } + } catch (error2) { + exit(error2); + } finally { + if (dbOpen) { + await closeDB(); + } + } +} +var module5 = { + builder: (yargs) => { + return yargs.option("url", { + describe: "URL of a remote server", + string: true + }).positional("key", { + describe: "Database key", + demandOption: true, + type: "string" + }); + }, + command: "get ", + describe: "Retrieves the entry associated with a given key, from a given database or server.\n\n- The output can be piped to a file, like this: chel get https://url.com mygreatlongkey > file.png", + postHandler: (argv) => { + return get(argv); + } +}; +init_functions(); +async function hash22({ filename }, multicode = multicodes.RAW, internal = false) { + const [cid] = await createEntryFromFile(filename, multicode); + if (!internal) { + console.log(`CID(${filename}):`, cid); + } + return cid; +} +var module6 = { + builder: (yargs) => { + return yargs.positional("filename", { + describe: "File name", + demandOption: true, + type: "string" + }); + }, + command: "hash ", + describe: "Computes and logs the content identifier (CID) for the given file.\n' + 'File contents will be interpreted as raw binary data, unless the file extension is '.json'.", + postHandler: (argv) => { + return void hash22(argv); + } +}; +init_esm6(); +var keygen2 = async (args) => { + await revokeNet(); + const key = keygen(EDWARDS25519SHA512BATCH); + const pubKeyData = { + version: "1.0.0", + pubkey: serializeKey(key, false) + }; + const keyData = { + ...pubKeyData, + privkey: serializeKey(key, true) + }; + const result = JSON.stringify(keyData); + const pubResult = JSON.stringify(pubKeyData); + const idx = keyId(key).slice(-12); + const outFile = args.out || `${EDWARDS25519SHA512BATCH}-${idx}.json`; + const pubOutFile = args.pubout || `${EDWARDS25519SHA512BATCH}-${idx}.pub.json`; + await Deno.writeTextFile(outFile, result); + console.log(green("wrote:"), outFile, blue("(secret)")); + await Deno.writeTextFile(pubOutFile, pubResult); + console.log(green("wrote:"), pubOutFile, blue("(public)")); +}; +var module7 = { + builder: (yargs) => { + return yargs.option("out", { + describe: "File name for the secret key", + requiresArg: true, + string: true + }).option("pubout", { + describe: "File name for the public key", + requiresArg: true, + string: true + }); + }, + command: "keygen", + describe: "", + postHandler: (argv) => { + return keygen2(argv); + } +}; +init_esm6(); +init_functions(); +function isSigningKeyDescriptor(obj) { + return obj !== null && typeof obj === "object" && typeof obj.privkey === "string"; +} +async function manifest(args) { + await revokeNet(); + const { signingKey: keyFileRaw, contractBundle: contractFileRaw } = args; + if (typeof keyFileRaw !== "string" || typeof contractFileRaw !== "string") { + exit("Missing or invalid key or contract file"); + } + const keyFile = keyFileRaw; + const contractFile = contractFileRaw; + const parsedFilepath = parse7(contractFile); + const { name: contractFileName, base: contractBasename, dir: contractDir } = parsedFilepath; + const name = args.name || contractFileName; + const version3 = args.contractVersion || "x"; + const slim = args.slim; + const outFile = args.out || join8(contractDir, `${contractFileName}.${version3}.manifest.json`); + if (!keyFile) exit("Missing signing key file"); + const signingKeyDescriptorRaw = await readJsonFile(keyFile); + if (!isSigningKeyDescriptor(signingKeyDescriptorRaw)) { + exit("Invalid signing key file: missing or invalid privkey", true); + } + const signingKeyDescriptor = signingKeyDescriptorRaw; + const signingKey = deserializeKey(signingKeyDescriptor.privkey); + const publicKeys = Array.from(new Set( + [serializeKey(signingKey, false)].concat(...await Promise.all(args.key?.map( + async (kf) => { + if (typeof kf !== "string" && typeof kf !== "number") { + exit(`Invalid key file reference: ${String(kf)}`); } - }, - cast: { - string: { - from: (value) => typeof value === "number", - to(value, helpers) { - return value.toString(); - } + const descriptor = await readJsonFile(String(kf)); + const key = deserializeKey(descriptor.pubkey); + if (key.type !== EDWARDS25519SHA512BATCH) { + exit(`Invalid key type ${key.type}; only ${EDWARDS25519SHA512BATCH} keys are supported.`); } - }, - messages: { - "number.base": "{{#label}} must be a number", - "number.greater": "{{#label}} must be greater than {{#limit}}", - "number.infinity": "{{#label}} cannot be infinity", - "number.integer": "{{#label}} must be an integer", - "number.less": "{{#label}} must be less than {{#limit}}", - "number.max": "{{#label}} must be less than or equal to {{#limit}}", - "number.min": "{{#label}} must be greater than or equal to {{#limit}}", - "number.multiple": "{{#label}} must be a multiple of {{#multiple}}", - "number.negative": "{{#label}} must be a negative number", - "number.port": "{{#label}} must be a valid port", - "number.positive": "{{#label}} must be a positive number", - "number.precision": "{{#label}} must have no more than {{#limit}} decimal places", - "number.unsafe": "{{#label}} must be a safe number" - } - }); - internals.extractSignificantDigits = function(value) { - return value.replace(internals.exponentialPartRegex, "").replace(internals.dotRegex, "").replace(internals.trailingZerosRegex, "").replace(internals.leadingSignAndZerosRegex, ""); - }; - internals.normalizeDecimal = function(str) { - str = str.replace(/^\+/, "").replace(/\.0*$/, "").replace(/^(-?)\.([^\.]*)$/, "$10.$2").replace(/^(-?)0+([0-9])/, "$1$2"); - if (str.includes(".") && str.endsWith("0")) { - str = str.replace(/0+$/, ""); - } - if (str === "-0") { - return "0"; + return serializeKey(key, false); } - return str; + ) || [])) + )); + const body = { + name, + version: version3, + contract: { + hash: await hash22({ ...args, filename: contractFile }, multicodes.SHELTER_CONTRACT_TEXT, true), + file: contractBasename + }, + signingKeys: publicKeys + }; + if (typeof slim === "string" && slim !== "") { + body.contractSlim = { + file: basename8(slim), + hash: await hash22({ ...args, filename: slim }, multicodes.SHELTER_CONTRACT_TEXT, true) }; } -}); -var require_object2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/object.js"(exports2, module14) { - "use strict"; - var Keys = require_keys2(); - module14.exports = Keys.extend({ - type: "object", - cast: { - map: { - from: (value) => value && typeof value === "object", - to(value, helpers) { - return new Map(Object.entries(value)); - } - } - } + const serializedBody = JSON.stringify(body); + const head = { manifestVersion: "1.0.0" }; + const serializedHead = JSON.stringify(head); + const manifest2 = JSON.stringify({ + head: serializedHead, + body: serializedBody, + signature: { + keyId: keyId(signingKey), + value: sign(signingKey, serializedBody + serializedHead) + } + }); + if (args.out === "-") { + console.log(manifest2); + } else { + Deno.writeTextFileSync(outFile, manifest2); + console.log(green("wrote:"), outFile); + } +} +var module8 = { + builder: (yargs) => { + return yargs.option("key", { + coerce: (v2) => Array.isArray(v2) ? v2 : [v2], + describe: "Additional public key", + requiresArg: true, + string: true + }).alias("k", "key").option("out", { + describe: "Manifest file name", + requiresArg: true, + string: true + }).option("name", { + describe: "Contract name", + requiresArg: true, + string: true + }).alias("n", "name").option("slim", { + describe: "Slim contract bundle", + requiresArg: true, + string: true + }).alias("s", "slim").option("contract-version", { + describe: "Contract version", + requiresArg: true, + string: true + }).alias("V", "contract-version").positional("signingKey", { + describe: "Signing key file", + demandOption: true, + type: "string" + }).positional("contractBundle", { + describe: "Contract bundle", + demandOption: true, + type: "string" }); + }, + command: "manifest [-k|--key ] [-k|--key ...] [--out ] [-s|--slim ] [-V|--contract-version ] ", + describe: "Produce a signed manifest from a contract.\nIf unspecified, is set to 'x'.", + postHandler: (argv) => { + return manifest(argv); } +}; +init_esm(); +var import_npm_nconf3 = __toESM(require_nconf()); +var globImport_serve_database_ts = __glob({ + "./serve/database-fs.ts": () => Promise.resolve().then(() => (init_database_fs(), database_fs_exports)), + "./serve/database-redis.ts": () => Promise.resolve().then(() => (init_database_redis(), database_redis_exports)), + "./serve/database-router.test.ts": () => Promise.resolve().then(() => (init_database_router_test(), database_router_test_exports)), + "./serve/database-router.ts": () => Promise.resolve().then(() => (init_database_router(), database_router_exports)), + "./serve/database-sqlite.ts": () => Promise.resolve().then(() => (init_database_sqlite(), database_sqlite_exports)) }); -var require_errors4 = __commonJS({ - "node_modules/.deno/@hapi+address@5.1.1/node_modules/@hapi/address/dist/errors.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.errorCode = exports2.errorCodes = void 0; - exports2.errorCodes = { - EMPTY_STRING: "Address must be a non-empty string", - FORBIDDEN_UNICODE: "Address contains forbidden Unicode characters", - MULTIPLE_AT_CHAR: "Address cannot contain more than one @ character", - MISSING_AT_CHAR: "Address must contain one @ character", - EMPTY_LOCAL: "Address local part cannot be empty", - ADDRESS_TOO_LONG: "Address too long", - LOCAL_TOO_LONG: "Address local part too long", - EMPTY_LOCAL_SEGMENT: "Address local part contains empty dot-separated segment", - INVALID_LOCAL_CHARS: "Address local part contains invalid character", - DOMAIN_NON_EMPTY_STRING: "Domain must be a non-empty string", - DOMAIN_TOO_LONG: "Domain too long", - DOMAIN_INVALID_UNICODE_CHARS: "Domain contains forbidden Unicode characters", - DOMAIN_INVALID_CHARS: "Domain contains invalid character", - DOMAIN_INVALID_TLDS_CHARS: "Domain contains invalid tld character", - DOMAIN_SEGMENTS_COUNT: "Domain lacks the minimum required number of segments", - DOMAIN_SEGMENTS_COUNT_MAX: "Domain contains too many segments", - DOMAIN_FORBIDDEN_TLDS: "Domain uses forbidden TLD", - DOMAIN_EMPTY_SEGMENT: "Domain contains empty dot-separated segment", - DOMAIN_LONG_SEGMENT: "Domain contains dot-separated segment that is too long" - }; - function errorCode(code2) { - return { code: code2, error: exports2.errorCodes[code2] }; - } - exports2.errorCode = errorCode; - } -}); -var require_domain = __commonJS({ - "node_modules/.deno/@hapi+address@5.1.1/node_modules/@hapi/address/dist/domain.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.validateDomainOptions = exports2.isDomainValid = exports2.analyzeDomain = void 0; - var Url = __require2("url"); - var errors_1 = require_errors4(); - var MIN_DOMAIN_SEGMENTS = 2; - var NON_ASCII_RX = /[^\x00-\x7f]/; - var DOMAIN_CONTROL_RX = /[\x00-\x20@\:\/\\#!\$&\'\(\)\*\+,;=\?]/; - var TLD_SEGMENT_RX = /^[a-zA-Z](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$/; - var DOMAIN_SEGMENT_RX = /^[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$/; - var DOMAIN_UNDERSCORE_SEGMENT_RX = /^[a-zA-Z0-9_](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$/; - var URL_IMPL = Url.URL || URL; - function isTldsAllow(tlds) { - return !!tlds.allow; - } - function analyzeDomain(domain, options2 = {}) { - if (!domain) { - return (0, errors_1.errorCode)("DOMAIN_NON_EMPTY_STRING"); - } - if (typeof domain !== "string") { - throw new Error("Invalid input: domain must be a string"); - } - if (domain.length > 256) { - return (0, errors_1.errorCode)("DOMAIN_TOO_LONG"); - } - const ascii = !NON_ASCII_RX.test(domain); - if (!ascii) { - if (options2.allowUnicode === false) { - return (0, errors_1.errorCode)("DOMAIN_INVALID_UNICODE_CHARS"); - } - domain = domain.normalize("NFC"); - } - if (DOMAIN_CONTROL_RX.test(domain)) { - return (0, errors_1.errorCode)("DOMAIN_INVALID_CHARS"); - } - domain = punycode(domain); - if (options2.allowFullyQualified && domain[domain.length - 1] === ".") { - domain = domain.slice(0, -1); - } - const minDomainSegments = options2.minDomainSegments || MIN_DOMAIN_SEGMENTS; - const segments = domain.split("."); - if (segments.length < minDomainSegments) { - return (0, errors_1.errorCode)("DOMAIN_SEGMENTS_COUNT"); - } - if (options2.maxDomainSegments) { - if (segments.length > options2.maxDomainSegments) { - return (0, errors_1.errorCode)("DOMAIN_SEGMENTS_COUNT_MAX"); - } - } - const tlds = options2.tlds; - if (tlds) { - const tld = segments[segments.length - 1].toLowerCase(); - if (isTldsAllow(tlds)) { - if (!tlds.allow.has(tld)) { - return (0, errors_1.errorCode)("DOMAIN_FORBIDDEN_TLDS"); - } - } else if (tlds.deny.has(tld)) { - return (0, errors_1.errorCode)("DOMAIN_FORBIDDEN_TLDS"); - } - } - for (let i2 = 0; i2 < segments.length; ++i2) { - const segment = segments[i2]; - if (!segment.length) { - return (0, errors_1.errorCode)("DOMAIN_EMPTY_SEGMENT"); - } - if (segment.length > 63) { - return (0, errors_1.errorCode)("DOMAIN_LONG_SEGMENT"); - } - if (i2 < segments.length - 1) { - if (options2.allowUnderscore) { - if (!DOMAIN_UNDERSCORE_SEGMENT_RX.test(segment)) { - return (0, errors_1.errorCode)("DOMAIN_INVALID_CHARS"); - } +async function migrate(args) { + const { to } = args; + if (args.fromConfig) { + const fromConfig = parse8(await readFile2(args.fromConfig, { encoding: "utf-8", flag: "r" })); + const backend = import_npm_nconf3.default.get("database:backend"); + const fromBackend = fromConfig?.database?.backend; + if (fromBackend !== backend) { + console.warn(`--from-config has backend ${fromBackend} but --from is ${backend}`); + } + const fromConfigOpts = fromConfig?.database?.backendOptions?.[backend] || {}; + import_npm_nconf3.default.set(`database:backendOptions:${backend}`, fromConfigOpts); + } + try { + await initDB({ skipDbPreloading: true }); + } catch (e2) { + console.error("Error setting up database"); + exit(e2); + throw e2; + } + let backendTo; + try { + try { + let toConfigOpts; + if (args.toConfig) { + const toConfig = parse8(await readFile2(args.toConfig, { encoding: "utf-8", flag: "r" })); + const toBackend = toConfig?.database?.backend; + if (toBackend !== to) { + console.warn(`--to-config has backend ${toBackend} but --to is ${to}`); + } + toConfigOpts = toConfig?.database?.backendOptions?.[to] || {}; + } else { + toConfigOpts = import_npm_nconf3.default.get(`database:backendOptions:${to}`) || {}; + } + const Ctor = (await globImport_serve_database_ts(`./serve/database-${to}.ts`)).default; + backendTo = new Ctor(toConfigOpts); + await backendTo.init(); + } catch (error2) { + exit(error2); + throw error2; + } + const numKeys2 = await esm_default("chelonia.db/keyCount"); + let numMigratedKeys = 0; + let numVisitedKeys = 0; + const reportStatus = () => { + console.log(`${green("Migrated:")} ${numMigratedKeys} entries`); + }; + const checkAndExit = (() => { + let interruptCount = 0; + let shouldExit = 0; + const handleSignal = (signal, code2) => { + process3.on(signal, () => { + shouldExit = 128 + code2; + if (++interruptCount < 3) { + console.error(`Received signal ${signal} (${code2}). Finishing current operation.`); } else { - if (!DOMAIN_SEGMENT_RX.test(segment)) { - return (0, errors_1.errorCode)("DOMAIN_INVALID_CHARS"); - } - } - } else { - if (!TLD_SEGMENT_RX.test(segment)) { - return (0, errors_1.errorCode)("DOMAIN_INVALID_TLDS_CHARS"); + console.error(`Received signal ${signal} (${code2}). Force quitting.`); + reportStatus(); + exit(shouldExit); } + }); + }; + const checkAndExit2 = async () => { + if (shouldExit) { + await backendTo.close(); + reportStatus(); + exit(shouldExit); } + }; + [ + ["SIGHUP", 1], + ["SIGINT", 2], + ["SIGQUIT", 3], + ["SIGTERM", 15], + ["SIGUSR1", 10], + ["SIGUSR2", 11] + ].forEach(([signal, code2]) => handleSignal(signal, code2)); + return checkAndExit2; + })(); + let lastReportedPercentage = 0; + for await (const key of esm_default("chelonia.db/iterKeys")) { + numVisitedKeys++; + if (!isValidKey(key)) { + console.debug("Skipping invalid key", key); + continue; } - return null; - } - exports2.analyzeDomain = analyzeDomain; - function isDomainValid(domain, options2) { - return !analyzeDomain(domain, options2); - } - exports2.isDomainValid = isDomainValid; - function punycode(domain) { - if (domain.includes("%")) { - domain = domain.replace(/%/g, "%25"); - } + let value; try { - return new URL_IMPL(`http://${domain}`).host; - } catch (err) { - return domain; + value = await esm_default("chelonia.db/get", `any:${key}`); + } catch (e2) { + reportStatus(); + console.error(`Error reading from source database key '${key}'`, e2); + exit(1); + throw e2; } - } - function validateDomainOptions(options2) { - if (!options2) { - return; + await checkAndExit(); + if (value === void 0) { + console.debug("Skipping empty key", key); + continue; } - if (typeof options2.tlds !== "object") { - throw new Error("Invalid options: tlds must be a boolean or an object"); + try { + await backendTo.writeData(key, value); + } catch (e2) { + reportStatus(); + console.error(`Error writing to target database key '${key}'`, e2); + exit(1); + throw e2; } - if (isTldsAllow(options2.tlds)) { - if (options2.tlds.allow instanceof Set === false) { - throw new Error("Invalid options: tlds.allow must be a Set object or true"); - } - if (options2.tlds.deny) { - throw new Error("Invalid options: cannot specify both tlds.allow and tlds.deny lists"); - } - } else { - if (options2.tlds.deny instanceof Set === false) { - throw new Error("Invalid options: tlds.deny must be a Set object"); - } + await checkAndExit(); + ++numMigratedKeys; + const percentage = Math.floor(numVisitedKeys / numKeys2 * 100); + if (percentage - lastReportedPercentage >= 10) { + lastReportedPercentage = percentage; + console.log(`Migrating... ${percentage}% done`); } } - exports2.validateDomainOptions = validateDomainOptions; + reportStatus(); + } finally { + await Promise.all([backendTo?.close(), closeDB()]); } -}); -var require_email = __commonJS({ - "node_modules/.deno/@hapi+address@5.1.1/node_modules/@hapi/address/dist/email.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.isEmailValid = exports2.analyzeEmail = void 0; - var Util = __require2("util"); - var domain_1 = require_domain(); - var errors_1 = require_errors4(); - var NON_ASCII_RX = /[^\x00-\x7f]/; - var ENCODER_IMPL = new (Util.TextEncoder || TextEncoder)(); - function analyzeEmail(email2, options2) { - return validateEmail(email2, options2); +} +var module9 = { + builder: (yargs) => { + return yargs.option("from", { + describe: "Source backend", + demandOption: true, + requiresArg: true, + string: true + }).alias("database:backend", "from").option("from-config", { + describe: "Source backend configuration", + requiresArg: true, + string: true + }).option("to", { + describe: "Destination backend", + demandOption: true, + requiresArg: true, + string: true + }).option("to-config", { + describe: "Destination backend configuration", + requiresArg: true, + string: true + }).strict(false).strictCommands(true); + }, + command: "migrate", + describe: "Reads all key-value pairs from a given database and creates or updates another database accordingly.\n\n- The output database will be created if necessary.\n- The source database won't be modified nor deleted.\n- Invalid key-value pairs entries will be skipped.\n- Requires read and write access to the source.\n", + postHandler: (argv) => { + return migrate(argv); + } +}; +var VALID_VERSION = /^[a-zA-Z0-9_+-][a-zA-Z0-9._+-]*[a-zA-Z0-9_+-]?$/; +var RESERVED_FILE_CHARS_REPLACE = /[\x00/\\:*?"<>|]/g; +var projectRoot; +var cheloniaConfig; +function sanitizeContractName(contractName) { + return contractName.replace(RESERVED_FILE_CHARS_REPLACE, "_").replace(/\.\./g, "__"); +} +async function pin(args) { + const version3 = args["manifest-version"]; + const manifestPath = args.manifest; + projectRoot = args["dir"] || process4.cwd(); + try { + if (!manifestPath) { + await loadCheloniaConfig(); + return; } - exports2.analyzeEmail = analyzeEmail; - function isEmailValid(email2, options2) { - return !validateEmail(email2, options2); + console.log(cyan(`\u{1F4CC} Requesting pin to version: ${version3}`)); + console.log(gray(`Manifest: ${manifestPath}`)); + await loadCheloniaConfig(); + const fullManifestPath = join62(projectRoot, manifestPath); + if (!existsSync(fullManifestPath)) { + exit(`Manifest file not found: ${manifestPath}`); } - exports2.isEmailValid = isEmailValid; - function validateEmail(email2, options2 = {}) { - if (typeof email2 !== "string") { - throw new Error("Invalid input: email must be a string"); - } - if (!email2) { - return (0, errors_1.errorCode)("EMPTY_STRING"); - } - const ascii = !NON_ASCII_RX.test(email2); - if (!ascii) { - if (options2.allowUnicode === false) { - return (0, errors_1.errorCode)("FORBIDDEN_UNICODE"); - } - email2 = email2.normalize("NFC"); - } - const parts = email2.split("@"); - if (parts.length !== 2) { - return parts.length > 2 ? (0, errors_1.errorCode)("MULTIPLE_AT_CHAR") : (0, errors_1.errorCode)("MISSING_AT_CHAR"); - } - const [local, domain] = parts; - if (!local) { - return (0, errors_1.errorCode)("EMPTY_LOCAL"); - } - if (!options2.ignoreLength) { - if (email2.length > 254) { - return (0, errors_1.errorCode)("ADDRESS_TOO_LONG"); - } - if (ENCODER_IMPL.encode(local).length > 64) { - return (0, errors_1.errorCode)("LOCAL_TOO_LONG"); - } - } - return validateLocal(local, ascii) || (0, domain_1.analyzeDomain)(domain, options2); + const { contractName, fullContractName, contractFiles, manifestVersion } = await parseManifest(fullManifestPath); + if (!manifestVersion || !VALID_VERSION.test(manifestVersion)) { + exit(`Invalid manifest version: ${manifestVersion}`); } - function validateLocal(local, ascii) { - const segments = local.split("."); - for (const segment of segments) { - if (!segment.length) { - return (0, errors_1.errorCode)("EMPTY_LOCAL_SEGMENT"); - } - if (ascii) { - if (!ATEXT_RX.test(segment)) { - return (0, errors_1.errorCode)("INVALID_LOCAL_CHARS"); - } - continue; - } - for (const char of segment) { - if (ATEXT_RX.test(char)) { - continue; - } - const binary = toBinary(char); - if (!ATOM_RX.test(binary)) { - return (0, errors_1.errorCode)("INVALID_LOCAL_CHARS"); - } - } + console.log(blue(`Contract name: ${fullContractName}`)); + console.log(blue(`Manifest version: ${manifestVersion}`)); + if (version3) { + if (version3 !== manifestVersion) { + console.error(red(`\u274C Version mismatch: CLI version (${version3}) does not match manifest version (${manifestVersion})`)); + console.error(yellow(`\u{1F4A1} To pin this contract, use: chel pin ${manifestVersion} ${manifestPath}`)); + exit("Version mismatch between CLI and manifest"); } - return null; + console.log(green(`\u2705 Version validation passed: ${version3}`)); } - function toBinary(char) { - return Array.from(ENCODER_IMPL.encode(char), (v2) => String.fromCharCode(v2)).join(""); - } - var ATEXT_RX = /^[\w!#\$%&'\*\+\-/=\?\^`\{\|\}~]+$/; - var ATOM_RX = new RegExp([ - // %xC2-DF UTF8-tail - "(?:[\\xc2-\\xdf][\\x80-\\xbf])", - // %xE0 %xA0-BF UTF8-tail %xE1-EC 2( UTF8-tail ) %xED %x80-9F UTF8-tail %xEE-EF 2( UTF8-tail ) - "(?:\\xe0[\\xa0-\\xbf][\\x80-\\xbf])|(?:[\\xe1-\\xec][\\x80-\\xbf]{2})|(?:\\xed[\\x80-\\x9f][\\x80-\\xbf])|(?:[\\xee-\\xef][\\x80-\\xbf]{2})", - // %xF0 %x90-BF 2( UTF8-tail ) %xF1-F3 3( UTF8-tail ) %xF4 %x80-8F 2( UTF8-tail ) - "(?:\\xf0[\\x90-\\xbf][\\x80-\\xbf]{2})|(?:[\\xf1-\\xf3][\\x80-\\xbf]{3})|(?:\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2})" - ].join("|")); - } -}); -var require_uri = __commonJS({ - "node_modules/.deno/@hapi+address@5.1.1/node_modules/@hapi/address/dist/uri.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.uriRegex = exports2.ipVersions = void 0; - var hoek_1 = require_lib(); - function generate() { - const rfc39862 = {}; - const hexDigit = "\\dA-Fa-f"; - const hexDigitOnly = "[" + hexDigit + "]"; - const unreserved = "\\w-\\.~"; - const subDelims = "!\\$&'\\(\\)\\*\\+,;="; - const pctEncoded = "%" + hexDigit; - const pchar = unreserved + pctEncoded + subDelims + ":@"; - const pcharOnly = "[" + pchar + "]"; - const decOctect = "(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])"; - rfc39862.ipv4address = "(?:" + decOctect + "\\.){3}" + decOctect; - const h16 = hexDigitOnly + "{1,4}"; - const ls32 = "(?:" + h16 + ":" + h16 + "|" + rfc39862.ipv4address + ")"; - const IPv6SixHex = "(?:" + h16 + ":){6}" + ls32; - const IPv6FiveHex = "::(?:" + h16 + ":){5}" + ls32; - const IPv6FourHex = "(?:" + h16 + ")?::(?:" + h16 + ":){4}" + ls32; - const IPv6ThreeHex = "(?:(?:" + h16 + ":){0,1}" + h16 + ")?::(?:" + h16 + ":){3}" + ls32; - const IPv6TwoHex = "(?:(?:" + h16 + ":){0,2}" + h16 + ")?::(?:" + h16 + ":){2}" + ls32; - const IPv6OneHex = "(?:(?:" + h16 + ":){0,3}" + h16 + ")?::" + h16 + ":" + ls32; - const IPv6NoneHex = "(?:(?:" + h16 + ":){0,4}" + h16 + ")?::" + ls32; - const IPv6NoneHex2 = "(?:(?:" + h16 + ":){0,5}" + h16 + ")?::" + h16; - const IPv6NoneHex3 = "(?:(?:" + h16 + ":){0,6}" + h16 + ")?::"; - rfc39862.ipv4Cidr = "(?:\\d|[1-2]\\d|3[0-2])"; - rfc39862.ipv6Cidr = "(?:0{0,2}\\d|0?[1-9]\\d|1[01]\\d|12[0-8])"; - rfc39862.ipv6address = "(?:" + IPv6SixHex + "|" + IPv6FiveHex + "|" + IPv6FourHex + "|" + IPv6ThreeHex + "|" + IPv6TwoHex + "|" + IPv6OneHex + "|" + IPv6NoneHex + "|" + IPv6NoneHex2 + "|" + IPv6NoneHex3 + ")"; - rfc39862.ipvFuture = "v" + hexDigitOnly + "+\\.[" + unreserved + subDelims + ":]+"; - rfc39862.scheme = "[a-zA-Z][a-zA-Z\\d+-\\.]*"; - rfc39862.schemeRegex = new RegExp(rfc39862.scheme); - const userinfo = "[" + unreserved + pctEncoded + subDelims + ":]*"; - const IPLiteral = "\\[(?:" + rfc39862.ipv6address + "|" + rfc39862.ipvFuture + ")\\]"; - const regName = "[" + unreserved + pctEncoded + subDelims + "]{1,255}"; - const host = "(?:" + IPLiteral + "|" + rfc39862.ipv4address + "|" + regName + ")"; - const port = "\\d*"; - const authority = "(?:" + userinfo + "@)?" + host + "(?::" + port + ")?"; - const authorityCapture = "(?:" + userinfo + "@)?(" + host + ")(?::" + port + ")?"; - const segment = pcharOnly + "*"; - const segmentNz = pcharOnly + "+"; - const segmentNzNc = "[" + unreserved + pctEncoded + subDelims + "@]+"; - const pathEmpty = ""; - const pathAbEmpty = "(?:\\/" + segment + ")*"; - const pathAbsolute = "\\/(?:" + segmentNz + pathAbEmpty + ")?"; - const pathRootless = segmentNz + pathAbEmpty; - const pathNoScheme = segmentNzNc + pathAbEmpty; - const pathAbNoAuthority = "(?:\\/\\/\\/" + segment + pathAbEmpty + ")"; - rfc39862.hierPart = "(?:(?:\\/\\/" + authority + pathAbEmpty + ")|" + pathAbsolute + "|" + pathRootless + "|" + pathAbNoAuthority + ")"; - rfc39862.hierPartCapture = "(?:(?:\\/\\/" + authorityCapture + pathAbEmpty + ")|" + pathAbsolute + "|" + pathRootless + ")"; - rfc39862.relativeRef = "(?:(?:\\/\\/" + authority + pathAbEmpty + ")|" + pathAbsolute + "|" + pathNoScheme + "|" + pathEmpty + ")"; - rfc39862.relativeRefCapture = "(?:(?:\\/\\/" + authorityCapture + pathAbEmpty + ")|" + pathAbsolute + "|" + pathNoScheme + "|" + pathEmpty + ")"; - rfc39862.query = "[" + pchar + "\\/\\?]*(?=#|$)"; - rfc39862.queryWithSquareBrackets = "[" + pchar + "\\[\\]\\/\\?]*(?=#|$)"; - rfc39862.fragment = "[" + pchar + "\\/\\?]*"; - return rfc39862; - } - var rfc3986 = generate(); - exports2.ipVersions = { - v4Cidr: rfc3986.ipv4Cidr, - v6Cidr: rfc3986.ipv6Cidr, - ipv4: rfc3986.ipv4address, - ipv6: rfc3986.ipv6address, - ipvfuture: rfc3986.ipvFuture - }; - function createRegex(options2) { - const rfc = rfc3986; - const query = options2.allowQuerySquareBrackets ? rfc.queryWithSquareBrackets : rfc.query; - const suffix = "(?:\\?" + query + ")?(?:#" + rfc.fragment + ")?"; - const relative32 = options2.domain ? rfc.relativeRefCapture : rfc.relativeRef; - if (options2.relativeOnly) { - return wrap2(relative32 + suffix); - } - let customScheme = ""; - if (options2.scheme) { - (0, hoek_1.assert)(options2.scheme instanceof RegExp || typeof options2.scheme === "string" || Array.isArray(options2.scheme), "scheme must be a RegExp, String, or Array"); - const schemes = [].concat(options2.scheme); - (0, hoek_1.assert)(schemes.length >= 1, "scheme must have at least 1 scheme specified"); - const selections = []; - for (let i2 = 0; i2 < schemes.length; ++i2) { - const scheme2 = schemes[i2]; - (0, hoek_1.assert)(scheme2 instanceof RegExp || typeof scheme2 === "string", "scheme at position " + i2 + " must be a RegExp or String"); - if (scheme2 instanceof RegExp) { - selections.push(scheme2.source.toString()); - } else { - (0, hoek_1.assert)(rfc.schemeRegex.test(scheme2), "scheme at position " + i2 + " must be a valid scheme"); - selections.push((0, hoek_1.escapeRegex)(scheme2)); - } - } - customScheme = selections.join("|"); - } - const scheme = customScheme ? "(?:" + customScheme + ")" : rfc.scheme; - const absolute = "(?:" + scheme + ":" + (options2.domain ? rfc.hierPartCapture : rfc.hierPart) + ")"; - const prefix = options2.allowRelative ? "(?:" + absolute + "|" + relative32 + ")" : absolute; - return wrap2(prefix + suffix, customScheme); + const currentPinnedVersion = cheloniaConfig.contracts[fullContractName]?.version; + if (currentPinnedVersion === manifestVersion) { + console.log(yellow(`\u2728 Contract ${fullContractName} is already pinned to version ${manifestVersion} - no action needed`)); + return; } - function wrap2(raw, scheme = null) { - raw = `(?=.)(?!https?:/(?:$|[^/]))(?!https?:///)(?!https?:[^/])${raw}`; - return { - raw, - regex: new RegExp(`^${raw}$`), - scheme - }; + if (currentPinnedVersion) { + console.log(cyan(`\u{1F4CC} Updating ${fullContractName} from version ${currentPinnedVersion} to ${manifestVersion}`)); + } else { + console.log(cyan(`\u{1F4CC} Pinning ${fullContractName} to version ${manifestVersion} (first time)`)); } - var genericUriRegex = createRegex({}); - function uriRegex(options2 = {}) { - if (options2.scheme || options2.allowRelative || options2.relativeOnly || options2.allowQuerySquareBrackets || options2.domain) { - return createRegex(options2); + const contractVersionDir = join62(projectRoot, "contracts", contractName, manifestVersion); + if (existsSync(contractVersionDir)) { + if (!args.overwrite) { + exit(`Version ${manifestVersion} already exists for contract ${fullContractName}. Use --overwrite to replace it.`); } - return genericUriRegex; + console.log(yellow(`Version ${manifestVersion} already exists for ${fullContractName} - checking files...`)); + } else { + await createVersionDirectory(contractName, manifestVersion); } - exports2.uriRegex = uriRegex; + await copyContractFiles(contractFiles, manifestPath, contractName, manifestVersion, args); + await updateCheloniaConfig(fullContractName, contractName, manifestVersion, manifestPath); + console.log(green(`\u2705 Successfully pinned ${fullContractName} to version ${manifestVersion}`)); + console.log(gray(`Location: contracts/${contractName}/${manifestVersion}/`)); + } catch (error2) { + exit(error2); } -}); -var require_ip = __commonJS({ - "node_modules/.deno/@hapi+address@5.1.1/node_modules/@hapi/address/dist/ip.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.ipRegex = void 0; - var hoek_1 = require_lib(); - var uri_1 = require_uri(); - function ipRegex(options2 = {}) { - const cidr = options2.cidr || "optional"; - (0, hoek_1.assert)(["required", "optional", "forbidden"].includes(cidr), "options.cidr must be one of required, optional, forbidden"); - (0, hoek_1.assert)(options2.version === void 0 || typeof options2.version === "string" || Array.isArray(options2.version), "options.version must be a string or an array of string"); - let versions = options2.version || ["ipv4", "ipv6", "ipvfuture"]; - if (!Array.isArray(versions)) { - versions = [versions]; - } - (0, hoek_1.assert)(versions.length >= 1, "options.version must have at least 1 version specified"); - for (const version3 of versions) { - (0, hoek_1.assert)(typeof version3 === "string" && version3 === version3.toLowerCase(), "Invalid options.version value"); - (0, hoek_1.assert)(["ipv4", "ipv6", "ipvfuture"].includes(version3), "options.version contains unknown version " + version3 + " - must be one of ipv4, ipv6, ipvfuture"); - } - versions = Array.from(new Set(versions)); - const parts = versions.map((version3) => { - if (cidr === "forbidden") { - return uri_1.ipVersions[version3]; - } - const cidrpart = `\\/${version3 === "ipv4" ? uri_1.ipVersions.v4Cidr : uri_1.ipVersions.v6Cidr}`; - if (cidr === "required") { - return `${uri_1.ipVersions[version3]}${cidrpart}`; - } - return `${uri_1.ipVersions[version3]}(?:${cidrpart})?`; - }); - const raw = `(?:${parts.join("|")})`; - const regex = new RegExp(`^${raw}$`); - return { cidr, versions, regex, raw }; - } - exports2.ipRegex = ipRegex; - } -}); -var require_decode2 = __commonJS({ - "node_modules/.deno/@hapi+address@5.1.1/node_modules/@hapi/address/dist/decode.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.uriDecode = void 0; - var HEX = { - "0": 0, - "1": 1, - "2": 2, - "3": 3, - "4": 4, - "5": 5, - "6": 6, - "7": 7, - "8": 8, - "9": 9, - a: 10, - A: 10, - b: 11, - B: 11, - c: 12, - C: 12, - d: 13, - D: 13, - e: 14, - E: 14, - f: 15, - F: 15 - }; - var UTF8 = { - accept: 12, - reject: 0, - data: [ - // Maps bytes to character to a transition - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 6, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 8, - 7, - 7, - 10, - 9, - 9, - 9, - 11, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - // Maps a state to a new state when adding a transition - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12, - 0, - 0, - 0, - 0, - 24, - 36, - 48, - 60, - 72, - 84, - 96, - 0, - 12, - 12, - 12, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24, - 24, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 48, - 48, - 48, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 48, - 48, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 48, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - // Maps the current transition to a mask that needs to apply to the byte - 127, - 63, - 63, - 63, - 0, - 31, - 15, - 15, - 15, - 7, - 7, - 7 - ] - }; - function uriDecode(string3) { - let percentPos = string3.indexOf("%"); - if (percentPos === -1) { - return string3; - } - let decoded = ""; - let last = 0; - let codepoint = 0; - let startOfOctets = percentPos; - let state = UTF8.accept; - while (percentPos > -1 && percentPos < string3.length) { - const high = resolveHex(string3[percentPos + 1], 4); - const low = resolveHex(string3[percentPos + 2], 0); - const byte = high | low; - const type = UTF8.data[byte]; - state = UTF8.data[256 + state + type]; - codepoint = codepoint << 6 | byte & UTF8.data[364 + type]; - if (state === UTF8.accept) { - decoded += string3.slice(last, startOfOctets); - decoded += codepoint <= 65535 ? String.fromCharCode(codepoint) : String.fromCharCode(55232 + (codepoint >> 10), 56320 + (codepoint & 1023)); - codepoint = 0; - last = percentPos + 3; - percentPos = string3.indexOf("%", last); - startOfOctets = percentPos; - continue; - } - if (state === UTF8.reject) { - return null; - } - percentPos += 3; - if (percentPos >= string3.length || string3[percentPos] !== "%") { - return null; - } - } - return decoded + string3.slice(last); +} +async function parseManifest(manifestPath) { + const manifestContent = await readFile3(manifestPath, "utf8"); + const manifest2 = JSON.parse(manifestContent); + const body = JSON.parse(manifest2.body); + const fullContractName = body.name; + const manifestVersion = body.version; + const mainFile = body.contract.file; + const slimFile = body.contractSlim?.file; + if (!fullContractName || !mainFile || !manifestVersion) { + console.error(red("\u274C Invalid manifest: missing contract name, main file, or version")); + exit("Invalid manifest: missing contract name, main file, or version"); + } + const contractName = sanitizeContractName(fullContractName); + return { + contractName, + manifestVersion, + fullContractName, + contractFiles: { + main: mainFile, + slim: slimFile } - exports2.uriDecode = uriDecode; - function resolveHex(char, shift) { - const i2 = HEX[char]; - return i2 === void 0 ? 255 : i2 << shift; + }; +} +async function createVersionDirectory(contractName, version3) { + const versionDir = join62(projectRoot, "contracts", contractName, version3); + console.log(blue(`\u{1F4C1} Creating directory: contracts/${contractName}/${version3}/`)); + await mkdir3(versionDir, { recursive: true }); +} +async function copyContractFiles(contractFiles, manifestPath, contractName, version3, args) { + const sourceDir = dirname42(join62(projectRoot, manifestPath)); + const targetDir = join62(projectRoot, "contracts", contractName, version3); + console.log(gray(`\u{1F4CB} Copying files from manifest: ${contractFiles.main}${contractFiles.slim ? `, ${contractFiles.slim}` : ""}, manifest`)); + const mainSource = join62(sourceDir, contractFiles.main); + const mainTarget = join62(targetDir, contractFiles.main); + await copyFileIfNeeded(mainSource, mainTarget, contractFiles.main, args); + if (contractFiles.slim) { + const slimSource = join62(sourceDir, contractFiles.slim); + const slimTarget = join62(targetDir, contractFiles.slim); + try { + await copyFileIfNeeded(slimSource, slimTarget, contractFiles.slim, args); + } catch (error2) { + const errorMessage = error2 instanceof Error ? error2.message : String(error2); + console.error(yellow(`\u26A0\uFE0F Could not copy slim file: ${errorMessage}`)); } } -}); -var require_dist3 = __commonJS({ - "node_modules/.deno/@hapi+address@5.1.1/node_modules/@hapi/address/dist/index.js"(exports2) { - "use strict"; - var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m3, k); - if (!desc || ("get" in desc ? !m3.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { - return m3[k]; - } }; - } - Object.defineProperty(o2, k2, desc); - } : function(o2, m3, k, k2) { - if (k2 === void 0) k2 = k; - o2[k2] = m3[k]; - }); - var __exportStar = exports2 && exports2.__exportStar || function(m3, exports3) { - for (var p in m3) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m3, p); - }; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.uriDecode = exports2.uriRegex = exports2.ipRegex = exports2.errorCodes = void 0; - __exportStar(require_domain(), exports2); - __exportStar(require_email(), exports2); - var errors_1 = require_errors4(); - Object.defineProperty(exports2, "errorCodes", { enumerable: true, get: function() { - return errors_1.errorCodes; - } }); - var ip_1 = require_ip(); - Object.defineProperty(exports2, "ipRegex", { enumerable: true, get: function() { - return ip_1.ipRegex; - } }); - var uri_1 = require_uri(); - Object.defineProperty(exports2, "uriRegex", { enumerable: true, get: function() { - return uri_1.uriRegex; - } }); - var decode_1 = require_decode2(); - Object.defineProperty(exports2, "uriDecode", { enumerable: true, get: function() { - return decode_1.uriDecode; - } }); + const manifestSource = join62(projectRoot, manifestPath); + const manifestTarget = join62(targetDir, basename42(manifestPath)); + await copyFileIfNeeded(manifestSource, manifestTarget, basename42(manifestPath), args); +} +async function copyFileIfNeeded(sourcePath, targetPath, fileName, args) { + const targetExists = existsSync(targetPath); + if (!targetExists) { + console.log(blue(`\u{1F4C4} Copying: ${fileName} (new file)`)); + await copyFile(sourcePath, targetPath); + return; } -}); -var require_tlds = __commonJS({ - "node_modules/.deno/@hapi+tlds@1.1.3/node_modules/@hapi/tlds/dist/commonjs/tlds.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.TLDS = void 0; - exports2.TLDS = [ - "AAA", - "AARP", - "ABB", - "ABBOTT", - "ABBVIE", - "ABC", - "ABLE", - "ABOGADO", - "ABUDHABI", - "AC", - "ACADEMY", - "ACCENTURE", - "ACCOUNTANT", - "ACCOUNTANTS", - "ACO", - "ACTOR", - "AD", - "ADS", - "ADULT", - "AE", - "AEG", - "AERO", - "AETNA", - "AF", - "AFL", - "AFRICA", - "AG", - "AGAKHAN", - "AGENCY", - "AI", - "AIG", - "AIRBUS", - "AIRFORCE", - "AIRTEL", - "AKDN", - "AL", - "ALIBABA", - "ALIPAY", - "ALLFINANZ", - "ALLSTATE", - "ALLY", - "ALSACE", - "ALSTOM", - "AM", - "AMAZON", - "AMERICANEXPRESS", - "AMERICANFAMILY", - "AMEX", - "AMFAM", - "AMICA", - "AMSTERDAM", - "ANALYTICS", - "ANDROID", - "ANQUAN", - "ANZ", - "AO", - "AOL", - "APARTMENTS", - "APP", - "APPLE", - "AQ", - "AQUARELLE", - "AR", - "ARAB", - "ARAMCO", - "ARCHI", - "ARMY", - "ARPA", - "ART", - "ARTE", - "AS", - "ASDA", - "ASIA", - "ASSOCIATES", - "AT", - "ATHLETA", - "ATTORNEY", - "AU", - "AUCTION", - "AUDI", - "AUDIBLE", - "AUDIO", - "AUSPOST", - "AUTHOR", - "AUTO", - "AUTOS", - "AW", - "AWS", - "AX", - "AXA", - "AZ", - "AZURE", - "BA", - "BABY", - "BAIDU", - "BANAMEX", - "BAND", - "BANK", - "BAR", - "BARCELONA", - "BARCLAYCARD", - "BARCLAYS", - "BAREFOOT", - "BARGAINS", - "BASEBALL", - "BASKETBALL", - "BAUHAUS", - "BAYERN", - "BB", - "BBC", - "BBT", - "BBVA", - "BCG", - "BCN", - "BD", - "BE", - "BEATS", - "BEAUTY", - "BEER", - "BERLIN", - "BEST", - "BESTBUY", - "BET", - "BF", - "BG", - "BH", - "BHARTI", - "BI", - "BIBLE", - "BID", - "BIKE", - "BING", - "BINGO", - "BIO", - "BIZ", - "BJ", - "BLACK", - "BLACKFRIDAY", - "BLOCKBUSTER", - "BLOG", - "BLOOMBERG", - "BLUE", - "BM", - "BMS", - "BMW", - "BN", - "BNPPARIBAS", - "BO", - "BOATS", - "BOEHRINGER", - "BOFA", - "BOM", - "BOND", - "BOO", - "BOOK", - "BOOKING", - "BOSCH", - "BOSTIK", - "BOSTON", - "BOT", - "BOUTIQUE", - "BOX", - "BR", - "BRADESCO", - "BRIDGESTONE", - "BROADWAY", - "BROKER", - "BROTHER", - "BRUSSELS", - "BS", - "BT", - "BUILD", - "BUILDERS", - "BUSINESS", - "BUY", - "BUZZ", - "BV", - "BW", - "BY", - "BZ", - "BZH", - "CA", - "CAB", - "CAFE", - "CAL", - "CALL", - "CALVINKLEIN", - "CAM", - "CAMERA", - "CAMP", - "CANON", - "CAPETOWN", - "CAPITAL", - "CAPITALONE", - "CAR", - "CARAVAN", - "CARDS", - "CARE", - "CAREER", - "CAREERS", - "CARS", - "CASA", - "CASE", - "CASH", - "CASINO", - "CAT", - "CATERING", - "CATHOLIC", - "CBA", - "CBN", - "CBRE", - "CC", - "CD", - "CENTER", - "CEO", - "CERN", - "CF", - "CFA", - "CFD", - "CG", - "CH", - "CHANEL", - "CHANNEL", - "CHARITY", - "CHASE", - "CHAT", - "CHEAP", - "CHINTAI", - "CHRISTMAS", - "CHROME", - "CHURCH", - "CI", - "CIPRIANI", - "CIRCLE", - "CISCO", - "CITADEL", - "CITI", - "CITIC", - "CITY", - "CK", - "CL", - "CLAIMS", - "CLEANING", - "CLICK", - "CLINIC", - "CLINIQUE", - "CLOTHING", - "CLOUD", - "CLUB", - "CLUBMED", - "CM", - "CN", - "CO", - "COACH", - "CODES", - "COFFEE", - "COLLEGE", - "COLOGNE", - "COM", - "COMMBANK", - "COMMUNITY", - "COMPANY", - "COMPARE", - "COMPUTER", - "COMSEC", - "CONDOS", - "CONSTRUCTION", - "CONSULTING", - "CONTACT", - "CONTRACTORS", - "COOKING", - "COOL", - "COOP", - "CORSICA", - "COUNTRY", - "COUPON", - "COUPONS", - "COURSES", - "CPA", - "CR", - "CREDIT", - "CREDITCARD", - "CREDITUNION", - "CRICKET", - "CROWN", - "CRS", - "CRUISE", - "CRUISES", - "CU", - "CUISINELLA", - "CV", - "CW", - "CX", - "CY", - "CYMRU", - "CYOU", - "CZ", - "DAD", - "DANCE", - "DATA", - "DATE", - "DATING", - "DATSUN", - "DAY", - "DCLK", - "DDS", - "DE", - "DEAL", - "DEALER", - "DEALS", - "DEGREE", - "DELIVERY", - "DELL", - "DELOITTE", - "DELTA", - "DEMOCRAT", - "DENTAL", - "DENTIST", - "DESI", - "DESIGN", - "DEV", - "DHL", - "DIAMONDS", - "DIET", - "DIGITAL", - "DIRECT", - "DIRECTORY", - "DISCOUNT", - "DISCOVER", - "DISH", - "DIY", - "DJ", - "DK", - "DM", - "DNP", - "DO", - "DOCS", - "DOCTOR", - "DOG", - "DOMAINS", - "DOT", - "DOWNLOAD", - "DRIVE", - "DTV", - "DUBAI", - "DUNLOP", - "DUPONT", - "DURBAN", - "DVAG", - "DVR", - "DZ", - "EARTH", - "EAT", - "EC", - "ECO", - "EDEKA", - "EDU", - "EDUCATION", - "EE", - "EG", - "EMAIL", - "EMERCK", - "ENERGY", - "ENGINEER", - "ENGINEERING", - "ENTERPRISES", - "EPSON", - "EQUIPMENT", - "ER", - "ERICSSON", - "ERNI", - "ES", - "ESQ", - "ESTATE", - "ET", - "EU", - "EUROVISION", - "EUS", - "EVENTS", - "EXCHANGE", - "EXPERT", - "EXPOSED", - "EXPRESS", - "EXTRASPACE", - "FAGE", - "FAIL", - "FAIRWINDS", - "FAITH", - "FAMILY", - "FAN", - "FANS", - "FARM", - "FARMERS", - "FASHION", - "FAST", - "FEDEX", - "FEEDBACK", - "FERRARI", - "FERRERO", - "FI", - "FIDELITY", - "FIDO", - "FILM", - "FINAL", - "FINANCE", - "FINANCIAL", - "FIRE", - "FIRESTONE", - "FIRMDALE", - "FISH", - "FISHING", - "FIT", - "FITNESS", - "FJ", - "FK", - "FLICKR", - "FLIGHTS", - "FLIR", - "FLORIST", - "FLOWERS", - "FLY", - "FM", - "FO", - "FOO", - "FOOD", - "FOOTBALL", - "FORD", - "FOREX", - "FORSALE", - "FORUM", - "FOUNDATION", - "FOX", - "FR", - "FREE", - "FRESENIUS", - "FRL", - "FROGANS", - "FRONTIER", - "FTR", - "FUJITSU", - "FUN", - "FUND", - "FURNITURE", - "FUTBOL", - "FYI", - "GA", - "GAL", - "GALLERY", - "GALLO", - "GALLUP", - "GAME", - "GAMES", - "GAP", - "GARDEN", - "GAY", - "GB", - "GBIZ", - "GD", - "GDN", - "GE", - "GEA", - "GENT", - "GENTING", - "GEORGE", - "GF", - "GG", - "GGEE", - "GH", - "GI", - "GIFT", - "GIFTS", - "GIVES", - "GIVING", - "GL", - "GLASS", - "GLE", - "GLOBAL", - "GLOBO", - "GM", - "GMAIL", - "GMBH", - "GMO", - "GMX", - "GN", - "GODADDY", - "GOLD", - "GOLDPOINT", - "GOLF", - "GOO", - "GOODYEAR", - "GOOG", - "GOOGLE", - "GOP", - "GOT", - "GOV", - "GP", - "GQ", - "GR", - "GRAINGER", - "GRAPHICS", - "GRATIS", - "GREEN", - "GRIPE", - "GROCERY", - "GROUP", - "GS", - "GT", - "GU", - "GUCCI", - "GUGE", - "GUIDE", - "GUITARS", - "GURU", - "GW", - "GY", - "HAIR", - "HAMBURG", - "HANGOUT", - "HAUS", - "HBO", - "HDFC", - "HDFCBANK", - "HEALTH", - "HEALTHCARE", - "HELP", - "HELSINKI", - "HERE", - "HERMES", - "HIPHOP", - "HISAMITSU", - "HITACHI", - "HIV", - "HK", - "HKT", - "HM", - "HN", - "HOCKEY", - "HOLDINGS", - "HOLIDAY", - "HOMEDEPOT", - "HOMEGOODS", - "HOMES", - "HOMESENSE", - "HONDA", - "HORSE", - "HOSPITAL", - "HOST", - "HOSTING", - "HOT", - "HOTELS", - "HOTMAIL", - "HOUSE", - "HOW", - "HR", - "HSBC", - "HT", - "HU", - "HUGHES", - "HYATT", - "HYUNDAI", - "IBM", - "ICBC", - "ICE", - "ICU", - "ID", - "IE", - "IEEE", - "IFM", - "IKANO", - "IL", - "IM", - "IMAMAT", - "IMDB", - "IMMO", - "IMMOBILIEN", - "IN", - "INC", - "INDUSTRIES", - "INFINITI", - "INFO", - "ING", - "INK", - "INSTITUTE", - "INSURANCE", - "INSURE", - "INT", - "INTERNATIONAL", - "INTUIT", - "INVESTMENTS", - "IO", - "IPIRANGA", - "IQ", - "IR", - "IRISH", - "IS", - "ISMAILI", - "IST", - "ISTANBUL", - "IT", - "ITAU", - "ITV", - "JAGUAR", - "JAVA", - "JCB", - "JE", - "JEEP", - "JETZT", - "JEWELRY", - "JIO", - "JLL", - "JM", - "JMP", - "JNJ", - "JO", - "JOBS", - "JOBURG", - "JOT", - "JOY", - "JP", - "JPMORGAN", - "JPRS", - "JUEGOS", - "JUNIPER", - "KAUFEN", - "KDDI", - "KE", - "KERRYHOTELS", - "KERRYPROPERTIES", - "KFH", - "KG", - "KH", - "KI", - "KIA", - "KIDS", - "KIM", - "KINDLE", - "KITCHEN", - "KIWI", - "KM", - "KN", - "KOELN", - "KOMATSU", - "KOSHER", - "KP", - "KPMG", - "KPN", - "KR", - "KRD", - "KRED", - "KUOKGROUP", - "KW", - "KY", - "KYOTO", - "KZ", - "LA", - "LACAIXA", - "LAMBORGHINI", - "LAMER", - "LAND", - "LANDROVER", - "LANXESS", - "LASALLE", - "LAT", - "LATINO", - "LATROBE", - "LAW", - "LAWYER", - "LB", - "LC", - "LDS", - "LEASE", - "LECLERC", - "LEFRAK", - "LEGAL", - "LEGO", - "LEXUS", - "LGBT", - "LI", - "LIDL", - "LIFE", - "LIFEINSURANCE", - "LIFESTYLE", - "LIGHTING", - "LIKE", - "LILLY", - "LIMITED", - "LIMO", - "LINCOLN", - "LINK", - "LIVE", - "LIVING", - "LK", - "LLC", - "LLP", - "LOAN", - "LOANS", - "LOCKER", - "LOCUS", - "LOL", - "LONDON", - "LOTTE", - "LOTTO", - "LOVE", - "LPL", - "LPLFINANCIAL", - "LR", - "LS", - "LT", - "LTD", - "LTDA", - "LU", - "LUNDBECK", - "LUXE", - "LUXURY", - "LV", - "LY", - "MA", - "MADRID", - "MAIF", - "MAISON", - "MAKEUP", - "MAN", - "MANAGEMENT", - "MANGO", - "MAP", - "MARKET", - "MARKETING", - "MARKETS", - "MARRIOTT", - "MARSHALLS", - "MATTEL", - "MBA", - "MC", - "MCKINSEY", - "MD", - "ME", - "MED", - "MEDIA", - "MEET", - "MELBOURNE", - "MEME", - "MEMORIAL", - "MEN", - "MENU", - "MERCKMSD", - "MG", - "MH", - "MIAMI", - "MICROSOFT", - "MIL", - "MINI", - "MINT", - "MIT", - "MITSUBISHI", - "MK", - "ML", - "MLB", - "MLS", - "MM", - "MMA", - "MN", - "MO", - "MOBI", - "MOBILE", - "MODA", - "MOE", - "MOI", - "MOM", - "MONASH", - "MONEY", - "MONSTER", - "MORMON", - "MORTGAGE", - "MOSCOW", - "MOTO", - "MOTORCYCLES", - "MOV", - "MOVIE", - "MP", - "MQ", - "MR", - "MS", - "MSD", - "MT", - "MTN", - "MTR", - "MU", - "MUSEUM", - "MUSIC", - "MV", - "MW", - "MX", - "MY", - "MZ", - "NA", - "NAB", - "NAGOYA", - "NAME", - "NAVY", - "NBA", - "NC", - "NE", - "NEC", - "NET", - "NETBANK", - "NETFLIX", - "NETWORK", - "NEUSTAR", - "NEW", - "NEWS", - "NEXT", - "NEXTDIRECT", - "NEXUS", - "NF", - "NFL", - "NG", - "NGO", - "NHK", - "NI", - "NICO", - "NIKE", - "NIKON", - "NINJA", - "NISSAN", - "NISSAY", - "NL", - "NO", - "NOKIA", - "NORTON", - "NOW", - "NOWRUZ", - "NOWTV", - "NP", - "NR", - "NRA", - "NRW", - "NTT", - "NU", - "NYC", - "NZ", - "OBI", - "OBSERVER", - "OFFICE", - "OKINAWA", - "OLAYAN", - "OLAYANGROUP", - "OLLO", - "OM", - "OMEGA", - "ONE", - "ONG", - "ONL", - "ONLINE", - "OOO", - "OPEN", - "ORACLE", - "ORANGE", - "ORG", - "ORGANIC", - "ORIGINS", - "OSAKA", - "OTSUKA", - "OTT", - "OVH", - "PA", - "PAGE", - "PANASONIC", - "PARIS", - "PARS", - "PARTNERS", - "PARTS", - "PARTY", - "PAY", - "PCCW", - "PE", - "PET", - "PF", - "PFIZER", - "PG", - "PH", - "PHARMACY", - "PHD", - "PHILIPS", - "PHONE", - "PHOTO", - "PHOTOGRAPHY", - "PHOTOS", - "PHYSIO", - "PICS", - "PICTET", - "PICTURES", - "PID", - "PIN", - "PING", - "PINK", - "PIONEER", - "PIZZA", - "PK", - "PL", - "PLACE", - "PLAY", - "PLAYSTATION", - "PLUMBING", - "PLUS", - "PM", - "PN", - "PNC", - "POHL", - "POKER", - "POLITIE", - "PORN", - "POST", - "PR", - "PRAXI", - "PRESS", - "PRIME", - "PRO", - "PROD", - "PRODUCTIONS", - "PROF", - "PROGRESSIVE", - "PROMO", - "PROPERTIES", - "PROPERTY", - "PROTECTION", - "PRU", - "PRUDENTIAL", - "PS", - "PT", - "PUB", - "PW", - "PWC", - "PY", - "QA", - "QPON", - "QUEBEC", - "QUEST", - "RACING", - "RADIO", - "RE", - "READ", - "REALESTATE", - "REALTOR", - "REALTY", - "RECIPES", - "RED", - "REDUMBRELLA", - "REHAB", - "REISE", - "REISEN", - "REIT", - "RELIANCE", - "REN", - "RENT", - "RENTALS", - "REPAIR", - "REPORT", - "REPUBLICAN", - "REST", - "RESTAURANT", - "REVIEW", - "REVIEWS", - "REXROTH", - "RICH", - "RICHARDLI", - "RICOH", - "RIL", - "RIO", - "RIP", - "RO", - "ROCKS", - "RODEO", - "ROGERS", - "ROOM", - "RS", - "RSVP", - "RU", - "RUGBY", - "RUHR", - "RUN", - "RW", - "RWE", - "RYUKYU", - "SA", - "SAARLAND", - "SAFE", - "SAFETY", - "SAKURA", - "SALE", - "SALON", - "SAMSCLUB", - "SAMSUNG", - "SANDVIK", - "SANDVIKCOROMANT", - "SANOFI", - "SAP", - "SARL", - "SAS", - "SAVE", - "SAXO", - "SB", - "SBI", - "SBS", - "SC", - "SCB", - "SCHAEFFLER", - "SCHMIDT", - "SCHOLARSHIPS", - "SCHOOL", - "SCHULE", - "SCHWARZ", - "SCIENCE", - "SCOT", - "SD", - "SE", - "SEARCH", - "SEAT", - "SECURE", - "SECURITY", - "SEEK", - "SELECT", - "SENER", - "SERVICES", - "SEVEN", - "SEW", - "SEX", - "SEXY", - "SFR", - "SG", - "SH", - "SHANGRILA", - "SHARP", - "SHELL", - "SHIA", - "SHIKSHA", - "SHOES", - "SHOP", - "SHOPPING", - "SHOUJI", - "SHOW", - "SI", - "SILK", - "SINA", - "SINGLES", - "SITE", - "SJ", - "SK", - "SKI", - "SKIN", - "SKY", - "SKYPE", - "SL", - "SLING", - "SM", - "SMART", - "SMILE", - "SN", - "SNCF", - "SO", - "SOCCER", - "SOCIAL", - "SOFTBANK", - "SOFTWARE", - "SOHU", - "SOLAR", - "SOLUTIONS", - "SONG", - "SONY", - "SOY", - "SPA", - "SPACE", - "SPORT", - "SPOT", - "SR", - "SRL", - "SS", - "ST", - "STADA", - "STAPLES", - "STAR", - "STATEBANK", - "STATEFARM", - "STC", - "STCGROUP", - "STOCKHOLM", - "STORAGE", - "STORE", - "STREAM", - "STUDIO", - "STUDY", - "STYLE", - "SU", - "SUCKS", - "SUPPLIES", - "SUPPLY", - "SUPPORT", - "SURF", - "SURGERY", - "SUZUKI", - "SV", - "SWATCH", - "SWISS", - "SX", - "SY", - "SYDNEY", - "SYSTEMS", - "SZ", - "TAB", - "TAIPEI", - "TALK", - "TAOBAO", - "TARGET", - "TATAMOTORS", - "TATAR", - "TATTOO", - "TAX", - "TAXI", - "TC", - "TCI", - "TD", - "TDK", - "TEAM", - "TECH", - "TECHNOLOGY", - "TEL", - "TEMASEK", - "TENNIS", - "TEVA", - "TF", - "TG", - "TH", - "THD", - "THEATER", - "THEATRE", - "TIAA", - "TICKETS", - "TIENDA", - "TIPS", - "TIRES", - "TIROL", - "TJ", - "TJMAXX", - "TJX", - "TK", - "TKMAXX", - "TL", - "TM", - "TMALL", - "TN", - "TO", - "TODAY", - "TOKYO", - "TOOLS", - "TOP", - "TORAY", - "TOSHIBA", - "TOTAL", - "TOURS", - "TOWN", - "TOYOTA", - "TOYS", - "TR", - "TRADE", - "TRADING", - "TRAINING", - "TRAVEL", - "TRAVELERS", - "TRAVELERSINSURANCE", - "TRUST", - "TRV", - "TT", - "TUBE", - "TUI", - "TUNES", - "TUSHU", - "TV", - "TVS", - "TW", - "TZ", - "UA", - "UBANK", - "UBS", - "UG", - "UK", - "UNICOM", - "UNIVERSITY", - "UNO", - "UOL", - "UPS", - "US", - "UY", - "UZ", - "VA", - "VACATIONS", - "VANA", - "VANGUARD", - "VC", - "VE", - "VEGAS", - "VENTURES", - "VERISIGN", - "VERSICHERUNG", - "VET", - "VG", - "VI", - "VIAJES", - "VIDEO", - "VIG", - "VIKING", - "VILLAS", - "VIN", - "VIP", - "VIRGIN", - "VISA", - "VISION", - "VIVA", - "VIVO", - "VLAANDEREN", - "VN", - "VODKA", - "VOLVO", - "VOTE", - "VOTING", - "VOTO", - "VOYAGE", - "VU", - "WALES", - "WALMART", - "WALTER", - "WANG", - "WANGGOU", - "WATCH", - "WATCHES", - "WEATHER", - "WEATHERCHANNEL", - "WEBCAM", - "WEBER", - "WEBSITE", - "WED", - "WEDDING", - "WEIBO", - "WEIR", - "WF", - "WHOSWHO", - "WIEN", - "WIKI", - "WILLIAMHILL", - "WIN", - "WINDOWS", - "WINE", - "WINNERS", - "WME", - "WOLTERSKLUWER", - "WOODSIDE", - "WORK", - "WORKS", - "WORLD", - "WOW", - "WS", - "WTC", - "WTF", - "XBOX", - "XEROX", - "XIHUAN", - "XIN", - "XN--11B4C3D", - "XN--1CK2E1B", - "XN--1QQW23A", - "XN--2SCRJ9C", - "XN--30RR7Y", - "XN--3BST00M", - "XN--3DS443G", - "XN--3E0B707E", - "XN--3HCRJ9C", - "XN--3PXU8K", - "XN--42C2D9A", - "XN--45BR5CYL", - "XN--45BRJ9C", - "XN--45Q11C", - "XN--4DBRK0CE", - "XN--4GBRIM", - "XN--54B7FTA0CC", - "XN--55QW42G", - "XN--55QX5D", - "XN--5SU34J936BGSG", - "XN--5TZM5G", - "XN--6FRZ82G", - "XN--6QQ986B3XL", - "XN--80ADXHKS", - "XN--80AO21A", - "XN--80AQECDR1A", - "XN--80ASEHDB", - "XN--80ASWG", - "XN--8Y0A063A", - "XN--90A3AC", - "XN--90AE", - "XN--90AIS", - "XN--9DBQ2A", - "XN--9ET52U", - "XN--9KRT00A", - "XN--B4W605FERD", - "XN--BCK1B9A5DRE4C", - "XN--C1AVG", - "XN--C2BR7G", - "XN--CCK2B3B", - "XN--CCKWCXETD", - "XN--CG4BKI", - "XN--CLCHC0EA0B2G2A9GCD", - "XN--CZR694B", - "XN--CZRS0T", - "XN--CZRU2D", - "XN--D1ACJ3B", - "XN--D1ALF", - "XN--E1A4C", - "XN--ECKVDTC9D", - "XN--EFVY88H", - "XN--FCT429K", - "XN--FHBEI", - "XN--FIQ228C5HS", - "XN--FIQ64B", - "XN--FIQS8S", - "XN--FIQZ9S", - "XN--FJQ720A", - "XN--FLW351E", - "XN--FPCRJ9C3D", - "XN--FZC2C9E2C", - "XN--FZYS8D69UVGM", - "XN--G2XX48C", - "XN--GCKR3F0F", - "XN--GECRJ9C", - "XN--GK3AT1E", - "XN--H2BREG3EVE", - "XN--H2BRJ9C", - "XN--H2BRJ9C8C", - "XN--HXT814E", - "XN--I1B6B1A6A2E", - "XN--IMR513N", - "XN--IO0A7I", - "XN--J1AEF", - "XN--J1AMH", - "XN--J6W193G", - "XN--JLQ480N2RG", - "XN--JVR189M", - "XN--KCRX77D1X4A", - "XN--KPRW13D", - "XN--KPRY57D", - "XN--KPUT3I", - "XN--L1ACC", - "XN--LGBBAT1AD8J", - "XN--MGB9AWBF", - "XN--MGBA3A3EJT", - "XN--MGBA3A4F16A", - "XN--MGBA7C0BBN0A", - "XN--MGBAAM7A8H", - "XN--MGBAB2BD", - "XN--MGBAH1A3HJKRD", - "XN--MGBAI9AZGQP6J", - "XN--MGBAYH7GPA", - "XN--MGBBH1A", - "XN--MGBBH1A71E", - "XN--MGBC0A9AZCG", - "XN--MGBCA7DZDO", - "XN--MGBCPQ6GPA1A", - "XN--MGBERP4A5D4AR", - "XN--MGBGU82A", - "XN--MGBI4ECEXP", - "XN--MGBPL2FH", - "XN--MGBT3DHD", - "XN--MGBTX2B", - "XN--MGBX4CD0AB", - "XN--MIX891F", - "XN--MK1BU44C", - "XN--MXTQ1M", - "XN--NGBC5AZD", - "XN--NGBE9E0A", - "XN--NGBRX", - "XN--NODE", - "XN--NQV7F", - "XN--NQV7FS00EMA", - "XN--NYQY26A", - "XN--O3CW4H", - "XN--OGBPF8FL", - "XN--OTU796D", - "XN--P1ACF", - "XN--P1AI", - "XN--PGBS0DH", - "XN--PSSY2U", - "XN--Q7CE6A", - "XN--Q9JYB4C", - "XN--QCKA1PMC", - "XN--QXA6A", - "XN--QXAM", - "XN--RHQV96G", - "XN--ROVU88B", - "XN--RVC1E0AM3E", - "XN--S9BRJ9C", - "XN--SES554G", - "XN--T60B56A", - "XN--TCKWE", - "XN--TIQ49XQYJ", - "XN--UNUP4Y", - "XN--VERMGENSBERATER-CTB", - "XN--VERMGENSBERATUNG-PWB", - "XN--VHQUV", - "XN--VUQ861B", - "XN--W4R85EL8FHU5DNRA", - "XN--W4RS40L", - "XN--WGBH1C", - "XN--WGBL6A", - "XN--XHQ521B", - "XN--XKC2AL3HYE2A", - "XN--XKC2DL3A5EE0H", - "XN--Y9A3AQ", - "XN--YFRO4I67O", - "XN--YGBI2AMMX", - "XN--ZFR164B", - "XXX", - "XYZ", - "YACHTS", - "YAHOO", - "YAMAXUN", - "YANDEX", - "YE", - "YODOBASHI", - "YOGA", - "YOKOHAMA", - "YOU", - "YOUTUBE", - "YT", - "YUN", - "ZA", - "ZAPPOS", - "ZARA", - "ZERO", - "ZIP", - "ZM", - "ZONE", - "ZUERICH", - "ZW" - ]; + if (targetExists && !args.overwrite) { + console.log(yellow(`\u23ED\uFE0F Skipping: ${fileName} (already exists, use --overwrite to replace)`)); + return; } -}); -var require_commonjs = __commonJS({ - "node_modules/.deno/@hapi+tlds@1.1.3/node_modules/@hapi/tlds/dist/commonjs/index.js"(exports2) { - "use strict"; - Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.tlds = void 0; - var tlds_js_1 = require_tlds(); - exports2.tlds = new Set(tlds_js_1.TLDS.map((tld) => tld.toLowerCase())); + console.log(blue(`\u{1F4C4} Copying: ${fileName} (overwriting)`)); + await copyFile(sourcePath, targetPath); +} +async function loadCheloniaConfig() { + const configPath = join62(projectRoot, "chelonia.json"); + cheloniaConfig = { contracts: {} }; + if (existsSync(configPath)) { + try { + const configContent = await readFile3(configPath, "utf8"); + cheloniaConfig = JSON.parse(configContent); + console.log(blue("\u{1F4C4} Loaded existing chelonia.json")); + } catch (error2) { + console.warn(yellow(`Warning: Could not parse chelonia.json: ${error2}`)); + } + } else { + console.log(blue("\u{1F4C4} No existing chelonia.json found")); } -}); -var require_string2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/string.js"(exports2, module14) { - "use strict"; - var { assert: assert2, escapeRegex: escapeRegex2 } = require_lib(); - var { isDomainValid, isEmailValid, ipRegex, uriRegex } = require_dist3(); - var Tlds = require_commonjs(); - var Any = require_any2(); - var Common = require_common3(); - var internals = { - tlds: Tlds.tlds instanceof Set ? { tlds: { allow: Tlds.tlds, deny: null } } : false, - // $lab:coverage:ignore$ - base64Regex: { - // paddingRequired - true: { - // urlSafe - true: /^(?:[\w\-]{2}[\w\-]{2})*(?:[\w\-]{2}==|[\w\-]{3}=)?$/, - false: /^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/ - }, - false: { - true: /^(?:[\w\-]{2}[\w\-]{2})*(?:[\w\-]{2}(==)?|[\w\-]{3}=?)?$/, - false: /^(?:[A-Za-z0-9+\/]{2}[A-Za-z0-9+\/]{2})*(?:[A-Za-z0-9+\/]{2}(==)?|[A-Za-z0-9+\/]{3}=?)?$/ - } - }, - dataUriRegex: /^data:[\w+.-]+\/[\w+.-]+;((charset=[\w-]+|base64),)?(.*)$/, - hexRegex: { - withPrefix: /^0x[0-9a-f]+$/i, - withOptionalPrefix: /^(?:0x)?[0-9a-f]+$/i, - withoutPrefix: /^[0-9a-f]+$/i - }, - ipRegex: ipRegex({ cidr: "forbidden" }).regex, - isoDurationRegex: /^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/, - guidBrackets: { - "{": "}", - "[": "]", - "(": ")", - "": "" - }, - guidVersions: { - uuidv1: "1", - uuidv2: "2", - uuidv3: "3", - uuidv4: "4", - uuidv5: "5", - uuidv6: "6", - uuidv7: "7", - uuidv8: "8" - }, - guidSeparators: /* @__PURE__ */ new Set([void 0, true, false, "-", ":"]), - normalizationForms: ["NFC", "NFD", "NFKC", "NFKD"] - }; - module14.exports = Any.extend({ - type: "string", - flags: { - insensitive: { default: false }, - truncate: { default: false } - }, - terms: { - replacements: { init: null } - }, - coerce: { - from: "string", - method(value, { schema, state, prefs }) { - const normalize32 = schema.$_getRule("normalize"); - if (normalize32) { - value = value.normalize(normalize32.args.form); - } - const casing = schema.$_getRule("case"); - if (casing) { - value = casing.args.direction === "upper" ? value.toLocaleUpperCase() : value.toLocaleLowerCase(); - } - const trim = schema.$_getRule("trim"); - if (trim && trim.args.enabled) { - value = value.trim(); - } - if (schema.$_terms.replacements) { - for (const replacement of schema.$_terms.replacements) { - value = value.replace(replacement.pattern, replacement.replacement); - } - } - const hex = schema.$_getRule("hex"); - if (hex && hex.args.options.byteAligned && value.length % 2 !== 0) { - value = `0${value}`; - } - if (schema.$_getRule("isoDate")) { - const iso = internals.isoDate(value); - if (iso) { - value = iso; - } - } - if (schema._flags.truncate) { - const rule = schema.$_getRule("max"); - if (rule) { - let limit = rule.args.limit; - if (Common.isResolvable(limit)) { - limit = limit.resolve(value, state, prefs); - if (!Common.limit(limit)) { - return { value, errors: schema.$_createError("any.ref", limit, { ref: rule.args.limit, arg: "limit", reason: "must be a positive integer" }, state, prefs) }; - } - } - value = value.slice(0, limit); - } - } - return { value }; - } - }, - validate(value, { schema, error: error2 }) { - if (typeof value !== "string") { - return { value, errors: error2("string.base") }; - } - if (value === "") { - const min = schema.$_getRule("min"); - if (min && min.args.limit === 0) { - return; - } - return { value, errors: error2("string.empty") }; - } - }, - rules: { - alphanum: { - method() { - return this.$_addRule("alphanum"); - }, - validate(value, helpers) { - if (/^[a-zA-Z0-9]+$/.test(value)) { - return value; - } - return helpers.error("string.alphanum"); - } - }, - base64: { - method(options2 = {}) { - Common.assertOptions(options2, ["paddingRequired", "urlSafe"]); - options2 = { urlSafe: false, paddingRequired: true, ...options2 }; - assert2(typeof options2.paddingRequired === "boolean", "paddingRequired must be boolean"); - assert2(typeof options2.urlSafe === "boolean", "urlSafe must be boolean"); - return this.$_addRule({ name: "base64", args: { options: options2 } }); - }, - validate(value, helpers, { options: options2 }) { - const regex = internals.base64Regex[options2.paddingRequired][options2.urlSafe]; - if (regex.test(value)) { - return value; - } - return helpers.error("string.base64"); - } - }, - case: { - method(direction) { - assert2(["lower", "upper"].includes(direction), "Invalid case:", direction); - return this.$_addRule({ name: "case", args: { direction } }); - }, - validate(value, helpers, { direction }) { - if (direction === "lower" && value === value.toLocaleLowerCase() || direction === "upper" && value === value.toLocaleUpperCase()) { - return value; - } - return helpers.error(`string.${direction}case`); - }, - convert: true - }, - creditCard: { - method() { - return this.$_addRule("creditCard"); - }, - validate(value, helpers) { - let i2 = value.length; - let sum = 0; - let mul = 1; - while (i2--) { - const char = value.charAt(i2) * mul; - sum = sum + (char - (char > 9) * 9); - mul = mul ^ 3; - } - if (sum > 0 && sum % 10 === 0) { - return value; - } - return helpers.error("string.creditCard"); - } - }, - dataUri: { - method(options2 = {}) { - Common.assertOptions(options2, ["paddingRequired"]); - options2 = { paddingRequired: true, ...options2 }; - assert2(typeof options2.paddingRequired === "boolean", "paddingRequired must be boolean"); - return this.$_addRule({ name: "dataUri", args: { options: options2 } }); - }, - validate(value, helpers, { options: options2 }) { - const matches = value.match(internals.dataUriRegex); - if (matches) { - if (!matches[2]) { - return value; - } - if (matches[2] !== "base64") { - return value; - } - const base64regex = internals.base64Regex[options2.paddingRequired].false; - if (base64regex.test(matches[3])) { - return value; - } - } - return helpers.error("string.dataUri"); - } - }, - domain: { - method(options2) { - if (options2) { - Common.assertOptions(options2, ["allowFullyQualified", "allowUnicode", "allowUnderscore", "maxDomainSegments", "minDomainSegments", "tlds"]); - } - const address = internals.addressOptions(options2); - return this.$_addRule({ name: "domain", args: { options: options2 }, address }); - }, - validate(value, helpers, args, { address }) { - if (isDomainValid(value, address)) { - return value; - } - return helpers.error("string.domain"); - } - }, - email: { - method(options2 = {}) { - Common.assertOptions(options2, ["allowFullyQualified", "allowUnicode", "ignoreLength", "maxDomainSegments", "minDomainSegments", "multiple", "separator", "tlds"]); - assert2(options2.multiple === void 0 || typeof options2.multiple === "boolean", "multiple option must be an boolean"); - const address = internals.addressOptions(options2); - const regex = new RegExp(`\\s*[${options2.separator ? escapeRegex2(options2.separator) : ","}]\\s*`); - return this.$_addRule({ name: "email", args: { options: options2 }, regex, address }); - }, - validate(value, helpers, { options: options2 }, { regex, address }) { - const emails = options2.multiple ? value.split(regex) : [value]; - const invalids = []; - for (const email2 of emails) { - if (!isEmailValid(email2, address)) { - invalids.push(email2); - } - } - if (!invalids.length) { - return value; - } - return helpers.error("string.email", { value, invalids }); - } - }, - guid: { - alias: "uuid", - method(options2 = {}) { - Common.assertOptions(options2, ["version", "separator", "wrapper"]); - assert2( - options2.wrapper === void 0 || typeof options2.wrapper === "boolean" || typeof options2.wrapper === "string" && typeof internals.guidBrackets[options2.wrapper] === "string", - `"wrapper" must be true, false, or one of "${Object.keys(internals.guidBrackets).filter(Boolean).join('", "')}"` - ); - let versionNumbers = ""; - if (options2.version) { - const versions = [].concat(options2.version); - assert2(versions.length >= 1, "version must have at least 1 valid version specified"); - const set = /* @__PURE__ */ new Set(); - for (let i2 = 0; i2 < versions.length; ++i2) { - const version3 = versions[i2]; - assert2(typeof version3 === "string", "version at position " + i2 + " must be a string"); - const versionNumber = internals.guidVersions[version3.toLowerCase()]; - assert2(versionNumber, "version at position " + i2 + " must be one of " + Object.keys(internals.guidVersions).join(", ")); - assert2(!set.has(versionNumber), "version at position " + i2 + " must not be a duplicate"); - versionNumbers += versionNumber; - set.add(versionNumber); - } - } - assert2(internals.guidSeparators.has(options2.separator), 'separator must be one of true, false, "-", or ":"'); - const separator = options2.separator === void 0 ? "[:-]?" : options2.separator === true ? "[:-]" : options2.separator === false ? "[]?" : `\\${options2.separator}`; - let wrapperStart; - let wrapperEnd; - if (options2.wrapper === void 0) { - wrapperStart = "[\\[{\\(]?"; - wrapperEnd = "[\\]}\\)]?"; - } else if (options2.wrapper === true) { - wrapperStart = "[\\[{\\(]"; - wrapperEnd = "[\\]}\\)]"; - } else if (options2.wrapper === false) { - wrapperStart = ""; - wrapperEnd = ""; - } else { - wrapperStart = escapeRegex2(options2.wrapper); - wrapperEnd = escapeRegex2(internals.guidBrackets[options2.wrapper]); - } - const regex = new RegExp( - `^(${wrapperStart})[0-9A-F]{8}(${separator})[0-9A-F]{4}\\2?[${versionNumbers || "0-9A-F"}][0-9A-F]{3}\\2?[${versionNumbers ? "89AB" : "0-9A-F"}][0-9A-F]{3}\\2?[0-9A-F]{12}(${wrapperEnd})$`, - "i" - ); - return this.$_addRule({ name: "guid", args: { options: options2 }, regex }); - }, - validate(value, helpers, args, { regex }) { - const results = regex.exec(value); - if (!results) { - return helpers.error("string.guid"); - } - const open = results[1]; - const close = results[results.length - 1]; - if ((open || close) && internals.guidBrackets[open] !== close) { - return helpers.error("string.guid"); - } - return value; - } - }, - hex: { - method(options2 = {}) { - Common.assertOptions(options2, ["byteAligned", "prefix"]); - options2 = { byteAligned: false, prefix: false, ...options2 }; - assert2(typeof options2.byteAligned === "boolean", "byteAligned must be boolean"); - assert2(typeof options2.prefix === "boolean" || options2.prefix === "optional", 'prefix must be boolean or "optional"'); - return this.$_addRule({ name: "hex", args: { options: options2 } }); - }, - validate(value, helpers, { options: options2 }) { - const re = options2.prefix === "optional" ? internals.hexRegex.withOptionalPrefix : options2.prefix === true ? internals.hexRegex.withPrefix : internals.hexRegex.withoutPrefix; - if (!re.test(value)) { - return helpers.error("string.hex"); - } - if (options2.byteAligned && value.length % 2 !== 0) { - return helpers.error("string.hexAlign"); - } - return value; - } - }, - hostname: { - method() { - return this.$_addRule("hostname"); - }, - validate(value, helpers) { - if (isDomainValid(value, { minDomainSegments: 1 }) || internals.ipRegex.test(value)) { - return value; - } - return helpers.error("string.hostname"); - } - }, - insensitive: { - method() { - return this.$_setFlag("insensitive", true); - } - }, - ip: { - method(options2 = {}) { - Common.assertOptions(options2, ["cidr", "version"]); - const { cidr, versions, regex } = ipRegex(options2); - const version3 = options2.version ? versions : void 0; - return this.$_addRule({ name: "ip", args: { options: { cidr, version: version3 } }, regex }); - }, - validate(value, helpers, { options: options2 }, { regex }) { - if (regex.test(value)) { - return value; - } - if (options2.version) { - return helpers.error("string.ipVersion", { value, cidr: options2.cidr, version: options2.version }); - } - return helpers.error("string.ip", { value, cidr: options2.cidr }); - } - }, - isoDate: { - method() { - return this.$_addRule("isoDate"); - }, - validate(value, { error: error2 }) { - if (internals.isoDate(value)) { - return value; - } - return error2("string.isoDate"); - } - }, - isoDuration: { - method() { - return this.$_addRule("isoDuration"); - }, - validate(value, helpers) { - if (internals.isoDurationRegex.test(value)) { - return value; - } - return helpers.error("string.isoDuration"); - } - }, - length: { - method(limit, encoding) { - return internals.length(this, "length", limit, "=", encoding); - }, - validate(value, helpers, { limit, encoding }, { name, operator, args }) { - const length2 = encoding ? Buffer && Buffer.byteLength(value, encoding) : value.length; - if (Common.compare(length2, limit, operator)) { - return value; - } - return helpers.error("string." + name, { limit: args.limit, value, encoding }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - }, - "encoding" - ] - }, - lowercase: { - method() { - return this.case("lower"); - } - }, - max: { - method(limit, encoding) { - return internals.length(this, "max", limit, "<=", encoding); - }, - args: ["limit", "encoding"] - }, - min: { - method(limit, encoding) { - return internals.length(this, "min", limit, ">=", encoding); - }, - args: ["limit", "encoding"] - }, - normalize: { - method(form = "NFC") { - assert2(internals.normalizationForms.includes(form), "normalization form must be one of " + internals.normalizationForms.join(", ")); - return this.$_addRule({ name: "normalize", args: { form } }); - }, - validate(value, { error: error2 }, { form }) { - if (value === value.normalize(form)) { - return value; - } - return error2("string.normalize", { value, form }); - }, - convert: true - }, - pattern: { - alias: "regex", - method(regex, options2 = {}) { - assert2(regex instanceof RegExp, "regex must be a RegExp"); - assert2(!regex.flags.includes("g") && !regex.flags.includes("y"), "regex should not use global or sticky mode"); - if (typeof options2 === "string") { - options2 = { name: options2 }; - } - Common.assertOptions(options2, ["invert", "name"]); - const errorCode = ["string.pattern", options2.invert ? ".invert" : "", options2.name ? ".name" : ".base"].join(""); - return this.$_addRule({ name: "pattern", args: { regex, options: options2 }, errorCode }); - }, - validate(value, helpers, { regex, options: options2 }, { errorCode }) { - const patternMatch = regex.test(value); - if (patternMatch ^ options2.invert) { - return value; - } - return helpers.error(errorCode, { name: options2.name, regex, value }); - }, - args: ["regex", "options"], - multi: true - }, - replace: { - method(pattern, replacement) { - if (typeof pattern === "string") { - pattern = new RegExp(escapeRegex2(pattern), "g"); - } - assert2(pattern instanceof RegExp, "pattern must be a RegExp"); - assert2(typeof replacement === "string", "replacement must be a String"); - const obj = this.clone(); - if (!obj.$_terms.replacements) { - obj.$_terms.replacements = []; - } - obj.$_terms.replacements.push({ pattern, replacement }); - return obj; - } - }, - token: { - method() { - return this.$_addRule("token"); - }, - validate(value, helpers) { - if (/^\w+$/.test(value)) { - return value; - } - return helpers.error("string.token"); - } - }, - trim: { - method(enabled2 = true) { - assert2(typeof enabled2 === "boolean", "enabled must be a boolean"); - return this.$_addRule({ name: "trim", args: { enabled: enabled2 } }); - }, - validate(value, helpers, { enabled: enabled2 }) { - if (!enabled2 || value === value.trim()) { - return value; - } - return helpers.error("string.trim"); - }, - convert: true - }, - truncate: { - method(enabled2 = true) { - assert2(typeof enabled2 === "boolean", "enabled must be a boolean"); - return this.$_setFlag("truncate", enabled2); - } - }, - uppercase: { - method() { - return this.case("upper"); - } - }, - uri: { - method(options2 = {}) { - Common.assertOptions(options2, ["allowRelative", "allowQuerySquareBrackets", "domain", "relativeOnly", "scheme", "encodeUri"]); - if (options2.domain) { - Common.assertOptions(options2.domain, ["allowFullyQualified", "allowUnicode", "maxDomainSegments", "minDomainSegments", "tlds"]); - } - const { regex, scheme } = uriRegex(options2); - const domain = options2.domain ? internals.addressOptions(options2.domain) : null; - return this.$_addRule({ name: "uri", args: { options: options2 }, regex, domain, scheme }); - }, - validate(value, helpers, { options: options2 }, { regex, domain, scheme }) { - if (["http:/", "https:/"].includes(value)) { - return helpers.error("string.uri"); - } - let match = regex.exec(value); - if (!match && helpers.prefs.convert && options2.encodeUri) { - const encoded = encodeURI(value); - match = regex.exec(encoded); - if (match) { - value = encoded; - } - } - if (match) { - const matched = match[1] || match[2]; - if (domain && (!options2.allowRelative || matched) && !isDomainValid(matched, domain)) { - return helpers.error("string.domain", { value: matched }); - } - return value; - } - if (options2.relativeOnly) { - return helpers.error("string.uriRelativeOnly"); - } - if (options2.scheme) { - return helpers.error("string.uriCustomScheme", { scheme, value }); - } - return helpers.error("string.uri"); - } + if (!cheloniaConfig.contracts) { + cheloniaConfig.contracts = {}; + } +} +async function updateCheloniaConfig(fullContractName, contractName, version3, manifestPath) { + const manifestFileName = basename42(manifestPath); + const pinnedManifestPath = `contracts/${contractName}/${version3}/${manifestFileName}`; + cheloniaConfig.contracts[fullContractName] = { + version: version3, + path: pinnedManifestPath + }; + const configPath = join62(projectRoot, "chelonia.json"); + const configContent = JSON.stringify(cheloniaConfig, null, 2) + "\n"; + await writeFile2(configPath, configContent, "utf8"); + console.log(green("\u2705 Saved chelonia.json")); +} +var module10 = { + builder: (yargs) => { + return yargs.option("overwrite", { + describe: "Overwrite existing files", + requiresArg: false, + boolean: true + }).alias("o", "overwrite").option("dir", { + default: false, + describe: "Output directory", + requiresArg: false, + string: true + }).alias("d", "dir").positional("manifest", { + describe: "Manifest file path", + demandOption: true, + type: "string" + }).positional("manifest-version", { + describe: "Manifest version", + demandOption: false, + type: "string" + }); + }, + command: "pin []", + describe: "Pin a manifest version", + postHandler: (argv) => { + return pin(argv); + } +}; +init_esm(); +init_esm4(); +init_esm3(); +init_esm(); +var isEventQueueSbpEvent2 = (e2) => { + return Object.prototype.hasOwnProperty.call(e2, "sbpInvocation"); +}; +var esm_default5 = esm_default("sbp/selectors/register", { + "okTurtles.eventQueue/_init": function() { + this.eventQueues = /* @__PURE__ */ Object.create(null); + }, + "okTurtles.eventQueue/isWaiting": function(name) { + var _a2; + return !!((_a2 = this.eventQueues[name]) === null || _a2 === void 0 ? void 0 : _a2.length); + }, + "okTurtles.eventQueue/queuedInvocations": function(name) { + var _a2, _b; + if (name == null) { + return Object.fromEntries(Object.entries(this.eventQueues).map(([name2, events]) => [name2, events.map((event) => { + if (isEventQueueSbpEvent2(event)) { + return event.sbpInvocation; + } else { + return event.fn; } - }, - manifest: { - build(obj, desc) { - if (desc.replacements) { - for (const { pattern, replacement } of desc.replacements) { - obj = obj.replace(pattern, replacement); - } - } - return obj; - } - }, - messages: { - "string.alphanum": "{{#label}} must only contain alpha-numeric characters", - "string.base": "{{#label}} must be a string", - "string.base64": "{{#label}} must be a valid base64 string", - "string.creditCard": "{{#label}} must be a credit card", - "string.dataUri": "{{#label}} must be a valid dataUri string", - "string.domain": "{{#label}} must contain a valid domain name", - "string.email": "{{#label}} must be a valid email", - "string.empty": "{{#label}} is not allowed to be empty", - "string.guid": "{{#label}} must be a valid GUID", - "string.hex": "{{#label}} must only contain hexadecimal characters", - "string.hexAlign": "{{#label}} hex decoded representation must be byte aligned", - "string.hostname": "{{#label}} must be a valid hostname", - "string.ip": "{{#label}} must be a valid ip address with a {{#cidr}} CIDR", - "string.ipVersion": "{{#label}} must be a valid ip address of one of the following versions {{#version}} with a {{#cidr}} CIDR", - "string.isoDate": "{{#label}} must be in iso format", - "string.isoDuration": "{{#label}} must be a valid ISO 8601 duration", - "string.length": "{{#label}} length must be {{#limit}} characters long", - "string.lowercase": "{{#label}} must only contain lowercase characters", - "string.max": "{{#label}} length must be less than or equal to {{#limit}} characters long", - "string.min": "{{#label}} length must be at least {{#limit}} characters long", - "string.normalize": "{{#label}} must be unicode normalized in the {{#form}} form", - "string.token": "{{#label}} must only contain alpha-numeric and underscore characters", - "string.pattern.base": "{{#label}} with value {:[.]} fails to match the required pattern: {{#regex}}", - "string.pattern.name": "{{#label}} with value {:[.]} fails to match the {{#name}} pattern", - "string.pattern.invert.base": "{{#label}} with value {:[.]} matches the inverted pattern: {{#regex}}", - "string.pattern.invert.name": "{{#label}} with value {:[.]} matches the inverted {{#name}} pattern", - "string.trim": "{{#label}} must not have leading or trailing whitespace", - "string.uri": "{{#label}} must be a valid uri", - "string.uriCustomScheme": "{{#label}} must be a valid uri with a scheme matching the {{#scheme}} pattern", - "string.uriRelativeOnly": "{{#label}} must be a valid relative uri", - "string.uppercase": "{{#label}} must only contain uppercase characters" + })])); + } + return (_b = (_a2 = this.eventQueues[name]) === null || _a2 === void 0 ? void 0 : _a2.map((event) => { + if (isEventQueueSbpEvent2(event)) { + return event.sbpInvocation; + } else { + return event.fn; } + })) !== null && _b !== void 0 ? _b : []; + }, + "okTurtles.eventQueue/queueEvent": async function(name, invocation) { + if (!Object.prototype.hasOwnProperty.call(this.eventQueues, name)) { + this.eventQueues[name] = []; + } + const events = this.eventQueues[name]; + let accept; + const promise = new Promise((resolve82) => { + accept = resolve82; }); - internals.addressOptions = function(options2) { - if (!options2) { - return internals.tlds || options2; + const thisEvent = typeof invocation === "function" ? { + fn: invocation, + promise + } : { + sbpInvocation: invocation, + promise + }; + events.push(thisEvent); + while (events.length > 0) { + const event = events[0]; + if (event === thisEvent) { + try { + if (typeof invocation === "function") { + return await invocation(); + } else { + return await esm_default(...invocation); + } + } finally { + accept(); + events.shift(); + } + } else { + await event.promise; } - assert2(options2.minDomainSegments === void 0 || Number.isSafeInteger(options2.minDomainSegments) && options2.minDomainSegments > 0, "minDomainSegments must be a positive integer"); - assert2(options2.maxDomainSegments === void 0 || Number.isSafeInteger(options2.maxDomainSegments) && options2.maxDomainSegments > 0, "maxDomainSegments must be a positive integer"); - if (options2.tlds === false) { - return options2; + } + } +}); +init_esm(); +init_esm3(); +var listenKey2 = (evt) => `events/${evt}/listeners`; +var esm_default6 = esm_default("sbp/selectors/register", { + "okTurtles.events/_init": function() { + this.errorHandler = (event, e2) => { + console.error(`[okTurtles.events] Error at handler for ${event}`, e2); + }; + }, + "okTurtles.events/on": function(event, handler) { + esm_default("okTurtles.data/add", listenKey2(event), handler); + return () => esm_default("okTurtles.events/off", event, handler); + }, + "okTurtles.events/once": function(event, handler) { + const cbWithOff = (...args) => { + handler(...args); + esm_default("okTurtles.events/off", event, cbWithOff); + }; + return esm_default("okTurtles.events/on", event, cbWithOff); + }, + "okTurtles.events/emit": function(event, ...data) { + var _a2; + for (const listener of esm_default("okTurtles.data/get", listenKey2(event)) || []) { + try { + listener(...data); + } catch (e2) { + (_a2 = this.errorHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, event, e2); + } + } + }, + // almost identical to Vue.prototype.$off, except we require `event` argument + "okTurtles.events/off": function(event, handler) { + if (handler) { + esm_default("okTurtles.data/remove", listenKey2(event), handler); + } else { + esm_default("okTurtles.data/delete", listenKey2(event)); + } + }, + "okTurtles.events/setErrorHandler": function(errorHandler2) { + this.errorHandler = errorHandler2; + } +}); +init_esm(); +var import_npm_chalk4 = __toESM(require_source()); +var SERVER_EXITING = "server-exiting"; +var SERVER_RUNNING = "server-running"; +init_SPMessage(); +init_functions(); +init_esm(); +var timer = Symbol("timer"); +var coerceToError = (arg) => { + if (arg && arg instanceof Error) + return arg; + console.warn(tag, "Please use Error objects when throwing or rejecting"); + return new Error((typeof arg === "string" ? arg : JSON.stringify(arg)) ?? "undefined"); +}; +var defaultOptions2 = { + maxAttempts: Number.POSITIVE_INFINITY, + retrySeconds: 30 +}; +var tag = "[chelonia.persistentActions]"; +var PersistentAction = class { + id; + invocation; + options; + status; + [timer]; + constructor(invocation, options2 = {}) { + this.id = crypto.randomUUID(); + this.invocation = invocation; + this.options = { ...defaultOptions2, ...options2 }; + this.status = { + attempting: false, + failedAttemptsSoFar: 0, + lastError: "", + nextRetry: "", + resolved: false + }; + } + async attempt() { + if (this.status.attempting || this.status.resolved) + return; + if (await this.trySBP(this.options.skipCondition)) + this.cancel(); + if (this.status.resolved) + return; + try { + this.status.attempting = true; + const result = await esm_default(...this.invocation); + this.status.attempting = false; + this.handleSuccess(result); + } catch (error2) { + this.status.attempting = false; + await this.handleError(coerceToError(error2)); + } + } + cancel() { + if (this[timer]) + clearTimeout(this[timer]); + this.status.nextRetry = ""; + this.status.resolved = true; + } + async handleError(error2) { + const { id, options: options2, status } = this; + status.failedAttemptsSoFar++; + status.lastError = error2.message; + const anyAttemptLeft = options2.maxAttempts > status.failedAttemptsSoFar; + if (!anyAttemptLeft) + status.resolved = true; + status.nextRetry = anyAttemptLeft && !status.resolved ? new Date(Date.now() + options2.retrySeconds * 1e3).toISOString() : ""; + esm_default("okTurtles.events/emit", PERSISTENT_ACTION_FAILURE, { error: error2, id }); + await this.trySBP(options2.errorInvocation); + if (!anyAttemptLeft) { + esm_default("okTurtles.events/emit", PERSISTENT_ACTION_TOTAL_FAILURE, { error: error2, id }); + await this.trySBP(options2.totalFailureInvocation); + } + if (status.nextRetry) { + this[timer] = setTimeout(() => { + this.attempt().catch((e2) => { + console.error("Error attempting persistent action", id, e2); + }); + }, this.options.retrySeconds * 1e3); + } + } + handleSuccess(result) { + const { id, status } = this; + status.lastError = ""; + status.nextRetry = ""; + status.resolved = true; + esm_default("okTurtles.events/emit", PERSISTENT_ACTION_SUCCESS, { id, result }); + } + async trySBP(invocation) { + try { + return invocation ? await esm_default(...invocation) : void 0; + } catch (error2) { + console.error(tag, coerceToError(error2).message); + } + } +}; +var persistent_actions_default = esm_default("sbp/selectors/register", { + "chelonia.persistentActions/_init"() { + this.actionsByID = /* @__PURE__ */ Object.create(null); + this.checkDatabaseKey = () => { + if (!this.databaseKey) + throw new TypeError(`${tag} No database key configured`); + }; + esm_default("okTurtles.events/on", PERSISTENT_ACTION_SUCCESS, ({ id }) => { + esm_default("chelonia.persistentActions/cancel", id); + }); + esm_default("okTurtles.events/on", PERSISTENT_ACTION_TOTAL_FAILURE, ({ id }) => { + esm_default("chelonia.persistentActions/cancel", id); + }); + }, + // Cancels a specific action by its ID. + // The action won't be retried again, but an async action cannot be aborted if its promise is stil attempting. + async "chelonia.persistentActions/cancel"(id) { + if (id in this.actionsByID) { + this.actionsByID[id].cancel(); + delete this.actionsByID[id]; + return await esm_default("chelonia.persistentActions/save"); + } + }, + // TODO: validation + "chelonia.persistentActions/configure"({ databaseKey, options: options2 = {} }) { + this.databaseKey = databaseKey; + for (const key in options2) { + if (key in defaultOptions2) { + defaultOptions2[key] = options2[key]; + } else { + throw new TypeError(`${tag} Unknown option: ${key}`); } - if (options2.tlds === true || options2.tlds === void 0) { - assert2(internals.tlds, "Built-in TLD list disabled"); - return Object.assign({}, options2, internals.tlds); + } + }, + "chelonia.persistentActions/enqueue"(...args) { + const ids = []; + for (const arg of args) { + const action = Array.isArray(arg) ? new PersistentAction(arg) : new PersistentAction(arg.invocation, arg); + this.actionsByID[action.id] = action; + ids.push(action.id); + } + esm_default("chelonia.persistentActions/save").catch((e2) => { + console.error("Error saving persistent actions", e2); + }); + for (const id of ids) { + this.actionsByID[id].attempt().catch((e2) => { + console.error("Error attempting persistent action", id, e2); + }); + } + return ids; + }, + // Forces retrying a given persisted action immediately, rather than waiting for the scheduled retry. + // - 'status.failedAttemptsSoFar' will still be increased upon failure. + // - Does nothing if a retry is already running. + // - Does nothing if the action has already been resolved, rejected or cancelled. + "chelonia.persistentActions/forceRetry"(id) { + if (id in this.actionsByID) { + return this.actionsByID[id].attempt(); + } + }, + // Loads and tries every stored persistent action under the configured database key. + async "chelonia.persistentActions/load"() { + this.checkDatabaseKey(); + const storedActions = JSON.parse(await esm_default("chelonia.db/get", this.databaseKey) ?? "[]"); + for (const { id, invocation, options: options2 } of storedActions) { + this.actionsByID[id] = new PersistentAction(invocation, options2); + this.actionsByID[id].id = id; + } + return esm_default("chelonia.persistentActions/retryAll"); + }, + // Retry all existing persisted actions. + // TODO: add some delay between actions so as not to spam the server, + // or have a way to issue them all at once in a single network call. + "chelonia.persistentActions/retryAll"() { + return Promise.allSettled(Object.keys(this.actionsByID).map((id) => esm_default("chelonia.persistentActions/forceRetry", id))); + }, + // Updates the database version of the attempting action list. + "chelonia.persistentActions/save"() { + this.checkDatabaseKey(); + return esm_default("chelonia.db/set", this.databaseKey, JSON.stringify(Object.values(this.actionsByID))); + }, + "chelonia.persistentActions/status"() { + return Object.values(this.actionsByID).map((action) => ({ + id: action.id, + invocation: action.invocation, + ...action.status + })); + }, + // Pauses every currently loaded action, and removes them from memory. + // Note: persistent storage is not affected, so that these actions can be later loaded again and retried. + "chelonia.persistentActions/unload"() { + for (const id in this.actionsByID) { + if (this.actionsByID[id][timer]) { + clearTimeout(this.actionsByID[id][timer]); + } + delete this.actionsByID[id]; + } + } +}); +var SERVER = { + // We don't check the subscriptionSet in the server because we accpt new + // contract registrations, and are also not subcribed to contracts the same + // way clients are + acceptAllMessages: true, + // The server also doesn't process actions + skipActionProcessing: true, + // The previous setting implies this one, which we set to be on the safe side + skipSideEffects: true, + // Changes the behaviour of unwrapMaybeEncryptedData so that it never decrypts. + // Mostly useful for the server, to avoid filling up the logs and for faster + // execution. + skipDecryptionAttempts: true, + // If an error occurs during processing, the message is rejected rather than + // ignored + strictProcessing: true, + // The server expects events to be received in order (no past or future events) + strictOrdering: true +}; +init_esm(); +var import_npm_chalk3 = __toESM(require_source()); +var compose = (middleware, onError, onNotFound) => { + return (context, next) => { + let index = -1; + return dispatch(0); + async function dispatch(i2) { + if (i2 <= index) { + throw new Error("next() called multiple times"); + } + index = i2; + let res; + let isError = false; + let handler; + if (middleware[i2]) { + handler = middleware[i2][0][0]; + context.req.routeIndex = i2; + } else { + handler = i2 === middleware.length && next || void 0; } - assert2(typeof options2.tlds === "object", "tlds must be true, false, or an object"); - const deny = options2.tlds.deny; - if (deny) { - if (Array.isArray(deny)) { - options2 = Object.assign({}, options2, { tlds: { deny: new Set(deny) } }); + if (handler) { + try { + res = await handler(context, () => dispatch(i2 + 1)); + } catch (err) { + if (err instanceof Error && onError) { + context.error = err; + res = await onError(err, context); + isError = true; + } else { + throw err; + } + } + } else { + if (context.finalized === false && onNotFound) { + res = await onNotFound(context); } - assert2(options2.tlds.deny instanceof Set, "tlds.deny must be an array, Set, or boolean"); - assert2(!options2.tlds.allow, "Cannot specify both tlds.allow and tlds.deny lists"); - internals.validateTlds(options2.tlds.deny, "tlds.deny"); - return options2; } - const allow = options2.tlds.allow; - if (!allow) { - return { ...options2, tlds: false }; + if (res && (context.finalized === false || isError)) { + context.res = res; + } + return context; + } + }; +}; +var HTTPException = class extends Error { + res; + status; + /** + * Creates an instance of `HTTPException`. + * @param status - HTTP status code for the exception. Defaults to 500. + * @param options - Additional options for the exception. + */ + constructor(status = 500, options2) { + super(options2?.message, { cause: options2?.cause }); + this.res = options2?.res; + this.status = status; + } + /** + * Returns the response object associated with the exception. + * If a response object is not provided, a new response is created with the error message and status code. + * @returns The response object. + */ + getResponse() { + if (this.res) { + const newResponse = new Response(this.res.body, { + status: this.status, + headers: this.res.headers + }); + return newResponse; + } + return new Response(this.message, { + status: this.status + }); + } +}; +var GET_MATCH_RESULT = /* @__PURE__ */ Symbol(); +var parseBody = async (request, options2 = /* @__PURE__ */ Object.create(null)) => { + const { all = false, dot = false } = options2; + const headers = request instanceof HonoRequest ? request.raw.headers : request.headers; + const contentType = headers.get("Content-Type"); + if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) { + return parseFormData(request, { all, dot }); + } + return {}; +}; +async function parseFormData(request, options2) { + const formData = await request.formData(); + if (formData) { + return convertFormDataToBodyData(formData, options2); + } + return {}; +} +function convertFormDataToBodyData(formData, options2) { + const form = /* @__PURE__ */ Object.create(null); + formData.forEach((value, key) => { + const shouldParseAllValues = options2.all || key.endsWith("[]"); + if (!shouldParseAllValues) { + form[key] = value; + } else { + handleParsingAllValues(form, key, value); + } + }); + if (options2.dot) { + Object.entries(form).forEach(([key, value]) => { + const shouldParseDotValues = key.includes("."); + if (shouldParseDotValues) { + handleParsingNestedValues(form, key, value); + delete form[key]; } - if (allow === true) { - assert2(internals.tlds, "Built-in TLD list disabled"); - return Object.assign({}, options2, internals.tlds); + }); + } + return form; +} +var handleParsingAllValues = (form, key, value) => { + if (form[key] !== void 0) { + if (Array.isArray(form[key])) { + ; + form[key].push(value); + } else { + form[key] = [form[key], value]; + } + } else { + if (!key.endsWith("[]")) { + form[key] = value; + } else { + form[key] = [value]; + } + } +}; +var handleParsingNestedValues = (form, key, value) => { + if (/(?:^|\.)__proto__\./.test(key)) { + return; + } + let nestedForm = form; + const keys = key.split("."); + keys.forEach((key2, index) => { + if (index === keys.length - 1) { + nestedForm[key2] = value; + } else { + if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) { + nestedForm[key2] = /* @__PURE__ */ Object.create(null); } - if (Array.isArray(allow)) { - options2 = Object.assign({}, options2, { tlds: { allow: new Set(allow) } }); + nestedForm = nestedForm[key2]; + } + }); +}; +var splitPath = (path8) => { + const paths = path8.split("/"); + if (paths[0] === "") { + paths.shift(); + } + return paths; +}; +var splitRoutingPath = (routePath) => { + const { groups, path: path8 } = extractGroupsFromPath(routePath); + const paths = splitPath(path8); + return replaceGroupMarks(paths, groups); +}; +var extractGroupsFromPath = (path8) => { + const groups = []; + path8 = path8.replace(/\{[^}]+\}/g, (match2, index) => { + const mark = `@${index}`; + groups.push([mark, match2]); + return mark; + }); + return { groups, path: path8 }; +}; +var replaceGroupMarks = (paths, groups) => { + for (let i2 = groups.length - 1; i2 >= 0; i2--) { + const [mark] = groups[i2]; + for (let j = paths.length - 1; j >= 0; j--) { + if (paths[j].includes(mark)) { + paths[j] = paths[j].replace(mark, groups[i2][1]); + break; } - assert2(options2.tlds.allow instanceof Set, "tlds.allow must be an array, Set, or boolean"); - internals.validateTlds(options2.tlds.allow, "tlds.allow"); - return options2; - }; - internals.validateTlds = function(set, source) { - for (const tld of set) { - assert2(isDomainValid(tld, { minDomainSegments: 1, maxDomainSegments: 1 }), `${source} must contain valid top level domain names`); + } + } + return paths; +}; +var patternCache = {}; +var getPattern = (label, next) => { + if (label === "*") { + return "*"; + } + const match2 = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/); + if (match2) { + const cacheKey2 = `${label}#${next}`; + if (!patternCache[cacheKey2]) { + if (match2[2]) { + patternCache[cacheKey2] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey2, match2[1], new RegExp(`^${match2[2]}(?=/${next})`)] : [label, match2[1], new RegExp(`^${match2[2]}$`)]; + } else { + patternCache[cacheKey2] = [label, match2[1], true]; } - }; - internals.isoDate = function(value) { - if (!Common.isIsoDate(value)) { - return null; + } + return patternCache[cacheKey2]; + } + return null; +}; +var tryDecode = (str, decoder) => { + try { + return decoder(str); + } catch { + return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match2) => { + try { + return decoder(match2); + } catch { + return match2; } - if (/.*T.*[+-]\d\d$/.test(value)) { - value += "00"; + }); + } +}; +var tryDecodeURI = (str) => tryDecode(str, decodeURI); +var getPath = (request) => { + const url2 = request.url; + const start = url2.indexOf("/", url2.indexOf(":") + 4); + let i2 = start; + for (; i2 < url2.length; i2++) { + const charCode = url2.charCodeAt(i2); + if (charCode === 37) { + const queryIndex = url2.indexOf("?", i2); + const hashIndex = url2.indexOf("#", i2); + const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex); + const path8 = url2.slice(start, end); + return tryDecodeURI(path8.includes("%25") ? path8.replace(/%25/g, "%2525") : path8); + } else if (charCode === 63 || charCode === 35) { + break; + } + } + return url2.slice(start, i2); +}; +var getPathNoStrict = (request) => { + const result = getPath(request); + return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result; +}; +var mergePath = (base2, sub, ...rest) => { + if (rest.length) { + sub = mergePath(sub, ...rest); + } + return `${base2?.[0] === "/" ? "" : "/"}${base2}${sub === "/" ? "" : `${base2?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`; +}; +var checkOptionalParameter = (path8) => { + if (path8.charCodeAt(path8.length - 1) !== 63 || !path8.includes(":")) { + return null; + } + const segments = path8.split("/"); + const results = []; + let basePath = ""; + segments.forEach((segment) => { + if (segment !== "" && !/\:/.test(segment)) { + basePath += "/" + segment; + } else if (/\:/.test(segment)) { + if (/\?/.test(segment)) { + if (results.length === 0 && basePath === "") { + results.push("/"); + } else { + results.push(basePath); + } + const optionalSegment = segment.replace("?", ""); + basePath += "/" + optionalSegment; + results.push(basePath); + } else { + basePath += "/" + segment; } - const date3 = new Date(value); - if (isNaN(date3.getTime())) { - return null; + } + }); + return results.filter((v2, i2, a) => a.indexOf(v2) === i2); +}; +var _decodeURI = (value) => { + if (!/[%+]/.test(value)) { + return value; + } + if (value.indexOf("+") !== -1) { + value = value.replace(/\+/g, " "); + } + return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value; +}; +var _getQueryParam = (url2, key, multiple) => { + let encoded; + if (!multiple && key && !/[%+]/.test(key)) { + let keyIndex2 = url2.indexOf("?", 8); + if (keyIndex2 === -1) { + return void 0; + } + if (!url2.startsWith(key, keyIndex2 + 1)) { + keyIndex2 = url2.indexOf(`&${key}`, keyIndex2 + 1); + } + while (keyIndex2 !== -1) { + const trailingKeyCode = url2.charCodeAt(keyIndex2 + key.length + 1); + if (trailingKeyCode === 61) { + const valueIndex = keyIndex2 + key.length + 2; + const endIndex = url2.indexOf("&", valueIndex); + return _decodeURI(url2.slice(valueIndex, endIndex === -1 ? void 0 : endIndex)); + } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) { + return ""; } - return date3.toISOString(); - }; - internals.length = function(schema, name, limit, operator, encoding) { - assert2(!encoding || Buffer && Buffer.isEncoding(encoding), "Invalid encoding:", encoding); - return schema.$_addRule({ name, method: "length", args: { limit, encoding }, operator }); - }; + keyIndex2 = url2.indexOf(`&${key}`, keyIndex2 + 1); + } + encoded = /[%+]/.test(url2); + if (!encoded) { + return void 0; + } } -}); -var require_symbol2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/symbol.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Any = require_any2(); - var internals = {}; - internals.Map = class extends Map { - slice() { - return new internals.Map(this); + const results = {}; + encoded ??= /[%+]/.test(url2); + let keyIndex = url2.indexOf("?", 8); + while (keyIndex !== -1) { + const nextKeyIndex = url2.indexOf("&", keyIndex + 1); + let valueIndex = url2.indexOf("=", keyIndex); + if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) { + valueIndex = -1; + } + let name = url2.slice( + keyIndex + 1, + valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex + ); + if (encoded) { + name = _decodeURI(name); + } + keyIndex = nextKeyIndex; + if (name === "") { + continue; + } + let value; + if (valueIndex === -1) { + value = ""; + } else { + value = url2.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex); + if (encoded) { + value = _decodeURI(value); } - }; - module14.exports = Any.extend({ - type: "symbol", - terms: { - map: { init: new internals.Map() } - }, - coerce: { - method(value, { schema, error: error2 }) { - const lookup = schema.$_terms.map.get(value); - if (lookup) { - value = lookup; - } - if (!schema._flags.only || typeof value === "symbol") { - return { value }; - } - return { value, errors: error2("symbol.map", { map: schema.$_terms.map }) }; - } - }, - validate(value, { error: error2 }) { - if (typeof value !== "symbol") { - return { value, errors: error2("symbol.base") }; - } - }, - rules: { - map: { - method(iterable) { - if (iterable && !iterable[Symbol.iterator] && typeof iterable === "object") { - iterable = Object.entries(iterable); - } - assert2(iterable && iterable[Symbol.iterator], "Iterable must be an iterable or object"); - const obj = this.clone(); - const symbols2 = []; - for (const entry of iterable) { - assert2(entry && entry[Symbol.iterator], "Entry must be an iterable"); - const [key, value] = entry; - assert2(typeof key !== "object" && typeof key !== "function" && typeof key !== "symbol", "Key must not be of type object, function, or Symbol"); - assert2(typeof value === "symbol", "Value must be a Symbol"); - obj.$_terms.map.set(key, value); - symbols2.push(value); - } - return obj.valid(...symbols2); - } - } - }, - manifest: { - build(obj, desc) { - if (desc.map) { - obj = obj.map(desc.map); - } - return obj; - } - }, - messages: { - "symbol.base": "{{#label}} must be a symbol", - "symbol.map": "{{#label}} must be one of {{#map}}" + } + if (multiple) { + if (!(results[name] && Array.isArray(results[name]))) { + results[name] = []; + } + ; + results[name].push(value); + } else { + results[name] ??= value; + } + } + return key ? results[key] : results; +}; +var getQueryParam = _getQueryParam; +var getQueryParams = (url2, key) => { + return _getQueryParam(url2, key, true); +}; +var decodeURIComponent_ = decodeURIComponent; +var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_); +var HonoRequest = class { + /** + * `.raw` can get the raw Request object. + * + * @see {@link https://hono.dev/docs/api/request#raw} + * + * @example + * ```ts + * // For Cloudflare Workers + * app.post('/', async (c) => { + * const metadata = c.req.raw.cf?.hostMetadata? + * ... + * }) + * ``` + */ + raw; + #validatedData; + // Short name of validatedData + #matchResult; + routeIndex = 0; + /** + * `.path` can get the pathname of the request. + * + * @see {@link https://hono.dev/docs/api/request#path} + * + * @example + * ```ts + * app.get('/about/me', (c) => { + * const pathname = c.req.path // `/about/me` + * }) + * ``` + */ + path; + bodyCache = {}; + constructor(request, path8 = "/", matchResult = [[]]) { + this.raw = request; + this.path = path8; + this.#matchResult = matchResult; + this.#validatedData = {}; + } + param(key) { + return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams(); + } + #getDecodedParam(key) { + const paramKey = this.#matchResult[0][this.routeIndex][1][key]; + const param = this.#getParamValue(paramKey); + return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param; + } + #getAllDecodedParams() { + const decoded = {}; + const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]); + for (const key of keys) { + const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]); + if (value !== void 0) { + decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value; } + } + return decoded; + } + #getParamValue(paramKey) { + return this.#matchResult[1] ? this.#matchResult[1][paramKey] : paramKey; + } + query(key) { + return getQueryParam(this.url, key); + } + queries(key) { + return getQueryParams(this.url, key); + } + header(name) { + if (name) { + return this.raw.headers.get(name) ?? void 0; + } + const headerData = {}; + this.raw.headers.forEach((value, key) => { + headerData[key] = value; }); + return headerData; } -}); -var require_binary2 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/types/binary.js"(exports2, module14) { - "use strict"; - var { assert: assert2 } = require_lib(); - var Any = require_any2(); - var Common = require_common3(); - module14.exports = Any.extend({ - type: "binary", - coerce: { - from: ["string", "object"], - method(value, { schema }) { - if (typeof value === "string" || value !== null && value.type === "Buffer") { - try { - return { value: Buffer.from(value, schema._flags.encoding) }; - } catch { - } - } - } - }, - validate(value, { error: error2 }) { - if (!Buffer.isBuffer(value)) { - return { value, errors: error2("binary.base") }; + async parseBody(options2) { + return parseBody(this, options2); + } + #cachedBody = (key) => { + const { bodyCache, raw: raw2 } = this; + const cachedBody = bodyCache[key]; + if (cachedBody) { + return cachedBody; + } + const anyCachedKey = Object.keys(bodyCache)[0]; + if (anyCachedKey) { + return bodyCache[anyCachedKey].then((body) => { + if (anyCachedKey === "json") { + body = JSON.stringify(body); } - }, - rules: { - encoding: { - method(encoding) { - assert2(Buffer.isEncoding(encoding), "Invalid encoding:", encoding); - return this.$_setFlag("encoding", encoding); - } - }, - length: { - method(limit) { - return this.$_addRule({ name: "length", method: "length", args: { limit }, operator: "=" }); - }, - validate(value, helpers, { limit }, { name, operator, args }) { - if (Common.compare(value.length, limit, operator)) { - return value; - } - return helpers.error("binary." + name, { limit: args.limit, value }); - }, - args: [ - { - name: "limit", - ref: true, - assert: Common.limit, - message: "must be a positive integer" - } - ] - }, - max: { - method(limit) { - return this.$_addRule({ name: "max", method: "length", args: { limit }, operator: "<=" }); - } - }, - min: { - method(limit) { - return this.$_addRule({ name: "min", method: "length", args: { limit }, operator: ">=" }); - } + return new Response(body)[key](); + }); + } + return bodyCache[key] = raw2[key](); + }; + /** + * `.json()` can parse Request body of type `application/json` + * + * @see {@link https://hono.dev/docs/api/request#json} + * + * @example + * ```ts + * app.post('/entry', async (c) => { + * const body = await c.req.json() + * }) + * ``` + */ + json() { + return this.#cachedBody("text").then((text) => JSON.parse(text)); + } + /** + * `.text()` can parse Request body of type `text/plain` + * + * @see {@link https://hono.dev/docs/api/request#text} + * + * @example + * ```ts + * app.post('/entry', async (c) => { + * const body = await c.req.text() + * }) + * ``` + */ + text() { + return this.#cachedBody("text"); + } + /** + * `.arrayBuffer()` parse Request body as an `ArrayBuffer` + * + * @see {@link https://hono.dev/docs/api/request#arraybuffer} + * + * @example + * ```ts + * app.post('/entry', async (c) => { + * const body = await c.req.arrayBuffer() + * }) + * ``` + */ + arrayBuffer() { + return this.#cachedBody("arrayBuffer"); + } + /** + * Parses the request body as a `Blob`. + * @example + * ```ts + * app.post('/entry', async (c) => { + * const body = await c.req.blob(); + * }); + * ``` + * @see https://hono.dev/docs/api/request#blob + */ + blob() { + return this.#cachedBody("blob"); + } + /** + * Parses the request body as `FormData`. + * @example + * ```ts + * app.post('/entry', async (c) => { + * const body = await c.req.formData(); + * }); + * ``` + * @see https://hono.dev/docs/api/request#formdata + */ + formData() { + return this.#cachedBody("formData"); + } + /** + * Adds validated data to the request. + * + * @param target - The target of the validation. + * @param data - The validated data to add. + */ + addValidatedData(target, data) { + this.#validatedData[target] = data; + } + valid(target) { + return this.#validatedData[target]; + } + /** + * `.url()` can get the request url strings. + * + * @see {@link https://hono.dev/docs/api/request#url} + * + * @example + * ```ts + * app.get('/about/me', (c) => { + * const url = c.req.url // `http://localhost:8787/about/me` + * ... + * }) + * ``` + */ + get url() { + return this.raw.url; + } + /** + * `.method()` can get the method name of the request. + * + * @see {@link https://hono.dev/docs/api/request#method} + * + * @example + * ```ts + * app.get('/about/me', (c) => { + * const method = c.req.method // `GET` + * }) + * ``` + */ + get method() { + return this.raw.method; + } + get [GET_MATCH_RESULT]() { + return this.#matchResult; + } + /** + * `.matchedRoutes()` can return a matched route in the handler + * + * @deprecated + * + * Use matchedRoutes helper defined in "hono/route" instead. + * + * @see {@link https://hono.dev/docs/api/request#matchedroutes} + * + * @example + * ```ts + * app.use('*', async function logger(c, next) { + * await next() + * c.req.matchedRoutes.forEach(({ handler, method, path }, i) => { + * const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]') + * console.log( + * method, + * ' ', + * path, + * ' '.repeat(Math.max(10 - path.length, 0)), + * name, + * i === c.req.routeIndex ? '<- respond from here' : '' + * ) + * }) + * }) + * ``` + */ + get matchedRoutes() { + return this.#matchResult[0].map(([[, route]]) => route); + } + /** + * `routePath()` can retrieve the path registered within the handler + * + * @deprecated + * + * Use routePath helper defined in "hono/route" instead. + * + * @see {@link https://hono.dev/docs/api/request#routepath} + * + * @example + * ```ts + * app.get('/posts/:id', (c) => { + * return c.json({ path: c.req.routePath }) + * }) + * ``` + */ + get routePath() { + return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path; + } +}; +var HtmlEscapedCallbackPhase = { + Stringify: 1, + BeforeStream: 2, + Stream: 3 +}; +var raw = (value, callbacks) => { + const escapedString = new String(value); + escapedString.isEscaped = true; + escapedString.callbacks = callbacks; + return escapedString; +}; +var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => { + if (typeof str === "object" && !(str instanceof String)) { + if (!(str instanceof Promise)) { + str = str.toString(); + } + if (str instanceof Promise) { + str = await str; + } + } + const callbacks = str.callbacks; + if (!callbacks?.length) { + return Promise.resolve(str); + } + if (buffer) { + buffer[0] += str; + } else { + buffer = [str]; + } + const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then( + (res) => Promise.all( + res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context, buffer)) + ).then(() => buffer[0]) + ); + if (preserveCallbacks) { + return raw(await resStr, callbacks); + } else { + return resStr; + } +}; +var TEXT_PLAIN = "text/plain; charset=UTF-8"; +var setDefaultContentType = (contentType, headers) => { + return { + "Content-Type": contentType, + ...headers + }; +}; +var createResponseInstance = (body, init2) => new Response(body, init2); +var Context = class { + #rawRequest; + #req; + /** + * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers. + * + * @see {@link https://hono.dev/docs/api/context#env} + * + * @example + * ```ts + * // Environment object for Cloudflare Workers + * app.get('*', async c => { + * const counter = c.env.COUNTER + * }) + * ``` + */ + env = {}; + #var; + finalized = false; + /** + * `.error` can get the error object from the middleware if the Handler throws an error. + * + * @see {@link https://hono.dev/docs/api/context#error} + * + * @example + * ```ts + * app.use('*', async (c, next) => { + * await next() + * if (c.error) { + * // do something... + * } + * }) + * ``` + */ + error; + #status; + #executionCtx; + #res; + #layout; + #renderer; + #notFoundHandler; + #preparedHeaders; + #matchResult; + #path; + /** + * Creates an instance of the Context class. + * + * @param req - The Request object. + * @param options - Optional configuration options for the context. + */ + constructor(req, options2) { + this.#rawRequest = req; + if (options2) { + this.#executionCtx = options2.executionCtx; + this.env = options2.env; + this.#notFoundHandler = options2.notFoundHandler; + this.#path = options2.path; + this.#matchResult = options2.matchResult; + } + } + /** + * `.req` is the instance of {@link HonoRequest}. + */ + get req() { + this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult); + return this.#req; + } + /** + * @see {@link https://hono.dev/docs/api/context#event} + * The FetchEvent associated with the current request. + * + * @throws Will throw an error if the context does not have a FetchEvent. + */ + get event() { + if (this.#executionCtx && "respondWith" in this.#executionCtx) { + return this.#executionCtx; + } else { + throw Error("This context has no FetchEvent"); + } + } + /** + * @see {@link https://hono.dev/docs/api/context#executionctx} + * The ExecutionContext associated with the current request. + * + * @throws Will throw an error if the context does not have an ExecutionContext. + */ + get executionCtx() { + if (this.#executionCtx) { + return this.#executionCtx; + } else { + throw Error("This context has no ExecutionContext"); + } + } + /** + * @see {@link https://hono.dev/docs/api/context#res} + * The Response object for the current request. + */ + get res() { + return this.#res ||= createResponseInstance(null, { + headers: this.#preparedHeaders ??= new Headers() + }); + } + /** + * Sets the Response object for the current request. + * + * @param _res - The Response object to set. + */ + set res(_res) { + if (this.#res && _res) { + _res = createResponseInstance(_res.body, _res); + for (const [k, v2] of this.#res.headers.entries()) { + if (k === "content-type") { + continue; } - }, - cast: { - string: { - from: (value) => Buffer.isBuffer(value), - to(value, helpers) { - return value.toString(); + if (k === "set-cookie") { + const cookies = this.#res.headers.getSetCookie(); + _res.headers.delete("set-cookie"); + for (const cookie of cookies) { + _res.headers.append("set-cookie", cookie); } + } else { + _res.headers.set(k, v2); } - }, - messages: { - "binary.base": "{{#label}} must be a buffer or a string", - "binary.length": "{{#label}} must be {{#limit}} bytes", - "binary.max": "{{#label}} must be less than or equal to {{#limit}} bytes", - "binary.min": "{{#label}} must be at least {{#limit}} bytes" } - }); + } + this.#res = _res; + this.finalized = true; } -}); -var require_lib39 = __commonJS({ - "node_modules/.deno/joi@18.0.1/node_modules/joi/lib/index.js"(exports2, module14) { - "use strict"; - var { assert: assert2, clone: clone2 } = require_lib(); - var Cache = require_cache2(); - var Common = require_common3(); - var Compile = require_compile2(); - var Errors = require_errors3(); - var Extend = require_extend2(); - var Manifest = require_manifest(); - var Ref = require_ref2(); - var Template = require_template2(); - var Trace = require_trace(); - var Schemas; - var internals = { - types: { - alternatives: require_alternatives2(), - any: require_any2(), - array: require_array2(), - boolean: require_boolean2(), - date: require_date2(), - function: require_function2(), - link: require_link2(), - number: require_number2(), - object: require_object2(), - string: require_string2(), - symbol: require_symbol2() - }, - aliases: { - alt: "alternatives", - bool: "boolean", - func: "function" - } - }; - if (Buffer) { - internals.types.binary = require_binary2(); - } - internals.root = function() { - const root = { - _types: new Set(Object.keys(internals.types)) - }; - for (const type of root._types) { - root[type] = function(...args) { - assert2(!args.length || ["alternatives", "link", "object"].includes(type), "The", type, "type does not allow arguments"); - return internals.generate(this, internals.types[type], args); - }; - } - for (const method of ["allow", "custom", "disallow", "equal", "exist", "forbidden", "invalid", "not", "only", "optional", "options", "prefs", "preferences", "required", "strip", "valid", "when"]) { - root[method] = function(...args) { - return this.any()[method](...args); - }; - } - Object.assign(root, internals.methods); - for (const alias in internals.aliases) { - const target = internals.aliases[alias]; - root[alias] = root[target]; - } - root.x = root.expression; - if (Trace.setup) { - Trace.setup(root); - } - return root; - }; - internals.methods = { - ValidationError: Errors.ValidationError, - version: Common.version, - cache: Cache.provider, - assert(value, schema, ...args) { - internals.assert(value, schema, true, args); - }, - attempt(value, schema, ...args) { - return internals.assert(value, schema, false, args); - }, - build(desc) { - assert2(typeof Manifest.build === "function", "Manifest functionality disabled"); - return Manifest.build(this, desc); - }, - checkPreferences(prefs) { - Common.checkPreferences(prefs); - }, - compile(schema, options2) { - return Compile.compile(this, schema, options2); - }, - defaults(modifier) { - assert2(typeof modifier === "function", "modifier must be a function"); - const joi = Object.assign({}, this); - for (const type of joi._types) { - const schema = modifier(joi[type]()); - assert2(Common.isSchema(schema), "modifier must return a valid schema object"); - joi[type] = function(...args) { - return internals.generate(this, schema, args); - }; + /** + * `.render()` can create a response within a layout. + * + * @see {@link https://hono.dev/docs/api/context#render-setrenderer} + * + * @example + * ```ts + * app.get('/', (c) => { + * return c.render('Hello!') + * }) + * ``` + */ + render = (...args) => { + this.#renderer ??= (content) => this.html(content); + return this.#renderer(...args); + }; + /** + * Sets the layout for the response. + * + * @param layout - The layout to set. + * @returns The layout function. + */ + setLayout = (layout) => this.#layout = layout; + /** + * Gets the current layout for the response. + * + * @returns The current layout function. + */ + getLayout = () => this.#layout; + /** + * `.setRenderer()` can set the layout in the custom middleware. + * + * @see {@link https://hono.dev/docs/api/context#render-setrenderer} + * + * @example + * ```tsx + * app.use('*', async (c, next) => { + * c.setRenderer((content) => { + * return c.html( + * + * + *

{content}

+ * + * + * ) + * }) + * await next() + * }) + * ``` + */ + setRenderer = (renderer) => { + this.#renderer = renderer; + }; + /** + * `.header()` can set headers. + * + * @see {@link https://hono.dev/docs/api/context#header} + * + * @example + * ```ts + * app.get('/welcome', (c) => { + * // Set headers + * c.header('X-Message', 'Hello!') + * c.header('Content-Type', 'text/plain') + * + * return c.body('Thank you for coming') + * }) + * ``` + */ + header = (name, value, options2) => { + if (this.finalized) { + this.#res = createResponseInstance(this.#res.body, this.#res); + } + const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers(); + if (value === void 0) { + headers.delete(name); + } else if (options2?.append) { + headers.append(name, value); + } else { + headers.set(name, value); + } + }; + status = (status) => { + this.#status = status; + }; + /** + * `.set()` can set the value specified by the key. + * + * @see {@link https://hono.dev/docs/api/context#set-get} + * + * @example + * ```ts + * app.use('*', async (c, next) => { + * c.set('message', 'Hono is hot!!') + * await next() + * }) + * ``` + */ + set = (key, value) => { + this.#var ??= /* @__PURE__ */ new Map(); + this.#var.set(key, value); + }; + /** + * `.get()` can use the value specified by the key. + * + * @see {@link https://hono.dev/docs/api/context#set-get} + * + * @example + * ```ts + * app.get('/', (c) => { + * const message = c.get('message') + * return c.text(`The message is "${message}"`) + * }) + * ``` + */ + get = (key) => { + return this.#var ? this.#var.get(key) : void 0; + }; + /** + * `.var` can access the value of a variable. + * + * @see {@link https://hono.dev/docs/api/context#var} + * + * @example + * ```ts + * const result = c.var.client.oneMethod() + * ``` + */ + // c.var.propName is a read-only + get var() { + if (!this.#var) { + return {}; + } + return Object.fromEntries(this.#var); + } + #newResponse(data, arg, headers) { + const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers(); + if (typeof arg === "object" && "headers" in arg) { + const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers); + for (const [key, value] of argHeaders) { + if (key.toLowerCase() === "set-cookie") { + responseHeaders.append(key, value); + } else { + responseHeaders.set(key, value); } - return joi; - }, - expression(...args) { - return new Template(...args); - }, - extend(...extensions) { - Common.verifyFlat(extensions, "extend"); - Schemas = Schemas || require_schemas2(); - assert2(extensions.length, "You need to provide at least one extension"); - this.assert(extensions, Schemas.extensions); - const joi = Object.assign({}, this); - joi._types = new Set(joi._types); - for (let extension of extensions) { - if (typeof extension === "function") { - extension = extension(joi); - } - this.assert(extension, Schemas.extension); - const expanded = internals.expandExtension(extension, joi); - for (const item of expanded) { - assert2(joi[item.type] === void 0 || joi._types.has(item.type), "Cannot override name", item.type); - const base2 = item.base || this.any(); - const schema = Extend.type(base2, item); - joi._types.add(item.type); - joi[item.type] = function(...args) { - return internals.generate(this, schema, args); - }; + } + } + if (headers) { + for (const [k, v2] of Object.entries(headers)) { + if (typeof v2 === "string") { + responseHeaders.set(k, v2); + } else { + responseHeaders.delete(k); + for (const v22 of v2) { + responseHeaders.append(k, v22); } } - return joi; - }, - isError: Errors.ValidationError.isError, - isExpression: Template.isTemplate, - isRef: Ref.isRef, - isSchema: Common.isSchema, - in(...args) { - return Ref.in(...args); - }, - override: Common.symbols.override, - ref(...args) { - return Ref.create(...args); - }, - types() { - const types = {}; - for (const type of this._types) { - types[type] = this[type](); + } + } + const status = typeof arg === "number" ? arg : arg?.status ?? this.#status; + return createResponseInstance(data, { status, headers: responseHeaders }); + } + newResponse = (...args) => this.#newResponse(...args); + /** + * `.body()` can return the HTTP response. + * You can set headers with `.header()` and set HTTP status code with `.status`. + * This can also be set in `.text()`, `.json()` and so on. + * + * @see {@link https://hono.dev/docs/api/context#body} + * + * @example + * ```ts + * app.get('/welcome', (c) => { + * // Set headers + * c.header('X-Message', 'Hello!') + * c.header('Content-Type', 'text/plain') + * // Set HTTP status code + * c.status(201) + * + * // Return the response body + * return c.body('Thank you for coming') + * }) + * ``` + */ + body = (data, arg, headers) => this.#newResponse(data, arg, headers); + /** + * `.text()` can render text as `Content-Type:text/plain`. + * + * @see {@link https://hono.dev/docs/api/context#text} + * + * @example + * ```ts + * app.get('/say', (c) => { + * return c.text('Hello!') + * }) + * ``` + */ + text = (text, arg, headers) => { + return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse( + text, + arg, + setDefaultContentType(TEXT_PLAIN, headers) + ); + }; + /** + * `.json()` can render JSON as `Content-Type:application/json`. + * + * @see {@link https://hono.dev/docs/api/context#json} + * + * @example + * ```ts + * app.get('/api', (c) => { + * return c.json({ message: 'Hello!' }) + * }) + * ``` + */ + json = (object2, arg, headers) => { + return this.#newResponse( + JSON.stringify(object2), + arg, + setDefaultContentType("application/json", headers) + ); + }; + html = (html2, arg, headers) => { + const res = (html22) => this.#newResponse(html22, arg, setDefaultContentType("text/html; charset=UTF-8", headers)); + return typeof html2 === "object" ? resolveCallback(html2, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html2); + }; + /** + * `.redirect()` can Redirect, default status code is 302. + * + * @see {@link https://hono.dev/docs/api/context#redirect} + * + * @example + * ```ts + * app.get('/redirect', (c) => { + * return c.redirect('/') + * }) + * app.get('/redirect-permanently', (c) => { + * return c.redirect('/', 301) + * }) + * ``` + */ + redirect = (location, status) => { + const locationString = String(location); + this.header( + "Location", + // Multibyes should be encoded + // eslint-disable-next-line no-control-regex + !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString) + ); + return this.newResponse(null, status ?? 302); + }; + /** + * `.notFound()` can return the Not Found Response. + * + * @see {@link https://hono.dev/docs/api/context#notfound} + * + * @example + * ```ts + * app.get('/notfound', (c) => { + * return c.notFound() + * }) + * ``` + */ + notFound = () => { + this.#notFoundHandler ??= () => createResponseInstance(); + return this.#notFoundHandler(this); + }; +}; +var METHOD_NAME_ALL = "ALL"; +var METHOD_NAME_ALL_LOWERCASE = "all"; +var METHODS = ["get", "post", "put", "delete", "options", "patch"]; +var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built."; +var UnsupportedPathError = class extends Error { +}; +var COMPOSED_HANDLER = "__COMPOSED_HANDLER"; +var notFoundHandler = (c) => { + return c.text("404 Not Found", 404); +}; +var errorHandler = (err, c) => { + if ("getResponse" in err) { + const res = err.getResponse(); + return c.newResponse(res.body, res); + } + console.error(err); + return c.text("Internal Server Error", 500); +}; +var Hono = class _Hono { + get; + post; + put; + delete; + options; + patch; + all; + on; + use; + /* + This class is like an abstract class and does not have a router. + To use it, inherit the class and implement router in the constructor. + */ + router; + getPath; + // Cannot use `#` because it requires visibility at JavaScript runtime. + _basePath = "/"; + #path = "/"; + routes = []; + constructor(options2 = {}) { + const allMethods = [...METHODS, METHOD_NAME_ALL_LOWERCASE]; + allMethods.forEach((method) => { + this[method] = (args1, ...args) => { + if (typeof args1 === "string") { + this.#path = args1; + } else { + this.#addRoute(method, this.#path, args1); } - for (const target in internals.aliases) { - types[target] = this[target](); + args.forEach((handler) => { + this.#addRoute(method, this.#path, handler); + }); + return this; + }; + }); + this.on = (method, path8, ...handlers) => { + for (const p of [path8].flat()) { + this.#path = p; + for (const m3 of [method].flat()) { + handlers.map((handler) => { + this.#addRoute(m3.toUpperCase(), this.#path, handler); + }); } - return types; - } - }; - internals.assert = function(value, schema, annotate, args) { - const message = args[0] instanceof Error || typeof args[0] === "string" ? args[0] : null; - const options2 = message !== null ? args[1] : args[0]; - const result = schema.validate(value, Common.preferences({ errors: { stack: true } }, options2 || {})); - let error2 = result.error; - if (!error2) { - return result.value; - } - if (message instanceof Error) { - throw message; - } - const display = annotate && typeof error2.annotate === "function" ? error2.annotate() : error2.message; - if (error2 instanceof Errors.ValidationError === false) { - error2 = clone2(error2); } - error2.message = message ? `${message} ${display}` : display; - throw error2; - }; - internals.generate = function(root, schema, args) { - assert2(root, "Must be invoked on a Joi instance."); - schema.$_root = root; - if (!schema._definition.args || !args.length) { - return schema; - } - return schema._definition.args(schema, ...args); + return this; }; - internals.expandExtension = function(extension, joi) { - if (typeof extension.type === "string") { - return [extension]; - } - const extended = []; - for (const type of joi._types) { - if (extension.type.test(type)) { - const item = Object.assign({}, extension); - item.type = type; - item.base = joi[type](); - extended.push(item); - } + this.use = (arg1, ...handlers) => { + if (typeof arg1 === "string") { + this.#path = arg1; + } else { + this.#path = "*"; + handlers.unshift(arg1); } - return extended; + handlers.forEach((handler) => { + this.#addRoute(METHOD_NAME_ALL, this.#path, handler); + }); + return this; }; - module14.exports = internals.root(); + const { strict, ...optionsWithoutStrict } = options2; + Object.assign(this, optionsWithoutStrict); + this.getPath = strict ?? true ? options2.getPath ?? getPath : getPathNoStrict; } -}); -var routes_exports = {}; -function notFoundNoCache(h2) { - return h2.response().code(404).header("Cache-Control", "no-store"); -} -var import_boom3; -var import_npm_bottleneck; -var import_npm_chalk2; -var import_npm_joi; -var import_npm_nconf5; -var MEGABYTE; -var SECOND; -var CID_REGEX; -var KV_KEY_REGEX; -var NAME_REGEX; -var POSITIVE_INTEGER_REGEX; -var FILE_UPLOAD_MAX_BYTES; -var SIGNUP_LIMIT_MIN; -var SIGNUP_LIMIT_HOUR; -var SIGNUP_LIMIT_DAY; -var SIGNUP_LIMIT_DISABLED; -var ARCHIVE_MODE; -var limiterPerMinute; -var limiterPerHour; -var limiterPerDay; -var cidLookupTable; -var limiterKey; -var ctEq; -var isCheloniaDashboard; -var appDir; -var dashboardDir; -var staticServeConfig; -var errorMapper; -var route; -var init_routes = __esm({ - "src/serve/routes.ts"() { - "use strict"; - init_SPMessage(); - init_chelonia(); - init_functions(); - init_persistent_actions(); - import_boom3 = __toESM(require_lib2()); - init_esm(); - import_npm_bottleneck = __toESM(require_lib36()); - import_npm_chalk2 = __toESM(require_source()); - import_npm_joi = __toESM(require_lib39()); - init_database(); - init_instance_keys(); - init_logger(); - init_zkppSalt(); - import_npm_nconf5 = __toESM(require_nconf()); - MEGABYTE = 1048576; - SECOND = 1e3; - CID_REGEX = /^z[1-9A-HJ-NP-Za-km-z]{8,72}$/; - KV_KEY_REGEX = /^(?!_private)[^\x00]{1,256}$/; - NAME_REGEX = /^(?![_-])((?!([_-])\2)[a-z\d_-]){1,80}(? c.text("user")) + * app.route("/api", app2) // GET /api/user + * ``` + */ + route(path8, app) { + const subApp = this.basePath(path8); + app.routes.map((r) => { + let handler; + if (app.errorHandler === errorHandler) { + handler = r.handler; + } else { + handler = async (c, next) => (await compose([], app.errorHandler)(c, () => r.handler(c, next))).res; + handler[COMPOSED_HANDLER] = r.handler; } + subApp.#addRoute(r.method, r.path, handler); }); - cidLookupTable = { - [multicodes.SHELTER_CONTRACT_MANIFEST]: "application/vnd.shelter.contractmanifest+json", - [multicodes.SHELTER_CONTRACT_TEXT]: "application/vnd.shelter.contracttext", - [multicodes.SHELTER_CONTRACT_DATA]: "application/vnd.shelter.contractdata+json", - [multicodes.SHELTER_FILE_MANIFEST]: "application/vnd.shelter.filemanifest+json", - [multicodes.SHELTER_FILE_CHUNK]: "application/vnd.shelter.filechunk+octet-stream" - }; - limiterKey = (ip) => { - const ipVersion = isIP(ip); - if (ipVersion === 4) { - return ip; - } else if (ipVersion === 6) { - const [address, zoneIdx] = ip.split("%"); - const segments = address.split(":"); - let isCompressed = false; - for (let i2 = 0; i2 < segments.length - 1; i2++) { - if (!isCompressed && segments[i2] === "") { - const requiredSegments = 8 - (segments.length - 1); - if (requiredSegments < 0) { - throw new Error("Invalid IPv6 address: too many segments"); - } - if ((i2 === 0 || i2 === segments.length - 2) && segments[i2 + 1] === "") { - segments[i2 + 1] = "0"; - } - if (i2 === 0 && segments.length === 3 && segments[i2 + 2] === "") { - segments[i2 + 2] = "0"; - } - segments.splice(i2, 1, ...new Array(requiredSegments).fill("0")); - isCompressed = true; - continue; - } - segments[i2] = segments[i2].replace(/^0+/, "0"); - } - if (segments.length === 8 && isIP(segments[7]) === 4) { - return segments[7]; - } else if (segments.length === 8) { - if (zoneIdx) { - segments[7] = segments[7].replace(/^0+/, "0"); - return segments.join(":").toLowerCase() + "%" + zoneIdx; - } else { - return segments.slice(0, 4).join(":").toLowerCase() + "::"; - } + return this; + } + /** + * `.basePath()` allows base paths to be specified. + * + * @see {@link https://hono.dev/docs/api/routing#base-path} + * + * @param {string} path - base Path + * @returns {Hono} changed Hono instance + * + * @example + * ```ts + * const api = new Hono().basePath('/api') + * ``` + */ + basePath(path8) { + const subApp = this.#clone(); + subApp._basePath = mergePath(this._basePath, path8); + return subApp; + } + /** + * `.onError()` handles an error and returns a customized Response. + * + * @see {@link https://hono.dev/docs/api/hono#error-handling} + * + * @param {ErrorHandler} handler - request Handler for error + * @returns {Hono} changed Hono instance + * + * @example + * ```ts + * app.onError((err, c) => { + * console.error(`${err}`) + * return c.text('Custom Error Message', 500) + * }) + * ``` + */ + onError = (handler) => { + this.errorHandler = handler; + return this; + }; + /** + * `.notFound()` allows you to customize a Not Found Response. + * + * @see {@link https://hono.dev/docs/api/hono#not-found} + * + * @param {NotFoundHandler} handler - request handler for not-found + * @returns {Hono} changed Hono instance + * + * @example + * ```ts + * app.notFound((c) => { + * return c.text('Custom 404 Message', 404) + * }) + * ``` + */ + notFound = (handler) => { + this.#notFoundHandler = handler; + return this; + }; + /** + * `.mount()` allows you to mount applications built with other frameworks into your Hono application. + * + * @see {@link https://hono.dev/docs/api/hono#mount} + * + * @param {string} path - base Path + * @param {Function} applicationHandler - other Request Handler + * @param {MountOptions} [options] - options of `.mount()` + * @returns {Hono} mounted Hono instance + * + * @example + * ```ts + * import { Router as IttyRouter } from 'itty-router' + * import { Hono } from 'hono' + * // Create itty-router application + * const ittyRouter = IttyRouter() + * // GET /itty-router/hello + * ittyRouter.get('/hello', () => new Response('Hello from itty-router')) + * + * const app = new Hono() + * app.mount('/itty-router', ittyRouter.handle) + * ``` + * + * @example + * ```ts + * const app = new Hono() + * // Send the request to another application without modification. + * app.mount('/app', anotherApp, { + * replaceRequest: (req) => req, + * }) + * ``` + */ + mount(path8, applicationHandler, options2) { + let replaceRequest; + let optionHandler; + if (options2) { + if (typeof options2 === "function") { + optionHandler = options2; + } else { + optionHandler = options2.optionHandler; + if (options2.replaceRequest === false) { + replaceRequest = (request) => request; } else { - throw new Error("Invalid IPv6 address"); - } - } - throw new Error("Invalid address format"); - }; - ctEq = (expected, actual) => { - let r = actual.length ^ expected.length; - for (let i2 = 0; i2 < actual.length; i2++) { - r |= actual.codePointAt(i2) ^ expected.codePointAt(i2); - } - return r === 0; - }; - isCheloniaDashboard = process9.env.IS_CHELONIA_DASHBOARD_DEV; - appDir = import_npm_nconf5.default.get("server:appDir") || "."; - dashboardDir = import.meta.dirname || "./build/dist-dashboard"; - staticServeConfig = { - routePath: isCheloniaDashboard ? "/dashboard/{path*}" : "/app/{path*}", - distAssets: path6.resolve(path6.join(isCheloniaDashboard ? dashboardDir : appDir, "assets")), - distIndexHtml: path6.resolve(path6.join(isCheloniaDashboard ? dashboardDir : appDir, "index.html")), - redirect: isCheloniaDashboard ? "/dashboard/" : "/app/" - }; - errorMapper = (e2) => { - switch (e2?.name) { - case "BackendErrorNotFound": - return import_boom3.default.notFound(); - case "BackendErrorGone": - return import_boom3.default.resourceGone(); - case "BackendErrorBadData": - return import_boom3.default.badData(e2.message); - default: - console.error(e2, "Unexpected backend error"); - return import_boom3.default.internal(e2.message ?? "internal error"); - } - }; - route = new Proxy({}, { - get: function(_obj, prop) { - return function(path8, options2, handler) { - esm_default("okTurtles.data/apply", SERVER_INSTANCE, function(server) { - server.route({ path: path8, method: prop, options: options2, handler }); - }); - }; - } - }); - route.POST("/event", { - auth: { - strategy: "chel-shelter", - mode: "optional" - }, - validate: { - headers: import_npm_joi.default.object({ - "shelter-namespace-registration": import_npm_joi.default.string().regex(NAME_REGEX) - }), - options: { - allowUnknown: true - }, - payload: import_npm_joi.default.string().required() - } - }, async function(request) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - const ip = request.headers["x-real-ip"] || request.info.remoteAddress; - try { - const deserializedHEAD = SPMessage.deserializeHEAD(request.payload); - try { - const parsed = maybeParseCID(deserializedHEAD.head.manifest); - if (parsed?.code !== multicodes.SHELTER_CONTRACT_MANIFEST) { - return import_boom3.default.badData("Invalid manifest"); - } - const credentials = request.auth.credentials; - if (!credentials?.billableContractID && deserializedHEAD.isFirstMessage) { - const manifest2 = await esm_default("chelonia.db/get", deserializedHEAD.head.manifest); - const parsedManifest = JSON.parse(manifest2); - const { name } = JSON.parse(parsedManifest.body); - if (name !== "gi.contracts/identity") { - return import_boom3.default.unauthorized("This contract type requires ownership information", "shelter"); - } - if (import_npm_nconf5.default.get("server:signup:disabled")) { - return import_boom3.default.forbidden("Registration disabled"); - } - if (!SIGNUP_LIMIT_DISABLED) { - try { - const keyedIp = limiterKey(ip); - await limiterPerMinute.key(keyedIp).schedule(() => Promise.resolve()); - await limiterPerHour.key(keyedIp).schedule(() => Promise.resolve()); - await limiterPerDay.key(keyedIp).schedule(() => Promise.resolve()); - } catch { - console.warn("rate limit hit for IP:", ip); - throw import_boom3.default.tooManyRequests("Rate limit exceeded"); - } - } - } - const saltUpdateToken = request.headers["shelter-salt-update-token"]; - let updateSalts; - if (saltUpdateToken) { - updateSalts = await redeemSaltUpdateToken(deserializedHEAD.contractID, saltUpdateToken); - } - await esm_default("backend/server/handleEntry", deserializedHEAD, request.payload); - await updateSalts?.(deserializedHEAD.hash); - if (deserializedHEAD.isFirstMessage) { - if (credentials?.billableContractID) { - await esm_default("backend/server/saveOwner", credentials.billableContractID, deserializedHEAD.contractID); - } else { - await esm_default("backend/server/registerBillableEntity", deserializedHEAD.contractID); - } - const name = request.headers["shelter-namespace-registration"]; - if (name) { - const cheloniaState = esm_default("chelonia/rootState"); - if (cheloniaState.contracts[deserializedHEAD.contractID]?.type === "gi.contracts/identity") { - const r = await esm_default("backend/db/registerName", name, deserializedHEAD.contractID); - if (import_boom3.default.isBoom(r)) { - return r; - } - const saltRegistrationToken = request.headers["shelter-salt-registration-token"]; - console.info(`new user: ${name}=${deserializedHEAD.contractID} (${ip})`); - if (saltRegistrationToken) { - await redeemSaltRegistrationToken(name, deserializedHEAD.contractID, saltRegistrationToken); - } - } - } - const deletionTokenDgst = request.headers["shelter-deletion-token-digest"]; - if (deletionTokenDgst) { - await esm_default("chelonia.db/set", `_private_deletionTokenDgst_${deserializedHEAD.contractID}`, deletionTokenDgst); - } - } - await esm_default("backend/server/updateSize", deserializedHEAD.contractID, Buffer15.byteLength(request.payload), deserializedHEAD.isFirstMessage && !credentials?.billableContractID ? deserializedHEAD.contractID : void 0); - } catch (err) { - console.error(err, import_npm_chalk2.default.bold.yellow(err.name)); - if (err.name === "ChelErrorDBBadPreviousHEAD" || err.name === "ChelErrorAlreadyProcessed") { - const HEADinfo = await esm_default("chelonia/db/latestHEADinfo", deserializedHEAD.contractID) ?? { HEAD: null, height: 0 }; - const r = import_boom3.default.conflict(err.message, { HEADinfo }); - Object.assign(r.output.headers, { - "shelter-headinfo-head": HEADinfo.HEAD, - "shelter-headinfo-height": HEADinfo.height - }); - return r; - } else if (err.name === "ChelErrorSignatureError") { - return import_boom3.default.badData("Invalid signature"); - } else if (err.name === "ChelErrorSignatureKeyUnauthorized") { - return import_boom3.default.forbidden("Unauthorized signing key"); - } - throw err; + replaceRequest = options2.replaceRequest; } - return deserializedHEAD.hash; - } catch (err) { - err.ip = ip; - logger_default.error(err, "POST /event", err.message); - return err; - } - }); - route.GET("/eventsAfter/{contractID}/{since}/{limit?}", { - validate: { - params: import_npm_joi.default.object({ - contractID: import_npm_joi.default.string().regex(CID_REGEX).required(), - since: import_npm_joi.default.string().regex(POSITIVE_INTEGER_REGEX).required(), - limit: import_npm_joi.default.string().regex(POSITIVE_INTEGER_REGEX) - }), - query: import_npm_joi.default.object({ - keyOps: import_npm_joi.default.boolean() - }) } - }, async function(request) { - const { contractID, since, limit } = request.params; - const ip = request.headers["x-real-ip"] || request.info.remoteAddress; + } + const getOptions = optionHandler ? (c) => { + const options22 = optionHandler(c); + return Array.isArray(options22) ? options22 : [options22]; + } : (c) => { + let executionContext = void 0; try { - const parsed = maybeParseCID(contractID); - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { - return import_boom3.default.badRequest(); - } - const stream = await esm_default("backend/db/streamEntriesAfter", contractID, Number(since), limit == null ? void 0 : Number(limit), { keyOps: !!request.query["keyOps"] }); - request.events.once("disconnect", stream.destroy.bind(stream)); - return stream; - } catch (err) { - err.ip = ip; - logger_default.error(err, `GET /eventsAfter/${contractID}/${since}`, err.message); - return err; - } - }); - route.GET("/ownResources", { - auth: { - strategies: ["chel-shelter"], - mode: "required" + executionContext = c.executionCtx; + } catch { } - }, async function(request) { - const billableContractID = request.auth.credentials.billableContractID; - const resources = (await esm_default("chelonia.db/get", `_private_resources_${billableContractID}`))?.split("\0"); - return resources || []; - }); - if (process9.env.NODE_ENV === "development") { - const levelToColor = { - error: import_npm_chalk2.default.bold.red, - warn: import_npm_chalk2.default.yellow, - log: import_npm_chalk2.default.green, - info: import_npm_chalk2.default.green, - debug: import_npm_chalk2.default.blue + return [c.env, executionContext]; + }; + replaceRequest ||= (() => { + const mergedPath = mergePath(this._basePath, path8); + const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length; + return (request) => { + const url2 = new URL(request.url); + url2.pathname = url2.pathname.slice(pathPrefixLength) || "/"; + return new Request(url2, request); }; - route.POST("/log", { - validate: { - payload: import_npm_joi.default.object({ - level: import_npm_joi.default.string().required(), - value: import_npm_joi.default.string().required() - }) - } - }, function(request, h2) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - const ip = request.headers["x-real-ip"] || request.info.remoteAddress; - const log2 = levelToColor[request.payload.level]; - console.debug(import_npm_chalk2.default.bold.yellow(`REMOTE LOG (${ip}): `) + log2(`[${request.payload.level}] ${request.payload.value}`)); - return h2.response().code(200); - }); - } - route.GET("/name/{name}", { - validate: { - params: import_npm_joi.default.object({ - name: import_npm_joi.default.string().regex(NAME_REGEX).required() - }) + })(); + const handler = async (c, next) => { + const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c)); + if (res) { + return res; } - }, async function(request, h2) { - const { name } = request.params; + await next(); + }; + this.#addRoute(METHOD_NAME_ALL, mergePath(path8, "*"), handler); + return this; + } + #addRoute(method, path8, handler) { + method = method.toUpperCase(); + path8 = mergePath(this._basePath, path8); + const r = { basePath: this._basePath, path: path8, method, handler }; + this.router.add(method, path8, [handler, r]); + this.routes.push(r); + } + #handleError(err, c) { + if (err instanceof Error) { + return this.errorHandler(err, c); + } + throw err; + } + #dispatch(request, executionCtx, env2, method) { + if (method === "HEAD") { + return (async () => new Response(null, await this.#dispatch(request, executionCtx, env2, "GET")))(); + } + const path8 = this.getPath(request, { env: env2 }); + const matchResult = this.router.match(method, path8); + const c = new Context(request, { + path: path8, + matchResult, + env: env2, + executionCtx, + notFoundHandler: this.#notFoundHandler + }); + if (matchResult[0].length === 1) { + let res; try { - const lookupResult = await esm_default("backend/db/lookupName", name); - return lookupResult ? h2.response(lookupResult).type("text/plain") : notFoundNoCache(h2); + res = matchResult[0][0][0][0](c, async () => { + c.res = await this.#notFoundHandler(c); + }); } catch (err) { - logger_default.error(err, `GET /name/${name}`, err.message); - return err; + return this.#handleError(err, c); } - }); - route.GET("/latestHEADinfo/{contractID}", { - cache: { otherwise: "no-store" }, - validate: { - params: import_npm_joi.default.object({ - contractID: import_npm_joi.default.string().regex(CID_REGEX).required() - }) - } - }, async function(request, h2) { - const { contractID } = request.params; + return res instanceof Promise ? res.then( + (resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c)) + ).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c); + } + const composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler); + return (async () => { try { - const parsed = maybeParseCID(contractID); - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) return import_boom3.default.badRequest(); - const HEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); - if (HEADinfo === "") { - return import_boom3.default.resourceGone(); - } - if (!HEADinfo) { - console.warn(`[backend] latestHEADinfo not found for ${contractID}`); - return notFoundNoCache(h2); + const context = await composed(c); + if (!context.finalized) { + throw new Error( + "Context is not finalized. Did you forget to return a Response object or `await next()`?" + ); } - return HEADinfo; + return context.res; } catch (err) { - logger_default.error(err, `GET /latestHEADinfo/${contractID}`, err.message); - return err; + return this.#handleError(err, c); } + })(); + } + /** + * `.fetch()` will be entry point of your app. + * + * @see {@link https://hono.dev/docs/api/hono#fetch} + * + * @param {Request} request - request Object of request + * @param {Env} Env - env Object + * @param {ExecutionContext} - context of execution + * @returns {Response | Promise} response of request + * + */ + fetch = (request, ...rest) => { + return this.#dispatch(request, rest[1], rest[0], request.method); + }; + /** + * `.request()` is a useful method for testing. + * You can pass a URL or pathname to send a GET request. + * app will return a Response object. + * ```ts + * test('GET /hello is ok', async () => { + * const res = await app.request('/hello') + * expect(res.status).toBe(200) + * }) + * ``` + * @see https://hono.dev/docs/api/hono#request + */ + request = (input, requestInit, Env, executionCtx) => { + if (input instanceof Request) { + return this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx); + } + input = input.toString(); + return this.fetch( + new Request( + /^https?:\/\//.test(input) ? input : `http://localhost${mergePath("/", input)}`, + requestInit + ), + Env, + executionCtx + ); + }; + /** + * `.fire()` automatically adds a global fetch event listener. + * This can be useful for environments that adhere to the Service Worker API, such as non-ES module Cloudflare Workers. + * @deprecated + * Use `fire` from `hono/service-worker` instead. + * ```ts + * import { Hono } from 'hono' + * import { fire } from 'hono/service-worker' + * + * const app = new Hono() + * // ... + * fire(app) + * ``` + * @see https://hono.dev/docs/api/hono#fire + * @see https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API + * @see https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/ + */ + fire = () => { + addEventListener("fetch", (event) => { + event.respondWith(this.#dispatch(event.request, event, void 0, event.request.method)); }); - route.GET("/time", {}, function(_request, h2) { - return h2.response((/* @__PURE__ */ new Date()).toISOString()).header("cache-control", "no-store").type("text/plain"); - }); - route.POST( - "/streams-test", - { - payload: { - parse: false - } - }, - function(request, h2) { - if (request.payload.byteLength === 2 && Buffer15.from(request.payload).toString() === "ok") { - return h2.response().code(204); - } else { - return import_boom3.default.badRequest(); - } + }; +}; +var emptyParam = []; +function match(method, path8) { + const matchers = this.buildAllMatchers(); + const match2 = (method2, path22) => { + const matcher = matchers[method2] || matchers[METHOD_NAME_ALL]; + const staticMatch = matcher[2][path22]; + if (staticMatch) { + return staticMatch; + } + const match3 = path22.match(matcher[0]); + if (!match3) { + return [[], emptyParam]; + } + const index = match3.indexOf("", 1); + return [matcher[1][index], match3]; + }; + this.match = match2; + return match2(method, path8); +} +var LABEL_REG_EXP_STR = "[^/]+"; +var ONLY_WILDCARD_REG_EXP_STR = ".*"; +var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)"; +var PATH_ERROR = /* @__PURE__ */ Symbol(); +var regExpMetaChars = new Set(".\\+*[^]$()"); +function compareKey(a, b) { + if (a.length === 1) { + return b.length === 1 ? a < b ? -1 : 1 : -1; + } + if (b.length === 1) { + return 1; + } + if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) { + return 1; + } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) { + return -1; + } + if (a === LABEL_REG_EXP_STR) { + return 1; + } else if (b === LABEL_REG_EXP_STR) { + return -1; + } + return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length; +} +var Node = class _Node { + #index; + #varIndex; + #children = /* @__PURE__ */ Object.create(null); + insert(tokens, index, paramMap, context, pathErrorCheckOnly) { + if (tokens.length === 0) { + if (this.#index !== void 0) { + throw PATH_ERROR; + } + if (pathErrorCheckOnly) { + return; } - ); - if (process9.env.NODE_ENV === "development") { - route.POST("/dev-file", { - payload: { - output: "data", - multipart: true, - allow: "multipart/form-data", - failAction: function(_request, _h, err) { - console.error("failAction error:", err); - return import_boom3.default.isBoom(err) ? err : import_boom3.default.boomify(err instanceof Error ? err : new Error(err)); - }, - maxBytes: 6 * MEGABYTE, - // TODO: make this a configurable setting - timeout: 10 * SECOND - // TODO: make this a configurable setting - } - }, async function(request) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - try { - console.log("FILE UPLOAD!"); - const { hash: hash3, data } = request.payload; - if (!hash3) return import_boom3.default.badRequest("missing hash"); - if (!data) return import_boom3.default.badRequest("missing data"); - const parsed = maybeParseCID(hash3); - if (!parsed) return import_boom3.default.badRequest("invalid hash"); - const ourHash = createCID(data, parsed.code); - if (ourHash !== hash3) { - console.error(`hash(${hash3}) != ourHash(${ourHash})`); - return import_boom3.default.badRequest("bad hash!"); - } - await esm_default("chelonia.db/set", hash3, data); - return "/file/" + hash3; - } catch (err) { - logger_default.error(err); - return import_boom3.default.internal("File upload failed"); - } - }); + this.#index = index; + return; } - route.POST("/file", { - auth: { - strategies: ["chel-shelter"], - mode: "required" - }, - payload: { - parse: true, - output: "stream", - multipart: { output: "annotated" }, - allow: "multipart/form-data", - failAction: function(_request, _h, err) { - console.error(err, "failAction error"); - return import_boom3.default.isBoom(err) ? err : import_boom3.default.boomify(err instanceof Error ? err : new Error(err)); - }, - maxBytes: FILE_UPLOAD_MAX_BYTES, - timeout: 10 * SECOND - // TODO: make this a configurable setting - } - }, async function(request, h2) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - try { - console.info("FILE UPLOAD!"); - const credentials = request.auth.credentials; - if (!credentials?.billableContractID) { - return import_boom3.default.unauthorized("Uploading files requires ownership information", "shelter"); - } - const manifestMeta = request.payload["manifest"]; - if (typeof manifestMeta !== "object") return import_boom3.default.badRequest("missing manifest"); - if (manifestMeta.filename !== "manifest.json") return import_boom3.default.badRequest("wrong manifest filename"); - if (!(manifestMeta.payload instanceof Uint8Array)) return import_boom3.default.badRequest("wrong manifest format"); - const manifest2 = (() => { - try { - return JSON.parse(Buffer15.from(manifestMeta.payload).toString()); - } catch { - throw import_boom3.default.badData("Error parsing manifest"); - } - })(); - if (typeof manifest2 !== "object") return import_boom3.default.badData("manifest format is invalid"); - if (manifest2.version !== "1.0.0") return import_boom3.default.badData("unsupported manifest version"); - if (manifest2.cipher !== "aes256gcm") return import_boom3.default.badData("unsupported cipher"); - if (!Array.isArray(manifest2.chunks) || !manifest2.chunks.length) return import_boom3.default.badData("missing chunks"); - let ourSize = 0; - const chunks = manifest2.chunks.map((chunk, i2) => { - if (!Array.isArray(chunk) || chunk.length !== 2 || typeof chunk[0] !== "number" || typeof chunk[1] !== "string" || !Number.isSafeInteger(chunk[0]) || chunk[0] <= 0) { - throw import_boom3.default.badData("bad chunk description"); - } - if (!request.payload[i2] || !(request.payload[i2].payload instanceof Uint8Array)) { - throw import_boom3.default.badRequest("chunk missing in submitted data"); - } - const ourHash = createCID(request.payload[i2].payload, multicodes.SHELTER_FILE_CHUNK); - if (request.payload[i2].payload.byteLength !== chunk[0]) { - throw import_boom3.default.badRequest("bad chunk size"); - } - if (ourHash !== chunk[1]) { - throw import_boom3.default.badRequest("bad chunk hash"); - } - ourSize += chunk[0]; - return [ourHash, request.payload[i2].payload]; - }); - if (ourSize !== manifest2.size) return import_boom3.default.badRequest("Mismatched total size"); - const manifestHash = createCID(manifestMeta.payload, multicodes.SHELTER_FILE_MANIFEST); - if (await esm_default("chelonia.db/get", manifestHash)) { - throw new Error(`Manifest ${manifestHash} already exists`); + const [token, ...restTokens] = tokens; + const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/); + let node; + if (pattern) { + const name = pattern[1]; + let regexpStr = pattern[2] || LABEL_REG_EXP_STR; + if (name && pattern[2]) { + if (regexpStr === ".*") { + throw PATH_ERROR; + } + regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:"); + if (/\((?!\?:)/.test(regexpStr)) { + throw PATH_ERROR; + } + } + node = this.#children[regexpStr]; + if (!node) { + if (Object.keys(this.#children).some( + (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR + )) { + throw PATH_ERROR; + } + if (pathErrorCheckOnly) { + return; } - await Promise.all(chunks.map(async ([cid]) => { - const exists = !!await esm_default("chelonia.db/get", cid); - if (exists) { - throw new Error(`Chunk ${cid} already exists`); - } - })); - await Promise.all(chunks.map(([cid, data]) => esm_default("chelonia.db/set", cid, data))); - await esm_default("chelonia.db/set", manifestHash, manifestMeta.payload); - await esm_default("backend/server/saveOwner", credentials.billableContractID, manifestHash); - const size = manifest2.size + manifestMeta.payload.byteLength; - await esm_default("backend/server/updateSize", manifestHash, size); - await esm_default("backend/server/updateContractFilesTotalSize", credentials.billableContractID, size); - const deletionTokenDgst = request.headers["shelter-deletion-token-digest"]; - if (deletionTokenDgst) { - await esm_default("chelonia.db/set", `_private_deletionTokenDgst_${manifestHash}`, deletionTokenDgst); + node = this.#children[regexpStr] = new _Node(); + if (name !== "") { + node.#varIndex = context.varIndex++; } - return h2.response(manifestHash); - } catch (err) { - logger_default.error(err, "POST /file", err.message); - return err; } - }); - route.GET("/file/{hash}", { - validate: { - params: import_npm_joi.default.object({ - hash: import_npm_joi.default.string().regex(CID_REGEX).required() - }) - } - }, async function(request, h2) { - const { hash: hash3 } = request.params; - const parsed = maybeParseCID(hash3); - if (!parsed) { - return import_boom3.default.badRequest(); + if (!pathErrorCheckOnly && name !== "") { + paramMap.push([name, node.#varIndex]); } - const blobOrString = await esm_default("chelonia.db/get", `any:${hash3}`); - if (blobOrString?.length === 0) { - return import_boom3.default.resourceGone(); - } else if (!blobOrString) { - return notFoundNoCache(h2); + } else { + node = this.#children[token]; + if (!node) { + if (Object.keys(this.#children).some( + (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR + )) { + throw PATH_ERROR; + } + if (pathErrorCheckOnly) { + return; + } + node = this.#children[token] = new _Node(); } - const type = cidLookupTable[parsed.code] || "application/octet-stream"; - return h2.response(blobOrString).etag(hash3).header("Cache-Control", "public,max-age=31536000,immutable").header("content-security-policy", "default-src 'none'; frame-ancestors 'none'; form-action 'none'; upgrade-insecure-requests; sandbox").header("x-content-type-options", "nosniff").type(type); + } + node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly); + } + buildRegExpStr() { + const childKeys = Object.keys(this.#children).sort(compareKey); + const strList = childKeys.map((k) => { + const c = this.#children[k]; + return (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr(); }); - route.POST("/deleteFile/{hash}", { - auth: { - // Allow file deletion, and allow either the bearer of the deletion token or - // the file owner to delete it - strategies: ["chel-shelter", "chel-bearer"], - mode: "required" - }, - validate: { - params: import_npm_joi.default.object({ - hash: import_npm_joi.default.string().regex(CID_REGEX).required() - }) - } - }, async function(request, h2) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - const { hash: hash3 } = request.params; - const strategy = request.auth.strategy; - const parsed = maybeParseCID(hash3); - if (parsed?.code !== multicodes.SHELTER_FILE_MANIFEST) { - return import_boom3.default.badRequest(); - } - const owner = await esm_default("chelonia.db/get", `_private_owner_${hash3}`); - if (!owner) { - return import_boom3.default.notFound(); + if (typeof this.#index === "number") { + strList.unshift(`#${this.#index}`); + } + if (strList.length === 0) { + return ""; + } + if (strList.length === 1) { + return strList[0]; + } + return "(?:" + strList.join("|") + ")"; + } +}; +var Trie = class { + #context = { varIndex: 0 }; + #root = new Node(); + insert(path8, index, pathErrorCheckOnly) { + const paramAssoc = []; + const groups = []; + for (let i2 = 0; ; ) { + let replaced = false; + path8 = path8.replace(/\{[^}]+\}/g, (m3) => { + const mark = `@\\${i2}`; + groups[i2] = [mark, m3]; + i2++; + replaced = true; + return mark; + }); + if (!replaced) { + break; } - switch (strategy) { - case "chel-shelter": { - const ultimateOwner = await lookupUltimateOwner(owner); - if (!ctEq(request.auth.credentials.billableContractID, ultimateOwner)) { - return import_boom3.default.unauthorized("Invalid shelter auth", "shelter"); - } - break; - } - case "chel-bearer": { - const expectedTokenDgst = await esm_default("chelonia.db/get", `_private_deletionTokenDgst_${hash3}`); - if (!expectedTokenDgst) { - return import_boom3.default.notFound(); - } - const tokenDgst = blake32Hash(request.auth.credentials.token); - if (!ctEq(expectedTokenDgst, tokenDgst)) { - return import_boom3.default.unauthorized("Invalid token", "bearer"); - } + } + const tokens = path8.match(/(?::[^\/]+)|(?:\/\*$)|./g) || []; + for (let i2 = groups.length - 1; i2 >= 0; i2--) { + const [mark] = groups[i2]; + for (let j = tokens.length - 1; j >= 0; j--) { + if (tokens[j].indexOf(mark) !== -1) { + tokens[j] = tokens[j].replace(mark, groups[i2][1]); break; } - default: - return import_boom3.default.unauthorized("Missing or invalid auth strategy"); - } - try { - await esm_default("backend/deleteFile", hash3, null, true); - return h2.response(); - } catch (e2) { - return errorMapper(e2); } - }); - route.POST("/deleteContract/{hash}", { - auth: { - // Allow file deletion, and allow either the bearer of the deletion token or - // the file owner to delete it - strategies: ["chel-shelter", "chel-bearer"], - mode: "required" - } - }, async function(request, h2) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - const { hash: hash3 } = request.params; - const strategy = request.auth.strategy; - if (!hash3 || hash3.startsWith("_private")) return import_boom3.default.notFound(); - switch (strategy) { - case "chel-shelter": { - const owner = await esm_default("chelonia.db/get", `_private_owner_${hash3}`); - if (!owner) { - return import_boom3.default.notFound(); - } - const ultimateOwner = await lookupUltimateOwner(owner); - if (!ctEq(request.auth.credentials.billableContractID, ultimateOwner)) { - return import_boom3.default.unauthorized("Invalid shelter auth", "shelter"); - } - break; - } - case "chel-bearer": { - const expectedTokenDgst = await esm_default("chelonia.db/get", `_private_deletionTokenDgst_${hash3}`); - if (!expectedTokenDgst) { - return import_boom3.default.notFound(); - } - const tokenDgst = blake32Hash(request.auth.credentials.token); - if (!ctEq(expectedTokenDgst, tokenDgst)) { - return import_boom3.default.unauthorized("Invalid token", "bearer"); - } - break; - } - default: - return import_boom3.default.unauthorized("Missing or invalid auth strategy"); + } + this.#root.insert(tokens, index, paramAssoc, this.#context, pathErrorCheckOnly); + return paramAssoc; + } + buildRegExp() { + let regexp = this.#root.buildRegExpStr(); + if (regexp === "") { + return [/^$/, [], []]; + } + let captureIndex = 0; + const indexReplacementMap = []; + const paramReplacementMap = []; + regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => { + if (handlerIndex !== void 0) { + indexReplacementMap[++captureIndex] = Number(handlerIndex); + return "$()"; } - const username = await esm_default("chelonia.db/get", `_private_cid2name_${hash3}`); - try { - const [id] = esm_default("chelonia.persistentActions/enqueue", ["backend/deleteContract", hash3, null, true]); - if (username) { - const ip = request.headers["x-real-ip"] || request.info.remoteAddress; - console.info({ contractID: hash3, username, ip, taskId: id }, "Scheduled deletion on named contract"); - } - return h2.response({ id }).code(202); - } catch (e2) { - return errorMapper(e2); + if (paramIndex !== void 0) { + paramReplacementMap[Number(paramIndex)] = ++captureIndex; + return ""; } + return ""; }); - route.POST("/kv/{contractID}/{key}", { - auth: { - strategies: ["chel-shelter"], - mode: "required" - }, - payload: { - parse: false, - maxBytes: 6 * MEGABYTE, - // TODO: make this a configurable setting - timeout: 10 * SECOND - // TODO: make this a configurable setting - }, - validate: { - params: import_npm_joi.default.object({ - contractID: import_npm_joi.default.string().regex(CID_REGEX).required(), - key: import_npm_joi.default.string().regex(KV_KEY_REGEX).required() - }) - } - }, function(request, h2) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - const { contractID, key } = request.params; - const parsed = maybeParseCID(contractID); - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { - return import_boom3.default.badRequest(); - } - if (!ctEq(request.auth.credentials.billableContractID, contractID)) { - return import_boom3.default.unauthorized(null, "shelter"); + return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap]; + } +}; +var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)]; +var wildcardRegExpCache = /* @__PURE__ */ Object.create(null); +function buildWildcardRegExp(path8) { + return wildcardRegExpCache[path8] ??= new RegExp( + path8 === "*" ? "" : `^${path8.replace( + /\/\*$|([.\\+*[^\]$()])/g, + (_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)" + )}$` + ); +} +function clearWildcardRegExpCache() { + wildcardRegExpCache = /* @__PURE__ */ Object.create(null); +} +function buildMatcherFromPreprocessedRoutes(routes) { + const trie = new Trie(); + const handlerData = []; + if (routes.length === 0) { + return nullMatcher; + } + const routesWithStaticPathFlag = routes.map( + (route) => [!/\*|\/:/.test(route[0]), ...route] + ).sort( + ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length + ); + const staticMap = /* @__PURE__ */ Object.create(null); + for (let i2 = 0, j = -1, len = routesWithStaticPathFlag.length; i2 < len; i2++) { + const [pathErrorCheckOnly, path8, handlers] = routesWithStaticPathFlag[i2]; + if (pathErrorCheckOnly) { + staticMap[path8] = [handlers.map(([h2]) => [h2, /* @__PURE__ */ Object.create(null)]), emptyParam]; + } else { + j++; + } + let paramAssoc; + try { + paramAssoc = trie.insert(path8, j, pathErrorCheckOnly); + } catch (e2) { + throw e2 === PATH_ERROR ? new UnsupportedPathError(path8) : e2; + } + if (pathErrorCheckOnly) { + continue; + } + handlerData[j] = handlers.map(([h2, paramCount]) => { + const paramIndexMap = /* @__PURE__ */ Object.create(null); + paramCount -= 1; + for (; paramCount >= 0; paramCount--) { + const [key, value] = paramAssoc[paramCount]; + paramIndexMap[key] = value; } - return esm_default("chelonia/queueInvocation", contractID, async () => { - const existing = await esm_default("chelonia.db/get", `_private_kv_${contractID}_${key}`); - const expectedEtag = request.headers["if-match"]; - if (!expectedEtag) { - return import_boom3.default.badRequest("if-match is required"); - } - const cid = existing ? createCID(existing, multicodes.RAW) : ""; - if (expectedEtag === "*") { - } else { - if (!expectedEtag.split(",").map((v2) => v2.trim()).includes(`"${cid}"`)) { - return h2.response(existing || "").etag(cid).header("x-cid", `"${cid}"`).code(412); - } - } - try { - const serializedData = JSON.parse(request.payload.toString()); - const { contracts } = esm_default("chelonia/rootState"); - if (contracts[contractID].height !== Number(serializedData.height)) { - return h2.response(existing || "").etag(cid).header("x-cid", `"${cid}"`).code(409); - } - esm_default("chelonia/parseEncryptedOrUnencryptedDetachedMessage", { - contractID, - serializedData, - meta: key - }); - } catch { - return import_boom3.default.badData(); - } - const existingSize = existing ? Buffer15.from(existing).byteLength : 0; - await esm_default("chelonia.db/set", `_private_kv_${contractID}_${key}`, request.payload); - await esm_default("backend/server/updateSize", contractID, request.payload.byteLength - existingSize); - await appendToIndexFactory(`_private_kvIdx_${contractID}`)(key); - esm_default("backend/server/broadcastKV", contractID, key, request.payload.toString()).catch((e2) => console.error(e2, "Error broadcasting KV update", contractID, key)); - return h2.response().code(204); - }); + return [h2, paramIndexMap]; }); - route.GET("/kv/{contractID}/{key}", { - auth: { - strategies: ["chel-shelter"], - mode: "required" - }, - cache: { otherwise: "no-store" }, - validate: { - params: import_npm_joi.default.object({ - contractID: import_npm_joi.default.string().regex(CID_REGEX).required(), - key: import_npm_joi.default.string().regex(KV_KEY_REGEX).required() - }) - } - }, async function(request, h2) { - const { contractID, key } = request.params; - const parsed = maybeParseCID(contractID); - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { - return import_boom3.default.badRequest(); - } - if (!ctEq(request.auth.credentials.billableContractID, contractID)) { - return import_boom3.default.unauthorized(null, "shelter"); - } - const result = await esm_default("chelonia.db/get", `_private_kv_${contractID}_${key}`); - if (!result) { - return notFoundNoCache(h2); + } + const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp(); + for (let i2 = 0, len = handlerData.length; i2 < len; i2++) { + for (let j = 0, len2 = handlerData[i2].length; j < len2; j++) { + const map = handlerData[i2][j]?.[1]; + if (!map) { + continue; } - const cid = createCID(result, multicodes.RAW); - return h2.response(result).etag(cid).header("x-cid", `"${cid}"`); - }); - route.GET("/serverMessages", { cache: { otherwise: "no-store" } }, (_request, h2) => { - const messages = import_npm_nconf5.default.get("server:messages"); - if (!messages) return []; - return h2.response(messages); - }); - route.GET("/assets/{subpath*}", { - ext: { - onPostHandler: { - method(request, h2) { - if (request.path.includes("assets/js/sw-")) { - if (!(request.response instanceof import_boom3.default.Boom)) { - console.debug("adding header: Service-Worker-Allowed /"); - request.response.header("Service-Worker-Allowed", "/"); - } - } - return h2.continue; - } - } - }, - files: { - relativeTo: staticServeConfig.distAssets + const keys = Object.keys(map); + for (let k = 0, len3 = keys.length; k < len3; k++) { + map[keys[k]] = paramReplacementMap[map[keys[k]]]; } - }, function(request, h2) { - const { subpath } = request.params; - const basename72 = path6.basename(subpath); - if (basename72.includes("-cached")) { - return h2.file(subpath, { etagMethod: false }).etag(basename72).header("Cache-Control", "public,max-age=31536000,immutable"); + } + } + const handlerMap = []; + for (const i2 in indexReplacementMap) { + handlerMap[i2] = handlerData[indexReplacementMap[i2]]; + } + return [regexp, handlerMap, staticMap]; +} +function findMiddleware(middleware, path8) { + if (!middleware) { + return void 0; + } + for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) { + if (buildWildcardRegExp(k).test(path8)) { + return [...middleware[k]]; + } + } + return void 0; +} +var RegExpRouter = class { + name = "RegExpRouter"; + #middleware; + #routes; + constructor() { + this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) }; + this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) }; + } + add(method, path8, handler) { + const middleware = this.#middleware; + const routes = this.#routes; + if (!middleware || !routes) { + throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT); + } + if (!middleware[method]) { + ; + [middleware, routes].forEach((handlerMap) => { + handlerMap[method] = /* @__PURE__ */ Object.create(null); + Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => { + handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]]; + }); + }); + } + if (path8 === "/*") { + path8 = "*"; + } + const paramCount = (path8.match(/\/:/g) || []).length; + if (/\*$/.test(path8)) { + const re = buildWildcardRegExp(path8); + if (method === METHOD_NAME_ALL) { + Object.keys(middleware).forEach((m3) => { + middleware[m3][path8] ||= findMiddleware(middleware[m3], path8) || findMiddleware(middleware[METHOD_NAME_ALL], path8) || []; + }); + } else { + middleware[method][path8] ||= findMiddleware(middleware[method], path8) || findMiddleware(middleware[METHOD_NAME_ALL], path8) || []; } - return h2.file(subpath); - }); - if (isCheloniaDashboard) { - route.GET("/dashboard/assets/{subpath*}", { - ext: { - onPostHandler: { - method(request, h2) { - if (request.path.includes("assets/js/sw-")) { - if (!(request.response instanceof import_boom3.default.Boom)) { - console.debug("adding header: Service-Worker-Allowed /"); - request.response.header("Service-Worker-Allowed", "/"); - } - } - return h2.continue; - } - } - }, - files: { - relativeTo: staticServeConfig.distAssets + Object.keys(middleware).forEach((m3) => { + if (method === METHOD_NAME_ALL || method === m3) { + Object.keys(middleware[m3]).forEach((p) => { + re.test(p) && middleware[m3][p].push([handler, paramCount]); + }); } - }, function(request, h2) { - const { subpath } = request.params; - const basename72 = path6.basename(subpath); - if (basename72.includes("-cached")) { - return h2.file(subpath, { etagMethod: false }).etag(basename72).header("Cache-Control", "public,max-age=31536000,immutable"); + }); + Object.keys(routes).forEach((m3) => { + if (method === METHOD_NAME_ALL || method === m3) { + Object.keys(routes[m3]).forEach( + (p) => re.test(p) && routes[m3][p].push([handler, paramCount]) + ); } - return h2.file(subpath); }); + return; } - route.GET(staticServeConfig.routePath, {}, { - file: staticServeConfig.distIndexHtml - }); - route.GET("/", {}, function(_req, h2) { - return h2.redirect(staticServeConfig.redirect); - }); - route.POST("/zkpp/register/{name}", { - validate: { - params: import_npm_joi.default.object({ - name: import_npm_joi.default.string().regex(NAME_REGEX).required() - }), - payload: import_npm_joi.default.alternatives([ - { - // b is a hash of a random public key (`g^r`) with secret key `r`, - // which is used by the requester to commit to that particular `r` - b: import_npm_joi.default.string().required() - }, - { - // `r` is the value used to derive `b` (in this case, it's the public - // key `g^r`) - r: import_npm_joi.default.string().required(), - // `s` is an opaque (to the client) value that was earlier returned by - // the server - s: import_npm_joi.default.string().required(), - // `sig` is an opaque (to the client) value returned by the server - // to validate the request (ensuring that (`r`, `s`) come from a - // previous request - sig: import_npm_joi.default.string().required(), - // `Eh` is the Eh = E_{S_A + S_C}(h), where S_A and S_C are salts and - // h = H\_{S_A}(P) - Eh: import_npm_joi.default.string().required() - } - ]) - } - }, async function(req) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - const lookupResult = await esm_default("backend/db/lookupName", req.params["name"]); - if (lookupResult) { - return import_boom3.default.conflict(); - } - try { - const { payload } = req; - if (payload["b"]) { - const result = registrationKey(req.params["name"], payload["b"]); - if (result) { - return result; - } - } else { - const result = register(req.params["name"], payload["r"], payload["s"], payload["sig"], payload["Eh"]); - if (result) { - return result; - } + const paths = checkOptionalParameter(path8) || [path8]; + for (let i2 = 0, len = paths.length; i2 < len; i2++) { + const path22 = paths[i2]; + Object.keys(routes).forEach((m3) => { + if (method === METHOD_NAME_ALL || method === m3) { + routes[m3][path22] ||= [ + ...findMiddleware(middleware[m3], path22) || findMiddleware(middleware[METHOD_NAME_ALL], path22) || [] + ]; + routes[m3][path22].push([handler, paramCount - len + i2 + 1]); } - } catch (e2) { - e2.ip = req.headers["x-real-ip"] || req.info.remoteAddress; - console.error(e2, "Error at POST /zkpp/{name}: " + e2.message); - } - return import_boom3.default.internal("internal error"); + }); + } + } + match = match; + buildAllMatchers() { + const matchers = /* @__PURE__ */ Object.create(null); + Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => { + matchers[method] ||= this.#buildMatcher(method); }); - route.GET("/zkpp/{contractID}/auth_hash", { - validate: { - params: import_npm_joi.default.object({ - contractID: import_npm_joi.default.string().regex(CID_REGEX).required() - }), - query: import_npm_joi.default.object({ b: import_npm_joi.default.string().required() }) - } - }, async function(req, h2) { - try { - const challenge = await getChallenge(req.params["contractID"], req.query["b"]); - return challenge || notFoundNoCache(h2); - } catch (e2) { - e2.ip = req.headers["x-real-ip"] || req.info.remoteAddress; - console.error(e2, "Error at GET /zkpp/{contractID}/auth_hash: " + e2.message); + this.#middleware = this.#routes = void 0; + clearWildcardRegExpCache(); + return matchers; + } + #buildMatcher(method) { + const routes = []; + let hasOwnRoute = method === METHOD_NAME_ALL; + [this.#middleware, this.#routes].forEach((r) => { + const ownRoute = r[method] ? Object.keys(r[method]).map((path8) => [path8, r[method][path8]]) : []; + if (ownRoute.length !== 0) { + hasOwnRoute ||= true; + routes.push(...ownRoute); + } else if (method !== METHOD_NAME_ALL) { + routes.push( + ...Object.keys(r[METHOD_NAME_ALL]).map((path8) => [path8, r[METHOD_NAME_ALL][path8]]) + ); } - return import_boom3.default.internal("internal error"); }); - route.GET("/zkpp/{contractID}/contract_hash", { - validate: { - params: import_npm_joi.default.object({ - contractID: import_npm_joi.default.string().regex(CID_REGEX).required() - }), - query: import_npm_joi.default.object({ - r: import_npm_joi.default.string().required(), - s: import_npm_joi.default.string().required(), - sig: import_npm_joi.default.string().required(), - hc: import_npm_joi.default.string().required() - }) - } - }, async function(req) { + if (!hasOwnRoute) { + return null; + } else { + return buildMatcherFromPreprocessedRoutes(routes); + } + } +}; +var SmartRouter = class { + name = "SmartRouter"; + #routers = []; + #routes = []; + constructor(init2) { + this.#routers = init2.routers; + } + add(method, path8, handler) { + if (!this.#routes) { + throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT); + } + this.#routes.push([method, path8, handler]); + } + match(method, path8) { + if (!this.#routes) { + throw new Error("Fatal error"); + } + const routers = this.#routers; + const routes = this.#routes; + const len = routers.length; + let i2 = 0; + let res; + for (; i2 < len; i2++) { + const router = routers[i2]; try { - const salt = await getContractSalt(req.params["contractID"], req.query["r"], req.query["s"], req.query["sig"], req.query["hc"]); - if (salt) { - return salt; + for (let i22 = 0, len2 = routes.length; i22 < len2; i22++) { + router.add(...routes[i22]); } + res = router.match(method, path8); } catch (e2) { - e2.ip = req.headers["x-real-ip"] || req.info.remoteAddress; - console.error(e2, "Error at GET /zkpp/{contractID}/contract_hash: " + e2.message); - } - return import_boom3.default.internal("internal error"); - }); - route.POST("/zkpp/{contractID}/updatePasswordHash", { - validate: { - params: import_npm_joi.default.object({ - contractID: import_npm_joi.default.string().regex(CID_REGEX).required() - }), - payload: import_npm_joi.default.object({ - r: import_npm_joi.default.string().required(), - s: import_npm_joi.default.string().required(), - sig: import_npm_joi.default.string().required(), - hc: import_npm_joi.default.string().required(), - Ea: import_npm_joi.default.string().required() - }) - } - }, async function(req) { - if (ARCHIVE_MODE) return import_boom3.default.notImplemented("Server in archive mode"); - try { - const { payload } = req; - const result = await updateContractSalt(req.params["contractID"], payload["r"], payload["s"], payload["sig"], payload["hc"], payload["Ea"]); - if (result) { - return result; + if (e2 instanceof UnsupportedPathError) { + continue; } - } catch (e2) { - e2.ip = req.headers["x-real-ip"] || req.info.remoteAddress; - console.error(e2, "Error at POST /zkpp/{contractID}/updatePasswordHash: " + e2.message); + throw e2; } - return import_boom3.default.internal("internal error"); - }); + this.match = router.match.bind(router); + this.#routers = [router]; + this.#routes = void 0; + break; + } + if (i2 === len) { + throw new Error("Fatal error"); + } + this.name = `SmartRouter + ${this.activeRouter.name}`; + return res; } -}); -var server_exports = {}; -var import_boom4; -var Hapi2; -var import_inert2; -var import_npm_chalk3; -var import_npm_nconf6; -var cheloniaAppManifest; -var ARCHIVE_MODE2; -var pushHeartbeatIntervalID; -var ownerSizeTotalWorker; -var creditsWorker; -var hapi; -var appendToOrphanedNamesIndex; -var init_server = __esm({ - async "src/serve/server.ts"() { - "use strict"; - init_SPMessage(); - init_chelonia(); - init_functions(); - init_persistent_actions(); - init_presets(); - import_boom4 = __toESM(require_lib2()); - Hapi2 = __toESM(require_lib34()); - import_inert2 = __toESM(require_lib35()); - init_esm(); - import_npm_chalk3 = __toESM(require_source()); - init_createWorker(); - init_auth(); - init_constants2(); - init_database(); - init_errors4(); - init_events2(); - init_instance_keys(); - init_pubsub2(); - init_push(); - import_npm_nconf6 = __toESM(require_nconf()); - cheloniaAppManifest = await (async () => { - try { - const appDir2 = import_npm_nconf6.default.get("server:appDir") || process10.cwd(); - return (await import(pathToFileURL(join72(appDir2, "chelonia.json")).toString(), { - with: { type: "json" } - })).default; - } catch { - console.warn("`chelonia.json` unparsable or not found. Version information will be unavailable."); - } - })(); - ARCHIVE_MODE2 = import_npm_nconf6.default.get("server:archiveMode"); - if (CREDITS_WORKER_TASK_TIME_INTERVAL && OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL > CREDITS_WORKER_TASK_TIME_INTERVAL) { - process10.stderr.write("The size calculation worker must run more frequently than the credits worker for accurate billing"); - process10.exit(1); - } - ownerSizeTotalWorker = ARCHIVE_MODE2 || !OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL ? void 0 : createWorker_default("./serve/ownerSizeTotalWorker.js"); - creditsWorker = ARCHIVE_MODE2 || !CREDITS_WORKER_TASK_TIME_INTERVAL ? void 0 : createWorker_default("./serve/creditsWorker.js"); - hapi = new Hapi2.Server({ - // debug: false, // <- Hapi v16 was outputing too many unnecessary debug statements - // // v17 doesn't seem to do this anymore so I've re-enabled the logging - // debug: { log: ['error'], request: ['error'] }, - host: import_npm_nconf6.default.get("server:host"), - port: import_npm_nconf6.default.get("server:port"), - // See: https://github.com/hapijs/discuss/issues/262#issuecomment-204616831 - routes: { - cors: { - // TODO: figure out if we can live with '*' or if we need to restrict it - origin: ["*"] - // origin: [ - // process.env.API_URL, - // // improve support for browsersync proxy - // ...(process.env.NODE_ENV === 'development' && ['http://localhost:3000']) - // ] + get activeRouter() { + if (this.#routes || this.#routers.length !== 1) { + throw new Error("No active router has been determined yet."); + } + return this.#routers[0]; + } +}; +var emptyParams = /* @__PURE__ */ Object.create(null); +var hasChildren = (children) => { + for (const _ in children) { + return true; + } + return false; +}; +var Node2 = class _Node2 { + #methods; + #children; + #patterns; + #order = 0; + #params = emptyParams; + constructor(method, handler, children) { + this.#children = children || /* @__PURE__ */ Object.create(null); + this.#methods = []; + if (method && handler) { + const m3 = /* @__PURE__ */ Object.create(null); + m3[method] = { handler, possibleKeys: [], score: 0 }; + this.#methods = [m3]; + } + this.#patterns = []; + } + insert(method, path8, handler) { + this.#order = ++this.#order; + let curNode = this; + const parts = splitRoutingPath(path8); + const possibleKeys = []; + for (let i2 = 0, len = parts.length; i2 < len; i2++) { + const p = parts[i2]; + const nextP = parts[i2 + 1]; + const pattern = getPattern(p, nextP); + const key = Array.isArray(pattern) ? pattern[0] : p; + if (key in curNode.#children) { + curNode = curNode.#children[key]; + if (pattern) { + possibleKeys.push(pattern[1]); } + continue; + } + curNode.#children[key] = new _Node2(); + if (pattern) { + curNode.#patterns.push(pattern); + possibleKeys.push(pattern[1]); + } + curNode = curNode.#children[key]; + } + curNode.#methods.push({ + [method]: { + handler, + possibleKeys: possibleKeys.filter((v2, i2, a) => a.indexOf(v2) === i2), + score: this.#order } }); - hapi.ext({ - type: "onPreResponse", - method: function(request, h2) { - try { - if (!(request.response instanceof import_boom4.default.Boom)) { - request.response.header("X-Frame-Options", "DENY"); + return curNode; + } + #pushHandlerSets(handlerSets, node, method, nodeParams, params) { + for (let i2 = 0, len = node.#methods.length; i2 < len; i2++) { + const m3 = node.#methods[i2]; + const handlerSet = m3[method] || m3[METHOD_NAME_ALL]; + const processedSet = {}; + if (handlerSet !== void 0) { + handlerSet.params = /* @__PURE__ */ Object.create(null); + handlerSets.push(handlerSet); + if (nodeParams !== emptyParams || params && params !== emptyParams) { + for (let i22 = 0, len2 = handlerSet.possibleKeys.length; i22 < len2; i22++) { + const key = handlerSet.possibleKeys[i22]; + const processed = processedSet[handlerSet.score]; + handlerSet.params[key] = params?.[key] && !processed ? params[key] : nodeParams[key] ?? params?.[key]; + processedSet[handlerSet.score] = true; + } + } + } + } + } + search(method, path8) { + const handlerSets = []; + this.#params = emptyParams; + const curNode = this; + let curNodes = [curNode]; + const parts = splitPath(path8); + const curNodesQueue = []; + const len = parts.length; + let partOffsets = null; + for (let i2 = 0; i2 < len; i2++) { + const part = parts[i2]; + const isLast = i2 === len - 1; + const tempNodes = []; + for (let j = 0, len2 = curNodes.length; j < len2; j++) { + const node = curNodes[j]; + const nextNode = node.#children[part]; + if (nextNode) { + nextNode.#params = node.#params; + if (isLast) { + if (nextNode.#children["*"]) { + this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params); + } + this.#pushHandlerSets(handlerSets, nextNode, method, node.#params); } else { - request.response.output.headers["X-Frame-Options"] = "DENY"; + tempNodes.push(nextNode); } - } catch (err) { - console.warn(import_npm_chalk3.default.yellow("[backend] Could not set X-Frame-Options header:", err.message)); - } - return h2.continue; - } - }); - appendToOrphanedNamesIndex = appendToIndexFactory("_private_orphaned_names_index"); - esm_default("okTurtles.data/set", SERVER_INSTANCE, hapi); - esm_default("sbp/selectors/register", { - "backend/server/persistState": async function(deserializedHEAD) { - const contractID = deserializedHEAD.contractID; - const cheloniaState = esm_default("chelonia/rootState"); - if (!cheloniaState.contracts[contractID] || cheloniaState.contracts[contractID].height < deserializedHEAD.head.height) { - return; } - if (cheloniaState.contracts[contractID].HEAD === deserializedHEAD.hash) { - const state = { - contractState: cheloniaState[contractID], - cheloniaContractInfo: cheloniaState.contracts[contractID] - }; - await esm_default("chelonia.db/set", "_private_cheloniaState_" + contractID, JSON.stringify(state)); - } - if (contractID === deserializedHEAD.hash) { - await esm_default("backend/server/appendToContractIndex", contractID); - } - if (cheloniaState.contracts[contractID].previousKeyOp === deserializedHEAD.hash) { - await appendToIndexFactory(`_private_keyop_idx_${contractID}_${deserializedHEAD.head.height - deserializedHEAD.head.height % KEYOP_SEGMENT_LENGTH}`)(String(deserializedHEAD.head.height)); - } - }, - "backend/server/appendToContractIndex": appendToIndexFactory("_private_cheloniaState_index"), - "backend/server/broadcastKV": async function(contractID, key, entry) { - const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); - const pubsubMessage = createKvMessage(contractID, key, entry); - const subscribers = pubsub.enumerateSubscribers(contractID, key); - console.debug(import_npm_chalk3.default.blue.bold(`[pubsub] Broadcasting KV change on ${contractID} to key ${key}`)); - await pubsub.broadcast(pubsubMessage, { to: subscribers, wsOnly: true }); - }, - "backend/server/broadcastEntry": async function(deserializedHEAD, entry) { - const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); - const contractID = deserializedHEAD.contractID; - const contractType = esm_default("chelonia/rootState").contracts[contractID]?.type; - const pubsubMessage = createMessage(NOTIFICATION_TYPE.ENTRY, entry, { contractID, contractType }); - const subscribers = pubsub.enumerateSubscribers(contractID); - console.debug(import_npm_chalk3.default.blue.bold(`[pubsub] Broadcasting ${deserializedHEAD.description()}`)); - await pubsub.broadcast(pubsubMessage, { to: subscribers }); - }, - "backend/server/broadcastDeletion": async function(contractID) { - const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); - const pubsubMessage = createMessage(NOTIFICATION_TYPE.DELETION, contractID); - const subscribers = pubsub.enumerateSubscribers(contractID); - console.debug(import_npm_chalk3.default.blue.bold(`[pubsub] Broadcasting deletion of ${contractID}`)); - await pubsub.broadcast(pubsubMessage, { to: subscribers }); - }, - "backend/server/handleEntry": async function(deserializedHEAD, entry) { - const contractID = deserializedHEAD.contractID; - if (deserializedHEAD.head.op === SPMessage.OP_CONTRACT) { - esm_default("okTurtles.data/get", PUBSUB_INSTANCE).channels.add(contractID); - } - await esm_default("chelonia/private/in/enqueueHandleEvent", contractID, entry); - await esm_default("backend/server/persistState", deserializedHEAD, entry); - esm_default("backend/server/broadcastEntry", deserializedHEAD, entry).catch((e2) => console.error(e2, "Error broadcasting entry", contractID, deserializedHEAD.hash)); - }, - "backend/server/saveOwner": async function(ownerID, resourceID) { - await esm_default("chelonia/queueInvocation", ownerID, async () => { - const owner = await esm_default("chelonia.db/get", ownerID); - if (!owner) { - throw new Error("Owner resource does not exist"); + for (let k = 0, len3 = node.#patterns.length; k < len3; k++) { + const pattern = node.#patterns[k]; + const params = node.#params === emptyParams ? {} : { ...node.#params }; + if (pattern === "*") { + const astNode = node.#children["*"]; + if (astNode) { + this.#pushHandlerSets(handlerSets, astNode, method, node.#params); + astNode.#params = params; + tempNodes.push(astNode); + } + continue; } - await esm_default("chelonia.db/set", `_private_owner_${resourceID}`, ownerID); - const resourcesKey = `_private_resources_${ownerID}`; - await appendToIndexFactory(resourcesKey)(resourceID); - esm_default("chelonia.persistentActions/enqueue", ["backend/server/addToIndirectResourcesIndex", resourceID]); - }); - }, - "backend/server/addToIndirectResourcesIndex": async function(resourceID) { - const ownerID = await esm_default("chelonia.db/get", `_private_owner_${resourceID}`); - let indirectOwnerID = ownerID; - while (indirectOwnerID = await esm_default("chelonia.db/get", `_private_owner_${indirectOwnerID}`)) { - await appendToIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(resourceID); - } - }, - "backend/server/removeFromIndirectResourcesIndex": async function(resourceID) { - const ownerID = await esm_default("chelonia.db/get", `_private_owner_${resourceID}`); - const resources = await esm_default("chelonia.db/get", `_private_resources_${resourceID}`); - const indirectResources = resources ? await esm_default("chelonia.db/get", `_private_indirectResources_${resourceID}`) : void 0; - const allSubresources = [ - resourceID, - ...resources ? resources.split("\0") : [], - ...indirectResources ? indirectResources.split("\0") : [] - ]; - let indirectOwnerID = ownerID; - while (indirectOwnerID = await esm_default("chelonia.db/get", `_private_owner_${indirectOwnerID}`)) { - await removeFromIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(allSubresources); - } - }, - "backend/server/registerBillableEntity": appendToIndexFactory("_private_billable_entities"), - "backend/server/updateSize": function(resourceID, size, ultimateOwnerID) { - const sizeKey = `_private_size_${resourceID}`; - return updateSize(resourceID, sizeKey, size).then(() => { - return ownerSizeTotalWorker?.rpcSbp("worker/updateSizeSideEffects", { resourceID, size, ultimateOwnerID }); - }); - }, - "backend/server/updateContractFilesTotalSize": function(resourceID, size) { - const sizeKey = `_private_contractFilesTotalSize_${resourceID}`; - return updateSize(resourceID, sizeKey, size, true); - }, - "backend/server/stop": async function() { - clearInterval(pushHeartbeatIntervalID); - if (esm_default("sbp/selectors/fn", "backend/server/stopRateLimiters")) { - await esm_default("backend/server/stopRateLimiters"); - } - await hapi.stop(); - await Promise.all([ - ownerSizeTotalWorker?.terminate(), - creditsWorker?.terminate() - ]); - }, - async "backend/deleteFile"(cid, ultimateOwnerID, skipIfDeleted) { - const owner = await esm_default("chelonia.db/get", `_private_owner_${cid}`); - const rawManifest = await esm_default("chelonia.db/get", cid); - const size = await esm_default("chelonia.db/get", `_private_size_${cid}`); - if (owner && !ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(owner); - if (rawManifest === "") { - if (skipIfDeleted) return; - throw new BackendErrorGone(); - } - if (!rawManifest) { - if (skipIfDeleted) return; - throw new BackendErrorNotFound(); - } - try { - const manifest2 = JSON.parse(rawManifest); - if (!manifest2 || typeof manifest2 !== "object") throw new BackendErrorBadData("manifest format is invalid"); - if (manifest2.version !== "1.0.0") throw new BackendErrorBadData("unsupported manifest version"); - if (!Array.isArray(manifest2.chunks) || !manifest2.chunks.length) throw new BackendErrorBadData("missing chunks"); - await Promise.all(manifest2.chunks.map(([, cid2]) => esm_default("chelonia.db/delete", cid2))); - } catch (e2) { - console.warn(e2, `Error parsing manifest for ${cid}. It's probably not a file manifest.`); - throw new BackendErrorNotFound(); - } - const resourcesKey = `_private_resources_${owner}`; - await removeFromIndexFactory(resourcesKey)(cid); - await esm_default("backend/server/removeFromIndirectResourcesIndex", cid); - await esm_default("chelonia.db/delete", `_private_owner_${cid}`); - await esm_default("chelonia.db/delete", `_private_size_${cid}`); - await esm_default("chelonia.db/delete", `_private_deletionTokenDgst_${cid}`); - await esm_default("chelonia.db/set", cid, ""); - await esm_default("backend/server/updateContractFilesTotalSize", owner, -Number(size)); - if (ultimateOwnerID && size) { - await ownerSizeTotalWorker?.rpcSbp("worker/updateSizeSideEffects", { resourceID: cid, size: -parseInt(size), ultimateOwnerID }); - } - }, - async "backend/deleteContract"(cid, ultimateOwnerID, skipIfDeleted) { - let contractsPendingDeletion = esm_default("okTurtles.data/get", "contractsPendingDeletion"); - if (!contractsPendingDeletion) { - contractsPendingDeletion = /* @__PURE__ */ new Set(); - esm_default("okTurtles.data/set", "contractsPendingDeletion", contractsPendingDeletion); - } - if (contractsPendingDeletion.has(cid)) { - return; - } - contractsPendingDeletion.add(cid); - return await esm_default("chelonia/queueInvocation", cid, async () => { - const owner = await esm_default("chelonia.db/get", `_private_owner_${cid}`); - if (!ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(cid); - const rawManifest = await esm_default("chelonia.db/get", cid); - const size = await esm_default("chelonia.db/get", `_private_size_${cid}`); - if (rawManifest === "") { - if (skipIfDeleted) return; - throw new BackendErrorGone(); - } - if (!rawManifest) { - if (skipIfDeleted) return; - throw new BackendErrorNotFound(); - } - const resourcesKey = `_private_resources_${cid}`; - const resources = await esm_default("chelonia.db/get", resourcesKey); - if (resources) { - await Promise.allSettled(resources.split("\0").map((resourceCid) => { - const parsed = parseCID(resourceCid); - if (parsed.code === multicodes.SHELTER_CONTRACT_DATA) { - return esm_default("chelonia.persistentActions/enqueue", ["backend/deleteContract", resourceCid, ultimateOwnerID, true]); - } else if (parsed.code === multicodes.SHELTER_FILE_MANIFEST) { - return esm_default("chelonia.persistentActions/enqueue", ["backend/deleteFile", resourceCid, ultimateOwnerID, true]); - } else { - console.warn({ cid, resourceCid, code: parsed.code }, "Resource should be deleted but it is of an unknown type"); - } - return void 0; - })); + const [key, name, matcher] = pattern; + if (!part && !(matcher instanceof RegExp)) { + continue; } - await esm_default("chelonia.db/delete", resourcesKey); - const latestHEADinfo = await esm_default("chelonia/db/latestHEADinfo", cid); - if (latestHEADinfo) { - for (let i2 = latestHEADinfo.height; i2 > 0; i2--) { - const eventKey = `_private_hidx=${cid}#${i2}`; - const event = await esm_default("chelonia.db/get", eventKey); - if (event) { - await esm_default("chelonia.db/delete", JSON.parse(event).hash); - await esm_default("chelonia.db/delete", eventKey); + const child = node.#children[key]; + if (matcher instanceof RegExp) { + if (partOffsets === null) { + partOffsets = new Array(len); + let offset = path8[0] === "/" ? 1 : 0; + for (let p = 0; p < len; p++) { + partOffsets[p] = offset; + offset += parts[p].length + 1; } - if (i2 % KEYOP_SEGMENT_LENGTH === 0) { - await esm_default("chelonia.db/delete", `_private_keyop_idx_${cid}_${i2}`); + } + const restPathString = path8.substring(partOffsets[i2]); + const m3 = matcher.exec(restPathString); + if (m3) { + params[name] = m3[0]; + this.#pushHandlerSets(handlerSets, child, method, node.#params, params); + if (hasChildren(child.#children)) { + child.#params = params; + const componentCount = m3[0].match(/\//)?.length ?? 0; + const targetCurNodes = curNodesQueue[componentCount] ||= []; + targetCurNodes.push(child); } + continue; } - await esm_default("chelonia/db/deleteLatestHEADinfo", cid); - } - const kvIndexKey = `_private_kvIdx_${cid}`; - const kvKeys = await esm_default("chelonia.db/get", kvIndexKey); - if (kvKeys) { - await Promise.all(kvKeys.split("\0").map((key) => { - return esm_default("chelonia.db/delete", `_private_kv_${cid}_${key}`); - })); } - await esm_default("chelonia.db/delete", kvIndexKey); - await esm_default("backend/server/removeFromIndirectResourcesIndex", cid); - await esm_default("chelonia.db/delete", `_private_indirectResources_${cid}`); - await esm_default("chelonia.db/get", `_private_cid2name_${cid}`).then((name) => { - if (!name) return; - return Promise.all([ - esm_default("chelonia.db/delete", `_private_cid2name_${cid}`), - appendToOrphanedNamesIndex(name) - ]); - }); - await esm_default("chelonia.db/delete", `_private_rid_${cid}`); - await esm_default("chelonia.db/delete", `_private_owner_${cid}`); - await esm_default("chelonia.db/delete", `_private_size_${cid}`); - await esm_default("chelonia.db/delete", `_private_contractFilesTotalSize_${cid}`); - await esm_default("chelonia.db/delete", `_private_deletionTokenDgst_${cid}`); - await removeFromIndexFactory(`_private_resources_${owner}`)(cid); - await esm_default("chelonia.db/delete", `_private_hidx=${cid}#0`); - await esm_default("chelonia.db/delete", `_private_keyop_idx_${cid}_0`); - await esm_default("chelonia.db/set", cid, ""); - esm_default("chelonia/private/removeImmediately", cid); - if (size) { - await ownerSizeTotalWorker?.rpcSbp("worker/updateSizeSideEffects", { resourceID: cid, size: -parseInt(size), ultimateOwnerID }); - } - await esm_default("chelonia.db/delete", `_private_cheloniaState_${cid}`); - await removeFromIndexFactory("_private_cheloniaState_index")(cid); - await removeFromIndexFactory("_private_billable_entities")(cid); - esm_default("backend/server/broadcastDeletion", cid).catch((e2) => { - console.error(e2, "Error broadcasting contract deletion", cid); - }); - }).finally(() => { - contractsPendingDeletion.delete(cid); - }).catch((e2) => { - console.error(e2, "Error in contract deletion cleanup"); - throw e2; - }); - } - }); - if (process10.env.NODE_ENV === "development" && !process10.env.CI) { - hapi.events.on("response", (req) => { - const ip = req.headers["x-real-ip"] || req.info.remoteAddress; - const statusCode = req.response instanceof import_boom4.default.Boom ? req.response.output.statusCode : req.response.statusCode; - console.debug(import_npm_chalk3.default`{grey ${ip}: ${req.method} ${req.path} --> ${statusCode}}`); - }); - } - esm_default("okTurtles.data/set", PUBSUB_INSTANCE, createServer(hapi.listener, { - serverHandlers: { - connection(socket) { - const versionInfo = { - appVersion: cheloniaAppManifest?.appVersion || null, - contractsVersion: cheloniaAppManifest?.contracts ? Object.fromEntries( - Object.entries(cheloniaAppManifest?.contracts).map(([k, v2]) => [k, v2.version]) - ) : null - }; - socket.send(createNotification(NOTIFICATION_TYPE.VERSION_INFO, versionInfo)); - } - }, - socketHandlers: { - // The `close()` handler signals the server that the WS has been closed and - // that subsequent messages to subscribed channels should now be sent to its - // associated web push subscription, if it exists. - close() { - const socket = this; - const { server } = this; - const subscriptionId = socket.pushSubscriptionId; - if (!subscriptionId) return; - if (!server.pushSubscriptions[subscriptionId]) return; - server.pushSubscriptions[subscriptionId].sockets.delete(socket); - delete socket.pushSubscriptionId; - if (server.pushSubscriptions[subscriptionId].sockets.size === 0) { - server.pushSubscriptions[subscriptionId].subscriptions.forEach((channelID) => { - if (!server.subscribersByChannelID[channelID]) { - server.subscribersByChannelID[channelID] = /* @__PURE__ */ new Set(); + if (matcher === true || matcher.test(part)) { + params[name] = part; + if (isLast) { + this.#pushHandlerSets(handlerSets, child, method, params, node.#params); + if (child.#children["*"]) { + this.#pushHandlerSets( + handlerSets, + child.#children["*"], + method, + params, + node.#params + ); } - server.subscribersByChannelID[channelID].add(server.pushSubscriptions[subscriptionId]); - }); - } - } - }, - messageHandlers: { - [REQUEST_TYPE.PUSH_ACTION]: async function({ data }) { - const socket = this; - const { action, payload } = data; - if (!action) { - socket.send(createPushErrorResponse({ message: "'action' field is required" })); - } - const handler = pushServerActionhandlers[action]; - if (handler) { - try { - await handler.call(socket, payload); - } catch (error2) { - const message = error2?.message || `push server failed to perform [${action}] action`; - console.warn(error2, `[${socket.ip}] Action '${action}' for '${REQUEST_TYPE.PUSH_ACTION}' handler failed: ${message}`); - socket.send(createPushErrorResponse({ actionType: action, message })); + } else { + child.#params = params; + tempNodes.push(child); } - } else { - socket.send(createPushErrorResponse({ message: `No handler for the '${action}' action` })); } - }, - // This handler adds subscribed channels to the web push subscription - // associated with the WS, so that when the WS is closed we can continue - // sending messages as web push notifications. - [NOTIFICATION_TYPE.SUB]({ channelID }) { - const socket = this; - const { server } = this; - if (!socket.pushSubscriptionId) return; - if (!server.pushSubscriptions[socket.pushSubscriptionId]) { - delete socket.pushSubscriptionId; - return; - } - addChannelToSubscription(server, socket.pushSubscriptionId, channelID); - }, - // This handler removes subscribed channels from the web push subscription - // associated with the WS, so that when the WS is closed we don't send - // messages as web push notifications. - [NOTIFICATION_TYPE.UNSUB]({ channelID }) { - const socket = this; - const { server } = this; - if (!socket.pushSubscriptionId) return; - if (!server.pushSubscriptions[socket.pushSubscriptionId]) { - delete socket.pushSubscriptionId; - return; - } - deleteChannelFromSubscription(server, socket.pushSubscriptionId, channelID); } } - })); - (async function() { - await initDB(); - await ownerSizeTotalWorker?.ready; - await creditsWorker?.ready; - await esm_default("chelonia/configure", SERVER); - esm_default("chelonia.persistentActions/configure", { - databaseKey: "_private_persistent_actions" - }); - const savedStateIndex = await esm_default("chelonia.db/get", "_private_cheloniaState_index"); - if (savedStateIndex) { - const recoveredState = /* @__PURE__ */ Object.create(null); - recoveredState.contracts = /* @__PURE__ */ Object.create(null); - const channels = esm_default("okTurtles.data/get", PUBSUB_INSTANCE).channels; - await Promise.all(savedStateIndex.split("\0").map(async (contractID) => { - const cpSerialized = await esm_default("chelonia.db/get", `_private_cheloniaState_${contractID}`); - if (!cpSerialized) { - console.warn(`[server] missing state for contractID ${contractID} - skipping setup for this contract`); - return; - } - const cp = JSON.parse(cpSerialized); - recoveredState[contractID] = cp.contractState; - recoveredState.contracts[contractID] = cp.cheloniaContractInfo; - channels.add(contractID); - })); - Object.assign(esm_default("chelonia/rootState"), recoveredState); - } - const savedWebPushIndex = await esm_default("chelonia.db/get", "_private_webpush_index"); - if (savedWebPushIndex) { - const { pushSubscriptions, subscribersByChannelID } = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); - await Promise.all(savedWebPushIndex.split("\0").map(async (subscriptionId) => { - const subscriptionSerialized = await esm_default("chelonia.db/get", `_private_webpush_${subscriptionId}`); - if (!subscriptionSerialized) { - console.warn(`[server] missing state for subscriptionId '${subscriptionId}' - skipping setup for this subscription`); - return; - } - const { settings, subscriptionInfo, channelIDs } = JSON.parse(subscriptionSerialized); - pushSubscriptions[subscriptionId] = subscriptionInfoWrapper(subscriptionId, subscriptionInfo, { channelIDs, settings }); - channelIDs.forEach((channelID) => { - if (!subscribersByChannelID[channelID]) subscribersByChannelID[channelID] = /* @__PURE__ */ new Set(); - subscribersByChannelID[channelID].add(pushSubscriptions[subscriptionId]); - }); - })); - } - esm_default("chelonia.persistentActions/load").catch((e2) => { - console.error(e2, "Error loading persistent actions"); + const shifted = curNodesQueue.shift(); + curNodes = shifted ? tempNodes.concat(shifted) : tempNodes; + } + if (handlerSets.length > 1) { + handlerSets.sort((a, b) => { + return a.score - b.score; }); - await hapi.register([ - { plugin: auth_default }, - { plugin: import_inert2.default } - // { - // plugin: require('hapi-pino'), - // options: { - // instance: logger - // } - // } - ]); - await Promise.resolve().then(() => (init_routes(), routes_exports)); - await hapi.start(); - console.info("Backend server running at:", hapi.info.uri); - esm_default("okTurtles.events/emit", SERVER_RUNNING, hapi); - })(); - (() => { - const map = /* @__PURE__ */ new WeakMap(); - pushHeartbeatIntervalID = setInterval(() => { - const now = Date.now(); - const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); - const notification = JSON.stringify({ type: "recurring" }); - Object.values(pubsub?.pushSubscriptions || {}).filter( - (pushSubscription) => !!pushSubscription.settings.heartbeatInterval && pushSubscription.sockets.size === 0 - ).forEach((pushSubscription) => { - const last = map.get(pushSubscription) ?? Number.NEGATIVE_INFINITY; - if (now - last < pushSubscription.settings.heartbeatInterval) return; - postEvent(pushSubscription, notification).then(() => { - map.set(pushSubscription, now); - }).catch((e2) => { - console.warn(e2, "Error sending recurring message to web push client", pushSubscription.id); - }); - }); - }, 1 * 60 * 60 * 1e3); - })(); + } + return [handlerSets.map(({ handler, params }) => [handler, params])]; } -}); -var serve_exports = {}; -__export(serve_exports, { - default: () => serve_default, - removeSignalHandlers: () => removeSignalHandlers -}); -function logSBP(_domain, selector, data) { - if (!dontLog[selector]) { - if (selector === "backend/server/handleEntry") { - console.debug(import_npm_chalk4.default.bold(`[sbp] ${selector}`), data[0].description()); - } else { - console.debug(import_npm_chalk4.default.bold(`[sbp] ${selector}`), data); +}; +var TrieRouter = class { + name = "TrieRouter"; + #node; + constructor() { + this.#node = new Node2(); + } + add(method, path8, handler) { + const results = checkOptionalParameter(path8); + if (results) { + for (let i2 = 0, len = results.length; i2 < len; i2++) { + this.#node.insert(method, results[i2], handler); + } + return; } + this.#node.insert(method, path8, handler); } -} -function removeSignalHandlers() { - for (const [signal, handler] of signalHandlers) { - process11.removeListener(signal, handler); + match(method, path8) { + return this.#node.search(method, path8); } - signalHandlers.length = 0; -} -var import_npm_chalk4; -var dontLog; -var serve_default; -var exit2; -var signalHandlers; -var handleSignal; -var init_serve = __esm({ - "src/serve/index.ts"() { - "use strict"; - init_esm3(); - init_esm9(); - init_esm10(); - init_esm(); - import_npm_chalk4 = __toESM(require_source()); - init_events2(); - init_instance_keys(); - init_logger(); - console.info("NODE_ENV =", process11.env.NODE_ENV); - dontLog = { - "backend/server/broadcastEntry": true, - "backend/server/broadcastDeletion": true, - "backend/server/broadcastKV": true - }; - ["backend"].forEach((domain) => esm_default("sbp/filters/domain/add", domain, logSBP)); - [].forEach((sel) => esm_default("sbp/filters/selector/add", sel, logSBP)); - serve_default = () => new Promise((resolve82, reject) => { - esm_default("okTurtles.events/on", SERVER_RUNNING, function() { - console.info(import_npm_chalk4.default.bold("backend startup sequence complete.")); - resolve82(); - }); - init_server().then(() => server_exports).catch(reject); - }); - esm_default("okTurtles.events/once", SERVER_EXITING, () => { - esm_default("okTurtles.data/apply", PUBSUB_INSTANCE, function(pubsub) { - esm_default("okTurtles.eventQueue/queueEvent", SERVER_EXITING, () => { - return new Promise((resolve82) => { - pubsub.on("close", async function() { - try { - removeSignalHandlers(); - await esm_default("chelonia.persistentActions/unload"); - await esm_default("backend/server/stop"); - console.info("Hapi server down"); - } catch (err) { - console.error(err, "Error during shutdown"); - } finally { - resolve82(); - } - }); - pubsub.close(); - pubsub.clients.forEach((client) => client.terminate()); - }); - }); - }); - }); - process11.on("uncaughtException", (err) => { - console.error(err, "[server] Unhandled exception"); - process11.exit(1); - }); - process11.on("unhandledRejection", (reason) => { - console.error(reason, "[server] Unhandled promise rejection:", reason); - process11.exit(1); +}; +var Hono2 = class extends Hono { + /** + * Creates an instance of the Hono class. + * + * @param options - Optional configuration options for the Hono instance. + */ + constructor(options2 = {}) { + super(options2); + this.router = options2.router ?? new SmartRouter({ + routers: [new RegExpRouter(), new TrieRouter()] }); - exit2 = (code2) => { - esm_default("okTurtles.events/once", SERVER_EXITING, () => { - esm_default("okTurtles.eventQueue/queueEvent", SERVER_EXITING, () => { - process11.send?.({}); - process11.nextTick(() => process11.exit(code2)); - }); - }); - esm_default("okTurtles.events/emit", SERVER_EXITING); - }; - signalHandlers = []; - handleSignal = (signal, code2) => { - const handler = () => { - console.error(`Exiting upon receiving ${signal} (${code2})`); - exit2(128 + code2); - }; - signalHandlers.push([signal, handler]); - process11.on(signal, handler); - }; - [ - ["SIGHUP", 1], - ["SIGINT", 2], - ["SIGQUIT", 3], - ["SIGTERM", 15], - ["SIGUSR1", 10], - ["SIGUSR2", 11] - ].forEach(([signal, code2]) => handleSignal(signal, code2)); - } -}); -init_esm(); -var import_npm_nconf7 = __toESM(require_nconf()); -function getLineColFromPtr(string3, ptr) { - let lines = string3.slice(0, ptr).split(/\r\n|\n|\r/g); - return [lines.length, lines.pop().length + 1]; -} -function makeCodeBlock(string3, line, column) { - let lines = string3.split(/\r\n|\n|\r/g); - let codeblock = ""; - let numberLen = (Math.log10(line + 1) | 0) + 1; - for (let i2 = line - 1; i2 <= line + 1; i2++) { - let l = lines[i2 - 1]; - if (!l) - continue; - codeblock += i2.toString().padEnd(numberLen, " "); - codeblock += ": "; - codeblock += l; - codeblock += "\n"; - if (i2 === line) { - codeblock += " ".repeat(numberLen + column + 2); - codeblock += "^\n"; - } - } - return codeblock; -} -var TomlError = class extends Error { - line; - column; - codeblock; - constructor(message, options2) { - const [line, column] = getLineColFromPtr(options2.toml, options2.ptr); - const codeblock = makeCodeBlock(options2.toml, line, column); - super(`Invalid TOML document: ${message} - -${codeblock}`, options2); - this.line = line; - this.column = column; - this.codeblock = codeblock; } }; -function isEscaped(str, ptr) { - let i2 = 0; - while (str[ptr - ++i2] === "\\") - ; - return --i2 && i2 % 2; -} -function indexOfNewline(str, start = 0, end = str.length) { - let idx = str.indexOf("\n", start); - if (str[idx - 1] === "\r") - idx--; - return idx <= end ? idx : -1; -} -function skipComment(str, ptr) { - for (let i2 = ptr; i2 < str.length; i2++) { - let c = str[i2]; - if (c === "\n") - return i2; - if (c === "\r" && str[i2 + 1] === "\n") - return i2 + 1; - if (c < " " && c !== " " || c === "\x7F") { - throw new TomlError("control characters are not allowed in comments", { - toml: str, - ptr - }); +var cors = (options2) => { + const defaults = { + origin: "*", + allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"], + allowHeaders: [], + exposeHeaders: [] + }; + const opts = { + ...defaults, + ...options2 + }; + const findAllowOrigin = ((optsOrigin) => { + if (typeof optsOrigin === "string") { + if (optsOrigin === "*") { + if (opts.credentials) { + return (origin) => origin || null; + } + return () => optsOrigin; + } else { + return (origin) => optsOrigin === origin ? origin : null; + } + } else if (typeof optsOrigin === "function") { + return optsOrigin; + } else { + return (origin) => optsOrigin.includes(origin) ? origin : null; + } + })(opts.origin); + const findAllowMethods = ((optsAllowMethods) => { + if (typeof optsAllowMethods === "function") { + return optsAllowMethods; + } else if (Array.isArray(optsAllowMethods)) { + return () => optsAllowMethods; + } else { + return () => []; } - } - return str.length; -} -function skipVoid(str, ptr, banNewLines, banComments) { - let c; - while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n")) - ptr++; - return banComments || c !== "#" ? ptr : skipVoid(str, skipComment(str, ptr), banNewLines); -} -function skipUntil(str, ptr, sep, end, banNewLines = false) { - if (!end) { - ptr = indexOfNewline(str, ptr); - return ptr < 0 ? str.length : ptr; - } - for (let i2 = ptr; i2 < str.length; i2++) { - let c = str[i2]; - if (c === "#") { - i2 = indexOfNewline(str, i2); - } else if (c === sep) { - return i2 + 1; - } else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i2 + 1] === "\n")) { - return i2; + })(opts.allowMethods); + return async function cors2(c, next) { + function set(key, value) { + c.res.headers.set(key, value); } - } - throw new TomlError("cannot find end of structure", { - toml: str, - ptr - }); -} -function getStringEnd(str, seek) { - let first = str[seek]; - let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2] ? str.slice(seek, seek + 3) : first; - seek += target.length - 1; - do - seek = str.indexOf(target, ++seek); - while (seek > -1 && first !== "'" && isEscaped(str, seek)); - if (seek > -1) { - seek += target.length; - if (target.length > 1) { - if (str[seek] === first) - seek++; - if (str[seek] === first) - seek++; + const allowOrigin = await findAllowOrigin(c.req.header("origin") || "", c); + if (allowOrigin) { + set("Access-Control-Allow-Origin", allowOrigin); } - } - return seek; -} -var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}:\d{2}(?:\.\d+)?)?(Z|[-+]\d{2}:\d{2})?$/i; -var TomlDate = class _TomlDate extends Date { - #hasDate = false; - #hasTime = false; - #offset = null; - constructor(date3) { - let hasDate = true; - let hasTime = true; - let offset = "Z"; - if (typeof date3 === "string") { - let match = date3.match(DATE_TIME_RE); - if (match) { - if (!match[1]) { - hasDate = false; - date3 = `0000-01-01T${date3}`; - } - hasTime = !!match[2]; - hasTime && date3[10] === " " && (date3 = date3.replace(" ", "T")); - if (match[2] && +match[2] > 23) { - date3 = ""; - } else { - offset = match[3] || null; - date3 = date3.toUpperCase(); - if (!offset && hasTime) - date3 += "Z"; + if (opts.credentials) { + set("Access-Control-Allow-Credentials", "true"); + } + if (opts.exposeHeaders?.length) { + set("Access-Control-Expose-Headers", opts.exposeHeaders.join(",")); + } + if (c.req.method === "OPTIONS") { + if (opts.origin !== "*" || opts.credentials) { + set("Vary", "Origin"); + } + if (opts.maxAge != null) { + set("Access-Control-Max-Age", opts.maxAge.toString()); + } + const allowMethods = await findAllowMethods(c.req.header("origin") || "", c); + if (allowMethods.length) { + set("Access-Control-Allow-Methods", allowMethods.join(",")); + } + let headers = opts.allowHeaders; + if (!headers?.length) { + const requestHeaders = c.req.header("Access-Control-Request-Headers"); + if (requestHeaders) { + headers = requestHeaders.split(/\s*,\s*/); } - } else { - date3 = ""; } + if (headers?.length) { + set("Access-Control-Allow-Headers", headers.join(",")); + c.res.headers.append("Vary", "Access-Control-Request-Headers"); + } + c.res.headers.delete("Content-Length"); + c.res.headers.delete("Content-Type"); + return new Response(null, { + headers: c.res.headers, + status: 204, + statusText: "No Content" + }); } - super(date3); - if (!isNaN(this.getTime())) { - this.#hasDate = hasDate; - this.#hasTime = hasTime; - this.#offset = offset; + await next(); + if (opts.origin !== "*" || opts.credentials) { + c.header("Vary", "Origin", { append: true }); } + }; +}; +var RequestError = class extends Error { + constructor(message, options2) { + super(message, options2); + this.name = "RequestError"; } - isDateTime() { - return this.#hasDate && this.#hasTime; +}; +var toRequestError = (e2) => { + if (e2 instanceof RequestError) { + return e2; } - isLocal() { - return !this.#hasDate || !this.#hasTime || !this.#offset; + return new RequestError(e2.message, { cause: e2 }); +}; +var GlobalRequest = global.Request; +var Request2 = class extends GlobalRequest { + constructor(input, options2) { + if (typeof input === "object" && getRequestCache in input) { + input = input[getRequestCache](); + } + if (typeof options2?.body?.getReader !== "undefined") { + ; + options2.duplex ??= "half"; + } + super(input, options2); } - isDate() { - return this.#hasDate && !this.#hasTime; +}; +var newHeadersFromIncoming = (incoming) => { + const headerRecord = []; + const rawHeaders = incoming.rawHeaders; + for (let i2 = 0; i2 < rawHeaders.length; i2 += 2) { + const { [i2]: key, [i2 + 1]: value } = rawHeaders; + if (key.charCodeAt(0) !== /*:*/ + 58) { + headerRecord.push([key, value]); + } } - isTime() { - return this.#hasTime && !this.#hasDate; + return new Headers(headerRecord); +}; +var wrapBodyStream = Symbol("wrapBodyStream"); +var newRequestFromIncoming = (method, url2, headers, incoming, abortController) => { + const init2 = { + method, + headers, + signal: abortController.signal + }; + if (method === "TRACE") { + init2.method = "GET"; + const req = new Request2(url2, init2); + Object.defineProperty(req, "method", { + get() { + return "TRACE"; + } + }); + return req; } - isValid() { - return this.#hasDate || this.#hasTime; + if (!(method === "GET" || method === "HEAD")) { + if ("rawBody" in incoming && incoming.rawBody instanceof Buffer) { + init2.body = new ReadableStream({ + start(controller) { + controller.enqueue(incoming.rawBody); + controller.close(); + } + }); + } else if (incoming[wrapBodyStream]) { + let reader; + init2.body = new ReadableStream({ + async pull(controller) { + try { + reader ||= Readable2.toWeb(incoming).getReader(); + const { done, value } = await reader.read(); + if (done) { + controller.close(); + } else { + controller.enqueue(value); + } + } catch (error2) { + controller.error(error2); + } + } + }); + } else { + init2.body = Readable2.toWeb(incoming); + } } - toISOString() { - let iso = super.toISOString(); - if (this.isDate()) - return iso.slice(0, 10); - if (this.isTime()) - return iso.slice(11, 23); - if (this.#offset === null) - return iso.slice(0, -1); - if (this.#offset === "Z") - return iso; - let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6); - offset = this.#offset[0] === "-" ? offset : -offset; - let offsetDate = new Date(this.getTime() - offset * 6e4); - return offsetDate.toISOString().slice(0, -1) + this.#offset; + return new Request2(url2, init2); +}; +var getRequestCache = Symbol("getRequestCache"); +var requestCache = Symbol("requestCache"); +var incomingKey = Symbol("incomingKey"); +var urlKey = Symbol("urlKey"); +var headersKey = Symbol("headersKey"); +var abortControllerKey = Symbol("abortControllerKey"); +var getAbortController = Symbol("getAbortController"); +var requestPrototype = { + get method() { + return this[incomingKey].method || "GET"; + }, + get url() { + return this[urlKey]; + }, + get headers() { + return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]); + }, + [getAbortController]() { + this[getRequestCache](); + return this[abortControllerKey]; + }, + [getRequestCache]() { + this[abortControllerKey] ||= new AbortController(); + return this[requestCache] ||= newRequestFromIncoming( + this.method, + this[urlKey], + this.headers, + this[incomingKey], + this[abortControllerKey] + ); } - static wrapAsOffsetDateTime(jsDate, offset = "Z") { - let date3 = new _TomlDate(jsDate); - date3.#offset = offset; - return date3; +}; +[ + "body", + "bodyUsed", + "cache", + "credentials", + "destination", + "integrity", + "mode", + "redirect", + "referrer", + "referrerPolicy", + "signal", + "keepalive" +].forEach((k) => { + Object.defineProperty(requestPrototype, k, { + get() { + return this[getRequestCache]()[k]; + } + }); +}); +["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => { + Object.defineProperty(requestPrototype, k, { + value: function() { + return this[getRequestCache]()[k](); + } + }); +}); +Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom"), { + value: function(depth, options2, inspectFn) { + const props = { + method: this.method, + url: this.url, + headers: this.headers, + nativeRequest: this[requestCache] + }; + return `Request (lightweight) ${inspectFn(props, { ...options2, depth: depth == null ? null : depth - 1 })}`; } - static wrapAsLocalDateTime(jsDate) { - let date3 = new _TomlDate(jsDate); - date3.#offset = null; - return date3; +}); +Object.setPrototypeOf(requestPrototype, Request2.prototype); +var newRequest = (incoming, defaultHostname) => { + const req = Object.create(requestPrototype); + req[incomingKey] = incoming; + const incomingUrl = incoming.url || ""; + if (incomingUrl[0] !== "/" && // short-circuit for performance. most requests are relative URL. + (incomingUrl.startsWith("http://") || incomingUrl.startsWith("https://"))) { + if (incoming instanceof Http2ServerRequest) { + throw new RequestError("Absolute URL for :path is not allowed in HTTP/2"); + } + try { + const url22 = new URL(incomingUrl); + req[urlKey] = url22.href; + } catch (e2) { + throw new RequestError("Invalid absolute URL", { cause: e2 }); + } + return req; } - static wrapAsLocalDate(jsDate) { - let date3 = new _TomlDate(jsDate); - date3.#hasTime = false; - date3.#offset = null; - return date3; + const host = (incoming instanceof Http2ServerRequest ? incoming.authority : incoming.headers.host) || defaultHostname; + if (!host) { + throw new RequestError("Missing host header"); } - static wrapAsLocalTime(jsDate) { - let date3 = new _TomlDate(jsDate); - date3.#hasDate = false; - date3.#offset = null; - return date3; + let scheme; + if (incoming instanceof Http2ServerRequest) { + scheme = incoming.scheme; + if (!(scheme === "http" || scheme === "https")) { + throw new RequestError("Unsupported scheme"); + } + } else { + scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http"; } -}; -var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/; -var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/; -var LEADING_ZERO = /^[+-]?0[0-9_]/; -var ESCAPE_REGEX = /^[0-9a-f]{4,8}$/i; -var ESC_MAP = { - b: "\b", - t: " ", - n: "\n", - f: "\f", - r: "\r", - '"': '"', - "\\": "\\" -}; -function parseString(str, ptr = 0, endPtr = str.length) { - let isLiteral = str[ptr] === "'"; - let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1]; - if (isMultiline) { - endPtr -= 2; - if (str[ptr += 2] === "\r") - ptr++; - if (str[ptr] === "\n") - ptr++; + const url2 = new URL(`${scheme}://${host}${incomingUrl}`); + if (url2.hostname.length !== host.length && url2.hostname !== host.replace(/:\d+$/, "")) { + throw new RequestError("Invalid host header"); } - let tmp = 0; - let isEscape; - let parsed = ""; - let sliceStart = ptr; - while (ptr < endPtr - 1) { - let c = str[ptr++]; - if (c === "\n" || c === "\r" && str[ptr] === "\n") { - if (!isMultiline) { - throw new TomlError("newlines are not allowed in strings", { - toml: str, - ptr: ptr - 1 - }); - } - } else if (c < " " && c !== " " || c === "\x7F") { - throw new TomlError("control characters are not allowed in strings", { - toml: str, - ptr: ptr - 1 - }); - } - if (isEscape) { - isEscape = false; - if (c === "u" || c === "U") { - let code2 = str.slice(ptr, ptr += c === "u" ? 4 : 8); - if (!ESCAPE_REGEX.test(code2)) { - throw new TomlError("invalid unicode escape", { - toml: str, - ptr: tmp - }); - } - try { - parsed += String.fromCodePoint(parseInt(code2, 16)); - } catch { - throw new TomlError("invalid unicode escape", { - toml: str, - ptr: tmp - }); - } - } else if (isMultiline && (c === "\n" || c === " " || c === " " || c === "\r")) { - ptr = skipVoid(str, ptr - 1, true); - if (str[ptr] !== "\n" && str[ptr] !== "\r") { - throw new TomlError("invalid escape: only line-ending whitespace may be escaped", { - toml: str, - ptr: tmp - }); - } - ptr = skipVoid(str, ptr); - } else if (c in ESC_MAP) { - parsed += ESC_MAP[c]; + req[urlKey] = url2.href; + return req; +}; +var responseCache = Symbol("responseCache"); +var getResponseCache = Symbol("getResponseCache"); +var cacheKey = Symbol("cache"); +var GlobalResponse = global.Response; +var Response2 = class _Response { + #body; + #init; + [getResponseCache]() { + delete this[cacheKey]; + return this[responseCache] ||= new GlobalResponse(this.#body, this.#init); + } + constructor(body, init2) { + let headers; + this.#body = body; + if (init2 instanceof _Response) { + const cachedGlobalResponse = init2[responseCache]; + if (cachedGlobalResponse) { + this.#init = cachedGlobalResponse; + this[getResponseCache](); + return; } else { - throw new TomlError("unrecognized escape sequence", { - toml: str, - ptr: tmp - }); + this.#init = init2.#init; + headers = new Headers(init2.#init.headers); } - sliceStart = ptr; - } else if (!isLiteral && c === "\\") { - tmp = ptr - 1; - isEscape = true; - parsed += str.slice(sliceStart, tmp); - } - } - return parsed + str.slice(sliceStart, endPtr - 1); -} -function parseValue(value, toml, ptr, integersAsBigInt) { - if (value === "true") - return true; - if (value === "false") - return false; - if (value === "-inf") - return -Infinity; - if (value === "inf" || value === "+inf") - return Infinity; - if (value === "nan" || value === "+nan" || value === "-nan") - return NaN; - if (value === "-0") - return integersAsBigInt ? 0n : 0; - let isInt = INT_REGEX.test(value); - if (isInt || FLOAT_REGEX.test(value)) { - if (LEADING_ZERO.test(value)) { - throw new TomlError("leading zeroes are not allowed", { - toml, - ptr - }); - } - value = value.replace(/_/g, ""); - let numeric = +value; - if (isNaN(numeric)) { - throw new TomlError("invalid number", { - toml, - ptr - }); + } else { + this.#init = init2; } - if (isInt) { - if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) { - throw new TomlError("integer value cannot be represented losslessly", { - toml, - ptr - }); + if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) { + ; + this[cacheKey] = [init2?.status || 200, body, headers || init2?.headers]; + } + } + get headers() { + const cache2 = this[cacheKey]; + if (cache2) { + if (!(cache2[2] instanceof Headers)) { + cache2[2] = new Headers( + cache2[2] || { "content-type": "text/plain; charset=UTF-8" } + ); } - if (isInt || integersAsBigInt === true) - numeric = BigInt(value); + return cache2[2]; } - return numeric; + return this[getResponseCache]().headers; } - const date3 = new TomlDate(value); - if (!date3.isValid()) { - throw new TomlError("invalid value", { - toml, - ptr + get status() { + return this[cacheKey]?.[0] ?? this[getResponseCache]().status; + } + get ok() { + const status = this.status; + return status >= 200 && status < 300; + } +}; +["body", "bodyUsed", "redirected", "statusText", "trailers", "type", "url"].forEach((k) => { + Object.defineProperty(Response2.prototype, k, { + get() { + return this[getResponseCache]()[k]; + } + }); +}); +["arrayBuffer", "blob", "clone", "formData", "json", "text"].forEach((k) => { + Object.defineProperty(Response2.prototype, k, { + value: function() { + return this[getResponseCache]()[k](); + } + }); +}); +Object.defineProperty(Response2.prototype, Symbol.for("nodejs.util.inspect.custom"), { + value: function(depth, options2, inspectFn) { + const props = { + status: this.status, + headers: this.headers, + ok: this.ok, + nativeResponse: this[responseCache] + }; + return `Response (lightweight) ${inspectFn(props, { ...options2, depth: depth == null ? null : depth - 1 })}`; + } +}); +Object.setPrototypeOf(Response2, GlobalResponse); +Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype); +async function readWithoutBlocking(readPromise) { + return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(void 0))]); +} +function writeFromReadableStreamDefaultReader(reader, writable, currentReadPromise) { + const cancel = (error2) => { + reader.cancel(error2).catch(() => { }); + }; + writable.on("close", cancel); + writable.on("error", cancel); + (currentReadPromise ?? reader.read()).then(flow, handleStreamError); + return reader.closed.finally(() => { + writable.off("close", cancel); + writable.off("error", cancel); + }); + function handleStreamError(error2) { + if (error2) { + writable.destroy(error2); + } + } + function onDrain() { + reader.read().then(flow, handleStreamError); + } + function flow({ done, value }) { + try { + if (done) { + writable.end(); + } else if (!writable.write(value)) { + writable.once("drain", onDrain); + } else { + return reader.read().then(flow, handleStreamError); + } + } catch (e2) { + handleStreamError(e2); + } } - return date3; } -function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) { - let value = str.slice(startPtr, endPtr); - let commentIdx = value.indexOf("#"); - if (commentIdx > -1) { - skipComment(str, commentIdx); - value = value.slice(0, commentIdx); +function writeFromReadableStream(stream, writable) { + if (stream.locked) { + throw new TypeError("ReadableStream is locked."); + } else if (writable.destroyed) { + return; } - let trimmed = value.trimEnd(); - if (!allowNewLines) { - let newlineIdx = value.indexOf("\n", trimmed.length); - if (newlineIdx > -1) { - throw new TomlError("newlines are not allowed in inline tables", { - toml: str, - ptr: startPtr + newlineIdx - }); + return writeFromReadableStreamDefaultReader(stream.getReader(), writable); +} +var buildOutgoingHttpHeaders = (headers) => { + const res = {}; + if (!(headers instanceof Headers)) { + headers = new Headers(headers ?? void 0); + } + const cookies = []; + for (const [k, v2] of headers) { + if (k === "set-cookie") { + cookies.push(v2); + } else { + res[k] = v2; } } - return [trimmed, commentIdx]; + if (cookies.length > 0) { + res["set-cookie"] = cookies; + } + res["content-type"] ??= "text/plain; charset=UTF-8"; + return res; +}; +var X_ALREADY_SENT = "x-hono-already-sent"; +if (typeof global.crypto === "undefined") { + global.crypto = crypto2; } -function extractValue(str, ptr, end, depth, integersAsBigInt) { - if (depth === 0) { - throw new TomlError("document contains excessively nested structures. aborting.", { - toml: str, - ptr - }); +var outgoingEnded = Symbol("outgoingEnded"); +var incomingDraining = Symbol("incomingDraining"); +var DRAIN_TIMEOUT_MS = 500; +var MAX_DRAIN_BYTES = 64 * 1024 * 1024; +var drainIncoming = (incoming) => { + const incomingWithDrainState = incoming; + if (incoming.destroyed || incomingWithDrainState[incomingDraining]) { + return; } - let c = str[ptr]; - if (c === "[" || c === "{") { - let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt); - let newPtr = end ? skipUntil(str, endPtr2, ",", end) : endPtr2; - if (endPtr2 - newPtr && end === "}") { - let nextNewLine = indexOfNewline(str, endPtr2, newPtr); - if (nextNewLine > -1) { - throw new TomlError("newlines are not allowed in inline tables", { - toml: str, - ptr: nextNewLine - }); + incomingWithDrainState[incomingDraining] = true; + if (incoming instanceof Http2ServerRequest2) { + try { + ; + incoming.stream?.close?.(h2constants.NGHTTP2_NO_ERROR); + } catch { + } + return; + } + let bytesRead = 0; + const cleanup = () => { + clearTimeout(timer2); + incoming.off("data", onData); + incoming.off("end", cleanup); + incoming.off("error", cleanup); + }; + const forceClose = () => { + cleanup(); + const socket = incoming.socket; + if (socket && !socket.destroyed) { + socket.destroySoon(); + } + }; + const timer2 = setTimeout(forceClose, DRAIN_TIMEOUT_MS); + timer2.unref?.(); + const onData = (chunk) => { + bytesRead += chunk.length; + if (bytesRead > MAX_DRAIN_BYTES) { + forceClose(); + } + }; + incoming.on("data", onData); + incoming.on("end", cleanup); + incoming.on("error", cleanup); + incoming.resume(); +}; +var handleRequestError = () => new Response(null, { + status: 400 +}); +var handleFetchError = (e2) => new Response(null, { + status: e2 instanceof Error && (e2.name === "TimeoutError" || e2.constructor.name === "TimeoutError") ? 504 : 500 +}); +var handleResponseError = (e2, outgoing) => { + const err = e2 instanceof Error ? e2 : new Error("unknown error", { cause: e2 }); + if (err.code === "ERR_STREAM_PREMATURE_CLOSE") { + console.info("The user aborted a request."); + } else { + console.error(e2); + if (!outgoing.headersSent) { + outgoing.writeHead(500, { "Content-Type": "text/plain" }); + } + outgoing.end(`Error: ${err.message}`); + outgoing.destroy(err); + } +}; +var flushHeaders = (outgoing) => { + if ("flushHeaders" in outgoing && outgoing.writable) { + outgoing.flushHeaders(); + } +}; +var responseViaCache = async (res, outgoing) => { + let [status, body, header] = res[cacheKey]; + let hasContentLength = false; + if (!header) { + header = { "content-type": "text/plain; charset=UTF-8" }; + } else if (header instanceof Headers) { + hasContentLength = header.has("content-length"); + header = buildOutgoingHttpHeaders(header); + } else if (Array.isArray(header)) { + const headerObj = new Headers(header); + hasContentLength = headerObj.has("content-length"); + header = buildOutgoingHttpHeaders(headerObj); + } else { + for (const key in header) { + if (key.length === 14 && key.toLowerCase() === "content-length") { + hasContentLength = true; + break; } } - return [value, newPtr]; } - let endPtr; - if (c === '"' || c === "'") { - endPtr = getStringEnd(str, ptr); - let parsed = parseString(str, ptr, endPtr); - if (end) { - endPtr = skipVoid(str, endPtr, end !== "]"); - if (str[endPtr] && str[endPtr] !== "," && str[endPtr] !== end && str[endPtr] !== "\n" && str[endPtr] !== "\r") { - throw new TomlError("unexpected character encountered", { - toml: str, - ptr: endPtr + if (!hasContentLength) { + if (typeof body === "string") { + header["Content-Length"] = Buffer.byteLength(body); + } else if (body instanceof Uint8Array) { + header["Content-Length"] = body.byteLength; + } else if (body instanceof Blob) { + header["Content-Length"] = body.size; + } + } + outgoing.writeHead(status, header); + if (typeof body === "string" || body instanceof Uint8Array) { + outgoing.end(body); + } else if (body instanceof Blob) { + outgoing.end(new Uint8Array(await body.arrayBuffer())); + } else { + flushHeaders(outgoing); + await writeFromReadableStream(body, outgoing)?.catch( + (e2) => handleResponseError(e2, outgoing) + ); + } + ; + outgoing[outgoingEnded]?.(); +}; +var isPromise = (res) => typeof res.then === "function"; +var responseViaResponseObject = async (res, outgoing, options2 = {}) => { + if (isPromise(res)) { + if (options2.errorHandler) { + try { + res = await res; + } catch (err) { + const errRes = await options2.errorHandler(err); + if (!errRes) { + return; + } + res = errRes; + } + } else { + res = await res.catch(handleFetchError); + } + } + if (cacheKey in res) { + return responseViaCache(res, outgoing); + } + const resHeaderRecord = buildOutgoingHttpHeaders(res.headers); + if (res.body) { + const reader = res.body.getReader(); + const values = []; + let done = false; + let currentReadPromise = void 0; + if (resHeaderRecord["transfer-encoding"] !== "chunked") { + let maxReadCount = 2; + for (let i2 = 0; i2 < maxReadCount; i2++) { + currentReadPromise ||= reader.read(); + const chunk = await readWithoutBlocking(currentReadPromise).catch((e2) => { + console.error(e2); + done = true; }); + if (!chunk) { + if (i2 === 1) { + await new Promise((resolve82) => setTimeout(resolve82)); + maxReadCount = 3; + continue; + } + break; + } + currentReadPromise = void 0; + if (chunk.value) { + values.push(chunk.value); + } + if (chunk.done) { + done = true; + break; + } + } + if (done && !("content-length" in resHeaderRecord)) { + resHeaderRecord["content-length"] = values.reduce((acc, value) => acc + value.length, 0); } - endPtr += +(str[endPtr] === ","); } - return [parsed, endPtr]; - } - endPtr = skipUntil(str, ptr, ",", end); - let slice = sliceAndTrimEndOf(str, ptr, endPtr - +(str[endPtr - 1] === ","), end === "]"); - if (!slice[0]) { - throw new TomlError("incomplete key-value declaration: no value specified", { - toml: str, - ptr + outgoing.writeHead(res.status, resHeaderRecord); + values.forEach((value) => { + ; + outgoing.write(value); }); + if (done) { + outgoing.end(); + } else { + if (values.length === 0) { + flushHeaders(outgoing); + } + await writeFromReadableStreamDefaultReader(reader, outgoing, currentReadPromise); + } + } else if (resHeaderRecord[X_ALREADY_SENT]) { + } else { + outgoing.writeHead(res.status, resHeaderRecord); + outgoing.end(); } - if (end && slice[1] > -1) { - endPtr = skipVoid(str, ptr + slice[1]); - endPtr += +(str[endPtr] === ","); - } - return [ - parseValue(slice[0], str, ptr, integersAsBigInt), - endPtr - ]; -} -var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/; -function parseKey(str, ptr, end = "=") { - let dot = ptr - 1; - let parsed = []; - let endPtr = str.indexOf(end, ptr); - if (endPtr < 0) { - throw new TomlError("incomplete key-value: cannot find end of key", { - toml: str, - ptr + ; + outgoing[outgoingEnded]?.(); +}; +var getRequestListener = (fetchCallback, options2 = {}) => { + const autoCleanupIncoming = options2.autoCleanupIncoming ?? true; + if (options2.overrideGlobalObjects !== false && global.Request !== Request2) { + Object.defineProperty(global, "Request", { + value: Request2 + }); + Object.defineProperty(global, "Response", { + value: Response2 }); } - do { - let c = str[ptr = ++dot]; - if (c !== " " && c !== " ") { - if (c === '"' || c === "'") { - if (c === str[ptr + 1] && c === str[ptr + 2]) { - throw new TomlError("multiline strings are not allowed in keys", { - toml: str, - ptr - }); - } - let eos = getStringEnd(str, ptr); - if (eos < 0) { - throw new TomlError("unfinished string encountered", { - toml: str, - ptr - }); + return async (incoming, outgoing) => { + let res, req; + try { + req = newRequest(incoming, options2.hostname); + let incomingEnded = !autoCleanupIncoming || incoming.method === "GET" || incoming.method === "HEAD"; + if (!incomingEnded) { + ; + incoming[wrapBodyStream] = true; + incoming.on("end", () => { + incomingEnded = true; + }); + if (incoming instanceof Http2ServerRequest2) { + ; + outgoing[outgoingEnded] = () => { + if (!incomingEnded) { + setTimeout(() => { + if (!incomingEnded) { + setTimeout(() => { + drainIncoming(incoming); + }); + } + }); + } + }; } - dot = str.indexOf(".", eos); - let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot); - let newLine = indexOfNewline(strEnd); - if (newLine > -1) { - throw new TomlError("newlines are not allowed in keys", { - toml: str, - ptr: ptr + dot + newLine - }); + outgoing.on("finish", () => { + if (!incomingEnded) { + drainIncoming(incoming); + } + }); + } + outgoing.on("close", () => { + const abortController = req[abortControllerKey]; + if (abortController) { + if (incoming.errored) { + req[abortControllerKey].abort(incoming.errored.toString()); + } else if (!outgoing.writableFinished) { + req[abortControllerKey].abort("Client connection prematurely closed."); + } } - if (strEnd.trimStart()) { - throw new TomlError("found extra tokens after the string part", { - toml: str, - ptr: eos + if (!incomingEnded) { + setTimeout(() => { + if (!incomingEnded) { + setTimeout(() => { + drainIncoming(incoming); + }); + } }); } - if (endPtr < eos) { - endPtr = str.indexOf(end, eos); - if (endPtr < 0) { - throw new TomlError("incomplete key-value: cannot find end of key", { - toml: str, - ptr - }); + }); + res = fetchCallback(req, { incoming, outgoing }); + if (cacheKey in res) { + return responseViaCache(res, outgoing); + } + } catch (e2) { + if (!res) { + if (options2.errorHandler) { + res = await options2.errorHandler(req ? e2 : toRequestError(e2)); + if (!res) { + return; } + } else if (!req) { + res = handleRequestError(); + } else { + res = handleFetchError(e2); } - parsed.push(parseString(str, ptr, eos)); } else { - dot = str.indexOf(".", ptr); - let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot); - if (!KEY_PART_RE.test(part)) { - throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", { - toml: str, - ptr - }); - } - parsed.push(part.trimEnd()); + return handleResponseError(e2, outgoing); } } - } while (dot + 1 && dot < endPtr); - return [parsed, skipVoid(str, endPtr + 1, true, true)]; -} -function parseInlineTable(str, ptr, depth, integersAsBigInt) { - let res = {}; - let seen = /* @__PURE__ */ new Set(); - let c; - let comma = 0; - ptr++; - while ((c = str[ptr++]) !== "}" && c) { - let err = { toml: str, ptr: ptr - 1 }; - if (c === "\n") { - throw new TomlError("newlines are not allowed in inline tables", err); - } else if (c === "#") { - throw new TomlError("inline tables cannot contain comments", err); - } else if (c === ",") { - throw new TomlError("expected key-value, found comma", err); - } else if (c !== " " && c !== " ") { - let k; - let t = res; - let hasOwn = false; - let [key, keyEndPtr] = parseKey(str, ptr - 1); - for (let i2 = 0; i2 < key.length; i2++) { - if (i2) - t = hasOwn ? t[k] : t[k] = {}; - k = key[i2]; - if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) { - throw new TomlError("trying to redefine an already defined value", { - toml: str, - ptr + try { + return await responseViaResponseObject(res, outgoing, options2); + } catch (e2) { + return handleResponseError(e2, outgoing); + } + }; +}; +var createAdaptorServer = (options2) => { + const fetchCallback = options2.fetch; + const requestListener = getRequestListener(fetchCallback, { + hostname: options2.hostname, + overrideGlobalObjects: options2.overrideGlobalObjects, + autoCleanupIncoming: options2.autoCleanupIncoming + }); + const createServer2 = options2.createServer || createServerHTTP; + const server = createServer2(options2.serverOptions || {}, requestListener); + return server; +}; +init_esm7(); +init_esm(); +Object.defineProperties(Buffer13, { + [serdesDeserializeSymbol]: { + value(buf2) { + return Buffer13.from(buf2); + } + }, + [serdesSerializeSymbol]: { + value(buf2) { + return new Uint8Array(buf2.buffer, buf2.byteOffset, buf2.byteLength); + } + }, + [serdesTagSymbol]: { + value: "node:buffer" + } +}); +deserializer.register(Buffer13); +var createWorker = (path8) => { + let worker; + let ready; + const launchWorker = () => { + worker = new Worker(new URL(path8, import.meta.url), { type: "module" }); + return new Promise((resolve82, reject) => { + const msgHandler = (event) => { + const msg = event.data; + if (msg === "ready") { + worker.removeEventListener("error", reject, { capture: false }); + worker.addEventListener("error", (ev) => { + const e2 = ev.error; + console.error(e2, `Running worker ${basename52(path8)} terminated. Attempting relaunch...`); + worker.removeEventListener("message", msgHandler, false); + ready = launchWorker().catch((e3) => { + console.error(e3, `Error on worker ${basename52(path8)} relaunch`); + process5.exit(1); + }); + }, false); + resolve82(); + } else if (msg && typeof msg === "object" && msg.type === "sbp" && Array.isArray(msg.data) && String(msg.data[0]).startsWith("chelonia.db/")) { + const port = msg.port; + Promise.try(() => esm_default(...deserializer(msg.data))).then((r) => { + const { data, transferables } = serializer(r); + port.postMessage([true, data], transferables); + }).catch((e2) => { + const { data, transferables } = serializer(e2); + port.postMessage([false, data], transferables); + }).finally(() => { + port.close(); }); } - if (!hasOwn && k === "__proto__") { - Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true }); - } - } - if (hasOwn) { - throw new TomlError("trying to redefine an already defined value", { - toml: str, - ptr - }); - } - let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt); - seen.add(value); - t[k] = value; - ptr = valueEndPtr; - comma = str[ptr - 1] === "," ? ptr - 1 : 0; - } - } - if (comma) { - throw new TomlError("trailing commas are not allowed in inline tables", { - toml: str, - ptr: comma - }); - } - if (!c) { - throw new TomlError("unfinished table encountered", { - toml: str, - ptr + }; + worker.addEventListener("message", msgHandler, false); + worker.addEventListener("error", reject, { capture: false, once: true }); }); + }; + ready = launchWorker(); + const rpcSbp = (...args) => { + return ready.then(() => new Promise((resolve82, reject) => { + const mc = new MessageChannel(); + const cleanup = /* @__PURE__ */ ((worker2) => () => { + worker2.removeEventListener("error", reject, { capture: true }); + mc.port2.close(); + mc.port2.onmessage = null; + mc.port2.onmessageerror = null; + })(worker); + mc.port2.onmessage = (event) => { + cleanup(); + const [success, result] = event.data; + if (success) return resolve82(result); + reject(result); + }; + mc.port2.onmessageerror = () => { + cleanup(); + reject(new Error("Message error")); + }; + worker.postMessage([mc.port1, ...args], [mc.port1]); + worker.addEventListener("error", reject, { capture: false, once: true }); + })); + }; + return { + ready, + rpcSbp, + terminate: () => worker.terminate() + }; +}; +var createWorker_default = createWorker; +init_SPMessage(); +init_functions(); +var getConnInfo = (c) => { + const bindings = c.env.server ? c.env.server : c.env; + const address = bindings.incoming.socket.remoteAddress; + const port = bindings.incoming.socket.remotePort; + const family = bindings.incoming.socket.remoteFamily; + return { + remote: { + address, + port, + addressType: family === "IPv4" ? "IPv4" : family === "IPv6" ? "IPv6" : void 0 + } + }; +}; +init_esm(); +var import_npm_bottleneck = __toESM(require_lib6()); +var import_npm_chalk = __toESM(require_source()); +var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/; +var validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/; +var trimCookieWhitespace = (value) => { + let start = 0; + let end = value.length; + while (start < end) { + const charCode = value.charCodeAt(start); + if (charCode !== 32 && charCode !== 9) { + break; + } + start++; } - return [res, ptr]; -} -function parseArray(str, ptr, depth, integersAsBigInt) { - let res = []; - let c; - ptr++; - while ((c = str[ptr++]) !== "]" && c) { - if (c === ",") { - throw new TomlError("expected value, found comma", { - toml: str, - ptr: ptr - 1 - }); - } else if (c === "#") - ptr = skipComment(str, ptr); - else if (c !== " " && c !== " " && c !== "\n" && c !== "\r") { - let e2 = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt); - res.push(e2[0]); - ptr = e2[1]; + while (end > start) { + const charCode = value.charCodeAt(end - 1); + if (charCode !== 32 && charCode !== 9) { + break; } + end--; } - if (!c) { - throw new TomlError("unfinished array encountered", { - toml: str, - ptr - }); + return start === 0 && end === value.length ? value : value.slice(start, end); +}; +var parse42 = (cookie, name) => { + if (name && cookie.indexOf(name) === -1) { + return {}; } - return [res, ptr]; -} -function peekTable(key, table, meta, type) { - let t = table; - let m3 = meta; - let k; - let hasOwn = false; - let state; - for (let i2 = 0; i2 < key.length; i2++) { - if (i2) { - t = hasOwn ? t[k] : t[k] = {}; - m3 = (state = m3[k]).c; - if (type === 0 && (state.t === 1 || state.t === 2)) { - return null; - } - if (state.t === 2) { - let l = t.length - 1; - t = t[l]; - m3 = m3[l].c; - } + const pairs = cookie.split(";"); + const parsedCookie = {}; + for (const pairStr of pairs) { + const valueStartPos = pairStr.indexOf("="); + if (valueStartPos === -1) { + continue; } - k = key[i2]; - if ((hasOwn = Object.hasOwn(t, k)) && m3[k]?.t === 0 && m3[k]?.d) { - return null; + const cookieName = trimCookieWhitespace(pairStr.substring(0, valueStartPos)); + if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName)) { + continue; } - if (!hasOwn) { - if (k === "__proto__") { - Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true }); - Object.defineProperty(m3, k, { enumerable: true, configurable: true, writable: true }); + let cookieValue = trimCookieWhitespace(pairStr.substring(valueStartPos + 1)); + if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) { + cookieValue = cookieValue.slice(1, -1); + } + if (validCookieValueRegEx.test(cookieValue)) { + parsedCookie[cookieName] = cookieValue.indexOf("%") !== -1 ? tryDecode(cookieValue, decodeURIComponent_) : cookieValue; + if (name) { + break; } - m3[k] = { - t: i2 < key.length - 1 && type === 2 ? 3 : type, - d: false, - i: 0, - c: {} - }; } } - state = m3[k]; - if (state.t !== type && !(type === 1 && state.t === 3)) { - return null; - } - if (type === 2) { - if (!state.d) { - state.d = true; - t[k] = []; + return parsedCookie; +}; +var getCookie = (c, key, prefix) => { + const cookie = c.req.raw.headers.get("Cookie"); + if (typeof key === "string") { + if (!cookie) { + return void 0; } - t[k].push(t = {}); - state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} }; - } - if (state.d) { - return null; + let finalKey = key; + if (prefix === "secure") { + finalKey = "__Secure-" + key; + } else if (prefix === "host") { + finalKey = "__Host-" + key; + } + const obj2 = parse42(cookie, finalKey); + return obj2[finalKey]; } - state.d = true; - if (type === 1) { - t = hasOwn ? t[k] : t[k] = {}; - } else if (type === 0 && hasOwn) { - return null; + if (!cookie) { + return {}; } - return [k, t, state.c]; -} -function parse8(toml, { maxDepth = 1e3, integersAsBigInt } = {}) { - let res = {}; - let meta = {}; - let tbl = res; - let m3 = meta; - for (let ptr = skipVoid(toml, 0); ptr < toml.length; ) { - if (toml[ptr] === "[") { - let isTableArray = toml[++ptr] === "["; - let k = parseKey(toml, ptr += +isTableArray, "]"); - if (isTableArray) { - if (toml[k[1] - 1] !== "]") { - throw new TomlError("expected end of table declaration", { - toml, - ptr: k[1] - 1 - }); + const obj = parse42(cookie); + return obj; +}; +var bufferToFormData = (arrayBuffer, contentType) => { + const response = new Response(arrayBuffer, { + headers: { + "Content-Type": contentType + } + }); + return response.formData(); +}; +var jsonRegex = /^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/; +var multipartRegex = /^multipart\/form-data(;\s?boundary=[a-zA-Z0-9'"()+_,\-./:=?]+)?$/; +var urlencodedRegex = /^application\/x-www-form-urlencoded(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/; +var validator = (target, validationFunc) => { + return async (c, next) => { + let value = {}; + const contentType = c.req.header("Content-Type"); + switch (target) { + case "json": + if (!contentType || !jsonRegex.test(contentType)) { + break; } - k[1]++; - } - let p = peekTable( - k[0], - res, - meta, - isTableArray ? 2 : 1 - /* Type.EXPLICIT */ - ); - if (!p) { - throw new TomlError("trying to redefine an already defined table or value", { - toml, - ptr - }); - } - m3 = p[2]; - tbl = p[1]; - ptr = k[1]; - } else { - let k = parseKey(toml, ptr); - let p = peekTable( - k[0], - tbl, - m3, - 0 - /* Type.DOTTED */ - ); - if (!p) { - throw new TomlError("trying to redefine an already defined table or value", { - toml, - ptr + try { + value = await c.req.json(); + } catch { + const message = "Malformed JSON in request body"; + throw new HTTPException(400, { message }); + } + break; + case "form": { + if (!contentType || !(multipartRegex.test(contentType) || urlencodedRegex.test(contentType))) { + break; + } + let formData; + if (c.req.bodyCache.formData) { + formData = await c.req.bodyCache.formData; + } else { + try { + const arrayBuffer = await c.req.arrayBuffer(); + formData = await bufferToFormData(arrayBuffer, contentType); + c.req.bodyCache.formData = formData; + } catch (e2) { + let message = "Malformed FormData request."; + message += e2 instanceof Error ? ` ${e2.message}` : ` ${String(e2)}`; + throw new HTTPException(400, { message }); + } + } + const form = /* @__PURE__ */ Object.create(null); + formData.forEach((value2, key) => { + if (key.endsWith("[]")) { + ; + (form[key] ??= []).push(value2); + } else if (Array.isArray(form[key])) { + ; + form[key].push(value2); + } else if (Object.hasOwn(form, key)) { + form[key] = [form[key], value2]; + } else { + form[key] = value2; + } }); + value = form; + break; } - let v2 = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt); - p[1][p[0]] = v2[0]; - ptr = v2[1]; + case "query": + value = Object.fromEntries( + Object.entries(c.req.queries()).map(([k, v2]) => { + return v2.length === 1 ? [k, v2[0]] : [k, v2]; + }) + ); + break; + case "param": + value = c.req.param(); + break; + case "header": + value = c.req.header(); + break; + case "cookie": + value = getCookie(c); + break; + } + const res = await validationFunc(value, c); + if (res instanceof Response) { + return res; + } + c.req.addValidatedData(target, res); + return await next(); + }; +}; +function zValidatorFunction(target, schema, hook, options2) { + return validator(target, async (value, c) => { + let validatorValue = value; + if (target === "header" && "_def" in schema || target === "header" && "_zod" in schema) { + const schemaKeys = Object.keys("in" in schema ? schema.in.shape : schema.shape); + const caseInsensitiveKeymap = Object.fromEntries(schemaKeys.map((key) => [key.toLowerCase(), key])); + validatorValue = Object.fromEntries(Object.entries(value).map(([key, value$1]) => [caseInsensitiveKeymap[key] || key, value$1])); + } + const result = options2 && options2.validationFunction ? await options2.validationFunction(schema, validatorValue) : await schema.safeParseAsync(validatorValue); + if (hook) { + const hookResult = await hook({ + data: validatorValue, + ...result, + target + }, c); + if (hookResult) { + if (hookResult instanceof Response) return hookResult; + if ("response" in hookResult) return hookResult.response; + } + } + if (!result.success) return c.json(result, 400); + return result.data; + }); +} +var zValidator = zValidatorFunction; +var ERROR_MESSAGE = "Payload Too Large"; +var BodyLimitError = class extends Error { + constructor(message) { + super(message); + this.name = "BodyLimitError"; + } +}; +var bodyLimit = (options2) => { + const onError = options2.onError || (() => { + const res = new Response(ERROR_MESSAGE, { + status: 413 + }); + throw new HTTPException(413, { res }); + }); + const maxSize = options2.maxSize; + return async function bodyLimit2(c, next) { + if (!c.req.raw.body) { + return next(); + } + const hasTransferEncoding = c.req.raw.headers.has("transfer-encoding"); + const hasContentLength = c.req.raw.headers.has("content-length"); + if (hasTransferEncoding && hasContentLength) { + } + if (hasContentLength && !hasTransferEncoding) { + const contentLength = parseInt(c.req.raw.headers.get("content-length") || "0", 10); + return contentLength > maxSize ? onError(c) : next(); + } + let size = 0; + const rawReader = c.req.raw.body.getReader(); + const reader = new ReadableStream({ + async start(controller) { + try { + for (; ; ) { + const { done, value } = await rawReader.read(); + if (done) { + break; + } + size += value.length; + if (size > maxSize) { + controller.error(new BodyLimitError(ERROR_MESSAGE)); + break; + } + controller.enqueue(value); + } + } finally { + controller.close(); + } + } + }); + const requestInit = { body: reader, duplex: "half" }; + c.req.raw = new Request(c.req.raw, requestInit); + await next(); + if (c.error instanceof BodyLimitError) { + c.res = await onError(c); } - ptr = skipVoid(toml, ptr, true); - if (toml[ptr] && toml[ptr] !== "\n" && toml[ptr] !== "\r") { - throw new TomlError("each key-value declaration must be followed by an end-of-line", { - toml, - ptr - }); + }; +}; +var import_npm_pino = __toESM(require_pino()); +var prettyPrint = process6.env.NODE_ENV === "development" || process6.env.CI || process6.env.CYPRESS_RECORD_KEY || process6.env.PRETTY; +function logMethod(args, method) { + const stringIdx = typeof args[0] === "string" ? 0 : 1; + if (args.length > 1) { + for (let i2 = stringIdx + 1; i2 < args.length; ++i2) { + args[stringIdx] += typeof args[i2] === "string" ? " %s" : " %o"; } - ptr = skipVoid(toml, ptr); } - return res; + method.apply(this, args); } -var BARE_KEY = /^[a-z0-9-_]+$/i; -function extendedTypeOf(obj) { - let type = typeof obj; - if (type === "object") { - if (Array.isArray(obj)) - return "array"; - if (obj instanceof Date) - return "date"; +var logger; +if (prettyPrint) { + try { + logger = (0, import_npm_pino.default)({ + hooks: { logMethod }, + transport: { + target: "pino-pretty", + options: { + colorize: true + } + } + }); + } catch (e2) { + console.warn("pino-pretty transport unavailable, using basic logging", e2); + logger = (0, import_npm_pino.default)({ hooks: { logMethod } }); } - return type; +} else { + logger = (0, import_npm_pino.default)({ hooks: { logMethod } }); } -function isArrayOfTables(obj) { - for (let i2 = 0; i2 < obj.length; i2++) { - if (extendedTypeOf(obj[i2]) !== "object") - return false; - } - return obj.length != 0; +var logLevel = process6.env.LOG_LEVEL || (prettyPrint ? "debug" : "info"); +if (Object.keys(logger.levels.values).includes(logLevel)) { + logger.level = logLevel; +} else { + logger.warn(`Unknown log level: ${logLevel}`); } -function formatString(s) { - return JSON.stringify(s).replace(/\x7f/g, "\\u007f"); +var loggerInitialized = false; +function initializeLogger() { + if (loggerInitialized) return; + loggerInitialized = true; + console.debug = logger.debug.bind(logger); + console.info = logger.info.bind(logger); + console.log = logger.info.bind(logger); + console.warn = logger.warn.bind(logger); + console.error = logger.error.bind(logger); } -function stringifyValue(val, type, depth, numberAsFloat) { - if (depth === 0) { - throw new Error("Could not stringify the object: maximum object depth exceeded"); - } - if (type === "number") { - if (isNaN(val)) - return "nan"; - if (val === Infinity) - return "inf"; - if (val === -Infinity) - return "-inf"; - if (numberAsFloat && Number.isInteger(val)) - return val.toFixed(1); - return val.toString(); - } - if (type === "bigint" || type === "boolean") { - return val.toString(); - } - if (type === "string") { - return formatString(val); - } - if (type === "date") { - if (isNaN(val.getTime())) { - throw new TypeError("cannot serialize invalid date"); - } - return val.toISOString(); - } - if (type === "object") { - return stringifyInlineTable(val, depth, numberAsFloat); - } - if (type === "array") { - return stringifyArray(val, depth, numberAsFloat); - } +var logger_default = logger; +var import_npm_nconf4 = __toESM(require_nconf()); +init_zod(); +function extractBearer(c) { + const authorization = c.req.header("authorization"); + if (!authorization) return null; + const prefix = "bearer "; + if (authorization.slice(0, prefix.length).toLowerCase() !== prefix) return null; + return { token: authorization.slice(prefix.length) }; } -function stringifyInlineTable(obj, depth, numberAsFloat) { - let keys = Object.keys(obj); - if (keys.length === 0) - return "{}"; - let res = "{ "; - for (let i2 = 0; i2 < keys.length; i2++) { - let k = keys[i2]; - if (i2) - res += ", "; - res += BARE_KEY.test(k) ? k : formatString(k); - res += " = "; - res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat); +function extractShelter(c) { + const authorization = c.req.header("authorization"); + if (!authorization) return null; + const prefix = "shelter "; + if (authorization.slice(0, prefix.length).toLowerCase() !== prefix) return null; + try { + const billableContractID = verifyShelterAuthorizationHeader(authorization); + return { billableContractID }; + } catch (e2) { + console.warn(e2, "Shelter authorization failed"); + return null; } - return res + " }"; } -function stringifyArray(array2, depth, numberAsFloat) { - if (array2.length === 0) - return "[]"; - let res = "[ "; - for (let i2 = 0; i2 < array2.length; i2++) { - if (i2) - res += ", "; - if (array2[i2] === null || array2[i2] === void 0) { - throw new TypeError("arrays cannot contain null or undefined values"); +var extractors = { + "chel-bearer": extractBearer, + "chel-shelter": extractShelter +}; +function authMiddleware(strategies, mode = "required") { + const strategyList = Array.isArray(strategies) ? strategies : [strategies]; + return async (c, next) => { + for (const strategy of strategyList) { + const extractor = extractors[strategy]; + if (!extractor) throw new Error(`Unknown auth strategy: ${strategy}`); + const credentials = extractor(c); + if (credentials) { + c.set("credentials", credentials); + c.set("authStrategy", strategy); + return next(); + } } - res += stringifyValue(array2[i2], extendedTypeOf(array2[i2]), depth - 1, numberAsFloat); - } - return res + " ]"; + if (mode === "optional") { + c.set("credentials", {}); + c.set("authStrategy", ""); + return next(); + } + throw new HTTPException(401, { message: "Unauthorized" }); + }; } -function stringifyArrayTable(array2, key, depth, numberAsFloat) { - if (depth === 0) { - throw new Error("Could not stringify the object: maximum object depth exceeded"); - } - let res = ""; - for (let i2 = 0; i2 < array2.length; i2++) { - res += `[[${key}]] -`; - res += stringifyTable(array2[i2], key, depth, numberAsFloat); - res += "\n\n"; - } - return res; +var MEGABYTE = 1048576; +var SECOND = 1e3; +var CID_REGEX = /^z[1-9A-HJ-NP-Za-km-z]{8,72}$/; +var KV_KEY_REGEX = /^(?!_private)[^\x00]{1,256}$/; +var NAME_REGEX = /^(?![_-])((?!([_-])\2)[a-z\d_-]){1,80}(? { + const contentType = (c.req.header("content-type") || "").trim().toLowerCase(); + let data; + try { + if (contentType.startsWith("application/x-www-form-urlencoded")) { + const form = await c.req.parseBody(); + data = Object.fromEntries( + Object.entries(form).filter(([, v2]) => typeof v2 === "string") + ); + } else if (contentType.startsWith("application/json")) { + data = await c.req.json(); + } else { + throw new HTTPException(415, { message: "Content-Type header expected with form or JSON data" }); + } + } catch (e2) { + if (e2 instanceof HTTPException) throw e2; + throw new HTTPException(400, { message: "Invalid request body" }); + } + const result = schema.safeParse(data); + if (!result.success) { + throw new HTTPException(400, { message: "Invalid request body" }); + } + c.set("validatedBody", result.data); + return next(); + }; } -function stringifyTable(obj, prefix, depth, numberAsFloat) { - if (depth === 0) { - throw new Error("Could not stringify the object: maximum object depth exceeded"); - } - let preamble = ""; - let tables = ""; - let keys = Object.keys(obj); - for (let i2 = 0; i2 < keys.length; i2++) { - let k = keys[i2]; - if (obj[k] !== null && obj[k] !== void 0) { - let type = extendedTypeOf(obj[k]); - if (type === "symbol" || type === "function") { - throw new TypeError(`cannot serialize values of type '${type}'`); +var cidLookupTable = { + [multicodes.SHELTER_CONTRACT_MANIFEST]: "application/vnd.shelter.contractmanifest+json", + [multicodes.SHELTER_CONTRACT_TEXT]: "application/vnd.shelter.contracttext", + [multicodes.SHELTER_CONTRACT_DATA]: "application/vnd.shelter.contractdata+json", + [multicodes.SHELTER_FILE_MANIFEST]: "application/vnd.shelter.filemanifest+json", + [multicodes.SHELTER_FILE_CHUNK]: "application/vnd.shelter.filechunk+octet-stream" +}; +var limiterKey = (ip) => { + const ipVersion = isIP(ip); + if (ipVersion === 4) { + return ip; + } else if (ipVersion === 6) { + const [address, zoneIdx] = ip.split("%"); + const segments = address.split(":"); + let isCompressed = false; + for (let i2 = 0; i2 < segments.length - 1; i2++) { + if (!isCompressed && segments[i2] === "") { + const requiredSegments = 8 - (segments.length - 1); + if (requiredSegments < 0) { + throw new Error("Invalid IPv6 address: too many segments"); + } + if ((i2 === 0 || i2 === segments.length - 2) && segments[i2 + 1] === "") { + segments[i2 + 1] = "0"; + } + if (i2 === 0 && segments.length === 3 && segments[i2 + 2] === "") { + segments[i2 + 2] = "0"; + } + segments.splice(i2, 1, ...new Array(requiredSegments).fill("0")); + isCompressed = true; + continue; } - let key = BARE_KEY.test(k) ? k : formatString(k); - if (type === "array" && isArrayOfTables(obj[k])) { - tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat); - } else if (type === "object") { - let tblKey = prefix ? `${prefix}.${key}` : key; - tables += `[${tblKey}] -`; - tables += stringifyTable(obj[k], tblKey, depth - 1, numberAsFloat); - tables += "\n\n"; + segments[i2] = segments[i2].replace(/^0+/, "0"); + } + if (segments.length === 8 && isIP(segments[7]) === 4) { + return segments[7]; + } else if (segments.length === 8) { + if (zoneIdx) { + segments[7] = segments[7].replace(/^0+/, "0"); + return segments.join(":").toLowerCase() + "%" + zoneIdx; } else { - preamble += key; - preamble += " = "; - preamble += stringifyValue(obj[k], type, depth, numberAsFloat); - preamble += "\n"; + return segments.slice(0, 4).join(":").toLowerCase() + "::"; } + } else { + throw new Error("Invalid IPv6 address"); } } - return `${preamble} -${tables}`.trim(); -} -function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) { - if (extendedTypeOf(obj) !== "object") { - throw new TypeError("stringify can only be called with an object"); + throw new Error("Invalid address format"); +}; +var ctEq = (expected, actual) => { + let r = actual.length ^ expected.length; + for (let i2 = 0; i2 < actual.length; i2++) { + r |= actual.codePointAt(i2) ^ expected.codePointAt(i2); } - return stringifyTable(obj, "", maxDepth, numbersAsFloat); + return r === 0; +}; +var currentLimiters = []; +var rateLimitersInstalled = false; +function installRateLimiterSelectorsOnce() { + if (rateLimitersInstalled) return; + rateLimitersInstalled = true; + esm_default("sbp/selectors/register", { + "backend/server/stopRateLimiters": async function() { + const limiters = currentLimiters; + await Promise.allSettled(limiters.map((l) => l.disconnect())); + for (const limiter of limiters) { + clearInterval(limiter.interval); + } + } + }); } -var commands_exports = {}; -__export(commands_exports, { - deploy: () => module3, - eventsAfter: () => module4, - get: () => module5, - hash: () => module6, - keygen: () => module7, - manifest: () => module8, - migrate: () => module9, - pin: () => module10, - serve: () => module11, - upload: () => module2, - verifySignature: () => module12, - version: () => module13 -}); -init_zod(); -init_functions(); -init_esm(); -init_database(); -init_functions(); -async function createEntryFromFile(filepath, multicode) { - const buffer = await Deno.readFile(filepath); - const key = createCID(buffer, multicode); - return [key, buffer]; +function getStaticServeConfig() { + const isCheloniaDashboard = process7.env.IS_CHELONIA_DASHBOARD_DEV; + const appDir = import_npm_nconf4.default.get("server:appDir") || "."; + const dashboardDir = import.meta.dirname || "./build/dist-dashboard"; + return { + distAssets: path5.resolve(path5.join(isCheloniaDashboard ? dashboardDir : appDir, "assets")), + distIndexHtml: path5.resolve(path5.join(isCheloniaDashboard ? dashboardDir : appDir, "index.html")), + redirect: isCheloniaDashboard ? "/dashboard/" : "/app/" + }; } -function exit(x3, internal = false) { - const msg = x3 instanceof Error ? x3.message : String(x3); - if (internal) throw new Error(msg); - console.error("[chel]", red("Error:"), msg); - Deno.exit(1); +var errorMapper = (e2) => { + switch (e2?.name) { + case "BackendErrorNotFound": + return new HTTPException(404); + case "BackendErrorGone": + return new HTTPException(410); + case "BackendErrorBadData": + return new HTTPException(422, { message: e2.message }); + default: + console.error(e2, "Unexpected backend error"); + return new HTTPException(500, { message: e2.message ?? "internal error" }); + } +}; +function getClientIP(c) { + const headerIP = c.req.header("x-real-ip"); + if (headerIP) return headerIP; + try { + const info = getConnInfo(c); + return info.remote.address || "unknown"; + } catch { + return "unknown"; + } } -function isValidKey(key) { - return !/[\x00-\x1f\x7f\t\\/]/.test(key); +function notFoundNoCache(c) { + return c.body(null, 404, { "Cache-Control": "no-store" }); } -async function readRemoteData(src2, key) { - const buffer = await fetch(`${src2}/file/${key}`).then(async (r) => r.ok ? await r.arrayBuffer() : await Promise.reject(new Error(`failed network request to ${src2}: ${r.status} - ${r.statusText}`))); - return new Uint8Array(buffer); +function safePathWithin(base2, subpath) { + const resolved = path5.resolve(base2, subpath); + if (!resolved.startsWith(base2 + path5.sep) && resolved !== base2) return null; + return resolved; } -async function revokeNet() { - await Deno.permissions.revoke({ name: "net" }); +function serveAsset(c, subpath, assetsDir) { + const basename72 = path5.basename(subpath); + const filePath = safePathWithin(assetsDir, subpath); + if (!filePath) return Promise.resolve(notFoundNoCache(c)); + return Deno.readFile(filePath).then((file) => { + const headers = {}; + if (basename72.includes("-cached")) { + headers["ETag"] = `"${basename72}"`; + headers["Cache-Control"] = "public,max-age=31536000,immutable"; + } + if (subpath.includes("js/sw-")) { + console.debug("adding header: Service-Worker-Allowed /"); + headers["Service-Worker-Allowed"] = "/"; + } + const ext = path5.extname(subpath).toLowerCase(); + headers["Content-Type"] = MIME_TYPES[ext] || "application/octet-stream"; + return c.body(file, 200, headers); + }).catch(() => notFoundNoCache(c)); } -var readJsonFile = async (file) => { - const contents = await Deno.readTextFile(resolve8(String(file))); - return JSON.parse(contents); -}; -var findManifestFiles = async (path8) => { - const visited = /* @__PURE__ */ new Set(); - const internal = async (path9) => { - if (visited.has(path9)) { - return /* @__PURE__ */ new Set(); +function registerRoutes(app) { + for (const limiter of currentLimiters) { + limiter.disconnect(); + clearInterval(limiter.interval); + } + const FILE_UPLOAD_MAX_BYTES = import_npm_nconf4.default.get("server:fileUploadMaxBytes") || 30 * MEGABYTE; + const SIGNUP_LIMIT_MIN = import_npm_nconf4.default.get("server:signup:limit:minute") || 2; + const SIGNUP_LIMIT_HOUR = import_npm_nconf4.default.get("server:signup:limit:hour") || 10; + const SIGNUP_LIMIT_DAY = import_npm_nconf4.default.get("server:signup:limit:day") || 50; + const SIGNUP_LIMIT_DISABLED = process7.env.NODE_ENV !== "production" || import_npm_nconf4.default.get("server:signup:limit:disabled"); + const ARCHIVE_MODE = import_npm_nconf4.default.get("server:archiveMode"); + const limiterPerMinute = new import_npm_bottleneck.default.Group({ + strategy: import_npm_bottleneck.default.strategy.LEAK, + highWater: 0, + reservoir: SIGNUP_LIMIT_MIN, + reservoirRefreshInterval: 60 * SECOND, + reservoirRefreshAmount: SIGNUP_LIMIT_MIN + }); + const limiterPerHour = new import_npm_bottleneck.default.Group({ + strategy: import_npm_bottleneck.default.strategy.LEAK, + highWater: 0, + reservoir: SIGNUP_LIMIT_HOUR, + reservoirRefreshInterval: 60 * 60 * SECOND, + reservoirRefreshAmount: SIGNUP_LIMIT_HOUR + }); + const limiterPerDay = new import_npm_bottleneck.default.Group({ + strategy: import_npm_bottleneck.default.strategy.LEAK, + highWater: 0, + reservoir: SIGNUP_LIMIT_DAY, + reservoirRefreshInterval: 24 * 60 * 60 * SECOND, + reservoirRefreshAmount: SIGNUP_LIMIT_DAY + }); + currentLimiters = [limiterPerMinute, limiterPerHour, limiterPerDay]; + installRateLimiterSelectorsOnce(); + const isCheloniaDashboard = process7.env.IS_CHELONIA_DASHBOARD_DEV; + const staticServeConfig = getStaticServeConfig(); + app.post( + "/event", + zValidator("header", object({ + "shelter-namespace-registration": nameSchema.optional(), + "shelter-salt-update-token": string2().optional(), + "shelter-salt-registration-token": string2().optional(), + "shelter-deletion-token-digest": string2().optional() + })), + bodyLimit({ maxSize: MEGABYTE }), + authMiddleware("chel-shelter", "optional"), + async function(c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + const ip = getClientIP(c); + try { + const contentType = c.req.header("content-type"); + if (contentType && !contentType.toLowerCase().startsWith("application/json")) { + throw new HTTPException(415, { message: "Expected JSON body" }); + } + const payload = await c.req.text(); + const validatedHeaders = c.req.valid("header"); + if (!payload) throw new HTTPException(400, { message: "Invalid request payload input" }); + const deserializedHEAD = SPMessage.deserializeHEAD(payload); + try { + const parsed = maybeParseCID(deserializedHEAD.head.manifest); + if (parsed?.code !== multicodes.SHELTER_CONTRACT_MANIFEST) { + throw new HTTPException(422, { message: "Invalid manifest" }); + } + const credentials = c.get("credentials"); + if (!credentials?.billableContractID && deserializedHEAD.isFirstMessage) { + const manifest2 = await esm_default("chelonia.db/get", deserializedHEAD.head.manifest); + const parsedManifest = JSON.parse(manifest2); + const { name } = JSON.parse(parsedManifest.body); + if (name !== "gi.contracts/identity") { + throw new HTTPException(401, { message: "This contract type requires ownership information" }); + } + if (import_npm_nconf4.default.get("server:signup:disabled")) { + throw new HTTPException(403, { message: "Registration disabled" }); + } + if (!SIGNUP_LIMIT_DISABLED) { + try { + const keyedIp = limiterKey(ip); + await limiterPerMinute.key(keyedIp).schedule(() => Promise.resolve()); + await limiterPerHour.key(keyedIp).schedule(() => Promise.resolve()); + await limiterPerDay.key(keyedIp).schedule(() => Promise.resolve()); + } catch { + console.warn("rate limit hit for IP:", ip); + throw new HTTPException(429, { message: "Rate limit exceeded" }); + } + } + } + const saltUpdateToken = validatedHeaders["shelter-salt-update-token"]; + let updateSalts; + if (saltUpdateToken) { + updateSalts = await redeemSaltUpdateToken(deserializedHEAD.contractID, saltUpdateToken); + } + await esm_default("backend/server/handleEntry", deserializedHEAD, payload); + await updateSalts?.(deserializedHEAD.hash); + if (deserializedHEAD.isFirstMessage) { + if (credentials?.billableContractID) { + await esm_default("backend/server/saveOwner", credentials.billableContractID, deserializedHEAD.contractID); + } else { + await esm_default("backend/server/registerBillableEntity", deserializedHEAD.contractID); + } + const name = validatedHeaders["shelter-namespace-registration"]; + if (name) { + const cheloniaState = esm_default("chelonia/rootState"); + if (cheloniaState.contracts[deserializedHEAD.contractID]?.type === "gi.contracts/identity") { + try { + await esm_default("backend/db/registerName", name, deserializedHEAD.contractID); + } catch (registerErr) { + if (registerErr.name === "BackendErrorConflict") { + throw new HTTPException(409, { message: "Name already exists" }); + } + throw registerErr; + } + const saltRegistrationToken = validatedHeaders["shelter-salt-registration-token"]; + console.info(`new user: ${name}=${deserializedHEAD.contractID} (${ip})`); + if (saltRegistrationToken) { + await redeemSaltRegistrationToken(name, deserializedHEAD.contractID, saltRegistrationToken); + } + } + } + const deletionTokenDgst = validatedHeaders["shelter-deletion-token-digest"]; + if (deletionTokenDgst) { + await esm_default("chelonia.db/set", `_private_deletionTokenDgst_${deserializedHEAD.contractID}`, deletionTokenDgst); + } + } + await esm_default("backend/server/updateSize", deserializedHEAD.contractID, Buffer14.byteLength(payload), deserializedHEAD.isFirstMessage && !credentials?.billableContractID ? deserializedHEAD.contractID : void 0); + } catch (err) { + if (err instanceof HTTPException) throw err; + console.error(err, import_npm_chalk.default.bold.yellow(err.name)); + if (err.name === "ChelErrorDBBadPreviousHEAD" || err.name === "ChelErrorAlreadyProcessed") { + const HEADinfo = await esm_default("chelonia/db/latestHEADinfo", deserializedHEAD.contractID) ?? { HEAD: null, height: 0 }; + return c.json({ message: err.message, data: { HEADinfo } }, 409, { + "shelter-headinfo-head": HEADinfo.HEAD, + "shelter-headinfo-height": String(HEADinfo.height) + }); + } else if (err.name === "ChelErrorSignatureError") { + throw new HTTPException(422, { message: "Invalid signature" }); + } else if (err.name === "ChelErrorSignatureKeyUnauthorized") { + throw new HTTPException(403, { message: "Unauthorized signing key" }); + } + throw err; + } + return c.text(deserializedHEAD.hash); + } catch (err) { + if (err instanceof HTTPException) throw err; + err.ip = ip; + logger_default.error(err, "POST /event", err.message); + throw err; + } } - visited.add(path9); - const entries = Deno.readDir(path9); - const manifests = /* @__PURE__ */ new Set(); - for await (const entry of entries) { - const realPath2 = await Deno.realPath(join32(path9, entry.name)); - const info = await Deno.lstat(realPath2); - if (info.isDirectory) { - const subitems = await internal(realPath2); - for (const item of subitems) { - manifests.add(item); + ); + app.get( + "/eventsAfter/:contractID/:since/:limit?", + zValidator("param", object({ + contractID: cidSchema, + since: nonNegativeIntegerSchema, + limit: nonNegativeIntegerSchema.optional() + }).strict()), + zValidator("query", object({ + keyOps: stringbool().optional() + }).strict()), + async function(c) { + const { contractID, since, limit } = c.req.valid("param"); + const keyOps2 = c.req.valid("query").keyOps; + const ip = getClientIP(c); + try { + const parsed = maybeParseCID(contractID); + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { + throw new HTTPException(400); + } + const stream = await esm_default("backend/db/streamEntriesAfter", contractID, Number(since), limit == null ? void 0 : Number(limit), { keyOps: keyOps2 }); + stream.on("error", (err) => logger_default.error("eventsAfter stream error", err)); + c.req.raw.signal.addEventListener("abort", () => stream.destroy()); + const streamHeaders = stream.headers || {}; + const webStream = Readable3.toWeb(stream); + return new Response(webStream, { + headers: { "content-type": "application/json", ...streamHeaders } + }); + } catch (err) { + if (err instanceof HTTPException) throw err; + err.ip = ip; + logger_default.error(err, `GET /eventsAfter/${contractID}/${since}`, err.message); + throw errorMapper(err); + } + } + ); + app.get( + "/ownResources", + authMiddleware("chel-shelter", "required"), + async function(c) { + const billableContractID = c.get("credentials").billableContractID; + const resources = (await esm_default("chelonia.db/get", `_private_resources_${billableContractID}`))?.split("\0"); + return c.json(resources || []); + } + ); + if (process7.env.NODE_ENV === "development") { + const levelToColor = { + error: import_npm_chalk.default.bold.red, + warn: import_npm_chalk.default.yellow, + log: import_npm_chalk.default.green, + info: import_npm_chalk.default.green, + debug: import_npm_chalk.default.blue + }; + app.post("/log", async function(c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + const body = await c.req.json(); + if (!body.level || !body.value) throw new HTTPException(400, { message: "level and value are required" }); + const ip = getClientIP(c); + const log2 = levelToColor[body.level]; + console.debug(import_npm_chalk.default.bold.yellow(`REMOTE LOG (${ip}): `) + log2(`[${body.level}] ${body.value}`)); + return c.body(null, 200); + }); + } + app.get( + "/name/:name", + zValidator("param", object({ name: nameSchema }).strict()), + async function(c) { + const { name } = c.req.valid("param"); + try { + const lookupResult = await esm_default("backend/db/lookupName", name); + return lookupResult ? c.text(lookupResult) : notFoundNoCache(c); + } catch (err) { + logger_default.error(err, `GET /name/${name}`, err.message); + throw err; + } + } + ); + app.get( + "/latestHEADinfo/:contractID", + zValidator("param", object({ contractID: cidSchema }).strict()), + async function(c) { + const { contractID } = c.req.valid("param"); + try { + const parsed = maybeParseCID(contractID); + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) throw new HTTPException(400); + const HEADinfo = await esm_default("chelonia/db/latestHEADinfo", contractID); + if (HEADinfo === "") { + throw new HTTPException(410); } - } else if (entry.name.toLowerCase().endsWith(".manifest.json")) { - manifests.add(join32(path9, entry.name)); + if (!HEADinfo) { + console.warn(`[backend] latestHEADinfo not found for ${contractID}`); + return notFoundNoCache(c); + } + return c.json(HEADinfo, 200, { "Cache-Control": "no-store" }); + } catch (err) { + if (err instanceof HTTPException) throw err; + logger_default.error(err, `GET /latestHEADinfo/${contractID}`, err.message); + throw err; } } - return manifests; - }; - const realPath = await Deno.realPath(path8); - return internal(realPath); -}; -async function upload(args, internal = false) { - const { url: url2, files } = args; - if (!url2) { - await initDB({ skipDbPreloading: true }); + ); + app.get("/time", function(c) { + return c.text((/* @__PURE__ */ new Date()).toISOString(), 200, { + "Cache-Control": "no-store" + }); + }); + app.post("/streams-test", async function(c) { + const raw2 = await c.req.arrayBuffer(); + const buf2 = Buffer14.from(raw2); + if (buf2.byteLength === 2 && buf2.toString() === "ok") { + return c.body(null, 204); + } else { + throw new HTTPException(400); + } + }); + if (process7.env.NODE_ENV === "development") { + app.post("/dev-file", bodyLimit({ maxSize: 6 * MEGABYTE }), async function(c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + try { + console.log("FILE UPLOAD!"); + const formData = await c.req.parseBody({ all: true }); + const hash3 = formData["hash"]; + const data = formData["data"]; + if (!hash3) throw new HTTPException(400, { message: "missing hash" }); + if (!data) throw new HTTPException(400, { message: "missing data" }); + const parsed = maybeParseCID(hash3); + if (!parsed) throw new HTTPException(400, { message: "invalid hash" }); + const ourHash = createCID(data, parsed.code); + if (ourHash !== hash3) { + console.error(`hash(${hash3}) != ourHash(${ourHash})`); + throw new HTTPException(400, { message: "bad hash!" }); + } + await esm_default("chelonia.db/set", hash3, data); + return c.text("/file/" + hash3); + } catch (err) { + if (err instanceof HTTPException) throw err; + logger_default.error(err); + throw new HTTPException(500, { message: "File upload failed" }); + } + }); } - const uploaded = []; - const uploaderFn = url2 ? uploadEntryToURL : uploadEntryToDB; - for (const filepath_ of files) { - let type = multicodes.RAW; - let filepath = filepath_; - if (internal) { - if (filepath_[1] !== "|") throw new Error("Invalid path format"); - switch (filepath_[0]) { - case "r": + app.post( + "/file", + authMiddleware("chel-shelter", "required"), + bodyLimit({ maxSize: FILE_UPLOAD_MAX_BYTES }), + async function(c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + try { + console.info("FILE UPLOAD!"); + const credentials = c.get("credentials"); + if (!credentials?.billableContractID) { + throw new HTTPException(401, { message: "Uploading files requires ownership information" }); + } + const contentType = c.req.header("content-type") || ""; + if (!contentType.includes("multipart/form-data")) { + throw new HTTPException(400, { message: "Expected multipart/form-data" }); + } + const formData = await c.req.formData(); + const manifestFile = formData.get("manifest"); + if (!manifestFile) throw new HTTPException(400, { message: "missing manifest" }); + if (manifestFile.name !== "manifest.json") throw new HTTPException(400, { message: "wrong manifest filename" }); + const manifestPayload = new Uint8Array(await manifestFile.arrayBuffer()); + const manifest2 = (() => { + try { + return JSON.parse(Buffer14.from(manifestPayload).toString()); + } catch { + throw new HTTPException(422, { message: "Error parsing manifest" }); + } + })(); + if (!manifest2 || typeof manifest2 !== "object") throw new HTTPException(422, { message: "manifest format is invalid" }); + if (manifest2.version !== "1.0.0") throw new HTTPException(422, { message: "unsupported manifest version" }); + if (manifest2.cipher !== "aes256gcm") throw new HTTPException(422, { message: "unsupported cipher" }); + if (!Array.isArray(manifest2.chunks) || !manifest2.chunks.length) throw new HTTPException(422, { message: "missing chunks" }); + const chunkFiles = []; + for (let i2 = 0; ; i2++) { + const chunkFile = formData.get(String(i2)); + if (!chunkFile) break; + chunkFiles.push(chunkFile); + } + let ourSize = 0; + const chunks = await Promise.all(manifest2.chunks.map(async (chunk, i2) => { + if (!Array.isArray(chunk) || chunk.length !== 2 || typeof chunk[0] !== "number" || typeof chunk[1] !== "string" || !Number.isSafeInteger(chunk[0]) || chunk[0] <= 0) { + throw new HTTPException(422, { message: "bad chunk description" }); + } + if (!chunkFiles[i2]) { + throw new HTTPException(400, { message: "chunk missing in submitted data" }); + } + const chunkPayload = new Uint8Array(await chunkFiles[i2].arrayBuffer()); + const ourHash = createCID(chunkPayload, multicodes.SHELTER_FILE_CHUNK); + if (chunkPayload.byteLength !== chunk[0]) { + throw new HTTPException(400, { message: "bad chunk size" }); + } + if (ourHash !== chunk[1]) { + throw new HTTPException(400, { message: "bad chunk hash" }); + } + ourSize += chunk[0]; + return [ourHash, chunkPayload]; + })); + if (ourSize !== manifest2.size) throw new HTTPException(400, { message: "Mismatched total size" }); + const manifestHash = createCID(manifestPayload, multicodes.SHELTER_FILE_MANIFEST); + if (await esm_default("chelonia.db/get", manifestHash)) { + throw new Error(`Manifest ${manifestHash} already exists`); + } + await Promise.all(chunks.map(async ([cid]) => { + const exists = !!await esm_default("chelonia.db/get", cid); + if (exists) { + throw new Error(`Chunk ${cid} already exists`); + } + })); + await Promise.all(chunks.map(([cid, data]) => esm_default("chelonia.db/set", cid, data))); + await esm_default("chelonia.db/set", manifestHash, manifestPayload); + await esm_default("backend/server/saveOwner", credentials.billableContractID, manifestHash); + const size = manifest2.size + manifestPayload.byteLength; + await esm_default("backend/server/updateSize", manifestHash, size); + await esm_default("backend/server/updateContractFilesTotalSize", credentials.billableContractID, size); + const deletionTokenDgst = c.req.header("shelter-deletion-token-digest"); + if (deletionTokenDgst) { + await esm_default("chelonia.db/set", `_private_deletionTokenDgst_${manifestHash}`, deletionTokenDgst); + } + return c.text(manifestHash); + } catch (err) { + if (err instanceof HTTPException) throw err; + logger_default.error(err, "POST /file", err.message); + throw err; + } + } + ); + app.get( + "/file/:hash", + zValidator("param", object({ hash: cidSchema }).strict()), + async function(c) { + const { hash: hash3 } = c.req.valid("param"); + const parsed = maybeParseCID(hash3); + if (!parsed) { + throw new HTTPException(400); + } + const blobOrString = await esm_default("chelonia.db/get", `any:${hash3}`); + if (blobOrString?.length === 0) { + throw new HTTPException(410); + } else if (!blobOrString) { + return notFoundNoCache(c); + } + const type = cidLookupTable[parsed.code] || "application/octet-stream"; + return c.body(blobOrString, 200, { + "ETag": `"${hash3}"`, + "Cache-Control": "public,max-age=31536000,immutable", + // CSP to disable everything -- this only affects direct navigation to the + // `/file` URL. + // The CSP below prevents any sort of resource loading or script execution + // on direct navigation. The `nosniff` header instructs the browser to + // honour the provided content-type. + "Content-Security-Policy": "default-src 'none'; frame-ancestors 'none'; form-action 'none'; upgrade-insecure-requests; sandbox", + "X-Content-Type-Options": "nosniff", + "Content-Type": type + }); + } + ); + app.post( + "/deleteFile/:hash", + authMiddleware(["chel-shelter", "chel-bearer"], "required"), + zValidator("param", object({ hash: cidSchema }).strict()), + async function(c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + const { hash: hash3 } = c.req.valid("param"); + const strategy = c.get("authStrategy"); + const parsed = maybeParseCID(hash3); + if (parsed?.code !== multicodes.SHELTER_FILE_MANIFEST) { + throw new HTTPException(400); + } + const owner = await esm_default("chelonia.db/get", `_private_owner_${hash3}`); + if (!owner) { + throw new HTTPException(404); + } + const credentials = c.get("credentials"); + switch (strategy) { + case "chel-shelter": { + const ultimateOwner = await lookupUltimateOwner(owner); + if (!ctEq(credentials.billableContractID, ultimateOwner)) { + throw new HTTPException(401, { message: "Invalid shelter auth" }); + } + break; + } + case "chel-bearer": { + const expectedTokenDgst = await esm_default("chelonia.db/get", `_private_deletionTokenDgst_${hash3}`); + if (!expectedTokenDgst) { + throw new HTTPException(404); + } + const tokenDgst = blake32Hash(credentials.token); + if (!ctEq(expectedTokenDgst, tokenDgst)) { + throw new HTTPException(401, { message: "Invalid token" }); + } break; - case "m": - type = multicodes.SHELTER_CONTRACT_MANIFEST; + } + default: + throw new HTTPException(401, { message: "Missing or invalid auth strategy" }); + } + try { + await esm_default("backend/deleteFile", hash3, null, true); + return c.body(null, 200); + } catch (e2) { + throw errorMapper(e2); + } + } + ); + app.post( + "/deleteContract/:hash", + authMiddleware(["chel-shelter", "chel-bearer"], "required"), + zValidator("param", object({ hash: cidSchema }).strict()), + async function(c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + const { hash: hash3 } = c.req.valid("param"); + const strategy = c.get("authStrategy"); + const credentials = c.get("credentials"); + switch (strategy) { + case "chel-shelter": { + const owner = await esm_default("chelonia.db/get", `_private_owner_${hash3}`); + if (!owner) { + throw new HTTPException(404); + } + const ultimateOwner = await lookupUltimateOwner(owner); + if (!ctEq(credentials.billableContractID, ultimateOwner)) { + throw new HTTPException(401, { message: "Invalid shelter auth" }); + } break; - case "t": - type = multicodes.SHELTER_CONTRACT_TEXT; + } + case "chel-bearer": { + const expectedTokenDgst = await esm_default("chelonia.db/get", `_private_deletionTokenDgst_${hash3}`); + if (!expectedTokenDgst) { + throw new HTTPException(404); + } + const tokenDgst = blake32Hash(credentials.token); + if (!ctEq(expectedTokenDgst, tokenDgst)) { + throw new HTTPException(401, { message: "Invalid token" }); + } break; + } default: - throw new Error("Unknown file type: " + filepath_[0]); + throw new HTTPException(401, { message: "Missing or invalid auth strategy" }); + } + const username = await esm_default("chelonia.db/get", `_private_cid2name_${hash3}`); + try { + const [id] = esm_default("chelonia.persistentActions/enqueue", ["backend/deleteContract", hash3, null, true]); + if (username) { + const ip = getClientIP(c); + console.info({ contractID: hash3, username, ip, taskId: id }, "Scheduled deletion on named contract"); + } + return c.json({ id }, 202); + } catch (e2) { + throw errorMapper(e2); } - filepath = filepath_.slice(2); } - const entry = await createEntryFromFile(filepath, type); - const destination = await uploaderFn(entry, url2); - if (!internal) { - console.log(green("uploaded:"), destination); - } else { - console.log(green(`${relative7(".", filepath)}:`), destination); + ); + app.post( + "/kv/:contractID/:key", + zValidator("param", object({ contractID: cidSchema, key: kvKeySchema }).strict()), + authMiddleware("chel-shelter", "required"), + bodyLimit({ maxSize: 6 * MEGABYTE }), + async function(c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + const { contractID, key } = c.req.valid("param"); + const parsed = maybeParseCID(contractID); + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { + throw new HTTPException(400); + } + const credentials = c.get("credentials"); + if (!ctEq(credentials.billableContractID, contractID)) { + throw new HTTPException(401); + } + const payloadBuffer = Buffer14.from(await c.req.arrayBuffer()); + return esm_default("chelonia/queueInvocation", contractID, async () => { + const existing = await esm_default("chelonia.db/get", `_private_kv_${contractID}_${key}`); + const expectedEtag = c.req.header("if-match"); + if (!expectedEtag) { + throw new HTTPException(400, { message: "if-match is required" }); + } + const cid = existing ? createCID(existing, multicodes.RAW) : ""; + if (expectedEtag === "*") { + } else { + if (!expectedEtag.split(",").map((v2) => v2.trim()).includes(`"${cid}"`)) { + return new Response(existing || "", { + status: 412, + headers: { + "ETag": `"${cid}"`, + "x-cid": `"${cid}"` + } + }); + } + } + try { + const serializedData = JSON.parse(payloadBuffer.toString()); + const { contracts } = esm_default("chelonia/rootState"); + if (contracts[contractID].height !== Number(serializedData.height)) { + return new Response(existing || "", { + status: 409, + headers: { + "ETag": `"${cid}"`, + "x-cid": `"${cid}"` + } + }); + } + esm_default("chelonia/parseEncryptedOrUnencryptedDetachedMessage", { + contractID, + serializedData, + meta: key + }); + } catch (parseErr) { + if (parseErr instanceof Response) throw parseErr; + throw new HTTPException(422); + } + const existingSize = existing ? Buffer14.from(existing).byteLength : 0; + await esm_default("chelonia.db/set", `_private_kv_${contractID}_${key}`, payloadBuffer); + await esm_default("backend/server/updateSize", contractID, payloadBuffer.byteLength - existingSize); + await appendToIndexFactory(`_private_kvIdx_${contractID}`)(key); + esm_default("backend/server/broadcastKV", contractID, key, payloadBuffer.toString()).catch((e2) => console.error(e2, "Error broadcasting KV update", contractID, key)); + return c.body(null, 204); + }); } - uploaded.push([filepath, destination]); - } - return uploaded; -} -async function uploadEntryToURL([cid, buffer], url2) { - const form = new FormData(); - form.append("hash", cid); - form.append("data", new Blob([buffer])); - return await fetch(`${url2}/dev-file`, { method: "POST", body: form }).then(handleFetchResult2("text")).then((r) => { - if (r !== `/file/${cid}`) { - throw new Error(`server returned bad URL: ${r}`); + ); + app.get( + "/kv/:contractID/:key", + authMiddleware("chel-shelter", "required"), + zValidator("param", object({ contractID: cidSchema, key: kvKeySchema }).strict()), + async function(c) { + const { contractID, key } = c.req.valid("param"); + const parsed = maybeParseCID(contractID); + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { + throw new HTTPException(400); + } + const credentials = c.get("credentials"); + if (!ctEq(credentials.billableContractID, contractID)) { + throw new HTTPException(401); + } + const result = await esm_default("chelonia.db/get", `_private_kv_${contractID}_${key}`); + if (!result) { + return notFoundNoCache(c); + } + const cid = createCID(result, multicodes.RAW); + return new Response(result, { + headers: { + "ETag": `"${cid}"`, + "x-cid": `"${cid}"`, + "Cache-Control": "no-store" + } + }); } - return `${url2}${r}`; + ); + app.get("/serverMessages", function(c) { + const messages = import_npm_nconf4.default.get("server:messages"); + if (!messages) return c.json([]); + return c.json(messages, 200, { "Cache-Control": "no-store" }); }); -} -function uploadEntryToDB([cid, buffer]) { - return esm_default("chelonia.db/set", cid, Buffer12.from(buffer)).then(() => cid); -} -function handleFetchResult2(type) { - return async function(r) { - if (!r.ok) throw new Error(`${r.status}: ${r.statusText}`); - return await r[type](); - }; -} -var module2 = { - builder: (yargs) => { - return yargs.option("url", { - describe: "URL of a remote server", - requiresArg: true, - string: true - }).positional("files", { - describe: "Files to upload", - demandOption: true, - array: true, - type: "string" + app.get("/assets/:subpath{.+}", function(c) { + const subpath = c.req.param("subpath"); + return serveAsset(c, subpath, staticServeConfig.distAssets); + }); + if (isCheloniaDashboard) { + app.get("/dashboard/assets/:subpath{.+}", function(c) { + const subpath = c.req.param("subpath"); + return serveAsset(c, subpath, staticServeConfig.distAssets); }); - }, - command: "upload ", - describe: "Requires read and write access to the destination.", - postHandler: (argv) => { - return void upload(argv); } -}; -var CONTRACT_TEXT_PREFIX = "t|"; -var CONTRACT_MANIFEST_PREFIX = "m|"; -var ContractBodySchema = object({ - contract: object({ file: string2() }), - contractSlim: object({ file: string2() }).optional() -}); -async function deploy(args) { - const { manifests } = args; - const toUpload = []; - const manifestSet = /* @__PURE__ */ new Set(); - for (const manifestPath of manifests) { + app.get(isCheloniaDashboard ? "/dashboard/*" : "/app/*", async function(c) { try { - const realPath = await Deno.realPath(manifestPath); - const info = await Deno.lstat(realPath); - if (info.isDirectory) { - const items = await findManifestFiles(realPath); - for (const item of items) { - manifestSet.add(item); + const file = await Deno.readFile(staticServeConfig.distIndexHtml); + return c.body(file, 200, { "Content-Type": "text/html" }); + } catch { + return notFoundNoCache(c); + } + }); + app.get("/", function(c) { + return c.redirect(staticServeConfig.redirect); + }); + const zkppRegisterBodySchema = union([ + object({ b: string2() }).strict(), + object({ r: string2(), s: string2(), sig: string2(), Eh: string2() }).strict() + ]); + app.post( + "/zkpp/register/:name", + zValidator("param", object({ name: nameSchema }).strict()), + zValidatorFormOrJson(zkppRegisterBodySchema), + async function(c) { + const { name } = c.req.valid("param"); + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + const payload = c.get("validatedBody"); + const lookupResult = await esm_default("backend/db/lookupName", name); + if (lookupResult) { + throw new HTTPException(409); + } + try { + if ("b" in payload) { + const result = registrationKey(name, payload.b); + if (result) { + return c.json(result); + } + } else { + const result = register(name, payload.r, payload.s, payload.sig, payload.Eh); + if (result) { + return c.text(result); + } } - } else { - manifestSet.add(realPath); + } catch (e2) { + if (e2 instanceof HTTPException) throw e2; + e2.ip = getClientIP(c); + console.error(e2, "Error at POST /zkpp/register/:name: " + e2.message); } - } catch { - console.warn(`Skipping invalid path: ${manifestPath}`); - continue; + throw new HTTPException(500, { message: "internal error" }); } - } - for (const manifestPath of manifestSet) { - const manifestText = await Deno.readTextFile(manifestPath); - const json = JSON.parse(manifestText); - const body = ContractBodySchema.parse(JSON.parse(json.body)); - const dirname72 = dirname8(manifestPath); - toUpload.push(CONTRACT_TEXT_PREFIX + join8(dirname72, body.contract.file)); - if (body.contractSlim) { - toUpload.push(CONTRACT_TEXT_PREFIX + join8(dirname72, body.contractSlim.file)); + ); + app.get( + "/zkpp/:contractID/auth_hash", + zValidator("param", object({ contractID: cidSchema }).strict()), + zValidator("query", object({ b: string2().min(1, "b is required") })), + async function(c) { + const { contractID } = c.req.valid("param"); + const { b } = c.req.valid("query"); + try { + const challenge = await getChallenge(contractID, b); + return challenge ? c.json(challenge) : notFoundNoCache(c); + } catch (e2) { + ; + e2.ip = getClientIP(c); + console.error(e2, "Error at GET /zkpp/{contractID}/auth_hash: " + e2.message); + } + throw new HTTPException(500, { message: "internal error" }); } - toUpload.push(CONTRACT_MANIFEST_PREFIX + manifestPath); - } - await upload({ ...args, files: toUpload }, true); + ); + app.get( + "/zkpp/:contractID/contract_hash", + zValidator("param", object({ contractID: cidSchema }).strict()), + zValidator("query", object({ + r: string2().min(1, "r is required"), + s: string2().min(1, "s is required"), + sig: string2().min(1, "sig is required"), + hc: string2().min(1, "hc is required") + }).strict()), + async function(c) { + const { contractID } = c.req.valid("param"); + const { r, s, sig, hc } = c.req.valid("query"); + try { + const salt = await getContractSalt(contractID, r, s, sig, hc); + if (salt) { + return c.text(salt); + } + } catch (e2) { + ; + e2.ip = getClientIP(c); + console.error(e2, "Error at GET /zkpp/{contractID}/contract_hash: " + e2.message); + } + throw new HTTPException(500, { message: "internal error" }); + } + ); + const zkppUpdatePasswordBodySchema = object({ + r: string2().min(1, "r is required"), + s: string2().min(1, "s is required"), + sig: string2().min(1, "sig is required"), + hc: string2().min(1, "hc is required"), + Ea: string2().min(1, "Ea is required") + }).strict(); + app.post( + "/zkpp/:contractID/updatePasswordHash", + zValidator("param", object({ contractID: cidSchema }).strict()), + zValidatorFormOrJson(zkppUpdatePasswordBodySchema), + async function(c) { + const { contractID } = c.req.valid("param"); + if (ARCHIVE_MODE) throw new HTTPException(501, { message: "Server in archive mode" }); + try { + const payload = c.get("validatedBody"); + const result = await updateContractSalt(contractID, payload.r, payload.s, payload.sig, payload.hc, payload.Ea); + if (result) { + return c.json(result); + } + } catch (e2) { + if (e2 instanceof HTTPException) throw e2; + e2.ip = getClientIP(c); + console.error(e2, "Error at POST /zkpp/{contractID}/updatePasswordHash: " + e2.message); + } + throw new HTTPException(500, { message: "internal error" }); + } + ); } -var module3 = { - builder: (yargs) => { - return yargs.option("url", { - describe: "URL of a remote server", - requiresArg: true, - string: true - }).positional("manifests", { - describe: "Manifest files to deploy (if a directory is passed in, all manifests in that directory, and sub-directories, will be added)", - demandOption: true, - array: true, - type: "string" - }); - }, - command: "deploy ", - describe: "", - postHandler: (argv) => { - return deploy(argv); - } -}; +var CREDITS_WORKER_TASK_TIME_INTERVAL = 3e5; +var OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL = 3e4; +var SERVER_INSTANCE = "@instance/server"; +var PUBSUB_INSTANCE = "@instance/pubsub"; +init_esm4(); +init_functions(); init_esm(); -init_database(); -async function eventsAfter2({ limit, url: url2, contractID, height }) { +var rfc8291Ikm_default = async (uaPublic, salt) => { + const [[asPrivateKey, asPublic], uaPublicKey] = await Promise.all([ + crypto.subtle.generateKey( + { + name: "ECDH", + namedCurve: "P-256" + }, + false, + ["deriveKey"] + ).then(async (asKeyPair) => { + const asPublic2 = await crypto.subtle.exportKey( + "raw", + asKeyPair.publicKey + ); + return [asKeyPair.privateKey, asPublic2]; + }), + crypto.subtle.importKey( + "raw", + uaPublic, + { name: "ECDH", namedCurve: "P-256" }, + false, + [] + ) + ]); + const ecdhSecret = await crypto.subtle.deriveKey( + { + name: "ECDH", + public: uaPublicKey + }, + asPrivateKey, + { + name: "HKDF", + hash: "SHA-256" + }, + false, + ["deriveBits"] + ); + const infoString = new Uint8Array([ + 87, + 101, + 98, + 80, + 117, + 115, + 104, + 58, + 32, + 105, + 110, + 102, + 111, + 0 + ]); + const info = new Uint8Array(infoString.byteLength + uaPublic.byteLength + asPublic.byteLength); + info.set(infoString, 0); + info.set(uaPublic, infoString.byteLength); + info.set( + new Uint8Array(asPublic), + infoString.byteLength + uaPublic.byteLength + ); + const IKM = await crypto.subtle.deriveBits( + { + name: "HKDF", + hash: "SHA-256", + salt, + info + }, + ecdhSecret, + 32 << 3 + ); + return [asPublic, IKM]; +}; +var addSubscriptionToIndex = appendToIndexFactory("_private_webpush_index"); +var deleteSubscriptionFromIndex = removeFromIndexFactory("_private_webpush_index"); +var saveSubscription = (server, subscriptionId) => { + return esm_default("chelonia.db/set", `_private_webpush_${subscriptionId}`, JSON.stringify({ + settings: server.pushSubscriptions[subscriptionId].settings, + subscriptionInfo: server.pushSubscriptions[subscriptionId], + channelIDs: [...server.pushSubscriptions[subscriptionId].subscriptions] + })).catch((e2) => { + console.error(e2, "Error saving subscription", subscriptionId); + throw e2; + }); +}; +var addChannelToSubscription = (server, subscriptionId, channelID) => { + server.pushSubscriptions[subscriptionId].subscriptions.add(channelID); + return saveSubscription(server, subscriptionId); +}; +var deleteChannelFromSubscription = (server, subscriptionId, channelID) => { + server.pushSubscriptions[subscriptionId].subscriptions.delete(channelID); + return saveSubscription(server, subscriptionId); +}; +var removeSubscription = async (subscriptionId) => { try { - let messages; - if (url2) { - messages = await getRemoteMessagesSince(url2, contractID, height, limit); + const server = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); + const subscription = server.pushSubscriptions[subscriptionId]; + if (subscription) { + delete server.pushSubscriptions[subscriptionId]; + if (server.subscribersByChannelID) { + subscription.subscriptions.forEach((channelID) => { + server.subscribersByChannelID[channelID]?.delete(subscription); + }); + } } else { - await initDB({ skipDbPreloading: true }); - messages = await getMessagesSince(contractID, height, limit); } - console.log(JSON.stringify(messages, null, 2)); - } catch (error2) { - exit(error2); + await esm_default("chelonia.db/delete", `_private_webpush_${subscriptionId}`); + await deleteSubscriptionFromIndex(subscriptionId); + } catch (e2) { + console.error(e2, "Error removing subscription", subscriptionId); } -} -async function getMessagesSince(contractID, sinceHeight, limit) { - const readable = await esm_default("backend/db/streamEntriesAfter", contractID, sinceHeight, limit); - return new Promise((resolve82, reject) => { - const data = []; - readable.on("readable", () => { - let chunk; - while (null !== (chunk = readable.read())) { - data.push(chunk); +}; +var subscriptionInfoWrapper = (subscriptionId, subscriptionInfo, extra) => { + subscriptionInfo.endpoint = new URL(subscriptionInfo.endpoint); + Object.defineProperties(subscriptionInfo, { + "id": { + get() { + return subscriptionId; } - }); - readable.on("error", reject); - readable.on("end", () => { - const events = JSON.parse(data.join("")).map((s) => { - return JSON.parse(new TextDecoder().decode(decodeBase64(s))); - }); - resolve82(events); - }); + }, + // These encryption keys are used for encrypting push notification bodies + // and are unrelated to VAPID, which is used for provenance. + "encryptionKeys": { + get: /* @__PURE__ */ (() => { + let count = 0; + let resultPromise; + let salt; + let uaPublic; + return function() { + if ((count | 0) === 0) { + if (!salt) { + salt = Buffer15.from(this.keys.auth, "base64url"); + } + if (!uaPublic) { + uaPublic = Buffer15.from(this.keys.p256dh, "base64url"); + } + resultPromise = rfc8291Ikm_default(uaPublic, salt); + count = 1; + } else { + count++; + } + return resultPromise; + }; + })() + }, + "settings": { + value: extra.settings || {} + }, + "sockets": { + value: /* @__PURE__ */ new Set() + }, + "subscriptions": { + value: new Set(extra.channelIDs) + } }); -} -async function getRemoteMessagesSince(src2, contractID, sinceHeight, limit) { - const response = await fetch(`${src2}/eventsAfter/${contractID}/${sinceHeight}`); - if (!response.ok) { - const bodyText = await response.text().catch(() => "") || ""; - throw new Error(`failed network request to ${src2}: ${response.status} - ${response.statusText} - '${bodyText}'`); - } - const b64messages = await response.json(); - if (b64messages.length > limit) { - b64messages.length = limit; - } - return b64messages.map((b64str) => JSON.parse(new TextDecoder().decode(decodeBase64(b64str)))); -} -var module4 = { - builder: (yargs) => { - return yargs.option("limit", { - describe: "Limit", - default: 50, - number: true, - requiresArg: true, - coerce(v2) { - if (!Number.isSafeInteger(v2) || v2 < 0) { - throw new Error("--limit must be a valid non-negative integer"); - } - return v2; - } - }).option("url", { - describe: "URL of a remote server", - string: true - }).positional("contractID", { - describe: "Contract ID", - demandOption: true, - type: "string" - }).positional("height", { - describe: "Height", - demandOption: true, - type: "number" - }); - }, - command: "eventsAfter ", - describe: "Displays a JSON array of the first LIMIT events that happened in a given contract, since a given entry identified by its hash.\n\n- Older events are displayed first.\n- The output is parseable with tools such as 'jq'.\n- If --url is given, then its /eventsAfter REST endpoint will be called.\n", - postHandler: (argv) => { - return eventsAfter2(argv); - } + Object.freeze(subscriptionInfo); + return subscriptionInfo; }; -init_esm(); -init_database(); -async function get({ key, url: url2 }) { - if (!url2) { - await initDB({ skipDbPreloading: true }); - } - try { - const data = url2 ? await readRemoteData(url2, key) : await esm_default("chelonia.db/get", key); - if (data === void 0) exit(`no entry found for ${key}`); - if (typeof data === "string") { - console.log(data); - } else { - await writeAll(Deno.stdout, data); +var encryptPayload = async (subscription, data) => { + const readableStream = new Response(data).body; + if (!readableStream) throw new Error("Failed to create readable stream"); + const [asPublic, IKM] = await subscription.encryptionKeys; + return K(x2, readableStream, 32768, asPublic, IKM).then(async (bodyStream) => { + const chunks = []; + const reader = bodyStream.getReader(); + for (; ; ) { + const { done, value } = await reader.read(); + if (done) break; + chunks.push(new Uint8Array(value)); + } + return Buffer15.concat(chunks); + }); +}; +var postEvent = async (subscription, event) => { + const authorization = await vapidAuthorization(subscription.endpoint); + const body = event ? await encryptPayload(subscription, event) : void 0; + const req = await fetch(subscription.endpoint, { + method: "POST", + headers: [ + ["authorization", authorization], + ...body ? [ + ["content-encoding", "aes128gcm"], + [ + "content-type", + "application/octet-stream" + ] + ] : [], + // ['push-receipt', ''], + ["ttl", "60"] + ], + body + }); + if (!req.ok) { + const endpointHost = new URL(subscription.endpoint).host; + console.info( + await req.text().then((response) => ({ response })).catch((e2) => `ERR: ${e2?.message}`), + `Error ${req.status} sending push notification to '${subscription.id}' via ${endpointHost}` + ); + if ([401, 404, 410].includes(req.status)) { + removeSubscription(subscription.id); + throw new Error(`Error sending push: ${req.status}`); + } + if (req.status === 413) { + throw new Error("Payload too large"); } - } catch (error2) { - exit(error2); - } -} -var module5 = { - builder: (yargs) => { - return yargs.option("url", { - describe: "URL of a remote server", - string: true - }).positional("key", { - describe: "Database key", - demandOption: true, - type: "string" - }); - }, - command: "get ", - describe: "Retrieves the entry associated with a given key, from a given database or server.\n\n- The output can be piped to a file, like this: chel get https://url.com mygreatlongkey > file.png", - postHandler: (argv) => { - return get(argv); } }; -init_functions(); -async function hash22({ filename }, multicode = multicodes.RAW, internal = false) { - const [cid] = await createEntryFromFile(filename, multicode); - if (!internal) { - console.log(`CID(${filename}):`, cid); - } - return cid; -} -var module6 = { - builder: (yargs) => { - return yargs.positional("filename", { - describe: "File name", - demandOption: true, - type: "string" - }); +var pushServerActionhandlers = { + [PUSH_SERVER_ACTION_TYPE.SEND_PUBLIC_KEY]() { + const socket = this; + socket.send(createMessage(REQUEST_TYPE.PUSH_ACTION, { type: PUSH_SERVER_ACTION_TYPE.SEND_PUBLIC_KEY, data: getVapidPublicKey() })); }, - command: "hash ", - describe: "Computes and logs the content identifier (CID) for the given file.\n' + 'File contents will be interpreted as raw binary data, unless the file extension is '.json'.", - postHandler: (argv) => { - return void hash22(argv); + async [PUSH_SERVER_ACTION_TYPE.STORE_SUBSCRIPTION](payload) { + const socket = this; + const { server } = socket; + const { applicationServerKey, settings, subscriptionInfo } = payload; + if (applicationServerKey) { + const ourVapidPublicKey = getVapidPublicKey(); + const theirVapidPublicKey = Buffer15.from(applicationServerKey, "base64").toString("base64url"); + if (ourVapidPublicKey !== theirVapidPublicKey) { + socket.send(createMessage(REQUEST_TYPE.PUSH_ACTION, { type: PUSH_SERVER_ACTION_TYPE.SEND_PUBLIC_KEY, data: getVapidPublicKey() })); + console.warn({ ourVapidPublicKey, theirVapidPublicKey }, "Refusing to store subscription because the associated public VAPID key does not match ours"); + return; + } + } + let subscriptionId = null; + let host = ""; + let subscriptionWrapper = null; + try { + subscriptionId = await getSubscriptionId(subscriptionInfo); + subscriptionWrapper = server.pushSubscriptions[subscriptionId]; + if (!subscriptionWrapper) { + console.debug(`saving new push subscription '${subscriptionId}':`, subscriptionInfo); + server.pushSubscriptions[subscriptionId] = subscriptionInfoWrapper(subscriptionId, subscriptionInfo, { settings }); + subscriptionWrapper = server.pushSubscriptions[subscriptionId]; + host = subscriptionWrapper.endpoint.host; + await addSubscriptionToIndex(subscriptionId); + await saveSubscription(server, subscriptionId); + await postEvent(subscriptionWrapper, JSON.stringify({ type: "initial" })); + } else { + host = subscriptionWrapper.endpoint.host; + if (subscriptionWrapper.sockets.size === 0) { + subscriptionWrapper.subscriptions.forEach((channelID) => { + if (!server.subscribersByChannelID[channelID]) return; + server.subscribersByChannelID[channelID].delete(subscriptionWrapper); + }); + } + } + if (socket.pushSubscriptionId) { + if (socket.pushSubscriptionId === subscriptionId) return; + await removeSubscription(socket.pushSubscriptionId); + } + socket.pushSubscriptionId = subscriptionId; + subscriptionWrapper.subscriptions.forEach((channelID) => { + server.subscribersByChannelID[channelID]?.delete(subscriptionWrapper); + }); + subscriptionWrapper.sockets.add(socket); + socket.subscriptions?.forEach((channelID) => { + subscriptionWrapper.subscriptions.add(channelID); + }); + await saveSubscription(server, subscriptionId); + } catch (e2) { + console.error(e2, `[${socket.ip}] Failed to store subscription '${subscriptionId || "??"}' (${host}), removing it!`); + subscriptionId && removeSubscription(subscriptionId); + throw e2; + } + }, + [PUSH_SERVER_ACTION_TYPE.DELETE_SUBSCRIPTION]() { + const socket = this; + const { pushSubscriptionId: subscriptionId } = socket; + if (subscriptionId) { + return removeSubscription(subscriptionId); + } } }; -init_esm7(); -var keygen2 = async (args) => { - await revokeNet(); - const key = keygen(EDWARDS25519SHA512BATCH); - const pubKeyData = { - version: "1.0.0", - pubkey: serializeKey(key, false) - }; - const keyData = { - ...pubKeyData, - privkey: serializeKey(key, true) - }; - const result = JSON.stringify(keyData); - const pubResult = JSON.stringify(pubKeyData); - const idx = keyId(key).slice(-12); - const outFile = args.out || `${EDWARDS25519SHA512BATCH}-${idx}.json`; - const pubOutFile = args.pubout || `${EDWARDS25519SHA512BATCH}-${idx}.pub.json`; - await Deno.writeTextFile(outFile, result); - console.log(green("wrote:"), outFile, blue("(secret)")); - await Deno.writeTextFile(pubOutFile, pubResult); - console.log(green("wrote:"), pubOutFile, blue("(public)")); +var import_npm_chalk2 = __toESM(require_source()); +var import_stream2 = __toESM(require_stream(), 1); +var import_receiver = __toESM(require_receiver(), 1); +var import_sender = __toESM(require_sender(), 1); +var import_websocket = __toESM(require_websocket(), 1); +var import_websocket_server = __toESM(require_websocket_server(), 1); +var wrapper_default = import_websocket.default; +var isPushSubscriptionInfo = (x3) => { + return has(x3, "endpoint"); }; -var module7 = { - builder: (yargs) => { - return yargs.option("out", { - describe: "File name for the secret key", - requiresArg: true, - string: true - }).option("pubout", { - describe: "File name for the public key", - requiresArg: true, - string: true - }); - }, - command: "keygen", - describe: "", - postHandler: (argv) => { - return keygen2(argv); - } +var { bold } = import_npm_chalk2.default; +var { PING, PONG, PUB, SUB, UNSUB, KV_FILTER } = NOTIFICATION_TYPE; +var { ERROR, OK } = RESPONSE_TYPE; +var defaultOptions3 = { + logPingRounds: process8.env.NODE_ENV !== "production" && !process8.env.CI, + logPongMessages: false, + maxPayload: 6 * 1024 * 1024, + pingInterval: 3e4 }; -init_esm7(); -init_functions(); -function isSigningKeyDescriptor(obj) { - return obj !== null && typeof obj === "object" && typeof obj.privkey === "string"; +var tag2 = "[pubsub]"; +var generateSocketID = /* @__PURE__ */ (() => { + let counter = 0; + return (debugID) => String(counter++) + (debugID ? "-" + debugID : ""); +})(); +var log = logger_default.info.bind(logger_default, tag2); +log.bold = (...args) => logger_default.debug(bold(tag2, ...args)); +log.debug = logger_default.debug.bind(logger_default, tag2); +log.error = (error2, ...args) => logger_default.error(error2, bold.red(tag2, ...args)); +function createErrorResponse(data) { + return JSON.stringify({ type: ERROR, data }); } -async function manifest(args) { - await revokeNet(); - const { signingKey: keyFileRaw, contractBundle: contractFileRaw } = args; - if (typeof keyFileRaw !== "string" || typeof contractFileRaw !== "string") { - exit("Missing or invalid key or contract file"); - } - const keyFile = keyFileRaw; - const contractFile = contractFileRaw; - const parsedFilepath = parse7(contractFile); - const { name: contractFileName, base: contractBasename, dir: contractDir } = parsedFilepath; - const name = args.name || contractFileName; - const version3 = args.contractVersion || "x"; - const slim = args.slim; - const outFile = args.out || join8(contractDir, `${contractFileName}.${version3}.manifest.json`); - if (!keyFile) exit("Missing signing key file"); - const signingKeyDescriptorRaw = await readJsonFile(keyFile); - if (!isSigningKeyDescriptor(signingKeyDescriptorRaw)) { - exit("Invalid signing key file: missing or invalid privkey", true); - } - const signingKeyDescriptor = signingKeyDescriptorRaw; - const signingKey = deserializeKey(signingKeyDescriptor.privkey); - const publicKeys = Array.from(new Set( - [serializeKey(signingKey, false)].concat(...await Promise.all(args.key?.map( - async (kf) => { - if (typeof kf !== "string" && typeof kf !== "number") { - exit(`Invalid key file reference: ${String(kf)}`); - } - const descriptor = await readJsonFile(String(kf)); - const key = deserializeKey(descriptor.pubkey); - if (key.type !== EDWARDS25519SHA512BATCH) { - exit(`Invalid key type ${key.type}; only ${EDWARDS25519SHA512BATCH} keys are supported.`); - } - return serializeKey(key, false); - } - ) || [])) - )); - const body = { - name, - version: version3, - contract: { - hash: await hash22({ ...args, filename: contractFile }, multicodes.SHELTER_CONTRACT_TEXT, true), - file: contractBasename - }, - signingKeys: publicKeys - }; - if (typeof slim === "string" && slim !== "") { - body.contractSlim = { - file: basename8(slim), - hash: await hash22({ ...args, filename: slim }, multicodes.SHELTER_CONTRACT_TEXT, true) - }; - } - const serializedBody = JSON.stringify(body); - const head = { manifestVersion: "1.0.0" }; - const serializedHead = JSON.stringify(head); - const manifest2 = JSON.stringify({ - head: serializedHead, - body: serializedBody, - signature: { - keyId: keyId(signingKey), - value: sign(signingKey, serializedBody + serializedHead) +function createPushErrorResponse(data) { + return JSON.stringify({ + type: ERROR, + data: { + ...data, + type: REQUEST_TYPE.PUSH_ACTION } }); - if (args.out === "-") { - console.log(manifest2); - } else { - Deno.writeTextFileSync(outFile, manifest2); - console.log(green("wrote:"), outFile); +} +function createNotification(type, data) { + return JSON.stringify({ type, data }); +} +function createOkResponse(data) { + return JSON.stringify({ type: OK, data }); +} +function createServer(httpServer, options2 = {}) { + const server = new import_websocket_server.default({ + ...defaultOptions3, + ...options2, + ...{ clientTracking: true }, + server: httpServer + }); + server.channels = /* @__PURE__ */ new Set(); + server.customServerEventHandlers = { ...options2.serverHandlers }; + server.customSocketEventHandlers = { ...options2.socketHandlers }; + server.customMessageHandlers = { ...options2.messageHandlers }; + server.pingIntervalID = void 0; + server.subscribersByChannelID = /* @__PURE__ */ Object.create(null); + server.pushSubscriptions = /* @__PURE__ */ Object.create(null); + const handlers = Object.keys(defaultServerHandlers); + handlers.forEach((name) => { + server.on(name, (...args) => { + try { + ; + defaultServerHandlers[name].apply(server, args); + server.customServerEventHandlers[name]?.apply(server, args); + } catch (error2) { + server.emit("error", error2); + } + }); + }); + if (server.options.pingInterval > 0) { + server.pingIntervalID = setInterval(() => { + if (server.clients.size && server.options.logPingRounds) { + log.debug("Pinging clients"); + } + server.clients.forEach((client) => { + if (isPushSubscriptionInfo(client)) return; + if (client.pinged && !client.activeSinceLastPing) { + log(`Disconnecting irresponsive client ${client.id}`); + return client.terminate(); + } + if (client.readyState === wrapper_default.OPEN) { + client.send(createMessage(PING, Date.now()), () => { + client.activeSinceLastPing = false; + client.pinged = true; + }); + } + }); + }, server.options.pingInterval); } + return Object.assign(server, publicMethods2); } -var module8 = { - builder: (yargs) => { - return yargs.option("key", { - coerce: (v2) => Array.isArray(v2) ? v2 : [v2], - describe: "Additional public key", - requiresArg: true, - string: true - }).alias("k", "key").option("out", { - describe: "Manifest file name", - requiresArg: true, - string: true - }).option("name", { - describe: "Contract name", - requiresArg: true, - string: true - }).alias("n", "name").option("slim", { - describe: "Slim contract bundle", - requiresArg: true, - string: true - }).alias("s", "slim").option("contract-version", { - describe: "Contract version", - requiresArg: true, - string: true - }).alias("V", "contract-version").positional("signingKey", { - describe: "Signing key file", - demandOption: true, - type: "string" - }).positional("contractBundle", { - describe: "Contract bundle", - demandOption: true, - type: "string" +var defaultServerHandlers = { + close() { + clearInterval(this.pingIntervalID); + log("Server closed"); + }, + /** + * Emitted when a connection handshake completes. + * + * @see https://github.com/websockets/ws/blob/master/doc/ws.md#event-connection + * @param {ws.WebSocket} socket - The client socket that connected. + * @param {http.IncomingMessage} request - The underlying Node http GET request. + */ + connection(socket, request) { + const server = this; + const url2 = request.url; + const urlSearch = url2?.includes("?") ? url2.slice(url2.lastIndexOf("?")) : ""; + const debugID = new URLSearchParams(urlSearch).get("debugID") || ""; + const send = socket.send.bind(socket); + socket.id = generateSocketID(debugID); + socket.activeSinceLastPing = true; + socket.pinged = false; + socket.server = server; + socket.subscriptions = /* @__PURE__ */ new Set(); + socket.kvFilter = /* @__PURE__ */ new Map(); + socket.ip = request.headers["x-real-ip"] || request.headers["x-forwarded-for"]?.split(",")[0].trim() || request.socket.remoteAddress; + socket.send = function(data) { + if (typeof data === "object" && data !== null && typeof data[Symbol.toPrimitive] === "function") { + return send(data[Symbol.toPrimitive]()); + } + return send(data); + }; + log.bold(`Socket ${socket.id} connected. Total: ${this.clients.size}`); + ["close", "error", "message", "ping", "pong"].forEach((eventName) => { + socket.on(eventName, (...args) => { + if (eventName !== "message") { + log.debug(`Event '${eventName}' on socket ${socket.id}`, ...args.map((arg) => String(arg))); + } + try { + ; + defaultSocketEventHandlers[eventName]?.call(socket, ...args); + socket.server.customSocketEventHandlers[eventName]?.call(socket, ...args); + } catch (error2) { + socket.server.emit("error", error2); + socket.terminate(); + } + }); }); }, - command: "manifest [-k|--key ] [-k|--key ...] [--out ] [-s|--slim ] [-V|--contract-version ] ", - describe: "Produce a signed manifest from a contract.\nIf unspecified, is set to 'x'.", - postHandler: (argv) => { - return manifest(argv); + error(error2) { + log.error(error2, "Server error"); + }, + headers() { + }, + listening() { + log("Server listening"); } }; -init_esm(); -init_database(); -var import_npm_nconf3 = __toESM(require_nconf()); -var globImport_serve_database_ts = __glob({ - "./serve/database-fs.ts": () => Promise.resolve().then(() => (init_database_fs(), database_fs_exports)), - "./serve/database-redis.ts": () => Promise.resolve().then(() => (init_database_redis(), database_redis_exports)), - "./serve/database-router.test.ts": () => Promise.resolve().then(() => (init_database_router_test(), database_router_test_exports)), - "./serve/database-router.ts": () => Promise.resolve().then(() => (init_database_router(), database_router_exports)), - "./serve/database-sqlite.ts": () => Promise.resolve().then(() => (init_database_sqlite(), database_sqlite_exports)) -}); -async function migrate(args) { - const { to } = args; - if (args.fromConfig) { - const fromConfig = parse8(await readFile2(args.fromConfig, { encoding: "utf-8", flag: "r" })); - const backend = import_npm_nconf3.default.get("database:backend"); - const fromBackend = fromConfig?.database?.backend; - if (fromBackend !== backend) { - console.warn(`--from-config has backend ${fromBackend} but --from is ${backend}`); +var defaultSocketEventHandlers = { + close() { + const socket = this; + const { server } = this; + for (const channelID of socket.subscriptions) { + server.subscribersByChannelID[channelID].delete(socket); } - const fromConfigOpts = fromConfig?.database?.backendOptions?.[backend] || {}; - import_npm_nconf3.default.set(`database:backendOptions:${backend}`, fromConfigOpts); - } - try { - await initDB({ skipDbPreloading: true }); - } catch (e2) { - console.error("Error setting up database"); - exit(e2); - throw e2; - } - let backendTo; - try { - let toConfigOpts; - if (args.toConfig) { - const toConfig = parse8(await readFile2(args.toConfig, { encoding: "utf-8", flag: "r" })); - const toBackend = toConfig?.database?.backend; - if (toBackend !== to) { - console.warn(`--to-config has backend ${toBackend} but --to is ${to}`); - } - toConfigOpts = toConfig?.database?.backendOptions?.[to] || {}; + socket.subscriptions.clear(); + }, + message(data) { + const socket = this; + const { server } = this; + const text = data.toString(); + let msg = { type: "" }; + try { + msg = messageParser(text); + } catch (error2) { + log.error(error2, `Malformed message: ${error2.message}`); + server.rejectMessageAndTerminateSocket(msg, socket); + return; + } + if (msg.type !== "pong" || server.options.logPongMessages) { + log.debug(`Received '${msg.type}' on socket ${socket.id}`, text); + } + socket.activeSinceLastPing = true; + const defaultHandler = defaultMessageHandlers2[msg.type]; + const customHandler = server.customMessageHandlers[msg.type]; + if (defaultHandler || customHandler) { + try { + ; + defaultHandler?.call(socket, msg); + customHandler?.call(socket, msg); + } catch (error2) { + log.error(error2, "onMessage"); + server.rejectMessageAndTerminateSocket(msg, socket); + } } else { - toConfigOpts = import_npm_nconf3.default.get(`database:backendOptions:${to}`) || {}; + log.error(`Unhandled message type: ${msg.type}`); + server.rejectMessageAndTerminateSocket(msg, socket); } - const Ctor = (await globImport_serve_database_ts(`./serve/database-${to}.ts`)).default; - backendTo = new Ctor(toConfigOpts); - await backendTo.init(); - } catch (error2) { - exit(error2); - throw error2; } - const numKeys2 = await esm_default("chelonia.db/keyCount"); - let numMigratedKeys = 0; - let numVisitedKeys = 0; - const reportStatus = () => { - console.log(`${green("Migrated:")} ${numMigratedKeys} entries`); - }; - const checkAndExit = (() => { - let interruptCount = 0; - let shouldExit = 0; - const handleSignal2 = (signal, code2) => { - process3.on(signal, () => { - shouldExit = 128 + code2; - if (++interruptCount < 3) { - console.error(`Received signal ${signal} (${code2}). Finishing current operation.`); - } else { - console.error(`Received signal ${signal} (${code2}). Force quitting.`); - reportStatus(); - exit(shouldExit); - } - }); - }; - const checkAndExit2 = async () => { - if (shouldExit) { - await backendTo.close(); - reportStatus(); - exit(shouldExit); +}; +var defaultMessageHandlers2 = { + [PONG]() { + const socket = this; + socket.activeSinceLastPing = true; + }, + [PUB](msg) { + const { server } = this; + const subscribers = server.subscribersByChannelID[msg.channelID]; + server.broadcast(msg, { to: subscribers ?? [] }); + }, + [SUB]({ channelID, kvFilter }) { + const socket = this; + const { server } = this; + if (!server.channels.has(channelID)) { + socket.send(createErrorResponse( + { type: SUB, channelID, reason: `Unknown channel id: ${channelID}` } + )); + return; + } + if (!socket.subscriptions.has(channelID)) { + socket.subscriptions.add(channelID); + if (Array.isArray(kvFilter)) { + socket.kvFilter.set(channelID, new Set(kvFilter)); } - }; - [ - ["SIGHUP", 1], - ["SIGINT", 2], - ["SIGQUIT", 3], - ["SIGTERM", 15], - ["SIGUSR1", 10], - ["SIGUSR2", 11] - ].forEach(([signal, code2]) => handleSignal2(signal, code2)); - return checkAndExit2; - })(); - let lastReportedPercentage = 0; - for await (const key of esm_default("chelonia.db/iterKeys")) { - numVisitedKeys++; - if (!isValidKey(key)) { - console.debug("Skipping invalid key", key); - continue; + if (!server.subscribersByChannelID[channelID]) { + server.subscribersByChannelID[channelID] = /* @__PURE__ */ new Set(); + } + server.subscribersByChannelID[channelID].add(socket); + } else { + log.debug("Already subscribed to", channelID); } - let value; - try { - value = await esm_default("chelonia.db/get", `any:${key}`); - } catch (e2) { - reportStatus(); - console.error(`Error reading from source database key '${key}'`, e2); - await backendTo.close(); - exit(1); - throw e2; + socket.send(createOkResponse({ type: SUB, channelID, kvFilter })); + }, + [KV_FILTER]({ channelID, kvFilter }) { + const socket = this; + const { server } = this; + if (!server.channels.has(channelID)) { + socket.send(createErrorResponse( + { type: SUB, channelID, reason: `Unknown channel id: ${channelID}` } + )); + return; } - await checkAndExit(); - if (value === void 0) { - console.debug("Skipping empty key", key); - continue; + if (socket.subscriptions.has(channelID)) { + if (Array.isArray(kvFilter)) { + socket.kvFilter.set(channelID, new Set(kvFilter)); + } else { + socket.kvFilter.delete(channelID); + } + } else { + log.debug("[KV_FILTER] Not subscribed to", channelID); } - try { - await backendTo.writeData(key, value); - } catch (e2) { - reportStatus(); - console.error(`Error writing to target database key '${key}'`, e2); - await backendTo.close(); - exit(1); - throw e2; + socket.send(createOkResponse({ type: KV_FILTER, channelID, kvFilter })); + }, + [UNSUB]({ channelID }) { + const socket = this; + const { server } = this; + if (!server.channels.has(channelID)) { + socket.send(createErrorResponse( + { type: UNSUB, channelID, reason: `Unknown channel id: ${channelID}` } + )); } - await checkAndExit(); - ++numMigratedKeys; - const percentage = Math.floor(numVisitedKeys / numKeys2 * 100); - if (percentage - lastReportedPercentage >= 10) { - lastReportedPercentage = percentage; - console.log(`Migrating... ${percentage}% done`); + if (socket.subscriptions.has(channelID)) { + socket.subscriptions.delete(channelID); + socket.kvFilter.delete(channelID); + if (server.subscribersByChannelID[channelID]) { + server.subscribersByChannelID[channelID].delete(socket); + } } + socket.send(createOkResponse({ type: UNSUB, channelID })); } - reportStatus(); - await backendTo.close(); -} -var module9 = { - builder: (yargs) => { - return yargs.option("from", { - describe: "Source backend", - demandOption: true, - requiresArg: true, - string: true - }).alias("database:backend", "from").option("from-config", { - describe: "Source backend configuration", - requiresArg: true, - string: true - }).option("to", { - describe: "Destination backend", - demandOption: true, - requiresArg: true, - string: true - }).option("to-config", { - describe: "Destination backend configuration", - requiresArg: true, - string: true - }).strict(false).strictCommands(true); +}; +var publicMethods2 = { + /** + * Broadcasts a message, ignoring clients which are not open. + * + * @param message + * @param to - The intended recipients of the message. Defaults to every open client socket. + * @param except - A recipient to exclude. Optional. + */ + broadcast(message, { to, except, wsOnly } = {}) { + const server = this; + const msg = typeof message === "string" ? message : JSON.stringify(message); + let shortMsg; + const shortenPayload = () => { + if (!shortMsg && (typeof message === "object" && message.type === NOTIFICATION_TYPE.ENTRY && message.data)) { + delete message.data; + shortMsg = JSON.stringify(message); + } + return shortMsg; + }; + for (const client of to || server.clients) { + if (!wsOnly && isPushSubscriptionInfo(client)) { + if (msg.length > 4096 - 86 - 17) { + if (!shortenPayload()) { + console.info("Skipping too large of a payload for", client.id); + continue; + } + } + postEvent(client, shortMsg || msg).catch((e2) => { + if (e2?.message === "Payload too large") { + if (shortMsg || !shortenPayload()) { + console.info("Skipping too large of a payload for", client.id); + return; + } + postEvent(client, shortMsg).catch((e3) => { + console.error(e3, "Error posting push notification"); + }); + return; + } + console.error(e2, "Error posting push notification"); + }); + continue; + } + if (client.readyState === wrapper_default.OPEN && client !== except) { + client.send(msg); + } + } }, - command: "migrate", - describe: "Reads all key-value pairs from a given database and creates or updates another database accordingly.\n\n- The output database will be created if necessary.\n- The source database won't be modified nor deleted.\n- Invalid key-value pairs entries will be skipped.\n- Requires read and write access to the source.\n", - postHandler: (argv) => { - return migrate(argv); + // Enumerates the subscribers of a given channel. + *enumerateSubscribers(channelID, kvKey) { + const server = this; + if (channelID in server.subscribersByChannelID) { + const subscribers = server.subscribersByChannelID[channelID]; + if (!kvKey) { + yield* subscribers; + } else { + for (const subscriber of subscribers) { + const kvFilter = subscriber.kvFilter?.get(channelID); + if (!kvFilter || kvFilter.has(kvKey)) yield subscriber; + } + } + } + }, + rejectMessageAndTerminateSocket(request, socket) { + socket.send(createErrorResponse({ ...request }), () => socket.terminate()); } }; -var VALID_VERSION = /^[a-zA-Z0-9_+-][a-zA-Z0-9._+-]*[a-zA-Z0-9_+-]?$/; -var RESERVED_FILE_CHARS_REPLACE = /[\x00/\\:*?"<>|]/g; -var projectRoot; -var cheloniaConfig; -function sanitizeContractName(contractName) { - return contractName.replace(RESERVED_FILE_CHARS_REPLACE, "_").replace(/\.\./g, "__"); +var import_npm_nconf5 = __toESM(require_nconf()); +var currentApp = null; +var currentHttpServer = null; +var currentOwnerSizeTotalWorker = void 0; +var currentCreditsWorker = void 0; +var currentManifest = void 0; +var currentPushHeartbeatIntervalID = void 0; +var isStopping = false; +var appendToOrphanedNamesIndex = appendToIndexFactory("_private_orphaned_names_index"); +var serverSelectorsInstalled = false; +function installServerSelectorsOnce() { + if (serverSelectorsInstalled) return; + serverSelectorsInstalled = true; + esm_default("sbp/selectors/register", { + "backend/server/persistState": async function(deserializedHEAD) { + const contractID = deserializedHEAD.contractID; + const cheloniaState = esm_default("chelonia/rootState"); + if (!cheloniaState.contracts[contractID] || cheloniaState.contracts[contractID].height < deserializedHEAD.head.height) { + return; + } + if (cheloniaState.contracts[contractID].HEAD === deserializedHEAD.hash) { + const state = { + contractState: cheloniaState[contractID], + cheloniaContractInfo: cheloniaState.contracts[contractID] + }; + await esm_default("chelonia.db/set", "_private_cheloniaState_" + contractID, JSON.stringify(state)); + } + if (contractID === deserializedHEAD.hash) { + await esm_default("backend/server/appendToContractIndex", contractID); + } + if (cheloniaState.contracts[contractID].previousKeyOp === deserializedHEAD.hash) { + await appendToIndexFactory(`_private_keyop_idx_${contractID}_${deserializedHEAD.head.height - deserializedHEAD.head.height % KEYOP_SEGMENT_LENGTH}`)(String(deserializedHEAD.head.height)); + } + }, + "backend/server/appendToContractIndex": appendToIndexFactory("_private_cheloniaState_index"), + "backend/server/broadcastKV": async function(contractID, key, entry) { + const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); + const pubsubMessage = createKvMessage(contractID, key, entry); + const subscribers = pubsub.enumerateSubscribers(contractID, key); + console.debug(import_npm_chalk3.default.blue.bold(`[pubsub] Broadcasting KV change on ${contractID} to key ${key}`)); + await pubsub.broadcast(pubsubMessage, { to: subscribers, wsOnly: true }); + }, + "backend/server/broadcastEntry": async function(deserializedHEAD, entry) { + const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); + const contractID = deserializedHEAD.contractID; + const contractType = esm_default("chelonia/rootState").contracts[contractID]?.type; + const pubsubMessage = createMessage(NOTIFICATION_TYPE.ENTRY, entry, { contractID, contractType }); + const subscribers = pubsub.enumerateSubscribers(contractID); + console.debug(import_npm_chalk3.default.blue.bold(`[pubsub] Broadcasting ${deserializedHEAD.description()}`)); + await pubsub.broadcast(pubsubMessage, { to: subscribers }); + }, + "backend/server/broadcastDeletion": async function(contractID) { + const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); + const pubsubMessage = createMessage(NOTIFICATION_TYPE.DELETION, contractID); + const subscribers = pubsub.enumerateSubscribers(contractID); + console.debug(import_npm_chalk3.default.blue.bold(`[pubsub] Broadcasting deletion of ${contractID}`)); + await pubsub.broadcast(pubsubMessage, { to: subscribers }); + }, + "backend/server/handleEntry": async function(deserializedHEAD, entry) { + const contractID = deserializedHEAD.contractID; + if (deserializedHEAD.head.op === SPMessage.OP_CONTRACT) { + esm_default("okTurtles.data/get", PUBSUB_INSTANCE).channels.add(contractID); + } + await esm_default("chelonia/private/in/enqueueHandleEvent", contractID, entry); + await esm_default("backend/server/persistState", deserializedHEAD, entry); + esm_default("backend/server/broadcastEntry", deserializedHEAD, entry).catch((e2) => console.error(e2, "Error broadcasting entry", contractID, deserializedHEAD.hash)); + }, + "backend/server/saveOwner": async function(ownerID, resourceID) { + await esm_default("chelonia/queueInvocation", ownerID, async () => { + const owner = await esm_default("chelonia.db/get", ownerID); + if (!owner) { + throw new Error("Owner resource does not exist"); + } + await esm_default("chelonia.db/set", `_private_owner_${resourceID}`, ownerID); + const resourcesKey = `_private_resources_${ownerID}`; + await appendToIndexFactory(resourcesKey)(resourceID); + esm_default("chelonia.persistentActions/enqueue", ["backend/server/addToIndirectResourcesIndex", resourceID]); + }); + }, + "backend/server/addToIndirectResourcesIndex": async function(resourceID) { + const ownerID = await esm_default("chelonia.db/get", `_private_owner_${resourceID}`); + let indirectOwnerID = ownerID; + while (indirectOwnerID = await esm_default("chelonia.db/get", `_private_owner_${indirectOwnerID}`)) { + await appendToIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(resourceID); + } + }, + "backend/server/removeFromIndirectResourcesIndex": async function(resourceID) { + const ownerID = await esm_default("chelonia.db/get", `_private_owner_${resourceID}`); + const resources = await esm_default("chelonia.db/get", `_private_resources_${resourceID}`); + const indirectResources = resources ? await esm_default("chelonia.db/get", `_private_indirectResources_${resourceID}`) : void 0; + const allSubresources = [ + resourceID, + ...resources ? resources.split("\0") : [], + ...indirectResources ? indirectResources.split("\0") : [] + ]; + let indirectOwnerID = ownerID; + while (indirectOwnerID = await esm_default("chelonia.db/get", `_private_owner_${indirectOwnerID}`)) { + await removeFromIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(allSubresources); + } + }, + "backend/server/registerBillableEntity": appendToIndexFactory("_private_billable_entities"), + "backend/server/updateSize": function(resourceID, size, ultimateOwnerID) { + const sizeKey = `_private_size_${resourceID}`; + return updateSize(resourceID, sizeKey, size).then(() => { + return currentOwnerSizeTotalWorker?.rpcSbp("worker/updateSizeSideEffects", { resourceID, size, ultimateOwnerID }); + }); + }, + "backend/server/updateContractFilesTotalSize": function(resourceID, size) { + const sizeKey = `_private_contractFilesTotalSize_${resourceID}`; + return updateSize(resourceID, sizeKey, size, true); + }, + "backend/server/stop": async function() { + await stopServer(); + }, + async "backend/deleteFile"(cid, ultimateOwnerID, skipIfDeleted) { + const owner = await esm_default("chelonia.db/get", `_private_owner_${cid}`); + const rawManifest = await esm_default("chelonia.db/get", cid); + const size = await esm_default("chelonia.db/get", `_private_size_${cid}`); + if (owner && !ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(owner); + if (rawManifest === "") { + if (skipIfDeleted) return; + throw new BackendErrorGone(); + } + if (!rawManifest) { + if (skipIfDeleted) return; + throw new BackendErrorNotFound(); + } + try { + const manifest2 = JSON.parse(rawManifest); + if (!manifest2 || typeof manifest2 !== "object") throw new BackendErrorBadData("manifest format is invalid"); + if (manifest2.version !== "1.0.0") throw new BackendErrorBadData("unsupported manifest version"); + if (!Array.isArray(manifest2.chunks) || !manifest2.chunks.length) throw new BackendErrorBadData("missing chunks"); + await Promise.all(manifest2.chunks.map(([, cid2]) => esm_default("chelonia.db/delete", cid2))); + } catch (e2) { + console.warn(e2, `Error parsing manifest for ${cid}. It's probably not a file manifest.`); + throw new BackendErrorNotFound(); + } + const resourcesKey = `_private_resources_${owner}`; + await removeFromIndexFactory(resourcesKey)(cid); + await esm_default("backend/server/removeFromIndirectResourcesIndex", cid); + await esm_default("chelonia.db/delete", `_private_owner_${cid}`); + await esm_default("chelonia.db/delete", `_private_size_${cid}`); + await esm_default("chelonia.db/delete", `_private_deletionTokenDgst_${cid}`); + await esm_default("chelonia.db/set", cid, ""); + await esm_default("backend/server/updateContractFilesTotalSize", owner, -Number(size)); + if (ultimateOwnerID && size) { + await currentOwnerSizeTotalWorker?.rpcSbp("worker/updateSizeSideEffects", { resourceID: cid, size: -parseInt(size), ultimateOwnerID }); + } + }, + async "backend/deleteContract"(cid, ultimateOwnerID, skipIfDeleted) { + let contractsPendingDeletion = esm_default("okTurtles.data/get", "contractsPendingDeletion"); + if (!contractsPendingDeletion) { + contractsPendingDeletion = /* @__PURE__ */ new Set(); + esm_default("okTurtles.data/set", "contractsPendingDeletion", contractsPendingDeletion); + } + if (contractsPendingDeletion.has(cid)) { + return; + } + contractsPendingDeletion.add(cid); + return await esm_default("chelonia/queueInvocation", cid, async () => { + const owner = await esm_default("chelonia.db/get", `_private_owner_${cid}`); + if (!ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(cid); + const rawManifest = await esm_default("chelonia.db/get", cid); + const size = await esm_default("chelonia.db/get", `_private_size_${cid}`); + if (rawManifest === "") { + if (skipIfDeleted) return; + throw new BackendErrorGone(); + } + if (!rawManifest) { + if (skipIfDeleted) return; + throw new BackendErrorNotFound(); + } + const resourcesKey = `_private_resources_${cid}`; + const resources = await esm_default("chelonia.db/get", resourcesKey); + if (resources) { + await Promise.allSettled(resources.split("\0").map((resourceCid) => { + const parsed = parseCID(resourceCid); + if (parsed.code === multicodes.SHELTER_CONTRACT_DATA) { + return esm_default("chelonia.persistentActions/enqueue", ["backend/deleteContract", resourceCid, ultimateOwnerID, true]); + } else if (parsed.code === multicodes.SHELTER_FILE_MANIFEST) { + return esm_default("chelonia.persistentActions/enqueue", ["backend/deleteFile", resourceCid, ultimateOwnerID, true]); + } else { + console.warn({ cid, resourceCid, code: parsed.code }, "Resource should be deleted but it is of an unknown type"); + } + return void 0; + })); + } + await esm_default("chelonia.db/delete", resourcesKey); + const latestHEADinfo = await esm_default("chelonia/db/latestHEADinfo", cid); + if (latestHEADinfo) { + for (let i2 = latestHEADinfo.height; i2 > 0; i2--) { + const eventKey = `_private_hidx=${cid}#${i2}`; + const event = await esm_default("chelonia.db/get", eventKey); + if (event) { + await esm_default("chelonia.db/delete", JSON.parse(event).hash); + await esm_default("chelonia.db/delete", eventKey); + } + if (i2 % KEYOP_SEGMENT_LENGTH === 0) { + await esm_default("chelonia.db/delete", `_private_keyop_idx_${cid}_${i2}`); + } + } + await esm_default("chelonia/db/deleteLatestHEADinfo", cid); + } + const kvIndexKey = `_private_kvIdx_${cid}`; + const kvKeys = await esm_default("chelonia.db/get", kvIndexKey); + if (kvKeys) { + await Promise.all(kvKeys.split("\0").map((key) => { + return esm_default("chelonia.db/delete", `_private_kv_${cid}_${key}`); + })); + } + await esm_default("chelonia.db/delete", kvIndexKey); + await esm_default("backend/server/removeFromIndirectResourcesIndex", cid); + await esm_default("chelonia.db/delete", `_private_indirectResources_${cid}`); + await esm_default("chelonia.db/get", `_private_cid2name_${cid}`).then((name) => { + if (!name) return; + return Promise.all([ + esm_default("chelonia.db/delete", `_private_cid2name_${cid}`), + appendToOrphanedNamesIndex(name) + ]); + }); + await esm_default("chelonia.db/delete", `_private_rid_${cid}`); + await esm_default("chelonia.db/delete", `_private_owner_${cid}`); + await esm_default("chelonia.db/delete", `_private_size_${cid}`); + await esm_default("chelonia.db/delete", `_private_contractFilesTotalSize_${cid}`); + await esm_default("chelonia.db/delete", `_private_deletionTokenDgst_${cid}`); + await removeFromIndexFactory(`_private_resources_${owner}`)(cid); + await esm_default("chelonia.db/delete", `_private_hidx=${cid}#0`); + await esm_default("chelonia.db/delete", `_private_keyop_idx_${cid}_0`); + await esm_default("chelonia.db/set", cid, ""); + esm_default("chelonia/private/removeImmediately", cid); + if (size) { + await currentOwnerSizeTotalWorker?.rpcSbp("worker/updateSizeSideEffects", { resourceID: cid, size: -parseInt(size), ultimateOwnerID }); + } + await esm_default("chelonia.db/delete", `_private_cheloniaState_${cid}`); + await removeFromIndexFactory("_private_cheloniaState_index")(cid); + await removeFromIndexFactory("_private_billable_entities")(cid); + esm_default("backend/server/broadcastDeletion", cid).catch((e2) => { + console.error(e2, "Error broadcasting contract deletion", cid); + }); + }).finally(() => { + contractsPendingDeletion.delete(cid); + }).catch((e2) => { + console.error(e2, "Error in contract deletion cleanup"); + throw e2; + }); + } + }); } -async function pin(args) { - const version3 = args["manifest-version"]; - const manifestPath = args.manifest; - projectRoot = args["dir"] || process4.cwd(); +async function startServer() { + const appDir = import_npm_nconf5.default.get("server:appDir") || process9.cwd(); + const ARCHIVE_MODE = import_npm_nconf5.default.get("server:archiveMode"); + const host = import_npm_nconf5.default.get("server:host") || "0.0.0.0"; + const port = import_npm_nconf5.default.get("server:port") ?? 8e3; + if (CREDITS_WORKER_TASK_TIME_INTERVAL && OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL > CREDITS_WORKER_TASK_TIME_INTERVAL) { + console.error("The size calculation worker must run more frequently than the credits worker for accurate billing"); + throw new Error("The size calculation worker must run more frequently than the credits worker for accurate billing"); + } try { - if (!manifestPath) { - await loadCheloniaConfig(); - return; - } - console.log(cyan(`\u{1F4CC} Requesting pin to version: ${version3}`)); - console.log(gray(`Manifest: ${manifestPath}`)); - await loadCheloniaConfig(); - const fullManifestPath = join62(projectRoot, manifestPath); - if (!existsSync(fullManifestPath)) { - exit(`Manifest file not found: ${manifestPath}`); - } - const { contractName, fullContractName, contractFiles, manifestVersion } = await parseManifest(fullManifestPath); - if (!manifestVersion || !VALID_VERSION.test(manifestVersion)) { - exit(`Invalid manifest version: ${manifestVersion}`); - } - console.log(blue(`Contract name: ${fullContractName}`)); - console.log(blue(`Manifest version: ${manifestVersion}`)); - if (version3) { - if (version3 !== manifestVersion) { - console.error(red(`\u274C Version mismatch: CLI version (${version3}) does not match manifest version (${manifestVersion})`)); - console.error(yellow(`\u{1F4A1} To pin this contract, use: chel pin ${manifestVersion} ${manifestPath}`)); - exit("Version mismatch between CLI and manifest"); + currentManifest = (await import(pathToFileURL(join72(appDir, "chelonia.json")).toString(), { + with: { type: "json" } + })).default; + } catch { + console.warn("`chelonia.json` unparsable or not found. Version information will be unavailable."); + } + currentOwnerSizeTotalWorker = ARCHIVE_MODE || !OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL ? void 0 : createWorker_default("./serve/ownerSizeTotalWorker.js"); + currentCreditsWorker = ARCHIVE_MODE || !CREDITS_WORKER_TASK_TIME_INTERVAL ? void 0 : createWorker_default("./serve/creditsWorker.js"); + currentApp = new Hono2(); + currentApp.use("*", cors({ origin: "*" })); + currentApp.use("*", async (c, next) => { + await next(); + c.header("X-Frame-Options", "DENY"); + }); + if (process9.env.NODE_ENV === "development" && !process9.env.CI) { + currentApp.use("*", async (c, next) => { + await next(); + const ip = getClientIP(c) || "unknown"; + console.debug(import_npm_chalk3.default`{grey ${ip}: ${c.req.method} ${c.req.path} --> ${c.res.status}}`); + }); + } + currentHttpServer = createAdaptorServer({ fetch: currentApp.fetch }); + installServerSelectorsOnce(); + esm_default("okTurtles.data/set", SERVER_INSTANCE, currentApp); + esm_default("okTurtles.data/set", PUBSUB_INSTANCE, createServer(currentHttpServer, { + serverHandlers: { + connection(socket) { + const manifest2 = currentManifest; + const appVersion = typeof manifest2?.appVersion === "string" ? manifest2.appVersion : null; + const contracts = manifest2?.contracts; + const versionInfo = { + appVersion, + contractsVersion: contracts ? Object.fromEntries( + Object.entries(contracts).map(([k, v2]) => [k, v2.version]) + ) : null + }; + socket.send(createNotification(NOTIFICATION_TYPE.VERSION_INFO, versionInfo)); } - console.log(green(`\u2705 Version validation passed: ${version3}`)); - } - const currentPinnedVersion = cheloniaConfig.contracts[fullContractName]?.version; - if (currentPinnedVersion === manifestVersion) { - console.log(yellow(`\u2728 Contract ${fullContractName} is already pinned to version ${manifestVersion} - no action needed`)); - return; - } - if (currentPinnedVersion) { - console.log(cyan(`\u{1F4CC} Updating ${fullContractName} from version ${currentPinnedVersion} to ${manifestVersion}`)); - } else { - console.log(cyan(`\u{1F4CC} Pinning ${fullContractName} to version ${manifestVersion} (first time)`)); - } - const contractVersionDir = join62(projectRoot, "contracts", contractName, manifestVersion); - if (existsSync(contractVersionDir)) { - if (!args.overwrite) { - exit(`Version ${manifestVersion} already exists for contract ${fullContractName}. Use --overwrite to replace it.`); + }, + socketHandlers: { + // The `close()` handler signals the server that the WS has been closed and + // that subsequent messages to subscribed channels should now be sent to its + // associated web push subscription, if it exists. + close() { + const socket = this; + const { server } = this; + const subscriptionId = socket.pushSubscriptionId; + if (!subscriptionId) return; + if (!server.pushSubscriptions[subscriptionId]) return; + server.pushSubscriptions[subscriptionId].sockets.delete(socket); + delete socket.pushSubscriptionId; + if (server.pushSubscriptions[subscriptionId].sockets.size === 0) { + server.pushSubscriptions[subscriptionId].subscriptions.forEach((channelID) => { + if (!server.subscribersByChannelID[channelID]) { + server.subscribersByChannelID[channelID] = /* @__PURE__ */ new Set(); + } + server.subscribersByChannelID[channelID].add(server.pushSubscriptions[subscriptionId]); + }); + } + } + }, + messageHandlers: { + [REQUEST_TYPE.PUSH_ACTION]: async function({ data }) { + const socket = this; + const { action, payload } = data; + if (!action) { + socket.send(createPushErrorResponse({ message: "'action' field is required" })); + } + const handler = pushServerActionhandlers[action]; + if (handler) { + try { + await handler.call(socket, payload); + } catch (error2) { + const message = error2?.message || `push server failed to perform [${action}] action`; + console.warn(error2, `[${socket.ip}] Action '${action}' for '${REQUEST_TYPE.PUSH_ACTION}' handler failed: ${message}`); + socket.send(createPushErrorResponse({ actionType: action, message })); + } + } else { + socket.send(createPushErrorResponse({ message: `No handler for the '${action}' action` })); + } + }, + // This handler adds subscribed channels to the web push subscription + // associated with the WS, so that when the WS is closed we can continue + // sending messages as web push notifications. + [NOTIFICATION_TYPE.SUB]({ channelID }) { + const socket = this; + const { server } = this; + if (!socket.pushSubscriptionId) return; + if (!server.pushSubscriptions[socket.pushSubscriptionId]) { + delete socket.pushSubscriptionId; + return; + } + addChannelToSubscription(server, socket.pushSubscriptionId, channelID); + }, + // This handler removes subscribed channels from the web push subscription + // associated with the WS, so that when the WS is closed we don't send + // messages as web push notifications. + [NOTIFICATION_TYPE.UNSUB]({ channelID }) { + const socket = this; + const { server } = this; + if (!socket.pushSubscriptionId) return; + if (!server.pushSubscriptions[socket.pushSubscriptionId]) { + delete socket.pushSubscriptionId; + return; + } + deleteChannelFromSubscription(server, socket.pushSubscriptionId, channelID); } - console.log(yellow(`Version ${manifestVersion} already exists for ${fullContractName} - checking files...`)); - } else { - await createVersionDirectory(contractName, manifestVersion); } - await copyContractFiles(contractFiles, manifestPath, contractName, manifestVersion, args); - await updateCheloniaConfig(fullContractName, contractName, manifestVersion, manifestPath); - console.log(green(`\u2705 Successfully pinned ${fullContractName} to version ${manifestVersion}`)); - console.log(gray(`Location: contracts/${contractName}/${manifestVersion}/`)); - } catch (error2) { - exit(error2); + })); + await initDB(); + await currentOwnerSizeTotalWorker?.ready; + await currentCreditsWorker?.ready; + await esm_default("chelonia/configure", SERVER); + esm_default("chelonia.persistentActions/configure", { + databaseKey: "_private_persistent_actions" + }); + const savedStateIndex = await esm_default("chelonia.db/get", "_private_cheloniaState_index"); + if (savedStateIndex) { + const recoveredState = /* @__PURE__ */ Object.create(null); + recoveredState.contracts = /* @__PURE__ */ Object.create(null); + const channels = esm_default("okTurtles.data/get", PUBSUB_INSTANCE).channels; + await Promise.all(savedStateIndex.split("\0").map(async (contractID) => { + const cpSerialized = await esm_default("chelonia.db/get", `_private_cheloniaState_${contractID}`); + if (!cpSerialized) { + console.warn(`[server] missing state for contractID ${contractID} - skipping setup for this contract`); + return; + } + const cp = JSON.parse(cpSerialized); + recoveredState[contractID] = cp.contractState; + recoveredState.contracts[contractID] = cp.cheloniaContractInfo; + channels.add(contractID); + })); + Object.assign(esm_default("chelonia/rootState"), recoveredState); + } + const savedWebPushIndex = await esm_default("chelonia.db/get", "_private_webpush_index"); + if (savedWebPushIndex) { + const { pushSubscriptions, subscribersByChannelID } = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); + await Promise.all(savedWebPushIndex.split("\0").map(async (subscriptionId) => { + const subscriptionSerialized = await esm_default("chelonia.db/get", `_private_webpush_${subscriptionId}`); + if (!subscriptionSerialized) { + console.warn(`[server] missing state for subscriptionId '${subscriptionId}' - skipping setup for this subscription`); + return; + } + const { settings, subscriptionInfo, channelIDs } = JSON.parse(subscriptionSerialized); + pushSubscriptions[subscriptionId] = subscriptionInfoWrapper(subscriptionId, subscriptionInfo, { channelIDs, settings }); + channelIDs.forEach((channelID) => { + if (!subscribersByChannelID[channelID]) subscribersByChannelID[channelID] = /* @__PURE__ */ new Set(); + subscribersByChannelID[channelID].add(pushSubscriptions[subscriptionId]); + }); + })); } + esm_default("chelonia.persistentActions/load").catch((e2) => { + console.error(e2, "Error loading persistent actions"); + }); + registerRoutes(currentApp); + const map = /* @__PURE__ */ new WeakMap(); + currentPushHeartbeatIntervalID = setInterval(() => { + const now = Date.now(); + const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); + const notification = JSON.stringify({ type: "recurring" }); + Object.values(pubsub?.pushSubscriptions || {}).filter( + (pushSubscription) => !!pushSubscription.settings.heartbeatInterval && pushSubscription.sockets.size === 0 + ).forEach((pushSubscription) => { + const last = map.get(pushSubscription) ?? Number.NEGATIVE_INFINITY; + if (now - last < pushSubscription.settings.heartbeatInterval) return; + postEvent(pushSubscription, notification).then(() => { + map.set(pushSubscription, now); + }).catch((e2) => { + console.warn(e2, "Error sending recurring message to web push client", pushSubscription.id); + }); + }); + }, 1 * 60 * 60 * 1e3); + const uri = await new Promise((resolve82, reject) => { + currentHttpServer.listen(port, host, () => { + const addr = currentHttpServer.address(); + const uri2 = `http://${addr.address}:${addr.port}`; + console.info("Backend server running at:", uri2); + esm_default("okTurtles.events/emit", SERVER_RUNNING, { info: { uri: uri2 } }); + resolve82(uri2); + }).once("error", reject); + }); + return { uri }; } -async function parseManifest(manifestPath) { - const manifestContent = await readFile3(manifestPath, "utf8"); - const manifest2 = JSON.parse(manifestContent); - const body = JSON.parse(manifest2.body); - const fullContractName = body.name; - const manifestVersion = body.version; - const mainFile = body.contract.file; - const slimFile = body.contractSlim?.file; - if (!fullContractName || !mainFile || !manifestVersion) { - console.error(red("\u274C Invalid manifest: missing contract name, main file, or version")); - exit("Invalid manifest: missing contract name, main file, or version"); +async function stopServer() { + if (isStopping) return; + isStopping = true; + try { + if (currentPushHeartbeatIntervalID !== void 0) { + clearInterval(currentPushHeartbeatIntervalID); + currentPushHeartbeatIntervalID = void 0; + } + if (esm_default("sbp/selectors/fn", "backend/server/stopRateLimiters")) { + await esm_default("backend/server/stopRateLimiters"); + } + const pubsub = esm_default("okTurtles.data/get", PUBSUB_INSTANCE); + if (pubsub) { + pubsub.clients.forEach((client) => client.terminate()); + pubsub.close(); + esm_default("okTurtles.data/delete", PUBSUB_INSTANCE); + } + if (currentHttpServer) { + await new Promise((resolve82, reject) => { + currentHttpServer.close((err) => { + if (err) { + reject(err); + } else { + resolve82(); + } + }); + }); + currentHttpServer = null; + } + await Promise.all([ + currentOwnerSizeTotalWorker?.terminate(), + currentCreditsWorker?.terminate() + ]); + currentOwnerSizeTotalWorker = void 0; + currentCreditsWorker = void 0; + await esm_default("chelonia.persistentActions/unload"); + await closeDB(); + currentApp = null; + currentManifest = void 0; + } finally { + isStopping = false; } - const contractName = sanitizeContractName(fullContractName); - return { - contractName, - manifestVersion, - fullContractName, - contractFiles: { - main: mainFile, - slim: slimFile +} +console.info("NODE_ENV =", process10.env.NODE_ENV); +var dontLog = { + "backend/server/broadcastEntry": true, + "backend/server/broadcastDeletion": true, + "backend/server/broadcastKV": true +}; +function logSBP(_domain, selector, data) { + if (!dontLog[selector]) { + if (selector === "backend/server/handleEntry") { + console.debug(import_npm_chalk4.default.bold(`[sbp] ${selector}`), data[0].description()); + } else { + console.debug(import_npm_chalk4.default.bold(`[sbp] ${selector}`), data); } + } +} +["backend"].forEach((domain) => esm_default("sbp/filters/domain/add", domain, logSBP)); +[].forEach((sel) => esm_default("sbp/filters/selector/add", sel, logSBP)); +var signalHandlersInstalled = false; +var signalHandlers = []; +var globalExceptionHandlersInstalled = false; +function installGlobalExceptionHandlers() { + if (globalExceptionHandlersInstalled) return; + globalExceptionHandlersInstalled = true; + process10.on("uncaughtException", (err) => { + console.error(err, "[server] Unhandled exception"); + process10.exit(1); + }); + process10.on("unhandledRejection", (reason) => { + console.error(reason, "[server] Unhandled promise rejection:", reason); + process10.exit(1); + }); +} +function installSignalHandlers() { + if (signalHandlersInstalled) return; + signalHandlersInstalled = true; + const handleSignal = (signal, code2) => { + const handler = () => { + console.error(`Exiting upon receiving ${signal} (${code2})`); + exit2(128 + code2); + }; + signalHandlers.push([signal, handler]); + process10.on(signal, handler); }; + [ + ["SIGHUP", 1], + ["SIGINT", 2], + ["SIGQUIT", 3], + ["SIGTERM", 15], + ["SIGUSR1", 10], + ["SIGUSR2", 11] + ].forEach(([signal, code2]) => handleSignal(signal, code2)); } -async function createVersionDirectory(contractName, version3) { - const versionDir = join62(projectRoot, "contracts", contractName, version3); - console.log(blue(`\u{1F4C1} Creating directory: contracts/${contractName}/${version3}/`)); - await mkdir3(versionDir, { recursive: true }); +function removeSignalHandlers() { + for (const [signal, handler] of signalHandlers) { + process10.removeListener(signal, handler); + } + signalHandlers.length = 0; + signalHandlersInstalled = false; } -async function copyContractFiles(contractFiles, manifestPath, contractName, version3, args) { - const sourceDir = dirname42(join62(projectRoot, manifestPath)); - const targetDir = join62(projectRoot, "contracts", contractName, version3); - console.log(gray(`\u{1F4CB} Copying files from manifest: ${contractFiles.main}${contractFiles.slim ? `, ${contractFiles.slim}` : ""}, manifest`)); - const mainSource = join62(sourceDir, contractFiles.main); - const mainTarget = join62(targetDir, contractFiles.main); - await copyFileIfNeeded(mainSource, mainTarget, contractFiles.main, args); - if (contractFiles.slim) { - const slimSource = join62(sourceDir, contractFiles.slim); - const slimTarget = join62(targetDir, contractFiles.slim); +var exit2 = (code2) => { + esm_default("okTurtles.events/once", SERVER_EXITING, () => { + esm_default("okTurtles.eventQueue/queueEvent", SERVER_EXITING, () => { + process10.send?.({}); + process10.nextTick(() => process10.exit(code2)); + }); + }); + esm_default("okTurtles.events/emit", SERVER_EXITING); +}; +async function startServer2(options2 = {}) { + const { installSignalHandlers: shouldInstallSignalHandlers = true } = options2; + initializeLogger(); + if (shouldInstallSignalHandlers) { + installGlobalExceptionHandlers(); + installSignalHandlers(); + } + esm_default("okTurtles.events/once", SERVER_EXITING, async () => { try { - await copyFileIfNeeded(slimSource, slimTarget, contractFiles.slim, args); - } catch (error2) { - const errorMessage = error2 instanceof Error ? error2.message : String(error2); - console.error(yellow(`\u26A0\uFE0F Could not copy slim file: ${errorMessage}`)); + removeSignalHandlers(); + await stopServer2(); + console.info("Server down"); + } catch (err) { + console.error(err, "Error during shutdown"); } - } - const manifestSource = join62(projectRoot, manifestPath); - const manifestTarget = join62(targetDir, basename42(manifestPath)); - await copyFileIfNeeded(manifestSource, manifestTarget, basename42(manifestPath), args); + }); + return await new Promise((resolve82, reject) => { + esm_default("okTurtles.events/on", SERVER_RUNNING, function onRunning(info) { + esm_default("okTurtles.events/off", SERVER_RUNNING, onRunning); + console.info(import_npm_chalk4.default.bold("backend startup sequence complete.")); + resolve82({ uri: info.info.uri }); + }); + startServer().catch(reject); + }); } -async function copyFileIfNeeded(sourcePath, targetPath, fileName, args) { - const targetExists = existsSync(targetPath); - if (!targetExists) { - console.log(blue(`\u{1F4C4} Copying: ${fileName} (new file)`)); - await copyFile(sourcePath, targetPath); +async function stopServer2() { + await stopServer(); +} +var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/(?!event-stream(?:[;\s]|$))[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i; +var getMimeType = (filename, mimes = baseMimes) => { + const regexp = /\.([a-zA-Z0-9]+?)$/; + const match2 = filename.match(regexp); + if (!match2) { return; } - if (targetExists && !args.overwrite) { - console.log(yellow(`\u23ED\uFE0F Skipping: ${fileName} (already exists, use --overwrite to replace)`)); - return; + let mimeType = mimes[match2[1].toLowerCase()]; + if (mimeType && mimeType.startsWith("text")) { + mimeType += "; charset=utf-8"; } - console.log(blue(`\u{1F4C4} Copying: ${fileName} (overwriting)`)); - await copyFile(sourcePath, targetPath); -} -async function loadCheloniaConfig() { - const configPath = join62(projectRoot, "chelonia.json"); - cheloniaConfig = { contracts: {} }; - if (existsSync(configPath)) { - try { - const configContent = await readFile3(configPath, "utf8"); - cheloniaConfig = JSON.parse(configContent); - console.log(blue("\u{1F4C4} Loaded existing chelonia.json")); - } catch (error2) { - console.warn(yellow(`Warning: Could not parse chelonia.json: ${error2}`)); + return mimeType; +}; +var _baseMimes = { + aac: "audio/aac", + avi: "video/x-msvideo", + avif: "image/avif", + av1: "video/av1", + bin: "application/octet-stream", + bmp: "image/bmp", + css: "text/css", + csv: "text/csv", + eot: "application/vnd.ms-fontobject", + epub: "application/epub+zip", + gif: "image/gif", + gz: "application/gzip", + htm: "text/html", + html: "text/html", + ico: "image/x-icon", + ics: "text/calendar", + jpeg: "image/jpeg", + jpg: "image/jpeg", + js: "text/javascript", + json: "application/json", + jsonld: "application/ld+json", + map: "application/json", + mid: "audio/x-midi", + midi: "audio/x-midi", + mjs: "text/javascript", + mp3: "audio/mpeg", + mp4: "video/mp4", + mpeg: "video/mpeg", + oga: "audio/ogg", + ogv: "video/ogg", + ogx: "application/ogg", + opus: "audio/opus", + otf: "font/otf", + pdf: "application/pdf", + png: "image/png", + rtf: "application/rtf", + svg: "image/svg+xml", + tif: "image/tiff", + tiff: "image/tiff", + ts: "video/mp2t", + ttf: "font/ttf", + txt: "text/plain", + wasm: "application/wasm", + webm: "video/webm", + weba: "audio/webm", + webmanifest: "application/manifest+json", + webp: "image/webp", + woff: "font/woff", + woff2: "font/woff2", + xhtml: "application/xhtml+xml", + xml: "application/xml", + zip: "application/zip", + "3gp": "video/3gpp", + "3g2": "video/3gpp2", + gltf: "model/gltf+json", + glb: "model/gltf-binary" +}; +var baseMimes = _baseMimes; +var defaultJoin = (...paths) => { + let result = paths.filter((p) => p !== "").join("/"); + result = result.replace(/(?<=\/)\/+/g, ""); + const segments = result.split("/"); + const resolved = []; + for (const segment of segments) { + if (segment === ".." && resolved.length > 0 && resolved.at(-1) !== "..") { + resolved.pop(); + } else if (segment !== ".") { + resolved.push(segment); + } + } + return resolved.join("/") || "."; +}; +var ENCODINGS = { + br: ".br", + zstd: ".zst", + gzip: ".gz" +}; +var ENCODINGS_ORDERED_KEYS = Object.keys(ENCODINGS); +var DEFAULT_DOCUMENT = "index.html"; +var serveStatic = (options2) => { + const root = options2.root ?? "./"; + const optionPath = options2.path; + const join10 = options2.join ?? defaultJoin; + return async (c, next) => { + if (c.finalized) { + return next(); + } + let filename; + if (options2.path) { + filename = options2.path; + } else { + try { + filename = tryDecodeURI(c.req.path); + if (/(?:^|[\/\\])\.{1,2}(?:$|[\/\\])|[\/\\]{2,}/.test(filename)) { + throw new Error(); + } + } catch { + await options2.onNotFound?.(c.req.path, c); + return next(); + } } - } else { - console.log(blue("\u{1F4C4} No existing chelonia.json found")); + let path8 = join10( + root, + !optionPath && options2.rewriteRequestPath ? options2.rewriteRequestPath(filename) : filename + ); + if (options2.isDir && await options2.isDir(path8)) { + path8 = join10(path8, DEFAULT_DOCUMENT); + } + const getContent = options2.getContent; + let content = await getContent(path8, c); + if (content instanceof Response) { + return c.newResponse(content.body, content); + } + if (content) { + const mimeType = options2.mimes && getMimeType(path8, options2.mimes) || getMimeType(path8); + c.header("Content-Type", mimeType || "application/octet-stream"); + if (options2.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))) { + const acceptEncodingSet = new Set( + c.req.header("Accept-Encoding")?.split(",").map((encoding) => encoding.trim()) + ); + for (const encoding of ENCODINGS_ORDERED_KEYS) { + if (!acceptEncodingSet.has(encoding)) { + continue; + } + const compressedContent = await getContent(path8 + ENCODINGS[encoding], c); + if (compressedContent) { + content = compressedContent; + c.header("Content-Encoding", encoding); + c.header("Vary", "Accept-Encoding", { append: true }); + break; + } + } + } + await options2.onFound?.(path8, c); + return c.body(content); + } + await options2.onNotFound?.(path8, c); + await next(); + return; + }; +}; +var { open, lstatSync, errors } = Deno; +var serveStatic2 = (options2) => { + return async function serveStatic22(c, next) { + const getContent = async (path8) => { + try { + if (isDir(path8)) { + return null; + } + const file = await open(path8); + return file.readable; + } catch (e2) { + if (!(e2 instanceof errors.NotFound)) { + console.warn(`${e2}`); + } + return null; + } + }; + const isDir = (path8) => { + let isDir2; + try { + const stat = lstatSync(path8); + isDir2 = stat.isDirectory; + } catch { + } + return isDir2; + }; + return serveStatic({ + ...options2, + getContent, + join: join82, + isDir + })(c, next); + }; +}; +var X_HONO_DISABLE_SSG_HEADER_KEY = "x-hono-disable-ssg"; +var SSG_DISABLED_RESPONSE = (() => { + try { + return new Response("SSG is disabled", { + status: 404, + headers: { [X_HONO_DISABLE_SSG_HEADER_KEY]: "true" } + }); + } catch { + return null; } - if (!cheloniaConfig.contracts) { - cheloniaConfig.contracts = {}; +})(); +var WSContext = class { + #init; + constructor(init2) { + this.#init = init2; + this.raw = init2.raw; + this.url = init2.url ? new URL(init2.url) : null; + this.protocol = init2.protocol ?? null; } -} -async function updateCheloniaConfig(fullContractName, contractName, version3, manifestPath) { - const manifestFileName = basename42(manifestPath); - const pinnedManifestPath = `contracts/${contractName}/${version3}/${manifestFileName}`; - cheloniaConfig.contracts[fullContractName] = { - version: version3, - path: pinnedManifestPath + send(source, options2) { + this.#init.send(source, options2 ?? {}); + } + raw; + binaryType = "arraybuffer"; + get readyState() { + return this.#init.readyState; + } + url; + protocol; + close(code2, reason) { + this.#init.close(code2, reason); + } +}; +var defineWebSocketHelper = (handler) => { + return (...args) => { + if (typeof args[0] === "function") { + const [createEvents, options2] = args; + return async function upgradeWebSocket2(c, next) { + const events = await createEvents(c); + const result = await handler(c, events, options2); + if (result) { + return result; + } + await next(); + }; + } else { + const [c, events, options2] = args; + return (async () => { + const upgraded = await handler(c, events, options2); + if (!upgraded) { + throw new Error("Failed to upgrade WebSocket"); + } + return upgraded; + })(); + } }; - const configPath = join62(projectRoot, "chelonia.json"); - const configContent = JSON.stringify(cheloniaConfig, null, 2) + "\n"; - await writeFile2(configPath, configContent, "utf8"); - console.log(green("\u2705 Saved chelonia.json")); -} -var module10 = { - builder: (yargs) => { - return yargs.option("overwrite", { - describe: "Overwrite existing files", - requiresArg: false, - boolean: true - }).alias("o", "overwrite").option("dir", { - default: false, - describe: "Output directory", - requiresArg: false, - string: true - }).alias("d", "dir").positional("manifest", { - describe: "Manifest file path", - demandOption: true, - type: "string" - }).positional("manifest-version", { - describe: "Manifest version", - demandOption: false, - type: "string" - }); - }, - command: "pin []", - describe: "Pin a manifest version", - postHandler: (argv) => { - return pin(argv); +}; +var upgradeWebSocket = defineWebSocketHelper(async (c, events, options2) => { + if (c.req.header("upgrade") !== "websocket") { + return; } + const { response, socket } = Deno.upgradeWebSocket(c.req.raw, options2 ?? {}); + const wsContext = new WSContext({ + close: (code2, reason) => socket.close(code2, reason), + get protocol() { + return socket.protocol; + }, + raw: socket, + get readyState() { + return socket.readyState; + }, + url: socket.url ? new URL(socket.url) : null, + send: (source) => socket.send(source) + }); + socket.onopen = (evt) => events.onOpen?.(evt, wsContext); + socket.onmessage = (evt) => events.onMessage?.(evt, wsContext); + socket.onclose = (evt) => events.onClose?.(evt, wsContext); + socket.onerror = (evt) => events.onError?.(evt, wsContext); + return response; +}); +var import_npm_nconf6 = __toESM(require_nconf()); +var getDashboardPath = () => { + const baseDir = import.meta.dirname || path6.join(process11.cwd(), "build"); + const dashboardPath = path6.resolve(baseDir, "dist-dashboard"); + return dashboardPath; }; -init_esm(); -init_esm5(); +async function startDashboard() { + const port = import_npm_nconf6.default.get("server:dashboardPort"); + const host = import_npm_nconf6.default.get("server:host") || "0.0.0.0"; + const dashboardRoot = getDashboardPath(); + const app = new Hono2(); + const staticMiddleware = serveStatic2({ root: dashboardRoot, rewriteRequestPath: (p) => p }); + const indexMiddleware = serveStatic2({ path: path6.join(dashboardRoot, "index.html") }); + app.get("/assets/*", staticMiddleware); + app.get("/dashboard", indexMiddleware); + app.get("/dashboard/", indexMiddleware); + app.get("/*", async (c) => { + const staticResponse = await staticMiddleware(c, async () => { + }); + if (staticResponse) { + return staticResponse; + } + const indexResponse = await indexMiddleware(c, async () => { + }); + return indexResponse || c.text("Not Found", 404); + }); + await new Promise((resolve82) => { + Deno.serve({ port, hostname: host, onListen: () => resolve82() }, app.fetch); + }); +} async function watch(args) { const dir = args["manifests-dir"]; const manifests = await findManifestFiles(dir); @@ -110894,12 +75408,10 @@ async function watch(args) { })(); } async function startDashboardServer() { - const dashboardServer = await Promise.resolve().then(() => (init_dashboard_server(), dashboard_server_exports)); - await dashboardServer.startDashboard(); + await startDashboard(); } async function startApplicationServer() { - const startServer = await Promise.resolve().then(() => (init_serve(), serve_exports)); - await startServer.default(); + await startServer2(); } async function serve(args) { try { @@ -110964,7 +75476,7 @@ var module11 = { return serve(argv); } }; -init_esm7(); +init_esm6(); init_functions(); function isExternalKeyDescriptor(obj) { return obj !== null && typeof obj === "object" && typeof obj.pubkey === "string"; @@ -111191,8 +75703,8 @@ var UI = class { // if the full 'source' can render in // the target line, do so. renderInline(source, previousLine) { - const match = source.match(/^ */); - const leadingWhitespace = match ? match[0].length : 0; + const match2 = source.match(/^ */); + const leadingWhitespace = match2 ? match2[0].length : 0; const target = previousLine.text; const targetTextWidth = mixin.stringWidth(target.trimRight()); if (!previousLine.span) { @@ -111269,11 +75781,11 @@ var UI = class { return void 0; }); const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0; - return widths.map((w4, i2) => { - if (w4 === void 0) { + return widths.map((w3, i2) => { + if (w3 === void 0) { return Math.max(unsetWidth, _minWidth(row[i2])); } - return w4; + return w3; }); } }; @@ -111359,12 +75871,12 @@ function sync_default(start, callback) { let dir = resolve42(".", start); let tmp, stats = statSync(dir); if (!stats.isDirectory()) { - dir = dirname52(dir); + dir = dirname62(dir); } while (true) { tmp = callback(dir, readdirSync(dir)); if (tmp) return resolve42(dir, tmp); - dir = dirname52(tmp = dir); + dir = dirname62(tmp = dir); if (tmp === dir) break; } } @@ -112155,8 +76667,8 @@ var YargsParser = class { function hasFlagsMatching(arg, ...patterns) { const toCheck = [].concat(...patterns); return toCheck.some(function(pattern) { - const match = arg.match(pattern); - return match && hasAnyFlag(match[1]); + const match2 = arg.match(pattern); + return match2 && hasAnyFlag(match2[1]); }); } function hasAllShortFlags(arg) { @@ -112555,7 +77067,7 @@ var esm_default7 = { Parser: lib_default, path: { basename: basename62, - dirname: dirname62, + dirname: dirname72, extname: extname8, relative: relative22, resolve: resolve72 @@ -112592,7 +77104,7 @@ function assertSingleKey(actual, shim4) { function objectKeys(object2) { return Object.keys(object2); } -function isPromise(maybePromise) { +function isPromise2(maybePromise) { return !!maybePromise && !!maybePromise.then && typeof maybePromise.then === "function"; } function parseCommand(cmd) { @@ -112714,16 +77226,16 @@ function applyMiddleware(argv, yargs, middlewares, beforeValidation) { if (middleware.applyBeforeValidation !== beforeValidation) { return acc; } - if (isPromise(acc)) { + if (isPromise2(acc)) { return acc.then((initialObj) => Promise.all([ initialObj, middleware(initialObj, yargs) ])).then(([initialObj, middlewareObj]) => Object.assign(initialObj, middlewareObj)); } else { const result = middleware(acc, yargs); - if (beforeValidation && isPromise(result)) + if (beforeValidation && isPromise2(result)) throw beforeValidationError; - return isPromise(result) ? result.then((middlewareObj) => Object.assign(acc, middlewareObj)) : Object.assign(acc, result); + return isPromise2(result) ? result.then((middlewareObj) => Object.assign(acc, middlewareObj)) : Object.assign(acc, result); } }, argv); } @@ -112889,13 +77401,13 @@ function command(yargs, usage2, validation2, globalMiddleware = [], shim4) { yargs2._postProcess(innerArgv, populateDoubleDash); innerArgv = applyMiddleware(innerArgv, yargs2, middlewares, false); let handlerResult; - if (isPromise(innerArgv)) { + if (isPromise2(innerArgv)) { handlerResult = innerArgv.then((argv) => commandHandler.handler(argv)); } else { handlerResult = commandHandler.handler(innerArgv); } const handlerFinishCommand = yargs2.getHandlerFinishCommand(); - if (isPromise(handlerResult)) { + if (isPromise2(handlerResult)) { yargs2.getUsageInstance().cacheHelpMessage(); handlerResult.then((value) => { if (handlerFinishCommand) { @@ -113661,7 +78173,7 @@ function completion(yargs, usage2, command2, shim4) { assertNotStrictEqual(completionFunction, null, shim4); if (isSyncCompletionFunction(completionFunction)) { const result = completionFunction(current, argv2); - if (isPromise(result)) { + if (isPromise2(result)) { return result.then((list) => { shim4.process.nextTick(() => { done(list); @@ -113680,7 +78192,7 @@ function completion(yargs, usage2, command2, shim4) { } } if (completionFunction) { - return isPromise(argv) ? argv.then(runCompletionFunction) : runCompletionFunction(argv); + return isPromise2(argv) ? argv.then(runCompletionFunction) : runCompletionFunction(argv); } const handlers = command2.getCommandHandlers(); for (let i2 = 0, ii = args.length; i2 < ii; ++i2) { @@ -114618,7 +79130,7 @@ function Yargs(processArgs = [], cwd = shim3.process.cwd(), parentRequire) { } let parseFn = null; let parseContext = null; - self2.parse = function parse52(args, shortCircuit, _parseFn) { + self2.parse = function parse62(args, shortCircuit, _parseFn) { argsert("[string|array] [function|boolean|object] [function]", [args, shortCircuit, _parseFn], arguments.length); freeze(); if (typeof args === "undefined") { @@ -115124,7 +79636,7 @@ function Yargs(processArgs = [], cwd = shim3.process.cwd(), parentRequire) { return self2._postProcess(argv, populateDoubleDash, _calledFromCommand); }; self2._postProcess = function(argv, populateDoubleDash, calledFromCommand = false) { - if (isPromise(argv)) + if (isPromise2(argv)) return argv; if (calledFromCommand) return argv; @@ -115191,14 +79703,16 @@ function isYargsInstance(y) { } var Yargs2 = YargsWithShim(esm_default7); var yargs_default = Yargs2; -var postHandler = () => { +var handlerState = { + postHandler: () => { + } }; var parseArgs = () => { const handlerWrapper = (commandModule) => { return { ...commandModule, handler: (argv) => { - postHandler = () => commandModule.postHandler(argv); + handlerState.postHandler = () => commandModule.postHandler(argv); if (commandModule.handler) { return commandModule.handler(argv); } @@ -115208,7 +79722,8 @@ var parseArgs = () => { const commandModules = Object.values(commands_exports).map( (c) => handlerWrapper(c) ); - return yargs_default(hideBin(process13.argv)).version("3.2.1").strict().command(commandModules).demandCommand().help(); + const yargsInstance = yargs_default(hideBin(process13.argv)).version("3.2.1").strict().command(commandModules).demandCommand().help(); + return yargsInstance; }; var parseArgs_default = parseArgs; var parseConfig = () => { @@ -115247,13 +79762,8 @@ var parseConfig = () => { }); }; var parseConfig_default = parseConfig; -init_events2(); parseConfig_default(); -try { - await postHandler(); -} finally { - esm_default("okTurtles.events/emit", SERVER_EXITING); -} +await handlerState.postHandler(); /*! Bundled license information: scrypt-async/scrypt-async.js: diff --git a/build/serve/creditsWorker.js b/build/serve/creditsWorker.js index 814a512..cbc985a 100644 --- a/build/serve/creditsWorker.js +++ b/build/serve/creditsWorker.js @@ -1259,10 +1259,10 @@ var require_atomic_sleep = __commonJS({ var require_sonic_boom = __commonJS({ "node_modules/.deno/sonic-boom@3.8.1/node_modules/sonic-boom/index.js"(exports, module) { "use strict"; - var fs = __require2("fs"); - var EventEmitter = __require2("events"); - var inherits = __require2("util").inherits; - var path = __require2("path"); + var fs = __require2("node:fs"); + var EventEmitter = __require2("node:events"); + var inherits = __require2("node:util").inherits; + var path = __require2("node:path"); var sleep = require_atomic_sleep(); var BUSY_WRITE_TIMEOUT = 100; var kEmptyBuffer = Buffer.allocUnsafe(0); @@ -2028,17 +2028,17 @@ var require_thread_stream = __commonJS({ "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/index.js"(exports, module) { "use strict"; var { version } = require_package(); - var { EventEmitter } = __require2("events"); - var { Worker } = __require2("worker_threads"); - var { join } = __require2("path"); - var { pathToFileURL } = __require2("url"); + var { EventEmitter } = __require2("node:events"); + var { Worker } = __require2("node:worker_threads"); + var { join } = __require2("node:path"); + var { pathToFileURL } = __require2("node:url"); var { wait } = require_wait(); var { WRITE_INDEX, READ_INDEX } = require_indexes(); - var buffer = __require2("buffer"); - var assert = __require2("assert"); + var buffer = __require2("node:buffer"); + var assert = __require2("node:assert"); var kImpl = Symbol("kImpl"); var MAX_STRING = buffer.constants.MAX_STRING_LENGTH; var FakeWeakRef = class { @@ -2448,9 +2448,9 @@ var require_thread_stream = __commonJS({ var require_transport = __commonJS({ "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/transport.js"(exports, module) { "use strict"; - var { createRequire } = __require2("module"); + var { createRequire } = __require2("node:module"); var getCallers = require_caller(); - var { join, isAbsolute, sep } = __require2("path"); + var { join, isAbsolute, sep } = __require2("node:path"); var sleep = require_atomic_sleep(); var onExit = require_on_exit_leak_free(); var ThreadStream = require_thread_stream(); @@ -2584,7 +2584,7 @@ var require_tools = __commonJS({ nestedKeyStrSym, msgPrefixSym } = require_symbols(); - var { isMainThread } = __require2("worker_threads"); + var { isMainThread } = __require2("node:worker_threads"); var transport = require_transport(); function noop() { } @@ -3096,7 +3096,7 @@ var require_meta = __commonJS({ var require_proto = __commonJS({ "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/proto.js"(exports, module) { "use strict"; - var { EventEmitter } = __require2("events"); + var { EventEmitter } = __require2("node:events"); var { lsCacheSym, levelValSym, @@ -4043,7 +4043,7 @@ var require_multistream = __commonJS({ var require_pino = __commonJS({ "node_modules/.deno/pino@8.19.0/node_modules/pino/pino.js"(exports, module) { "use strict"; - var os = __require2("os"); + var os = __require2("node:os"); var stdSerializers = require_pino_std_serializers(); var caller = require_caller(); var redaction = require_redaction(); @@ -4633,11 +4633,17 @@ if (Object.keys(logger.levels.values).includes(logLevel)) { } else { logger.warn(`Unknown log level: ${logLevel}`); } -console.debug = logger.debug.bind(logger); -console.info = logger.info.bind(logger); -console.log = logger.info.bind(logger); -console.warn = logger.warn.bind(logger); -console.error = logger.error.bind(logger); +var loggerInitialized = false; +function initializeLogger() { + if (loggerInitialized) return; + loggerInitialized = true; + console.debug = logger.debug.bind(logger); + console.info = logger.info.bind(logger); + console.log = logger.info.bind(logger); + console.warn = logger.warn.bind(logger); + console.error = logger.error.bind(logger); +} +initializeLogger(); Object.defineProperties(Buffer2, { [serdesDeserializeSymbol]: { value(buf) { diff --git a/build/serve/ownerSizeTotalWorker.js b/build/serve/ownerSizeTotalWorker.js index deaef25..2744f84 100644 --- a/build/serve/ownerSizeTotalWorker.js +++ b/build/serve/ownerSizeTotalWorker.js @@ -1259,10 +1259,10 @@ var require_atomic_sleep = __commonJS({ var require_sonic_boom = __commonJS({ "node_modules/.deno/sonic-boom@3.8.1/node_modules/sonic-boom/index.js"(exports, module) { "use strict"; - var fs = __require2("fs"); - var EventEmitter = __require2("events"); - var inherits = __require2("util").inherits; - var path = __require2("path"); + var fs = __require2("node:fs"); + var EventEmitter = __require2("node:events"); + var inherits = __require2("node:util").inherits; + var path = __require2("node:path"); var sleep = require_atomic_sleep(); var BUSY_WRITE_TIMEOUT = 100; var kEmptyBuffer = Buffer.allocUnsafe(0); @@ -2028,17 +2028,17 @@ var require_thread_stream = __commonJS({ "node_modules/.deno/thread-stream@2.7.0/node_modules/thread-stream/index.js"(exports, module) { "use strict"; var { version } = require_package(); - var { EventEmitter } = __require2("events"); - var { Worker } = __require2("worker_threads"); - var { join } = __require2("path"); - var { pathToFileURL } = __require2("url"); + var { EventEmitter } = __require2("node:events"); + var { Worker } = __require2("node:worker_threads"); + var { join } = __require2("node:path"); + var { pathToFileURL } = __require2("node:url"); var { wait } = require_wait(); var { WRITE_INDEX, READ_INDEX } = require_indexes(); - var buffer = __require2("buffer"); - var assert = __require2("assert"); + var buffer = __require2("node:buffer"); + var assert = __require2("node:assert"); var kImpl = Symbol("kImpl"); var MAX_STRING = buffer.constants.MAX_STRING_LENGTH; var FakeWeakRef = class { @@ -2448,9 +2448,9 @@ var require_thread_stream = __commonJS({ var require_transport = __commonJS({ "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/transport.js"(exports, module) { "use strict"; - var { createRequire } = __require2("module"); + var { createRequire } = __require2("node:module"); var getCallers = require_caller(); - var { join, isAbsolute, sep } = __require2("path"); + var { join, isAbsolute, sep } = __require2("node:path"); var sleep = require_atomic_sleep(); var onExit = require_on_exit_leak_free(); var ThreadStream = require_thread_stream(); @@ -2584,7 +2584,7 @@ var require_tools = __commonJS({ nestedKeyStrSym, msgPrefixSym } = require_symbols(); - var { isMainThread } = __require2("worker_threads"); + var { isMainThread } = __require2("node:worker_threads"); var transport = require_transport(); function noop() { } @@ -3096,7 +3096,7 @@ var require_meta = __commonJS({ var require_proto = __commonJS({ "node_modules/.deno/pino@8.19.0/node_modules/pino/lib/proto.js"(exports, module) { "use strict"; - var { EventEmitter } = __require2("events"); + var { EventEmitter } = __require2("node:events"); var { lsCacheSym, levelValSym, @@ -4043,7 +4043,7 @@ var require_multistream = __commonJS({ var require_pino = __commonJS({ "node_modules/.deno/pino@8.19.0/node_modules/pino/pino.js"(exports, module) { "use strict"; - var os = __require2("os"); + var os = __require2("node:os"); var stdSerializers = require_pino_std_serializers(); var caller = require_caller(); var redaction = require_redaction(); @@ -4718,11 +4718,17 @@ if (Object.keys(logger.levels.values).includes(logLevel)) { } else { logger.warn(`Unknown log level: ${logLevel}`); } -console.debug = logger.debug.bind(logger); -console.info = logger.info.bind(logger); -console.log = logger.info.bind(logger); -console.warn = logger.warn.bind(logger); -console.error = logger.error.bind(logger); +var loggerInitialized = false; +function initializeLogger() { + if (loggerInitialized) return; + loggerInitialized = true; + console.debug = logger.debug.bind(logger); + console.info = logger.info.bind(logger); + console.log = logger.info.bind(logger); + console.warn = logger.warn.bind(logger); + console.error = logger.error.bind(logger); +} +initializeLogger(); Object.defineProperties(Buffer2, { [serdesDeserializeSymbol]: { value(buf) { diff --git a/deno.json b/deno.json index f695c5c..8920949 100644 --- a/deno.json +++ b/deno.json @@ -45,18 +45,14 @@ "npm:vuelidate": "npm:vuelidate@0.7.6", "npm:vuex": "npm:vuex@3.6.0", "npm:multiformats/": "npm:multiformats@11.0.2/", - "npm:@hapi/hapi": "npm:@hapi/hapi@21.4.3", - "npm:@hapi/boom": "npm:@hapi/boom@10.0.1", "npm:@chelonia/lib/": "npm:@chelonia/lib@1.2.9/", "npm:lru-cache": "npm:lru-cache@7.14.0", "npm:pino": "npm:pino@8.19.0", "npm:tweetnacl": "npm:tweetnacl@1.0.3", - "npm:@hapi/inert": "npm:@hapi/inert@7.1.0", "npm:chalk": "npm:chalk@4.1.0", "npm:ws": "npm:ws@8.5.0", "npm:zod": "npm:zod@4.0.5", "npm:@types/ws": "npm:@types/ws@8.5.10", - "npm:joi": "npm:joi@18.0.1", "npm:bottleneck": "npm:bottleneck@2.19.5", "npm:@apeleghq/rfc8188/": "npm:@apeleghq/rfc8188@1.0.7/", "npm:redis": "npm:redis@5.9.0", @@ -65,7 +61,12 @@ "npm:@types/nconf": "npm:@types/nconf@0.10.7", "npm:@types/yargs": "npm:@types/yargs@17.0.34", "npm:smol-toml": "npm:smol-toml@1.4.2", - "npm:@chelonia/serdes": "npm:@chelonia/serdes@1.0.0" + "npm:@chelonia/serdes": "npm:@chelonia/serdes@1.0.0", + "npm:hono": "npm:hono@4.12.12", + "npm:hono/": "npm:hono@4.12.12/", + "npm:@hono/node-server": "npm:@hono/node-server@1.19.14", + "npm:@hono/node-server/": "npm:@hono/node-server@1.19.14/", + "npm:@hono/zod-validator": "npm:@hono/zod-validator@0.7.6" }, "nodeModulesDir": "auto", "fmt": { diff --git a/deno.lock b/deno.lock index 49b2504..6998d96 100644 --- a/deno.lock +++ b/deno.lock @@ -22,7 +22,7 @@ "jsr:@std/path@1.1.1": "1.1.1", "jsr:@std/path@^1.1.3": "1.1.3", "jsr:@std/streams@1.0.10": "1.0.10", - "npm:@apeleghq/rfc8188@*": "1.0.7", + "npm:@apeleghq/rfc8188@*": "1.0.8", "npm:@apeleghq/rfc8188@1.0.7": "1.0.7", "npm:@chelonia/crypto@*": "1.0.1", "npm:@chelonia/lib@*": "1.2.9_@sbp+sbp@2.4.1", @@ -30,9 +30,9 @@ "npm:@chelonia/lib@1.2.9": "1.2.9_@sbp+sbp@2.4.1", "npm:@chelonia/serdes@1.0.0": "1.0.0", "npm:@eslint/js@9.31.0": "9.31.0", - "npm:@hapi/boom@10.0.1": "10.0.1", - "npm:@hapi/hapi@21.4.3": "21.4.3", - "npm:@hapi/inert@7.1.0": "7.1.0", + "npm:@hono/node-server@*": "1.19.14_hono@4.12.12", + "npm:@hono/node-server@1.19.14": "1.19.14_hono@4.12.12", + "npm:@hono/zod-validator@0.7.6": "0.7.6_hono@4.12.12_zod@4.0.5", "npm:@sbp/okturtles.data@0.1.5": "0.1.5_@sbp+sbp@2.4.1", "npm:@sbp/okturtles.data@0.1.7": "0.1.7_@sbp+sbp@2.4.1", "npm:@sbp/okturtles.eventqueue@1.2.0": "1.2.0_@sbp+sbp@2.4.1", @@ -47,11 +47,12 @@ "npm:bottleneck@2.19.5": "2.19.5", "npm:chalk@4.1.0": "4.1.0", "npm:dompurify@2.4.2": "2.4.2", - "npm:esbuild-sass-plugin@3.3.1": "3.3.1_esbuild@0.25.6_sass-embedded@1.93.3", + "npm:esbuild-sass-plugin@3.3.1": "3.3.1_esbuild@0.25.8", "npm:esbuild@0.25.6": "0.25.6", "npm:esbuild@0.25.8": "0.25.8", "npm:eslint@9.31.0": "9.31.0", - "npm:joi@18.0.1": "18.0.1", + "npm:hono@*": "4.12.12", + "npm:hono@4.12.12": "4.12.12", "npm:lru-cache@7.14.0": "7.14.0", "npm:multiformats@*": "11.0.2", "npm:multiformats@11.0.2": "11.0.2", @@ -558,247 +559,17 @@ "levn" ] }, - "@hapi/accept@6.0.3": { - "integrity": "sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==", + "@hono/node-server@1.19.14_hono@4.12.12": { + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", "dependencies": [ - "@hapi/boom", - "@hapi/hoek" + "hono" ] }, - "@hapi/address@5.1.1": { - "integrity": "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==", + "@hono/zod-validator@0.7.6_hono@4.12.12_zod@4.0.5": { + "integrity": "sha512-Io1B6d011Gj1KknV4rXYz4le5+5EubcWEU/speUjuw9XMMIaP3n78yXLhjd2A3PXaXaUwEAluOiAyLqhBEJgsw==", "dependencies": [ - "@hapi/hoek" - ] - }, - "@hapi/ammo@6.0.1": { - "integrity": "sha512-pmL+nPod4g58kXrMcsGLp05O2jF4P2Q3GiL8qYV7nKYEh3cGf+rV4P5Jyi2Uq0agGhVU63GtaSAfBEZOlrJn9w==", - "dependencies": [ - "@hapi/hoek" - ] - }, - "@hapi/b64@6.0.1": { - "integrity": "sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw==", - "dependencies": [ - "@hapi/hoek" - ] - }, - "@hapi/boom@10.0.1": { - "integrity": "sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==", - "dependencies": [ - "@hapi/hoek" - ] - }, - "@hapi/bounce@3.0.2": { - "integrity": "sha512-d0XmlTi3H9HFDHhQLjg4F4auL1EY3Wqj7j7/hGDhFFe6xAbnm3qiGrXeT93zZnPH8gH+SKAFYiRzu26xkXcH3g==", - "dependencies": [ - "@hapi/boom", - "@hapi/hoek" - ] - }, - "@hapi/bourne@3.0.0": { - "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==" - }, - "@hapi/call@9.0.1": { - "integrity": "sha512-uPojQRqEL1GRZR4xXPqcLMujQGaEpyVPRyBlD8Pp5rqgIwLhtveF9PkixiKru2THXvuN8mUrLeet5fqxKAAMGg==", - "dependencies": [ - "@hapi/boom", - "@hapi/hoek" - ] - }, - "@hapi/catbox-memory@6.0.2": { - "integrity": "sha512-H1l4ugoFW/ZRkqeFrIo8p1rWN0PA4MDTfu4JmcoNDvnY975o29mqoZblqFTotxNHlEkMPpIiIBJTV+Mbi+aF0g==", - "dependencies": [ - "@hapi/boom", - "@hapi/hoek" - ] - }, - "@hapi/catbox@12.1.1": { - "integrity": "sha512-hDqYB1J+R0HtZg4iPH3LEnldoaBsar6bYp0EonBmNQ9t5CO+1CqgCul2ZtFveW1ReA5SQuze9GPSU7/aecERhw==", - "dependencies": [ - "@hapi/boom", - "@hapi/hoek", - "@hapi/podium", - "@hapi/validate" - ] - }, - "@hapi/content@6.0.0": { - "integrity": "sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==", - "dependencies": [ - "@hapi/boom" - ] - }, - "@hapi/cryptiles@6.0.1": { - "integrity": "sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==", - "dependencies": [ - "@hapi/boom" - ] - }, - "@hapi/file@3.0.0": { - "integrity": "sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==" - }, - "@hapi/formula@3.0.2": { - "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==" - }, - "@hapi/hapi@21.4.3": { - "integrity": "sha512-Q7g0ZY4gxU69wabFKH75qR0AFOdiOECj6vGqTHBSO5Lrwe6TwD8r9LkYQIbvtG8N423VDpdVsiZP8MnBwmD6Hw==", - "dependencies": [ - "@hapi/accept", - "@hapi/ammo", - "@hapi/boom", - "@hapi/bounce", - "@hapi/call", - "@hapi/catbox", - "@hapi/catbox-memory", - "@hapi/heavy", - "@hapi/hoek", - "@hapi/mimos", - "@hapi/podium", - "@hapi/shot", - "@hapi/somever", - "@hapi/statehood", - "@hapi/subtext", - "@hapi/teamwork", - "@hapi/topo", - "@hapi/validate" - ] - }, - "@hapi/heavy@8.0.1": { - "integrity": "sha512-gBD/NANosNCOp6RsYTsjo2vhr5eYA3BEuogk6cxY0QdhllkkTaJFYtTXv46xd6qhBVMbMMqcSdtqey+UQU3//w==", - "dependencies": [ - "@hapi/boom", - "@hapi/hoek", - "@hapi/validate" - ] - }, - "@hapi/hoek@11.0.7": { - "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==" - }, - "@hapi/inert@7.1.0": { - "integrity": "sha512-5X+cl/Ozm0U9uPGGX1dSKhnhTQIf161bH/kkTN9OBVAZKFG+nrj8j/NMj6S1zBBZWmQrkVRNPfCUGrXzB4fCFQ==", - "dependencies": [ - "@hapi/ammo", - "@hapi/boom", - "@hapi/bounce", - "@hapi/hoek", - "@hapi/validate", - "lru-cache@7.18.3" - ] - }, - "@hapi/iron@7.0.1": { - "integrity": "sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ==", - "dependencies": [ - "@hapi/b64", - "@hapi/boom", - "@hapi/bourne", - "@hapi/cryptiles", - "@hapi/hoek" - ] - }, - "@hapi/mimos@7.0.1": { - "integrity": "sha512-b79V+BrG0gJ9zcRx1VGcCI6r6GEzzZUgiGEJVoq5gwzuB2Ig9Cax8dUuBauQCFKvl2YWSWyOc8mZ8HDaJOtkew==", - "dependencies": [ - "@hapi/hoek", - "mime-db" - ] - }, - "@hapi/nigel@5.0.1": { - "integrity": "sha512-uv3dtYuB4IsNaha+tigWmN8mQw/O9Qzl5U26Gm4ZcJVtDdB1AVJOwX3X5wOX+A07qzpEZnOMBAm8jjSqGsU6Nw==", - "dependencies": [ - "@hapi/hoek", - "@hapi/vise" - ] - }, - "@hapi/pez@6.1.0": { - "integrity": "sha512-+FE3sFPYuXCpuVeHQ/Qag1b45clR2o54QoonE/gKHv9gukxQ8oJJZPR7o3/ydDTK6racnCJXxOyT1T93FCJMIg==", - "dependencies": [ - "@hapi/b64", - "@hapi/boom", - "@hapi/content", - "@hapi/hoek", - "@hapi/nigel" - ] - }, - "@hapi/pinpoint@2.0.1": { - "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==" - }, - "@hapi/podium@5.0.2": { - "integrity": "sha512-T7gf2JYHQQfEfewTQFbsaXoZxSvuXO/QBIGljucUQ/lmPnTTNAepoIKOakWNVWvo2fMEDjycu77r8k6dhreqHA==", - "dependencies": [ - "@hapi/hoek", - "@hapi/teamwork", - "@hapi/validate" - ] - }, - "@hapi/shot@6.0.2": { - "integrity": "sha512-WKK1ShfJTrL1oXC0skoIZQYzvLsyMDEF8lfcWuQBjpjCN29qivr9U36ld1z0nt6edvzv28etNMOqUF4klnHryw==", - "dependencies": [ - "@hapi/hoek", - "@hapi/validate" - ] - }, - "@hapi/somever@4.1.1": { - "integrity": "sha512-lt3QQiDDOVRatS0ionFDNrDIv4eXz58IibQaZQDOg4DqqdNme8oa0iPWcE0+hkq/KTeBCPtEOjDOBKBKwDumVg==", - "dependencies": [ - "@hapi/bounce", - "@hapi/hoek" - ] - }, - "@hapi/statehood@8.2.0": { - "integrity": "sha512-63JlCVIrsmuunWsyc3OeuFO+gH6v56swLCl7OM1w09l/exQKPUxSUDF2Slkuw8k91nIzr0A2/aPvjLOWf9ksrg==", - "dependencies": [ - "@hapi/boom", - "@hapi/bounce", - "@hapi/bourne", - "@hapi/cryptiles", - "@hapi/hoek", - "@hapi/iron", - "@hapi/validate" - ] - }, - "@hapi/subtext@8.1.1": { - "integrity": "sha512-ex1Y2s/KuJktS8Ww0k6XJ5ysSKrzNym4i5pDVuCwlSgHHviHUsT1JNzE6FYhNU9TTHSNdyfue/t2m89bpkX9Jw==", - "dependencies": [ - "@hapi/boom", - "@hapi/bourne", - "@hapi/content", - "@hapi/file", - "@hapi/hoek", - "@hapi/pez", - "@hapi/wreck" - ] - }, - "@hapi/teamwork@6.0.1": { - "integrity": "sha512-52OXRslUfYwXAOG8k58f2h2ngXYQGP0x5RPOo+eWA/FtyLgHjGMrE3+e9LSXP/0q2YfHAK5wj9aA9DTy1K+kyQ==" - }, - "@hapi/tlds@1.1.3": { - "integrity": "sha512-QIvUMB5VZ8HMLZF9A2oWr3AFM430QC8oGd0L35y2jHpuW6bIIca6x/xL7zUf4J7L9WJ3qjz+iJII8ncaeMbpSg==" - }, - "@hapi/topo@6.0.2": { - "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", - "dependencies": [ - "@hapi/hoek" - ] - }, - "@hapi/validate@2.0.1": { - "integrity": "sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==", - "dependencies": [ - "@hapi/hoek", - "@hapi/topo" - ] - }, - "@hapi/vise@5.0.1": { - "integrity": "sha512-XZYWzzRtINQLedPYlIkSkUr7m5Ddwlu99V9elh8CSygXstfv3UnWIXT0QD+wmR0VAG34d2Vx3olqcEhRRoTu9A==", - "dependencies": [ - "@hapi/hoek" - ] - }, - "@hapi/wreck@18.1.0": { - "integrity": "sha512-0z6ZRCmFEfV/MQqkQomJ7sl/hyxvcZM7LtuVqN3vdAO4vM9eBbowl0kaqQj9EJJQab+3Uuh1GxbGIBFy4NfJ4w==", - "dependencies": [ - "@hapi/boom", - "@hapi/bourne", - "@hapi/hoek" + "hono", + "zod" ] }, "@humanfs/core@0.19.1": { @@ -1008,9 +779,6 @@ "@sbp/sbp@2.4.1": { "integrity": "sha512-k6Blz95Gl1KlTc/PHNRMCQDD3niZ1p5tTHOzABiLo82YYQe8UGNl/AiastIJ8GfByW7M/VHLYLsQEK/41Skx3g==" }, - "@standard-schema/spec@1.0.0": { - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==" - }, "@tweenjs/tween.js@23.1.3": { "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==" }, @@ -1023,16 +791,10 @@ "@types/nconf@0.10.7": { "integrity": "sha512-ltJgbQX0XgjkeDrz0anTCXLBLatppWYFCxp88ILEwybfAuyNWr0Qb+ceFFqZ0VDR8fguEjr0hH37ZF+AF4gsxw==" }, - "@types/node@22.15.15": { - "integrity": "sha512-R5muMcZob3/Jjchn5LcO8jdKwSCbzqmPB6ruBxMcf9kbxtniZHP327s6C37iOfuw8mbKK3cAQa7sEl7afLrQ8A==", - "dependencies": [ - "undici-types@6.21.0" - ] - }, "@types/node@24.0.13": { "integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==", "dependencies": [ - "undici-types@7.8.0" + "undici-types" ] }, "@types/stats.js@0.17.4": { @@ -1056,7 +818,7 @@ "@types/ws@8.5.10": { "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dependencies": [ - "@types/node@22.15.15" + "@types/node" ] }, "@types/yargs-parser@21.0.3": { @@ -1557,10 +1319,10 @@ "es-errors" ] }, - "esbuild-sass-plugin@3.3.1_esbuild@0.25.6_sass-embedded@1.93.3": { + "esbuild-sass-plugin@3.3.1_esbuild@0.25.8": { "integrity": "sha512-SnO1ls+d52n6j8gRRpjexXI8MsHEaumS0IdDHaYM29Y6gakzZYMls6i9ql9+AWMSQk/eryndmUpXEgT34QrX1A==", "dependencies": [ - "esbuild@0.25.6", + "esbuild@0.25.8", "resolve", "safe-identifier", "sass", @@ -1901,6 +1663,9 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "bin": true }, + "hono@4.12.12": { + "integrity": "sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q==" + }, "icss-replace-symbols@1.1.0": { "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==" }, @@ -1990,18 +1755,6 @@ "isexe@2.0.0": { "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "joi@18.0.1": { - "integrity": "sha512-IiQpRyypSnLisQf3PwuN2eIHAsAIGZIrLZkd4zdvIar2bDyhM91ubRjy8a3eYablXsh9BeI/c7dmPYHca5qtoA==", - "dependencies": [ - "@hapi/address", - "@hapi/formula", - "@hapi/hoek", - "@hapi/pinpoint", - "@hapi/tlds", - "@hapi/topo", - "@standard-schema/spec" - ] - }, "js-base64@2.6.4": { "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" }, @@ -2103,9 +1856,6 @@ "lru-cache@7.14.0": { "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==" }, - "lru-cache@7.18.3": { - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, "make-dir@2.1.0": { "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dependencies": [ @@ -2135,9 +1885,6 @@ "picomatch" ] }, - "mime-db@1.54.0": { - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==" - }, "mime@1.6.0": { "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "bin": true @@ -2918,9 +2665,6 @@ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "bin": true }, - "undici-types@6.21.0": { - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" - }, "undici-types@7.8.0": { "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==" }, @@ -3063,9 +2807,8 @@ "npm:@chelonia/lib@1.2.9", "npm:@chelonia/serdes@1.0.0", "npm:@eslint/js@9.31.0", - "npm:@hapi/boom@10.0.1", - "npm:@hapi/hapi@21.4.3", - "npm:@hapi/inert@7.1.0", + "npm:@hono/node-server@1.19.14", + "npm:@hono/zod-validator@0.7.6", "npm:@sbp/okturtles.data@0.1.7", "npm:@sbp/okturtles.eventqueue@1.2.0", "npm:@sbp/okturtles.events@1.0.0", @@ -3081,7 +2824,7 @@ "npm:dompurify@2.4.2", "npm:esbuild-sass-plugin@3.3.1", "npm:esbuild@0.25.8", - "npm:joi@18.0.1", + "npm:hono@4.12.12", "npm:lru-cache@7.14.0", "npm:multiformats@11.0.2", "npm:nconf@0.13.0", diff --git a/scripts/build.ts b/scripts/build.ts index 0003783..74faad3 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -2,9 +2,12 @@ import * as esbuild from 'npm:esbuild@0.25.6' import * as colors from 'jsr:@std/fmt/colors' +import { builtinModules } from 'node:module' const { default: { version } } = await import('../package.json', { with: { type: 'json' } }) +const nodeBuiltins = new Set(builtinModules.filter((m: string) => !m.startsWith('_'))) + const options: esbuild.BuildOptions = { entryPoints: [ './src/main.ts', @@ -16,6 +19,7 @@ const options: esbuild.BuildOptions = { 'import.meta.VERSION': JSON.stringify(version), 'import.meta.ownerSizeTotalWorker': '"./serve/ownerSizeTotalWorker.js"', 'import.meta.creditsWorker': '"./serve/creditsWorker.js"', + 'import.meta.initDbOnce': 'true' }, format: 'esm', platform: 'node', @@ -29,6 +33,17 @@ const options: esbuild.BuildOptions = { build.onResolve({ filter: /^npm:/, namespace: 'file' }, ({ path, ...args }) => build.resolve(path.slice(4), args)) } }, + { + name: 'node-builtins', + setup (build) { + build.onResolve({ filter: /^[0-9a-zA-Z_/]+$/, namespace: 'file' }, ({ path }) => { + if (nodeBuiltins.has(path)) { + return { path: `node:${path}`, external: true } + } + return null + }) + } + }, { name: 'skip', setup (build) { diff --git a/src/eventsAfter.ts b/src/eventsAfter.ts index 8cf7126..d420a88 100644 --- a/src/eventsAfter.ts +++ b/src/eventsAfter.ts @@ -3,12 +3,13 @@ import * as base64 from 'jsr:@std/encoding/base64' import sbp from 'npm:@sbp/sbp' import type { ArgumentsCamelCase, CommandModule } from './commands.ts' -import { initDB } from './serve/database.ts' +import { closeDB, initDB } from './serve/database.ts' import { exit } from './utils.ts' type Params = { limit: number, url: string | undefined, contractID: string, height: number } export async function eventsAfter ({ limit, url, contractID, height }: ArgumentsCamelCase): Promise { + let dbOpen = false try { let messages @@ -16,11 +17,16 @@ export async function eventsAfter ({ limit, url, contractID, height }: Arguments messages = await getRemoteMessagesSince(url, contractID, height, limit) } else { await initDB({ skipDbPreloading: true }) + dbOpen = true messages = await getMessagesSince(contractID, height, limit) } console.log(JSON.stringify(messages, null, 2)) } catch (error) { exit(error) + } finally { + if (dbOpen) { + await closeDB() + } } } @@ -50,7 +56,7 @@ async function getMessagesSince (contractID: string, sinceHeight: number, limit: async function getRemoteMessagesSince (src: string, contractID: string, sinceHeight: number, limit: number): Promise { const response = await fetch(`${src}/eventsAfter/${contractID}/${sinceHeight}`) if (!response.ok) { - // The response body may contain some useful error info if we got a Boom error response. + // The response body may contain some useful error info. const bodyText = await response.text().catch(() => '') || '' throw new Error(`failed network request to ${src}: ${response.status} - ${response.statusText} - '${bodyText}'`) } diff --git a/src/get.ts b/src/get.ts index 4e89536..591e065 100644 --- a/src/get.ts +++ b/src/get.ts @@ -10,14 +10,16 @@ chel get https://url.com mygreatlongkey > file.png import { writeAll } from 'jsr:@std/io/' import sbp from 'npm:@sbp/sbp' import type { ArgumentsCamelCase, CommandModule } from './commands.ts' -import { initDB } from './serve/database.ts' +import { closeDB, initDB } from './serve/database.ts' import { exit, readRemoteData } from './utils.ts' type Params = { url?: string, key: string } export async function get ({ key, url }: ArgumentsCamelCase): Promise { + let dbOpen = false if (!url) { await initDB({ skipDbPreloading: true }) + dbOpen = true } try { @@ -35,6 +37,10 @@ export async function get ({ key, url }: ArgumentsCamelCase): Promise): Promise throw e } - let backendTo: DatabaseBackend + let backendTo: DatabaseBackend | undefined try { - let toConfigOpts: unknown - if (args.toConfig) { - const toConfig = parse(await readFile(args.toConfig, { encoding: 'utf-8', flag: 'r' })) - const toBackend = (toConfig?.database as TomlTable)?.backend as string - if (toBackend !== to) { - console.warn(`--to-config has backend ${toBackend} but --to is ${to}`) + try { + let toConfigOpts: unknown + if (args.toConfig) { + const toConfig = parse(await readFile(args.toConfig, { encoding: 'utf-8', flag: 'r' })) + const toBackend = (toConfig?.database as TomlTable)?.backend as string + if (toBackend !== to) { + console.warn(`--to-config has backend ${toBackend} but --to is ${to}`) + } + toConfigOpts = ((toConfig?.database as TomlTable)?.backendOptions as TomlTable)?.[to] || {} + } else { + toConfigOpts = nconf.get(`database:backendOptions:${to}`) || {} } - toConfigOpts = ((toConfig?.database as TomlTable)?.backendOptions as TomlTable)?.[to] || {} - } else { - toConfigOpts = nconf.get(`database:backendOptions:${to}`) || {} - } - const Ctor = (await import(`./serve/database-${to}.ts`)).default - backendTo = new Ctor(toConfigOpts) - await backendTo.init() - } catch (error) { - exit(error) - throw error - } + const Ctor = (await import(`./serve/database-${to}.ts`)).default + backendTo = new Ctor(toConfigOpts) + await backendTo!.init() + } catch (error) { + exit(error) + throw error + } - const numKeys = await sbp('chelonia.db/keyCount') - let numMigratedKeys = 0 - let numVisitedKeys = 0 + const numKeys = await sbp('chelonia.db/keyCount') + let numMigratedKeys = 0 + let numVisitedKeys = 0 - const reportStatus = () => { - console.log(`${colors.green('Migrated:')} ${numMigratedKeys} entries`) - } + const reportStatus = () => { + console.log(`${colors.green('Migrated:')} ${numMigratedKeys} entries`) + } - const checkAndExit = (() => { - let interruptCount = 0 - let shouldExit = 0 + const checkAndExit = (() => { + let interruptCount = 0 + let shouldExit = 0 - const handleSignal = (signal: string, code: number) => { - process.on(signal, () => { + const handleSignal = (signal: string, code: number) => { + process.on(signal, () => { // Exit codes follow the 128 + signal code convention. // See - shouldExit = 128 + code + shouldExit = 128 + code + + if (++interruptCount < 3) { + console.error(`Received signal ${signal} (${code}). Finishing current operation.`) + } else { + console.error(`Received signal ${signal} (${code}). Force quitting.`) + reportStatus() + exit(shouldExit) + } + }) + } - if (++interruptCount < 3) { - console.error(`Received signal ${signal} (${code}). Finishing current operation.`) - } else { - console.error(`Received signal ${signal} (${code}). Force quitting.`) + const checkAndExit = async () => { + if (shouldExit) { + await backendTo!.close() reportStatus() exit(shouldExit) } - }) - } - - const checkAndExit = async () => { - if (shouldExit) { - await backendTo.close() - reportStatus() - exit(shouldExit) } - } // Codes from ;([ - ['SIGHUP', 1], - ['SIGINT', 2], - ['SIGQUIT', 3], - ['SIGTERM', 15], - ['SIGUSR1', 10], - ['SIGUSR2', 11] - ] as [string, number][]).forEach(([signal, code]) => handleSignal(signal, code)) - - return checkAndExit - })() - - let lastReportedPercentage = 0 - for await (const key of sbp('chelonia.db/iterKeys')) { - numVisitedKeys++ - if (!isValidKey(key)) { - console.debug('Skipping invalid key', key) - continue - } - // `any:` prefix needed to get the raw value, else the default is getting - // a string, which will be encoded as UTF-8. This can cause data loss. - let value: Buffer | string | undefined - try { - value = await sbp('chelonia.db/get', `any:${key}`) - } catch (e) { - reportStatus() - console.error(`Error reading from source database key '${key}'`, e) - await backendTo.close() - exit(1) - throw e - } - await checkAndExit() - // Make `deno check` happy. - if (value === undefined) { - console.debug('Skipping empty key', key) - continue - } - try { - await backendTo.writeData(key, value) - } catch (e) { - reportStatus() - console.error(`Error writing to target database key '${key}'`, e) - await backendTo.close() - exit(1) - throw e - } - await checkAndExit() - ++numMigratedKeys - // Prints a message roughly every 10% of progress. - const percentage = Math.floor((numVisitedKeys / numKeys) * 100) - if (percentage - lastReportedPercentage >= 10) { - lastReportedPercentage = percentage - console.log(`Migrating... ${percentage}% done`) + ['SIGHUP', 1], + ['SIGINT', 2], + ['SIGQUIT', 3], + ['SIGTERM', 15], + ['SIGUSR1', 10], + ['SIGUSR2', 11] + ] as [string, number][]).forEach(([signal, code]) => handleSignal(signal, code)) + + return checkAndExit + })() + + let lastReportedPercentage = 0 + for await (const key of sbp('chelonia.db/iterKeys')) { + numVisitedKeys++ + if (!isValidKey(key)) { + console.debug('Skipping invalid key', key) + continue + } + // `any:` prefix needed to get the raw value, else the default is getting + // a string, which will be encoded as UTF-8. This can cause data loss. + let value: Buffer | string | undefined + try { + value = await sbp('chelonia.db/get', `any:${key}`) + } catch (e) { + reportStatus() + console.error(`Error reading from source database key '${key}'`, e) + exit(1) + throw e + } + await checkAndExit() + // Make `deno check` happy. + if (value === undefined) { + console.debug('Skipping empty key', key) + continue + } + try { + await backendTo!.writeData(key, value) + } catch (e) { + reportStatus() + console.error(`Error writing to target database key '${key}'`, e) + exit(1) + throw e + } + await checkAndExit() + ++numMigratedKeys + // Prints a message roughly every 10% of progress. + const percentage = Math.floor((numVisitedKeys / numKeys) * 100) + if (percentage - lastReportedPercentage >= 10) { + lastReportedPercentage = percentage + console.log(`Migrating... ${percentage}% done`) + } } + reportStatus() + } finally { + await Promise.all([backendTo?.close(), closeDB()]) } - reportStatus() - await backendTo.close() } export const module = { diff --git a/src/parseArgs.ts b/src/parseArgs.ts index bd13d3e..81d1a70 100644 --- a/src/parseArgs.ts +++ b/src/parseArgs.ts @@ -5,14 +5,17 @@ import * as commands from './commands.ts' import yargs, { type ArgumentsCamelCase, type CommandModule as YCommandModule } from 'npm:yargs' import { hideBin } from 'npm:yargs/helpers' -let postHandler: () => void | Promise = () => {} +// Use an object to hold the handler to ensure live binding works +const handlerState: { postHandler: () => void | Promise } = { + postHandler: () => {} +} const parseArgs = () => { const handlerWrapper = (commandModule: commands.CommandModule): YCommandModule => { return { ...commandModule, handler: (argv: ArgumentsCamelCase) => { - postHandler = () => commandModule.postHandler(argv) + handlerState.postHandler = () => commandModule.postHandler(argv) if (commandModule.handler) { return commandModule.handler(argv) } @@ -25,13 +28,15 @@ const parseArgs = () => { (c) => handlerWrapper(c as commands.CommandModule) ) - return yargs(hideBin(process.argv)) + const yargsInstance = yargs(hideBin(process.argv)) .version(import.meta.VERSION) .strict() .command(commandModules) .demandCommand() .help() + + return yargsInstance } export default parseArgs -export { postHandler } +export { handlerState } diff --git a/src/parseConfig.ts b/src/parseConfig.ts index 6fa850f..1819bdd 100644 --- a/src/parseConfig.ts +++ b/src/parseConfig.ts @@ -1,7 +1,7 @@ // @deno-types="npm:@types/nconf" import nconf from 'npm:nconf' import { parse, stringify } from 'npm:smol-toml' -import parseArgs from './parseArgs.ts' +import parseArgs, { handlerState } from './parseArgs.ts' const parseConfig = () => { nconf @@ -44,4 +44,4 @@ const parseConfig = () => { } export default parseConfig -export { postHandler } from './parseArgs.ts' +export { handlerState } diff --git a/src/serve.ts b/src/serve.ts index d739341..9bcf4ab 100644 --- a/src/serve.ts +++ b/src/serve.ts @@ -5,6 +5,8 @@ import { debounce } from 'npm:turtledash' import type { ArgumentsCamelCase, CommandModule } from './commands.ts' import { deploy } from './deploy.ts' import { findManifestFiles } from './utils.ts' +import { startServer } from './serve/index.ts' +import { startDashboard } from './serve/dashboard-server.ts' type Params = { port: number, 'dashboard-port': number, directory: string, dev: boolean, 'manifests-dir': string } @@ -67,16 +69,12 @@ async function watch (args: ArgumentsCamelCase): Promise { // Dashboard server function async function startDashboardServer (): Promise { - // Import and start the dashboard server - const dashboardServer = await import('./serve/dashboard-server.ts') - await dashboardServer.startDashboard() + await startDashboard() } // Application server function async function startApplicationServer (): Promise { - // Import and start the application server - const startServer = await import('./serve/index.ts') - await startServer.default() + await startServer() } export async function serve (args: ArgumentsCamelCase) { diff --git a/src/serve/auth.ts b/src/serve/auth.ts index 39c93c1..d8609c8 100644 --- a/src/serve/auth.ts +++ b/src/serve/auth.ts @@ -1,52 +1,69 @@ import { verifyShelterAuthorizationHeader } from 'npm:@chelonia/lib/utils' -import Boom from 'npm:@hapi/boom' -import type * as Hapi from 'npm:@hapi/hapi' +import { HTTPException } from 'npm:hono/http-exception' +import type { Context, MiddlewareHandler } from 'npm:hono' -const plugin: Hapi.NamedPlugin = { - name: 'chel-auth', - register: function (server: Hapi.Server) { - server.auth.scheme('chel-bearer', () => { - return { - authenticate: function (request, h) { - const { authorization } = request.headers - if (!authorization) { - return h.unauthenticated(Boom.unauthorized(null, 'bearer')) - } - const thisScheme = 'bearer ' - if (authorization.slice(0, thisScheme.length) !== thisScheme) { - return h.unauthenticated(Boom.unauthorized(null, 'bearer')) - } - const token = authorization.slice(thisScheme.length) - return h.authenticated({ credentials: { token } }) - } - } - }) +export type AuthCredentials = { + token?: string + billableContractID?: string +} - server.auth.scheme ('chel-shelter', () => { - return { - authenticate: function (request, h) { - const { authorization } = request.headers - if (!authorization) { - return h.unauthenticated(Boom.unauthorized(null, 'shelter')) - } - const thisScheme = 'shelter ' - if (authorization.slice(0, thisScheme.length) !== thisScheme) { - return h.unauthenticated(Boom.unauthorized(null, 'shelter')) - } - try { - const billableContractID = verifyShelterAuthorizationHeader(authorization) - return h.authenticated({ credentials: { billableContractID } }) - } catch (e) { - console.warn(e, 'Shelter authorization failed') - return h.unauthenticated(Boom.unauthorized('Authentication failed', 'shelter')) - } - } - } - }) +declare module 'npm:hono' { + interface ContextVariableMap { + credentials: AuthCredentials + authStrategy: string + validatedBody: unknown + } +} + +function extractBearer (c: Context): AuthCredentials | null { + const authorization = c.req.header('authorization') + if (!authorization) return null + const prefix = 'bearer ' + if (authorization.slice(0, prefix.length).toLowerCase() !== prefix) return null + return { token: authorization.slice(prefix.length) } +} - server.auth.strategy('chel-bearer', 'chel-bearer') - server.auth.strategy('chel-shelter', 'chel-shelter') +function extractShelter (c: Context): AuthCredentials | null { + const authorization = c.req.header('authorization') + if (!authorization) return null + const prefix = 'shelter ' + if (authorization.slice(0, prefix.length).toLowerCase() !== prefix) return null + try { + const billableContractID = verifyShelterAuthorizationHeader(authorization) + return { billableContractID } + } catch (e) { + console.warn(e, 'Shelter authorization failed') + return null } } -export default plugin +const extractors: Record AuthCredentials | null> = { + 'chel-bearer': extractBearer, + 'chel-shelter': extractShelter +} + +export function authMiddleware ( + strategies: string | string[], + mode: 'required' | 'optional' = 'required' +): MiddlewareHandler { + const strategyList = Array.isArray(strategies) ? strategies : [strategies] + + return async (c, next) => { + for (const strategy of strategyList) { + const extractor = extractors[strategy] + if (!extractor) throw new Error(`Unknown auth strategy: ${strategy}`) + const credentials = extractor(c) + if (credentials) { + c.set('credentials', credentials) + c.set('authStrategy', strategy) + return next() + } + } + if (mode === 'optional') { + c.set('credentials', {} as AuthCredentials) + c.set('authStrategy', '') + return next() + } + throw new HTTPException(401, { message: 'Unauthorized' }) + } +} diff --git a/src/serve/dashboard-server.ts b/src/serve/dashboard-server.ts index 64391b5..cf2529d 100644 --- a/src/serve/dashboard-server.ts +++ b/src/serve/dashboard-server.ts @@ -1,71 +1,49 @@ import path from 'node:path' import process from 'node:process' -import * as Hapi from 'npm:@hapi/hapi' -import Inert from 'npm:@hapi/inert' +import { Hono } from 'npm:hono' +import { serveStatic } from 'npm:hono/deno' // @deno-types="npm:@types/nconf" import nconf from 'npm:nconf' -// Get the current directory for dashboard assets const getDashboardPath = () => { - // In development, use relative path from serve directory - return path.resolve(import.meta.dirname || process.cwd(), 'dist-dashboard') + // When running from build/main.js, the dashboard is in build/dist-dashboard + // import.meta.dirname points to the build/ directory in that case + const baseDir = import.meta.dirname || path.join(process.cwd(), 'build') + const dashboardPath = path.resolve(baseDir, 'dist-dashboard') + return dashboardPath } export async function startDashboard (): Promise { - // Create a separate Hapi server for the dashboard const port = nconf.get('server:dashboardPort') - const dashboardServer = new Hapi.Server({ - port, - host: nconf.get('server:host'), - routes: { - files: { - relativeTo: getDashboardPath() - } - } - }) + const host = nconf.get('server:host') || '0.0.0.0' + const dashboardRoot = getDashboardPath() - // Register the Inert plugin for static file serving - await dashboardServer.register(Inert) + const app = new Hono() - // Dashboard assets routes (must come first to handle static files) - dashboardServer.route({ - method: 'GET', - path: '/assets/{path*}', - handler: { - directory: { - path: 'assets', - redirectToSlash: false - } - } - }) + // Cache middleware instances to avoid creating new ones on every request + const staticMiddleware = serveStatic({ root: dashboardRoot, rewriteRequestPath: (p) => p }) + const indexMiddleware = serveStatic({ path: path.join(dashboardRoot, 'index.html') }) - // Support accessing dashboard under /dashboard/ path - dashboardServer.route({ - method: 'GET', - path: '/dashboard', - handler: (_request: Hapi.Request, h: Hapi.ResponseToolkit) => h.file('index.html') - }) + app.get('/assets/*', staticMiddleware) - dashboardServer.route({ - method: 'GET', - path: '/dashboard/', - handler: (_request: Hapi.Request, h: Hapi.ResponseToolkit) => h.file('index.html') - }) + app.get('/dashboard', indexMiddleware) + app.get('/dashboard/', indexMiddleware) - // Catch-all route for root and other paths (serves index.html) - dashboardServer.route({ - method: 'GET', - path: '/{path*}', - handler: { - directory: { - path: '.', - index: ['index.html'] - } + // SPA fallback: try static file first, then serve index.html for SPA routing + app.get('/*', async (c) => { + const staticResponse = await staticMiddleware(c, async () => {}) + // If static file exists and was served successfully, return it + if (staticResponse) { + return staticResponse } + // File not found, serve index.html for SPA routing + const indexResponse = await indexMiddleware(c, async () => {}) + return indexResponse || c.text('Not Found', 404) }) - // Start the dashboard server - await dashboardServer.start() + await new Promise((resolve) => { + Deno.serve({ port, hostname: host, onListen: () => resolve() }, app.fetch) + }) } export default startDashboard diff --git a/src/serve/database.ts b/src/serve/database.ts index 502beb6..c8a23c5 100644 --- a/src/serve/database.ts +++ b/src/serve/database.ts @@ -5,176 +5,191 @@ import 'npm:@chelonia/lib/chelonia' import 'npm:@chelonia/lib/db' import { checkKey, parsePrefixableKey, prefixHandlers } from 'npm:@chelonia/lib/db' import { strToB64 } from 'npm:@chelonia/lib/functions' -import Boom from 'npm:@hapi/boom' import sbp from 'npm:@sbp/sbp' import LRU from 'npm:lru-cache' -import { SERVER_EXITING } from './events.ts' +import { BackendErrorConflict, BackendErrorGone, BackendErrorNotFound } from './errors.ts' import { initVapid } from './vapid.ts' import { initZkpp } from './zkppSalt.ts' // @deno-types="npm:@types/nconf" import nconf from 'npm:nconf' +import type { ImportMeta } from '../types/build.d.ts' import type DatabaseBackend from './DatabaseBackend.ts' import { KEYOP_SEGMENT_LENGTH, appendToNamesIndex, namespaceKey } from './db-utils.ts' const production = process.env.NODE_ENV === 'production' -// Streams stored contract log entries since the given entry hash (inclusive!). -export default sbp('sbp/selectors/register', { - 'backend/db/streamEntriesAfter': async function (contractID: string, height: number, requestedLimit?: number, options: { keyOps?: boolean } = {}): Promise { - const batchMaxSize = nconf.get('server:maxEventsBatchSize') ?? 500 - const limit = Math.min(requestedLimit ?? Number.POSITIVE_INFINITY, batchMaxSize) - const latestHEADinfo = await sbp('chelonia/db/latestHEADinfo', contractID) - if (latestHEADinfo === '') { - throw Boom.resourceGone(`contractID ${contractID} has been deleted!`) - } - if (!latestHEADinfo) { - throw Boom.notFound(`contractID ${contractID} doesn't exist!`) - } - // Number of entries pushed. - let counter = 0 - let currentHeight = height - let currentHash, serverMeta - let prefix = '' - // `nextKeyOp` is used to advance `currentHeight` when fetching keyOps, and - // more complex behaviour than simple 'increment by 1' is needed. - // It returns three possible values: `true`, indicating `currentHeight` has - // been set to the next `currentHeight`; `false`, indicating the end of - // the stream; and `null`, indicating the result is indeterminate and - // `nextKeyOp` should be called again (this is because key ops are indexed - // based on their height in segments of 10k height entries). - // `nextKeyOp` will do the following: if `currentHeight` points to a key op, - // it will leave `currentHeight` unchanged; otherwise, if `currentHeight` - // does _not_ point to a key op, `currentHeight` will be set to the smallest - // height larger than the current `currentHeight` value which is a key op. - const nextKeyOp = (() => { - let index: string[] | undefined +// Module-scope state for the active backend instance and LRU cache. +// The overwritten `chelonia.db/*` selectors close over these so that +// a second `initDB()` call (after `closeDB()`) rebinds them to a fresh +// backend + cache without needing to re-overwrite the selectors. +let currentBackend: DatabaseBackend | null = null +let currentCache: LRU | null = null +let isClosing = false - return async () => { - if (!index) { - index = (await sbp('chelonia.db/get', `_private_keyop_idx_${contractID}_${currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH}`))?.split('\x00') - } - const value = index?.find((h, i) => { - if (Number(h) >= currentHeight) { - // Remove values that no longer are relevant from the index - index = index!.slice(i + 1) - return true - } else { - return false +let baseSelectorsInstalled = false +function installBaseSelectorsOnce () { + if (baseSelectorsInstalled) return + baseSelectorsInstalled = true + sbp('sbp/selectors/register', { + 'backend/db/streamEntriesAfter': async function (contractID: string, height: number, requestedLimit?: number, options: { keyOps?: boolean } = {}): Promise { + const batchMaxSize = nconf.get('server:maxEventsBatchSize') ?? 500 + const limit = Math.min(requestedLimit ?? Number.POSITIVE_INFINITY, batchMaxSize) + const latestHEADinfo = await sbp('chelonia/db/latestHEADinfo', contractID) + if (latestHEADinfo === '') { + throw new BackendErrorGone(`contractID ${contractID} has been deleted!`) + } + if (!latestHEADinfo) { + throw new BackendErrorNotFound(`contractID ${contractID} doesn't exist!`) + } + // Number of entries pushed. + let counter = 0 + let currentHeight = height + let currentHash, serverMeta + let prefix = '' + // `nextKeyOp` is used to advance `currentHeight` when fetching keyOps, and + // more complex behaviour than simple 'increment by 1' is needed. + // It returns three possible values: `true`, indicating `currentHeight` has + // been set to the next `currentHeight`; `false`, indicating the end of + // the stream; and `null`, indicating the result is indeterminate and + // `nextKeyOp` should be called again (this is because key ops are indexed + // based on their height in segments of 10k height entries). + // `nextKeyOp` will do the following: if `currentHeight` points to a key op, + // it will leave `currentHeight` unchanged; otherwise, if `currentHeight` + // does _not_ point to a key op, `currentHeight` will be set to the smallest + // height larger than the current `currentHeight` value which is a key op. + const nextKeyOp = (() => { + let index: string[] | undefined + + return async () => { + if (!index) { + index = (await sbp('chelonia.db/get', `_private_keyop_idx_${contractID}_${currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH}`))?.split('\x00') } - }) - if (value != null) { - const newHeight = Number(value) - currentHeight = newHeight - } else { - // We've exhausted the current index; we'll return `null` and advance - // height by KEYOP_SEGMENT_LENGTH so that we can read the next index - // upon the next invocation (or, if we've reached the end of the - // contract, we return `false`). - currentHeight = currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH + KEYOP_SEGMENT_LENGTH - index = undefined - if (currentHeight > latestHEADinfo.height) { - return false + const value = index?.find((h, i) => { + if (Number(h) >= currentHeight) { + // Remove values that no longer are relevant from the index + index = index!.slice(i + 1) + return true + } else { + return false + } + }) + if (value != null) { + const newHeight = Number(value) + currentHeight = newHeight } else { - return null + // We've exhausted the current index; we'll return `null` and advance + // height by KEYOP_SEGMENT_LENGTH so that we can read the next index + // upon the next invocation (or, if we've reached the end of the + // contract, we return `false`). + currentHeight = currentHeight - currentHeight % KEYOP_SEGMENT_LENGTH + KEYOP_SEGMENT_LENGTH + index = undefined + if (currentHeight > latestHEADinfo.height) { + return false + } else { + return null + } } + return true + } + })() + // `fetchMeta` fetches metadata information for entries based on height. + // Crucially, it fetches the entry hash (i.e., height -> hash lookup), which + // is needed for returning the correct data. + // The return value isn't currently used but is left as it may be useful in + // the future if this code is refactored. `false` indicates that no metadata + // could be found (indicating the end of a contract --or some kind of data + // corruption) and that the stream has ended. `true` indicates that the + // function executed successfully and the stream continues. + // Currently, the return value is not used because we're relying on the + // truthiness of `serverMeta` as a subtitute. + const fetchMeta = async () => { + if (currentHeight > latestHEADinfo.height) { + return false + } + const meta = await sbp('chelonia/db/getEntryMeta', contractID, currentHeight) + if (!meta) { + return false } - return true - } - })() - // `fetchMeta` fetches metadata information for entries based on height. - // Crucially, it fetches the entry hash (i.e., height -> hash lookup), which - // is needed for returning the correct data. - // The return value isn't currently used but is left as it may be useful in - // the future if this code is refactored. `false` indicates that no metadata - // could be found (indicating the end of a contract --or some kind of data - // corruption) and that the stream has ended. `true` indicates that the - // function executed successfully and the stream continues. - // Currently, the return value is not used because we're relying on the - // truthiness of `serverMeta` as a subtitute. - const fetchMeta = async () => { - if (currentHeight > latestHEADinfo.height) { - return false - } - const meta = await sbp('chelonia/db/getEntryMeta', contractID, currentHeight) - if (!meta) { - return false - } - const { hash: newCurrentHash, ...newServerMeta } = meta - currentHash = newCurrentHash - serverMeta = newServerMeta + const { hash: newCurrentHash, ...newServerMeta } = meta + currentHash = newCurrentHash + serverMeta = newServerMeta - return true - } - // NOTE: if this ever stops working you can also try Readable.from(): - // https://nodejs.org/api/stream.html#stream_stream_readable_from_iterable_options - const stream = Readable.from((async function * () { - yield '[' - await fetchMeta() - while (serverMeta && counter < limit) { - try { - const entry = await sbp('chelonia/db/getEntry', currentHash) - // If the entry doesn't exist, we may have reached the end - if (!entry) break - const currentPrefix = prefix - prefix = ',' - counter++ - yield `${currentPrefix}"${strToB64( - JSON.stringify({ serverMeta, message: entry.serialize() }) - )}"` - // Note for future improvement: implement a generator function for - // advancing height, which would make this logic more general by - // having just something like `await height.next()` instead of this - // avancement here and separate logic for each special case (like the - // `if` below for key ops). - currentHeight++ - currentHash = undefined - serverMeta = undefined - // queries with 'keyOps' always return the requested height, whether - // or not a keyOp. - if (options.keyOps) { - // Advance `currentHeight` until the next key op - // `nextKeyOp` relies on the height advancing after an ideration and - while ((await nextKeyOp()) === null); + return true + } + // NOTE: if this ever stops working you can also try Readable.from(): + // https://nodejs.org/api/stream.html#stream_stream_readable_from_iterable_options + const stream = Readable.from((async function * () { + yield '[' + await fetchMeta() + while (serverMeta && counter < limit) { + try { + const entry = await sbp('chelonia/db/getEntry', currentHash) + // If the entry doesn't exist, we may have reached the end + if (!entry) break + const currentPrefix = prefix + prefix = ',' + counter++ + yield `${currentPrefix}"${strToB64( + JSON.stringify({ serverMeta, message: entry.serialize() }) + )}"` + // Note for future improvement: implement a generator function for + // advancing height, which would make this logic more general by + // having just something like `await height.next()` instead of this + // avancement here and separate logic for each special case (like the + // `if` below for key ops). + currentHeight++ + currentHash = undefined + serverMeta = undefined + // queries with 'keyOps' always return the requested height, whether + // or not a keyOp. + if (options.keyOps) { + // Advance `currentHeight` until the next key op + // `nextKeyOp` relies on the height advancing after an ideration and + while ((await nextKeyOp()) === null); + } + await fetchMeta() + } catch (e) { + console.error(e, '[backend] streamEntriesAfter: read()') + break } - await fetchMeta() - } catch (e) { - console.error(e, '[backend] streamEntriesAfter: read()') - break } + yield ']' + })(), { encoding: 'utf-8', objectMode: false }) + + // Add headers to stream (TypeScript workaround) + ;(stream as { headers?: Record }).headers = { + 'shelter-headinfo-head': String(latestHEADinfo.HEAD), + 'shelter-headinfo-height': String(latestHEADinfo.height) } - yield ']' - })(), { encoding: 'utf-8', objectMode: false }) + return stream + }, + // ======================= + // wrapper methods to add / lookup names + // ======================= + 'backend/db/registerName': async function (name: string, value: string): Promise<{ name: string, value: string }> { + const exists = await sbp('backend/db/lookupName', name) + if (exists) { + throw new BackendErrorConflict('exists') + } + await sbp('chelonia.db/set', namespaceKey(name), value) + await sbp('chelonia.db/set', `_private_cid2name_${value}`, name) + await appendToNamesIndex(name) - // Add headers to stream (TypeScript workaround) - ;(stream as { headers?: Record }).headers = { - 'shelter-headinfo-head': latestHEADinfo.HEAD, - 'shelter-headinfo-height': latestHEADinfo.height - } - return stream - }, - // ======================= - // wrapper methods to add / lookup names - // ======================= - 'backend/db/registerName': async function (name: string, value: string): Promise<{ name: string, value: string }> { - const exists = await sbp('backend/db/lookupName', name) - if (exists) { - throw Boom.conflict('exists') + return { name, value } + }, + 'backend/db/lookupName': async function (name: string): Promise { + const value = await sbp('chelonia.db/get', namespaceKey(name)) + return value } - await sbp('chelonia.db/set', namespaceKey(name), value) - await sbp('chelonia.db/set', `_private_cid2name_${value}`, name) - await appendToNamesIndex(name) + }) +} - return { name, value } - }, - 'backend/db/lookupName': async function (name: string): Promise { - const value = await sbp('chelonia.db/get', namespaceKey(name)) - return value - } -}) +export default installBaseSelectorsOnce let initedDB: false | true | 'preloaded' = false export const initDB = async ({ skipDbPreloading }: { skipDbPreloading?: boolean } = {}) => { + installBaseSelectorsOnce() if (!initedDB) { // If persistence must be enabled: // - load and initialize the selected storage backend @@ -187,27 +202,19 @@ export const initDB = async ({ skipDbPreloading }: { skipDbPreloading?: boolean if (persistence && persistence !== 'mem') { const Ctor = (await import(`./database-${persistence}.ts`)).default - // Destructuring is safe because these methods have been bound using rebindMethods(). - const { init, readData, writeData, deleteData, iterKeys, keyCount, close } = new Ctor(options[persistence]) as DatabaseBackend - await init() - sbp('okTurtles.events/once', SERVER_EXITING, () => { - sbp('okTurtles.eventQueue/queueEvent', SERVER_EXITING, async () => { - try { - await close() - } catch (e) { - console.error(e, `Error closing DB ${persistence}`) - } - }) - }) + const instance = new Ctor(options[persistence]) as DatabaseBackend + await instance.init() + currentBackend = instance // https://github.com/isaacs/node-lru-cache#usage - const cache = new LRU({ + currentCache = new LRU({ max: nconf.get('database:lruNumItems') ?? 10000 }) const prefixes = Object.keys(prefixHandlers) sbp('sbp/selectors/overwrite', { 'chelonia.db/get': async function (prefixableKey: string, { bypassCache }: { bypassCache?: boolean } = {}): Promise { + const cache = currentCache! if (!bypassCache) { const lookupValue = cache.get(prefixableKey) if (lookupValue !== undefined) { @@ -215,7 +222,7 @@ export const initDB = async ({ skipDbPreloading }: { skipDbPreloading?: boolean } } const [prefix, key] = parsePrefixableKey(prefixableKey) - let value = await readData(key) + let value = await currentBackend!.readData(key) if (value === undefined) { return } @@ -227,12 +234,12 @@ export const initDB = async ({ skipDbPreloading }: { skipDbPreloading?: boolean if (ARCHIVE_MODE) throw new Error('Unable to write in archive mode') checkKey(key) if (key.startsWith('_private_immutable')) { - const existingValue = await readData(key) + const existingValue = await currentBackend!.readData(key) if (existingValue !== undefined) { throw new Error('Cannot set already set immutable key') } } - await writeData(key, value) + await currentBackend!.writeData(key, value) // `get` uses `prefixableKey` as key, which now that the value is updated // is stale. We delete all prefixed key variants from the cache to // avoid serving stale data. Note that because of prefixes, `cache.set` @@ -242,6 +249,7 @@ export const initDB = async ({ skipDbPreloading }: { skipDbPreloading?: boolean // Which one was faster depended on the browser, with no clear overall // winner, but `.forEach` was faster on Chrome, which uses the same // engine as Node.JS (V8). + const cache = currentCache! prefixes.forEach(prefix => { cache.delete(prefix + key) }) @@ -252,24 +260,27 @@ export const initDB = async ({ skipDbPreloading }: { skipDbPreloading?: boolean if (key.startsWith('_private_immutable')) { throw new Error('Cannot delete immutable key') } - await deleteData(key) + await currentBackend!.deleteData(key) // `get` uses `prefixableKey` as key, which now that the value is updated // is stale. We delete all prefixed key variants from the cache to // avoid serving stale data. + const cache = currentCache! prefixes.forEach(prefix => { cache.delete(prefix + key) }) }, 'chelonia.db/iterKeys': () => { - return iterKeys() + return currentBackend!.iterKeys() }, 'chelonia.db/keyCount': () => { - return keyCount() + return currentBackend!.keyCount() } }) - sbp('sbp/selectors/lock', ['chelonia.db/get', 'chelonia.db/set', 'chelonia.db/delete', 'chelonia.db/iterKeys']) } initedDB = true + if ((import.meta as ImportMeta).initDbOnce) { + sbp('sbp/selectors/lock', ['chelonia.db/get', 'chelonia.db/set', 'chelonia.db/delete', 'chelonia.db/iterKeys']) + } } if (skipDbPreloading || initedDB === 'preloaded') return /* @@ -328,4 +339,26 @@ export const initDB = async ({ skipDbPreloading }: { skipDbPreloading?: boolean initedDB = 'preloaded' } +export async function closeDB (): Promise { + if (isClosing) return + isClosing = true + try { + if (currentBackend) { + try { + await currentBackend.close() + } catch (e) { + console.error(e, 'Error closing DB') + } + currentBackend = null + } + currentCache?.clear() + currentCache = null + if (!(import.meta as ImportMeta).initDbOnce) { + initedDB = false + } + } finally { + isClosing = false + } +} + export * from './db-utils.ts' diff --git a/src/serve/errors.ts b/src/serve/errors.ts index a49225e..adcecfc 100644 --- a/src/serve/errors.ts +++ b/src/serve/errors.ts @@ -3,3 +3,4 @@ import { ChelErrorGenerator } from 'npm:@chelonia/lib/errors' export const BackendErrorNotFound = ChelErrorGenerator('BackendErrorNotFound') export const BackendErrorGone = ChelErrorGenerator('BackendErrorGone') export const BackendErrorBadData = ChelErrorGenerator('BackendErrorBadData') +export const BackendErrorConflict = ChelErrorGenerator('BackendErrorConflict') diff --git a/src/serve/genericWorker.ts b/src/serve/genericWorker.ts index fbffb6e..072341d 100644 --- a/src/serve/genericWorker.ts +++ b/src/serve/genericWorker.ts @@ -2,7 +2,10 @@ import { Buffer } from 'node:buffer' import { deserializer, serdesDeserializeSymbol, serdesSerializeSymbol, serdesTagSymbol, serializer } from 'npm:@chelonia/serdes' import 'npm:@sbp/okturtles.eventqueue' import sbp from 'npm:@sbp/sbp' -import './logger.ts' +import { initializeLogger } from './logger.ts' + +// Initialize pino logger for worker processes +initializeLogger() Object.defineProperties(Buffer, { [serdesDeserializeSymbol]: { diff --git a/src/serve/index.ts b/src/serve/index.ts index 39783d6..0bdfe3b 100644 --- a/src/serve/index.ts +++ b/src/serve/index.ts @@ -5,8 +5,8 @@ import 'npm:@sbp/okturtles.events' import sbp from 'npm:@sbp/sbp' import chalk from 'npm:chalk' import { SERVER_EXITING, SERVER_RUNNING } from './events.ts' -import { PUBSUB_INSTANCE } from './instance-keys.ts' -import './logger.ts' +import { startServer as startServerImpl, stopServer as stopServerImpl } from './server.ts' +import { initializeLogger } from './logger.ts' console.info('NODE_ENV =', process.env.NODE_ENV) @@ -30,49 +30,63 @@ function logSBP (_domain: string, selector: string, data: Array) { // any specific selectors outside of backend namespace to log ;[].forEach(sel => sbp('sbp/filters/selector/add', sel, logSBP)) -export default () => (new Promise((resolve, reject) => { - sbp('okTurtles.events/on', SERVER_RUNNING, function () { - console.info(chalk.bold('backend startup sequence complete.')) - resolve() +// Signal handlers are installed only once per process +let signalHandlersInstalled = false +const signalHandlers: Array<[string, () => void]> = [] + +// Global exception handlers are installed only once per process +let globalExceptionHandlersInstalled = false + +// Helper to install global exception handlers (once per process) +function installGlobalExceptionHandlers (): void { + if (globalExceptionHandlersInstalled) return + globalExceptionHandlersInstalled = true + + process.on('uncaughtException', (err: Error) => { + console.error(err, '[server] Unhandled exception') + process.exit(1) }) - // call this after we've registered listener for SERVER_RUNNING - import('./server.ts').catch(reject) -})) -sbp('okTurtles.events/once', SERVER_EXITING, () => { - sbp('okTurtles.data/apply', PUBSUB_INSTANCE, function (pubsub: { on: (event: string, callback: () => void) => void; close: () => void; clients: { forEach: (callback: (client: { terminate: () => void }) => void) => void } }) { - sbp('okTurtles.eventQueue/queueEvent', SERVER_EXITING, () => { - return new Promise((resolve) => { - pubsub.on('close', async function () { - try { - removeSignalHandlers() - await sbp('chelonia.persistentActions/unload') - await sbp('backend/server/stop') - console.info('Hapi server down') - } catch (err) { - console.error(err, 'Error during shutdown') - } finally { - resolve() - } - }) - pubsub.close() - // Since `ws` v8.0, `WebSocketServer.close()` no longer closes remaining connections. - // See https://github.com/websockets/ws/commit/df7de574a07115e2321fdb5fc9b2d0fea55d27e8 - pubsub.clients.forEach((client: { terminate: () => void }) => client.terminate()) - }) - }) + process.on('unhandledRejection', (reason: unknown) => { + console.error(reason, '[server] Unhandled promise rejection:', reason) + process.exit(1) }) -}) +} + +// Helper to install signal handlers +function installSignalHandlers (): void { + if (signalHandlersInstalled) return + signalHandlersInstalled = true -process.on('uncaughtException', (err: Error) => { - console.error(err, '[server] Unhandled exception') - process.exit(1) -}) + const handleSignal = (signal: string, code: number) => { + const handler = () => { + console.error(`Exiting upon receiving ${signal} (${code})`) + // Exit codes follow the 128 + signal code convention. + // See + exit(128 + code) + } + signalHandlers.push([signal, handler]) + process.on(signal, handler) + } + + // Codes from + ;([ + ['SIGHUP', 1], + ['SIGINT', 2], + ['SIGQUIT', 3], + ['SIGTERM', 15], + ['SIGUSR1', 10], + ['SIGUSR2', 11] + ] as [string, number][]).forEach(([signal, code]) => handleSignal(signal, code)) +} -process.on('unhandledRejection', (reason: unknown) => { - console.error(reason, '[server] Unhandled promise rejection:', reason) - process.exit(1) -}) +export function removeSignalHandlers (): void { + for (const [signal, handler] of signalHandlers) { + process.removeListener(signal, handler) + } + signalHandlers.length = 0 + signalHandlersInstalled = false +} const exit = (code: number) => { // Make sure `process.exit` is called after all existing SERVER_EXITING @@ -88,32 +102,48 @@ const exit = (code: number) => { sbp('okTurtles.events/emit', SERVER_EXITING) } -const signalHandlers: Array<[string, () => void]> = [] +export interface StartServerOptions { + installSignalHandlers?: boolean +} + +export async function startServer (options: StartServerOptions = {}): Promise<{ uri: string }> { + const { installSignalHandlers: shouldInstallSignalHandlers = true } = options -const handleSignal = (signal: string, code: number) => { - const handler = () => { - console.error(`Exiting upon receiving ${signal} (${code})`) - // Exit codes follow the 128 + signal code convention. - // See - exit(128 + code) + // Initialize pino logger (replaces console.* methods) + initializeLogger() + + // Install global exception handlers once per process (only if signal handlers are enabled) + if (shouldInstallSignalHandlers) { + installGlobalExceptionHandlers() + installSignalHandlers() } - signalHandlers.push([signal, handler]) - process.on(signal, handler) + + // Register a SERVER_EXITING handler for this startServer call + // This handler self-removes when it fires + sbp('okTurtles.events/once', SERVER_EXITING, async () => { + try { + removeSignalHandlers() + await stopServer() + console.info('Server down') + } catch (err) { + console.error(err, 'Error during shutdown') + } + }) + + // Start the server and wait for it to be running + return await new Promise((resolve, reject) => { + sbp('okTurtles.events/on', SERVER_RUNNING, function onRunning (info: { info: { uri: string } }) { + sbp('okTurtles.events/off', SERVER_RUNNING, onRunning) + console.info(chalk.bold('backend startup sequence complete.')) + resolve({ uri: info.info.uri }) + }) + startServerImpl().catch(reject) + }) } -// Codes from -;([ - ['SIGHUP', 1], - ['SIGINT', 2], - ['SIGQUIT', 3], - ['SIGTERM', 15], - ['SIGUSR1', 10], - ['SIGUSR2', 11] -] as [string, number][]).forEach(([signal, code]) => handleSignal(signal, code)) - -export function removeSignalHandlers () { - for (const [signal, handler] of signalHandlers) { - process.removeListener(signal, handler) - } - signalHandlers.length = 0 +export async function stopServer (): Promise { + await stopServerImpl() } + +// Backwards compatibility: default export is startServer +export default startServer diff --git a/src/serve/logger.ts b/src/serve/logger.ts index 5991914..51a33ca 100644 --- a/src/serve/logger.ts +++ b/src/serve/logger.ts @@ -48,10 +48,22 @@ if (Object.keys(logger.levels.values).includes(logLevel)) { logger.warn(`Unknown log level: ${logLevel}`) } -console.debug = logger.debug.bind(logger) -console.info = logger.info.bind(logger) -console.log = logger.info.bind(logger) -console.warn = logger.warn.bind(logger) -console.error = logger.error.bind(logger) +let loggerInitialized = false + +/** + * Initialize the pino logger by replacing console.* methods. + * This should be called explicitly when pino logging is desired + * (e.g., in the serve command), not automatically on import. + */ +export function initializeLogger (): void { + if (loggerInitialized) return + loggerInitialized = true + + console.debug = logger.debug.bind(logger) + console.info = logger.info.bind(logger) + console.log = logger.info.bind(logger) + console.warn = logger.warn.bind(logger) + console.error = logger.error.bind(logger) +} export default logger diff --git a/src/serve/ownerSizeTotalWorker.test.ts b/src/serve/ownerSizeTotalWorker.test.ts index ee3e3c6..daa0312 100644 --- a/src/serve/ownerSizeTotalWorker.test.ts +++ b/src/serve/ownerSizeTotalWorker.test.ts @@ -2,7 +2,7 @@ import { createCID } from 'npm:@chelonia/lib/functions' import sbp from 'npm:@sbp/sbp' // import { assert } from 'jsr:@std/assert' // TODO: Use for additional test assertions import createWorker from './createWorker.ts' -import { appendToIndexFactory, initDB, updateSize as updateSize_ } from './database.ts' +import { appendToIndexFactory, closeDB, initDB, updateSize as updateSize_ } from './database.ts' let worker = createWorker(new URL('./ownerSizeTotalWorker.ts', import.meta.url).toString()) @@ -263,6 +263,7 @@ Deno.test({ }) } finally { // Teardown + await closeDB() await worker.terminate() } } diff --git a/src/serve/routes-test-helpers.ts b/src/serve/routes-test-helpers.ts index 091e5e9..c9e7ef8 100644 --- a/src/serve/routes-test-helpers.ts +++ b/src/serve/routes-test-helpers.ts @@ -10,7 +10,7 @@ import { blake32Hash, createCID, multicodes } from 'npm:@chelonia/lib/functions' import { EDWARDS25519SHA512BATCH, keygen, keyId, serializeKey, sign } from 'npm:@chelonia/crypto' import { AUTHSALT, CONTRACTSALT, CS, SALT_LENGTH_IN_OCTETS } from 'npm:@chelonia/lib/zkppConstants' import tweetnacl from 'npm:tweetnacl' -import { SERVER_EXITING, SERVER_RUNNING } from './events.ts' +import { startServer, stopServer } from './index.ts' export { blake32Hash, createCID, multicodes } from 'npm:@chelonia/lib/functions' export { EDWARDS25519SHA512BATCH, keygen, keyId, serializeKey, sign } from 'npm:@chelonia/crypto' @@ -137,19 +137,9 @@ export function startTestServer (): Promise { } }) - const serverAddress = await new Promise((resolve, reject) => { - const unregister = sbp('okTurtles.events/once', SERVER_RUNNING, function (hapi: { info: { uri: string } }) { - resolve(hapi.info.uri) - }) - import('./index.ts').then(({ default: start }) => { - return start() - }).catch((e) => { - unregister() - reject(e) - }) - }) + const serverAddress = await startServer({ installSignalHandlers: false }) - return serverAddress + return serverAddress.uri } cachedServerAddress = internal().catch(e => { @@ -175,13 +165,6 @@ export async function stopTestServer (): Promise { if (--serverStartRefCount > 0) { return } - await new Promise((resolve) => { - sbp('okTurtles.events/once', SERVER_EXITING, () => { - sbp('okTurtles.eventQueue/queueEvent', SERVER_EXITING, () => { - resolve() - }) - }) - sbp('okTurtles.events/emit', SERVER_EXITING) - }) + await stopServer() cachedServerAddress = undefined } diff --git a/src/serve/routes-writes.test.ts b/src/serve/routes-writes.test.ts index 9ecd4de..4cf81ff 100644 --- a/src/serve/routes-writes.test.ts +++ b/src/serve/routes-writes.test.ts @@ -295,14 +295,14 @@ Deno.test({ if (res.status !== 401) throw new Error(`Expected 401 but got ${res.status}`) }) - await t.step('POST /deleteContract with _private prefix returns 404', async () => { + await t.step('POST /deleteContract with _private prefix returns 400 (invalid CID)', async () => { const auth = buildShelterAuthHeader(owner.contractID, owner.SAK) const res = await fetch(`${baseURL}/deleteContract/_private_something`, { method: 'POST', headers: { authorization: auth } }) await res.body?.cancel() - if (res.status !== 404) throw new Error(`Expected 404 but got ${res.status}`) + if (res.status !== 400) throw new Error(`Expected 400 but got ${res.status}`) }) await t.step('POST /deleteContract with nonexistent contract returns 404', async () => { @@ -359,21 +359,21 @@ Deno.test({ await t.step('POST /event with invalid payload returns 400', async () => { const res = await fetch(`${baseURL}/event`, { method: 'POST', - headers: { 'content-type': 'text/plain' }, + headers: { 'content-type': 'application/json' }, body: '' }) await res.body?.cancel() if (res.status !== 400) throw new Error(`Expected 400 but got ${res.status}`) }) - await t.step('POST /event with non-JSON payload returns 500', async () => { + await t.step('POST /event with non-JSON payload returns 415', async () => { const res = await fetch(`${baseURL}/event`, { method: 'POST', headers: { 'content-type': 'text/plain' }, body: 'not-json-at-all' }) await res.body?.cancel() - if (res.status !== 500) throw new Error(`Expected 500 but got ${res.status}`) + if (res.status !== 415) throw new Error(`Expected 415 but got ${res.status}`) }) await t.step('POST /file without auth returns 401', async () => { diff --git a/src/serve/routes-zkpp.test.ts b/src/serve/routes-zkpp.test.ts index 2655dc8..f03b592 100644 --- a/src/serve/routes-zkpp.test.ts +++ b/src/serve/routes-zkpp.test.ts @@ -97,7 +97,7 @@ Deno.test({ const baseURL = await startTestServer() try { - await t.step('POST /zkpp/register step 1: returns {s, p, sig}', async () => { + await t.step('POST /zkpp/register step 1 with JSON body', async () => { const keyPair = nacl.box.keyPair() const publicKeyHash = Buffer.from(nacl.hash(Buffer.from( Buffer.from(keyPair.publicKey).toString('base64url') @@ -114,7 +114,7 @@ Deno.test({ if (!body.sig) throw new Error('Expected sig in response') }) - await t.step('POST /zkpp/register step 2: completes registration', async () => { + await t.step('POST /zkpp/register step 2 with JSON body', async () => { const keyPair = nacl.box.keyPair() const publicKey = Buffer.from(keyPair.publicKey).toString('base64url') const publicKeyHash = Buffer.from(nacl.hash(Buffer.from(publicKey))).toString('base64url') @@ -192,7 +192,7 @@ Deno.test({ if (res.status !== 400) throw new Error(`Expected 400 but got ${res.status}`) }) - await t.step('POST /zkpp/{contractID}/updatePasswordHash with missing params returns 400', async () => { + await t.step('POST /zkpp/{contractID}/updatePasswordHash with JSON body returns 400 for missing params', async () => { const cid = createCID('zkpp-test', multicodes.SHELTER_CONTRACT_DATA) const res = await fetch(`${baseURL}/zkpp/${cid}/updatePasswordHash`, { method: 'POST', diff --git a/src/serve/routes.ts b/src/serve/routes.ts index 0311bbd..bb6def7 100644 --- a/src/serve/routes.ts +++ b/src/serve/routes.ts @@ -5,22 +5,26 @@ import { SPMessage } from 'npm:@chelonia/lib/SPMessage' import 'npm:@chelonia/lib/chelonia' import { blake32Hash, createCID, maybeParseCID, multicodes } from 'npm:@chelonia/lib/functions' import 'npm:@chelonia/lib/persistent-actions' -import Boom from 'npm:@hapi/boom' -import * as Hapi from 'npm:@hapi/hapi' +import { getConnInfo } from 'npm:@hono/node-server/conninfo' import sbp from 'npm:@sbp/sbp' import Bottleneck from 'npm:bottleneck' import chalk from 'npm:chalk' -import Joi from 'npm:joi' +import { HTTPException } from 'npm:hono/http-exception' // TODO: Use logger for debugging route handlers import { isIP } from 'node:net' import path from 'node:path' import process from 'node:process' +import { Readable } from 'node:stream' +import { zValidator } from 'npm:@hono/zod-validator' +import type { Context, Hono, MiddlewareHandler } from 'npm:hono' +import { bodyLimit } from 'npm:hono/body-limit' import { appendToIndexFactory, lookupUltimateOwner } from './database.ts' -import { SERVER_INSTANCE } from './instance-keys.ts' import logger from './logger.ts' import { getChallenge, getContractSalt, redeemSaltRegistrationToken, redeemSaltUpdateToken, register, registrationKey, updateContractSalt } from './zkppSalt.ts' // @deno-types="npm:@types/nconf" import nconf from 'npm:nconf' +import * as z from 'npm:zod' +import { authMiddleware, type AuthCredentials } from './auth.ts' const MEGABYTE = 1048576 // TODO: add settings for these const SECOND = 1000 @@ -35,51 +39,71 @@ const KV_KEY_REGEX = /^(?!_private)[^\x00]{1,256}$/ // - No two consecutive - or _ // - Allowed characters: lowercase letters, numbers, underscore and dashes const NAME_REGEX = /^(?![_-])((?!([_-])\2)[a-z\d_-]){1,80}(? = { + '.js': 'application/javascript', + '.mjs': 'application/javascript', + '.css': 'text/css', + '.html': 'text/html', + '.json': 'application/json', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.gif': 'image/gif', + '.svg': 'image/svg+xml', + '.ico': 'image/x-icon', + '.woff': 'font/woff', + '.woff2': 'font/woff2', + '.ttf': 'font/ttf', + '.otf': 'font/otf', + '.webp': 'image/webp', + '.mp4': 'video/mp4', + '.webm': 'video/webm', + '.map': 'application/json' +} + +// Zod schemas for declarative request validation +const cidSchema = z.string().regex(CID_REGEX, 'Invalid CID') +const nameSchema = z.string().regex(NAME_REGEX, 'Invalid name') +const kvKeySchema = z.string().regex(KV_KEY_REGEX, 'Invalid key') +const nonNegativeIntegerSchema = z.string().regex(NON_NEGATIVE_INTEGER_REGEX, 'Invalid non-negative integer') + +// Custom validator for endpoints that accept both JSON and form-urlencoded bodies +function zValidatorFormOrJson ( + schema: T +): MiddlewareHandler { + return async (c, next) => { + const contentType = (c.req.header('content-type') || '').trim().toLowerCase() + let data: unknown + + try { + if (contentType.startsWith('application/x-www-form-urlencoded')) { + const form = await c.req.parseBody() + data = Object.fromEntries( + Object.entries(form as Record) + .filter(([, v]) => typeof v === 'string') + ) + } else if (contentType.startsWith('application/json')) { + data = await c.req.json() + } else { + throw new HTTPException(415, { message: 'Content-Type header expected with form or JSON data' }) + } + } catch (e) { + if (e instanceof HTTPException) throw e + throw new HTTPException(400, { message: 'Invalid request body' }) + } + + const result = schema.safeParse(data) + if (!result.success) { + throw new HTTPException(400, { message: 'Invalid request body' }) + } -sbp('sbp/selectors/register', { - 'backend/server/stopRateLimiters': async function () { - await Promise.allSettled([ - limiterPerMinute.disconnect(), - limiterPerHour.disconnect(), - limiterPerDay.disconnect() - ]) - // The following needs to be done using a private API because `disconnect()` - // isn't enough. - clearInterval((limiterPerMinute as unknown as { interval: ReturnType }).interval) - clearInterval((limiterPerHour as unknown as { interval: ReturnType }).interval) - clearInterval((limiterPerDay as unknown as { interval: ReturnType }).interval) + c.set('validatedBody', result.data as z.infer) + return next() } -}) +} const cidLookupTable = { [multicodes.SHELTER_CONTRACT_MANIFEST]: 'application/vnd.shelter.contractmanifest+json', @@ -161,1042 +185,995 @@ const ctEq = (expected: string, actual: string): boolean => { return r === 0 } -// Boom and Joi already imported above -const isCheloniaDashboard = process.env.IS_CHELONIA_DASHBOARD_DEV -const appDir = nconf.get('server:appDir') || '.' -const dashboardDir = import.meta.dirname || './build/dist-dashboard' -const staticServeConfig = { - routePath: isCheloniaDashboard ? '/dashboard/{path*}' : '/app/{path*}', - distAssets: path.resolve(path.join(isCheloniaDashboard ? dashboardDir : appDir, 'assets')), - distIndexHtml: path.resolve(path.join(isCheloniaDashboard ? dashboardDir : appDir, 'index.html')), - redirect: isCheloniaDashboard ? '/dashboard/' : '/app/' +let currentLimiters: Bottleneck.Group[] = [] +let rateLimitersInstalled = false + +function installRateLimiterSelectorsOnce (): void { + if (rateLimitersInstalled) return + rateLimitersInstalled = true + sbp('sbp/selectors/register', { + 'backend/server/stopRateLimiters': async function () { + const limiters = currentLimiters + await Promise.allSettled(limiters.map(l => l.disconnect())) + // Bottleneck v2 Group.disconnect() only disconnects the Redis connection (if any). + // The internal `setInterval` from `_startAutoCleanup()` is not cleaned up, causing + // async leaks on shutdown. We must clear it via the private `interval` property. + for (const limiter of limiters) { + clearInterval((limiter as unknown as { interval: ReturnType }).interval) + } + } + }) } -const errorMapper = (e: Error): ReturnType => { +export function getStaticServeConfig () { + const isCheloniaDashboard = process.env.IS_CHELONIA_DASHBOARD_DEV + const appDir = nconf.get('server:appDir') || '.' + const dashboardDir = import.meta.dirname || './build/dist-dashboard' + return { + distAssets: path.resolve(path.join(isCheloniaDashboard ? dashboardDir : appDir, 'assets')), + distIndexHtml: path.resolve(path.join(isCheloniaDashboard ? dashboardDir : appDir, 'index.html')), + redirect: isCheloniaDashboard ? '/dashboard/' : '/app/' + } +} + +const errorMapper = (e: Error): HTTPException => { switch (e?.name) { case 'BackendErrorNotFound': - return Boom.notFound() + return new HTTPException(404) case 'BackendErrorGone': - return Boom.resourceGone() + return new HTTPException(410) case 'BackendErrorBadData': - return Boom.badData(e.message) + return new HTTPException(422, { message: e.message }) default: console.error(e, 'Unexpected backend error') - return Boom.internal(e.message ?? 'internal error') + return new HTTPException(500, { message: e.message ?? 'internal error' }) } } -// We define a `Proxy` for route so that we can use `route.VERB` syntax for -// defining routes instead of calling `server.route` with an object, and to -// dynamically get the HAPI server object from the `SERVER_INSTANCE`, which is -// defined in `server.js`. -interface RouteHandler { - (path: string, options: Hapi.RouteOptions, handler: Hapi.Lifecycle.Method | Hapi.HandlerDecorations): void; -} - -type RouteProxy = Record - -const route = new Proxy({} as RouteProxy, { - get: function (_obj, prop: Hapi.RouteDefMethods): RouteHandler { - return function (path, options, handler): void { - sbp('okTurtles.data/apply', SERVER_INSTANCE, function (server: Hapi.Server) { - server.route({ path, method: prop, options, handler }) - }) - } +export function getClientIP (c: Context): string { + const headerIP = c.req.header('x-real-ip') + if (headerIP) return headerIP + try { + const info = getConnInfo(c) + return info.remote.address || 'unknown' + } catch { + return 'unknown' } -}) +} // helper function that returns 404 and prevents client from caching the 404 response // which can sometimes break things: https://github.com/okTurtles/group-income/issues/2608 -function notFoundNoCache (h: Hapi.ResponseToolkit): ReturnType { - return h.response().code(404).header('Cache-Control', 'no-store') +function notFoundNoCache (c: Context): Response { + return c.body(null, 404, { 'Cache-Control': 'no-store' }) } -// RESTful API routes - -// NOTE: We could get rid of this RESTful API and just rely on pubsub.js to do this -// —BUT HTTP2 might be better than websockets and so we keep this around. -// See related TODO in pubsub.js and the reddit discussion link. -route.POST('/event', { - auth: { - strategy: 'chel-shelter', - mode: 'optional' - }, - validate: { - headers: Joi.object({ - 'shelter-namespace-registration': Joi.string().regex(NAME_REGEX) - }), - options: { - allowUnknown: true - }, - payload: Joi.string().required() - } -}, async function (request) { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - // IMPORTANT: IT IS A REQUIREMENT THAT ANY PROXY SERVERS (E.G. nginx) IN FRONT OF US SET THE - // X-Real-IP HEADER! OTHERWISE THIS IS EASILY SPOOFED! - const ip = request.headers['x-real-ip'] || request.info.remoteAddress - try { - const deserializedHEAD = SPMessage.deserializeHEAD(request.payload as string) - try { - const parsed = maybeParseCID(deserializedHEAD.head.manifest) - if (parsed?.code !== multicodes.SHELTER_CONTRACT_MANIFEST) { - return Boom.badData('Invalid manifest') - } - const credentials = request.auth.credentials - // Only allow identity contracts to be created without attribution - if (!credentials?.billableContractID && deserializedHEAD.isFirstMessage) { - const manifest = await sbp('chelonia.db/get', deserializedHEAD.head.manifest) - const parsedManifest = JSON.parse(manifest) - const { name } = JSON.parse(parsedManifest.body) - if (name !== 'gi.contracts/identity') { - return Boom.unauthorized('This contract type requires ownership information', 'shelter') - } - if (nconf.get('server:signup:disabled')) { - return Boom.forbidden('Registration disabled') - } - // rate limit signups in production - if (!SIGNUP_LIMIT_DISABLED) { - try { - // See discussion: https://github.com/okTurtles/group-income/pull/2280#pullrequestreview-2219347378 - const keyedIp = limiterKey(ip) - await limiterPerMinute.key(keyedIp).schedule(() => Promise.resolve()) - await limiterPerHour.key(keyedIp).schedule(() => Promise.resolve()) - await limiterPerDay.key(keyedIp).schedule(() => Promise.resolve()) - } catch { - console.warn('rate limit hit for IP:', ip) - throw Boom.tooManyRequests('Rate limit exceeded') - } - } +function safePathWithin (base: string, subpath: string): string | null { + const resolved = path.resolve(base, subpath) + if (!resolved.startsWith(base + path.sep) && resolved !== base) return null + return resolved +} + +// Helper to serve static assets with proper caching headers +function serveAsset (c: Context, subpath: string, assetsDir: string): Promise { + const basename = path.basename(subpath) + const filePath = safePathWithin(assetsDir, subpath) + if (!filePath) return Promise.resolve(notFoundNoCache(c)) + + return Deno.readFile(filePath) + .then((file) => { + const headers: Record = {} + + if (basename.includes('-cached')) { + headers['ETag'] = `"${basename}"` + headers['Cache-Control'] = 'public,max-age=31536000,immutable' } - const saltUpdateToken = request.headers['shelter-salt-update-token'] - let updateSalts - if (saltUpdateToken) { - // If we've got a salt update token (i.e., a password change), - // validate the token - updateSalts = await redeemSaltUpdateToken(deserializedHEAD.contractID, saltUpdateToken) + + if (subpath.includes('js/sw-')) { + console.debug('adding header: Service-Worker-Allowed /') + headers['Service-Worker-Allowed'] = '/' } - await sbp('backend/server/handleEntry', deserializedHEAD, request.payload) - // If it's a salt update, do it now after handling the message. This way - // we make it less likely that someone will end up locked out from their - // identity contract. - await updateSalts?.(deserializedHEAD.hash) - if (deserializedHEAD.isFirstMessage) { - // Store attribution information - if (credentials?.billableContractID) { - await sbp('backend/server/saveOwner', credentials.billableContractID, deserializedHEAD.contractID) - // A billable entity has been created - } else { - await sbp('backend/server/registerBillableEntity', deserializedHEAD.contractID) + + const ext = path.extname(subpath).toLowerCase() + headers['Content-Type'] = MIME_TYPES[ext] || 'application/octet-stream' + + return c.body(file, 200, headers) + }) + .catch(() => notFoundNoCache(c)) +} + +export function registerRoutes (app: Hono): void { + // Clean up any previous rate limiters (their intervals leak if stopRateLimiters + // wasn't called, e.g. when the SERVER_EXITING handler was consumed already) + for (const limiter of currentLimiters) { + limiter.disconnect() + clearInterval((limiter as unknown as { interval: ReturnType }).interval) + } + + const FILE_UPLOAD_MAX_BYTES = nconf.get('server:fileUploadMaxBytes') || 30 * MEGABYTE + const SIGNUP_LIMIT_MIN = nconf.get('server:signup:limit:minute') || 2 + const SIGNUP_LIMIT_HOUR = nconf.get('server:signup:limit:hour') || 10 + const SIGNUP_LIMIT_DAY = nconf.get('server:signup:limit:day') || 50 + const SIGNUP_LIMIT_DISABLED = process.env.NODE_ENV !== 'production' || nconf.get('server:signup:limit:disabled') + const ARCHIVE_MODE = nconf.get('server:archiveMode') + + const limiterPerMinute = new Bottleneck.Group({ + strategy: Bottleneck.strategy.LEAK, + highWater: 0, + reservoir: SIGNUP_LIMIT_MIN, + reservoirRefreshInterval: 60 * SECOND, + reservoirRefreshAmount: SIGNUP_LIMIT_MIN + }) + const limiterPerHour = new Bottleneck.Group({ + strategy: Bottleneck.strategy.LEAK, + highWater: 0, + reservoir: SIGNUP_LIMIT_HOUR, + reservoirRefreshInterval: 60 * 60 * SECOND, + reservoirRefreshAmount: SIGNUP_LIMIT_HOUR + }) + const limiterPerDay = new Bottleneck.Group({ + strategy: Bottleneck.strategy.LEAK, + highWater: 0, + reservoir: SIGNUP_LIMIT_DAY, + reservoirRefreshInterval: 24 * 60 * 60 * SECOND, + reservoirRefreshAmount: SIGNUP_LIMIT_DAY + }) + currentLimiters = [limiterPerMinute, limiterPerHour, limiterPerDay] + installRateLimiterSelectorsOnce() + + const isCheloniaDashboard = process.env.IS_CHELONIA_DASHBOARD_DEV + const staticServeConfig = getStaticServeConfig() + + // RESTful API routes + + // NOTE: We could get rid of this RESTful API and just rely on pubsub.js to do this + // —BUT HTTP2 might be better than websockets and so we keep this around. + // See related TODO in pubsub.js and the reddit discussion link. + app.post('/event', + zValidator('header', z.object({ + 'shelter-namespace-registration': nameSchema.optional(), + 'shelter-salt-update-token': z.string().optional(), + 'shelter-salt-registration-token': z.string().optional(), + 'shelter-deletion-token-digest': z.string().optional() + })), + bodyLimit({ maxSize: MEGABYTE }), + authMiddleware('chel-shelter', 'optional'), + async function (c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + // IMPORTANT: IT IS A REQUIREMENT THAT ANY PROXY SERVERS (E.G. nginx) IN FRONT OF US SET THE + // X-Real-IP HEADER! OTHERWISE THIS IS EASILY SPOOFED! + const ip = getClientIP(c) + try { + const contentType = c.req.header('content-type') + if (contentType && !contentType.toLowerCase().startsWith('application/json')) { + throw new HTTPException(415, { message: 'Expected JSON body' }) } - // If this is the first message in a contract and the - // `shelter-namespace-registration` header is present, proceed with also - // registering a name for the new contract - const name = request.headers['shelter-namespace-registration'] - if (name) { - // Name registation is enabled only for identity contracts - const cheloniaState = sbp('chelonia/rootState') - if (cheloniaState.contracts[deserializedHEAD.contractID]?.type === 'gi.contracts/identity') { - const r = await sbp('backend/db/registerName', name, deserializedHEAD.contractID) - if (Boom.isBoom(r)) { - return r + const payload = await c.req.text() + const validatedHeaders = c.req.valid('header') + if (!payload) throw new HTTPException(400, { message: 'Invalid request payload input' }) + const deserializedHEAD = SPMessage.deserializeHEAD(payload) + try { + const parsed = maybeParseCID(deserializedHEAD.head.manifest) + if (parsed?.code !== multicodes.SHELTER_CONTRACT_MANIFEST) { + throw new HTTPException(422, { message: 'Invalid manifest' }) + } + const credentials = c.get('credentials') as AuthCredentials | undefined + // Only allow identity contracts to be created without attribution + if (!credentials?.billableContractID && deserializedHEAD.isFirstMessage) { + const manifest = await sbp('chelonia.db/get', deserializedHEAD.head.manifest) + const parsedManifest = JSON.parse(manifest) + const { name } = JSON.parse(parsedManifest.body) + if (name !== 'gi.contracts/identity') { + throw new HTTPException(401, { message: 'This contract type requires ownership information' }) + } + if (nconf.get('server:signup:disabled')) { + throw new HTTPException(403, { message: 'Registration disabled' }) } - const saltRegistrationToken = request.headers['shelter-salt-registration-token'] - console.info(`new user: ${name}=${deserializedHEAD.contractID} (${ip})`) - if (saltRegistrationToken) { - // If we've got a salt registration token, redeem it - await redeemSaltRegistrationToken(name, deserializedHEAD.contractID, saltRegistrationToken) + // rate limit signups in production + if (!SIGNUP_LIMIT_DISABLED) { + try { + // See discussion: https://github.com/okTurtles/group-income/pull/2280#pullrequestreview-2219347378 + const keyedIp = limiterKey(ip) + await limiterPerMinute.key(keyedIp).schedule(() => Promise.resolve()) + await limiterPerHour.key(keyedIp).schedule(() => Promise.resolve()) + await limiterPerDay.key(keyedIp).schedule(() => Promise.resolve()) + } catch { + console.warn('rate limit hit for IP:', ip) + throw new HTTPException(429, { message: 'Rate limit exceeded' }) + } } } + const saltUpdateToken = validatedHeaders['shelter-salt-update-token'] + let updateSalts + if (saltUpdateToken) { + // If we've got a salt update token (i.e., a password change), + // validate the token + updateSalts = await redeemSaltUpdateToken(deserializedHEAD.contractID, saltUpdateToken) + } + await sbp('backend/server/handleEntry', deserializedHEAD, payload) + // If it's a salt update, do it now after handling the message. This way + // we make it less likely that someone will end up locked out from their + // identity contract. + await updateSalts?.(deserializedHEAD.hash) + if (deserializedHEAD.isFirstMessage) { + // Store attribution information + if (credentials?.billableContractID) { + await sbp('backend/server/saveOwner', credentials.billableContractID, deserializedHEAD.contractID) + // A billable entity has been created + } else { + await sbp('backend/server/registerBillableEntity', deserializedHEAD.contractID) + } + // If this is the first message in a contract and the + // `shelter-namespace-registration` header is present, proceed with also + // registering a name for the new contract + const name = validatedHeaders['shelter-namespace-registration'] + if (name) { + // Name registation is enabled only for identity contracts + const cheloniaState = sbp('chelonia/rootState') + if (cheloniaState.contracts[deserializedHEAD.contractID]?.type === 'gi.contracts/identity') { + try { + await sbp('backend/db/registerName', name, deserializedHEAD.contractID) + } catch (registerErr: unknown) { + if ((registerErr as Error).name === 'BackendErrorConflict') { + throw new HTTPException(409, { message: 'Name already exists' }) + } + throw registerErr + } + const saltRegistrationToken = validatedHeaders['shelter-salt-registration-token'] + console.info(`new user: ${name}=${deserializedHEAD.contractID} (${ip})`) + if (saltRegistrationToken) { + // If we've got a salt registration token, redeem it + await redeemSaltRegistrationToken(name, deserializedHEAD.contractID, saltRegistrationToken) + } + } + } + const deletionTokenDgst = validatedHeaders['shelter-deletion-token-digest'] + if (deletionTokenDgst) { + await sbp('chelonia.db/set', `_private_deletionTokenDgst_${deserializedHEAD.contractID}`, deletionTokenDgst) + } + } + // Store size information + await sbp('backend/server/updateSize', deserializedHEAD.contractID, Buffer.byteLength(payload), deserializedHEAD.isFirstMessage && !credentials?.billableContractID ? deserializedHEAD.contractID : undefined) + } catch (err: unknown) { + if (err instanceof HTTPException) throw err + console.error(err, chalk.bold.yellow((err as Error).name)) + if ((err as Error).name === 'ChelErrorDBBadPreviousHEAD' || (err as Error).name === 'ChelErrorAlreadyProcessed') { + const HEADinfo = await sbp('chelonia/db/latestHEADinfo', deserializedHEAD.contractID) ?? { HEAD: null, height: 0 } + return c.json({ message: (err as Error).message, data: { HEADinfo } }, 409, { + 'shelter-headinfo-head': HEADinfo.HEAD, + 'shelter-headinfo-height': String(HEADinfo.height) + }) + } else if ((err as Error).name === 'ChelErrorSignatureError') { + throw new HTTPException(422, { message: 'Invalid signature' }) + } else if ((err as Error).name === 'ChelErrorSignatureKeyUnauthorized') { + throw new HTTPException(403, { message: 'Unauthorized signing key' }) + } + throw err // rethrow error } - const deletionTokenDgst = request.headers['shelter-deletion-token-digest'] - if (deletionTokenDgst) { - await sbp('chelonia.db/set', `_private_deletionTokenDgst_${deserializedHEAD.contractID}`, deletionTokenDgst) - } + return c.text(deserializedHEAD.hash) + } catch (err) { + if (err instanceof HTTPException) throw err + ;(err as unknown as { ip: string }).ip = ip + logger.error(err, 'POST /event', (err as Error).message) + throw err } - // Store size information - await sbp('backend/server/updateSize', deserializedHEAD.contractID, Buffer.byteLength(request.payload as Buffer), deserializedHEAD.isFirstMessage && !credentials?.billableContractID ? deserializedHEAD.contractID : undefined) - } catch (err: unknown) { - console.error(err, chalk.bold.yellow((err as Error).name)) - if ((err as Error).name === 'ChelErrorDBBadPreviousHEAD' || (err as Error).name === 'ChelErrorAlreadyProcessed') { - const HEADinfo = await sbp('chelonia/db/latestHEADinfo', deserializedHEAD.contractID) ?? { HEAD: null, height: 0 } - const r = Boom.conflict((err as Error).message, { HEADinfo }) - Object.assign(r.output.headers, { - 'shelter-headinfo-head': HEADinfo.HEAD, - 'shelter-headinfo-height': HEADinfo.height - }) - return r - } else if ((err as Error).name === 'ChelErrorSignatureError') { - return Boom.badData('Invalid signature') - } else if ((err as Error).name === 'ChelErrorSignatureKeyUnauthorized') { - return Boom.forbidden('Unauthorized signing key') - } - throw err // rethrow error - } - return deserializedHEAD.hash - } catch (err) { - (err as unknown as { ip: string }).ip = ip - logger.error(err, 'POST /event', (err as Error).message) - return err - } -}) - -route.GET('/eventsAfter/{contractID}/{since}/{limit?}', { - validate: { - params: Joi.object({ - contractID: Joi.string().regex(CID_REGEX).required(), - since: Joi.string().regex(POSITIVE_INTEGER_REGEX).required(), - limit: Joi.string().regex(POSITIVE_INTEGER_REGEX) - }), - query: Joi.object({ - keyOps: Joi.boolean() }) - } -}, async function (request) { - const { contractID, since, limit } = request.params - const ip = request.headers['x-real-ip'] || request.info.remoteAddress - try { - const parsed = maybeParseCID(contractID) - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { - return Boom.badRequest() - } - const stream = await sbp('backend/db/streamEntriesAfter', contractID, Number(since), limit == null ? undefined : Number(limit), { keyOps: !!request.query['keyOps'] }) - // "On an HTTP server, make sure to manually close your streams if a request is aborted." - // From: http://knexjs.org/#Interfaces-Streams - // https://github.com/tgriesser/knex/wiki/Manually-Closing-Streams - // Plus: https://hapijs.com/api#request-events - // request.on('disconnect', stream.end.bind(stream)) - // NOTE: since rewriting database.js to remove objection.js and knex, - // we're currently returning a Readable stream, which doesn't have - // '.end'. If there are any issues we can try switching to returning a - // Writable stream. Both types however do have .destroy. - request.events.once('disconnect', stream.destroy.bind(stream)) - return stream - } catch (err) { - (err as unknown as { ip: string }).ip = ip - logger.error(err, `GET /eventsAfter/${contractID}/${since}`, (err as Error).message) - return err as object[] - } -}) + app.get('/eventsAfter/:contractID/:since/:limit?', + zValidator('param', z.object({ + contractID: cidSchema, + since: nonNegativeIntegerSchema, + limit: nonNegativeIntegerSchema.optional() + }).strict()), + zValidator('query', z.object({ + keyOps: z.stringbool().optional() + }).strict()), + async function (c) { + const { contractID, since, limit } = c.req.valid('param') + + const keyOps = c.req.valid('query').keyOps + const ip = getClientIP(c) + try { + const parsed = maybeParseCID(contractID) + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { + throw new HTTPException(400) + } -// This endpoint returns to anyone in possession of a contract's SAK all of the -// resources that that contract owns (without recursion). This is useful for -// APIs and for some UI actions (e.g., to warn users about resources that would -// be (cascade) deleted following a delete) -route.GET('/ownResources', { - auth: { - strategies: ['chel-shelter'], - mode: 'required' - } -}, async function (request): Promise { - const billableContractID = request.auth.credentials.billableContractID - const resources = (await sbp('chelonia.db/get', `_private_resources_${billableContractID}`))?.split('\x00') + const stream = await sbp('backend/db/streamEntriesAfter', contractID, Number(since), limit == null ? undefined : Number(limit), { keyOps }) as Readable + stream.on('error', (err) => logger.error('eventsAfter stream error', err)) + // "On an HTTP server, make sure to manually close your streams if a request is aborted." + // From: http://knexjs.org/#Interfaces-Streams + // https://github.com/tgriesser/knex/wiki/Manually-Closing-Streams + // Use the request abort signal to destroy the stream when the client disconnects + c.req.raw.signal.addEventListener('abort', () => stream.destroy()) + // Convert the Node Readable stream to a web ReadableStream for the Response + const streamHeaders = (stream as { headers?: Record }).headers || {} + const webStream = Readable.toWeb(stream) as ReadableStream + return new Response(webStream, { + headers: { 'content-type': 'application/json', ...streamHeaders } + }) + } catch (err) { + if (err instanceof HTTPException) throw err + ;(err as unknown as { ip: string }).ip = ip + logger.error(err, `GET /eventsAfter/${contractID}/${since}`, (err as Error).message) + throw errorMapper(err as Error) + } + }) - return resources || [] -}) + // This endpoint returns to anyone in possession of a contract's SAK all of the + // resources that that contract owns (without recursion). This is useful for + // APIs and for some UI actions (e.g., to warn users about resources that would + // be (cascade) deleted following a delete) + app.get('/ownResources', + authMiddleware('chel-shelter', 'required'), + async function (c) { + const billableContractID = (c.get('credentials') as AuthCredentials).billableContractID + const resources = (await sbp('chelonia.db/get', `_private_resources_${billableContractID}`))?.split('\x00') + + return c.json(resources || []) + }) -if (process.env.NODE_ENV === 'development') { - const levelToColor = { - error: chalk.bold.red, - warn: chalk.yellow, - log: chalk.green, - info: chalk.green, - debug: chalk.blue - } - route.POST('/log', { - validate: { - payload: Joi.object({ - level: Joi.string().required(), - value: Joi.string().required() - }) + if (process.env.NODE_ENV === 'development') { + const levelToColor = { + error: chalk.bold.red, + warn: chalk.yellow, + log: chalk.green, + info: chalk.green, + debug: chalk.blue } - }, function (request, h) { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - const ip = request.headers['x-real-ip'] || request.info.remoteAddress - const log = (levelToColor as Record string>)[(request.payload as { level: string }).level] - console.debug(chalk.bold.yellow(`REMOTE LOG (${ip}): `) + log(`[${(request.payload as { level: string }).level}] ${(request.payload as { value: string }).value}`)) - return h.response().code(200) - }) -} + app.post('/log', async function (c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + const body = await c.req.json() as { level: string, value: string } + if (!body.level || !body.value) throw new HTTPException(400, { message: 'level and value are required' }) + const ip = getClientIP(c) + const log = (levelToColor as Record string>)[body.level] + console.debug(chalk.bold.yellow(`REMOTE LOG (${ip}): `) + log(`[${body.level}] ${body.value}`)) + return c.body(null, 200) + }) + } -/* + /* // The following endpoint is disabled because name registrations are handled // through the `shelter-namespace-registration` header when registering a // new contract -route.POST('/name', { - validate: { - payload: Joi.object({ - name: Joi.string().required(), - value: Joi.string().required() - }) - } -}, async function (request, h): Promise { +app.post('/name', async function (c) { try { - const { name, value } = request.payload - if (value.startsWith('_private')) return Boom.badData() - return await sbp('backend/db/registerName', name, value) + const { name, value } = await c.req.json() + if (!name || !value) throw new HTTPException(400) + if (value.startsWith('_private')) throw new HTTPException(422) + return c.json(await sbp('backend/db/registerName', name, value)) } catch (err) { + if (err instanceof HTTPException) throw err logger.error(err, 'POST /name', (err as Error).message) - return err + throw err } }) */ -route.GET('/name/{name}', { - validate: { - params: Joi.object({ - name: Joi.string().regex(NAME_REGEX).required() - }) - } -}, async function (request, h): Promise { - const { name } = request.params - try { - const lookupResult = await sbp('backend/db/lookupName', name) - return lookupResult - ? h.response(lookupResult).type('text/plain') - : notFoundNoCache(h) - } catch (err) { - logger.error(err, `GET /name/${name}`, (err as Error).message) - return err - } -}) - -route.GET('/latestHEADinfo/{contractID}', { - cache: { otherwise: 'no-store' }, - validate: { - params: Joi.object({ - contractID: Joi.string().regex(CID_REGEX).required() - }) - } -}, async function (request, h): Promise { - const { contractID } = request.params - try { - const parsed = maybeParseCID(contractID) - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) return Boom.badRequest() - - const HEADinfo = await sbp('chelonia/db/latestHEADinfo', contractID) - if (HEADinfo === '') { - return Boom.resourceGone() - } - if (!HEADinfo) { - console.warn(`[backend] latestHEADinfo not found for ${contractID}`) - return notFoundNoCache(h) + app.get('/name/:name', + zValidator('param', z.object({ name: nameSchema }).strict()), + async function (c) { + const { name } = c.req.valid('param') + try { + const lookupResult = await sbp('backend/db/lookupName', name) + return lookupResult + ? c.text(lookupResult) + : notFoundNoCache(c) + } catch (err) { + logger.error(err, `GET /name/${name}`, (err as Error).message) + throw err + } } - return HEADinfo - } catch (err) { - logger.error(err, `GET /latestHEADinfo/${contractID}`, (err as Error).message) - return err - } -}) - -route.GET('/time', {}, function (_request, h) { - return h - .response(new Date().toISOString()) - .header('cache-control', 'no-store') - .type('text/plain') -}) + ) -// TODO: if the browser deletes our cache then not everyone -// has a complete copy of the data and can act as a -// new coordinating server... I don't like that. + app.get('/latestHEADinfo/:contractID', + zValidator('param', z.object({ contractID: cidSchema }).strict()), + async function (c) { + const { contractID } = c.req.valid('param') + try { + const parsed = maybeParseCID(contractID) + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) throw new HTTPException(400) -// API endpoint to check for streams support -route.POST('/streams-test', { - payload: { - parse: false - } -}, -function (request, h) { - if ( - (request.payload as Buffer).byteLength === 2 && - Buffer.from(request.payload as Buffer).toString() === 'ok' - ) { - return h.response().code(204) - } else { - return Boom.badRequest() - } -} -) - -// Development file upload route. The difference between this and /file is that -// this endpoint bypasses checks in /file for well-formedness, and it also -// doesn't set or read accounting information. -// If accepted, the file will be stored in Chelonia DB. -if (process.env.NODE_ENV === 'development') { - route.POST('/dev-file', { - payload: { - output: 'data', - multipart: true, - allow: 'multipart/form-data', - failAction: function (_request, _h, err) { - console.error('failAction error:', err) - return Boom.isBoom(err) ? err : Boom.boomify(err instanceof Error ? err : new Error(err)) - }, - maxBytes: 6 * MEGABYTE, // TODO: make this a configurable setting - timeout: 10 * SECOND // TODO: make this a configurable setting + const HEADinfo = await sbp('chelonia/db/latestHEADinfo', contractID) + if (HEADinfo === '') { + throw new HTTPException(410) + } + if (!HEADinfo) { + console.warn(`[backend] latestHEADinfo not found for ${contractID}`) + return notFoundNoCache(c) + } + return c.json(HEADinfo, 200, { 'Cache-Control': 'no-store' }) + } catch (err) { + if (err instanceof HTTPException) throw err + logger.error(err, `GET /latestHEADinfo/${contractID}`, (err as Error).message) + throw err + } } - }, async function (request): Promise { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - try { - console.log('FILE UPLOAD!') - const { hash, data } = request.payload as ({hash: string, data: string}) - if (!hash) return Boom.badRequest('missing hash') - if (!data) return Boom.badRequest('missing data') + ) - const parsed = maybeParseCID(hash) - if (!parsed) return Boom.badRequest('invalid hash') + app.get('/time', function (c) { + return c.text(new Date().toISOString(), 200, { + 'Cache-Control': 'no-store' + }) + }) - const ourHash = createCID(data, parsed.code) - if (ourHash !== hash) { - console.error(`hash(${hash}) != ourHash(${ourHash})`) - return Boom.badRequest('bad hash!') - } - await sbp('chelonia.db/set', hash, data) - return '/file/' + hash - } catch (err) { - logger.error(err) - return Boom.internal('File upload failed') + // TODO: if the browser deletes our cache then not everyone + // has a complete copy of the data and can act as a + // new coordinating server... I don't like that. + + // API endpoint to check for streams support + app.post('/streams-test', async function (c) { + const raw = await c.req.arrayBuffer() + const buf = Buffer.from(raw) + if (buf.byteLength === 2 && buf.toString() === 'ok') { + return c.body(null, 204) + } else { + throw new HTTPException(400) } }) -} -// File upload route. -// If accepted, the file will be stored in Chelonia DB. -route.POST('/file', { - auth: { - strategies: ['chel-shelter'], - mode: 'required' - }, - payload: { - parse: true, - output: 'stream', - multipart: { output: 'annotated' }, - allow: 'multipart/form-data', - failAction: function (_request, _h, err) { - console.error(err, 'failAction error') - return Boom.isBoom(err) ? err : Boom.boomify(err instanceof Error ? err : new Error(err)) - }, - maxBytes: FILE_UPLOAD_MAX_BYTES, - timeout: 10 * SECOND // TODO: make this a configurable setting - } -}, async function (request, h): Promise { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - try { - console.info('FILE UPLOAD!') - const credentials = request.auth.credentials - if (!credentials?.billableContractID) { - return Boom.unauthorized('Uploading files requires ownership information', 'shelter') - } - const manifestMeta = (request.payload as { manifest: Record })['manifest'] - if (typeof manifestMeta !== 'object') return Boom.badRequest('missing manifest') - if (manifestMeta.filename !== 'manifest.json') return Boom.badRequest('wrong manifest filename') - if (!(manifestMeta.payload instanceof Uint8Array)) return Boom.badRequest('wrong manifest format') - const manifest = (() => { + // Development file upload route. The difference between this and /file is that + // this endpoint bypasses checks in /file for well-formedness, and it also + // doesn't set or read accounting information. + // If accepted, the file will be stored in Chelonia DB. + if (process.env.NODE_ENV === 'development') { + app.post('/dev-file', bodyLimit({ maxSize: 6 * MEGABYTE }), async function (c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) try { - return JSON.parse(Buffer.from(manifestMeta.payload).toString()) - } catch { - throw Boom.badData('Error parsing manifest') - } - })() - if (typeof manifest !== 'object') return Boom.badData('manifest format is invalid') - if (manifest.version !== '1.0.0') return Boom.badData('unsupported manifest version') - if (manifest.cipher !== 'aes256gcm') return Boom.badData('unsupported cipher') - if (!Array.isArray(manifest.chunks) || !manifest.chunks.length) return Boom.badData('missing chunks') - - // Now that the manifest format looks right, validate the chunks - let ourSize = 0 - const chunks = manifest.chunks.map((chunk: { hash: string; size: number }, i: number) => { - // Validate the chunk information - if ( - !Array.isArray(chunk) || - chunk.length !== 2 || - typeof chunk[0] !== 'number' || - typeof chunk[1] !== 'string' || - !Number.isSafeInteger(chunk[0]) || - chunk[0] <= 0 - ) { - throw Boom.badData('bad chunk description') - } - if (!(request.payload as unknown[])[i] || !((request.payload as { payload: unknown }[])[i].payload instanceof Uint8Array)) { - throw Boom.badRequest('chunk missing in submitted data') - } - const ourHash = createCID((request.payload as { payload: Uint8Array }[])[i].payload, multicodes.SHELTER_FILE_CHUNK) - if ((request.payload as { payload: Uint8Array }[])[i].payload.byteLength !== chunk[0]) { - throw Boom.badRequest('bad chunk size') - } - if (ourHash !== chunk[1]) { - throw Boom.badRequest('bad chunk hash') + console.log('FILE UPLOAD!') + const formData = await c.req.parseBody({ all: true }) + const hash = formData['hash'] as string + const data = formData['data'] as string + if (!hash) throw new HTTPException(400, { message: 'missing hash' }) + if (!data) throw new HTTPException(400, { message: 'missing data' }) + + const parsed = maybeParseCID(hash) + if (!parsed) throw new HTTPException(400, { message: 'invalid hash' }) + + const ourHash = createCID(data, parsed.code) + if (ourHash !== hash) { + console.error(`hash(${hash}) != ourHash(${ourHash})`) + throw new HTTPException(400, { message: 'bad hash!' }) + } + await sbp('chelonia.db/set', hash, data) + return c.text('/file/' + hash) + } catch (err) { + if (err instanceof HTTPException) throw err + logger.error(err) + throw new HTTPException(500, { message: 'File upload failed' }) } - // We're done validating the chunk - ourSize += chunk[0] - return [ourHash, (request.payload as { payload: Uint8Array }[])[i].payload] }) - // Finally, verify the size is correct - if (ourSize !== manifest.size) return Boom.badRequest('Mismatched total size') - - const manifestHash = createCID(manifestMeta.payload, multicodes.SHELTER_FILE_MANIFEST) - - // Check that we're not overwriting data. At best this is a useless operation - // since there is no need to write things that exist. However, overwriting - // data would also make it ambiguous in terms of ownership. For example, - // someone could upload a file F1 using some existing chunks (from a - // different file F2) and then request to delete their file F1, which would - // result in corrupting F2. - // Ensure that the manifest doesn't exist - if (await sbp('chelonia.db/get', manifestHash)) { - throw new Error(`Manifest ${manifestHash} already exists`) - } - // Ensure that the chunks do not exist - await Promise.all(chunks.map(async ([cid]: [string]) => { - const exists = !!(await sbp('chelonia.db/get', cid)) - if (exists) { - throw new Error(`Chunk ${cid} already exists`) - } - })) - // Now, store all chunks and the manifest - await Promise.all(chunks.map(([cid, data]: [string, unknown]) => sbp('chelonia.db/set', cid, data))) - await sbp('chelonia.db/set', manifestHash, manifestMeta.payload) - // Store attribution information - await sbp('backend/server/saveOwner', credentials.billableContractID, manifestHash) - // Store size information - const size = manifest.size + manifestMeta.payload.byteLength - await sbp('backend/server/updateSize', manifestHash, size) - await sbp('backend/server/updateContractFilesTotalSize', credentials.billableContractID, size) - // Store deletion token - const deletionTokenDgst = request.headers['shelter-deletion-token-digest'] - if (deletionTokenDgst) { - await sbp('chelonia.db/set', `_private_deletionTokenDgst_${manifestHash}`, deletionTokenDgst) - } - return h.response(manifestHash) - } catch (err) { - logger.error(err, 'POST /file', (err as Error).message) - return err } -}) -// Serve data from Chelonia DB. -// Note that a `Last-Modified` header isn't included in the response. -route.GET('/file/{hash}', { - validate: { - params: Joi.object({ - hash: Joi.string().regex(CID_REGEX).required() - }) - } -}, async function (request, h): Promise { - const { hash } = request.params + // File upload route. + // If accepted, the file will be stored in Chelonia DB. + app.post('/file', + authMiddleware('chel-shelter', 'required'), + bodyLimit({ maxSize: FILE_UPLOAD_MAX_BYTES }), + async function (c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + try { + console.info('FILE UPLOAD!') + const credentials = c.get('credentials') as AuthCredentials + if (!credentials?.billableContractID) { + throw new HTTPException(401, { message: 'Uploading files requires ownership information' }) + } - const parsed = maybeParseCID(hash) - if (!parsed) { - return Boom.badRequest() - } + const contentType = c.req.header('content-type') || '' + if (!contentType.includes('multipart/form-data')) { + throw new HTTPException(400, { message: 'Expected multipart/form-data' }) + } - const blobOrString = await sbp('chelonia.db/get', `any:${hash}`) - if (blobOrString?.length === 0) { - return Boom.resourceGone() - } else if (!blobOrString) { - return notFoundNoCache(h) - } + const formData = await c.req.formData() + const manifestFile = formData.get('manifest') as File | null + if (!manifestFile) throw new HTTPException(400, { message: 'missing manifest' }) + if (manifestFile.name !== 'manifest.json') throw new HTTPException(400, { message: 'wrong manifest filename' }) + const manifestPayload = new Uint8Array(await manifestFile.arrayBuffer()) - const type = cidLookupTable[parsed.code] || 'application/octet-stream' - - return h - .response(blobOrString) - .etag(hash) - .header('Cache-Control', 'public,max-age=31536000,immutable') - // CSP to disable everything -- this only affects direct navigation to the - // `/file` URL. - // The CSP below prevents any sort of resource loading or script execution - // on direct navigation. The `nosniff` header instructs the browser to - // honour the provided content-type. - .header('content-security-policy', 'default-src \'none\'; frame-ancestors \'none\'; form-action \'none\'; upgrade-insecure-requests; sandbox') - .header('x-content-type-options', 'nosniff') - .type(type) -}) + const manifest = (() => { + try { + return JSON.parse(Buffer.from(manifestPayload).toString()) + } catch { + throw new HTTPException(422, { message: 'Error parsing manifest' }) + } + })() + if (!manifest || typeof manifest !== 'object') throw new HTTPException(422, { message: 'manifest format is invalid' }) + if (manifest.version !== '1.0.0') throw new HTTPException(422, { message: 'unsupported manifest version' }) + if (manifest.cipher !== 'aes256gcm') throw new HTTPException(422, { message: 'unsupported cipher' }) + if (!Array.isArray(manifest.chunks) || !manifest.chunks.length) throw new HTTPException(422, { message: 'missing chunks' }) + + // Collect all chunk files from form data (numbered keys: 0, 1, 2, ...) + const chunkFiles: File[] = [] + for (let i = 0; ; i++) { + const chunkFile = formData.get(String(i)) as File | null + if (!chunkFile) break + chunkFiles.push(chunkFile) + } -route.POST('/deleteFile/{hash}', { - auth: { - // Allow file deletion, and allow either the bearer of the deletion token or - // the file owner to delete it - strategies: ['chel-shelter', 'chel-bearer'], - mode: 'required' - }, - validate: { - params: Joi.object({ - hash: Joi.string().regex(CID_REGEX).required() + // Now that the manifest format looks right, validate the chunks + let ourSize = 0 + const chunks: [string, Uint8Array][] = await Promise.all(manifest.chunks.map(async (chunk: [number, string], i: number) => { + // Validate the chunk information + if ( + !Array.isArray(chunk) || + chunk.length !== 2 || + typeof chunk[0] !== 'number' || + typeof chunk[1] !== 'string' || + !Number.isSafeInteger(chunk[0]) || + chunk[0] <= 0 + ) { + throw new HTTPException(422, { message: 'bad chunk description' }) + } + if (!chunkFiles[i]) { + throw new HTTPException(400, { message: 'chunk missing in submitted data' }) + } + const chunkPayload = new Uint8Array(await chunkFiles[i].arrayBuffer()) + const ourHash = createCID(chunkPayload, multicodes.SHELTER_FILE_CHUNK) + if (chunkPayload.byteLength !== chunk[0]) { + throw new HTTPException(400, { message: 'bad chunk size' }) + } + if (ourHash !== chunk[1]) { + throw new HTTPException(400, { message: 'bad chunk hash' }) + } + // We're done validating the chunk + ourSize += chunk[0] + return [ourHash, chunkPayload] as [string, Uint8Array] + })) + // Finally, verify the size is correct + if (ourSize !== manifest.size) throw new HTTPException(400, { message: 'Mismatched total size' }) + + const manifestHash = createCID(manifestPayload, multicodes.SHELTER_FILE_MANIFEST) + + // Check that we're not overwriting data. At best this is a useless operation + // since there is no need to write things that exist. However, overwriting + // data would also make it ambiguous in terms of ownership. For example, + // someone could upload a file F1 using some existing chunks (from a + // different file F2) and then request to delete their file F1, which would + // result in corrupting F2. + // Ensure that the manifest doesn't exist + if (await sbp('chelonia.db/get', manifestHash)) { + throw new Error(`Manifest ${manifestHash} already exists`) + } + // Ensure that the chunks do not exist + await Promise.all(chunks.map(async ([cid]) => { + const exists = !!(await sbp('chelonia.db/get', cid)) + if (exists) { + throw new Error(`Chunk ${cid} already exists`) + } + })) + // Now, store all chunks and the manifest + await Promise.all(chunks.map(([cid, data]) => sbp('chelonia.db/set', cid, data))) + await sbp('chelonia.db/set', manifestHash, manifestPayload) + // Store attribution information + await sbp('backend/server/saveOwner', credentials.billableContractID, manifestHash) + // Store size information + const size = manifest.size + manifestPayload.byteLength + await sbp('backend/server/updateSize', manifestHash, size) + await sbp('backend/server/updateContractFilesTotalSize', credentials.billableContractID, size) + // Store deletion token + const deletionTokenDgst = c.req.header('shelter-deletion-token-digest') + if (deletionTokenDgst) { + await sbp('chelonia.db/set', `_private_deletionTokenDgst_${manifestHash}`, deletionTokenDgst) + } + return c.text(manifestHash) + } catch (err) { + if (err instanceof HTTPException) throw err + logger.error(err, 'POST /file', (err as Error).message) + throw err + } }) - } -}, async function (request, h): Promise { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - const { hash } = request.params - const strategy = request.auth.strategy - const parsed = maybeParseCID(hash) - if (parsed?.code !== multicodes.SHELTER_FILE_MANIFEST) { - return Boom.badRequest() - } - const owner = await sbp('chelonia.db/get', `_private_owner_${hash}`) - if (!owner) { - return Boom.notFound() - } + // Serve data from Chelonia DB. + // Note that a `Last-Modified` header isn't included in the response. + app.get('/file/:hash', + zValidator('param', z.object({ hash: cidSchema }).strict()), + async function (c) { + const { hash } = c.req.valid('param') - switch (strategy) { - case 'chel-shelter': { - const ultimateOwner = await lookupUltimateOwner(owner) - // Check that the user making the request is the ultimate owner (i.e., - // that they have permission to delete this file) - if (!ctEq(request.auth.credentials.billableContractID as string, ultimateOwner)) { - return Boom.unauthorized('Invalid shelter auth', 'shelter') - } - break - } - case 'chel-bearer': { - const expectedTokenDgst = await sbp('chelonia.db/get', `_private_deletionTokenDgst_${hash}`) - if (!expectedTokenDgst) { - return Boom.notFound() + const parsed = maybeParseCID(hash) + if (!parsed) { + throw new HTTPException(400) } - const tokenDgst = blake32Hash(request.auth.credentials.token as string) - // Constant-time comparison - // Check that the token provided matches the deletion token for this file - if (!ctEq(expectedTokenDgst, tokenDgst)) { - return Boom.unauthorized('Invalid token', 'bearer') + + const blobOrString = await sbp('chelonia.db/get', `any:${hash}`) + if (blobOrString?.length === 0) { + throw new HTTPException(410) + } else if (!blobOrString) { + return notFoundNoCache(c) } - break - } - default: - return Boom.unauthorized('Missing or invalid auth strategy') - } - // Authentication passed, now proceed to delete the file and its associated - // keys - try { - await sbp('backend/deleteFile', hash, null, true) - return h.response() - } catch (e) { - return errorMapper(e as Error) - } -}) + const type = cidLookupTable[parsed.code] || 'application/octet-stream' + + return c.body(blobOrString, 200, { + 'ETag': `"${hash}"`, + 'Cache-Control': 'public,max-age=31536000,immutable', + // CSP to disable everything -- this only affects direct navigation to the + // `/file` URL. + // The CSP below prevents any sort of resource loading or script execution + // on direct navigation. The `nosniff` header instructs the browser to + // honour the provided content-type. + 'Content-Security-Policy': 'default-src \'none\'; frame-ancestors \'none\'; form-action \'none\'; upgrade-insecure-requests; sandbox', + 'X-Content-Type-Options': 'nosniff', + 'Content-Type': type + }) + } + ) + + app.post('/deleteFile/:hash', + authMiddleware(['chel-shelter', 'chel-bearer'], 'required'), + zValidator('param', z.object({ hash: cidSchema }).strict()), + async function (c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + const { hash } = c.req.valid('param') + const strategy = c.get('authStrategy') + const parsed = maybeParseCID(hash) + if (parsed?.code !== multicodes.SHELTER_FILE_MANIFEST) { + throw new HTTPException(400) + } -route.POST('/deleteContract/{hash}', { - auth: { - // Allow file deletion, and allow either the bearer of the deletion token or - // the file owner to delete it - strategies: ['chel-shelter', 'chel-bearer'], - mode: 'required' - } -}, async function (request, h): Promise { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - const { hash } = request.params - const strategy = request.auth.strategy - if (!hash || hash.startsWith('_private')) return Boom.notFound() - - switch (strategy) { - case 'chel-shelter': { const owner = await sbp('chelonia.db/get', `_private_owner_${hash}`) if (!owner) { - return Boom.notFound() + throw new HTTPException(404) } - const ultimateOwner = await lookupUltimateOwner(owner) - // Check that the user making the request is the ultimate owner (i.e., - // that they have permission to delete this file) - if (!ctEq(request.auth.credentials.billableContractID as string, ultimateOwner)) { - return Boom.unauthorized('Invalid shelter auth', 'shelter') - } - break - } - case 'chel-bearer': { - const expectedTokenDgst = await sbp('chelonia.db/get', `_private_deletionTokenDgst_${hash}`) - if (!expectedTokenDgst) { - return Boom.notFound() - } - const tokenDgst = blake32Hash(request.auth.credentials.token as string) - // Constant-time comparison - // Check that the token provided matches the deletion token for this contract - if (!ctEq(expectedTokenDgst, tokenDgst)) { - return Boom.unauthorized('Invalid token', 'bearer') + const credentials = c.get('credentials') as AuthCredentials + switch (strategy) { + case 'chel-shelter': { + const ultimateOwner = await lookupUltimateOwner(owner) + // Check that the user making the request is the ultimate owner (i.e., + // that they have permission to delete this file) + if (!ctEq(credentials.billableContractID as string, ultimateOwner)) { + throw new HTTPException(401, { message: 'Invalid shelter auth' }) + } + break + } + case 'chel-bearer': { + const expectedTokenDgst = await sbp('chelonia.db/get', `_private_deletionTokenDgst_${hash}`) + if (!expectedTokenDgst) { + throw new HTTPException(404) + } + const tokenDgst = blake32Hash(credentials.token as string) + // Constant-time comparison + // Check that the token provided matches the deletion token for this file + if (!ctEq(expectedTokenDgst, tokenDgst)) { + throw new HTTPException(401, { message: 'Invalid token' }) + } + break + } + default: + throw new HTTPException(401, { message: 'Missing or invalid auth strategy' }) } - break - } - default: - return Boom.unauthorized('Missing or invalid auth strategy') - } - - const username = await sbp('chelonia.db/get', `_private_cid2name_${hash}`) - // Authentication passed, now proceed to delete the contract and its associated - // keys - try { - const [id] = sbp('chelonia.persistentActions/enqueue', ['backend/deleteContract', hash, null, true]) - if (username) { - const ip = request.headers['x-real-ip'] || request.info.remoteAddress - console.info({ contractID: hash, username, ip, taskId: id }, 'Scheduled deletion on named contract') - } - // We return the queue ID to allow users to track progress - // TODO: Tracking progress not yet implemented - return h.response({ id }).code(202) - } catch (e) { - return errorMapper(e as Error) - } -}) -route.POST('/kv/{contractID}/{key}', { - auth: { - strategies: ['chel-shelter'], - mode: 'required' - }, - payload: { - parse: false, - maxBytes: 6 * MEGABYTE, // TODO: make this a configurable setting - timeout: 10 * SECOND // TODO: make this a configurable setting - }, - validate: { - params: Joi.object({ - contractID: Joi.string().regex(CID_REGEX).required(), - key: Joi.string().regex(KV_KEY_REGEX).required() + // Authentication passed, now proceed to delete the file and its associated + // keys + try { + await sbp('backend/deleteFile', hash, null, true) + return c.body(null, 200) + } catch (e) { + throw errorMapper(e as Error) + } }) - } -}, function (request, h) { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - const { contractID, key } = request.params - const parsed = maybeParseCID(contractID) - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { - return Boom.badRequest() - } - - if (!ctEq(request.auth.credentials.billableContractID as string, contractID)) { - return Boom.unauthorized(null, 'shelter') - } - - // Use a queue to prevent race conditions (for example, writing to a contract - // that's being deleted or updated) - return sbp('chelonia/queueInvocation', contractID, async () => { - const existing = await sbp('chelonia.db/get', `_private_kv_${contractID}_${key}`) - - // Some protection against accidental overwriting by implementing the if-match - // header - // If-Match contains a list of ETags or '*' - // If `If-Match` contains a known ETag, allow the request through, otherwise - // return 412 Precondition Failed. - // This is useful to clients to avoid accidentally overwriting existing data - // For example, client A and client B want to write to key 'K', which contains - // an array. Let's say that the array is originally empty (`[]`) and A and B - // want to append `A` and `B` to it, respectively. If both write at the same - // time, the following could happen: - // t = 0: A reads `K`, gets `[]` - // t = 1: B reads `K`, gets `[]` - // t = 2: A writes `['A']` to `K` - // t = 3: B writes `['B']` to `K` <-- ERROR: B should have written `['A', 'B']` - // To avoid this situation, A and B could use `If-Match`, which would have - // given B a 412 response - const expectedEtag = request.headers['if-match'] - if (!expectedEtag) { - return Boom.badRequest('if-match is required') - } - // "Quote" string (to match ETag format) - const cid = existing ? createCID(existing, multicodes.RAW) : '' + app.post('/deleteContract/:hash', + authMiddleware(['chel-shelter', 'chel-bearer'], 'required'), + zValidator('param', z.object({ hash: cidSchema }).strict()), + async function (c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + const { hash } = c.req.valid('param') + const strategy = c.get('authStrategy') + + const credentials = c.get('credentials') as AuthCredentials + switch (strategy) { + case 'chel-shelter': { + const owner = await sbp('chelonia.db/get', `_private_owner_${hash}`) + if (!owner) { + throw new HTTPException(404) + } - if (expectedEtag === '*') { - // pass through - } else { - if (!expectedEtag.split(',').map((v: string) => v.trim()).includes(`"${cid}"`)) { - // We need this `x-cid` because HAPI modifies Etags - return h.response(existing || '').etag(cid).header('x-cid', `"${cid}"`).code(412) + const ultimateOwner = await lookupUltimateOwner(owner) + // Check that the user making the request is the ultimate owner (i.e., + // that they have permission to delete this file) + if (!ctEq(credentials.billableContractID as string, ultimateOwner)) { + throw new HTTPException(401, { message: 'Invalid shelter auth' }) + } + break + } + case 'chel-bearer': { + const expectedTokenDgst = await sbp('chelonia.db/get', `_private_deletionTokenDgst_${hash}`) + if (!expectedTokenDgst) { + throw new HTTPException(404) + } + const tokenDgst = blake32Hash(credentials.token as string) + // Constant-time comparison + // Check that the token provided matches the deletion token for this contract + if (!ctEq(expectedTokenDgst, tokenDgst)) { + throw new HTTPException(401, { message: 'Invalid token' }) + } + break + } + default: + throw new HTTPException(401, { message: 'Missing or invalid auth strategy' }) } - } - try { - const serializedData = JSON.parse(request.payload.toString()) - const { contracts } = sbp('chelonia/rootState') - // Check that the height is the latest value. Not only should the height be - // the latest, but also enforcing this lets us check that signatures are - // using the latest (cryptograhpic) keys. Since the KV is detached from the - // contract, in isolation it's impossible to know if an old signature is - // just because it was created in the past, or if it's because someone - // is reusing a previously good key that has since been revoked. - if (contracts[contractID].height !== Number(serializedData.height)) { - return h.response(existing || '').etag(cid).header('x-cid', `"${cid}"`).code(409) + const username = await sbp('chelonia.db/get', `_private_cid2name_${hash}`) + // Authentication passed, now proceed to delete the contract and its associated + // keys + try { + const [id] = sbp('chelonia.persistentActions/enqueue', ['backend/deleteContract', hash, null, true]) + if (username) { + const ip = getClientIP(c) + console.info({ contractID: hash, username, ip, taskId: id }, 'Scheduled deletion on named contract') + } + // We return the queue ID to allow users to track progress + // TODO: Tracking progress not yet implemented + return c.json({ id }, 202) + } catch (e) { + throw errorMapper(e as Error) } - // Check that the signature is valid - sbp('chelonia/parseEncryptedOrUnencryptedDetachedMessage', { - contractID, - serializedData, - meta: key - }) - } catch { - return Boom.badData() - } - - const existingSize = existing ? Buffer.from(existing).byteLength : 0 - await sbp('chelonia.db/set', `_private_kv_${contractID}_${key}`, request.payload) - await sbp('backend/server/updateSize', contractID, (request.payload as Buffer).byteLength - existingSize) - await appendToIndexFactory(`_private_kvIdx_${contractID}`)(key) - // No await on broadcast for faster responses - sbp('backend/server/broadcastKV', contractID, key, request.payload.toString()).catch((e: Error) => console.error(e, 'Error broadcasting KV update', contractID, key)) - - return h.response().code(204) - }) -}) - -route.GET('/kv/{contractID}/{key}', { - auth: { - strategies: ['chel-shelter'], - mode: 'required' - }, - cache: { otherwise: 'no-store' }, - validate: { - params: Joi.object({ - contractID: Joi.string().regex(CID_REGEX).required(), - key: Joi.string().regex(KV_KEY_REGEX).required() }) - } -}, async function (request, h): Promise { - const { contractID, key } = request.params - const parsed = maybeParseCID(contractID) - if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { - return Boom.badRequest() - } + app.post('/kv/:contractID/:key', + zValidator('param', z.object({ contractID: cidSchema, key: kvKeySchema }).strict()), + authMiddleware('chel-shelter', 'required'), + bodyLimit({ maxSize: 6 * MEGABYTE }), + async function (c) { + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + const { contractID, key } = c.req.valid('param') + + const parsed = maybeParseCID(contractID) + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { + throw new HTTPException(400) + } - if (!ctEq(request.auth.credentials.billableContractID as string, contractID)) { - return Boom.unauthorized(null, 'shelter') - } + const credentials = c.get('credentials') as AuthCredentials + if (!ctEq(credentials.billableContractID as string, contractID)) { + throw new HTTPException(401) + } - const result = await sbp('chelonia.db/get', `_private_kv_${contractID}_${key}`) - if (!result) { - return notFoundNoCache(h) - } + const payloadBuffer = Buffer.from(await c.req.arrayBuffer()) - const cid = createCID(result, multicodes.RAW) - return h.response(result).etag(cid).header('x-cid', `"${cid}"`) -}) + // Use a queue to prevent race conditions (for example, writing to a contract + // that's being deleted or updated) + return sbp('chelonia/queueInvocation', contractID, async () => { + const existing = await sbp('chelonia.db/get', `_private_kv_${contractID}_${key}`) -route.GET('/serverMessages', { cache: { otherwise: 'no-store' } }, (_request, h) => { - const messages = nconf.get('server:messages') - if (!messages) return [] - return h.response(messages) -}) + // Some protection against accidental overwriting by implementing the if-match + // header + const expectedEtag = c.req.header('if-match') + if (!expectedEtag) { + throw new HTTPException(400, { message: 'if-match is required' }) + } + // "Quote" string (to match ETag format) + const cid = existing ? createCID(existing, multicodes.RAW) : '' -// SPA routes - -route.GET('/assets/{subpath*}', { - ext: { - onPostHandler: { - method (request, h) { - // since our JS is placed under /assets/ and since service workers - // have their scope limited by where they are, we must add this - // header to allow the service worker to function. Details: - // https://w3c.github.io/ServiceWorker/#service-worker-allowed - if (request.path.includes('assets/js/sw-')) { - // If `response` is an error, then no SW is being served - if (!(request.response instanceof Boom.Boom)) { - console.debug('adding header: Service-Worker-Allowed /') - request.response.header('Service-Worker-Allowed', '/') + if (expectedEtag === '*') { + // pass through + } else { + if (!expectedEtag.split(',').map((v: string) => v.trim()).includes(`"${cid}"`)) { + return new Response(existing || '', { + status: 412, + headers: { + 'ETag': `"${cid}"`, + 'x-cid': `"${cid}"` + } + }) } } - return h.continue - } - } - }, - files: { - relativeTo: staticServeConfig.distAssets - } -}, function (request, h) { - const { subpath } = request.params - const basename = path.basename(subpath) - // In the build config we told our bundler to use the `[name]-[hash]-cached` template - // to name immutable assets. This is useful because `dist/assets/` currently includes - // a few files without hash in their name. - if (basename.includes('-cached')) { - return h.file(subpath, { etagMethod: false }) - .etag(basename) - .header('Cache-Control', 'public,max-age=31536000,immutable') - } - // Files like `main.js` or `main.css` should be revalidated before use. Se we use the default headers. - // This should also be suitable for serving unversioned fonts and images. - return h.file(subpath) -}) -// Dashboard-specific assets route (when IS_CHELONIA_DASHBOARD_DEV is set) -if (isCheloniaDashboard) { - route.GET('/dashboard/assets/{subpath*}', { - ext: { - onPostHandler: { - method (request, h) { - // since our JS is placed under /assets/ and since service workers - // have their scope limited by where they are, we must add this - // header to allow the service worker to function. Details: - // https://w3c.github.io/ServiceWorker/#service-worker-allowed - if (request.path.includes('assets/js/sw-')) { - // If `response` is an error, then no SW is being served - if (!(request.response instanceof Boom.Boom)) { - console.debug('adding header: Service-Worker-Allowed /') - request.response.header('Service-Worker-Allowed', '/') - } + try { + const serializedData = JSON.parse(payloadBuffer.toString()) + const { contracts } = sbp('chelonia/rootState') + // Check that the height is the latest value + if (contracts[contractID].height !== Number(serializedData.height)) { + return new Response(existing || '', { + status: 409, + headers: { + 'ETag': `"${cid}"`, + 'x-cid': `"${cid}"` + } + }) } - return h.continue + // Check that the signature is valid + sbp('chelonia/parseEncryptedOrUnencryptedDetachedMessage', { + contractID, + serializedData, + meta: key + }) + } catch (parseErr) { + if (parseErr instanceof Response) throw parseErr + throw new HTTPException(422) } - } - }, - files: { - relativeTo: staticServeConfig.distAssets - } - }, function (request, h) { - const { subpath } = request.params - const basename = path.basename(subpath) - // In the build config we told our bundler to use the `[name]-[hash]-cached` template - // to name immutable assets. This is useful because `dist/assets/` currently includes - // a few files without hash in their name. - if (basename.includes('-cached')) { - return h.file(subpath, { etagMethod: false }) - .etag(basename) - .header('Cache-Control', 'public,max-age=31536000,immutable') - } - // Files like `main.js` or `main.css` should be revalidated before use. Se we use the default headers. - // This should also be suitable for serving unversioned fonts and images. - return h.file(subpath) - }) -} -route.GET(staticServeConfig.routePath, {}, { - file: staticServeConfig.distIndexHtml -}) + const existingSize = existing ? Buffer.from(existing).byteLength : 0 + await sbp('chelonia.db/set', `_private_kv_${contractID}_${key}`, payloadBuffer) + await sbp('backend/server/updateSize', contractID, payloadBuffer.byteLength - existingSize) + await appendToIndexFactory(`_private_kvIdx_${contractID}`)(key) + // No await on broadcast for faster responses + sbp('backend/server/broadcastKV', contractID, key, payloadBuffer.toString()).catch((e: Error) => console.error(e, 'Error broadcasting KV update', contractID, key)) -route.GET('/', {}, function (_req, h) { - return h.redirect(staticServeConfig.redirect) -}) + return c.body(null, 204) + }) + }) + + app.get('/kv/:contractID/:key', + authMiddleware('chel-shelter', 'required'), + zValidator('param', z.object({ contractID: cidSchema, key: kvKeySchema }).strict()), + async function (c) { + const { contractID, key } = c.req.valid('param') -route.POST('/zkpp/register/{name}', { - validate: { - params: Joi.object({ - name: Joi.string().regex(NAME_REGEX).required() - }), - payload: Joi.alternatives([ - { - // b is a hash of a random public key (`g^r`) with secret key `r`, - // which is used by the requester to commit to that particular `r` - b: Joi.string().required() - }, - { - // `r` is the value used to derive `b` (in this case, it's the public - // key `g^r`) - r: Joi.string().required(), - // `s` is an opaque (to the client) value that was earlier returned by - // the server - s: Joi.string().required(), - // `sig` is an opaque (to the client) value returned by the server - // to validate the request (ensuring that (`r`, `s`) come from a - // previous request - sig: Joi.string().required(), - // `Eh` is the Eh = E_{S_A + S_C}(h), where S_A and S_C are salts and - // h = H\_{S_A}(P) - Eh: Joi.string().required() + const parsed = maybeParseCID(contractID) + if (parsed?.code !== multicodes.SHELTER_CONTRACT_DATA) { + throw new HTTPException(400) } - ]) - } -}, async function (req) { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - const lookupResult = await sbp('backend/db/lookupName', req.params['name']) - if (lookupResult) { - // If the username is already registered, abort - return Boom.conflict() - } - try { - const { payload } = req as { payload: { b: string, r: string, s: string, sig: string, Eh: string } } - if (payload['b']) { - const result = registrationKey(req.params['name'], payload['b']) - if (result) { - return result + const credentials = c.get('credentials') as AuthCredentials + if (!ctEq(credentials.billableContractID as string, contractID)) { + throw new HTTPException(401) } - } else { - const result = register(req.params['name'], payload['r'], payload['s'], payload['sig'], payload['Eh']) - if (result) { - return result + const result = await sbp('chelonia.db/get', `_private_kv_${contractID}_${key}`) + if (!result) { + return notFoundNoCache(c) } - } - } catch (e) { - (e as { ip: string }).ip = req.headers['x-real-ip'] || req.info.remoteAddress - console.error(e, 'Error at POST /zkpp/{name}: ' + (e as Error).message) - } - return Boom.internal('internal error') -}) + const cid = createCID(result, multicodes.RAW) + return new Response(result, { + headers: { + 'ETag': `"${cid}"`, + 'x-cid': `"${cid}"`, + 'Cache-Control': 'no-store' + } + }) + }) -route.GET('/zkpp/{contractID}/auth_hash', { - validate: { - params: Joi.object({ - contractID: Joi.string().regex(CID_REGEX).required() - }), - query: Joi.object({ b: Joi.string().required() }) - } -}, async function (req, h) { - try { - const challenge = await getChallenge(req.params['contractID'], req.query['b']) + app.get('/serverMessages', function (c) { + const messages = nconf.get('server:messages') + if (!messages) return c.json([]) + return c.json(messages, 200, { 'Cache-Control': 'no-store' }) + }) - return challenge || notFoundNoCache(h) - } catch (e) { - (e as unknown as { ip: string }).ip = req.headers['x-real-ip'] || req.info.remoteAddress - console.error(e, 'Error at GET /zkpp/{contractID}/auth_hash: ' + (e as Error).message) - } + // SPA routes - return Boom.internal('internal error') -}) + app.get('/assets/:subpath{.+}', function (c) { + const subpath = c.req.param('subpath') + return serveAsset(c, subpath, staticServeConfig.distAssets) + }) -route.GET('/zkpp/{contractID}/contract_hash', { - validate: { - params: Joi.object({ - contractID: Joi.string().regex(CID_REGEX).required() - }), - query: Joi.object({ - r: Joi.string().required(), - s: Joi.string().required(), - sig: Joi.string().required(), - hc: Joi.string().required() + // Dashboard-specific assets route (when IS_CHELONIA_DASHBOARD_DEV is set) + if (isCheloniaDashboard) { + app.get('/dashboard/assets/:subpath{.+}', function (c) { + const subpath = c.req.param('subpath') + return serveAsset(c, subpath, staticServeConfig.distAssets) }) } -}, async function (req) { - try { - const salt = await getContractSalt(req.params['contractID'], req.query['r'], req.query['s'], req.query['sig'], req.query['hc']) - if (salt) { - return salt + // SPA catch-all route + app.get(isCheloniaDashboard ? '/dashboard/*' : '/app/*', async function (c) { + try { + const file = await Deno.readFile(staticServeConfig.distIndexHtml) + return c.body(file, 200, { 'Content-Type': 'text/html' }) + } catch { + return notFoundNoCache(c) } - } catch (e) { - (e as { ip: string }).ip = req.headers['x-real-ip'] || req.info.remoteAddress - console.error(e, 'Error at GET /zkpp/{contractID}/contract_hash: ' + (e as Error).message) - } + }) - return Boom.internal('internal error') -}) + app.get('/', function (c) { + return c.redirect(staticServeConfig.redirect) + }) -route.POST('/zkpp/{contractID}/updatePasswordHash', { - validate: { - params: Joi.object({ - contractID: Joi.string().regex(CID_REGEX).required() - }), - payload: Joi.object({ - r: Joi.string().required(), - s: Joi.string().required(), - sig: Joi.string().required(), - hc: Joi.string().required(), - Ea: Joi.string().required() - }) - } -}, async function (req) { - if (ARCHIVE_MODE) return Boom.notImplemented('Server in archive mode') - try { - const { payload } = req as { payload: { r: string, s: string, sig: string, hc: string, Ea: string } } - const result = await updateContractSalt(req.params['contractID'], payload['r'], payload['s'], payload['sig'], payload['hc'], payload['Ea']) + const zkppRegisterBodySchema = z.union([ + z.object({ b: z.string() }).strict(), + z.object({ r: z.string(), s: z.string(), sig: z.string(), Eh: z.string() }).strict() + ]) + app.post('/zkpp/register/:name', + zValidator('param', z.object({ name: nameSchema }).strict()), + zValidatorFormOrJson(zkppRegisterBodySchema), + async function (c) { + const { name } = c.req.valid('param') + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + + const payload = c.get('validatedBody') as z.infer + + const lookupResult = await sbp('backend/db/lookupName', name) + if (lookupResult) { + // If the username is already registered, abort + throw new HTTPException(409) + } + try { + if ('b' in payload) { + const result = registrationKey(name, payload.b) + + if (result) { + return c.json(result) + } + } else { + const result = register(name, payload.r, payload.s, payload.sig, payload.Eh) + + if (result) { + return c.text(result) + } + } + } catch (e) { + if (e instanceof HTTPException) throw e + ;(e as { ip: string }).ip = getClientIP(c) + console.error(e, 'Error at POST /zkpp/register/:name: ' + (e as Error).message) + } - if (result) { - return result + throw new HTTPException(500, { message: 'internal error' }) } - } catch (e) { - (e as unknown as { ip: string }).ip = req.headers['x-real-ip'] || req.info.remoteAddress - console.error(e, 'Error at POST /zkpp/{contractID}/updatePasswordHash: ' + (e as Error).message) - } + ) + + app.get('/zkpp/:contractID/auth_hash', + zValidator('param', z.object({ contractID: cidSchema }).strict()), + zValidator('query', z.object({ b: z.string().min(1, 'b is required') })), + async function (c) { + const { contractID } = c.req.valid('param') + const { b } = c.req.valid('query') + try { + const challenge = await getChallenge(contractID, b) - return Boom.internal('internal error') -}) + return challenge ? c.json(challenge) : notFoundNoCache(c) + } catch (e) { + ;(e as unknown as { ip: string }).ip = getClientIP(c) + console.error(e, 'Error at GET /zkpp/{contractID}/auth_hash: ' + (e as Error).message) + } + + throw new HTTPException(500, { message: 'internal error' }) + } + ) + + app.get('/zkpp/:contractID/contract_hash', + zValidator('param', z.object({ contractID: cidSchema }).strict()), + zValidator('query', z.object({ + r: z.string().min(1, 'r is required'), + s: z.string().min(1, 's is required'), + sig: z.string().min(1, 'sig is required'), + hc: z.string().min(1, 'hc is required') + }).strict()), + async function (c) { + const { contractID } = c.req.valid('param') + const { r, s, sig, hc } = c.req.valid('query') + try { + const salt = await getContractSalt(contractID, r, s, sig, hc) + + if (salt) { + return c.text(salt) + } + } catch (e) { + ;(e as { ip: string }).ip = getClientIP(c) + console.error(e, 'Error at GET /zkpp/{contractID}/contract_hash: ' + (e as Error).message) + } + + throw new HTTPException(500, { message: 'internal error' }) + } + ) + + const zkppUpdatePasswordBodySchema = z.object({ + r: z.string().min(1, 'r is required'), + s: z.string().min(1, 's is required'), + sig: z.string().min(1, 'sig is required'), + hc: z.string().min(1, 'hc is required'), + Ea: z.string().min(1, 'Ea is required') + }).strict() + app.post('/zkpp/:contractID/updatePasswordHash', + zValidator('param', z.object({ contractID: cidSchema }).strict()), + zValidatorFormOrJson(zkppUpdatePasswordBodySchema), + async function (c) { + const { contractID } = c.req.valid('param') + if (ARCHIVE_MODE) throw new HTTPException(501, { message: 'Server in archive mode' }) + try { + const payload = c.get('validatedBody') as z.infer + const result = await updateContractSalt(contractID, payload.r, payload.s, payload.sig, payload.hc, payload.Ea) + + if (result) { + return c.json(result) + } + } catch (e) { + if (e instanceof HTTPException) throw e + ;(e as unknown as { ip: string }).ip = getClientIP(c) + console.error(e, 'Error at POST /zkpp/{contractID}/updatePasswordHash: ' + (e as Error).message) + } + + throw new HTTPException(500, { message: 'internal error' }) + } + ) +} diff --git a/src/serve/server.ts b/src/serve/server.ts index 2424de1..b5bf6bf 100644 --- a/src/serve/server.ts +++ b/src/serve/server.ts @@ -5,19 +5,19 @@ import 'npm:@chelonia/lib/chelonia' import { multicodes, parseCID } from 'npm:@chelonia/lib/functions' import 'npm:@chelonia/lib/persistent-actions' import { SERVER } from 'npm:@chelonia/lib/presets' -import Boom from 'npm:@hapi/boom' -import * as Hapi from 'npm:@hapi/hapi' -import Inert from 'npm:@hapi/inert' import sbp from 'npm:@sbp/sbp' import chalk from 'npm:chalk' +import { Hono } from 'npm:hono' +import { cors } from 'npm:hono/cors' +import { createAdaptorServer } from 'npm:@hono/node-server' +import type { Server } from 'node:http' import type { ImportMeta } from '../types/build.d.ts' import createWorker from './createWorker.ts' -// import type { SubMessage, UnsubMessage } from './pubsub.ts' // TODO: Use for type checking import { join } from 'node:path' import process from 'node:process' -import authPlugin from './auth.ts' +import { getClientIP, registerRoutes } from './routes.ts' import { CREDITS_WORKER_TASK_TIME_INTERVAL, OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL } from './constants.ts' -import { KEYOP_SEGMENT_LENGTH, appendToIndexFactory, initDB, lookupUltimateOwner, removeFromIndexFactory, updateSize } from './database.ts' +import { KEYOP_SEGMENT_LENGTH, appendToIndexFactory, closeDB, initDB, lookupUltimateOwner, removeFromIndexFactory, updateSize } from './database.ts' import { BackendErrorBadData, BackendErrorGone, BackendErrorNotFound } from './errors.ts' import { SERVER_RUNNING } from './events.ts' import { PUBSUB_INSTANCE, SERVER_INSTANCE } from './instance-keys.ts' @@ -36,510 +36,519 @@ import { pathToFileURL } from 'node:url' // @deno-types="npm:@types/nconf" import nconf from 'npm:nconf' -const cheloniaAppManifest = await (async () => { - try { - const appDir = nconf.get('server:appDir') || process.cwd() - return (await import(pathToFileURL(join(appDir, 'chelonia.json')).toString(), { - with: { type: 'json' } - })).default - } catch { - console.warn('`chelonia.json` unparsable or not found. Version information will be unavailable.') - } -})() - -const ARCHIVE_MODE = nconf.get('server:archiveMode') -let pushHeartbeatIntervalID: ReturnType - -if (CREDITS_WORKER_TASK_TIME_INTERVAL && OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL > CREDITS_WORKER_TASK_TIME_INTERVAL) { - process.stderr.write('The size calculation worker must run more frequently than the credits worker for accurate billing') - process.exit(1) -} - -// Initialize workers for size calculation and credits processing -const ownerSizeTotalWorker = ARCHIVE_MODE || !OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL - ? undefined - : createWorker((import.meta as ImportMeta).ownerSizeTotalWorker || './ownerSizeTotalWorker.ts') -const creditsWorker = ARCHIVE_MODE || !CREDITS_WORKER_TASK_TIME_INTERVAL - ? undefined - : createWorker((import.meta as ImportMeta).creditsWorker || './creditsWorker.ts') - -// Dynamic runtime import to bypass bundling issues with npm: specifier -const hapi = new Hapi.Server({ - // debug: false, // <- Hapi v16 was outputing too many unnecessary debug statements - // // v17 doesn't seem to do this anymore so I've re-enabled the logging - // debug: { log: ['error'], request: ['error'] }, - host: nconf.get('server:host'), - port: nconf.get('server:port'), - // See: https://github.com/hapijs/discuss/issues/262#issuecomment-204616831 - routes: { - cors: { - // TODO: figure out if we can live with '*' or if we need to restrict it - origin: ['*'] - // origin: [ - // process.env.API_URL, - // // improve support for browsersync proxy - // ...(process.env.NODE_ENV === 'development' && ['http://localhost:3000']) - // ] - } - } -}) - -// See https://stackoverflow.com/questions/26213255/hapi-set-header-before-sending-response -hapi.ext({ - type: 'onPreResponse', - method: function (request, h) { - try { - // Hapi Boom error responses don't have `.header()`, - // but custom headers can be manually added using `.output.headers`. - // See https://hapi.dev/module/boom/api/. - if (!(request.response instanceof Boom.Boom)) { - request.response.header('X-Frame-Options', 'DENY') - } else { - request.response.output.headers['X-Frame-Options'] = 'DENY' - } - } catch (err) { - console.warn(chalk.yellow('[backend] Could not set X-Frame-Options header:', (err as Error).message)) - } - return h.continue - } -}) - +// ============================================================================ +// Module-scope state for the current server run +// ============================================================================ +let currentApp: Hono | null = null +let currentHttpServer: Server | null = null +let currentOwnerSizeTotalWorker: ReturnType | undefined = undefined +let currentCreditsWorker: ReturnType | undefined = undefined +let currentManifest: Record | undefined = undefined +let currentPushHeartbeatIntervalID: ReturnType | undefined = undefined +let isStopping = false + +// Helper for appending to orphaned names index (stateless) const appendToOrphanedNamesIndex = appendToIndexFactory('_private_orphaned_names_index') -sbp('okTurtles.data/set', SERVER_INSTANCE, hapi) - -sbp('sbp/selectors/register', { - 'backend/server/persistState': async function (deserializedHEAD: unknown) { - const contractID = (deserializedHEAD as Record).contractID - const cheloniaState = sbp('chelonia/rootState') - // If the contract has been removed or the height hasn't been updated, - // there's nothing to persist. - // If `!cheloniaState.contracts[contractID]`, the contract's been removed - // and therefore we shouldn't save it. - // If `cheloniaState.contracts[contractID].height < deserializedHEAD.head.height`, - // it means that the message wasn't processed (we'd expect the height to - // be `>=` than the message's height if so), and therefore we also shouldn't - // save it. - if (!cheloniaState.contracts[contractID as string] || cheloniaState.contracts[contractID as string].height < (((deserializedHEAD as Record).head as Record).height as number)) { - return - } - // If the current HEAD is not what we expect, don't save (the state could - // have been updated by a later message). This ensures that we save the - // latest state and also reduces the number of write operations - if (cheloniaState.contracts[contractID as string].HEAD === (deserializedHEAD as Record).hash) { - // Extract the parts of the state relevant to this contract - const state = { - contractState: (cheloniaState as Record)[contractID as string], - cheloniaContractInfo: cheloniaState.contracts[contractID as string] +// ============================================================================ +// SBP selector registration (once per process) +// ============================================================================ +let serverSelectorsInstalled = false + +function installServerSelectorsOnce (): void { + if (serverSelectorsInstalled) return + serverSelectorsInstalled = true + + sbp('sbp/selectors/register', { + 'backend/server/persistState': async function (deserializedHEAD: unknown) { + const contractID = (deserializedHEAD as Record).contractID + const cheloniaState = sbp('chelonia/rootState') + // If the contract has been removed or the height hasn't been updated, + // there's nothing to persist. + // If `!cheloniaState.contracts[contractID]`, the contract's been removed + // and therefore we shouldn't save it. + // If `cheloniaState.contracts[contractID].height < deserializedHEAD.head.height`, + // it means that the message wasn't processed (we'd expect the height to + // be `>=` than the message's height if so), and therefore we also shouldn't + // save it. + if (!cheloniaState.contracts[contractID as string] || cheloniaState.contracts[contractID as string].height < (((deserializedHEAD as Record).head as Record).height as number)) { + return } - // Save the state under a 'contract partition' key, so that updating a - // contract doesn't require saving the entire state. - // Although it's not important for the server right now, this will fail to - // persist changes to the state for other contracts. - // For example, when watching foreign keys, this happens: whenever a - // foreign key for contract A is added to contract B, the private state - // for both contract A and B is updated (when both contracts are being - // monitored by Chelonia). However, here in this case, the updated state - // for contract A will not be saved immediately here, and it will only be - // saved if some other event happens later on contract A. - // TODO: If, in the future, processing a message affects other contracts - // in a way that is meaningful to the server, there'll need to be a way - // to detect these changes as well. One example could be, expanding on the - // previous scenario, if we decide that the server should enforce key - // rotations, so that updating a foreign key 'locks' that contract until - // the foreign key is rotated or deleted. For this to work reliably, we'd - // need to ensure that the state for both contract B and contract A are - // saved when the foreign key gets added to contract B. - await sbp('chelonia.db/set', '_private_cheloniaState_' + contractID, JSON.stringify(state)) - } - // If this is a new contract, we also need to add it to the index, which - // is used when starting up the server to know which keys to fetch. - // In the future, consider having a multi-level index, since the index can - // get pretty large. - if (contractID === (deserializedHEAD as Record).hash) { - // We want to ensure that the index is updated atomically (i.e., if there - // are multiple new contracts, all of them should be added), so a queue - // is needed for the load & store operation. - await sbp('backend/server/appendToContractIndex', contractID) - } - // If this was a key op, add it to a keyop index. To prevent the index from - // growing too large, the index is segmented for every KEYOP_SEGMENT_LENGTH - // height values - if (cheloniaState.contracts[contractID as string].previousKeyOp === (deserializedHEAD as Record).hash) { - await appendToIndexFactory(`_private_keyop_idx_${contractID}_${(((deserializedHEAD as Record).head as Record).height as number) - (((deserializedHEAD as Record).head as Record).height as number) % KEYOP_SEGMENT_LENGTH}`)(String(((deserializedHEAD as Record).head as Record).height)) - } - }, - 'backend/server/appendToContractIndex': appendToIndexFactory('_private_cheloniaState_index'), - 'backend/server/broadcastKV': async function (contractID: string, key: string, entry: string) { - const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as WSS - const pubsubMessage = createKvMessage(contractID, key, entry) - const subscribers = pubsub.enumerateSubscribers(contractID, key) - console.debug(chalk.blue.bold(`[pubsub] Broadcasting KV change on ${contractID} to key ${key}`)) - await pubsub.broadcast(pubsubMessage, { to: subscribers, wsOnly: true }) - }, - 'backend/server/broadcastEntry': async function (deserializedHEAD: ReturnType, entry: string) { - const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as WSS - const contractID = deserializedHEAD.contractID - const contractType = sbp('chelonia/rootState').contracts[contractID as string]?.type - const pubsubMessage = createMessage(NOTIFICATION_TYPE.ENTRY, entry, { contractID, contractType }) - const subscribers = pubsub.enumerateSubscribers(contractID) - console.debug(chalk.blue.bold(`[pubsub] Broadcasting ${deserializedHEAD.description()}`)) - await pubsub.broadcast(pubsubMessage, { to: subscribers }) - }, - 'backend/server/broadcastDeletion': async function (contractID: string) { - const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as WSS - const pubsubMessage = createMessage(NOTIFICATION_TYPE.DELETION, contractID) - const subscribers = pubsub.enumerateSubscribers(contractID) - console.debug(chalk.blue.bold(`[pubsub] Broadcasting deletion of ${contractID}`)) - await pubsub.broadcast(pubsubMessage, { to: subscribers }) - }, - 'backend/server/handleEntry': async function (deserializedHEAD: ReturnType, entry: string) { - const contractID = deserializedHEAD.contractID - if (deserializedHEAD.head.op === SPMessage.OP_CONTRACT) { - sbp('okTurtles.data/get', PUBSUB_INSTANCE).channels.add(contractID) - } - await sbp('chelonia/private/in/enqueueHandleEvent', contractID, entry) - // Persist the Chelonia state after processing a message - await sbp('backend/server/persistState', deserializedHEAD, entry) - // No await on broadcast for faster responses - sbp('backend/server/broadcastEntry', deserializedHEAD, entry).catch((e: unknown) => console.error(e, 'Error broadcasting entry', contractID, deserializedHEAD.hash)) - }, - 'backend/server/saveOwner': async function (ownerID: string, resourceID: string) { - // Store the owner for the current resource - // Use a queue to check that the owner exists, preventing the creation of - // orphaned resources (e.g., because the owner was just deleted) - await sbp('chelonia/queueInvocation', ownerID, async () => { - const owner = await sbp('chelonia.db/get', ownerID) - if (!owner) { - throw new Error('Owner resource does not exist') + // If the current HEAD is not what we expect, don't save (the state could + // have been updated by a later message). This ensures that we save the + // latest state and also reduces the number of write operations + if (cheloniaState.contracts[contractID as string].HEAD === (deserializedHEAD as Record).hash) { + // Extract the parts of the state relevant to this contract + const state = { + contractState: (cheloniaState as Record)[contractID as string], + cheloniaContractInfo: cheloniaState.contracts[contractID as string] + } + // Save the state under a 'contract partition' key, so that updating a + // contract doesn't require saving the entire state. + // Although it's not important for the server right now, this will fail to + // persist changes to the state for other contracts. + // For example, when watching foreign keys, this happens: whenever a + // foreign key for contract A is added to contract B, the private state + // for both contract A and B is updated (when both contracts are being + // monitored by Chelonia). However, here in this case, the updated state + // for contract A will not be saved immediately here, and it will only be + // saved if some other event happens later on contract A. + // TODO: If, in the future, processing a message affects other contracts + // in a way that is meaningful to the server, there'll need to be a way + // to detect these changes as well. One example could be, expanding on the + // previous scenario, if we decide that the server should enforce key + // rotations, so that updating a foreign key 'locks' that contract until + // the foreign key is rotated or deleted. For this to work reliably, we'd + // need to ensure that the state for both contract B and contract A are + // saved when the foreign key gets added to contract B. + await sbp('chelonia.db/set', '_private_cheloniaState_' + contractID, JSON.stringify(state)) } - await sbp('chelonia.db/set', `_private_owner_${resourceID}`, ownerID) - const resourcesKey = `_private_resources_${ownerID}` - // Store the resource in the resource index key - // This is done in a queue to handle several simultaneous requests - // reading and writing to the same key - await appendToIndexFactory(resourcesKey)(resourceID) - // Done as a persistent action to return quickly. If one of the owners - // up the chain has many resources, the operation could take a while. - sbp('chelonia.persistentActions/enqueue', ['backend/server/addToIndirectResourcesIndex', resourceID]) - }) - }, - 'backend/server/addToIndirectResourcesIndex': async function (resourceID: string) { - const ownerID = await sbp('chelonia.db/get', `_private_owner_${resourceID}`) - let indirectOwnerID = ownerID - // If the owner of the owner doesn't exist, there are no indirect resources. - while ((indirectOwnerID = await sbp('chelonia.db/get', `_private_owner_${indirectOwnerID}`))) { - await appendToIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(resourceID) - } - }, - 'backend/server/removeFromIndirectResourcesIndex': async function (resourceID: string) { - const ownerID = await sbp('chelonia.db/get', `_private_owner_${resourceID}`) - const resources = await sbp('chelonia.db/get', `_private_resources_${resourceID}`) - const indirectResources = resources ? await sbp('chelonia.db/get', `_private_indirectResources_${resourceID}`) : undefined - const allSubresources = [ - resourceID, - ...(resources ? resources.split('\x00') : []), - ...(indirectResources ? indirectResources.split('\x00') : []) - ] - let indirectOwnerID = ownerID - while ((indirectOwnerID = await sbp('chelonia.db/get', `_private_owner_${indirectOwnerID}`))) { - await removeFromIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(allSubresources) - } - }, - 'backend/server/registerBillableEntity': appendToIndexFactory('_private_billable_entities'), - 'backend/server/updateSize': function (resourceID: string, size: number, ultimateOwnerID: string | null | undefined) { - const sizeKey = `_private_size_${resourceID}` - return updateSize(resourceID, sizeKey, size).then(() => { - // Because this is relevant key for size accounting, call updateSizeSideEffects - return ownerSizeTotalWorker?.rpcSbp('worker/updateSizeSideEffects', { resourceID, size, ultimateOwnerID }) - }) - }, - 'backend/server/updateContractFilesTotalSize': function (resourceID: string, size: number) { - const sizeKey = `_private_contractFilesTotalSize_${resourceID}` - return updateSize(resourceID, sizeKey, size, true) - }, - 'backend/server/stop': async function () { - clearInterval(pushHeartbeatIntervalID) - if (sbp('sbp/selectors/fn', 'backend/server/stopRateLimiters')) { - await sbp('backend/server/stopRateLimiters') - } - await hapi.stop() - await Promise.all([ - ownerSizeTotalWorker?.terminate(), - creditsWorker?.terminate() - ]) - }, - async 'backend/deleteFile' (cid: string, ultimateOwnerID: string | null | undefined, skipIfDeleted: boolean | null | undefined): Promise { - const owner = await sbp('chelonia.db/get', `_private_owner_${cid}`) - const rawManifest = await sbp('chelonia.db/get', cid) - const size = await sbp('chelonia.db/get', `_private_size_${cid}`) - if (owner && !ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(owner) - // If running in a persistent queue, already deleted contract should not - // result in an error, because exceptions will result in the task being - // re-attempted - if (rawManifest === '') { if (skipIfDeleted) return; throw new BackendErrorGone() } - if (!rawManifest) { if (skipIfDeleted) return; throw new BackendErrorNotFound() } - - try { - const manifest = JSON.parse(rawManifest) - if (!manifest || typeof manifest !== 'object') throw new BackendErrorBadData('manifest format is invalid') - if (manifest.version !== '1.0.0') throw new BackendErrorBadData('unsupported manifest version') - if (!Array.isArray(manifest.chunks) || !manifest.chunks.length) throw new BackendErrorBadData('missing chunks') - // Delete all chunks - await Promise.all(manifest.chunks.map(([, cid]: [unknown, string]) => sbp('chelonia.db/delete', cid))) - } catch (e: unknown) { - console.warn(e, `Error parsing manifest for ${cid}. It's probably not a file manifest.`) - throw new BackendErrorNotFound() - } - // The keys to be deleted are not read from or updated, so they can be deleted - // without using a queue - const resourcesKey = `_private_resources_${owner}` - await removeFromIndexFactory(resourcesKey)(cid) - await sbp('backend/server/removeFromIndirectResourcesIndex', cid) - - await sbp('chelonia.db/delete', `_private_owner_${cid}`) - await sbp('chelonia.db/delete', `_private_size_${cid}`) - await sbp('chelonia.db/delete', `_private_deletionTokenDgst_${cid}`) - - await sbp('chelonia.db/set', cid, '') - await sbp('backend/server/updateContractFilesTotalSize', owner, -Number(size)) - - if (ultimateOwnerID && size) { - await ownerSizeTotalWorker?.rpcSbp('worker/updateSizeSideEffects', { resourceID: cid, size: -parseInt(size), ultimateOwnerID }) - } - }, - async 'backend/deleteContract' (cid: string, ultimateOwnerID?: string | null, skipIfDeleted?: boolean | null): Promise { - let contractsPendingDeletion = sbp('okTurtles.data/get', 'contractsPendingDeletion') - if (!contractsPendingDeletion) { - contractsPendingDeletion = new Set() - sbp('okTurtles.data/set', 'contractsPendingDeletion', contractsPendingDeletion) - } - // Avoid deadlocks due to loops - if (contractsPendingDeletion.has(cid)) { - return - } - contractsPendingDeletion.add(cid) - - return await sbp('chelonia/queueInvocation', cid, async () => { + // If this is a new contract, we also need to add it to the index, which + // is used when starting up the server to know which keys to fetch. + // In the future, consider having a multi-level index, since the index can + // get pretty large. + if (contractID === (deserializedHEAD as Record).hash) { + // We want to ensure that the index is updated atomically (i.e., if there + // are multiple new contracts, all of them should be added), so a queue + // is needed for the load & store operation. + await sbp('backend/server/appendToContractIndex', contractID) + } + // If this was a key op, add it to a keyop index. To prevent the index from + // growing too large, the index is segmented for every KEYOP_SEGMENT_LENGTH + // height values + if (cheloniaState.contracts[contractID as string].previousKeyOp === (deserializedHEAD as Record).hash) { + await appendToIndexFactory(`_private_keyop_idx_${contractID}_${(((deserializedHEAD as Record).head as Record).height as number) - (((deserializedHEAD as Record).head as Record).height as number) % KEYOP_SEGMENT_LENGTH}`)(String(((deserializedHEAD as Record).head as Record).height)) + } + }, + 'backend/server/appendToContractIndex': appendToIndexFactory('_private_cheloniaState_index'), + 'backend/server/broadcastKV': async function (contractID: string, key: string, entry: string) { + const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as WSS + const pubsubMessage = createKvMessage(contractID, key, entry) + const subscribers = pubsub.enumerateSubscribers(contractID, key) + console.debug(chalk.blue.bold(`[pubsub] Broadcasting KV change on ${contractID} to key ${key}`)) + await pubsub.broadcast(pubsubMessage, { to: subscribers, wsOnly: true }) + }, + 'backend/server/broadcastEntry': async function (deserializedHEAD: ReturnType, entry: string) { + const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as WSS + const contractID = deserializedHEAD.contractID + const contractType = sbp('chelonia/rootState').contracts[contractID as string]?.type + const pubsubMessage = createMessage(NOTIFICATION_TYPE.ENTRY, entry, { contractID, contractType }) + const subscribers = pubsub.enumerateSubscribers(contractID) + console.debug(chalk.blue.bold(`[pubsub] Broadcasting ${deserializedHEAD.description()}`)) + await pubsub.broadcast(pubsubMessage, { to: subscribers }) + }, + 'backend/server/broadcastDeletion': async function (contractID: string) { + const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as WSS + const pubsubMessage = createMessage(NOTIFICATION_TYPE.DELETION, contractID) + const subscribers = pubsub.enumerateSubscribers(contractID) + console.debug(chalk.blue.bold(`[pubsub] Broadcasting deletion of ${contractID}`)) + await pubsub.broadcast(pubsubMessage, { to: subscribers }) + }, + 'backend/server/handleEntry': async function (deserializedHEAD: ReturnType, entry: string) { + const contractID = deserializedHEAD.contractID + if (deserializedHEAD.head.op === SPMessage.OP_CONTRACT) { + sbp('okTurtles.data/get', PUBSUB_INSTANCE).channels.add(contractID) + } + await sbp('chelonia/private/in/enqueueHandleEvent', contractID, entry) + // Persist the Chelonia state after processing a message + await sbp('backend/server/persistState', deserializedHEAD, entry) + // No await on broadcast for faster responses + sbp('backend/server/broadcastEntry', deserializedHEAD, entry).catch((e: unknown) => console.error(e, 'Error broadcasting entry', contractID, deserializedHEAD.hash)) + }, + 'backend/server/saveOwner': async function (ownerID: string, resourceID: string) { + // Store the owner for the current resource + // Use a queue to check that the owner exists, preventing the creation of + // orphaned resources (e.g., because the owner was just deleted) + await sbp('chelonia/queueInvocation', ownerID, async () => { + const owner = await sbp('chelonia.db/get', ownerID) + if (!owner) { + throw new Error('Owner resource does not exist') + } + await sbp('chelonia.db/set', `_private_owner_${resourceID}`, ownerID) + const resourcesKey = `_private_resources_${ownerID}` + // Store the resource in the resource index key + // This is done in a queue to handle several simultaneous requests + // reading and writing to the same key + await appendToIndexFactory(resourcesKey)(resourceID) + // Done as a persistent action to return quickly. If one of the owners + // up the chain has many resources, the operation could take a while. + sbp('chelonia.persistentActions/enqueue', ['backend/server/addToIndirectResourcesIndex', resourceID]) + }) + }, + 'backend/server/addToIndirectResourcesIndex': async function (resourceID: string) { + const ownerID = await sbp('chelonia.db/get', `_private_owner_${resourceID}`) + let indirectOwnerID = ownerID + // If the owner of the owner doesn't exist, there are no indirect resources. + while ((indirectOwnerID = await sbp('chelonia.db/get', `_private_owner_${indirectOwnerID}`))) { + await appendToIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(resourceID) + } + }, + 'backend/server/removeFromIndirectResourcesIndex': async function (resourceID: string) { + const ownerID = await sbp('chelonia.db/get', `_private_owner_${resourceID}`) + const resources = await sbp('chelonia.db/get', `_private_resources_${resourceID}`) + const indirectResources = resources ? await sbp('chelonia.db/get', `_private_indirectResources_${resourceID}`) : undefined + const allSubresources = [ + resourceID, + ...(resources ? resources.split('\x00') : []), + ...(indirectResources ? indirectResources.split('\x00') : []) + ] + let indirectOwnerID = ownerID + while ((indirectOwnerID = await sbp('chelonia.db/get', `_private_owner_${indirectOwnerID}`))) { + await removeFromIndexFactory(`_private_indirectResources_${indirectOwnerID}`)(allSubresources) + } + }, + 'backend/server/registerBillableEntity': appendToIndexFactory('_private_billable_entities'), + 'backend/server/updateSize': function (resourceID: string, size: number, ultimateOwnerID: string | null | undefined) { + const sizeKey = `_private_size_${resourceID}` + return updateSize(resourceID, sizeKey, size).then(() => { + // Because this is relevant key for size accounting, call updateSizeSideEffects + return currentOwnerSizeTotalWorker?.rpcSbp('worker/updateSizeSideEffects', { resourceID, size, ultimateOwnerID }) + }) + }, + 'backend/server/updateContractFilesTotalSize': function (resourceID: string, size: number) { + const sizeKey = `_private_contractFilesTotalSize_${resourceID}` + return updateSize(resourceID, sizeKey, size, true) + }, + 'backend/server/stop': async function () { + await stopServer() + }, + async 'backend/deleteFile' (cid: string, ultimateOwnerID: string | null | undefined, skipIfDeleted: boolean | null | undefined): Promise { const owner = await sbp('chelonia.db/get', `_private_owner_${cid}`) - if (!ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(cid) const rawManifest = await sbp('chelonia.db/get', cid) const size = await sbp('chelonia.db/get', `_private_size_${cid}`) + if (owner && !ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(owner) // If running in a persistent queue, already deleted contract should not // result in an error, because exceptions will result in the task being // re-attempted if (rawManifest === '') { if (skipIfDeleted) return; throw new BackendErrorGone() } if (!rawManifest) { if (skipIfDeleted) return; throw new BackendErrorNotFound() } - // Cascade delete all resources owned by this contract, such as files - // (attachments) and other contracts. Removing a single contract could - // therefore result in a large number of contracts being deleted. For - // example, in Group Income, deleting an identity contract will delete: - // - All groups created by that contract - // - This includes files like the group avatar - // - And also all chatrooms - // - And all attachments in chatrooms - // - All DMs created by that contract - // - And all attachments - const resourcesKey = `_private_resources_${cid}` - const resources = await sbp('chelonia.db/get', resourcesKey) - if (resources) { - await Promise.allSettled(resources.split('\x00').map((resourceCid: string) => { - const parsed = parseCID(resourceCid) - - if (parsed.code === multicodes.SHELTER_CONTRACT_DATA) { - return sbp('chelonia.persistentActions/enqueue', ['backend/deleteContract', resourceCid, ultimateOwnerID, true]) - } else if (parsed.code === multicodes.SHELTER_FILE_MANIFEST) { - return sbp('chelonia.persistentActions/enqueue', ['backend/deleteFile', resourceCid, ultimateOwnerID, true]) - } else { - console.warn({ cid, resourceCid, code: parsed.code }, 'Resource should be deleted but it is of an unknown type') - } - - return undefined - })) - } - await sbp('chelonia.db/delete', resourcesKey) - - // Next, loop through all the events, except the very first one, - // in the contract and delete them, starting with the most recent ones. - // If the deletion process is interrupted, parts of the contract will - // still be able to be synced, but won't be to write to it (due to - // latestHEADinfo not being deleted). - const latestHEADinfo = await sbp('chelonia/db/latestHEADinfo', cid) - if (latestHEADinfo) { - for (let i = latestHEADinfo.height; i > 0; i--) { - const eventKey = `_private_hidx=${cid}#${i}` - const event = await sbp('chelonia.db/get', eventKey) - if (event) { - await sbp('chelonia.db/delete', JSON.parse(event).hash) - await sbp('chelonia.db/delete', eventKey) - } - if (i % KEYOP_SEGMENT_LENGTH === 0) { - await sbp('chelonia.db/delete', `_private_keyop_idx_${cid}_${i}`) - } - } - await sbp('chelonia/db/deleteLatestHEADinfo', cid) - } - - // Then, delete all KV-store values associated with this contract - const kvIndexKey = `_private_kvIdx_${cid}` - const kvKeys = await sbp('chelonia.db/get', kvIndexKey) - if (kvKeys) { - await Promise.all(kvKeys.split('\x00').map((key: string) => { - return sbp('chelonia.db/delete', `_private_kv_${cid}_${key}`) - })) + try { + const manifest = JSON.parse(rawManifest) + if (!manifest || typeof manifest !== 'object') throw new BackendErrorBadData('manifest format is invalid') + if (manifest.version !== '1.0.0') throw new BackendErrorBadData('unsupported manifest version') + if (!Array.isArray(manifest.chunks) || !manifest.chunks.length) throw new BackendErrorBadData('missing chunks') + // Delete all chunks + await Promise.all(manifest.chunks.map(([, cid]: [unknown, string]) => sbp('chelonia.db/delete', cid))) + } catch (e: unknown) { + console.warn(e, `Error parsing manifest for ${cid}. It's probably not a file manifest.`) + throw new BackendErrorNotFound() } - await sbp('chelonia.db/delete', kvIndexKey) + // The keys to be deleted are not read from or updated, so they can be deleted + // without using a queue + const resourcesKey = `_private_resources_${owner}` + await removeFromIndexFactory(resourcesKey)(cid) await sbp('backend/server/removeFromIndirectResourcesIndex', cid) - await sbp('chelonia.db/delete', `_private_indirectResources_${cid}`) - - await sbp('chelonia.db/get', `_private_cid2name_${cid}`).then((name: unknown) => { - if (!name) return - return Promise.all([ - sbp('chelonia.db/delete', `_private_cid2name_${cid}`), - appendToOrphanedNamesIndex(name as string) - ]) - }) - await sbp('chelonia.db/delete', `_private_rid_${cid}`) + await sbp('chelonia.db/delete', `_private_owner_${cid}`) await sbp('chelonia.db/delete', `_private_size_${cid}`) - await sbp('chelonia.db/delete', `_private_contractFilesTotalSize_${cid}`) await sbp('chelonia.db/delete', `_private_deletionTokenDgst_${cid}`) - await removeFromIndexFactory(`_private_resources_${owner}`)(cid) - // Delete the first event and its associated keys. These were not deleted - // in the loop above that deletes events one by one. - await sbp('chelonia.db/delete', `_private_hidx=${cid}#0`) - await sbp('chelonia.db/delete', `_private_keyop_idx_${cid}_0`) await sbp('chelonia.db/set', cid, '') - sbp('chelonia/private/removeImmediately', cid) + await sbp('backend/server/updateContractFilesTotalSize', owner, -Number(size)) - if (size) { - await ownerSizeTotalWorker?.rpcSbp('worker/updateSizeSideEffects', { resourceID: cid, size: -parseInt(size), ultimateOwnerID }) + if (ultimateOwnerID && size) { + await currentOwnerSizeTotalWorker?.rpcSbp('worker/updateSizeSideEffects', { resourceID: cid, size: -parseInt(size), ultimateOwnerID }) + } + }, + async 'backend/deleteContract' (cid: string, ultimateOwnerID?: string | null, skipIfDeleted?: boolean | null): Promise { + let contractsPendingDeletion = sbp('okTurtles.data/get', 'contractsPendingDeletion') + if (!contractsPendingDeletion) { + contractsPendingDeletion = new Set() + sbp('okTurtles.data/set', 'contractsPendingDeletion', contractsPendingDeletion) + } + // Avoid deadlocks due to loops + if (contractsPendingDeletion.has(cid)) { + return } + contractsPendingDeletion.add(cid) + + return await sbp('chelonia/queueInvocation', cid, async () => { + const owner = await sbp('chelonia.db/get', `_private_owner_${cid}`) + if (!ultimateOwnerID) ultimateOwnerID = await lookupUltimateOwner(cid) + const rawManifest = await sbp('chelonia.db/get', cid) + const size = await sbp('chelonia.db/get', `_private_size_${cid}`) + // If running in a persistent queue, already deleted contract should not + // result in an error, because exceptions will result in the task being + // re-attempted + if (rawManifest === '') { if (skipIfDeleted) return; throw new BackendErrorGone() } + if (!rawManifest) { if (skipIfDeleted) return; throw new BackendErrorNotFound() } + + // Cascade delete all resources owned by this contract, such as files + // (attachments) and other contracts. Removing a single contract could + // therefore result in a large number of contracts being deleted. For + // example, in Group Income, deleting an identity contract will delete: + // - All groups created by that contract + // - This includes files like the group avatar + // - And also all chatrooms + // - And all attachments in chatrooms + // - All DMs created by that contract + // - And all attachments + const resourcesKey = `_private_resources_${cid}` + const resources = await sbp('chelonia.db/get', resourcesKey) + if (resources) { + await Promise.allSettled(resources.split('\x00').map((resourceCid: string) => { + const parsed = parseCID(resourceCid) + + if (parsed.code === multicodes.SHELTER_CONTRACT_DATA) { + return sbp('chelonia.persistentActions/enqueue', ['backend/deleteContract', resourceCid, ultimateOwnerID, true]) + } else if (parsed.code === multicodes.SHELTER_FILE_MANIFEST) { + return sbp('chelonia.persistentActions/enqueue', ['backend/deleteFile', resourceCid, ultimateOwnerID, true]) + } else { + console.warn({ cid, resourceCid, code: parsed.code }, 'Resource should be deleted but it is of an unknown type') + } + + return undefined + })) + } + await sbp('chelonia.db/delete', resourcesKey) + + // Next, loop through all the events, except the very first one, + // in the contract and delete them, starting with the most recent ones. + // If the deletion process is interrupted, parts of the contract will + // still be able to be synced, but won't be to write to it (due to + // latestHEADinfo not being deleted). + const latestHEADinfo = await sbp('chelonia/db/latestHEADinfo', cid) + if (latestHEADinfo) { + for (let i = latestHEADinfo.height; i > 0; i--) { + const eventKey = `_private_hidx=${cid}#${i}` + const event = await sbp('chelonia.db/get', eventKey) + if (event) { + await sbp('chelonia.db/delete', JSON.parse(event).hash) + await sbp('chelonia.db/delete', eventKey) + } + if (i % KEYOP_SEGMENT_LENGTH === 0) { + await sbp('chelonia.db/delete', `_private_keyop_idx_${cid}_${i}`) + } + } + await sbp('chelonia/db/deleteLatestHEADinfo', cid) + } - await sbp('chelonia.db/delete', `_private_cheloniaState_${cid}`) - await removeFromIndexFactory('_private_cheloniaState_index')(cid) - // Note: `creditsWorker.js` could be updated to do this instead - await removeFromIndexFactory('_private_billable_entities')(cid) - sbp('backend/server/broadcastDeletion', cid).catch((e: unknown) => { - console.error(e, 'Error broadcasting contract deletion', cid) - }) - }).finally(() => { - contractsPendingDeletion.delete(cid) - }).catch((e: unknown) => { - console.error(e, 'Error in contract deletion cleanup') - throw e - }) - } -}) + // Then, delete all KV-store values associated with this contract + const kvIndexKey = `_private_kvIdx_${cid}` + const kvKeys = await sbp('chelonia.db/get', kvIndexKey) + if (kvKeys) { + await Promise.all(kvKeys.split('\x00').map((key: string) => { + return sbp('chelonia.db/delete', `_private_kv_${cid}_${key}`) + })) + } + await sbp('chelonia.db/delete', kvIndexKey) + await sbp('backend/server/removeFromIndirectResourcesIndex', cid) + await sbp('chelonia.db/delete', `_private_indirectResources_${cid}`) + + await sbp('chelonia.db/get', `_private_cid2name_${cid}`).then((name: unknown) => { + if (!name) return + return Promise.all([ + sbp('chelonia.db/delete', `_private_cid2name_${cid}`), + appendToOrphanedNamesIndex(name as string) + ]) + }) + await sbp('chelonia.db/delete', `_private_rid_${cid}`) + await sbp('chelonia.db/delete', `_private_owner_${cid}`) + await sbp('chelonia.db/delete', `_private_size_${cid}`) + await sbp('chelonia.db/delete', `_private_contractFilesTotalSize_${cid}`) + await sbp('chelonia.db/delete', `_private_deletionTokenDgst_${cid}`) + await removeFromIndexFactory(`_private_resources_${owner}`)(cid) + + // Delete the first event and its associated keys. These were not deleted + // in the loop above that deletes events one by one. + await sbp('chelonia.db/delete', `_private_hidx=${cid}#0`) + await sbp('chelonia.db/delete', `_private_keyop_idx_${cid}_0`) + await sbp('chelonia.db/set', cid, '') + sbp('chelonia/private/removeImmediately', cid) + + if (size) { + await currentOwnerSizeTotalWorker?.rpcSbp('worker/updateSizeSideEffects', { resourceID: cid, size: -parseInt(size), ultimateOwnerID }) + } -if (process.env.NODE_ENV === 'development' && !process.env.CI) { - hapi.events.on('response', (req) => { - const ip = req.headers['x-real-ip'] || req.info.remoteAddress - const statusCode = req.response instanceof Boom.Boom ? req.response.output.statusCode : req.response.statusCode - console.debug(chalk`{grey ${ip}: ${req.method} ${req.path} --> ${statusCode}}`) + await sbp('chelonia.db/delete', `_private_cheloniaState_${cid}`) + await removeFromIndexFactory('_private_cheloniaState_index')(cid) + // Note: `creditsWorker.js` could be updated to do this instead + await removeFromIndexFactory('_private_billable_entities')(cid) + sbp('backend/server/broadcastDeletion', cid).catch((e: unknown) => { + console.error(e, 'Error broadcasting contract deletion', cid) + }) + }).finally(() => { + contractsPendingDeletion.delete(cid) + }).catch((e: unknown) => { + console.error(e, 'Error in contract deletion cleanup') + throw e + }) + } }) } -sbp('okTurtles.data/set', PUBSUB_INSTANCE, createServer(hapi.listener, { - serverHandlers: { - connection (socket) { - const versionInfo = { - appVersion: cheloniaAppManifest?.appVersion || null, - contractsVersion: cheloniaAppManifest?.contracts ? Object.fromEntries( - Object.entries(cheloniaAppManifest?.contracts) - .map(([k, v]) => [k, (v as { version: string }).version]) - ) : null - } - socket.send(createNotification(NOTIFICATION_TYPE.VERSION_INFO, versionInfo)) - } - }, - socketHandlers: { - // The `close()` handler signals the server that the WS has been closed and - // that subsequent messages to subscribed channels should now be sent to its - // associated web push subscription, if it exists. - close () { - const socket = this - const { server } = this - const subscriptionId = socket.pushSubscriptionId - if (!subscriptionId) return - if (!server.pushSubscriptions[subscriptionId]) return - server.pushSubscriptions[subscriptionId].sockets.delete(socket) - delete socket.pushSubscriptionId - - if (server.pushSubscriptions[subscriptionId].sockets.size === 0) { - server.pushSubscriptions[subscriptionId].subscriptions.forEach((channelID) => { - if (!server.subscribersByChannelID[channelID]) { - server.subscribersByChannelID[channelID] = new Set() - } - server.subscribersByChannelID[channelID].add(server.pushSubscriptions[subscriptionId]) - }) - } - } - }, - messageHandlers: { - [REQUEST_TYPE.PUSH_ACTION]: async function ({ data }) { - const socket = this - const { action, payload } = data - - if (!action) { - socket.send(createPushErrorResponse({ message: '\'action\' field is required' })) - } +// ============================================================================ +// Exported server lifecycle functions +// ============================================================================ + +export async function startServer (): Promise<{ uri: string }> { + // Read configuration from nconf + const appDir = nconf.get('server:appDir') || process.cwd() + const ARCHIVE_MODE = nconf.get('server:archiveMode') + const host = nconf.get('server:host') || '0.0.0.0' + const port = nconf.get('server:port') ?? 8000 + + // Validate worker intervals + if (CREDITS_WORKER_TASK_TIME_INTERVAL && OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL > CREDITS_WORKER_TASK_TIME_INTERVAL) { + console.error('The size calculation worker must run more frequently than the credits worker for accurate billing') + throw new Error('The size calculation worker must run more frequently than the credits worker for accurate billing') + } + + // Load chelonia.json manifest + try { + currentManifest = (await import(pathToFileURL(join(appDir, 'chelonia.json')).toString(), { + with: { type: 'json' } + })).default + } catch { + console.warn('`chelonia.json` unparsable or not found. Version information will be unavailable.') + } - const handler = pushServerActionhandlers[action as keyof typeof pushServerActionhandlers] + // Initialize workers for size calculation and credits processing + currentOwnerSizeTotalWorker = ARCHIVE_MODE || !OWNER_SIZE_TOTAL_WORKER_TASK_TIME_INTERVAL + ? undefined + : createWorker((import.meta as ImportMeta).ownerSizeTotalWorker || './ownerSizeTotalWorker.ts') + currentCreditsWorker = ARCHIVE_MODE || !CREDITS_WORKER_TASK_TIME_INTERVAL + ? undefined + : createWorker((import.meta as ImportMeta).creditsWorker || './creditsWorker.ts') - if (handler) { - try { - await (handler as (this: typeof socket, payload: unknown) => Promise).call(socket, payload) - } catch (error) { - const message = (error as Error)?.message || `push server failed to perform [${action}] action` - console.warn(error, `[${socket.ip}] Action '${action}' for '${REQUEST_TYPE.PUSH_ACTION}' handler failed: ${message}`) - socket.send(createPushErrorResponse({ actionType: action, message: message })) + // Create Hono app + currentApp = new Hono() + + // Global middleware: CORS + currentApp.use('*', cors({ origin: '*' })) + + // Global middleware: X-Frame-Options on every response + currentApp.use('*', async (c, next) => { + await next() + c.header('X-Frame-Options', 'DENY') + }) + + // Dev logging middleware + if (process.env.NODE_ENV === 'development' && !process.env.CI) { + currentApp.use('*', async (c, next) => { + await next() + const ip = getClientIP(c) || 'unknown' + console.debug(chalk`{grey ${ip}: ${c.req.method} ${c.req.path} --> ${c.res.status}}`) + }) + } + + // Create the Node http.Server (without listening yet) via @hono/node-server + currentHttpServer = createAdaptorServer({ fetch: currentApp.fetch }) as Server + + // Install SBP selectors + installServerSelectorsOnce() + + // Set SERVER_INSTANCE so routes.ts can access it + sbp('okTurtles.data/set', SERVER_INSTANCE, currentApp) + + // Create pubsub server and set PUBSUB_INSTANCE + sbp('okTurtles.data/set', PUBSUB_INSTANCE, createServer(currentHttpServer, { + serverHandlers: { + connection (socket) { + const manifest = currentManifest + const appVersion = typeof manifest?.appVersion === 'string' ? manifest.appVersion : null + const contracts = manifest?.contracts as Record | undefined + const versionInfo = { + appVersion, + contractsVersion: contracts ? Object.fromEntries( + Object.entries(contracts) + .map(([k, v]) => [k, v.version]) + ) : null } - } else { - socket.send(createPushErrorResponse({ message: `No handler for the '${action}' action` })) + socket.send(createNotification(NOTIFICATION_TYPE.VERSION_INFO, versionInfo)) } }, - // This handler adds subscribed channels to the web push subscription - // associated with the WS, so that when the WS is closed we can continue - // sending messages as web push notifications. - [NOTIFICATION_TYPE.SUB] ({ channelID }) { - const socket = this - const { server } = this - if (!socket.pushSubscriptionId) return - if (!server.pushSubscriptions[socket.pushSubscriptionId]) { + socketHandlers: { + // The `close()` handler signals the server that the WS has been closed and + // that subsequent messages to subscribed channels should now be sent to its + // associated web push subscription, if it exists. + close () { + const socket = this + const { server } = this + const subscriptionId = socket.pushSubscriptionId + if (!subscriptionId) return + if (!server.pushSubscriptions[subscriptionId]) return + server.pushSubscriptions[subscriptionId].sockets.delete(socket) delete socket.pushSubscriptionId - return - } - addChannelToSubscription(server, socket.pushSubscriptionId, channelID) - }, - // This handler removes subscribed channels from the web push subscription - // associated with the WS, so that when the WS is closed we don't send - // messages as web push notifications. - [NOTIFICATION_TYPE.UNSUB] ({ channelID }) { - const socket = this - const { server } = this - if (!socket.pushSubscriptionId) return - if (!server.pushSubscriptions[socket.pushSubscriptionId]) { - delete socket.pushSubscriptionId - return + if (server.pushSubscriptions[subscriptionId].sockets.size === 0) { + server.pushSubscriptions[subscriptionId].subscriptions.forEach((channelID) => { + if (!server.subscribersByChannelID[channelID]) { + server.subscribersByChannelID[channelID] = new Set() + } + server.subscribersByChannelID[channelID].add(server.pushSubscriptions[subscriptionId]) + }) + } } + }, + messageHandlers: { + [REQUEST_TYPE.PUSH_ACTION]: async function ({ data }) { + const socket = this + const { action, payload } = data + + if (!action) { + socket.send(createPushErrorResponse({ message: '\'action\' field is required' })) + } + + const handler = pushServerActionhandlers[action as keyof typeof pushServerActionhandlers] + + if (handler) { + try { + await (handler as (this: typeof socket, payload: unknown) => Promise).call(socket, payload) + } catch (error) { + const message = (error as Error)?.message || `push server failed to perform [${action}] action` + console.warn(error, `[${socket.ip}] Action '${action}' for '${REQUEST_TYPE.PUSH_ACTION}' handler failed: ${message}`) + socket.send(createPushErrorResponse({ actionType: action, message: message })) + } + } else { + socket.send(createPushErrorResponse({ message: `No handler for the '${action}' action` })) + } + }, + // This handler adds subscribed channels to the web push subscription + // associated with the WS, so that when the WS is closed we can continue + // sending messages as web push notifications. + [NOTIFICATION_TYPE.SUB] ({ channelID }) { + const socket = this + const { server } = this + if (!socket.pushSubscriptionId) return + if (!server.pushSubscriptions[socket.pushSubscriptionId]) { + delete socket.pushSubscriptionId + return + } + + addChannelToSubscription(server, socket.pushSubscriptionId, channelID) + }, + // This handler removes subscribed channels from the web push subscription + // associated with the WS, so that when the WS is closed we don't send + // messages as web push notifications. + [NOTIFICATION_TYPE.UNSUB] ({ channelID }) { + const socket = this + const { server } = this + if (!socket.pushSubscriptionId) return + if (!server.pushSubscriptions[socket.pushSubscriptionId]) { + delete socket.pushSubscriptionId + return + } - deleteChannelFromSubscription(server, socket.pushSubscriptionId, channelID) + deleteChannelFromSubscription(server, socket.pushSubscriptionId, channelID) + } } - } -})) + })) -;(async function () { + // Initialize database await initDB() - await ownerSizeTotalWorker?.ready - await creditsWorker?.ready + + // Wait for workers to be ready + await currentOwnerSizeTotalWorker?.ready + await currentCreditsWorker?.ready + + // Configure Chelonia await sbp('chelonia/configure', SERVER) sbp('chelonia.persistentActions/configure', { databaseKey: '_private_persistent_actions' }) + // Load the saved Chelonia state // First, get the contract index const savedStateIndex = await sbp('chelonia.db/get', '_private_cheloniaState_index') @@ -563,6 +572,7 @@ sbp('okTurtles.data/set', PUBSUB_INSTANCE, createServer(hapi.listener, { })) Object.assign(sbp('chelonia/rootState'), recoveredState) } + // Then, load push subscriptions const savedWebPushIndex = await sbp('chelonia.db/get', '_private_webpush_index') if (savedWebPushIndex) { @@ -582,32 +592,18 @@ sbp('okTurtles.data/set', PUBSUB_INSTANCE, createServer(hapi.listener, { }) })) } + + // Fire-and-forget persistent actions load sbp('chelonia.persistentActions/load').catch((e: unknown) => { console.error(e, 'Error loading persistent actions') }) - // https://hapi.dev/tutorials/plugins - await hapi.register([ - { plugin: authPlugin }, - { plugin: Inert } - // { - // plugin: require('hapi-pino'), - // options: { - // instance: logger - // } - // } - ]) - // Import routes after plugins are registered - await import('./routes.ts') - await hapi.start() - console.info('Backend server running at:', hapi.info.uri) - sbp('okTurtles.events/emit', SERVER_RUNNING, hapi) -})() - -// Recurring task to send messages to push clients (for periodic notifications) -;(() => { - const map = new WeakMap() - pushHeartbeatIntervalID = setInterval(() => { + // Register routes + registerRoutes(currentApp) + + // Start the push-heartbeat interval + const map = new WeakMap() + currentPushHeartbeatIntervalID = setInterval(() => { const now = Date.now() const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as WSS | undefined // Notification text @@ -628,4 +624,78 @@ sbp('okTurtles.data/set', PUBSUB_INSTANCE, createServer(hapi.listener, { }) // Repeat every 1 hour }, 1 * 60 * 60 * 1000) -})() + + // Start listening + const uri = await new Promise((resolve, reject) => { + currentHttpServer!.listen(port, host, () => { + const addr = currentHttpServer!.address() as { address: string; port: number } + const uri = `http://${addr.address}:${addr.port}` + console.info('Backend server running at:', uri) + sbp('okTurtles.events/emit', SERVER_RUNNING, { info: { uri } }) + resolve(uri) + }).once('error', reject) + }) + + return { uri } +} + +export async function stopServer (): Promise { + if (isStopping) return + isStopping = true + try { + // Clear push-heartbeat interval + if (currentPushHeartbeatIntervalID !== undefined) { + clearInterval(currentPushHeartbeatIntervalID) + currentPushHeartbeatIntervalID = undefined + } + + // Stop rate limiters if registered + if (sbp('sbp/selectors/fn', 'backend/server/stopRateLimiters')) { + await sbp('backend/server/stopRateLimiters') + } + + // Close pubsub server (clears its ping interval) + const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE) as { close: () => void; clients: Set<{ terminate: () => void }> } | undefined + if (pubsub) { + // Since `ws` v8.0, `WebSocketServer.close()` no longer closes remaining connections. + // See https://github.com/websockets/ws/commit/df7de574a07115e2321fdb5fc9b2d0fea55d27e8 + pubsub.clients.forEach((client) => client.terminate()) + pubsub.close() + sbp('okTurtles.data/delete', PUBSUB_INSTANCE) + } + + // Close HTTP server + if (currentHttpServer) { + await new Promise((resolve, reject) => { + currentHttpServer!.close((err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) + currentHttpServer = null + } + + // Terminate workers + await Promise.all([ + currentOwnerSizeTotalWorker?.terminate(), + currentCreditsWorker?.terminate() + ]) + currentOwnerSizeTotalWorker = undefined + currentCreditsWorker = undefined + + // Unload persistent actions + await sbp('chelonia.persistentActions/unload') + + // Close database + await closeDB() + + // Clear app and manifest + currentApp = null + currentManifest = undefined + } finally { + isStopping = false + } +} diff --git a/src/serve/zkppSalt.test.ts b/src/serve/zkppSalt.test.ts index 8a78365..deb7284 100644 --- a/src/serve/zkppSalt.test.ts +++ b/src/serve/zkppSalt.test.ts @@ -1,7 +1,7 @@ import { Buffer } from 'node:buffer' import { AUTHSALT, CONTRACTSALT, CS, SALT_LENGTH_IN_OCTETS, SU } from 'npm:@chelonia/lib/zkppConstants' import tweetnacl from 'npm:tweetnacl' -import { initDB } from './database.ts' +import { closeDB, initDB } from './database.ts' const nacl = tweetnacl @@ -38,111 +38,115 @@ Deno.test({ async fn (t: Deno.TestContext) { // Setup await initDB() - await t.step('register() conforms to the API to register a new salt', async () => { - const keyPair = nacl.box.keyPair() - const publicKey = Buffer.from(keyPair.publicKey).toString('base64url') - const publicKeyHash = Buffer.from(nacl.hash(Buffer.from(publicKey))).toString('base64url') - - const regKeyAlice1 = registrationKey('alice', publicKeyHash) - const regKeyAlice2 = registrationKey('alice', publicKeyHash) - if (typeof regKeyAlice1 !== 'object') throw new Error('regKeyAlice1 should be object') - if (typeof regKeyAlice2 !== 'object') throw new Error('regKeyAlice2 should be object') - const [, , encryptedHashedPasswordAlice1] = saltsAndEncryptedHashedPassword(regKeyAlice1.p, keyPair.secretKey, 'hash') - const res1 = register('alice', publicKey, regKeyAlice1.s, regKeyAlice1.sig, encryptedHashedPasswordAlice1) - if (typeof res1 !== 'string') throw new Error('register should return a token (alice)') - const token = decryptRegistrationRedemptionToken(regKeyAlice1.p, keyPair.secretKey, res1) - await redeemSaltRegistrationToken('alice', 'alice', token) - - const [, , encryptedHashedPasswordAlice2] = saltsAndEncryptedHashedPassword(regKeyAlice1.p, keyPair.secretKey, 'hash') - const res2 = register('alice', publicKey, regKeyAlice2.s, regKeyAlice2.sig, encryptedHashedPasswordAlice2) - if (res2 !== false) throw new Error('register should not overwrite entry (alice)') - - const regKeyBob1 = registrationKey('bob', publicKeyHash) - if (typeof regKeyBob1 !== 'object') throw new Error('regKeyBob1 should be object') - const [, , encryptedHashedPasswordBob1] = saltsAndEncryptedHashedPassword(regKeyBob1.p, keyPair.secretKey, 'hash') - const res3 = register('bob', publicKey, regKeyBob1.s, regKeyBob1.sig, encryptedHashedPasswordBob1) - if (typeof res3 !== 'string') throw new Error('register should return a token (bob)') - }) - - await t.step('getContractSalt() conforms to the API to obtain salt', async () => { - const keyPair = nacl.box.keyPair() - const publicKey = Buffer.from(keyPair.publicKey).toString('base64url') - const publicKeyHash = Buffer.from(nacl.hash(Buffer.from(publicKey))).toString('base64url') - - const [contract, hash, r] = ['getContractSalt', 'hash', 'r'] - const regKey = registrationKey(contract, publicKeyHash) - if (typeof regKey !== 'object') throw new Error('regKey should be object') - if (!regKey) throw new Error('regKey should not be false') - - const [authSalt, contractSalt, encryptedHashedPassword] = saltsAndEncryptedHashedPassword(regKey.p, keyPair.secretKey, hash) - - const res = register(contract, publicKey, regKey.s, regKey.sig, encryptedHashedPassword) - if (typeof res !== 'string') throw new Error('register should allow new entry (' + contract + ')') - const token = decryptRegistrationRedemptionToken(regKey.p, keyPair.secretKey, res as string) - await redeemSaltRegistrationToken(contract, contract, token) - - const b = Buffer.from(nacl.hash(Buffer.from(r))).toString('base64url') - const challenge = await getChallenge(contract, b) - if (typeof challenge !== 'object') throw new Error('challenge should be object') - if (!challenge) throw new Error('challenge should not be false') - if (challenge.authSalt !== authSalt) throw new Error('mismatched authSalt') - - const ħ = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(r)), nacl.hash(Buffer.from(challenge.s))])) - const c = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(hash)), nacl.hash(ħ)])) - const hc = nacl.hash(c) - - const salt = await getContractSalt(contract, r, challenge.s, challenge.sig, Buffer.from(hc).toString('base64url')) - if (typeof salt !== 'string') throw new Error('salt response should be string') - if (!salt) throw new Error('salt should not be false') - - const saltBuf = Buffer.from(salt, 'base64url') - const nonce = saltBuf.slice(0, nacl.secretbox.nonceLength) - const encryptionKey = nacl.hash(Buffer.concat([Buffer.from(CS), c])).slice(0, nacl.secretbox.keyLength) - const [retrievedContractSalt] = JSON.parse( - (() => { - const decrypted = nacl.secretbox.open(saltBuf.slice(nacl.secretbox.nonceLength), nonce, encryptionKey) - if (!decrypted) throw new Error('Failed to decrypt salt') - return Buffer.from(decrypted).toString() - })() - ) - if (retrievedContractSalt !== contractSalt) throw new Error('mismatched contractSalt') - }) - - await t.step('updateContractSalt() conforms to the API to update salt', async () => { - const keyPair = nacl.box.keyPair() - const publicKey = Buffer.from(keyPair.publicKey).toString('base64url') - const publicKeyHash = Buffer.from(nacl.hash(Buffer.from(publicKey))).toString('base64url') - - const [contract, hash, r] = ['update', 'hash', 'r'] - const regKey = registrationKey(contract, publicKeyHash) - if (typeof regKey !== 'object') throw new Error('regKey should be object') - if (!regKey) throw new Error('regKey should not be false') - - const [authSalt, , encryptedHashedPassword] = saltsAndEncryptedHashedPassword(regKey.p, keyPair.secretKey, hash) - - const res = register(contract, publicKey, regKey.s, regKey.sig, encryptedHashedPassword) - if (typeof res !== 'string') throw new Error('register should allow new entry (' + contract + ')') - const token = decryptRegistrationRedemptionToken(regKey.p, keyPair.secretKey, res as string) - await redeemSaltRegistrationToken(contract, contract, token) - - const b = Buffer.from(nacl.hash(Buffer.from(r))).toString('base64url') - const challenge = await getChallenge(contract, b) - if (typeof challenge !== 'object') throw new Error('challenge should be object') - if (challenge.authSalt !== authSalt) throw new Error('mismatched authSalt') - - const ħ = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(r)), nacl.hash(Buffer.from(challenge.s))])) - const c = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(hash)), nacl.hash(ħ)])) - const hc = nacl.hash(c) - - const encryptionKey = nacl.hash(Buffer.concat([Buffer.from(SU), c])).slice(0, nacl.secretbox.keyLength) - const nonce = nacl.randomBytes(nacl.secretbox.nonceLength) - - const encryptedArgsCiphertext = nacl.secretbox(Buffer.from(JSON.stringify(['a', 'b', 'c'])), nonce, encryptionKey) - - const encryptedArgs = Buffer.concat([nonce, encryptedArgsCiphertext]).toString('base64url') - - const updateRes = await updateContractSalt(contract, r, challenge.s, challenge.sig, Buffer.from(hc).toString('base64url'), encryptedArgs) - if (!updateRes) throw new Error('updateContractSalt should be successful') - }) + try { + await t.step('register() conforms to the API to register a new salt', async () => { + const keyPair = nacl.box.keyPair() + const publicKey = Buffer.from(keyPair.publicKey).toString('base64url') + const publicKeyHash = Buffer.from(nacl.hash(Buffer.from(publicKey))).toString('base64url') + + const regKeyAlice1 = registrationKey('alice', publicKeyHash) + const regKeyAlice2 = registrationKey('alice', publicKeyHash) + if (typeof regKeyAlice1 !== 'object') throw new Error('regKeyAlice1 should be object') + if (typeof regKeyAlice2 !== 'object') throw new Error('regKeyAlice2 should be object') + const [, , encryptedHashedPasswordAlice1] = saltsAndEncryptedHashedPassword(regKeyAlice1.p, keyPair.secretKey, 'hash') + const res1 = register('alice', publicKey, regKeyAlice1.s, regKeyAlice1.sig, encryptedHashedPasswordAlice1) + if (typeof res1 !== 'string') throw new Error('register should return a token (alice)') + const token = decryptRegistrationRedemptionToken(regKeyAlice1.p, keyPair.secretKey, res1) + await redeemSaltRegistrationToken('alice', 'alice', token) + + const [, , encryptedHashedPasswordAlice2] = saltsAndEncryptedHashedPassword(regKeyAlice1.p, keyPair.secretKey, 'hash') + const res2 = register('alice', publicKey, regKeyAlice2.s, regKeyAlice2.sig, encryptedHashedPasswordAlice2) + if (res2 !== false) throw new Error('register should not overwrite entry (alice)') + + const regKeyBob1 = registrationKey('bob', publicKeyHash) + if (typeof regKeyBob1 !== 'object') throw new Error('regKeyBob1 should be object') + const [, , encryptedHashedPasswordBob1] = saltsAndEncryptedHashedPassword(regKeyBob1.p, keyPair.secretKey, 'hash') + const res3 = register('bob', publicKey, regKeyBob1.s, regKeyBob1.sig, encryptedHashedPasswordBob1) + if (typeof res3 !== 'string') throw new Error('register should return a token (bob)') + }) + + await t.step('getContractSalt() conforms to the API to obtain salt', async () => { + const keyPair = nacl.box.keyPair() + const publicKey = Buffer.from(keyPair.publicKey).toString('base64url') + const publicKeyHash = Buffer.from(nacl.hash(Buffer.from(publicKey))).toString('base64url') + + const [contract, hash, r] = ['getContractSalt', 'hash', 'r'] + const regKey = registrationKey(contract, publicKeyHash) + if (typeof regKey !== 'object') throw new Error('regKey should be object') + if (!regKey) throw new Error('regKey should not be false') + + const [authSalt, contractSalt, encryptedHashedPassword] = saltsAndEncryptedHashedPassword(regKey.p, keyPair.secretKey, hash) + + const res = register(contract, publicKey, regKey.s, regKey.sig, encryptedHashedPassword) + if (typeof res !== 'string') throw new Error('register should allow new entry (' + contract + ')') + const token = decryptRegistrationRedemptionToken(regKey.p, keyPair.secretKey, res as string) + await redeemSaltRegistrationToken(contract, contract, token) + + const b = Buffer.from(nacl.hash(Buffer.from(r))).toString('base64url') + const challenge = await getChallenge(contract, b) + if (typeof challenge !== 'object') throw new Error('challenge should be object') + if (!challenge) throw new Error('challenge should not be false') + if (challenge.authSalt !== authSalt) throw new Error('mismatched authSalt') + + const ħ = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(r)), nacl.hash(Buffer.from(challenge.s))])) + const c = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(hash)), nacl.hash(ħ)])) + const hc = nacl.hash(c) + + const salt = await getContractSalt(contract, r, challenge.s, challenge.sig, Buffer.from(hc).toString('base64url')) + if (typeof salt !== 'string') throw new Error('salt response should be string') + if (!salt) throw new Error('salt should not be false') + + const saltBuf = Buffer.from(salt, 'base64url') + const nonce = saltBuf.slice(0, nacl.secretbox.nonceLength) + const encryptionKey = nacl.hash(Buffer.concat([Buffer.from(CS), c])).slice(0, nacl.secretbox.keyLength) + const [retrievedContractSalt] = JSON.parse( + (() => { + const decrypted = nacl.secretbox.open(saltBuf.slice(nacl.secretbox.nonceLength), nonce, encryptionKey) + if (!decrypted) throw new Error('Failed to decrypt salt') + return Buffer.from(decrypted).toString() + })() + ) + if (retrievedContractSalt !== contractSalt) throw new Error('mismatched contractSalt') + }) + + await t.step('updateContractSalt() conforms to the API to update salt', async () => { + const keyPair = nacl.box.keyPair() + const publicKey = Buffer.from(keyPair.publicKey).toString('base64url') + const publicKeyHash = Buffer.from(nacl.hash(Buffer.from(publicKey))).toString('base64url') + + const [contract, hash, r] = ['update', 'hash', 'r'] + const regKey = registrationKey(contract, publicKeyHash) + if (typeof regKey !== 'object') throw new Error('regKey should be object') + if (!regKey) throw new Error('regKey should not be false') + + const [authSalt, , encryptedHashedPassword] = saltsAndEncryptedHashedPassword(regKey.p, keyPair.secretKey, hash) + + const res = register(contract, publicKey, regKey.s, regKey.sig, encryptedHashedPassword) + if (typeof res !== 'string') throw new Error('register should allow new entry (' + contract + ')') + const token = decryptRegistrationRedemptionToken(regKey.p, keyPair.secretKey, res as string) + await redeemSaltRegistrationToken(contract, contract, token) + + const b = Buffer.from(nacl.hash(Buffer.from(r))).toString('base64url') + const challenge = await getChallenge(contract, b) + if (typeof challenge !== 'object') throw new Error('challenge should be object') + if (challenge.authSalt !== authSalt) throw new Error('mismatched authSalt') + + const ħ = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(r)), nacl.hash(Buffer.from(challenge.s))])) + const c = nacl.hash(Buffer.concat([nacl.hash(Buffer.from(hash)), nacl.hash(ħ)])) + const hc = nacl.hash(c) + + const encryptionKey = nacl.hash(Buffer.concat([Buffer.from(SU), c])).slice(0, nacl.secretbox.keyLength) + const nonce = nacl.randomBytes(nacl.secretbox.nonceLength) + + const encryptedArgsCiphertext = nacl.secretbox(Buffer.from(JSON.stringify(['a', 'b', 'c'])), nonce, encryptionKey) + + const encryptedArgs = Buffer.concat([nonce, encryptedArgsCiphertext]).toString('base64url') + + const updateRes = await updateContractSalt(contract, r, challenge.s, challenge.sig, Buffer.from(hc).toString('base64url'), encryptedArgs) + if (!updateRes) throw new Error('updateContractSalt should be successful') + }) + } finally { + await closeDB() + } } }) diff --git a/src/upload.ts b/src/upload.ts index 20068cf..5016e14 100644 --- a/src/upload.ts +++ b/src/upload.ts @@ -4,51 +4,59 @@ import { Buffer } from 'node:buffer' import { multicodes } from 'npm:@chelonia/lib/functions' import sbp from 'npm:@sbp/sbp' import type { ArgumentsCamelCase, CommandModule } from './commands.ts' -import { initDB } from './serve/database.ts' +import { closeDB, initDB } from './serve/database.ts' import { createEntryFromFile, type Entry } from './utils.ts' type Params = { url?: string, files: string[] } export async function upload (args: ArgumentsCamelCase, internal = false): Promise<[string, string][]> { const { url, files } = args + let dbOpen = false if (!url) { await initDB({ skipDbPreloading: true }) + dbOpen = true } - const uploaded: Array<[string, string]> = [] - const uploaderFn = url - ? uploadEntryToURL - : uploadEntryToDB - for (const filepath_ of files) { - let type = multicodes.RAW - let filepath = filepath_ - if (internal) { + try { + const uploaded: Array<[string, string]> = [] + const uploaderFn = url + ? uploadEntryToURL + : uploadEntryToDB + for (const filepath_ of files) { + let type = multicodes.RAW + let filepath = filepath_ + if (internal) { // The `{type}|` prefix is used to determine which kind of CID is needed - if (filepath_[1] !== '|') throw new Error('Invalid path format') - switch (filepath_[0]) { - case 'r': - // raw file type - break - case 'm': - type = multicodes.SHELTER_CONTRACT_MANIFEST - break - case 't': - type = multicodes.SHELTER_CONTRACT_TEXT - break - default: - throw new Error('Unknown file type: ' + filepath_[0]) + if (filepath_[1] !== '|') throw new Error('Invalid path format') + switch (filepath_[0]) { + case 'r': + // raw file type + break + case 'm': + type = multicodes.SHELTER_CONTRACT_MANIFEST + break + case 't': + type = multicodes.SHELTER_CONTRACT_TEXT + break + default: + throw new Error('Unknown file type: ' + filepath_[0]) + } + filepath = filepath_.slice(2) } - filepath = filepath_.slice(2) + const entry = await createEntryFromFile(filepath, type) + const destination = await uploaderFn(entry, url!) + if (!internal) { + console.log(colors.green('uploaded:'), destination) + } else { + console.log(colors.green(`${path.relative('.', filepath)}:`), destination) + } + uploaded.push([filepath, destination]) } - const entry = await createEntryFromFile(filepath, type) - const destination = await uploaderFn(entry, url!) - if (!internal) { - console.log(colors.green('uploaded:'), destination) - } else { - console.log(colors.green(`${path.relative('.', filepath)}:`), destination) + return uploaded + } finally { + if (dbOpen) { + await closeDB() } - uploaded.push([filepath, destination]) } - return uploaded } async function uploadEntryToURL ([cid, buffer]: Entry, url: string): Promise {