From d1bfc9fbaca612dae1ded02ac9bc599d81531330 Mon Sep 17 00:00:00 2001 From: Tu Nombre <22030946@itcelaya.edu.mx> Date: Sat, 23 May 2026 01:06:04 -0600 Subject: [PATCH] feat: simulador GPS con cron job y pub/sub Redis --- backend/env | 20 + backend/node_modules/.package-lock.json | 119 + .../node_modules/@ioredis/commands/LICENSE | 23 + .../node_modules/@ioredis/commands/README.md | 43 + .../@ioredis/commands/built/commands.json | 2578 +++++ .../@ioredis/commands/built/index.d.ts | 34 + .../@ioredis/commands/built/index.js | 217 + .../@ioredis/commands/package.json | 52 + .../node_modules/cluster-key-slot/.eslintrc | 16 + backend/node_modules/cluster-key-slot/LICENSE | 13 + .../node_modules/cluster-key-slot/README.md | 61 + .../node_modules/cluster-key-slot/index.d.ts | 10 + .../cluster-key-slot/lib/index.js | 166 + .../cluster-key-slot/package.json | 56 + backend/node_modules/denque/CHANGELOG.md | 29 + backend/node_modules/denque/LICENSE | 201 + backend/node_modules/denque/README.md | 77 + backend/node_modules/denque/index.d.ts | 47 + backend/node_modules/denque/index.js | 481 + backend/node_modules/denque/package.json | 58 + backend/node_modules/ioredis/LICENSE | 21 + backend/node_modules/ioredis/README.md | 1498 +++ .../node_modules/ioredis/built/Command.d.ts | 165 + backend/node_modules/ioredis/built/Command.js | 449 + .../ioredis/built/DataHandler.d.ts | 37 + .../node_modules/ioredis/built/DataHandler.js | 224 + .../node_modules/ioredis/built/Pipeline.d.ts | 31 + .../node_modules/ioredis/built/Pipeline.js | 342 + backend/node_modules/ioredis/built/Redis.d.ts | 232 + backend/node_modules/ioredis/built/Redis.js | 745 ++ .../ioredis/built/ScanStream.d.ts | 23 + .../node_modules/ioredis/built/ScanStream.js | 51 + .../node_modules/ioredis/built/Script.d.ts | 11 + backend/node_modules/ioredis/built/Script.js | 62 + .../ioredis/built/SubscriptionSet.d.ts | 14 + .../ioredis/built/SubscriptionSet.js | 41 + .../ioredis/built/autoPipelining.d.ts | 8 + .../ioredis/built/autoPipelining.js | 167 + .../ioredis/built/cluster/ClusterOptions.d.ts | 172 + .../ioredis/built/cluster/ClusterOptions.js | 22 + .../built/cluster/ClusterSubscriber.d.ts | 29 + .../built/cluster/ClusterSubscriber.js | 223 + .../built/cluster/ClusterSubscriberGroup.d.ts | 108 + .../built/cluster/ClusterSubscriberGroup.js | 373 + .../ioredis/built/cluster/ConnectionPool.d.ts | 37 + .../ioredis/built/cluster/ConnectionPool.js | 154 + .../ioredis/built/cluster/DelayQueue.d.ts | 20 + .../ioredis/built/cluster/DelayQueue.js | 53 + .../built/cluster/ShardedSubscriber.d.ts | 36 + .../built/cluster/ShardedSubscriber.js | 147 + .../ioredis/built/cluster/index.d.ts | 163 + .../ioredis/built/cluster/index.js | 937 ++ .../ioredis/built/cluster/util.d.ts | 25 + .../ioredis/built/cluster/util.js | 100 + .../built/connectors/AbstractConnector.d.ts | 12 + .../built/connectors/AbstractConnector.js | 26 + .../connectors/ConnectorConstructor.d.ts | 5 + .../built/connectors/ConnectorConstructor.js | 2 + .../SentinelConnector/FailoverDetector.d.ts | 11 + .../SentinelConnector/FailoverDetector.js | 45 + .../SentinelConnector/SentinelIterator.d.ts | 13 + .../SentinelConnector/SentinelIterator.js | 37 + .../connectors/SentinelConnector/index.d.ts | 72 + .../connectors/SentinelConnector/index.js | 305 + .../connectors/SentinelConnector/types.d.ts | 21 + .../connectors/SentinelConnector/types.js | 2 + .../built/connectors/StandaloneConnector.d.ts | 17 + .../built/connectors/StandaloneConnector.js | 69 + .../ioredis/built/connectors/index.d.ts | 3 + .../ioredis/built/connectors/index.js | 7 + .../ioredis/built/constants/TLSProfiles.d.ts | 9 + .../ioredis/built/constants/TLSProfiles.js | 149 + .../built/errors/ClusterAllFailedError.d.ts | 7 + .../built/errors/ClusterAllFailedError.js | 15 + .../errors/MaxRetriesPerRequestError.d.ts | 5 + .../built/errors/MaxRetriesPerRequestError.js | 14 + .../ioredis/built/errors/index.d.ts | 2 + .../ioredis/built/errors/index.js | 5 + backend/node_modules/ioredis/built/index.d.ts | 43 + backend/node_modules/ioredis/built/index.js | 62 + .../ioredis/built/redis/RedisOptions.d.ts | 197 + .../ioredis/built/redis/RedisOptions.js | 58 + .../ioredis/built/redis/event_handler.d.ts | 4 + .../ioredis/built/redis/event_handler.js | 315 + .../ioredis/built/transaction.d.ts | 13 + .../node_modules/ioredis/built/transaction.js | 93 + backend/node_modules/ioredis/built/types.d.ts | 33 + backend/node_modules/ioredis/built/types.js | 2 + .../ioredis/built/utils/Commander.d.ts | 50 + .../ioredis/built/utils/Commander.js | 117 + .../ioredis/built/utils/RedisCommander.d.ts | 8950 +++++++++++++++++ .../ioredis/built/utils/RedisCommander.js | 7 + .../ioredis/built/utils/applyMixin.d.ts | 3 + .../ioredis/built/utils/applyMixin.js | 8 + .../ioredis/built/utils/argumentParsers.d.ts | 14 + .../ioredis/built/utils/argumentParsers.js | 74 + .../ioredis/built/utils/debug.d.ts | 16 + .../node_modules/ioredis/built/utils/debug.js | 95 + .../ioredis/built/utils/index.d.ts | 124 + .../node_modules/ioredis/built/utils/index.js | 332 + .../ioredis/built/utils/lodash.d.ts | 4 + .../ioredis/built/utils/lodash.js | 9 + .../ioredis/node_modules/debug/LICENSE | 20 + .../ioredis/node_modules/debug/README.md | 481 + .../ioredis/node_modules/debug/package.json | 64 + .../ioredis/node_modules/debug/src/browser.js | 272 + .../ioredis/node_modules/debug/src/common.js | 292 + .../ioredis/node_modules/debug/src/index.js | 10 + .../ioredis/node_modules/debug/src/node.js | 263 + .../ioredis/node_modules/ms/index.js | 162 + .../ioredis/node_modules/ms/license.md | 21 + .../ioredis/node_modules/ms/package.json | 38 + .../ioredis/node_modules/ms/readme.md | 59 + backend/node_modules/ioredis/package.json | 102 + backend/node_modules/lodash.defaults/LICENSE | 47 + .../node_modules/lodash.defaults/README.md | 18 + backend/node_modules/lodash.defaults/index.js | 668 ++ .../node_modules/lodash.defaults/package.json | 17 + .../node_modules/lodash.isarguments/LICENSE | 47 + .../node_modules/lodash.isarguments/README.md | 18 + .../node_modules/lodash.isarguments/index.js | 229 + .../lodash.isarguments/package.json | 17 + backend/node_modules/node-cron/LICENSE.md | 7 + backend/node_modules/node-cron/README.md | 117 + .../node-cron/dist/cjs/create-id.d.ts | 1 + .../node-cron/dist/cjs/create-id.js | 14 + .../node-cron/dist/cjs/create-id.js.map | 1 + .../node-cron/dist/cjs/logger.d.ts | 7 + .../node_modules/node-cron/dist/cjs/logger.js | 57 + .../node-cron/dist/cjs/logger.js.map | 1 + .../node-cron/dist/cjs/node-cron.d.ts | 18 + .../node-cron/dist/cjs/node-cron.js | 71 + .../node-cron/dist/cjs/node-cron.js.map | 1 + .../asterisk-to-range-conversion.d.ts | 2 + .../asterisk-to-range-conversion.js | 21 + .../asterisk-to-range-conversion.js.map | 1 + .../dist/cjs/pattern/convertion/index.d.ts | 2 + .../dist/cjs/pattern/convertion/index.js | 42 + .../dist/cjs/pattern/convertion/index.js.map | 1 + .../convertion/month-names-conversion.d.ts | 2 + .../convertion/month-names-conversion.js | 21 + .../convertion/month-names-conversion.js.map | 1 + .../pattern/convertion/range-conversion.d.ts | 2 + .../pattern/convertion/range-conversion.js | 35 + .../convertion/range-conversion.js.map | 1 + .../convertion/week-day-names-conversion.d.ts | 2 + .../convertion/week-day-names-conversion.js | 20 + .../week-day-names-conversion.js.map | 1 + .../validation/pattern-validation.d.ts | 2 + .../pattern/validation/pattern-validation.js | 61 + .../validation/pattern-validation.js.map | 1 + .../dist/cjs/promise/tracked-promise.d.ts | 19 + .../dist/cjs/promise/tracked-promise.js | 55 + .../dist/cjs/promise/tracked-promise.js.map | 1 + .../node-cron/dist/cjs/scheduler/runner.d.ts | 42 + .../node-cron/dist/cjs/scheduler/runner.js | 192 + .../dist/cjs/scheduler/runner.js.map | 1 + .../node-cron/dist/cjs/task-registry.d.ts | 11 + .../node-cron/dist/cjs/task-registry.js | 35 + .../node-cron/dist/cjs/task-registry.js.map | 1 + .../background-scheduled-task.d.ts | 28 + .../background-scheduled-task.js | 220 + .../background-scheduled-task.js.map | 1 + .../background-scheduled-task/daemon.d.ts | 3 + .../tasks/background-scheduled-task/daemon.js | 142 + .../background-scheduled-task/daemon.js.map | 1 + .../background-scheduled-task/index.d.ts | 0 .../tasks/background-scheduled-task/index.js | 2 + .../background-scheduled-task/index.js.map | 1 + .../dist/cjs/tasks/inline-scheduled-task.d.ts | 30 + .../dist/cjs/tasks/inline-scheduled-task.js | 144 + .../cjs/tasks/inline-scheduled-task.js.map | 1 + .../dist/cjs/tasks/scheduled-task.d.ts | 37 + .../dist/cjs/tasks/scheduled-task.js | 3 + .../dist/cjs/tasks/scheduled-task.js.map | 1 + .../dist/cjs/tasks/state-machine.d.ts | 6 + .../node-cron/dist/cjs/tasks/state-machine.js | 25 + .../dist/cjs/tasks/state-machine.js.map | 1 + .../dist/cjs/time/localized-time.d.ts | 22 + .../node-cron/dist/cjs/time/localized-time.js | 81 + .../dist/cjs/time/localized-time.js.map | 1 + .../dist/cjs/time/matcher-walker.d.ts | 13 + .../node-cron/dist/cjs/time/matcher-walker.js | 100 + .../dist/cjs/time/matcher-walker.js.map | 1 + .../node-cron/dist/cjs/time/time-matcher.d.ts | 8 + .../node-cron/dist/cjs/time/time-matcher.js | 41 + .../dist/cjs/time/time-matcher.js.map | 1 + .../node-cron/dist/esm/create-id.d.ts | 1 + .../node-cron/dist/esm/create-id.js | 14 + .../node-cron/dist/esm/create-id.js.map | 1 + .../node-cron/dist/esm/logger.d.ts | 7 + .../node_modules/node-cron/dist/esm/logger.js | 57 + .../node-cron/dist/esm/logger.js.map | 1 + .../node-cron/dist/esm/node-cron.d.ts | 18 + .../node-cron/dist/esm/node-cron.js | 71 + .../node-cron/dist/esm/node-cron.js.map | 1 + .../asterisk-to-range-conversion.d.ts | 2 + .../asterisk-to-range-conversion.js | 21 + .../asterisk-to-range-conversion.js.map | 1 + .../dist/esm/pattern/convertion/index.d.ts | 2 + .../dist/esm/pattern/convertion/index.js | 42 + .../dist/esm/pattern/convertion/index.js.map | 1 + .../convertion/month-names-conversion.d.ts | 2 + .../convertion/month-names-conversion.js | 21 + .../convertion/month-names-conversion.js.map | 1 + .../pattern/convertion/range-conversion.d.ts | 2 + .../pattern/convertion/range-conversion.js | 35 + .../convertion/range-conversion.js.map | 1 + .../convertion/week-day-names-conversion.d.ts | 2 + .../convertion/week-day-names-conversion.js | 20 + .../week-day-names-conversion.js.map | 1 + .../validation/pattern-validation.d.ts | 2 + .../pattern/validation/pattern-validation.js | 61 + .../validation/pattern-validation.js.map | 1 + .../dist/esm/promise/tracked-promise.d.ts | 19 + .../dist/esm/promise/tracked-promise.js | 55 + .../dist/esm/promise/tracked-promise.js.map | 1 + .../node-cron/dist/esm/scheduler/runner.d.ts | 42 + .../node-cron/dist/esm/scheduler/runner.js | 192 + .../dist/esm/scheduler/runner.js.map | 1 + .../node-cron/dist/esm/task-registry.d.ts | 11 + .../node-cron/dist/esm/task-registry.js | 35 + .../node-cron/dist/esm/task-registry.js.map | 1 + .../background-scheduled-task.d.ts | 28 + .../background-scheduled-task.js | 220 + .../background-scheduled-task.js.map | 1 + .../background-scheduled-task/daemon.d.ts | 3 + .../tasks/background-scheduled-task/daemon.js | 109 + .../background-scheduled-task/daemon.js.map | 1 + .../background-scheduled-task/index.d.ts | 1 + .../tasks/background-scheduled-task/index.js | 3 + .../background-scheduled-task/index.js.map | 1 + .../dist/esm/tasks/inline-scheduled-task.d.ts | 30 + .../dist/esm/tasks/inline-scheduled-task.js | 144 + .../esm/tasks/inline-scheduled-task.js.map | 1 + .../dist/esm/tasks/scheduled-task.d.ts | 37 + .../dist/esm/tasks/scheduled-task.js | 3 + .../dist/esm/tasks/scheduled-task.js.map | 1 + .../dist/esm/tasks/state-machine.d.ts | 6 + .../node-cron/dist/esm/tasks/state-machine.js | 25 + .../dist/esm/tasks/state-machine.js.map | 1 + .../dist/esm/time/localized-time.d.ts | 22 + .../node-cron/dist/esm/time/localized-time.js | 81 + .../dist/esm/time/localized-time.js.map | 1 + .../dist/esm/time/matcher-walker.d.ts | 13 + .../node-cron/dist/esm/time/matcher-walker.js | 100 + .../dist/esm/time/matcher-walker.js.map | 1 + .../node-cron/dist/esm/time/time-matcher.d.ts | 8 + .../node-cron/dist/esm/time/time-matcher.js | 41 + .../dist/esm/time/time-matcher.js.map | 1 + backend/node_modules/node-cron/package.json | 85 + backend/node_modules/redis-errors/.npmignore | 15 + backend/node_modules/redis-errors/LICENSE | 22 + backend/node_modules/redis-errors/README.md | 116 + backend/node_modules/redis-errors/index.js | 7 + .../node_modules/redis-errors/lib/modern.js | 59 + backend/node_modules/redis-errors/lib/old.js | 119 + .../node_modules/redis-errors/package.json | 41 + backend/node_modules/redis-parser/.npmignore | 15 + backend/node_modules/redis-parser/LICENSE | 22 + backend/node_modules/redis-parser/README.md | 166 + .../node_modules/redis-parser/changelog.md | 156 + backend/node_modules/redis-parser/index.js | 3 + .../node_modules/redis-parser/lib/parser.js | 552 + .../node_modules/redis-parser/package.json | 53 + .../node_modules/standard-as-callback/LICENSE | 22 + .../standard-as-callback/README.md | 33 + .../standard-as-callback/built/index.d.ts | 5 + .../standard-as-callback/built/index.js | 41 + .../standard-as-callback/built/types.d.ts | 1 + .../standard-as-callback/built/types.js | 2 + .../standard-as-callback/built/utils.d.ts | 9 + .../standard-as-callback/built/utils.js | 23 + .../standard-as-callback/package.json | 40 + backend/package-lock.json | 121 + backend/package.json | 16 +- backend/server.js | 25 +- backend/src/config/redis.js | 12 + backend/src/jobs/gps.job.js | 29 + backend/src/services/simulator.service.js | 179 + 280 files changed, 30733 insertions(+), 11 deletions(-) create mode 100644 backend/env create mode 100644 backend/node_modules/@ioredis/commands/LICENSE create mode 100644 backend/node_modules/@ioredis/commands/README.md create mode 100644 backend/node_modules/@ioredis/commands/built/commands.json create mode 100644 backend/node_modules/@ioredis/commands/built/index.d.ts create mode 100644 backend/node_modules/@ioredis/commands/built/index.js create mode 100644 backend/node_modules/@ioredis/commands/package.json create mode 100644 backend/node_modules/cluster-key-slot/.eslintrc create mode 100644 backend/node_modules/cluster-key-slot/LICENSE create mode 100644 backend/node_modules/cluster-key-slot/README.md create mode 100644 backend/node_modules/cluster-key-slot/index.d.ts create mode 100644 backend/node_modules/cluster-key-slot/lib/index.js create mode 100644 backend/node_modules/cluster-key-slot/package.json create mode 100644 backend/node_modules/denque/CHANGELOG.md create mode 100644 backend/node_modules/denque/LICENSE create mode 100644 backend/node_modules/denque/README.md create mode 100644 backend/node_modules/denque/index.d.ts create mode 100644 backend/node_modules/denque/index.js create mode 100644 backend/node_modules/denque/package.json create mode 100644 backend/node_modules/ioredis/LICENSE create mode 100644 backend/node_modules/ioredis/README.md create mode 100644 backend/node_modules/ioredis/built/Command.d.ts create mode 100644 backend/node_modules/ioredis/built/Command.js create mode 100644 backend/node_modules/ioredis/built/DataHandler.d.ts create mode 100644 backend/node_modules/ioredis/built/DataHandler.js create mode 100644 backend/node_modules/ioredis/built/Pipeline.d.ts create mode 100644 backend/node_modules/ioredis/built/Pipeline.js create mode 100644 backend/node_modules/ioredis/built/Redis.d.ts create mode 100644 backend/node_modules/ioredis/built/Redis.js create mode 100644 backend/node_modules/ioredis/built/ScanStream.d.ts create mode 100644 backend/node_modules/ioredis/built/ScanStream.js create mode 100644 backend/node_modules/ioredis/built/Script.d.ts create mode 100644 backend/node_modules/ioredis/built/Script.js create mode 100644 backend/node_modules/ioredis/built/SubscriptionSet.d.ts create mode 100644 backend/node_modules/ioredis/built/SubscriptionSet.js create mode 100644 backend/node_modules/ioredis/built/autoPipelining.d.ts create mode 100644 backend/node_modules/ioredis/built/autoPipelining.js create mode 100644 backend/node_modules/ioredis/built/cluster/ClusterOptions.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/ClusterOptions.js create mode 100644 backend/node_modules/ioredis/built/cluster/ClusterSubscriber.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/ClusterSubscriber.js create mode 100644 backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.js create mode 100644 backend/node_modules/ioredis/built/cluster/ConnectionPool.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/ConnectionPool.js create mode 100644 backend/node_modules/ioredis/built/cluster/DelayQueue.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/DelayQueue.js create mode 100644 backend/node_modules/ioredis/built/cluster/ShardedSubscriber.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/ShardedSubscriber.js create mode 100644 backend/node_modules/ioredis/built/cluster/index.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/index.js create mode 100644 backend/node_modules/ioredis/built/cluster/util.d.ts create mode 100644 backend/node_modules/ioredis/built/cluster/util.js create mode 100644 backend/node_modules/ioredis/built/connectors/AbstractConnector.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/AbstractConnector.js create mode 100644 backend/node_modules/ioredis/built/connectors/ConnectorConstructor.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/ConnectorConstructor.js create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.js create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.js create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/index.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/index.js create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/types.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/SentinelConnector/types.js create mode 100644 backend/node_modules/ioredis/built/connectors/StandaloneConnector.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/StandaloneConnector.js create mode 100644 backend/node_modules/ioredis/built/connectors/index.d.ts create mode 100644 backend/node_modules/ioredis/built/connectors/index.js create mode 100644 backend/node_modules/ioredis/built/constants/TLSProfiles.d.ts create mode 100644 backend/node_modules/ioredis/built/constants/TLSProfiles.js create mode 100644 backend/node_modules/ioredis/built/errors/ClusterAllFailedError.d.ts create mode 100644 backend/node_modules/ioredis/built/errors/ClusterAllFailedError.js create mode 100644 backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.d.ts create mode 100644 backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.js create mode 100644 backend/node_modules/ioredis/built/errors/index.d.ts create mode 100644 backend/node_modules/ioredis/built/errors/index.js create mode 100644 backend/node_modules/ioredis/built/index.d.ts create mode 100644 backend/node_modules/ioredis/built/index.js create mode 100644 backend/node_modules/ioredis/built/redis/RedisOptions.d.ts create mode 100644 backend/node_modules/ioredis/built/redis/RedisOptions.js create mode 100644 backend/node_modules/ioredis/built/redis/event_handler.d.ts create mode 100644 backend/node_modules/ioredis/built/redis/event_handler.js create mode 100644 backend/node_modules/ioredis/built/transaction.d.ts create mode 100644 backend/node_modules/ioredis/built/transaction.js create mode 100644 backend/node_modules/ioredis/built/types.d.ts create mode 100644 backend/node_modules/ioredis/built/types.js create mode 100644 backend/node_modules/ioredis/built/utils/Commander.d.ts create mode 100644 backend/node_modules/ioredis/built/utils/Commander.js create mode 100644 backend/node_modules/ioredis/built/utils/RedisCommander.d.ts create mode 100644 backend/node_modules/ioredis/built/utils/RedisCommander.js create mode 100644 backend/node_modules/ioredis/built/utils/applyMixin.d.ts create mode 100644 backend/node_modules/ioredis/built/utils/applyMixin.js create mode 100644 backend/node_modules/ioredis/built/utils/argumentParsers.d.ts create mode 100644 backend/node_modules/ioredis/built/utils/argumentParsers.js create mode 100644 backend/node_modules/ioredis/built/utils/debug.d.ts create mode 100644 backend/node_modules/ioredis/built/utils/debug.js create mode 100644 backend/node_modules/ioredis/built/utils/index.d.ts create mode 100644 backend/node_modules/ioredis/built/utils/index.js create mode 100644 backend/node_modules/ioredis/built/utils/lodash.d.ts create mode 100644 backend/node_modules/ioredis/built/utils/lodash.js create mode 100644 backend/node_modules/ioredis/node_modules/debug/LICENSE create mode 100644 backend/node_modules/ioredis/node_modules/debug/README.md create mode 100644 backend/node_modules/ioredis/node_modules/debug/package.json create mode 100644 backend/node_modules/ioredis/node_modules/debug/src/browser.js create mode 100644 backend/node_modules/ioredis/node_modules/debug/src/common.js create mode 100644 backend/node_modules/ioredis/node_modules/debug/src/index.js create mode 100644 backend/node_modules/ioredis/node_modules/debug/src/node.js create mode 100644 backend/node_modules/ioredis/node_modules/ms/index.js create mode 100644 backend/node_modules/ioredis/node_modules/ms/license.md create mode 100644 backend/node_modules/ioredis/node_modules/ms/package.json create mode 100644 backend/node_modules/ioredis/node_modules/ms/readme.md create mode 100644 backend/node_modules/ioredis/package.json create mode 100644 backend/node_modules/lodash.defaults/LICENSE create mode 100644 backend/node_modules/lodash.defaults/README.md create mode 100644 backend/node_modules/lodash.defaults/index.js create mode 100644 backend/node_modules/lodash.defaults/package.json create mode 100644 backend/node_modules/lodash.isarguments/LICENSE create mode 100644 backend/node_modules/lodash.isarguments/README.md create mode 100644 backend/node_modules/lodash.isarguments/index.js create mode 100644 backend/node_modules/lodash.isarguments/package.json create mode 100644 backend/node_modules/node-cron/LICENSE.md create mode 100644 backend/node_modules/node-cron/README.md create mode 100644 backend/node_modules/node-cron/dist/cjs/create-id.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/create-id.js create mode 100644 backend/node_modules/node-cron/dist/cjs/create-id.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/logger.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/logger.js create mode 100644 backend/node_modules/node-cron/dist/cjs/logger.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/node-cron.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/node-cron.js create mode 100644 backend/node_modules/node-cron/dist/cjs/node-cron.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js create mode 100644 backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js create mode 100644 backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/scheduler/runner.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/scheduler/runner.js create mode 100644 backend/node_modules/node-cron/dist/cjs/scheduler/runner.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/task-registry.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/task-registry.js create mode 100644 backend/node_modules/node-cron/dist/cjs/task-registry.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/state-machine.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js create mode 100644 backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/time/localized-time.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/time/localized-time.js create mode 100644 backend/node_modules/node-cron/dist/cjs/time/localized-time.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/time/matcher-walker.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js create mode 100644 backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js.map create mode 100644 backend/node_modules/node-cron/dist/cjs/time/time-matcher.d.ts create mode 100644 backend/node_modules/node-cron/dist/cjs/time/time-matcher.js create mode 100644 backend/node_modules/node-cron/dist/cjs/time/time-matcher.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/create-id.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/create-id.js create mode 100644 backend/node_modules/node-cron/dist/esm/create-id.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/logger.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/logger.js create mode 100644 backend/node_modules/node-cron/dist/esm/logger.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/node-cron.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/node-cron.js create mode 100644 backend/node_modules/node-cron/dist/esm/node-cron.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/index.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js create mode 100644 backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/promise/tracked-promise.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js create mode 100644 backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/scheduler/runner.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/scheduler/runner.js create mode 100644 backend/node_modules/node-cron/dist/esm/scheduler/runner.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/task-registry.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/task-registry.js create mode 100644 backend/node_modules/node-cron/dist/esm/task-registry.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/state-machine.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/state-machine.js create mode 100644 backend/node_modules/node-cron/dist/esm/tasks/state-machine.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/time/localized-time.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/time/localized-time.js create mode 100644 backend/node_modules/node-cron/dist/esm/time/localized-time.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/time/matcher-walker.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/time/matcher-walker.js create mode 100644 backend/node_modules/node-cron/dist/esm/time/matcher-walker.js.map create mode 100644 backend/node_modules/node-cron/dist/esm/time/time-matcher.d.ts create mode 100644 backend/node_modules/node-cron/dist/esm/time/time-matcher.js create mode 100644 backend/node_modules/node-cron/dist/esm/time/time-matcher.js.map create mode 100644 backend/node_modules/node-cron/package.json create mode 100644 backend/node_modules/redis-errors/.npmignore create mode 100644 backend/node_modules/redis-errors/LICENSE create mode 100644 backend/node_modules/redis-errors/README.md create mode 100644 backend/node_modules/redis-errors/index.js create mode 100644 backend/node_modules/redis-errors/lib/modern.js create mode 100644 backend/node_modules/redis-errors/lib/old.js create mode 100644 backend/node_modules/redis-errors/package.json create mode 100644 backend/node_modules/redis-parser/.npmignore create mode 100644 backend/node_modules/redis-parser/LICENSE create mode 100644 backend/node_modules/redis-parser/README.md create mode 100644 backend/node_modules/redis-parser/changelog.md create mode 100644 backend/node_modules/redis-parser/index.js create mode 100644 backend/node_modules/redis-parser/lib/parser.js create mode 100644 backend/node_modules/redis-parser/package.json create mode 100644 backend/node_modules/standard-as-callback/LICENSE create mode 100644 backend/node_modules/standard-as-callback/README.md create mode 100644 backend/node_modules/standard-as-callback/built/index.d.ts create mode 100644 backend/node_modules/standard-as-callback/built/index.js create mode 100644 backend/node_modules/standard-as-callback/built/types.d.ts create mode 100644 backend/node_modules/standard-as-callback/built/types.js create mode 100644 backend/node_modules/standard-as-callback/built/utils.d.ts create mode 100644 backend/node_modules/standard-as-callback/built/utils.js create mode 100644 backend/node_modules/standard-as-callback/package.json create mode 100644 backend/src/config/redis.js create mode 100644 backend/src/jobs/gps.job.js create mode 100644 backend/src/services/simulator.service.js diff --git a/backend/env b/backend/env new file mode 100644 index 0000000..52aebd1 --- /dev/null +++ b/backend/env @@ -0,0 +1,20 @@ +PORT=3000 +DB_HOST=localhost +DB_PORT=5433 +DB_NAME=recoleccion_db +DB_USER=recoleccion +DB_PASSWORD=recoleccion123 +REDIS_HOST=localhost +REDIS_PORT=6380 +JWT_SECRET=hackathon_celaya_2026_secret_key +JWT_EXPIRES_IN=7d + +# Simulador GPS +# TIME_MULTIPLIER: cuántos segundos simulados por segundo real +# 1 = tiempo real | 60 = demo (1 min real = 1 hora simulada) +TIME_MULTIPLIER=60 + +# CRON_SCHEDULE: cada cuánto corre el simulador +# '*/1 * * * *' = cada 1 minuto (recomendado) +# '*/30 * * * * *' = cada 30 segundos (más responsivo en demo) +CRON_SCHEDULE=*/1 * * * * diff --git a/backend/node_modules/.package-lock.json b/backend/node_modules/.package-lock.json index 6d3c064..9718b42 100644 --- a/backend/node_modules/.package-lock.json +++ b/backend/node_modules/.package-lock.json @@ -4,6 +4,12 @@ "lockfileVersion": 3, "requires": true, "packages": { + "node_modules/@ioredis/commands": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.1.tgz", + "integrity": "sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw==", + "license": "MIT" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -238,6 +244,15 @@ "fsevents": "~2.3.2" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -321,6 +336,15 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -782,6 +806,53 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ioredis": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.10.1.tgz", + "integrity": "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "1.5.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ioredis/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -886,12 +957,24 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", "license": "MIT" }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", @@ -1028,6 +1111,15 @@ "node": ">= 0.6" } }, + "node_modules/node-cron": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.2.1.tgz", + "integrity": "sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==", + "license": "ISC", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "3.1.14", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", @@ -1362,6 +1454,27 @@ "node": ">=8.10.0" } }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1545,6 +1658,12 @@ "node": ">= 10.x" } }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", diff --git a/backend/node_modules/@ioredis/commands/LICENSE b/backend/node_modules/@ioredis/commands/LICENSE new file mode 100644 index 0000000..8931fa9 --- /dev/null +++ b/backend/node_modules/@ioredis/commands/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2022 Zihua Li +Copyright (c) 2015 NodeRedis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/backend/node_modules/@ioredis/commands/README.md b/backend/node_modules/@ioredis/commands/README.md new file mode 100644 index 0000000..2649696 --- /dev/null +++ b/backend/node_modules/@ioredis/commands/README.md @@ -0,0 +1,43 @@ +# Redis Commands + +This module exports all the commands that Redis supports. + +## Install + +```shell +$ npm install @ioredis/commands +``` + +## Usage + +```js +const commands = require('@ioredis/commands'); +``` + +`.list` is an array contains all the lowercased commands: + +```js +commands.list.forEach((command) => { + console.log(command); +}); +``` + +`.exists()` is used to check if the command exists: + +```js +commands.exists('set') // true +commands.exists('other-command') // false +``` + +`.hasFlag()` is used to check if the command has the flag: + +```js +commands.hasFlag('set', 'readonly') // false +``` + +`.getKeyIndexes()` is used to get the indexes of keys in the command arguments: + +```js +commands.getKeyIndexes('set', ['key', 'value']) // [0] +commands.getKeyIndexes('mget', ['key1', 'key2']) // [0, 1] +``` diff --git a/backend/node_modules/@ioredis/commands/built/commands.json b/backend/node_modules/@ioredis/commands/built/commands.json new file mode 100644 index 0000000..4004701 --- /dev/null +++ b/backend/node_modules/@ioredis/commands/built/commands.json @@ -0,0 +1,2578 @@ +{ + "acl": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "append": { + "arity": 3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "asking": { + "arity": 1, + "flags": [ + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "auth": { + "arity": -2, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "no_auth", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "bgrewriteaof": { + "arity": 1, + "flags": [ + "admin", + "noscript", + "no_async_loading" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "bgsave": { + "arity": -1, + "flags": [ + "admin", + "noscript", + "no_async_loading" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "bitcount": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "bitfield": { + "arity": -2, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "bitfield_ro": { + "arity": -2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "bitop": { + "arity": -4, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 2, + "keyStop": -1, + "step": 1 + }, + "bitpos": { + "arity": -3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "blmove": { + "arity": 6, + "flags": [ + "write", + "denyoom", + "noscript", + "blocking" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "blmpop": { + "arity": -5, + "flags": [ + "write", + "blocking", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "blpop": { + "arity": -3, + "flags": [ + "write", + "noscript", + "blocking" + ], + "keyStart": 1, + "keyStop": -2, + "step": 1 + }, + "brpop": { + "arity": -3, + "flags": [ + "write", + "noscript", + "blocking" + ], + "keyStart": 1, + "keyStop": -2, + "step": 1 + }, + "brpoplpush": { + "arity": 4, + "flags": [ + "write", + "denyoom", + "noscript", + "blocking" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "bzmpop": { + "arity": -5, + "flags": [ + "write", + "blocking", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "bzpopmax": { + "arity": -3, + "flags": [ + "write", + "noscript", + "blocking", + "fast" + ], + "keyStart": 1, + "keyStop": -2, + "step": 1 + }, + "bzpopmin": { + "arity": -3, + "flags": [ + "write", + "noscript", + "blocking", + "fast" + ], + "keyStart": 1, + "keyStop": -2, + "step": 1 + }, + "client": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "cluster": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "command": { + "arity": -1, + "flags": [ + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "config": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "copy": { + "arity": -3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "dbsize": { + "arity": 1, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "debug": { + "arity": -2, + "flags": [ + "admin", + "noscript", + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "decr": { + "arity": 2, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "decrby": { + "arity": 3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "del": { + "arity": -2, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "discard": { + "arity": 1, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "dump": { + "arity": 2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "echo": { + "arity": 2, + "flags": [ + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "eval": { + "arity": -3, + "flags": [ + "noscript", + "stale", + "skip_monitor", + "no_mandatory_keys", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "eval_ro": { + "arity": -3, + "flags": [ + "readonly", + "noscript", + "stale", + "skip_monitor", + "no_mandatory_keys", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "evalsha": { + "arity": -3, + "flags": [ + "noscript", + "stale", + "skip_monitor", + "no_mandatory_keys", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "evalsha_ro": { + "arity": -3, + "flags": [ + "readonly", + "noscript", + "stale", + "skip_monitor", + "no_mandatory_keys", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "exec": { + "arity": 1, + "flags": [ + "noscript", + "loading", + "stale", + "skip_slowlog" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "exists": { + "arity": -2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "expire": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "expireat": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "expiretime": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "failover": { + "arity": -1, + "flags": [ + "admin", + "noscript", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "fcall": { + "arity": -3, + "flags": [ + "noscript", + "stale", + "skip_monitor", + "no_mandatory_keys", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "fcall_ro": { + "arity": -3, + "flags": [ + "readonly", + "noscript", + "stale", + "skip_monitor", + "no_mandatory_keys", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "flushall": { + "arity": -1, + "flags": [ + "write" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "flushdb": { + "arity": -1, + "flags": [ + "write" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "function": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "geoadd": { + "arity": -5, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "geodist": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "geohash": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "geopos": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "georadius": { + "arity": -6, + "flags": [ + "write", + "denyoom", + "movablekeys" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "georadius_ro": { + "arity": -6, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "georadiusbymember": { + "arity": -5, + "flags": [ + "write", + "denyoom", + "movablekeys" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "georadiusbymember_ro": { + "arity": -5, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "geosearch": { + "arity": -7, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "geosearchstore": { + "arity": -8, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "get": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "getbit": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "getdel": { + "arity": 2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "getex": { + "arity": -2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "getrange": { + "arity": 4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "getset": { + "arity": 3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hdel": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hello": { + "arity": -1, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "no_auth", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "hexists": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hexpire": { + "arity": -6, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hexpireat": { + "arity": -6, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hexpiretime": { + "arity": -5, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hget": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hgetall": { + "arity": 2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hgetdel": { + "arity": -5, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hgetex": { + "arity": -5, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hincrby": { + "arity": 4, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hincrbyfloat": { + "arity": 4, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hkeys": { + "arity": 2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hlen": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hmget": { + "arity": -3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hmset": { + "arity": -4, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hpersist": { + "arity": -5, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hpexpire": { + "arity": -6, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hpexpireat": { + "arity": -6, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hpexpiretime": { + "arity": -5, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hpttl": { + "arity": -5, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hrandfield": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hscan": { + "arity": -3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hset": { + "arity": -4, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hsetex": { + "arity": -6, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hsetnx": { + "arity": 4, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hstrlen": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "httl": { + "arity": -5, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "hvals": { + "arity": 2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "incr": { + "arity": 2, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "incrby": { + "arity": 3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "incrbyfloat": { + "arity": 3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "info": { + "arity": -1, + "flags": [ + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "keys": { + "arity": 2, + "flags": [ + "readonly" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "lastsave": { + "arity": 1, + "flags": [ + "loading", + "stale", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "latency": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "lcs": { + "arity": -3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "lindex": { + "arity": 3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "linsert": { + "arity": 5, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "llen": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "lmove": { + "arity": 5, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "lmpop": { + "arity": -4, + "flags": [ + "write", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "lolwut": { + "arity": -1, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "lpop": { + "arity": -2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "lpos": { + "arity": -3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "lpush": { + "arity": -3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "lpushx": { + "arity": -3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "lrange": { + "arity": 4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "lrem": { + "arity": 4, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "lset": { + "arity": 4, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "ltrim": { + "arity": 4, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "memory": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "mget": { + "arity": -2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "migrate": { + "arity": -6, + "flags": [ + "write", + "movablekeys" + ], + "keyStart": 3, + "keyStop": 3, + "step": 1 + }, + "module": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "monitor": { + "arity": 1, + "flags": [ + "admin", + "noscript", + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "move": { + "arity": 3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "mset": { + "arity": -3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": -1, + "step": 2 + }, + "msetnx": { + "arity": -3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": -1, + "step": 2 + }, + "multi": { + "arity": 1, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "object": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "persist": { + "arity": 2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "pexpire": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "pexpireat": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "pexpiretime": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "pfadd": { + "arity": -2, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "pfcount": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "pfdebug": { + "arity": 3, + "flags": [ + "write", + "denyoom", + "admin" + ], + "keyStart": 2, + "keyStop": 2, + "step": 1 + }, + "pfmerge": { + "arity": -2, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "pfselftest": { + "arity": 1, + "flags": [ + "admin" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "ping": { + "arity": -1, + "flags": [ + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "psetex": { + "arity": 4, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "psubscribe": { + "arity": -2, + "flags": [ + "pubsub", + "noscript", + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "psync": { + "arity": -3, + "flags": [ + "admin", + "noscript", + "no_async_loading", + "no_multi" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "pttl": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "publish": { + "arity": 3, + "flags": [ + "pubsub", + "loading", + "stale", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "pubsub": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "punsubscribe": { + "arity": -1, + "flags": [ + "pubsub", + "noscript", + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "quit": { + "arity": -1, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "no_auth", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "randomkey": { + "arity": 1, + "flags": [ + "readonly" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "readonly": { + "arity": 1, + "flags": [ + "loading", + "stale", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "readwrite": { + "arity": 1, + "flags": [ + "loading", + "stale", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "rename": { + "arity": 3, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "renamenx": { + "arity": 3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "replconf": { + "arity": -1, + "flags": [ + "admin", + "noscript", + "loading", + "stale", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "replicaof": { + "arity": 3, + "flags": [ + "admin", + "noscript", + "stale", + "no_async_loading" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "reset": { + "arity": 1, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "no_auth", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "restore": { + "arity": -4, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "restore-asking": { + "arity": -4, + "flags": [ + "write", + "denyoom", + "asking" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "role": { + "arity": 1, + "flags": [ + "noscript", + "loading", + "stale", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "rpop": { + "arity": -2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "rpoplpush": { + "arity": 3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "rpush": { + "arity": -3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "rpushx": { + "arity": -3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "sadd": { + "arity": -3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "save": { + "arity": 1, + "flags": [ + "admin", + "noscript", + "no_async_loading", + "no_multi" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "scan": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "scard": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "script": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "sdiff": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "sdiffstore": { + "arity": -3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "select": { + "arity": 2, + "flags": [ + "loading", + "stale", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "set": { + "arity": -3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "setbit": { + "arity": 4, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "setex": { + "arity": 4, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "setnx": { + "arity": 3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "setrange": { + "arity": 4, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "shutdown": { + "arity": -1, + "flags": [ + "admin", + "noscript", + "loading", + "stale", + "no_multi", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "sinter": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "sintercard": { + "arity": -3, + "flags": [ + "readonly", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "sinterstore": { + "arity": -3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "sismember": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "slaveof": { + "arity": 3, + "flags": [ + "admin", + "noscript", + "stale", + "no_async_loading" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "slowlog": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "smembers": { + "arity": 2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "smismember": { + "arity": -3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "smove": { + "arity": 4, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "sort": { + "arity": -2, + "flags": [ + "write", + "denyoom", + "movablekeys" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "sort_ro": { + "arity": -2, + "flags": [ + "readonly", + "movablekeys" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "spop": { + "arity": -2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "spublish": { + "arity": 3, + "flags": [ + "pubsub", + "loading", + "stale", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "srandmember": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "srem": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "sscan": { + "arity": -3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "ssubscribe": { + "arity": -2, + "flags": [ + "pubsub", + "noscript", + "loading", + "stale" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "strlen": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "subscribe": { + "arity": -2, + "flags": [ + "pubsub", + "noscript", + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "substr": { + "arity": 4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "sunion": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "sunionstore": { + "arity": -3, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "sunsubscribe": { + "arity": -1, + "flags": [ + "pubsub", + "noscript", + "loading", + "stale" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "swapdb": { + "arity": 3, + "flags": [ + "write", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "sync": { + "arity": 1, + "flags": [ + "admin", + "noscript", + "no_async_loading", + "no_multi" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "time": { + "arity": 1, + "flags": [ + "loading", + "stale", + "fast" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "touch": { + "arity": -2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "ttl": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "type": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "unlink": { + "arity": -2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "unsubscribe": { + "arity": -1, + "flags": [ + "pubsub", + "noscript", + "loading", + "stale" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "unwatch": { + "arity": 1, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "allow_busy" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "wait": { + "arity": 3, + "flags": [ + "noscript" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "watch": { + "arity": -2, + "flags": [ + "noscript", + "loading", + "stale", + "fast", + "allow_busy" + ], + "keyStart": 1, + "keyStop": -1, + "step": 1 + }, + "xack": { + "arity": -4, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xadd": { + "arity": -5, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xautoclaim": { + "arity": -6, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xclaim": { + "arity": -6, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xdel": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xdelex": { + "arity": -5, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xgroup": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "xinfo": { + "arity": -2, + "flags": [], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "xlen": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xpending": { + "arity": -3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xrange": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xread": { + "arity": -4, + "flags": [ + "readonly", + "blocking", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "xreadgroup": { + "arity": -7, + "flags": [ + "write", + "blocking", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "xrevrange": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xsetid": { + "arity": -3, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "xtrim": { + "arity": -4, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zadd": { + "arity": -4, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zcard": { + "arity": 2, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zcount": { + "arity": 4, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zdiff": { + "arity": -3, + "flags": [ + "readonly", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "zdiffstore": { + "arity": -4, + "flags": [ + "write", + "denyoom", + "movablekeys" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zincrby": { + "arity": 4, + "flags": [ + "write", + "denyoom", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zinter": { + "arity": -3, + "flags": [ + "readonly", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "zintercard": { + "arity": -3, + "flags": [ + "readonly", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "zinterstore": { + "arity": -4, + "flags": [ + "write", + "denyoom", + "movablekeys" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zlexcount": { + "arity": 4, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zmpop": { + "arity": -4, + "flags": [ + "write", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "zmscore": { + "arity": -3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zpopmax": { + "arity": -2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zpopmin": { + "arity": -2, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrandmember": { + "arity": -2, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrange": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrangebylex": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrangebyscore": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrangestore": { + "arity": -5, + "flags": [ + "write", + "denyoom" + ], + "keyStart": 1, + "keyStop": 2, + "step": 1 + }, + "zrank": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrem": { + "arity": -3, + "flags": [ + "write", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zremrangebylex": { + "arity": 4, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zremrangebyrank": { + "arity": 4, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zremrangebyscore": { + "arity": 4, + "flags": [ + "write" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrevrange": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrevrangebylex": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrevrangebyscore": { + "arity": -4, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zrevrank": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zscan": { + "arity": -3, + "flags": [ + "readonly" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zscore": { + "arity": 3, + "flags": [ + "readonly", + "fast" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + }, + "zunion": { + "arity": -3, + "flags": [ + "readonly", + "movablekeys" + ], + "keyStart": 0, + "keyStop": 0, + "step": 0 + }, + "zunionstore": { + "arity": -4, + "flags": [ + "write", + "denyoom", + "movablekeys" + ], + "keyStart": 1, + "keyStop": 1, + "step": 1 + } +} diff --git a/backend/node_modules/@ioredis/commands/built/index.d.ts b/backend/node_modules/@ioredis/commands/built/index.d.ts new file mode 100644 index 0000000..94506a2 --- /dev/null +++ b/backend/node_modules/@ioredis/commands/built/index.d.ts @@ -0,0 +1,34 @@ +/// +/** + * Redis command list + * + * All commands are lowercased. + */ +export declare const list: string[]; +/** + * Check if the command exists + */ +export declare function exists(commandName: string, options?: { + caseInsensitive?: boolean; +}): boolean; +/** + * Check if the command has the flag + * + * Some of possible flags: readonly, noscript, loading + */ +export declare function hasFlag(commandName: string, flag: string, options?: { + nameCaseInsensitive?: boolean; +}): boolean; +/** + * Get indexes of keys in the command arguments + * + * @example + * ```javascript + * getKeyIndexes('set', ['key', 'value']) // [0] + * getKeyIndexes('mget', ['key1', 'key2']) // [0, 1] + * ``` + */ +export declare function getKeyIndexes(commandName: string, args: (string | Buffer | number)[], options?: { + parseExternalKey?: boolean; + nameCaseInsensitive?: boolean; +}): number[]; diff --git a/backend/node_modules/@ioredis/commands/built/index.js b/backend/node_modules/@ioredis/commands/built/index.js new file mode 100644 index 0000000..c0e9b2f --- /dev/null +++ b/backend/node_modules/@ioredis/commands/built/index.js @@ -0,0 +1,217 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getKeyIndexes = exports.hasFlag = exports.exists = exports.list = void 0; +const commands_json_1 = __importDefault(require("./commands.json")); +/** + * Redis command list + * + * All commands are lowercased. + */ +exports.list = Object.keys(commands_json_1.default); +const flags = {}; +exports.list.forEach((commandName) => { + flags[commandName] = commands_json_1.default[commandName].flags.reduce(function (flags, flag) { + flags[flag] = true; + return flags; + }, {}); +}); +/** + * Check if the command exists + */ +function exists(commandName, options) { + commandName = (options === null || options === void 0 ? void 0 : options.caseInsensitive) + ? String(commandName).toLowerCase() + : commandName; + return Boolean(commands_json_1.default[commandName]); +} +exports.exists = exists; +/** + * Check if the command has the flag + * + * Some of possible flags: readonly, noscript, loading + */ +function hasFlag(commandName, flag, options) { + commandName = (options === null || options === void 0 ? void 0 : options.nameCaseInsensitive) + ? String(commandName).toLowerCase() + : commandName; + if (!flags[commandName]) { + throw new Error("Unknown command " + commandName); + } + return Boolean(flags[commandName][flag]); +} +exports.hasFlag = hasFlag; +/** + * Get indexes of keys in the command arguments + * + * @example + * ```javascript + * getKeyIndexes('set', ['key', 'value']) // [0] + * getKeyIndexes('mget', ['key1', 'key2']) // [0, 1] + * ``` + */ +function getKeyIndexes(commandName, args, options) { + commandName = (options === null || options === void 0 ? void 0 : options.nameCaseInsensitive) + ? String(commandName).toLowerCase() + : commandName; + const command = commands_json_1.default[commandName]; + if (!command) { + throw new Error("Unknown command " + commandName); + } + if (!Array.isArray(args)) { + throw new Error("Expect args to be an array"); + } + const keys = []; + const parseExternalKey = Boolean(options && options.parseExternalKey); + const takeDynamicKeys = (args, startIndex) => { + const keys = []; + const keyStop = Number(args[startIndex]); + for (let i = 0; i < keyStop; i++) { + keys.push(i + startIndex + 1); + } + return keys; + }; + const takeKeyAfterToken = (args, startIndex, token) => { + for (let i = startIndex; i < args.length - 1; i += 1) { + if (String(args[i]).toLowerCase() === token.toLowerCase()) { + return i + 1; + } + } + return null; + }; + switch (commandName) { + case "zunionstore": + case "zinterstore": + case "zdiffstore": + keys.push(0, ...takeDynamicKeys(args, 1)); + break; + case "eval": + case "evalsha": + case "eval_ro": + case "evalsha_ro": + case "fcall": + case "fcall_ro": + case "blmpop": + case "bzmpop": + keys.push(...takeDynamicKeys(args, 1)); + break; + case "sintercard": + case "lmpop": + case "zunion": + case "zinter": + case "zmpop": + case "zintercard": + case "zdiff": { + keys.push(...takeDynamicKeys(args, 0)); + break; + } + case "georadius": { + keys.push(0); + const storeKey = takeKeyAfterToken(args, 5, "STORE"); + if (storeKey) + keys.push(storeKey); + const distKey = takeKeyAfterToken(args, 5, "STOREDIST"); + if (distKey) + keys.push(distKey); + break; + } + case "georadiusbymember": { + keys.push(0); + const storeKey = takeKeyAfterToken(args, 4, "STORE"); + if (storeKey) + keys.push(storeKey); + const distKey = takeKeyAfterToken(args, 4, "STOREDIST"); + if (distKey) + keys.push(distKey); + break; + } + case "sort": + case "sort_ro": + keys.push(0); + for (let i = 1; i < args.length - 1; i++) { + let arg = args[i]; + if (typeof arg !== "string") { + continue; + } + const directive = arg.toUpperCase(); + if (directive === "GET") { + i += 1; + arg = args[i]; + if (arg !== "#") { + if (parseExternalKey) { + keys.push([i, getExternalKeyNameLength(arg)]); + } + else { + keys.push(i); + } + } + } + else if (directive === "BY") { + i += 1; + if (parseExternalKey) { + keys.push([i, getExternalKeyNameLength(args[i])]); + } + else { + keys.push(i); + } + } + else if (directive === "STORE") { + i += 1; + keys.push(i); + } + } + break; + case "migrate": + if (args[2] === "") { + for (let i = 5; i < args.length - 1; i++) { + const arg = args[i]; + if (typeof arg === "string" && arg.toUpperCase() === "KEYS") { + for (let j = i + 1; j < args.length; j++) { + keys.push(j); + } + break; + } + } + } + else { + keys.push(2); + } + break; + case "xreadgroup": + case "xread": + // Keys are 1st half of the args after STREAMS argument. + for (let i = commandName === "xread" ? 0 : 3; i < args.length - 1; i++) { + if (String(args[i]).toUpperCase() === "STREAMS") { + for (let j = i + 1; j <= i + (args.length - 1 - i) / 2; j++) { + keys.push(j); + } + break; + } + } + break; + default: + // Step has to be at least one in this case, otherwise the command does + // not contain a key. + if (command.step > 0) { + const keyStart = command.keyStart - 1; + const keyStop = command.keyStop > 0 + ? command.keyStop + : args.length + command.keyStop + 1; + for (let i = keyStart; i < keyStop; i += command.step) { + keys.push(i); + } + } + break; + } + return keys; +} +exports.getKeyIndexes = getKeyIndexes; +function getExternalKeyNameLength(key) { + if (typeof key !== "string") { + key = String(key); + } + const hashPos = key.indexOf("->"); + return hashPos === -1 ? key.length : hashPos; +} diff --git a/backend/node_modules/@ioredis/commands/package.json b/backend/node_modules/@ioredis/commands/package.json new file mode 100644 index 0000000..c60e19a --- /dev/null +++ b/backend/node_modules/@ioredis/commands/package.json @@ -0,0 +1,52 @@ +{ + "name": "@ioredis/commands", + "version": "1.5.1", + "description": "Redis commands", + "main": "built/index.js", + "files": [ + "built/", + "commands.json" + ], + "scripts": { + "pretest": "npm run lint", + "test": "mocha", + "build": "rm -rf built && tsc", + "gen": "node tools/build", + "lint": "standard --fix --verbose | snazzy", + "release": "release-it" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "repository": { + "type": "git", + "url": "https://github.com/ioredis/commands.git" + }, + "keywords": [ + "redis", + "commands", + "prefix" + ], + "author": "Zihua Li (http://zihua.li)", + "license": "MIT", + "bugs": { + "url": "https://github.com/ioredis/commands/issues" + }, + "homepage": "https://github.com/ioredis/commands", + "devDependencies": { + "@release-it/conventional-changelog": "^4.2.0", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/commit-analyzer": "^9.0.2", + "@semantic-release/git": "^10.0.1", + "chai": "^4.3.6", + "ioredis": "^5.0.6", + "mocha": "^9.2.1", + "release-it": "^14.12.5", + "safe-stable-stringify": "^2.3.1", + "semantic-release": "^19.0.2", + "snazzy": "^9.0.0", + "standard": "^16.0.4", + "typescript": "^4.6.2" + } +} diff --git a/backend/node_modules/cluster-key-slot/.eslintrc b/backend/node_modules/cluster-key-slot/.eslintrc new file mode 100644 index 0000000..3ee8296 --- /dev/null +++ b/backend/node_modules/cluster-key-slot/.eslintrc @@ -0,0 +1,16 @@ +{ + "extends": "airbnb-base/legacy", + "parserOptions":{ + "ecmaFeatures": { + "experimentalObjectRestSpread": true + } + }, + "rules": { + "max-len": 0, + "no-plusplus": 0, + "no-bitwise": 0, + "no-param-reassign": 0, + "no-undef": 0 + }, + "globals": {} +} diff --git a/backend/node_modules/cluster-key-slot/LICENSE b/backend/node_modules/cluster-key-slot/LICENSE new file mode 100644 index 0000000..fd22a2d --- /dev/null +++ b/backend/node_modules/cluster-key-slot/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2018 Mike Diarmid (Salakar) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this library except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/backend/node_modules/cluster-key-slot/README.md b/backend/node_modules/cluster-key-slot/README.md new file mode 100644 index 0000000..440f7b1 --- /dev/null +++ b/backend/node_modules/cluster-key-slot/README.md @@ -0,0 +1,61 @@ +[![Coverage Status](https://coveralls.io/repos/github/Salakar/cluster-key-slot/badge.svg?branch=master)](https://coveralls.io/github/Salakar/cluster-key-slot?branch=master) +![Downloads](https://img.shields.io/npm/dt/cluster-key-slot.svg) +[![npm version](https://img.shields.io/npm/v/cluster-key-slot.svg)](https://www.npmjs.com/package/cluster-key-slot) +[![dependencies](https://img.shields.io/david/Salakar/cluster-key-slot.svg)](https://david-dm.org/Salakar/cluster-key-slot) +[![License](https://img.shields.io/npm/l/cluster-key-slot.svg)](/LICENSE) +Follow on Twitter + +# Redis Key Slot Calculator + +A high performance redis cluster key slot calculator for node redis clients e.g. [node_redis](https://github.com/NodeRedis/node_redis), [ioredis](https://github.com/luin/ioredis) and [redis-clustr](https://github.com/gosquared/redis-clustr/). + +This also handles key tags such as `somekey{actualTag}`. + +## Install + +Install with [NPM](https://npmjs.org/): + +``` +npm install cluster-key-slot --save +``` + +## Usage + +```js +const calculateSlot = require('cluster-key-slot'); +const calculateMultipleSlots = require('cluster-key-slot').generateMulti; + +// ... + +// a single slot number +const slot = calculateSlot('test:key:{butOnlyThis}redis'); +// Buffer is also supported +const anotherSlot = calculateSlot(Buffer.from([0x7b, 0x7d, 0x2a])); + +// multiple keys - multi returns a single key slot number, returns -1 if any +// of the keys does not match the base slot number (base is defaulted to first keys slot) +// This is useful to quickly determine a singe slot for multi keys operations. +const slotForRedisMulti = calculateMultipleSlots([ + 'test:key:{butOnlyThis}redis', + 'something:key45:{butOnlyThis}hello', + 'example:key46:{butOnlyThis}foobar', +]); +``` + +## Benchmarks + +`OLD` in these benchmarks refers to the `ioredis` crc calc and many of the other calculators that use `Buffer`. + +```text +node -v  ✔  16.38G RAM  10:29:07 +v10.15.3 + +NEW tags x 721,445 ops/sec ±0.44% (90 runs sampled) +OLD tags x 566,777 ops/sec ±0.97% (96 runs sampled) +NEW without tags x 2,054,845 ops/sec ±1.77% (92 runs sampled) +OLD without tags x 865,839 ops/sec ±0.43% (96 runs sampled) +NEW without tags singular x 6,354,097 ops/sec ±1.25% (94 runs sampled) +OLD without tags singular x 4,012,250 ops/sec ±0.96% (94 runs sampled) +NEW tags (Buffer) x 552,346 ops/sec ±1.35% (92 runs sampled) +``` + diff --git a/backend/node_modules/cluster-key-slot/index.d.ts b/backend/node_modules/cluster-key-slot/index.d.ts new file mode 100644 index 0000000..1713b44 --- /dev/null +++ b/backend/node_modules/cluster-key-slot/index.d.ts @@ -0,0 +1,10 @@ +declare module 'cluster-key-slot' { + // Convert a string or Buffer into a redis slot hash. + function calculate(value: string | Buffer): number; + + // Convert an array of multiple strings or Buffers into a redis slot hash. + // Returns -1 if one of the keys is not for the same slot as the others + export function generateMulti(values: Array): number; + + export = calculate; +} \ No newline at end of file diff --git a/backend/node_modules/cluster-key-slot/lib/index.js b/backend/node_modules/cluster-key-slot/lib/index.js new file mode 100644 index 0000000..7928c77 --- /dev/null +++ b/backend/node_modules/cluster-key-slot/lib/index.js @@ -0,0 +1,166 @@ +/* + * Copyright 2001-2010 Georges Menie (www.menie.org) + * Copyright 2010 Salvatore Sanfilippo (adapted to Redis coding style) + * Copyright 2015 Zihua Li (http://zihua.li) (ported to JavaScript) + * Copyright 2016 Mike Diarmid (http://github.com/salakar) (re-write for performance, ~700% perf inc) + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* CRC16 implementation according to CCITT standards. + * + * Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the + * following parameters: + * + * Name : "XMODEM", also known as "ZMODEM", "CRC-16/ACORN" + * Width : 16 bit + * Poly : 1021 (That is actually x^16 + x^12 + x^5 + 1) + * Initialization : 0000 + * Reflect Input byte : False + * Reflect Output CRC : False + * Xor constant to output CRC : 0000 + * Output for "123456789" : 31C3 + */ + +var lookup = [ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +]; + +/** + * Convert a string to a UTF8 array - faster than via buffer + * @param str + * @returns {Array} + */ +var toUTF8Array = function toUTF8Array(str) { + var char; + var i = 0; + var p = 0; + var utf8 = []; + var len = str.length; + + for (; i < len; i++) { + char = str.charCodeAt(i); + if (char < 128) { + utf8[p++] = char; + } else if (char < 2048) { + utf8[p++] = (char >> 6) | 192; + utf8[p++] = (char & 63) | 128; + } else if ( + ((char & 0xFC00) === 0xD800) && (i + 1) < str.length && + ((str.charCodeAt(i + 1) & 0xFC00) === 0xDC00)) { + char = 0x10000 + ((char & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF); + 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; +}; + +/** + * Convert a string into a redis slot hash. + * @param str + * @returns {number} + */ +var generate = module.exports = function generate(str) { + var char; + var i = 0; + var start = -1; + var result = 0; + var resultHash = 0; + var utf8 = typeof str === 'string' ? toUTF8Array(str) : str; + var len = utf8.length; + + while (i < len) { + char = utf8[i++]; + if (start === -1) { + if (char === 0x7B) { + start = i; + } + } else if (char !== 0x7D) { + resultHash = lookup[(char ^ (resultHash >> 8)) & 0xFF] ^ (resultHash << 8); + } else if (i - 1 !== start) { + return resultHash & 0x3FFF; + } + + result = lookup[(char ^ (result >> 8)) & 0xFF] ^ (result << 8); + } + + return result & 0x3FFF; +}; + +/** + * Convert an array of multiple strings into a redis slot hash. + * Returns -1 if one of the keys is not for the same slot as the others + * @param keys + * @returns {number} + */ +module.exports.generateMulti = function generateMulti(keys) { + var i = 1; + var len = keys.length; + var base = generate(keys[0]); + + while (i < len) { + if (generate(keys[i++]) !== base) return -1; + } + + return base; +}; diff --git a/backend/node_modules/cluster-key-slot/package.json b/backend/node_modules/cluster-key-slot/package.json new file mode 100644 index 0000000..f75d3d6 --- /dev/null +++ b/backend/node_modules/cluster-key-slot/package.json @@ -0,0 +1,56 @@ +{ + "name": "cluster-key-slot", + "version": "1.1.2", + "description": "Generates CRC hashes for strings - for use by node redis clients to determine key slots.", + "main": "lib/index.js", + "types": "index.d.ts", + "scripts": { + "benchmark": "node ./benchmark", + "posttest": "eslint ./lib && npm run coveralls", + "coveralls": "cat ./coverage/lcov.info | coveralls", + "test": "node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec", + "coverage:check": "node ./node_modules/istanbul/lib/cli.js check-coverage --branch 100 --statement 100" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Salakar/cluster-key-slot.git" + }, + "keywords": [ + "redis", + "hash", + "crc", + "slot", + "calc", + "javascript", + "node", + "node_redis", + "ioredis" + ], + "engines": { + "node": ">=0.10.0" + }, + "devDependencies": { + "benchmark": "^2.1.0", + "codeclimate-test-reporter": "^0.3.1", + "coveralls": "^2.11.9", + "eslint": "^3.5.0", + "eslint-config-airbnb-base": "^7.1.0", + "eslint-plugin-import": "^1.8.0", + "istanbul": "^0.4.0", + "mocha": "^3.0.2" + }, + "author": { + "name": "Mike Diarmid", + "email": "mike.diarmid@gmail.com", + "url": "http://github.com/Salakar/" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/Salakar/cluster-key-slot/issues" + }, + "homepage": "https://github.com/Salakar/cluster-key-slot#readme", + "directories": { + "test": "test", + "lib": "lib" + } +} diff --git a/backend/node_modules/denque/CHANGELOG.md b/backend/node_modules/denque/CHANGELOG.md new file mode 100644 index 0000000..391a1f5 --- /dev/null +++ b/backend/node_modules/denque/CHANGELOG.md @@ -0,0 +1,29 @@ +## 2.1.0 + + - fix: issue where `clear()` is still keeping references to the elements (#47) + - refactor: performance optimizations for growth and array copy (#43) + - refactor: performance optimizations for toArray and fromArray (#46) + - test: add additional benchmarks for queue growth and `toArray` (#45) + +## 2.0.1 + + - fix(types): incorrect return type on `size()` + +## 2.0.0 + + - fix!: `push` & `unshift` now accept `undefined` values to match behaviour of `Array` (fixes #25) (#35) + - This is only a **BREAKING** change if you are currently expecting `push(undefined)` and `unshift(undefined)` to do + nothing - the new behaviour now correctly adds undefined values to the queue. + - **Note**: behaviour of `push()` & `unshift()` (no arguments) remains unchanged (nothing gets added to the queue). + - **Note**: If you need to differentiate between `undefined` values in the queue and the return value of `pop()` then + check the queue `.length` before popping. + - fix: incorrect methods in types definition file + +## 1.5.1 + + - perf: minor performance tweak when growing queue size (#29) + +## 1.5.0 + + - feat: adds capacity option for circular buffers (#27) + diff --git a/backend/node_modules/denque/LICENSE b/backend/node_modules/denque/LICENSE new file mode 100644 index 0000000..c9cde92 --- /dev/null +++ b/backend/node_modules/denque/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-present Invertase Limited + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/backend/node_modules/denque/README.md b/backend/node_modules/denque/README.md new file mode 100644 index 0000000..3c645d3 --- /dev/null +++ b/backend/node_modules/denque/README.md @@ -0,0 +1,77 @@ +

+

Denque

+

+ +

+ NPM downloads + NPM version + Tests status + Coverage + License + Follow on Twitter +

+ +Denque is a well tested, extremely fast and lightweight [double-ended queue](http://en.wikipedia.org/wiki/Double-ended_queue) +implementation with zero dependencies and includes TypeScript types. + +Double-ended queues can also be used as a: + +- [Stack](http://en.wikipedia.org/wiki/Stack_\(abstract_data_type\)) +- [Queue](http://en.wikipedia.org/wiki/Queue_\(data_structure\)) + +This implementation is currently the fastest available, even faster than `double-ended-queue`, see the [benchmarks](https://docs.page/invertase/denque/benchmarks). + +Every queue operation is done at a constant `O(1)` - including random access from `.peekAt(index)`. + +**Works on all node versions >= v0.10** + +## Quick Start + +Install the package: + +```bash +npm install denque +``` + +Create and consume a queue: + +```js +const Denque = require("denque"); + +const denque = new Denque([1,2,3,4]); +denque.shift(); // 1 +denque.pop(); // 4 +``` + + +See the [API reference documentation](https://docs.page/invertase/denque/api) for more examples. + +--- + +## Who's using it? + +- [Kafka Node.js client](https://www.npmjs.com/package/kafka-node) +- [MariaDB Node.js client](https://www.npmjs.com/package/mariadb) +- [MongoDB Node.js client](https://www.npmjs.com/package/mongodb) +- [MySQL Node.js client](https://www.npmjs.com/package/mysql2) +- [Redis Node.js clients](https://www.npmjs.com/package/redis) + +... and [many more](https://www.npmjs.com/browse/depended/denque). + + +--- + +## License + +- See [LICENSE](/LICENSE) + +--- + +

+ + + +

+ Built and maintained by Invertase. +

+

diff --git a/backend/node_modules/denque/index.d.ts b/backend/node_modules/denque/index.d.ts new file mode 100644 index 0000000..e125dd4 --- /dev/null +++ b/backend/node_modules/denque/index.d.ts @@ -0,0 +1,47 @@ +declare class Denque { + length: number; + + constructor(); + + constructor(array: T[]); + + constructor(array: T[], options: IDenqueOptions); + + push(item: T): number; + + unshift(item: T): number; + + pop(): T | undefined; + + shift(): T | undefined; + + peekBack(): T | undefined; + + peekFront(): T | undefined; + + peekAt(index: number): T | undefined; + + get(index: number): T | undefined; + + remove(index: number, count: number): T[]; + + removeOne(index: number): T | undefined; + + splice(index: number, count: number, ...item: T[]): T[] | undefined; + + isEmpty(): boolean; + + clear(): void; + + size(): number; + + toString(): string; + + toArray(): T[]; +} + +interface IDenqueOptions { + capacity?: number +} + +export = Denque; diff --git a/backend/node_modules/denque/index.js b/backend/node_modules/denque/index.js new file mode 100644 index 0000000..6b2e9d8 --- /dev/null +++ b/backend/node_modules/denque/index.js @@ -0,0 +1,481 @@ +'use strict'; + +/** + * Custom implementation of a double ended queue. + */ +function Denque(array, options) { + var options = options || {}; + this._capacity = options.capacity; + + this._head = 0; + this._tail = 0; + + if (Array.isArray(array)) { + this._fromArray(array); + } else { + this._capacityMask = 0x3; + this._list = new Array(4); + } +} + +/** + * -------------- + * PUBLIC API + * ------------- + */ + +/** + * Returns the item at the specified index from the list. + * 0 is the first element, 1 is the second, and so on... + * Elements at negative values are that many from the end: -1 is one before the end + * (the last element), -2 is two before the end (one before last), etc. + * @param index + * @returns {*} + */ +Denque.prototype.peekAt = function peekAt(index) { + var i = index; + // expect a number or return undefined + if ((i !== (i | 0))) { + return void 0; + } + var len = this.size(); + if (i >= len || i < -len) return undefined; + if (i < 0) i += len; + i = (this._head + i) & this._capacityMask; + return this._list[i]; +}; + +/** + * Alias for peekAt() + * @param i + * @returns {*} + */ +Denque.prototype.get = function get(i) { + return this.peekAt(i); +}; + +/** + * Returns the first item in the list without removing it. + * @returns {*} + */ +Denque.prototype.peek = function peek() { + if (this._head === this._tail) return undefined; + return this._list[this._head]; +}; + +/** + * Alias for peek() + * @returns {*} + */ +Denque.prototype.peekFront = function peekFront() { + return this.peek(); +}; + +/** + * Returns the item that is at the back of the queue without removing it. + * Uses peekAt(-1) + */ +Denque.prototype.peekBack = function peekBack() { + return this.peekAt(-1); +}; + +/** + * Returns the current length of the queue + * @return {Number} + */ +Object.defineProperty(Denque.prototype, 'length', { + get: function length() { + return this.size(); + } +}); + +/** + * Return the number of items on the list, or 0 if empty. + * @returns {number} + */ +Denque.prototype.size = function size() { + if (this._head === this._tail) return 0; + if (this._head < this._tail) return this._tail - this._head; + else return this._capacityMask + 1 - (this._head - this._tail); +}; + +/** + * Add an item at the beginning of the list. + * @param item + */ +Denque.prototype.unshift = function unshift(item) { + if (arguments.length === 0) return this.size(); + var len = this._list.length; + this._head = (this._head - 1 + len) & this._capacityMask; + this._list[this._head] = item; + if (this._tail === this._head) this._growArray(); + if (this._capacity && this.size() > this._capacity) this.pop(); + if (this._head < this._tail) return this._tail - this._head; + else return this._capacityMask + 1 - (this._head - this._tail); +}; + +/** + * Remove and return the first item on the list, + * Returns undefined if the list is empty. + * @returns {*} + */ +Denque.prototype.shift = function shift() { + var head = this._head; + if (head === this._tail) return undefined; + var item = this._list[head]; + this._list[head] = undefined; + this._head = (head + 1) & this._capacityMask; + if (head < 2 && this._tail > 10000 && this._tail <= this._list.length >>> 2) this._shrinkArray(); + return item; +}; + +/** + * Add an item to the bottom of the list. + * @param item + */ +Denque.prototype.push = function push(item) { + if (arguments.length === 0) return this.size(); + var tail = this._tail; + this._list[tail] = item; + this._tail = (tail + 1) & this._capacityMask; + if (this._tail === this._head) { + this._growArray(); + } + if (this._capacity && this.size() > this._capacity) { + this.shift(); + } + if (this._head < this._tail) return this._tail - this._head; + else return this._capacityMask + 1 - (this._head - this._tail); +}; + +/** + * Remove and return the last item on the list. + * Returns undefined if the list is empty. + * @returns {*} + */ +Denque.prototype.pop = function pop() { + var tail = this._tail; + if (tail === this._head) return undefined; + var len = this._list.length; + this._tail = (tail - 1 + len) & this._capacityMask; + var item = this._list[this._tail]; + this._list[this._tail] = undefined; + if (this._head < 2 && tail > 10000 && tail <= len >>> 2) this._shrinkArray(); + return item; +}; + +/** + * Remove and return the item at the specified index from the list. + * Returns undefined if the list is empty. + * @param index + * @returns {*} + */ +Denque.prototype.removeOne = function removeOne(index) { + var i = index; + // expect a number or return undefined + if ((i !== (i | 0))) { + return void 0; + } + if (this._head === this._tail) return void 0; + var size = this.size(); + var len = this._list.length; + if (i >= size || i < -size) return void 0; + if (i < 0) i += size; + i = (this._head + i) & this._capacityMask; + var item = this._list[i]; + var k; + if (index < size / 2) { + for (k = index; k > 0; k--) { + this._list[i] = this._list[i = (i - 1 + len) & this._capacityMask]; + } + this._list[i] = void 0; + this._head = (this._head + 1 + len) & this._capacityMask; + } else { + for (k = size - 1 - index; k > 0; k--) { + this._list[i] = this._list[i = (i + 1 + len) & this._capacityMask]; + } + this._list[i] = void 0; + this._tail = (this._tail - 1 + len) & this._capacityMask; + } + return item; +}; + +/** + * Remove number of items from the specified index from the list. + * Returns array of removed items. + * Returns undefined if the list is empty. + * @param index + * @param count + * @returns {array} + */ +Denque.prototype.remove = function remove(index, count) { + var i = index; + var removed; + var del_count = count; + // expect a number or return undefined + if ((i !== (i | 0))) { + return void 0; + } + if (this._head === this._tail) return void 0; + var size = this.size(); + var len = this._list.length; + if (i >= size || i < -size || count < 1) return void 0; + if (i < 0) i += size; + if (count === 1 || !count) { + removed = new Array(1); + removed[0] = this.removeOne(i); + return removed; + } + if (i === 0 && i + count >= size) { + removed = this.toArray(); + this.clear(); + return removed; + } + if (i + count > size) count = size - i; + var k; + removed = new Array(count); + for (k = 0; k < count; k++) { + removed[k] = this._list[(this._head + i + k) & this._capacityMask]; + } + i = (this._head + i) & this._capacityMask; + if (index + count === size) { + this._tail = (this._tail - count + len) & this._capacityMask; + for (k = count; k > 0; k--) { + this._list[i = (i + 1 + len) & this._capacityMask] = void 0; + } + return removed; + } + if (index === 0) { + this._head = (this._head + count + len) & this._capacityMask; + for (k = count - 1; k > 0; k--) { + this._list[i = (i + 1 + len) & this._capacityMask] = void 0; + } + return removed; + } + if (i < size / 2) { + this._head = (this._head + index + count + len) & this._capacityMask; + for (k = index; k > 0; k--) { + this.unshift(this._list[i = (i - 1 + len) & this._capacityMask]); + } + i = (this._head - 1 + len) & this._capacityMask; + while (del_count > 0) { + this._list[i = (i - 1 + len) & this._capacityMask] = void 0; + del_count--; + } + if (index < 0) this._tail = i; + } else { + this._tail = i; + i = (i + count + len) & this._capacityMask; + for (k = size - (count + index); k > 0; k--) { + this.push(this._list[i++]); + } + i = this._tail; + while (del_count > 0) { + this._list[i = (i + 1 + len) & this._capacityMask] = void 0; + del_count--; + } + } + if (this._head < 2 && this._tail > 10000 && this._tail <= len >>> 2) this._shrinkArray(); + return removed; +}; + +/** + * Native splice implementation. + * Remove number of items from the specified index from the list and/or add new elements. + * Returns array of removed items or empty array if count == 0. + * Returns undefined if the list is empty. + * + * @param index + * @param count + * @param {...*} [elements] + * @returns {array} + */ +Denque.prototype.splice = function splice(index, count) { + var i = index; + // expect a number or return undefined + if ((i !== (i | 0))) { + return void 0; + } + var size = this.size(); + if (i < 0) i += size; + if (i > size) return void 0; + if (arguments.length > 2) { + var k; + var temp; + var removed; + var arg_len = arguments.length; + var len = this._list.length; + var arguments_index = 2; + if (!size || i < size / 2) { + temp = new Array(i); + for (k = 0; k < i; k++) { + temp[k] = this._list[(this._head + k) & this._capacityMask]; + } + if (count === 0) { + removed = []; + if (i > 0) { + this._head = (this._head + i + len) & this._capacityMask; + } + } else { + removed = this.remove(i, count); + this._head = (this._head + i + len) & this._capacityMask; + } + while (arg_len > arguments_index) { + this.unshift(arguments[--arg_len]); + } + for (k = i; k > 0; k--) { + this.unshift(temp[k - 1]); + } + } else { + temp = new Array(size - (i + count)); + var leng = temp.length; + for (k = 0; k < leng; k++) { + temp[k] = this._list[(this._head + i + count + k) & this._capacityMask]; + } + if (count === 0) { + removed = []; + if (i != size) { + this._tail = (this._head + i + len) & this._capacityMask; + } + } else { + removed = this.remove(i, count); + this._tail = (this._tail - leng + len) & this._capacityMask; + } + while (arguments_index < arg_len) { + this.push(arguments[arguments_index++]); + } + for (k = 0; k < leng; k++) { + this.push(temp[k]); + } + } + return removed; + } else { + return this.remove(i, count); + } +}; + +/** + * Soft clear - does not reset capacity. + */ +Denque.prototype.clear = function clear() { + this._list = new Array(this._list.length); + this._head = 0; + this._tail = 0; +}; + +/** + * Returns true or false whether the list is empty. + * @returns {boolean} + */ +Denque.prototype.isEmpty = function isEmpty() { + return this._head === this._tail; +}; + +/** + * Returns an array of all queue items. + * @returns {Array} + */ +Denque.prototype.toArray = function toArray() { + return this._copyArray(false); +}; + +/** + * ------------- + * INTERNALS + * ------------- + */ + +/** + * Fills the queue with items from an array + * For use in the constructor + * @param array + * @private + */ +Denque.prototype._fromArray = function _fromArray(array) { + var length = array.length; + var capacity = this._nextPowerOf2(length); + + this._list = new Array(capacity); + this._capacityMask = capacity - 1; + this._tail = length; + + for (var i = 0; i < length; i++) this._list[i] = array[i]; +}; + +/** + * + * @param fullCopy + * @param size Initialize the array with a specific size. Will default to the current list size + * @returns {Array} + * @private + */ +Denque.prototype._copyArray = function _copyArray(fullCopy, size) { + var src = this._list; + var capacity = src.length; + var length = this.length; + size = size | length; + + // No prealloc requested and the buffer is contiguous + if (size == length && this._head < this._tail) { + // Simply do a fast slice copy + return this._list.slice(this._head, this._tail); + } + + var dest = new Array(size); + + var k = 0; + var i; + if (fullCopy || this._head > this._tail) { + for (i = this._head; i < capacity; i++) dest[k++] = src[i]; + for (i = 0; i < this._tail; i++) dest[k++] = src[i]; + } else { + for (i = this._head; i < this._tail; i++) dest[k++] = src[i]; + } + + return dest; +} + +/** + * Grows the internal list array. + * @private + */ +Denque.prototype._growArray = function _growArray() { + if (this._head != 0) { + // double array size and copy existing data, head to end, then beginning to tail. + var newList = this._copyArray(true, this._list.length << 1); + + this._tail = this._list.length; + this._head = 0; + + this._list = newList; + } else { + this._tail = this._list.length; + this._list.length <<= 1; + } + + this._capacityMask = (this._capacityMask << 1) | 1; +}; + +/** + * Shrinks the internal list array. + * @private + */ +Denque.prototype._shrinkArray = function _shrinkArray() { + this._list.length >>>= 1; + this._capacityMask >>>= 1; +}; + +/** + * Find the next power of 2, at least 4 + * @private + * @param {number} num + * @returns {number} + */ +Denque.prototype._nextPowerOf2 = function _nextPowerOf2(num) { + var log2 = Math.log(num) / Math.log(2); + var nextPow2 = 1 << (log2 + 1); + + return Math.max(nextPow2, 4); +} + +module.exports = Denque; diff --git a/backend/node_modules/denque/package.json b/backend/node_modules/denque/package.json new file mode 100644 index 0000000..a635910 --- /dev/null +++ b/backend/node_modules/denque/package.json @@ -0,0 +1,58 @@ +{ + "name": "denque", + "version": "2.1.0", + "description": "The fastest javascript implementation of a double-ended queue. Used by the official Redis, MongoDB, MariaDB & MySQL libraries for Node.js and many other libraries. Maintains compatability with deque.", + "main": "index.js", + "engines": { + "node": ">=0.10" + }, + "keywords": [ + "data-structure", + "data-structures", + "queue", + "double", + "end", + "ended", + "deque", + "denque", + "double-ended-queue" + ], + "scripts": { + "test": "istanbul cover --report lcov _mocha && npm run typescript", + "coveralls": "cat ./coverage/lcov.info | coveralls", + "typescript": "tsc --project ./test/type/tsconfig.json", + "benchmark_thousand": "node benchmark/thousand", + "benchmark_2mil": "node benchmark/two_million", + "benchmark_splice": "node benchmark/splice", + "benchmark_remove": "node benchmark/remove", + "benchmark_removeOne": "node benchmark/removeOne", + "benchmark_growth": "node benchmark/growth", + "benchmark_toArray": "node benchmark/toArray", + "benchmark_fromArray": "node benchmark/fromArray" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/invertase/denque.git" + }, + "license": "Apache-2.0", + "author": { + "name": "Invertase", + "email": "oss@invertase.io", + "url": "http://github.com/invertase/" + }, + "contributors": [ + "Mike Diarmid (Salakar) " + ], + "bugs": { + "url": "https://github.com/invertase/denque/issues" + }, + "homepage": "https://docs.page/invertase/denque", + "devDependencies": { + "benchmark": "^2.1.4", + "codecov": "^3.8.3", + "double-ended-queue": "^2.1.0-0", + "istanbul": "^0.4.5", + "mocha": "^3.5.3", + "typescript": "^3.4.1" + } +} diff --git a/backend/node_modules/ioredis/LICENSE b/backend/node_modules/ioredis/LICENSE new file mode 100644 index 0000000..1d4bd28 --- /dev/null +++ b/backend/node_modules/ioredis/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2022 Zihua Li + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/backend/node_modules/ioredis/README.md b/backend/node_modules/ioredis/README.md new file mode 100644 index 0000000..2b33d38 --- /dev/null +++ b/backend/node_modules/ioredis/README.md @@ -0,0 +1,1498 @@ +[![ioredis](https://cdn.jsdelivr.net/gh/redis/ioredis@b5e8c74/logo.svg)](https://github.com/redis/ioredis) + +[![Build Status](https://github.com/redis/ioredis/actions/workflows/release.yml/badge.svg?branch=main)](https://github.com/redis/ioredis/actions/workflows/release.yml?query=branch%3Amain) +[![Coverage Status](https://coveralls.io/repos/github/luin/ioredis/badge.svg?branch=main)](https://coveralls.io/github/luin/ioredis?branch=main) +[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) +[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) + +[![Discord](https://img.shields.io/discord/697882427875393627.svg?style=social&logo=discord)](https://discord.gg/redis) +[![Twitch](https://img.shields.io/twitch/status/redisinc?style=social)](https://www.twitch.tv/redisinc) +[![YouTube](https://img.shields.io/youtube/channel/views/UCD78lHSwYqMlyetR0_P4Vig?style=social)](https://www.youtube.com/redisinc) +[![Twitter](https://img.shields.io/twitter/follow/redisinc?style=social)](https://twitter.com/redisinc) + +A robust, performance-focused and full-featured [Redis](http://redis.io) client for [Node.js](https://nodejs.org). + +Supports Redis >= 2.6.12. Completely compatible with Redis 7.x. + +ioredis is a stable project and maintenance is done on a best-effort basis for relevant issues (contributions to ioredis will still be evaluated, reviewed, and merged when they benefit the project). For new projects, node-redis is the recommended client library. [node-redis](https://github.com/redis/node-redis) is the open-source (MIT license) Redis JavaScript client library redesigned from the ground up and actively maintained. [node-redis](https://github.com/redis/node-redis) supports new (hash-field expiration) and future commands and the capabilities available in Redis Stack and Redis 8 (search, JSON, time-series, probabilistic data structures). + +# Features + +ioredis is a robust, full-featured Redis client that is +used in the world's biggest online commerce company [Alibaba](http://www.alibaba.com/) and many other awesome companies. + +0. Full-featured. It supports [Cluster](http://redis.io/topics/cluster-tutorial), [Sentinel](https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/), [Streams](https://redis.io/topics/streams-intro), [Pipelining](http://redis.io/topics/pipelining), and of course [Lua scripting](http://redis.io/commands/eval), [Redis Functions](https://redis.io/topics/functions-intro), [Pub/Sub](http://redis.io/topics/pubsub) (with the support of binary messages). +1. High performance 🚀. +2. Delightful API 😄. It works with Node callbacks and Native promises. +3. Transformation of command arguments and replies. +4. Transparent key prefixing. +5. Abstraction for Lua scripting, allowing you to [define custom commands](https://github.com/redis/ioredis#lua-scripting). +6. Supports [binary data](https://github.com/redis/ioredis#handle-binary-data). +7. Supports [TLS](https://github.com/redis/ioredis#tls-options) 🔒. +8. Supports offline queue and ready checking. +9. Supports ES6 types, such as `Map` and `Set`. +10. Supports GEO commands 📍. +11. Supports Redis ACL. +12. Sophisticated error handling strategy. +13. Supports NAT mapping. +14. Supports autopipelining. + +**100% written in TypeScript and official declarations are provided:** + +TypeScript Screenshot + +# Versions + +| Version | Branch | Node.js Version | Redis Version | +| -------------- | ------ | --------------- | --------------- | +| 5.x.x (latest) | main | >= 12 | 2.6.12 ~ latest | +| 4.x.x | v4 | >= 8 | 2.6.12 ~ 7 | + +Refer to [CHANGELOG.md](CHANGELOG.md) for features and bug fixes introduced in v5. + +🚀 [Upgrading from v4 to v5](https://github.com/redis/ioredis/wiki/Upgrading-from-v4-to-v5) + +# Links + +- [API Documentation](https://redis.github.io/ioredis/) ([Redis](https://redis.github.io/ioredis/classes/Redis.html), [Cluster](https://redis.github.io/ioredis/classes/Cluster.html)) +- [Changelog](CHANGELOG.md) + +
+ +# Quick Start + +## Install + +```shell +npm install ioredis +``` + +In a TypeScript project, you may want to add TypeScript declarations for Node.js: + +```shell +npm install --save-dev @types/node +``` + +## Basic Usage + +```javascript +// Import ioredis. +// You can also use `import { Redis } from "ioredis"` +// if your project is a TypeScript project, +// Note that `import Redis from "ioredis"` is still supported, +// but will be deprecated in the next major version. +const Redis = require("ioredis"); + +// Create a Redis instance. +// By default, it will connect to localhost:6379. +// We are going to cover how to specify connection options soon. +const redis = new Redis(); + +redis.set("mykey", "value"); // Returns a promise which resolves to "OK" when the command succeeds. + +// ioredis supports the node.js callback style +redis.get("mykey", (err, result) => { + if (err) { + console.error(err); + } else { + console.log(result); // Prints "value" + } +}); + +// Or ioredis returns a promise if the last argument isn't a function +redis.get("mykey").then((result) => { + console.log(result); // Prints "value" +}); + +redis.zadd("sortedSet", 1, "one", 2, "dos", 4, "quatro", 3, "three"); +redis.zrange("sortedSet", 0, 2, "WITHSCORES").then((elements) => { + // ["one", "1", "dos", "2", "three", "3"] as if the command was `redis> ZRANGE sortedSet 0 2 WITHSCORES` + console.log(elements); +}); + +// All arguments are passed directly to the redis server, +// so technically ioredis supports all Redis commands. +// The format is: redis[SOME_REDIS_COMMAND_IN_LOWERCASE](ARGUMENTS_ARE_JOINED_INTO_COMMAND_STRING) +// so the following statement is equivalent to the CLI: `redis> SET mykey hello EX 10` +redis.set("mykey", "hello", "EX", 10); +``` + +See the `examples/` folder for more examples. For example: + +- [TTL](examples/ttl.js) +- [Strings](examples/string.js) +- [Hashes](examples/hash.js) +- [Lists](examples/list.js) +- [Sets](examples/set.js) +- [Sorted Sets](examples/zset.js) +- [Streams](examples/stream.js) +- [Redis Modules](examples/module.js) e.g. RedisJSON + +All Redis commands are supported. See [the documentation](https://redis.github.io/ioredis/classes/Redis.html) for details. + +## Connect to Redis + +When a new `Redis` instance is created, +a connection to Redis will be created at the same time. +You can specify which Redis to connect to by: + +```javascript +new Redis(); // Connect to 127.0.0.1:6379 +new Redis(6380); // 127.0.0.1:6380 +new Redis(6379, "192.168.1.1"); // 192.168.1.1:6379 +new Redis("/tmp/redis.sock"); +new Redis({ + port: 6379, // Redis port + host: "127.0.0.1", // Redis host + username: "default", // needs Redis >= 6 + password: "my-top-secret", + db: 0, // Defaults to 0 +}); +``` + +You can also specify connection options as a [`redis://` URL](http://www.iana.org/assignments/uri-schemes/prov/redis) or [`rediss://` URL](https://www.iana.org/assignments/uri-schemes/prov/rediss) when using [TLS encryption](#tls-options): + +```javascript +// Connect to 127.0.0.1:6380, db 4, using password "authpassword": +new Redis("redis://:authpassword@127.0.0.1:6380/4"); + +// Username can also be passed via URI. +new Redis("redis://username:authpassword@127.0.0.1:6380/4"); +``` + +See [API Documentation](https://redis.github.io/ioredis/index.html#RedisOptions) for all available options. + +## Pub/Sub + +Redis provides several commands for developers to implement the [Publish–subscribe pattern](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern). There are two roles in this pattern: publisher and subscriber. Publishers are not programmed to send their messages to specific subscribers. Rather, published messages are characterized into channels, without knowledge of what (if any) subscribers there may be. + +By leveraging Node.js's built-in events module, ioredis makes pub/sub very straightforward to use. Below is a simple example that consists of two files, one is publisher.js that publishes messages to a channel, the other is subscriber.js that listens for messages on specific channels. + +```javascript +// publisher.js + +const Redis = require("ioredis"); +const redis = new Redis(); + +setInterval(() => { + const message = { foo: Math.random() }; + // Publish to my-channel-1 or my-channel-2 randomly. + const channel = `my-channel-${1 + Math.round(Math.random())}`; + + // Message can be either a string or a buffer + redis.publish(channel, JSON.stringify(message)); + console.log("Published %s to %s", message, channel); +}, 1000); +``` + +```javascript +// subscriber.js + +const Redis = require("ioredis"); +const redis = new Redis(); + +redis.subscribe("my-channel-1", "my-channel-2", (err, count) => { + if (err) { + // Just like other commands, subscribe() can fail for some reasons, + // ex network issues. + console.error("Failed to subscribe: %s", err.message); + } else { + // `count` represents the number of channels this client are currently subscribed to. + console.log( + `Subscribed successfully! This client is currently subscribed to ${count} channels.` + ); + } +}); + +redis.on("message", (channel, message) => { + console.log(`Received ${message} from ${channel}`); +}); + +// There's also an event called 'messageBuffer', which is the same as 'message' except +// it returns buffers instead of strings. +// It's useful when the messages are binary data. +redis.on("messageBuffer", (channel, message) => { + // Both `channel` and `message` are buffers. + console.log(channel, message); +}); +``` + +It's worth noticing that a connection (aka a `Redis` instance) can't play both roles at the same time. More specifically, when a client issues `subscribe()` or `psubscribe()`, it enters the "subscriber" mode. From that point, only commands that modify the subscription set are valid. Namely, they are: `subscribe`, `psubscribe`, `unsubscribe`, `punsubscribe`, `ping`, and `quit`. When the subscription set is empty (via `unsubscribe`/`punsubscribe`), the connection is put back into the regular mode. + +If you want to do pub/sub in the same file/process, you should create a separate connection: + +```javascript +const Redis = require("ioredis"); +const sub = new Redis(); +const pub = new Redis(); + +sub.subscribe(/* ... */); // From now, `sub` enters the subscriber mode. +sub.on("message" /* ... */); + +setInterval(() => { + // `pub` can be used to publish messages, or send other regular commands (e.g. `hgetall`) + // because it's not in the subscriber mode. + pub.publish(/* ... */); +}, 1000); +``` + +`PSUBSCRIBE` is also supported in a similar way when you want to subscribe all channels whose name matches a pattern: + +```javascript +redis.psubscribe("pat?ern", (err, count) => {}); + +// Event names are "pmessage"/"pmessageBuffer" instead of "message/messageBuffer". +redis.on("pmessage", (pattern, channel, message) => {}); +redis.on("pmessageBuffer", (pattern, channel, message) => {}); +``` + +## Streams + +Redis v5 introduces a new data type called streams. It doubles as a communication channel for building streaming architectures and as a log-like data structure for persisting data. With ioredis, the usage can be pretty straightforward. Say we have a producer publishes messages to a stream with `redis.xadd("mystream", "*", "randomValue", Math.random())` (You may find the [official documentation of Streams](https://redis.io/topics/streams-intro) as a starter to understand the parameters used), to consume the messages, we'll have a consumer with the following code: + +```javascript +const Redis = require("ioredis"); +const redis = new Redis(); + +const processMessage = (message) => { + console.log("Id: %s. Data: %O", message[0], message[1]); +}; + +async function listenForMessage(lastId = "$") { + // `results` is an array, each element of which corresponds to a key. + // Because we only listen to one key (mystream) here, `results` only contains + // a single element. See more: https://redis.io/commands/xread#return-value + const results = await redis.xread("BLOCK", 0, "STREAMS", "mystream", lastId); + const [key, messages] = results[0]; // `key` equals to "mystream" + + messages.forEach(processMessage); + + // Pass the last id of the results to the next round. + await listenForMessage(messages[messages.length - 1][0]); +} + +listenForMessage(); +``` + +## Expiration + +Redis can set a timeout to expire your key, after the timeout has expired the key will be automatically deleted. (You can find the [official Expire documentation](https://redis.io/commands/expire/) to understand better the different parameters you can use), to set your key to expire in 60 seconds, we will have the following code: + +```javascript +redis.set("key", "data", "EX", 60); +// Equivalent to redis command "SET key data EX 60", because on ioredis set method, +// all arguments are passed directly to the redis server. +``` + +## Handle Binary Data + +Binary data support is out of the box. Pass buffers to send binary data: + +```javascript +redis.set("foo", Buffer.from([0x62, 0x75, 0x66])); +``` + +Every command that returns a [bulk string](https://redis.io/docs/reference/protocol-spec/#resp-bulk-strings) +has a variant command with a `Buffer` suffix. The variant command returns a buffer instead of a UTF-8 string: + +```javascript +const result = await redis.getBuffer("foo"); +// result is `` +``` + +It's worth noticing that you don't need the `Buffer` suffix variant in order to **send** binary data. That means +in most case you should just use `redis.set()` instead of `redis.setBuffer()` unless you want to get the old value +with the `GET` parameter: + +```javascript +const result = await redis.setBuffer("foo", "new value", "GET"); +// result is `` as `GET` indicates returning the old value. +``` + +## Pipelining + +If you want to send a batch of commands (e.g. > 5), you can use pipelining to queue +the commands in memory and then send them to Redis all at once. This way the performance improves by 50%~300% (See [benchmark section](#benchmarks)). + +`redis.pipeline()` creates a `Pipeline` instance. You can call any Redis +commands on it just like the `Redis` instance. The commands are queued in memory +and flushed to Redis by calling the `exec` method: + +```javascript +const pipeline = redis.pipeline(); +pipeline.set("foo", "bar"); +pipeline.del("cc"); +pipeline.exec((err, results) => { + // `err` is always null, and `results` is an array of responses + // corresponding to the sequence of queued commands. + // Each response follows the format `[err, result]`. +}); + +// You can even chain the commands: +redis + .pipeline() + .set("foo", "bar") + .del("cc") + .exec((err, results) => {}); + +// `exec` also returns a Promise: +const promise = redis.pipeline().set("foo", "bar").get("foo").exec(); +promise.then((result) => { + // result === [[null, 'OK'], [null, 'bar']] +}); +``` + +Each chained command can also have a callback, which will be invoked when the command +gets a reply: + +```javascript +redis + .pipeline() + .set("foo", "bar") + .get("foo", (err, result) => { + // result === 'bar' + }) + .exec((err, result) => { + // result[1][1] === 'bar' + }); +``` + +In addition to adding commands to the `pipeline` queue individually, you can also pass an array of commands and arguments to the constructor: + +```javascript +redis + .pipeline([ + ["set", "foo", "bar"], + ["get", "foo"], + ]) + .exec(() => { + /* ... */ + }); +``` + +`#length` property shows how many commands in the pipeline: + +```javascript +const length = redis.pipeline().set("foo", "bar").get("foo").length; +// length === 2 +``` + +## Transaction + +Most of the time, the transaction commands `multi` & `exec` are used together with pipeline. +Therefore, when `multi` is called, a `Pipeline` instance is created automatically by default, +so you can use `multi` just like `pipeline`: + +```javascript +redis + .multi() + .set("foo", "bar") + .get("foo") + .exec((err, results) => { + // results === [[null, 'OK'], [null, 'bar']] + }); +``` + +If there's a syntax error in the transaction's command chain (e.g. wrong number of arguments, wrong command name, etc), +then none of the commands would be executed, and an error is returned: + +```javascript +redis + .multi() + .set("foo") + .set("foo", "new value") + .exec((err, results) => { + // err: + // { [ReplyError: EXECABORT Transaction discarded because of previous errors.] + // name: 'ReplyError', + // message: 'EXECABORT Transaction discarded because of previous errors.', + // command: { name: 'exec', args: [] }, + // previousErrors: + // [ { [ReplyError: ERR wrong number of arguments for 'set' command] + // name: 'ReplyError', + // message: 'ERR wrong number of arguments for \'set\' command', + // command: [Object] } ] } + }); +``` + +In terms of the interface, `multi` differs from `pipeline` in that when specifying a callback +to each chained command, the queueing state is passed to the callback instead of the result of the command: + +```javascript +redis + .multi() + .set("foo", "bar", (err, result) => { + // result === 'QUEUED' + }) + .exec(/* ... */); +``` + +If you want to use transaction without pipeline, pass `{ pipeline: false }` to `multi`, +and every command will be sent to Redis immediately without waiting for an `exec` invocation: + +```javascript +redis.multi({ pipeline: false }); +redis.set("foo", "bar"); +redis.get("foo"); +redis.exec((err, result) => { + // result === [[null, 'OK'], [null, 'bar']] +}); +``` + +The constructor of `multi` also accepts a batch of commands: + +```javascript +redis + .multi([ + ["set", "foo", "bar"], + ["get", "foo"], + ]) + .exec(() => { + /* ... */ + }); +``` + +Inline transactions are supported by pipeline, which means you can group a subset of commands +in the pipeline into a transaction: + +```javascript +redis + .pipeline() + .get("foo") + .multi() + .set("foo", "bar") + .get("foo") + .exec() + .get("foo") + .exec(); +``` + +## Lua Scripting + +ioredis supports all of the scripting commands such as `EVAL`, `EVALSHA` and `SCRIPT`. +However, it's tedious to use in real world scenarios since developers have to take +care of script caching and to detect when to use `EVAL` and when to use `EVALSHA`. +ioredis exposes a `defineCommand` method to make scripting much easier to use: + +```javascript +const redis = new Redis(); + +// This will define a command myecho: +redis.defineCommand("myecho", { + numberOfKeys: 2, + lua: "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", +}); + +// Now `myecho` can be used just like any other ordinary command, +// and ioredis will try to use `EVALSHA` internally when possible for better performance. +redis.myecho("k1", "k2", "a1", "a2", (err, result) => { + // result === ['k1', 'k2', 'a1', 'a2'] +}); + +// `myechoBuffer` is also defined automatically to return buffers instead of strings: +redis.myechoBuffer("k1", "k2", "a1", "a2", (err, result) => { + // result[0] equals to Buffer.from('k1'); +}); + +// And of course it works with pipeline: +redis.pipeline().set("foo", "bar").myecho("k1", "k2", "a1", "a2").exec(); +``` + +### Dynamic Keys + +If the number of keys can't be determined when defining a command, you can +omit the `numberOfKeys` property and pass the number of keys as the first argument +when you call the command: + +```javascript +redis.defineCommand("echoDynamicKeyNumber", { + lua: "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", +}); + +// Now you have to pass the number of keys as the first argument every time +// you invoke the `echoDynamicKeyNumber` command: +redis.echoDynamicKeyNumber(2, "k1", "k2", "a1", "a2", (err, result) => { + // result === ['k1', 'k2', 'a1', 'a2'] +}); +``` + +### As Constructor Options + +Besides `defineCommand()`, you can also define custom commands with the `scripts` constructor option: + +```javascript +const redis = new Redis({ + scripts: { + myecho: { + numberOfKeys: 2, + lua: "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", + }, + }, +}); +``` + +### TypeScript Usages + +You can refer to [the example](examples/typescript/scripts.ts) for how to declare your custom commands. + +## Transparent Key Prefixing + +This feature allows you to specify a string that will automatically be prepended +to all the keys in a command, which makes it easier to manage your key +namespaces. + +**Warning** This feature won't apply to commands like [KEYS](http://redis.io/commands/KEYS) and [SCAN](http://redis.io/commands/scan) that take patterns rather than actual keys([#239](https://github.com/redis/ioredis/issues/239)), +and this feature also won't apply to the replies of commands even if they are key names ([#325](https://github.com/redis/ioredis/issues/325)). + +```javascript +const fooRedis = new Redis({ keyPrefix: "foo:" }); +fooRedis.set("bar", "baz"); // Actually sends SET foo:bar baz + +fooRedis.defineCommand("myecho", { + numberOfKeys: 2, + lua: "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", +}); + +// Works well with pipelining/transaction +fooRedis + .pipeline() + // Sends SORT foo:list BY foo:weight_*->fieldname + .sort("list", "BY", "weight_*->fieldname") + // Supports custom commands + // Sends EVALSHA xxx foo:k1 foo:k2 a1 a2 + .myecho("k1", "k2", "a1", "a2") + .exec(); +``` + +## Transforming Arguments & Replies + +Most Redis commands take one or more Strings as arguments, +and replies are sent back as a single String or an Array of Strings. However, sometimes +you may want something different. For instance, it would be more convenient if the `HGETALL` +command returns a hash (e.g. `{ key: val1, key2: v2 }`) rather than an array of key values (e.g. `[key1, val1, key2, val2]`). + +ioredis has a flexible system for transforming arguments and replies. There are two types +of transformers, argument transformer and reply transformer: + +```javascript +const Redis = require("ioredis"); + +// Here's the built-in argument transformer converting +// hmset('key', { k1: 'v1', k2: 'v2' }) +// or +// hmset('key', new Map([['k1', 'v1'], ['k2', 'v2']])) +// into +// hmset('key', 'k1', 'v1', 'k2', 'v2') +Redis.Command.setArgumentTransformer("hmset", (args) => { + if (args.length === 2) { + if (args[1] instanceof Map) { + // utils is a internal module of ioredis + return [args[0], ...utils.convertMapToArray(args[1])]; + } + if (typeof args[1] === "object" && args[1] !== null) { + return [args[0], ...utils.convertObjectToArray(args[1])]; + } + } + return args; +}); + +// Here's the built-in reply transformer converting the HGETALL reply +// ['k1', 'v1', 'k2', 'v2'] +// into +// { k1: 'v1', 'k2': 'v2' } +Redis.Command.setReplyTransformer("hgetall", (result) => { + if (Array.isArray(result)) { + const obj = {}; + for (let i = 0; i < result.length; i += 2) { + obj[result[i]] = result[i + 1]; + } + return obj; + } + return result; +}); +``` + +There are three built-in transformers, two argument transformers for `hmset` & `mset` and +a reply transformer for `hgetall`. Transformers for `hmset` and `hgetall` were mentioned +above, and the transformer for `mset` is similar to the one for `hmset`: + +```javascript +redis.mset({ k1: "v1", k2: "v2" }); +redis.get("k1", (err, result) => { + // result === 'v1'; +}); + +redis.mset( + new Map([ + ["k3", "v3"], + ["k4", "v4"], + ]) +); +redis.get("k3", (err, result) => { + // result === 'v3'; +}); +``` + +Another useful example of a reply transformer is one that changes `hgetall` to return array of arrays instead of objects which avoids an unwanted conversation of hash keys to strings when dealing with binary hash keys: + +```javascript +Redis.Command.setReplyTransformer("hgetall", (result) => { + const arr = []; + for (let i = 0; i < result.length; i += 2) { + arr.push([result[i], result[i + 1]]); + } + return arr; +}); +redis.hset("h1", Buffer.from([0x01]), Buffer.from([0x02])); +redis.hset("h1", Buffer.from([0x03]), Buffer.from([0x04])); +redis.hgetallBuffer("h1", (err, result) => { + // result === [ [ , ], [ , ] ]; +}); +``` + +## Monitor + +Redis supports the MONITOR command, +which lets you see all commands received by the Redis server across all client connections, +including from other client libraries and other computers. + +The `monitor` method returns a monitor instance. +After you send the MONITOR command, no other commands are valid on that connection. ioredis will emit a monitor event for every new monitor message that comes across. +The callback for the monitor event takes a timestamp from the Redis server and an array of command arguments. + +Here is a simple example: + +```javascript +redis.monitor((err, monitor) => { + monitor.on("monitor", (time, args, source, database) => {}); +}); +``` + +Here is another example illustrating an `async` function and `monitor.disconnect()`: + +```javascript +async () => { + const monitor = await redis.monitor(); + monitor.on("monitor", console.log); + // Any other tasks + monitor.disconnect(); +}; +``` + +## Streamify Scanning + +Redis 2.8 added the `SCAN` command to incrementally iterate through the keys in the database. It's different from `KEYS` in that +`SCAN` only returns a small number of elements each call, so it can be used in production without the downside +of blocking the server for a long time. However, it requires recording the cursor on the client side each time +the `SCAN` command is called in order to iterate through all the keys correctly. Since it's a relatively common use case, ioredis +provides a streaming interface for the `SCAN` command to make things much easier. A readable stream can be created by calling `scanStream`: + +```javascript +const redis = new Redis(); +// Create a readable stream (object mode) +const stream = redis.scanStream(); +stream.on("data", (resultKeys) => { + // `resultKeys` is an array of strings representing key names. + // Note that resultKeys may contain 0 keys, and that it will sometimes + // contain duplicates due to SCAN's implementation in Redis. + for (let i = 0; i < resultKeys.length; i++) { + console.log(resultKeys[i]); + } +}); +stream.on("end", () => { + console.log("all keys have been visited"); +}); +``` + +`scanStream` accepts an option, with which you can specify the `MATCH` pattern, the `TYPE` filter, and the `COUNT` argument: + +```javascript +const stream = redis.scanStream({ + // only returns keys following the pattern of `user:*` + match: "user:*", + // only return objects that match a given type, + // (requires Redis >= 6.0) + type: "zset", + // returns approximately 100 elements per call + count: 100, +}); +``` + +Just like other commands, `scanStream` has a binary version `scanBufferStream`, which returns an array of buffers. It's useful when +the key names are not utf8 strings. + +There are also `hscanStream`, `zscanStream` and `sscanStream` to iterate through elements in a hash, zset and set. The interface of each is +similar to `scanStream` except the first argument is the key name: + +```javascript +const stream = redis.zscanStream("myhash", { + match: "age:??", +}); +``` +The `hscanStream` also accepts the `noValues` option to specify whether Redis should return only the keys in the hash table without their corresponding values. +```javascript +const stream = redis.hscanStream("myhash", { + match: "age:??", + noValues: true, +}); +``` +You can learn more from the [Redis documentation](http://redis.io/commands/scan). + +**Useful Tips** +It's pretty common that doing an async task in the `data` handler. We'd like the scanning process to be paused until the async task to be finished. `Stream#pause()` and `Stream#resume()` do the trick. For example if we want to migrate data in Redis to MySQL: + +```javascript +const stream = redis.scanStream(); +stream.on("data", (resultKeys) => { + // Pause the stream from scanning more keys until we've migrated the current keys. + stream.pause(); + + Promise.all(resultKeys.map(migrateKeyToMySQL)).then(() => { + // Resume the stream here. + stream.resume(); + }); +}); + +stream.on("end", () => { + console.log("done migration"); +}); +``` + +## Auto-reconnect + +By default, ioredis will try to reconnect when the connection to Redis is lost +except when the connection is closed manually by `redis.disconnect()` or `redis.quit()`. + +It's very flexible to control how long to wait to reconnect after disconnection +using the `retryStrategy` option: + +```javascript +const redis = new Redis({ + // This is the default value of `retryStrategy` + retryStrategy(times) { + const delay = Math.min(times * 50, 2000); + return delay; + }, +}); +``` + +`retryStrategy` is a function that will be called when the connection is lost. +The argument `times` means this is the nth reconnection being made and +the return value represents how long (in ms) to wait to reconnect. When the +return value isn't a number, ioredis will stop trying to reconnect, and the connection +will be lost forever if the user doesn't call `redis.connect()` manually. + +When reconnected, the client will auto subscribe to channels that the previous connection subscribed to. +This behavior can be disabled by setting the `autoResubscribe` option to `false`. + +And if the previous connection has some unfulfilled commands (most likely blocking commands such as `brpop` and `blpop`), +the client will resend them when reconnected. This behavior can be disabled by setting the `autoResendUnfulfilledCommands` option to `false`. + +By default, all pending commands will be flushed with an error every 20 retry attempts. That makes sure commands won't wait forever when the connection is down. You can change this behavior by setting `maxRetriesPerRequest`: + +```javascript +const redis = new Redis({ + maxRetriesPerRequest: 1, +}); +``` + +Set maxRetriesPerRequest to `null` to disable this behavior, and every command will wait forever until the connection is alive again (which is the default behavior before ioredis v4). + +### Blocking Command Timeout + +ioredis can apply a client-side timeout to blocking commands (such as `blpop`, `brpop`, `bzpopmin`, `bzmpop`, `blmpop`, `xread`, `xreadgroup`, etc.). This protects against scenarios where the TCP connection becomes a zombie (e.g., due to a silent network failure like a Docker network disconnect) and Redis never replies. + +This feature is **opt-in**. It is **disabled by default** and is only enabled +when `blockingTimeout` is set to a positive number of milliseconds. If +`blockingTimeout` is omitted, `0`, or negative (for example `-1`), ioredis +does not arm any client-side timeouts for blocking commands and their +behavior matches Redis exactly. + +```javascript +const redis = new Redis({ + blockingTimeout: 30000, // Enable blocking timeout protection +}); +``` + +When enabled: +- For commands with a finite timeout (e.g., `blpop("key", 5)`), ioredis sets a client-side deadline based on the command's timeout plus a small grace period (`blockingTimeoutGrace`, default 100ms). If no reply arrives before the deadline, the command resolves with `null`—the same value Redis returns when a blocking command times out normally. +- For commands that block forever (e.g., `timeout = 0` or `BLOCK 0`), the `blockingTimeout` value is used as a safety net. + +### Reconnect on Error + +Besides auto-reconnect when the connection is closed, ioredis supports reconnecting on certain Redis errors using the `reconnectOnError` option. Here's an example that will reconnect when receiving `READONLY` error: + +```javascript +const redis = new Redis({ + reconnectOnError(err) { + const targetError = "READONLY"; + if (err.message.includes(targetError)) { + // Only reconnect when the error contains "READONLY" + return true; // or `return 1;` + } + }, +}); +``` + +This feature is useful when using Amazon ElastiCache instances with Auto-failover disabled. On these instances, test your `reconnectOnError` handler by manually promoting the replica node to the primary role using the AWS console. The following writes fail with the error `READONLY`. Using `reconnectOnError`, we can force the connection to reconnect on this error in order to connect to the new master. Furthermore, if the `reconnectOnError` returns `2`, ioredis will resend the failed command after reconnecting. + +On ElastiCache instances with Auto-failover enabled, `reconnectOnError` does not execute. Instead of returning a Redis error, AWS closes all connections to the master endpoint until the new primary node is ready. ioredis reconnects via `retryStrategy` instead of `reconnectOnError` after about a minute. On ElastiCache instances with Auto-failover enabled, test failover events with the `Failover primary` option in the AWS console. + +## Connection Events + +The Redis instance will emit some events about the state of the connection to the Redis server. + +| Event | Description | +| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| connect | emits when a connection is established to the Redis server. | +| ready | If `enableReadyCheck` is `true`, client will emit `ready` when the server reports that it is ready to receive commands (e.g. finish loading data from disk).
Otherwise, `ready` will be emitted immediately right after the `connect` event. | +| error | emits when an error occurs while connecting.
However, ioredis emits all `error` events silently (only emits when there's at least one listener) so that your application won't crash if you're not listening to the `error` event.
When `redis.connect()` is explicitly called the error will also be rejected from the returned promise, in addition to emitting it. If `redis.connect()` is not called explicitly and `lazyConnect` is true, ioredis will try to connect automatically on the first command and emit the `error` event silently. | +| close | emits when an established Redis server connection has closed. | +| reconnecting | emits after `close` when a reconnection will be made. The argument of the event is the time (in ms) before reconnecting. | +| end | emits after `close` when no more reconnections will be made, or the connection is failed to establish. | +| wait | emits when `lazyConnect` is set and will wait for the first command to be called before connecting. | + +You can also check out the `Redis#status` property to get the current connection status. + +Besides the above connection events, there are several other custom events: + +| Event | Description | +| :----- | :------------------------------------------------------------------ | +| select | emits when the database changed. The argument is the new db number. | + +## Offline Queue + +When a command can't be processed by Redis (being sent before the `ready` event), by default, it's added to the offline queue and will be +executed when it can be processed. You can disable this feature by setting the `enableOfflineQueue` +option to `false`: + +```javascript +const redis = new Redis({ enableOfflineQueue: false }); +``` + +## TLS Options + +Redis doesn't support TLS natively, however if the redis server you want to connect to is hosted behind a TLS proxy (e.g. [stunnel](https://www.stunnel.org/)) or is offered by a PaaS service that supports TLS connection (e.g. [Redis.com](https://redis.com/)), you can set the `tls` option: + +```javascript +const redis = new Redis({ + host: "localhost", + tls: { + // Refer to `tls.connect()` section in + // https://nodejs.org/api/tls.html + // for all supported options + ca: fs.readFileSync("cert.pem"), + }, +}); +``` + +Alternatively, specify the connection through a [`rediss://` URL](https://www.iana.org/assignments/uri-schemes/prov/rediss). + +```javascript +const redis = new Redis("rediss://redis.my-service.com"); +``` + +If you do not want to use a connection string, you can also specify an empty `tls: {}` object: + +```javascript +const redis = new Redis({ + host: "redis.my-service.com", + tls: {}, +}); +``` + +### TLS Profiles + +> **Warning** +> TLS profiles described in this section are going to be deprecated in the next major version. Please provide TLS options explicitly. + +To make it easier to configure we provide a few pre-configured TLS profiles that can be specified by setting the `tls` option to the profile's name or specifying a `tls.profile` option in case you need to customize some values of the profile. + +Profiles: + +- `RedisCloudFixed`: Contains the CA for [Redis.com](https://redis.com/) Cloud fixed subscriptions +- `RedisCloudFlexible`: Contains the CA for [Redis.com](https://redis.com/) Cloud flexible subscriptions + +```javascript +const redis = new Redis({ + host: "localhost", + tls: "RedisCloudFixed", +}); + +const redisWithClientCertificate = new Redis({ + host: "localhost", + tls: { + profile: "RedisCloudFixed", + key: "123", + }, +}); +``` + +
+ +## Sentinel + +ioredis supports Sentinel out of the box. It works transparently as all features that work when +you connect to a single node also work when you connect to a sentinel group. Make sure to run Redis >= 2.8.12 if you want to use this feature. Sentinels have a default port of 26379. + +To connect using Sentinel, use: + +```javascript +const redis = new Redis({ + sentinels: [ + { host: "localhost", port: 26379 }, + { host: "localhost", port: 26380 }, + ], + name: "mymaster", +}); + +redis.set("foo", "bar"); +``` + +The arguments passed to the constructor are different from the ones you use to connect to a single node, where: + +- `name` identifies a group of Redis instances composed of a master and one or more slaves (`mymaster` in the example); +- `sentinelPassword` (optional) password for Sentinel instances. +- `sentinels` are a list of sentinels to connect to. The list does not need to enumerate all your sentinel instances, but a few so that if one is down the client will try the next one. +- `role` (optional) with a value of `slave` will return a random slave from the Sentinel group. +- `preferredSlaves` (optional) can be used to prefer a particular slave or set of slaves based on priority. It accepts a function or array. +- `enableTLSForSentinelMode` (optional) set to true if connecting to sentinel instances that are encrypted + +ioredis **guarantees** that the node you connected to is always a master even after a failover. When a failover happens, instead of trying to reconnect to the failed node (which will be demoted to slave when it's available again), ioredis will ask sentinels for the new master node and connect to it. All commands sent during the failover are queued and will be executed when the new connection is established so that none of the commands will be lost. + +It's possible to connect to a slave instead of a master by specifying the option `role` with the value of `slave` and ioredis will try to connect to a random slave of the specified master, with the guarantee that the connected node is always a slave. If the current node is promoted to master due to a failover, ioredis will disconnect from it and ask the sentinels for another slave node to connect to. + +If you specify the option `preferredSlaves` along with `role: 'slave'` ioredis will attempt to use this value when selecting the slave from the pool of available slaves. The value of `preferredSlaves` should either be a function that accepts an array of available slaves and returns a single result, or an array of slave values priorities by the lowest `prio` value first with a default value of `1`. + +```javascript +// available slaves format +const availableSlaves = [{ ip: "127.0.0.1", port: "31231", flags: "slave" }]; + +// preferredSlaves array format +let preferredSlaves = [ + { ip: "127.0.0.1", port: "31231", prio: 1 }, + { ip: "127.0.0.1", port: "31232", prio: 2 }, +]; + +// preferredSlaves function format +preferredSlaves = function (availableSlaves) { + for (let i = 0; i < availableSlaves.length; i++) { + const slave = availableSlaves[i]; + if (slave.ip === "127.0.0.1") { + if (slave.port === "31234") { + return slave; + } + } + } + // if no preferred slaves are available a random one is used + return false; +}; + +const redis = new Redis({ + sentinels: [ + { host: "127.0.0.1", port: 26379 }, + { host: "127.0.0.1", port: 26380 }, + ], + name: "mymaster", + role: "slave", + preferredSlaves: preferredSlaves, +}); +``` + +Besides the `retryStrategy` option, there's also a `sentinelRetryStrategy` in Sentinel mode which will be invoked when all the sentinel nodes are unreachable during connecting. If `sentinelRetryStrategy` returns a valid delay time, ioredis will try to reconnect from scratch. The default value of `sentinelRetryStrategy` is: + +```javascript +function (times) { + const delay = Math.min(times * 10, 1000); + return delay; +} +``` + +## Cluster + +Redis Cluster provides a way to run a Redis installation where data is automatically sharded across multiple Redis nodes. +You can connect to a Redis Cluster like this: + +```javascript +const Redis = require("ioredis"); + +const cluster = new Redis.Cluster([ + { + port: 6380, + host: "127.0.0.1", + }, + { + port: 6381, + host: "127.0.0.1", + }, +]); + +cluster.set("foo", "bar"); +cluster.get("foo", (err, res) => { + // res === 'bar' +}); +``` + +`Cluster` constructor accepts two arguments, where: + +0. The first argument is a list of nodes of the cluster you want to connect to. + Just like Sentinel, the list does not need to enumerate all your cluster nodes, + but a few so that if one is unreachable the client will try the next one, and the client will discover other nodes automatically when at least one node is connected. +1. The second argument is the options, where: + + - `clusterRetryStrategy`: When none of the startup nodes are reachable, `clusterRetryStrategy` will be invoked. When a number is returned, + ioredis will try to reconnect to the startup nodes from scratch after the specified delay (in ms). Otherwise, an error of "None of startup nodes is available" will be returned. + The default value of this option is: + + ```javascript + function (times) { + const delay = Math.min(100 + times * 2, 2000); + return delay; + } + ``` + + It's possible to modify the `startupNodes` property in order to switch to another set of nodes here: + + ```javascript + function (times) { + this.startupNodes = [{ port: 6790, host: '127.0.0.1' }]; + return Math.min(100 + times * 2, 2000); + } + ``` + + - `dnsLookup`: Alternative DNS lookup function (`dns.lookup()` is used by default). It may be useful to override this in special cases, such as when AWS ElastiCache used with TLS enabled. + - `enableOfflineQueue`: Similar to the `enableOfflineQueue` option of `Redis` class. + - `enableReadyCheck`: When enabled, "ready" event will only be emitted when `CLUSTER INFO` command + reporting the cluster is ready for handling commands. Otherwise, it will be emitted immediately after "connect" is emitted. + - `scaleReads`: Config where to send the read queries. See below for more details. + - `maxRedirections`: When a cluster related error (e.g. `MOVED`, `ASK` and `CLUSTERDOWN` etc.) is received, the client will redirect the + command to another node. This option limits the max redirections allowed when sending a command. The default value is `16`. + - `retryDelayOnFailover`: If the target node is disconnected when sending a command, + ioredis will retry after the specified delay. The default value is `100`. You should make sure `retryDelayOnFailover * maxRedirections > cluster-node-timeout` + to insure that no command will fail during a failover. + - `retryDelayOnClusterDown`: When a cluster is down, all commands will be rejected with the error of `CLUSTERDOWN`. If this option is a number (by default, it is `100`), the client + will resend the commands after the specified time (in ms). + - `retryDelayOnTryAgain`: If this option is a number (by default, it is `100`), the client + will resend the commands rejected with `TRYAGAIN` error after the specified time (in ms). + - `retryDelayOnMoved`: By default, this value is `0` (in ms), which means when a `MOVED` error is received, the client will resend + the command instantly to the node returned together with the `MOVED` error. However, sometimes it takes time for a cluster to become + state stabilized after a failover, so adding a delay before resending can prevent a ping pong effect. + - `redisOptions`: Default options passed to the constructor of `Redis` when connecting to a node. + - `slotsRefreshTimeout`: Milliseconds before a timeout occurs while refreshing slots from the cluster (default `1000`). + - `slotsRefreshInterval`: Milliseconds between every automatic slots refresh (by default, it is disabled). + +### Read-Write Splitting + +A typical redis cluster contains three or more masters and several slaves for each master. It's possible to scale out redis cluster by sending read queries to slaves and write queries to masters by setting the `scaleReads` option. + +`scaleReads` is "master" by default, which means ioredis will never send any queries to slaves. There are other three available options: + +1. "all": Send write queries to masters and read queries to masters or slaves randomly. +2. "slave": Send write queries to masters and read queries to slaves. +3. a custom `function(nodes, command): node`: Will choose the custom function to select to which node to send read queries (write queries keep being sent to master). The first node in `nodes` is always the master serving the relevant slots. If the function returns an array of nodes, a random node of that list will be selected. + +For example: + +```javascript +const cluster = new Redis.Cluster( + [ + /* nodes */ + ], + { + scaleReads: "slave", + } +); +cluster.set("foo", "bar"); // This query will be sent to one of the masters. +cluster.get("foo", (err, res) => { + // This query will be sent to one of the slaves. +}); +``` + +**NB** In the code snippet above, the `res` may not be equal to "bar" because of the lag of replication between the master and slaves. + +### Running Commands to Multiple Nodes + +Every command will be sent to exactly one node. For commands containing keys, (e.g. `GET`, `SET` and `HGETALL`), ioredis sends them to the node that serving the keys, and for other commands not containing keys, (e.g. `INFO`, `KEYS` and `FLUSHDB`), ioredis sends them to a random node. + +Sometimes you may want to send a command to multiple nodes (masters or slaves) of the cluster, you can get the nodes via `Cluster#nodes()` method. + +`Cluster#nodes()` accepts a parameter role, which can be "master", "slave" and "all" (default), and returns an array of `Redis` instance. For example: + +```javascript +// Send `FLUSHDB` command to all slaves: +const slaves = cluster.nodes("slave"); +Promise.all(slaves.map((node) => node.flushdb())); + +// Get keys of all the masters: +const masters = cluster.nodes("master"); +Promise.all( + masters + .map((node) => node.keys()) + .then((keys) => { + // keys: [['key1', 'key2'], ['key3', 'key4']] + }) +); +``` + +### NAT Mapping + +Sometimes the cluster is hosted within a internal network that can only be accessed via a NAT (Network Address Translation) instance. See [Accessing ElastiCache from outside AWS](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/accessing-elasticache.html) as an example. + +You can specify nat mapping rules via `natMap` option: + +```javascript +const cluster = new Redis.Cluster( + [ + { + host: "203.0.113.73", + port: 30001, + }, + ], + { + natMap: { + "10.0.1.230:30001": { host: "203.0.113.73", port: 30001 }, + "10.0.1.231:30001": { host: "203.0.113.73", port: 30002 }, + "10.0.1.232:30001": { host: "203.0.113.73", port: 30003 }, + }, + } +); +``` + +Or you can specify this parameter through function: +```javascript +const cluster = new Redis.Cluster( + [ + { + host: "203.0.113.73", + port: 30001, + }, + ], + { + natMap: (key) => { + if(key.includes('30001')) { + return { host: "203.0.113.73", port: 30001 }; + } + + return null; + }, + } +); +``` + +This option is also useful when the cluster is running inside a Docker container. +Also it works for Clusters in cloud infrastructure where cluster nodes connected through dedicated subnet. + +Specifying through may be useful if you don't know concrete internal host and know only node port. + +### Transaction and Pipeline in Cluster Mode + +Almost all features that are supported by `Redis` are also supported by `Redis.Cluster`, e.g. custom commands, transaction and pipeline. +However there are some differences when using transaction and pipeline in Cluster mode: + +0. All keys in a pipeline should belong to slots served by the same node, since ioredis sends all commands in a pipeline to the same node. +1. You can't use `multi` without pipeline (aka `cluster.multi({ pipeline: false })`). This is because when you call `cluster.multi({ pipeline: false })`, ioredis doesn't know which node the `multi` command should be sent to. + +When any commands in a pipeline receives a `MOVED` or `ASK` error, ioredis will resend the whole pipeline to the specified node automatically if all of the following conditions are satisfied: + +0. All errors received in the pipeline are the same. For example, we won't resend the pipeline if we got two `MOVED` errors pointing to different nodes. +1. All commands executed successfully are readonly commands. This makes sure that resending the pipeline won't have side effects. + +### Pub/Sub + +Pub/Sub in cluster mode works exactly as the same as in standalone mode. Internally, when a node of the cluster receives a message, it will broadcast the message to the other nodes. ioredis makes sure that each message will only be received once by strictly subscribing one node at the same time. + +```javascript +const nodes = [ + /* nodes */ +]; +const pub = new Redis.Cluster(nodes); +const sub = new Redis.Cluster(nodes); +sub.on("message", (channel, message) => { + console.log(channel, message); +}); + +sub.subscribe("news", () => { + pub.publish("news", "highlights"); +}); +``` + +### Sharded Pub/Sub + +For sharded Pub/Sub, use the `spublish` and `ssubscribe` commands instead of the traditional `publish` and `subscribe`. With the old commands, the Redis cluster handles message propagation behind the scenes, allowing you to publish or subscribe to any node without considering sharding. However, this approach has scalability limitations that are addressed with sharded Pub/Sub. Here’s what you need to know: + +1. Instead of a single subscriber connection, there is now one subscriber connection per shard. Because of the potential overhead, you can enable or disable the use of the cluster subscriber group with the `shardedSubscribers` option. By default, this option is set to `false`, meaning sharded subscriptions are disabled. You should enable this option when establishing your cluster connection before using `ssubscribe`. +2. All channel names that you pass to a single `ssubscribe` need to map to the same hash slot. You can call `ssubscribe` multiple times on the same cluster client instance to subscribe to channels across slots. The cluster's subscriber group takes care of forwarding the `ssubscribe` command to the shard that is responsible for the channels. + +The following basic example shows you how to use sharded Pub/Sub: + +```javascript +const cluster: Cluster = new Cluster([{host: host, port: port}], {shardedSubscribers: true}); + +//Register the callback +cluster.on("smessage", (channel, message) => { + console.log(message); +}); + + +//Subscribe to the channels on the same slot +cluster.ssubscribe("channel{my}:1", "channel{my}:2").then( ( count: number ) => { + console.log(count); +}).catch( (err) => { + console.log(err); +}); + +//Publish a message +cluster.spublish("channel{my}:1", "This is a test message to my first channel.").then((value: number) => { + console.log("Published a message to channel{my}:1"); +}); +``` + + +### Events + +| Event | Description | +| :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| connect | emits when a connection is established to the Redis server. | +| ready | emits when `CLUSTER INFO` reporting the cluster is able to receive commands (if `enableReadyCheck` is `true`) or immediately after `connect` event (if `enableReadyCheck` is false). | +| error | emits when an error occurs while connecting with a property of `lastNodeError` representing the last node error received. This event is emitted silently (only emitting if there's at least one listener). | +| close | emits when an established Redis server connection has closed. | +| reconnecting | emits after `close` when a reconnection will be made. The argument of the event is the time (in ms) before reconnecting. | +| end | emits after `close` when no more reconnections will be made. | +| +node | emits when a new node is connected. | +| -node | emits when a node is disconnected. | +| node error | emits when an error occurs when connecting to a node. The second argument indicates the address of the node. | + +### Password + +Setting the `password` option to access password-protected clusters: + +```javascript +const Redis = require("ioredis"); +const cluster = new Redis.Cluster(nodes, { + redisOptions: { + password: "your-cluster-password", + }, +}); +``` + +If some of nodes in the cluster using a different password, you should specify them in the first parameter: + +```javascript +const Redis = require("ioredis"); +const cluster = new Redis.Cluster( + [ + // Use password "password-for-30001" for 30001 + { port: 30001, password: "password-for-30001" }, + // Don't use password when accessing 30002 + { port: 30002, password: null }, + // Other nodes will use "fallback-password" + ], + { + redisOptions: { + password: "fallback-password", + }, + } +); +``` + +### Special Note: Aws Elasticache Clusters with TLS + +AWS ElastiCache for Redis (Clustered Mode) supports TLS encryption. If you use +this, you may encounter errors with invalid certificates. To resolve this +issue, construct the `Cluster` with the `dnsLookup` option as follows: + +```javascript +const cluster = new Redis.Cluster( + [ + { + host: "clustercfg.myCluster.abcdefg.xyz.cache.amazonaws.com", + port: 6379, + }, + ], + { + dnsLookup: (address, callback) => callback(null, address), + redisOptions: { + tls: {}, + }, + } +); +``` + +
+ +## Autopipelining + +In standard mode, when you issue multiple commands, ioredis sends them to the server one by one. As described in Redis pipeline documentation, this is a suboptimal use of the network link, especially when such link is not very performant. + +The TCP and network overhead negatively affects performance. Commands are stuck in the send queue until the previous ones are correctly delivered to the server. This is a problem known as Head-Of-Line blocking (HOL). + +ioredis supports a feature called “auto pipelining”. It can be enabled by setting the option `enableAutoPipelining` to `true`. No other code change is necessary. + +In auto pipelining mode, all commands issued during an event loop are enqueued in a pipeline automatically managed by ioredis. At the end of the iteration, the pipeline is executed and thus all commands are sent to the server at the same time. + +This feature can dramatically improve throughput and avoids HOL blocking. In our benchmarks, the improvement was between 35% and 50%. + +While an automatic pipeline is executing, all new commands will be enqueued in a new pipeline which will be executed as soon as the previous finishes. + +When using Redis Cluster, one pipeline per node is created. Commands are assigned to pipelines according to which node serves the slot. + +A pipeline will thus contain commands using different slots but that ultimately are assigned to the same node. + +Note that the same slot limitation within a single command still holds, as it is a Redis limitation. + +### Example of Automatic Pipeline Enqueuing + +This sample code uses ioredis with automatic pipeline enabled. + +```javascript +const Redis = require("./built"); +const http = require("http"); + +const db = new Redis({ enableAutoPipelining: true }); + +const server = http.createServer((request, response) => { + const key = new URL(request.url, "https://localhost:3000/").searchParams.get( + "key" + ); + + db.get(key, (err, value) => { + response.writeHead(200, { "Content-Type": "text/plain" }); + response.end(value); + }); +}); + +server.listen(3000); +``` + +When Node receives requests, it schedules them to be processed in one or more iterations of the events loop. + +All commands issued by requests processing during one iteration of the loop will be wrapped in a pipeline automatically created by ioredis. + +In the example above, the pipeline will have the following contents: + +``` +GET key1 +GET key2 +GET key3 +... +GET keyN +``` + +When all events in the current loop have been processed, the pipeline is executed and thus all commands are sent to the server at the same time. + +While waiting for pipeline response from Redis, Node will still be able to process requests. All commands issued by request handler will be enqueued in a new automatically created pipeline. This pipeline will not be sent to the server yet. + +As soon as a previous automatic pipeline has received all responses from the server, the new pipeline is immediately sent without waiting for the events loop iteration to finish. + +This approach increases the utilization of the network link, reduces the TCP overhead and idle times and therefore improves throughput. + +### Benchmarks + +Here's some of the results of our tests for a single node. + +Each iteration of the test runs 1000 random commands on the server. + +| | Samples | Result | Tolerance | +| ------------------------- | ------- | ------------- | --------- | +| default | 1000 | 174.62 op/sec | ± 0.45 % | +| enableAutoPipelining=true | 1500 | 233.33 op/sec | ± 0.88 % | + +And here's the same test for a cluster of 3 masters and 3 replicas: + +| | Samples | Result | Tolerance | +| ------------------------- | ------- | ------------- | --------- | +| default | 1000 | 164.05 op/sec | ± 0.42 % | +| enableAutoPipelining=true | 3000 | 235.31 op/sec | ± 0.94 % | + +# Error Handling + +All the errors returned by the Redis server are instances of `ReplyError`, which can be accessed via `Redis`: + +```javascript +const Redis = require("ioredis"); +const redis = new Redis(); +// This command causes a reply error since the SET command requires two arguments. +redis.set("foo", (err) => { + err instanceof Redis.ReplyError; +}); +``` + +This is the error stack of the `ReplyError`: + +``` +ReplyError: ERR wrong number of arguments for 'set' command + at ReplyParser._parseResult (/app/node_modules/ioredis/lib/parsers/javascript.js:60:14) + at ReplyParser.execute (/app/node_modules/ioredis/lib/parsers/javascript.js:178:20) + at Socket. (/app/node_modules/ioredis/lib/redis/event_handler.js:99:22) + at Socket.emit (events.js:97:17) + at readableAddChunk (_stream_readable.js:143:16) + at Socket.Readable.push (_stream_readable.js:106:10) + at TCP.onread (net.js:509:20) +``` + +By default, the error stack doesn't make any sense because the whole stack happens in the ioredis +module itself, not in your code. So it's not easy to find out where the error happens in your code. +ioredis provides an option `showFriendlyErrorStack` to solve the problem. When you enable +`showFriendlyErrorStack`, ioredis will optimize the error stack for you: + +```javascript +const Redis = require("ioredis"); +const redis = new Redis({ showFriendlyErrorStack: true }); +redis.set("foo"); +``` + +And the output will be: + +``` +ReplyError: ERR wrong number of arguments for 'set' command + at Object. (/app/index.js:3:7) + at Module._compile (module.js:446:26) + at Object.Module._extensions..js (module.js:464:10) + at Module.load (module.js:341:32) + at Function.Module._load (module.js:296:12) + at Function.Module.runMain (module.js:487:10) + at startup (node.js:111:16) + at node.js:799:3 +``` + +This time the stack tells you that the error happens on the third line in your code. Pretty sweet! +However, it would decrease the performance significantly to optimize the error stack. So by +default, this option is disabled and can only be used for debugging purposes. You **shouldn't** use this feature in a production environment. + +# Running tests + +Start a Redis server on 127.0.0.1:6379, and then: + +```shell +npm test +``` + +`FLUSH ALL` will be invoked after each test, so make sure there's no valuable data in it before running tests. + +If your testing environment does not let you spin up a Redis server [ioredis-mock](https://github.com/stipsan/ioredis-mock) is a drop-in replacement you can use in your tests. It aims to behave identically to ioredis connected to a Redis server so that your integration tests is easier to write and of better quality. + +# Debug + +You can set the `DEBUG` env to `ioredis:*` to print debug info: + +```shell +$ DEBUG=ioredis:* node app.js +``` + +# Join in! + +I'm happy to receive bug reports, fixes, documentation enhancements, and any other improvements. + +And since I'm not a native English speaker, if you find any grammar mistakes in the documentation, please also let me know. :) + +# Contributors + +This project exists thanks to all the people who contribute: + + + +# License + +MIT + +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fluin%2Fioredis.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fluin%2Fioredis?ref=badge_large) diff --git a/backend/node_modules/ioredis/built/Command.d.ts b/backend/node_modules/ioredis/built/Command.d.ts new file mode 100644 index 0000000..1121bb8 --- /dev/null +++ b/backend/node_modules/ioredis/built/Command.d.ts @@ -0,0 +1,165 @@ +/// +import { Callback, Respondable, CommandParameter } from "./types"; +export declare type ArgumentType = string | Buffer | number | (string | Buffer | number | any[])[]; +interface CommandOptions { + /** + * Set the encoding of the reply, by default buffer will be returned. + */ + replyEncoding?: BufferEncoding | null; + errorStack?: Error; + keyPrefix?: string; + /** + * Force the command to be readOnly so it will also execute on slaves + */ + readOnly?: boolean; +} +declare type ArgumentTransformer = (args: any[]) => any[]; +declare type ReplyTransformer = (reply: any) => any; +export interface CommandNameFlags { + VALID_IN_SUBSCRIBER_MODE: [ + "subscribe", + "psubscribe", + "unsubscribe", + "punsubscribe", + "ssubscribe", + "sunsubscribe", + "ping", + "quit" + ]; + VALID_IN_MONITOR_MODE: ["monitor", "auth"]; + ENTER_SUBSCRIBER_MODE: ["subscribe", "psubscribe", "ssubscribe"]; + EXIT_SUBSCRIBER_MODE: ["unsubscribe", "punsubscribe", "sunsubscribe"]; + WILL_DISCONNECT: ["quit"]; + HANDSHAKE_COMMANDS: ["auth", "select", "client", "readonly", "info"]; + IGNORE_RECONNECT_ON_ERROR: ["client"]; + BLOCKING_COMMANDS: [ + "blpop", + "brpop", + "brpoplpush", + "blmove", + "bzpopmin", + "bzpopmax", + "bzmpop", + "blmpop", + "xread", + "xreadgroup" + ]; + LAST_ARG_TIMEOUT_COMMANDS: [ + "blpop", + "brpop", + "brpoplpush", + "blmove", + "bzpopmin", + "bzpopmax" + ]; + FIRST_ARG_TIMEOUT_COMMANDS: ["bzmpop", "blmpop"]; + BLOCK_OPTION_COMMANDS: ["xread", "xreadgroup"]; +} +/** + * Command instance + * + * It's rare that you need to create a Command instance yourself. + * + * ```js + * var infoCommand = new Command('info', null, function (err, result) { + * console.log('result', result); + * }); + * + * redis.sendCommand(infoCommand); + * + * // When no callback provided, Command instance will have a `promise` property, + * // which will resolve/reject with the result of the command. + * var getCommand = new Command('get', ['foo']); + * getCommand.promise.then(function (result) { + * console.log('result', result); + * }); + * ``` + */ +export default class Command implements Respondable { + name: string; + static FLAGS: { + [key in keyof CommandNameFlags]: CommandNameFlags[key]; + }; + private static flagMap?; + private static _transformer; + /** + * Check whether the command has the flag + */ + static checkFlag(flagName: T, commandName: string): commandName is CommandNameFlags[T][number]; + static setArgumentTransformer(name: string, func: ArgumentTransformer): void; + static setReplyTransformer(name: string, func: ReplyTransformer): void; + private static getFlagMap; + ignore?: boolean; + isReadOnly?: boolean; + args: CommandParameter[]; + inTransaction: boolean; + pipelineIndex?: number; + isResolved: boolean; + reject: (err: Error) => void; + resolve: (result: any) => void; + promise: Promise; + private replyEncoding; + private errorStack; + private bufferMode; + private callback; + private transformed; + private _commandTimeoutTimer?; + private _blockingTimeoutTimer?; + private _blockingDeadline?; + private slot?; + private keys?; + /** + * Creates an instance of Command. + * @param name Command name + * @param args An array of command arguments + * @param options + * @param callback The callback that handles the response. + * If omit, the response will be handled via Promise + */ + constructor(name: string, args?: Array, options?: CommandOptions, callback?: Callback); + getSlot(): number; + getKeys(): Array; + /** + * Convert command to writable buffer or string + */ + toWritable(_socket: object): string | Buffer; + stringifyArguments(): void; + /** + * Convert buffer/buffer[] to string/string[], + * and apply reply transformer. + */ + transformReply(result: Buffer | Buffer[]): string | string[] | Buffer | Buffer[]; + /** + * Set the wait time before terminating the attempt to execute a command + * and generating an error. + */ + setTimeout(ms: number): void; + /** + * Set a timeout for blocking commands. + * When the timeout expires, the command resolves with null (matching Redis behavior). + * This handles the case of undetectable network failures (e.g., docker network disconnect) + * where the TCP connection becomes a zombie and no close event fires. + */ + setBlockingTimeout(ms: number): void; + /** + * Extract the blocking timeout from the command arguments. + * + * @returns The timeout in seconds, null for indefinite blocking (timeout of 0), + * or undefined if this is not a blocking command + */ + extractBlockingTimeout(): number | null | undefined; + /** + * Clear the command and blocking timers + */ + private _clearTimers; + private initPromise; + /** + * Iterate through the command arguments that are considered keys. + */ + private _iterateKeys; + /** + * Convert the value from buffer to the target encoding. + */ + private _convertValue; +} +export {}; diff --git a/backend/node_modules/ioredis/built/Command.js b/backend/node_modules/ioredis/built/Command.js new file mode 100644 index 0000000..5069820 --- /dev/null +++ b/backend/node_modules/ioredis/built/Command.js @@ -0,0 +1,449 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const commands_1 = require("@ioredis/commands"); +const calculateSlot = require("cluster-key-slot"); +const standard_as_callback_1 = require("standard-as-callback"); +const utils_1 = require("./utils"); +const argumentParsers_1 = require("./utils/argumentParsers"); +/** + * Command instance + * + * It's rare that you need to create a Command instance yourself. + * + * ```js + * var infoCommand = new Command('info', null, function (err, result) { + * console.log('result', result); + * }); + * + * redis.sendCommand(infoCommand); + * + * // When no callback provided, Command instance will have a `promise` property, + * // which will resolve/reject with the result of the command. + * var getCommand = new Command('get', ['foo']); + * getCommand.promise.then(function (result) { + * console.log('result', result); + * }); + * ``` + */ +class Command { + /** + * Creates an instance of Command. + * @param name Command name + * @param args An array of command arguments + * @param options + * @param callback The callback that handles the response. + * If omit, the response will be handled via Promise + */ + constructor(name, args = [], options = {}, callback) { + this.name = name; + this.inTransaction = false; + this.isResolved = false; + this.transformed = false; + this.replyEncoding = options.replyEncoding; + this.errorStack = options.errorStack; + this.args = args.flat(); + this.callback = callback; + this.initPromise(); + if (options.keyPrefix) { + // @ts-expect-error + const isBufferKeyPrefix = options.keyPrefix instanceof Buffer; + // @ts-expect-error + let keyPrefixBuffer = isBufferKeyPrefix + ? options.keyPrefix + : null; + this._iterateKeys((key) => { + if (key instanceof Buffer) { + if (keyPrefixBuffer === null) { + keyPrefixBuffer = Buffer.from(options.keyPrefix); + } + return Buffer.concat([keyPrefixBuffer, key]); + } + else if (isBufferKeyPrefix) { + // @ts-expect-error + return Buffer.concat([options.keyPrefix, Buffer.from(String(key))]); + } + return options.keyPrefix + key; + }); + } + if (options.readOnly) { + this.isReadOnly = true; + } + } + /** + * Check whether the command has the flag + */ + static checkFlag(flagName, commandName) { + commandName = commandName.toLowerCase(); + return !!this.getFlagMap()[flagName][commandName]; + } + static setArgumentTransformer(name, func) { + this._transformer.argument[name] = func; + } + static setReplyTransformer(name, func) { + this._transformer.reply[name] = func; + } + static getFlagMap() { + if (!this.flagMap) { + this.flagMap = Object.keys(Command.FLAGS).reduce((map, flagName) => { + map[flagName] = {}; + Command.FLAGS[flagName].forEach((commandName) => { + map[flagName][commandName] = true; + }); + return map; + }, {}); + } + return this.flagMap; + } + getSlot() { + if (typeof this.slot === "undefined") { + const key = this.getKeys()[0]; + this.slot = key == null ? null : calculateSlot(key); + } + return this.slot; + } + getKeys() { + return this._iterateKeys(); + } + /** + * Convert command to writable buffer or string + */ + toWritable(_socket) { + let result; + const commandStr = "*" + + (this.args.length + 1) + + "\r\n$" + + Buffer.byteLength(this.name) + + "\r\n" + + this.name + + "\r\n"; + if (this.bufferMode) { + const buffers = new MixedBuffers(); + buffers.push(commandStr); + for (let i = 0; i < this.args.length; ++i) { + const arg = this.args[i]; + if (arg instanceof Buffer) { + if (arg.length === 0) { + buffers.push("$0\r\n\r\n"); + } + else { + buffers.push("$" + arg.length + "\r\n"); + buffers.push(arg); + buffers.push("\r\n"); + } + } + else { + buffers.push("$" + + Buffer.byteLength(arg) + + "\r\n" + + arg + + "\r\n"); + } + } + result = buffers.toBuffer(); + } + else { + result = commandStr; + for (let i = 0; i < this.args.length; ++i) { + const arg = this.args[i]; + result += + "$" + + Buffer.byteLength(arg) + + "\r\n" + + arg + + "\r\n"; + } + } + return result; + } + stringifyArguments() { + for (let i = 0; i < this.args.length; ++i) { + const arg = this.args[i]; + if (typeof arg === "string") { + // buffers and strings don't need any transformation + } + else if (arg instanceof Buffer) { + this.bufferMode = true; + } + else { + this.args[i] = (0, utils_1.toArg)(arg); + } + } + } + /** + * Convert buffer/buffer[] to string/string[], + * and apply reply transformer. + */ + transformReply(result) { + if (this.replyEncoding) { + result = (0, utils_1.convertBufferToString)(result, this.replyEncoding); + } + const transformer = Command._transformer.reply[this.name]; + if (transformer) { + result = transformer(result); + } + return result; + } + /** + * Set the wait time before terminating the attempt to execute a command + * and generating an error. + */ + setTimeout(ms) { + if (!this._commandTimeoutTimer) { + this._commandTimeoutTimer = setTimeout(() => { + if (!this.isResolved) { + this.reject(new Error("Command timed out")); + } + }, ms); + } + } + /** + * Set a timeout for blocking commands. + * When the timeout expires, the command resolves with null (matching Redis behavior). + * This handles the case of undetectable network failures (e.g., docker network disconnect) + * where the TCP connection becomes a zombie and no close event fires. + */ + setBlockingTimeout(ms) { + if (ms <= 0) { + return; + } + // Clear existing timer if any (can happen when command moves from offline to command queue) + if (this._blockingTimeoutTimer) { + clearTimeout(this._blockingTimeoutTimer); + this._blockingTimeoutTimer = undefined; + } + const now = Date.now(); + // First call: establish absolute deadline + if (this._blockingDeadline === undefined) { + this._blockingDeadline = now + ms; + } + // Check if we've already exceeded the deadline + const remaining = this._blockingDeadline - now; + if (remaining <= 0) { + // Resolve with null to indicate timeout (same as Redis behavior) + this.resolve(null); + return; + } + this._blockingTimeoutTimer = setTimeout(() => { + if (this.isResolved) { + this._blockingTimeoutTimer = undefined; + return; + } + this._blockingTimeoutTimer = undefined; + // Timeout expired - resolve with null (same as Redis behavior when blocking command times out) + this.resolve(null); + }, remaining); + } + /** + * Extract the blocking timeout from the command arguments. + * + * @returns The timeout in seconds, null for indefinite blocking (timeout of 0), + * or undefined if this is not a blocking command + */ + extractBlockingTimeout() { + const args = this.args; + if (!args || args.length === 0) { + return undefined; + } + const name = this.name.toLowerCase(); + if (Command.checkFlag("LAST_ARG_TIMEOUT_COMMANDS", name)) { + return (0, argumentParsers_1.parseSecondsArgument)(args[args.length - 1]); + } + if (Command.checkFlag("FIRST_ARG_TIMEOUT_COMMANDS", name)) { + return (0, argumentParsers_1.parseSecondsArgument)(args[0]); + } + if (Command.checkFlag("BLOCK_OPTION_COMMANDS", name)) { + return (0, argumentParsers_1.parseBlockOption)(args); + } + return undefined; + } + /** + * Clear the command and blocking timers + */ + _clearTimers() { + const existingTimer = this._commandTimeoutTimer; + if (existingTimer) { + clearTimeout(existingTimer); + delete this._commandTimeoutTimer; + } + const blockingTimer = this._blockingTimeoutTimer; + if (blockingTimer) { + clearTimeout(blockingTimer); + delete this._blockingTimeoutTimer; + } + } + initPromise() { + const promise = new Promise((resolve, reject) => { + if (!this.transformed) { + this.transformed = true; + const transformer = Command._transformer.argument[this.name]; + if (transformer) { + this.args = transformer(this.args); + } + this.stringifyArguments(); + } + this.resolve = this._convertValue(resolve); + this.reject = (err) => { + this._clearTimers(); + if (this.errorStack) { + reject((0, utils_1.optimizeErrorStack)(err, this.errorStack.stack, __dirname)); + } + else { + reject(err); + } + }; + }); + this.promise = (0, standard_as_callback_1.default)(promise, this.callback); + } + /** + * Iterate through the command arguments that are considered keys. + */ + _iterateKeys(transform = (key) => key) { + if (typeof this.keys === "undefined") { + this.keys = []; + if ((0, commands_1.exists)(this.name, { caseInsensitive: true })) { + // @ts-expect-error + const keyIndexes = (0, commands_1.getKeyIndexes)(this.name, this.args, { + nameCaseInsensitive: true, + }); + for (const index of keyIndexes) { + this.args[index] = transform(this.args[index]); + this.keys.push(this.args[index]); + } + } + } + return this.keys; + } + /** + * Convert the value from buffer to the target encoding. + */ + _convertValue(resolve) { + return (value) => { + try { + this._clearTimers(); + resolve(this.transformReply(value)); + this.isResolved = true; + } + catch (err) { + this.reject(err); + } + return this.promise; + }; + } +} +exports.default = Command; +Command.FLAGS = { + VALID_IN_SUBSCRIBER_MODE: [ + "subscribe", + "psubscribe", + "unsubscribe", + "punsubscribe", + "ssubscribe", + "sunsubscribe", + "ping", + "quit", + ], + VALID_IN_MONITOR_MODE: ["monitor", "auth"], + ENTER_SUBSCRIBER_MODE: ["subscribe", "psubscribe", "ssubscribe"], + EXIT_SUBSCRIBER_MODE: ["unsubscribe", "punsubscribe", "sunsubscribe"], + WILL_DISCONNECT: ["quit"], + HANDSHAKE_COMMANDS: ["auth", "select", "client", "readonly", "info"], + IGNORE_RECONNECT_ON_ERROR: ["client"], + BLOCKING_COMMANDS: [ + "blpop", + "brpop", + "brpoplpush", + "blmove", + "bzpopmin", + "bzpopmax", + "bzmpop", + "blmpop", + "xread", + "xreadgroup", + ], + LAST_ARG_TIMEOUT_COMMANDS: [ + "blpop", + "brpop", + "brpoplpush", + "blmove", + "bzpopmin", + "bzpopmax", + ], + FIRST_ARG_TIMEOUT_COMMANDS: ["bzmpop", "blmpop"], + BLOCK_OPTION_COMMANDS: ["xread", "xreadgroup"], +}; +Command._transformer = { + argument: {}, + reply: {}, +}; +const msetArgumentTransformer = function (args) { + if (args.length === 1) { + if (args[0] instanceof Map) { + return (0, utils_1.convertMapToArray)(args[0]); + } + if (typeof args[0] === "object" && args[0] !== null) { + return (0, utils_1.convertObjectToArray)(args[0]); + } + } + return args; +}; +const hsetArgumentTransformer = function (args) { + if (args.length === 2) { + if (args[1] instanceof Map) { + return [args[0]].concat((0, utils_1.convertMapToArray)(args[1])); + } + if (typeof args[1] === "object" && args[1] !== null) { + return [args[0]].concat((0, utils_1.convertObjectToArray)(args[1])); + } + } + return args; +}; +Command.setArgumentTransformer("mset", msetArgumentTransformer); +Command.setArgumentTransformer("msetnx", msetArgumentTransformer); +Command.setArgumentTransformer("hset", hsetArgumentTransformer); +Command.setArgumentTransformer("hmset", hsetArgumentTransformer); +Command.setReplyTransformer("hgetall", function (result) { + if (Array.isArray(result)) { + const obj = {}; + for (let i = 0; i < result.length; i += 2) { + const key = result[i]; + const value = result[i + 1]; + if (key in obj) { + // can only be truthy if the property is special somehow, like '__proto__' or 'constructor' + // https://github.com/luin/ioredis/issues/1267 + Object.defineProperty(obj, key, { + value, + configurable: true, + enumerable: true, + writable: true, + }); + } + else { + obj[key] = value; + } + } + return obj; + } + return result; +}); +class MixedBuffers { + constructor() { + this.length = 0; + this.items = []; + } + push(x) { + this.length += Buffer.byteLength(x); + this.items.push(x); + } + toBuffer() { + const result = Buffer.allocUnsafe(this.length); + let offset = 0; + for (const item of this.items) { + const length = Buffer.byteLength(item); + Buffer.isBuffer(item) + ? item.copy(result, offset) + : result.write(item, offset, length); + offset += length; + } + return result; + } +} diff --git a/backend/node_modules/ioredis/built/DataHandler.d.ts b/backend/node_modules/ioredis/built/DataHandler.d.ts new file mode 100644 index 0000000..93e97d9 --- /dev/null +++ b/backend/node_modules/ioredis/built/DataHandler.d.ts @@ -0,0 +1,37 @@ +/// +import { NetStream, CommandItem } from "./types"; +import Deque = require("denque"); +import { EventEmitter } from "events"; +import SubscriptionSet from "./SubscriptionSet"; +export interface Condition { + select: number; + auth?: string | [string, string]; + subscriber: false | SubscriptionSet; +} +export declare type FlushQueueOptions = { + offlineQueue?: boolean; + commandQueue?: boolean; +}; +export interface DataHandledable extends EventEmitter { + stream: NetStream; + status: string; + condition: Condition | null; + commandQueue: Deque; + disconnect(reconnect: boolean): void; + recoverFromFatalError(commandError: Error, err: Error, options: FlushQueueOptions): void; + handleReconnection(err: Error, item: CommandItem): void; +} +interface ParserOptions { + stringNumbers: boolean; +} +export default class DataHandler { + private redis; + constructor(redis: DataHandledable, parserOptions: ParserOptions); + private returnFatalError; + private returnError; + private returnReply; + private handleSubscriberReply; + private handleMonitorReply; + private shiftCommand; +} +export {}; diff --git a/backend/node_modules/ioredis/built/DataHandler.js b/backend/node_modules/ioredis/built/DataHandler.js new file mode 100644 index 0000000..7f95466 --- /dev/null +++ b/backend/node_modules/ioredis/built/DataHandler.js @@ -0,0 +1,224 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Command_1 = require("./Command"); +const utils_1 = require("./utils"); +const RedisParser = require("redis-parser"); +const SubscriptionSet_1 = require("./SubscriptionSet"); +const debug = (0, utils_1.Debug)("dataHandler"); +class DataHandler { + constructor(redis, parserOptions) { + this.redis = redis; + const parser = new RedisParser({ + stringNumbers: parserOptions.stringNumbers, + returnBuffers: true, + returnError: (err) => { + this.returnError(err); + }, + returnFatalError: (err) => { + this.returnFatalError(err); + }, + returnReply: (reply) => { + this.returnReply(reply); + }, + }); + // prependListener ensures the parser receives and processes data before socket timeout checks are performed + redis.stream.prependListener("data", (data) => { + parser.execute(data); + }); + // prependListener() doesn't enable flowing mode automatically - we need to resume the stream manually + redis.stream.resume(); + } + returnFatalError(err) { + err.message += ". Please report this."; + this.redis.recoverFromFatalError(err, err, { offlineQueue: false }); + } + returnError(err) { + const item = this.shiftCommand(err); + if (!item) { + return; + } + err.command = { + name: item.command.name, + args: item.command.args, + }; + if (item.command.name == "ssubscribe" && err.message.includes("MOVED")) { + this.redis.emit("moved"); + return; + } + this.redis.handleReconnection(err, item); + } + returnReply(reply) { + if (this.handleMonitorReply(reply)) { + return; + } + if (this.handleSubscriberReply(reply)) { + return; + } + const item = this.shiftCommand(reply); + if (!item) { + return; + } + if (Command_1.default.checkFlag("ENTER_SUBSCRIBER_MODE", item.command.name)) { + this.redis.condition.subscriber = new SubscriptionSet_1.default(); + this.redis.condition.subscriber.add(item.command.name, reply[1].toString()); + if (!fillSubCommand(item.command, reply[2])) { + this.redis.commandQueue.unshift(item); + } + } + else if (Command_1.default.checkFlag("EXIT_SUBSCRIBER_MODE", item.command.name)) { + if (!fillUnsubCommand(item.command, reply[2])) { + this.redis.commandQueue.unshift(item); + } + } + else { + item.command.resolve(reply); + } + } + handleSubscriberReply(reply) { + if (!this.redis.condition.subscriber) { + return false; + } + const replyType = Array.isArray(reply) ? reply[0].toString() : null; + debug('receive reply "%s" in subscriber mode', replyType); + switch (replyType) { + case "message": + if (this.redis.listeners("message").length > 0) { + // Check if there're listeners to avoid unnecessary `toString()`. + this.redis.emit("message", reply[1].toString(), reply[2] ? reply[2].toString() : ""); + } + this.redis.emit("messageBuffer", reply[1], reply[2]); + break; + case "pmessage": { + const pattern = reply[1].toString(); + if (this.redis.listeners("pmessage").length > 0) { + this.redis.emit("pmessage", pattern, reply[2].toString(), reply[3].toString()); + } + this.redis.emit("pmessageBuffer", pattern, reply[2], reply[3]); + break; + } + case "smessage": { + if (this.redis.listeners("smessage").length > 0) { + this.redis.emit("smessage", reply[1].toString(), reply[2] ? reply[2].toString() : ""); + } + this.redis.emit("smessageBuffer", reply[1], reply[2]); + break; + } + case "ssubscribe": + case "subscribe": + case "psubscribe": { + const channel = reply[1].toString(); + this.redis.condition.subscriber.add(replyType, channel); + const item = this.shiftCommand(reply); + if (!item) { + return; + } + if (!fillSubCommand(item.command, reply[2])) { + this.redis.commandQueue.unshift(item); + } + break; + } + case "sunsubscribe": + case "unsubscribe": + case "punsubscribe": { + const channel = reply[1] ? reply[1].toString() : null; + if (channel) { + this.redis.condition.subscriber.del(replyType, channel); + } + const count = reply[2]; + if (Number(count) === 0) { + this.redis.condition.subscriber = false; + } + const item = this.shiftCommand(reply); + if (!item) { + return; + } + if (!fillUnsubCommand(item.command, count)) { + this.redis.commandQueue.unshift(item); + } + break; + } + default: { + const item = this.shiftCommand(reply); + if (!item) { + return; + } + item.command.resolve(reply); + } + } + return true; + } + handleMonitorReply(reply) { + if (this.redis.status !== "monitoring") { + return false; + } + const replyStr = reply.toString(); + if (replyStr === "OK") { + // Valid commands in the monitoring mode are AUTH and MONITOR, + // both of which always reply with 'OK'. + // So if we got an 'OK', we can make certain that + // the reply is made to AUTH & MONITOR. + return false; + } + // Since commands sent in the monitoring mode will trigger an exception, + // any replies we received in the monitoring mode should consider to be + // realtime monitor data instead of result of commands. + const len = replyStr.indexOf(" "); + const timestamp = replyStr.slice(0, len); + const argIndex = replyStr.indexOf('"'); + const args = replyStr + .slice(argIndex + 1, -1) + .split('" "') + .map((elem) => elem.replace(/\\"/g, '"')); + const dbAndSource = replyStr.slice(len + 2, argIndex - 2).split(" "); + this.redis.emit("monitor", timestamp, args, dbAndSource[1], dbAndSource[0]); + return true; + } + shiftCommand(reply) { + const item = this.redis.commandQueue.shift(); + if (!item) { + const message = "Command queue state error. If you can reproduce this, please report it."; + const error = new Error(message + + (reply instanceof Error + ? ` Last error: ${reply.message}` + : ` Last reply: ${reply.toString()}`)); + this.redis.emit("error", error); + return null; + } + return item; + } +} +exports.default = DataHandler; +const remainingRepliesMap = new WeakMap(); +function fillSubCommand(command, count) { + let remainingReplies = remainingRepliesMap.has(command) + ? remainingRepliesMap.get(command) + : command.args.length; + remainingReplies -= 1; + if (remainingReplies <= 0) { + command.resolve(count); + remainingRepliesMap.delete(command); + return true; + } + remainingRepliesMap.set(command, remainingReplies); + return false; +} +function fillUnsubCommand(command, count) { + let remainingReplies = remainingRepliesMap.has(command) + ? remainingRepliesMap.get(command) + : command.args.length; + if (remainingReplies === 0) { + if (Number(count) === 0) { + remainingRepliesMap.delete(command); + command.resolve(count); + return true; + } + return false; + } + remainingReplies -= 1; + if (remainingReplies <= 0) { + command.resolve(count); + return true; + } + remainingRepliesMap.set(command, remainingReplies); + return false; +} diff --git a/backend/node_modules/ioredis/built/Pipeline.d.ts b/backend/node_modules/ioredis/built/Pipeline.d.ts new file mode 100644 index 0000000..8503d72 --- /dev/null +++ b/backend/node_modules/ioredis/built/Pipeline.d.ts @@ -0,0 +1,31 @@ +import Redis from "./Redis"; +import Cluster from "./cluster"; +import Command from "./Command"; +import Commander from "./utils/Commander"; +declare class Pipeline extends Commander<{ + type: "pipeline"; +}> { + redis: Redis | Cluster; + isCluster: boolean; + isPipeline: boolean; + leftRedirections: { + value?: number; + }; + promise: Promise; + resolve: (result: unknown) => void; + reject: (error: Error) => void; + private replyPending; + private _queue; + private _result; + private _transactions; + private _shaToScript; + private preferKey; + constructor(redis: Redis | Cluster); + fillResult(value: unknown[], position: number): void; + sendCommand(command: Command): unknown; + addBatch(commands: any): this; +} +export default Pipeline; +interface Pipeline { + length: number; +} diff --git a/backend/node_modules/ioredis/built/Pipeline.js b/backend/node_modules/ioredis/built/Pipeline.js new file mode 100644 index 0000000..c1c4566 --- /dev/null +++ b/backend/node_modules/ioredis/built/Pipeline.js @@ -0,0 +1,342 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const calculateSlot = require("cluster-key-slot"); +const commands_1 = require("@ioredis/commands"); +const standard_as_callback_1 = require("standard-as-callback"); +const util_1 = require("util"); +const Command_1 = require("./Command"); +const utils_1 = require("./utils"); +const Commander_1 = require("./utils/Commander"); +/* + This function derives from the cluster-key-slot implementation. + Instead of checking that all keys have the same slot, it checks that all slots are served by the same set of nodes. + If this is satisfied, it returns the first key's slot. +*/ +function generateMultiWithNodes(redis, keys) { + const slot = calculateSlot(keys[0]); + const target = redis._groupsBySlot[slot]; + for (let i = 1; i < keys.length; i++) { + if (redis._groupsBySlot[calculateSlot(keys[i])] !== target) { + return -1; + } + } + return slot; +} +class Pipeline extends Commander_1.default { + constructor(redis) { + super(); + this.redis = redis; + this.isPipeline = true; + this.replyPending = 0; + this._queue = []; + this._result = []; + this._transactions = 0; + this._shaToScript = {}; + this.isCluster = + this.redis.constructor.name === "Cluster" || this.redis.isCluster; + this.options = redis.options; + Object.keys(redis.scriptsSet).forEach((name) => { + const script = redis.scriptsSet[name]; + this._shaToScript[script.sha] = script; + this[name] = redis[name]; + this[name + "Buffer"] = redis[name + "Buffer"]; + }); + redis.addedBuiltinSet.forEach((name) => { + this[name] = redis[name]; + this[name + "Buffer"] = redis[name + "Buffer"]; + }); + this.promise = new Promise((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + const _this = this; + Object.defineProperty(this, "length", { + get: function () { + return _this._queue.length; + }, + }); + } + fillResult(value, position) { + if (this._queue[position].name === "exec" && Array.isArray(value[1])) { + const execLength = value[1].length; + for (let i = 0; i < execLength; i++) { + if (value[1][i] instanceof Error) { + continue; + } + const cmd = this._queue[position - (execLength - i)]; + try { + value[1][i] = cmd.transformReply(value[1][i]); + } + catch (err) { + value[1][i] = err; + } + } + } + this._result[position] = value; + if (--this.replyPending) { + return; + } + if (this.isCluster) { + let retriable = true; + let commonError; + for (let i = 0; i < this._result.length; ++i) { + const error = this._result[i][0]; + const command = this._queue[i]; + if (error) { + if (command.name === "exec" && + error.message === + "EXECABORT Transaction discarded because of previous errors.") { + continue; + } + if (!commonError) { + commonError = { + name: error.name, + message: error.message, + }; + } + else if (commonError.name !== error.name || + commonError.message !== error.message) { + retriable = false; + break; + } + } + else if (!command.inTransaction) { + const isReadOnly = (0, commands_1.exists)(command.name, { caseInsensitive: true }) && + (0, commands_1.hasFlag)(command.name, "readonly", { nameCaseInsensitive: true }); + if (!isReadOnly) { + retriable = false; + break; + } + } + } + if (commonError && retriable) { + const _this = this; + const errv = commonError.message.split(" "); + const queue = this._queue; + let inTransaction = false; + this._queue = []; + for (let i = 0; i < queue.length; ++i) { + if (errv[0] === "ASK" && + !inTransaction && + queue[i].name !== "asking" && + (!queue[i - 1] || queue[i - 1].name !== "asking")) { + const asking = new Command_1.default("asking"); + asking.ignore = true; + this.sendCommand(asking); + } + queue[i].initPromise(); + this.sendCommand(queue[i]); + inTransaction = queue[i].inTransaction; + } + let matched = true; + if (typeof this.leftRedirections === "undefined") { + this.leftRedirections = {}; + } + const exec = function () { + _this.exec(); + }; + const cluster = this.redis; + cluster.handleError(commonError, this.leftRedirections, { + moved: function (_slot, key) { + _this.preferKey = key; + if (cluster.slots[errv[1]]) { + if (cluster.slots[errv[1]][0] !== key) { + cluster.slots[errv[1]] = [key]; + } + } + else { + cluster.slots[errv[1]] = [key]; + } + cluster._groupsBySlot[errv[1]] = + cluster._groupsIds[cluster.slots[errv[1]].join(";")]; + cluster.refreshSlotsCache(); + _this.exec(); + }, + ask: function (_slot, key) { + _this.preferKey = key; + _this.exec(); + }, + tryagain: exec, + clusterDown: exec, + connectionClosed: exec, + maxRedirections: () => { + matched = false; + }, + defaults: () => { + matched = false; + }, + }); + if (matched) { + return; + } + } + } + let ignoredCount = 0; + for (let i = 0; i < this._queue.length - ignoredCount; ++i) { + if (this._queue[i + ignoredCount].ignore) { + ignoredCount += 1; + } + this._result[i] = this._result[i + ignoredCount]; + } + this.resolve(this._result.slice(0, this._result.length - ignoredCount)); + } + sendCommand(command) { + if (this._transactions > 0) { + command.inTransaction = true; + } + const position = this._queue.length; + command.pipelineIndex = position; + command.promise + .then((result) => { + this.fillResult([null, result], position); + }) + .catch((error) => { + this.fillResult([error], position); + }); + this._queue.push(command); + return this; + } + addBatch(commands) { + let command, commandName, args; + for (let i = 0; i < commands.length; ++i) { + command = commands[i]; + commandName = command[0]; + args = command.slice(1); + this[commandName].apply(this, args); + } + return this; + } +} +exports.default = Pipeline; +// @ts-expect-error +const multi = Pipeline.prototype.multi; +// @ts-expect-error +Pipeline.prototype.multi = function () { + this._transactions += 1; + return multi.apply(this, arguments); +}; +// @ts-expect-error +const execBuffer = Pipeline.prototype.execBuffer; +// @ts-expect-error +Pipeline.prototype.execBuffer = (0, util_1.deprecate)(function () { + if (this._transactions > 0) { + this._transactions -= 1; + } + return execBuffer.apply(this, arguments); +}, "Pipeline#execBuffer: Use Pipeline#exec instead"); +// NOTE: To avoid an unhandled promise rejection, this will unconditionally always return this.promise, +// which always has the rejection handled by standard-as-callback +// adding the provided rejection callback. +// +// If a different promise instance were returned, that promise would cause its own unhandled promise rejection +// errors, even if that promise unconditionally resolved to **the resolved value of** this.promise. +Pipeline.prototype.exec = function (callback) { + // Wait for the cluster to be connected, since we need nodes information before continuing + if (this.isCluster && !this.redis.slots.length) { + if (this.redis.status === "wait") + this.redis.connect().catch(utils_1.noop); + if (callback && !this.nodeifiedPromise) { + this.nodeifiedPromise = true; + (0, standard_as_callback_1.default)(this.promise, callback); + } + this.redis.delayUntilReady((err) => { + if (err) { + this.reject(err); + return; + } + this.exec(callback); + }); + return this.promise; + } + if (this._transactions > 0) { + this._transactions -= 1; + return execBuffer.apply(this, arguments); + } + if (!this.nodeifiedPromise) { + this.nodeifiedPromise = true; + (0, standard_as_callback_1.default)(this.promise, callback); + } + if (!this._queue.length) { + this.resolve([]); + } + let pipelineSlot; + if (this.isCluster) { + // List of the first key for each command + const sampleKeys = []; + for (let i = 0; i < this._queue.length; i++) { + const keys = this._queue[i].getKeys(); + if (keys.length) { + sampleKeys.push(keys[0]); + } + // For each command, check that the keys belong to the same slot + if (keys.length && calculateSlot.generateMulti(keys) < 0) { + this.reject(new Error("All the keys in a pipeline command should belong to the same slot")); + return this.promise; + } + } + if (sampleKeys.length) { + pipelineSlot = generateMultiWithNodes(this.redis, sampleKeys); + if (pipelineSlot < 0) { + this.reject(new Error("All keys in the pipeline should belong to the same slots allocation group")); + return this.promise; + } + } + else { + // Send the pipeline to a random node + pipelineSlot = (Math.random() * 16384) | 0; + } + } + const _this = this; + execPipeline(); + return this.promise; + function execPipeline() { + let writePending = (_this.replyPending = _this._queue.length); + let node; + if (_this.isCluster) { + node = { + slot: pipelineSlot, + redis: _this.redis.connectionPool.nodes.all[_this.preferKey], + }; + } + let data = ""; + let buffers; + const stream = { + isPipeline: true, + destination: _this.isCluster ? node : { redis: _this.redis }, + write(writable) { + if (typeof writable !== "string") { + if (!buffers) { + buffers = []; + } + if (data) { + buffers.push(Buffer.from(data, "utf8")); + data = ""; + } + buffers.push(writable); + } + else { + data += writable; + } + if (!--writePending) { + if (buffers) { + if (data) { + buffers.push(Buffer.from(data, "utf8")); + } + stream.destination.redis.stream.write(Buffer.concat(buffers)); + } + else { + stream.destination.redis.stream.write(data); + } + // Reset writePending for resending + writePending = _this._queue.length; + data = ""; + buffers = undefined; + } + }, + }; + for (let i = 0; i < _this._queue.length; ++i) { + _this.redis.sendCommand(_this._queue[i], stream, node); + } + return _this.promise; + } +}; diff --git a/backend/node_modules/ioredis/built/Redis.d.ts b/backend/node_modules/ioredis/built/Redis.d.ts new file mode 100644 index 0000000..5cc73b0 --- /dev/null +++ b/backend/node_modules/ioredis/built/Redis.d.ts @@ -0,0 +1,232 @@ +/// +import { EventEmitter } from "events"; +import Cluster from "./cluster"; +import Command from "./Command"; +import { DataHandledable, FlushQueueOptions, Condition } from "./DataHandler"; +import { RedisOptions } from "./redis/RedisOptions"; +import ScanStream from "./ScanStream"; +import { Transaction } from "./transaction"; +import { Callback, CommandItem, NetStream, ScanStreamOptions, WriteableStream } from "./types"; +import Commander from "./utils/Commander"; +import Deque = require("denque"); +declare type RedisStatus = "wait" | "reconnecting" | "connecting" | "connect" | "ready" | "close" | "end"; +/** + * This is the major component of ioredis. + * Use it to connect to a standalone Redis server or Sentinels. + * + * ```typescript + * const redis = new Redis(); // Default port is 6379 + * async function main() { + * redis.set("foo", "bar"); + * redis.get("foo", (err, result) => { + * // `result` should be "bar" + * console.log(err, result); + * }); + * // Or use Promise + * const result = await redis.get("foo"); + * } + * ``` + */ +declare class Redis extends Commander implements DataHandledable { + static Cluster: typeof Cluster; + static Command: typeof Command; + /** + * Default options + */ + private static defaultOptions; + /** + * Create a Redis instance. + * This is the same as `new Redis()` but is included for compatibility with node-redis. + */ + static createClient(...args: ConstructorParameters): Redis; + options: RedisOptions; + status: RedisStatus; + /** + * @ignore + */ + stream: NetStream; + /** + * @ignore + */ + isCluster: boolean; + /** + * @ignore + */ + condition: Condition | null; + /** + * @ignore + */ + commandQueue: Deque; + private connector; + private reconnectTimeout; + private offlineQueue; + private connectionEpoch; + private retryAttempts; + private manuallyClosing; + private socketTimeoutTimer; + private _autoPipelines; + private _runningAutoPipelines; + constructor(port: number, host: string, options: RedisOptions); + constructor(path: string, options: RedisOptions); + constructor(port: number, options: RedisOptions); + constructor(port: number, host: string); + constructor(options: RedisOptions); + constructor(port: number); + constructor(path: string); + constructor(); + get autoPipelineQueueSize(): number; + /** + * Create a connection to Redis. + * This method will be invoked automatically when creating a new Redis instance + * unless `lazyConnect: true` is passed. + * + * When calling this method manually, a Promise is returned, which will + * be resolved when the connection status is ready. The promise can reject + * if the connection fails, times out, or if Redis is already connecting/connected. + */ + connect(callback?: Callback): Promise; + /** + * Disconnect from Redis. + * + * This method closes the connection immediately, + * and may lose some pending replies that haven't written to client. + * If you want to wait for the pending replies, use Redis#quit instead. + */ + disconnect(reconnect?: boolean): void; + /** + * Disconnect from Redis. + * + * @deprecated + */ + end(): void; + /** + * Create a new instance with the same options as the current one. + * + * @example + * ```js + * var redis = new Redis(6380); + * var anotherRedis = redis.duplicate(); + * ``` + */ + duplicate(override?: Partial): Redis; + /** + * Mode of the connection. + * + * One of `"normal"`, `"subscriber"`, or `"monitor"`. When the connection is + * not in `"normal"` mode, certain commands are not allowed. + */ + get mode(): "normal" | "subscriber" | "monitor"; + /** + * Listen for all requests received by the server in real time. + * + * This command will create a new connection to Redis and send a + * MONITOR command via the new connection in order to avoid disturbing + * the current connection. + * + * @param callback The callback function. If omit, a promise will be returned. + * @example + * ```js + * var redis = new Redis(); + * redis.monitor(function (err, monitor) { + * // Entering monitoring mode. + * monitor.on('monitor', function (time, args, source, database) { + * console.log(time + ": " + util.inspect(args)); + * }); + * }); + * + * // supports promise as well as other commands + * redis.monitor().then(function (monitor) { + * monitor.on('monitor', function (time, args, source, database) { + * console.log(time + ": " + util.inspect(args)); + * }); + * }); + * ``` + */ + monitor(callback?: Callback): Promise; + /** + * Send a command to Redis + * + * This method is used internally and in most cases you should not + * use it directly. If you need to send a command that is not supported + * by the library, you can use the `call` method: + * + * ```js + * const redis = new Redis(); + * + * redis.call('set', 'foo', 'bar'); + * // or + * redis.call(['set', 'foo', 'bar']); + * ``` + * + * @ignore + */ + sendCommand(command: Command, stream?: WriteableStream): unknown; + private getBlockingTimeoutInMs; + private getConfiguredBlockingTimeout; + private setSocketTimeout; + scanStream(options?: ScanStreamOptions): ScanStream; + scanBufferStream(options?: ScanStreamOptions): ScanStream; + sscanStream(key: string, options?: ScanStreamOptions): ScanStream; + sscanBufferStream(key: string, options?: ScanStreamOptions): ScanStream; + hscanStream(key: string, options?: ScanStreamOptions): ScanStream; + hscanBufferStream(key: string, options?: ScanStreamOptions): ScanStream; + zscanStream(key: string, options?: ScanStreamOptions): ScanStream; + zscanBufferStream(key: string, options?: ScanStreamOptions): ScanStream; + /** + * Emit only when there's at least one listener. + * + * @ignore + */ + silentEmit(eventName: string, arg?: unknown): boolean; + /** + * @ignore + */ + recoverFromFatalError(_commandError: Error, err: Error, options: FlushQueueOptions): void; + /** + * @ignore + */ + handleReconnection(err: Error, item: CommandItem): void; + /** + * Get description of the connection. Used for debugging. + */ + private _getDescription; + private resetCommandQueue; + private resetOfflineQueue; + private parseOptions; + /** + * Change instance's status + */ + private setStatus; + private createScanStream; + /** + * Flush offline queue and command queue with error. + * + * @param error The error object to send to the commands + * @param options options + */ + private flushQueue; + /** + * Check whether Redis has finished loading the persistent data and is able to + * process commands. + */ + private _readyCheck; +} +interface Redis extends EventEmitter { + on(event: "message", cb: (channel: string, message: string) => void): this; + once(event: "message", cb: (channel: string, message: string) => void): this; + on(event: "messageBuffer", cb: (channel: Buffer, message: Buffer) => void): this; + once(event: "messageBuffer", cb: (channel: Buffer, message: Buffer) => void): this; + on(event: "pmessage", cb: (pattern: string, channel: string, message: string) => void): this; + once(event: "pmessage", cb: (pattern: string, channel: string, message: string) => void): this; + on(event: "pmessageBuffer", cb: (pattern: string, channel: Buffer, message: Buffer) => void): this; + once(event: "pmessageBuffer", cb: (pattern: string, channel: Buffer, message: Buffer) => void): this; + on(event: "error", cb: (error: Error) => void): this; + once(event: "error", cb: (error: Error) => void): this; + on(event: RedisStatus, cb: () => void): this; + once(event: RedisStatus, cb: () => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; +} +interface Redis extends Transaction { +} +export default Redis; diff --git a/backend/node_modules/ioredis/built/Redis.js b/backend/node_modules/ioredis/built/Redis.js new file mode 100644 index 0000000..6c9bdfd --- /dev/null +++ b/backend/node_modules/ioredis/built/Redis.js @@ -0,0 +1,745 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const commands_1 = require("@ioredis/commands"); +const events_1 = require("events"); +const standard_as_callback_1 = require("standard-as-callback"); +const cluster_1 = require("./cluster"); +const Command_1 = require("./Command"); +const connectors_1 = require("./connectors"); +const SentinelConnector_1 = require("./connectors/SentinelConnector"); +const eventHandler = require("./redis/event_handler"); +const RedisOptions_1 = require("./redis/RedisOptions"); +const ScanStream_1 = require("./ScanStream"); +const transaction_1 = require("./transaction"); +const utils_1 = require("./utils"); +const applyMixin_1 = require("./utils/applyMixin"); +const Commander_1 = require("./utils/Commander"); +const lodash_1 = require("./utils/lodash"); +const Deque = require("denque"); +const debug = (0, utils_1.Debug)("redis"); +/** + * This is the major component of ioredis. + * Use it to connect to a standalone Redis server or Sentinels. + * + * ```typescript + * const redis = new Redis(); // Default port is 6379 + * async function main() { + * redis.set("foo", "bar"); + * redis.get("foo", (err, result) => { + * // `result` should be "bar" + * console.log(err, result); + * }); + * // Or use Promise + * const result = await redis.get("foo"); + * } + * ``` + */ +class Redis extends Commander_1.default { + constructor(arg1, arg2, arg3) { + super(); + this.status = "wait"; + /** + * @ignore + */ + this.isCluster = false; + this.reconnectTimeout = null; + this.connectionEpoch = 0; + this.retryAttempts = 0; + this.manuallyClosing = false; + // Prepare autopipelines structures + this._autoPipelines = new Map(); + this._runningAutoPipelines = new Set(); + this.parseOptions(arg1, arg2, arg3); + events_1.EventEmitter.call(this); + this.resetCommandQueue(); + this.resetOfflineQueue(); + if (this.options.Connector) { + this.connector = new this.options.Connector(this.options); + } + else if (this.options.sentinels) { + const sentinelConnector = new SentinelConnector_1.default(this.options); + sentinelConnector.emitter = this; + this.connector = sentinelConnector; + } + else { + this.connector = new connectors_1.StandaloneConnector(this.options); + } + if (this.options.scripts) { + Object.entries(this.options.scripts).forEach(([name, definition]) => { + this.defineCommand(name, definition); + }); + } + // end(or wait) -> connecting -> connect -> ready -> end + if (this.options.lazyConnect) { + this.setStatus("wait"); + } + else { + this.connect().catch(lodash_1.noop); + } + } + /** + * Create a Redis instance. + * This is the same as `new Redis()` but is included for compatibility with node-redis. + */ + static createClient(...args) { + return new Redis(...args); + } + get autoPipelineQueueSize() { + let queued = 0; + for (const pipeline of this._autoPipelines.values()) { + queued += pipeline.length; + } + return queued; + } + /** + * Create a connection to Redis. + * This method will be invoked automatically when creating a new Redis instance + * unless `lazyConnect: true` is passed. + * + * When calling this method manually, a Promise is returned, which will + * be resolved when the connection status is ready. The promise can reject + * if the connection fails, times out, or if Redis is already connecting/connected. + */ + connect(callback) { + const promise = new Promise((resolve, reject) => { + if (this.status === "connecting" || + this.status === "connect" || + this.status === "ready") { + reject(new Error("Redis is already connecting/connected")); + return; + } + this.connectionEpoch += 1; + this.setStatus("connecting"); + const { options } = this; + this.condition = { + select: options.db, + auth: options.username + ? [options.username, options.password] + : options.password, + subscriber: false, + }; + const _this = this; + (0, standard_as_callback_1.default)(this.connector.connect(function (type, err) { + _this.silentEmit(type, err); + }), function (err, stream) { + if (err) { + _this.flushQueue(err); + _this.silentEmit("error", err); + reject(err); + _this.setStatus("end"); + return; + } + let CONNECT_EVENT = options.tls ? "secureConnect" : "connect"; + if ("sentinels" in options && + options.sentinels && + !options.enableTLSForSentinelMode) { + CONNECT_EVENT = "connect"; + } + _this.stream = stream; + if (options.noDelay) { + stream.setNoDelay(true); + } + // Node ignores setKeepAlive before connect, therefore we wait for the event: + // https://github.com/nodejs/node/issues/31663 + if (typeof options.keepAlive === "number") { + if (stream.connecting) { + stream.once(CONNECT_EVENT, () => { + stream.setKeepAlive(true, options.keepAlive); + }); + } + else { + stream.setKeepAlive(true, options.keepAlive); + } + } + if (stream.connecting) { + stream.once(CONNECT_EVENT, eventHandler.connectHandler(_this)); + if (options.connectTimeout) { + /* + * Typically, Socket#setTimeout(0) will clear the timer + * set before. However, in some platforms (Electron 3.x~4.x), + * the timer will not be cleared. So we introduce a variable here. + * + * See https://github.com/electron/electron/issues/14915 + */ + let connectTimeoutCleared = false; + stream.setTimeout(options.connectTimeout, function () { + if (connectTimeoutCleared) { + return; + } + stream.setTimeout(0); + stream.destroy(); + const err = new Error("connect ETIMEDOUT"); + // @ts-expect-error + err.errorno = "ETIMEDOUT"; + // @ts-expect-error + err.code = "ETIMEDOUT"; + // @ts-expect-error + err.syscall = "connect"; + eventHandler.errorHandler(_this)(err); + }); + stream.once(CONNECT_EVENT, function () { + connectTimeoutCleared = true; + stream.setTimeout(0); + }); + } + } + else if (stream.destroyed) { + const firstError = _this.connector.firstError; + if (firstError) { + process.nextTick(() => { + eventHandler.errorHandler(_this)(firstError); + }); + } + process.nextTick(eventHandler.closeHandler(_this)); + } + else { + process.nextTick(eventHandler.connectHandler(_this)); + } + if (!stream.destroyed) { + stream.once("error", eventHandler.errorHandler(_this)); + stream.once("close", eventHandler.closeHandler(_this)); + } + const connectionReadyHandler = function () { + _this.removeListener("close", connectionCloseHandler); + resolve(); + }; + var connectionCloseHandler = function () { + _this.removeListener("ready", connectionReadyHandler); + reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG)); + }; + _this.once("ready", connectionReadyHandler); + _this.once("close", connectionCloseHandler); + }); + }); + return (0, standard_as_callback_1.default)(promise, callback); + } + /** + * Disconnect from Redis. + * + * This method closes the connection immediately, + * and may lose some pending replies that haven't written to client. + * If you want to wait for the pending replies, use Redis#quit instead. + */ + disconnect(reconnect = false) { + if (!reconnect) { + this.manuallyClosing = true; + } + if (this.reconnectTimeout && !reconnect) { + clearTimeout(this.reconnectTimeout); + this.reconnectTimeout = null; + } + if (this.status === "wait") { + eventHandler.closeHandler(this)(); + } + else { + this.connector.disconnect(); + } + } + /** + * Disconnect from Redis. + * + * @deprecated + */ + end() { + this.disconnect(); + } + /** + * Create a new instance with the same options as the current one. + * + * @example + * ```js + * var redis = new Redis(6380); + * var anotherRedis = redis.duplicate(); + * ``` + */ + duplicate(override) { + return new Redis({ ...this.options, ...override }); + } + /** + * Mode of the connection. + * + * One of `"normal"`, `"subscriber"`, or `"monitor"`. When the connection is + * not in `"normal"` mode, certain commands are not allowed. + */ + get mode() { + var _a; + return this.options.monitor + ? "monitor" + : ((_a = this.condition) === null || _a === void 0 ? void 0 : _a.subscriber) + ? "subscriber" + : "normal"; + } + /** + * Listen for all requests received by the server in real time. + * + * This command will create a new connection to Redis and send a + * MONITOR command via the new connection in order to avoid disturbing + * the current connection. + * + * @param callback The callback function. If omit, a promise will be returned. + * @example + * ```js + * var redis = new Redis(); + * redis.monitor(function (err, monitor) { + * // Entering monitoring mode. + * monitor.on('monitor', function (time, args, source, database) { + * console.log(time + ": " + util.inspect(args)); + * }); + * }); + * + * // supports promise as well as other commands + * redis.monitor().then(function (monitor) { + * monitor.on('monitor', function (time, args, source, database) { + * console.log(time + ": " + util.inspect(args)); + * }); + * }); + * ``` + */ + monitor(callback) { + const monitorInstance = this.duplicate({ + monitor: true, + lazyConnect: false, + }); + return (0, standard_as_callback_1.default)(new Promise(function (resolve, reject) { + monitorInstance.once("error", reject); + monitorInstance.once("monitoring", function () { + resolve(monitorInstance); + }); + }), callback); + } + /** + * Send a command to Redis + * + * This method is used internally and in most cases you should not + * use it directly. If you need to send a command that is not supported + * by the library, you can use the `call` method: + * + * ```js + * const redis = new Redis(); + * + * redis.call('set', 'foo', 'bar'); + * // or + * redis.call(['set', 'foo', 'bar']); + * ``` + * + * @ignore + */ + sendCommand(command, stream) { + var _a, _b; + if (this.status === "wait") { + this.connect().catch(lodash_1.noop); + } + if (this.status === "end") { + command.reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG)); + return command.promise; + } + if (((_a = this.condition) === null || _a === void 0 ? void 0 : _a.subscriber) && + !Command_1.default.checkFlag("VALID_IN_SUBSCRIBER_MODE", command.name)) { + command.reject(new Error("Connection in subscriber mode, only subscriber commands may be used")); + return command.promise; + } + if (typeof this.options.commandTimeout === "number") { + command.setTimeout(this.options.commandTimeout); + } + const blockingTimeout = this.getBlockingTimeoutInMs(command); + let writable = this.status === "ready" || + (!stream && + this.status === "connect" && + (0, commands_1.exists)(command.name, { caseInsensitive: true }) && + ((0, commands_1.hasFlag)(command.name, "loading", { nameCaseInsensitive: true }) || + Command_1.default.checkFlag("HANDSHAKE_COMMANDS", command.name))); + if (!this.stream) { + writable = false; + } + else if (!this.stream.writable) { + writable = false; + // @ts-expect-error + } + else if (this.stream._writableState && this.stream._writableState.ended) { + // TODO: We should be able to remove this as the PR has already been merged. + // https://github.com/iojs/io.js/pull/1217 + writable = false; + } + if (!writable) { + if (!this.options.enableOfflineQueue) { + command.reject(new Error("Stream isn't writeable and enableOfflineQueue options is false")); + return command.promise; + } + if (command.name === "quit" && this.offlineQueue.length === 0) { + this.disconnect(); + command.resolve(Buffer.from("OK")); + return command.promise; + } + // @ts-expect-error + if (debug.enabled) { + debug("queue command[%s]: %d -> %s(%o)", this._getDescription(), this.condition.select, command.name, command.args); + } + this.offlineQueue.push({ + command: command, + stream: stream, + select: this.condition.select, + }); + // For blocking commands in the offline queue, arm a client-side timeout + // only when blockingTimeout is configured. Without this option, queued + // blocking commands may wait indefinitely on a dead connection. + if (Command_1.default.checkFlag("BLOCKING_COMMANDS", command.name)) { + const offlineTimeout = this.getConfiguredBlockingTimeout(); + if (offlineTimeout !== undefined) { + command.setBlockingTimeout(offlineTimeout); + } + } + } + else { + // @ts-expect-error + if (debug.enabled) { + debug("write command[%s]: %d -> %s(%o)", this._getDescription(), (_b = this.condition) === null || _b === void 0 ? void 0 : _b.select, command.name, command.args); + } + if (stream) { + if ("isPipeline" in stream && stream.isPipeline) { + stream.write(command.toWritable(stream.destination.redis.stream)); + } + else { + stream.write(command.toWritable(stream)); + } + } + else { + this.stream.write(command.toWritable(this.stream)); + } + this.commandQueue.push({ + command: command, + stream: stream, + select: this.condition.select, + }); + if (blockingTimeout !== undefined) { + command.setBlockingTimeout(blockingTimeout); + } + if (Command_1.default.checkFlag("WILL_DISCONNECT", command.name)) { + this.manuallyClosing = true; + } + if (this.options.socketTimeout !== undefined && this.socketTimeoutTimer === undefined) { + this.setSocketTimeout(); + } + } + if (command.name === "select" && (0, utils_1.isInt)(command.args[0])) { + const db = parseInt(command.args[0], 10); + if (this.condition.select !== db) { + this.condition.select = db; + this.emit("select", db); + debug("switch to db [%d]", this.condition.select); + } + } + return command.promise; + } + getBlockingTimeoutInMs(command) { + var _a; + if (!Command_1.default.checkFlag("BLOCKING_COMMANDS", command.name)) { + return undefined; + } + // Feature is opt-in: only enabled when blockingTimeout is set to a positive number + const configuredTimeout = this.getConfiguredBlockingTimeout(); + if (configuredTimeout === undefined) { + return undefined; + } + const timeout = command.extractBlockingTimeout(); + if (typeof timeout === "number") { + if (timeout > 0) { + // Finite timeout from command args - add grace period + return timeout + ((_a = this.options.blockingTimeoutGrace) !== null && _a !== void 0 ? _a : RedisOptions_1.DEFAULT_REDIS_OPTIONS.blockingTimeoutGrace); + } + // Command has timeout=0 (block forever), use blockingTimeout option as safety net + return configuredTimeout; + } + if (timeout === null) { + // No BLOCK option found (e.g., XREAD without BLOCK), use blockingTimeout as safety net + return configuredTimeout; + } + return undefined; + } + getConfiguredBlockingTimeout() { + if (typeof this.options.blockingTimeout === "number" && + this.options.blockingTimeout > 0) { + return this.options.blockingTimeout; + } + return undefined; + } + setSocketTimeout() { + this.socketTimeoutTimer = setTimeout(() => { + this.stream.destroy(new Error(`Socket timeout. Expecting data, but didn't receive any in ${this.options.socketTimeout}ms.`)); + this.socketTimeoutTimer = undefined; + }, this.options.socketTimeout); + // this handler must run after the "data" handler in "DataHandler" + // so that `this.commandQueue.length` will be updated + this.stream.once("data", () => { + clearTimeout(this.socketTimeoutTimer); + this.socketTimeoutTimer = undefined; + if (this.commandQueue.length === 0) + return; + this.setSocketTimeout(); + }); + } + scanStream(options) { + return this.createScanStream("scan", { options }); + } + scanBufferStream(options) { + return this.createScanStream("scanBuffer", { options }); + } + sscanStream(key, options) { + return this.createScanStream("sscan", { key, options }); + } + sscanBufferStream(key, options) { + return this.createScanStream("sscanBuffer", { key, options }); + } + hscanStream(key, options) { + return this.createScanStream("hscan", { key, options }); + } + hscanBufferStream(key, options) { + return this.createScanStream("hscanBuffer", { key, options }); + } + zscanStream(key, options) { + return this.createScanStream("zscan", { key, options }); + } + zscanBufferStream(key, options) { + return this.createScanStream("zscanBuffer", { key, options }); + } + /** + * Emit only when there's at least one listener. + * + * @ignore + */ + silentEmit(eventName, arg) { + let error; + if (eventName === "error") { + error = arg; + if (this.status === "end") { + return; + } + if (this.manuallyClosing) { + // ignore connection related errors when manually disconnecting + if (error instanceof Error && + (error.message === utils_1.CONNECTION_CLOSED_ERROR_MSG || + // @ts-expect-error + error.syscall === "connect" || + // @ts-expect-error + error.syscall === "read")) { + return; + } + } + } + if (this.listeners(eventName).length > 0) { + return this.emit.apply(this, arguments); + } + if (error && error instanceof Error) { + console.error("[ioredis] Unhandled error event:", error.stack); + } + return false; + } + /** + * @ignore + */ + recoverFromFatalError(_commandError, err, options) { + this.flushQueue(err, options); + this.silentEmit("error", err); + this.disconnect(true); + } + /** + * @ignore + */ + handleReconnection(err, item) { + var _a; + let needReconnect = false; + if (this.options.reconnectOnError && + !Command_1.default.checkFlag("IGNORE_RECONNECT_ON_ERROR", item.command.name)) { + needReconnect = this.options.reconnectOnError(err); + } + switch (needReconnect) { + case 1: + case true: + if (this.status !== "reconnecting") { + this.disconnect(true); + } + item.command.reject(err); + break; + case 2: + if (this.status !== "reconnecting") { + this.disconnect(true); + } + if (((_a = this.condition) === null || _a === void 0 ? void 0 : _a.select) !== item.select && + item.command.name !== "select") { + this.select(item.select); + } + // TODO + // @ts-expect-error + this.sendCommand(item.command); + break; + default: + item.command.reject(err); + } + } + /** + * Get description of the connection. Used for debugging. + */ + _getDescription() { + let description; + if ("path" in this.options && this.options.path) { + description = this.options.path; + } + else if (this.stream && + this.stream.remoteAddress && + this.stream.remotePort) { + description = this.stream.remoteAddress + ":" + this.stream.remotePort; + } + else if ("host" in this.options && this.options.host) { + description = this.options.host + ":" + this.options.port; + } + else { + // Unexpected + description = ""; + } + if (this.options.connectionName) { + description += ` (${this.options.connectionName})`; + } + return description; + } + resetCommandQueue() { + this.commandQueue = new Deque(); + } + resetOfflineQueue() { + this.offlineQueue = new Deque(); + } + parseOptions(...args) { + const options = {}; + let isTls = false; + for (let i = 0; i < args.length; ++i) { + const arg = args[i]; + if (arg === null || typeof arg === "undefined") { + continue; + } + if (typeof arg === "object") { + (0, lodash_1.defaults)(options, arg); + } + else if (typeof arg === "string") { + (0, lodash_1.defaults)(options, (0, utils_1.parseURL)(arg)); + if (arg.startsWith("rediss://")) { + isTls = true; + } + } + else if (typeof arg === "number") { + options.port = arg; + } + else { + throw new Error("Invalid argument " + arg); + } + } + if (isTls) { + (0, lodash_1.defaults)(options, { tls: true }); + } + (0, lodash_1.defaults)(options, Redis.defaultOptions); + if (typeof options.port === "string") { + options.port = parseInt(options.port, 10); + } + if (typeof options.db === "string") { + options.db = parseInt(options.db, 10); + } + // @ts-expect-error + this.options = (0, utils_1.resolveTLSProfile)(options); + } + /** + * Change instance's status + */ + setStatus(status, arg) { + // @ts-expect-error + if (debug.enabled) { + debug("status[%s]: %s -> %s", this._getDescription(), this.status || "[empty]", status); + } + this.status = status; + process.nextTick(this.emit.bind(this, status, arg)); + } + createScanStream(command, { key, options = {} }) { + return new ScanStream_1.default({ + objectMode: true, + key: key, + redis: this, + command: command, + ...options, + }); + } + /** + * Flush offline queue and command queue with error. + * + * @param error The error object to send to the commands + * @param options options + */ + flushQueue(error, options) { + options = (0, lodash_1.defaults)({}, options, { + offlineQueue: true, + commandQueue: true, + }); + let item; + if (options.offlineQueue) { + while ((item = this.offlineQueue.shift())) { + item.command.reject(error); + } + } + if (options.commandQueue) { + if (this.commandQueue.length > 0) { + if (this.stream) { + this.stream.removeAllListeners("data"); + } + while ((item = this.commandQueue.shift())) { + item.command.reject(error); + } + } + } + } + /** + * Check whether Redis has finished loading the persistent data and is able to + * process commands. + */ + _readyCheck(callback) { + const _this = this; + this.info(function (err, res) { + if (err) { + if (err.message && err.message.includes("NOPERM")) { + console.warn(`Skipping the ready check because INFO command fails: "${err.message}". You can disable ready check with "enableReadyCheck". More: https://github.com/luin/ioredis/wiki/Disable-ready-check.`); + return callback(null, {}); + } + return callback(err); + } + if (typeof res !== "string") { + return callback(null, res); + } + const info = {}; + const lines = res.split("\r\n"); + for (let i = 0; i < lines.length; ++i) { + const [fieldName, ...fieldValueParts] = lines[i].split(":"); + const fieldValue = fieldValueParts.join(":"); + if (fieldValue) { + info[fieldName] = fieldValue; + } + } + if (!info.loading || info.loading === "0") { + callback(null, info); + } + else { + const loadingEtaMs = (info.loading_eta_seconds || 1) * 1000; + const retryTime = _this.options.maxLoadingRetryTime && + _this.options.maxLoadingRetryTime < loadingEtaMs + ? _this.options.maxLoadingRetryTime + : loadingEtaMs; + debug("Redis server still loading, trying again in " + retryTime + "ms"); + setTimeout(function () { + _this._readyCheck(callback); + }, retryTime); + } + }).catch(lodash_1.noop); + } +} +Redis.Cluster = cluster_1.default; +Redis.Command = Command_1.default; +/** + * Default options + */ +Redis.defaultOptions = RedisOptions_1.DEFAULT_REDIS_OPTIONS; +(0, applyMixin_1.default)(Redis, events_1.EventEmitter); +(0, transaction_1.addTransactionSupport)(Redis.prototype); +exports.default = Redis; diff --git a/backend/node_modules/ioredis/built/ScanStream.d.ts b/backend/node_modules/ioredis/built/ScanStream.d.ts new file mode 100644 index 0000000..38c3803 --- /dev/null +++ b/backend/node_modules/ioredis/built/ScanStream.d.ts @@ -0,0 +1,23 @@ +/// +import { Readable, ReadableOptions } from "stream"; +interface Options extends ReadableOptions { + key?: string; + match?: string; + type?: string; + command: string; + redis: any; + count?: string | number; + noValues?: boolean; +} +/** + * Convenient class to convert the process of scanning keys to a readable stream. + */ +export default class ScanStream extends Readable { + private opt; + private _redisCursor; + private _redisDrained; + constructor(opt: Options); + _read(): void; + close(): void; +} +export {}; diff --git a/backend/node_modules/ioredis/built/ScanStream.js b/backend/node_modules/ioredis/built/ScanStream.js new file mode 100644 index 0000000..3abecaf --- /dev/null +++ b/backend/node_modules/ioredis/built/ScanStream.js @@ -0,0 +1,51 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = require("stream"); +/** + * Convenient class to convert the process of scanning keys to a readable stream. + */ +class ScanStream extends stream_1.Readable { + constructor(opt) { + super(opt); + this.opt = opt; + this._redisCursor = "0"; + this._redisDrained = false; + } + _read() { + if (this._redisDrained) { + this.push(null); + return; + } + const args = [this._redisCursor]; + if (this.opt.key) { + args.unshift(this.opt.key); + } + if (this.opt.match) { + args.push("MATCH", this.opt.match); + } + if (this.opt.type) { + args.push("TYPE", this.opt.type); + } + if (this.opt.count) { + args.push("COUNT", String(this.opt.count)); + } + if (this.opt.noValues) { + args.push("NOVALUES"); + } + this.opt.redis[this.opt.command](args, (err, res) => { + if (err) { + this.emit("error", err); + return; + } + this._redisCursor = res[0] instanceof Buffer ? res[0].toString() : res[0]; + if (this._redisCursor === "0") { + this._redisDrained = true; + } + this.push(res[1]); + }); + } + close() { + this._redisDrained = true; + } +} +exports.default = ScanStream; diff --git a/backend/node_modules/ioredis/built/Script.d.ts b/backend/node_modules/ioredis/built/Script.d.ts new file mode 100644 index 0000000..b17f4d8 --- /dev/null +++ b/backend/node_modules/ioredis/built/Script.d.ts @@ -0,0 +1,11 @@ +import { Callback } from "./types"; +export default class Script { + private lua; + private numberOfKeys; + private keyPrefix; + private readOnly; + private sha; + private Command; + constructor(lua: string, numberOfKeys?: number | null, keyPrefix?: string, readOnly?: boolean); + execute(container: any, args: any[], options: any, callback?: Callback): any; +} diff --git a/backend/node_modules/ioredis/built/Script.js b/backend/node_modules/ioredis/built/Script.js new file mode 100644 index 0000000..34ea485 --- /dev/null +++ b/backend/node_modules/ioredis/built/Script.js @@ -0,0 +1,62 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const Command_1 = require("./Command"); +const standard_as_callback_1 = require("standard-as-callback"); +class Script { + constructor(lua, numberOfKeys = null, keyPrefix = "", readOnly = false) { + this.lua = lua; + this.numberOfKeys = numberOfKeys; + this.keyPrefix = keyPrefix; + this.readOnly = readOnly; + this.sha = (0, crypto_1.createHash)("sha1").update(lua).digest("hex"); + const sha = this.sha; + const socketHasScriptLoaded = new WeakSet(); + this.Command = class CustomScriptCommand extends Command_1.default { + toWritable(socket) { + const origReject = this.reject; + this.reject = (err) => { + if (err.message.indexOf("NOSCRIPT") !== -1) { + socketHasScriptLoaded.delete(socket); + } + origReject.call(this, err); + }; + if (!socketHasScriptLoaded.has(socket)) { + socketHasScriptLoaded.add(socket); + this.name = "eval"; + this.args[0] = lua; + } + else if (this.name === "eval") { + this.name = "evalsha"; + this.args[0] = sha; + } + return super.toWritable(socket); + } + }; + } + execute(container, args, options, callback) { + if (typeof this.numberOfKeys === "number") { + args.unshift(this.numberOfKeys); + } + if (this.keyPrefix) { + options.keyPrefix = this.keyPrefix; + } + if (this.readOnly) { + options.readOnly = true; + } + const evalsha = new this.Command("evalsha", [this.sha, ...args], options); + evalsha.promise = evalsha.promise.catch((err) => { + if (err.message.indexOf("NOSCRIPT") === -1) { + throw err; + } + // Resend the same custom evalsha command that gets transformed + // to an eval in case it's not loaded yet on the connection. + const resend = new this.Command("evalsha", [this.sha, ...args], options); + const client = container.isPipeline ? container.redis : container; + return client.sendCommand(resend); + }); + (0, standard_as_callback_1.default)(evalsha.promise, callback); + return container.sendCommand(evalsha); + } +} +exports.default = Script; diff --git a/backend/node_modules/ioredis/built/SubscriptionSet.d.ts b/backend/node_modules/ioredis/built/SubscriptionSet.d.ts new file mode 100644 index 0000000..2b5c7cc --- /dev/null +++ b/backend/node_modules/ioredis/built/SubscriptionSet.d.ts @@ -0,0 +1,14 @@ +import { CommandNameFlags } from "./Command"; +declare type AddSet = CommandNameFlags["ENTER_SUBSCRIBER_MODE"][number]; +declare type DelSet = CommandNameFlags["EXIT_SUBSCRIBER_MODE"][number]; +/** + * Tiny class to simplify dealing with subscription set + */ +export default class SubscriptionSet { + private set; + add(set: AddSet, channel: string): void; + del(set: DelSet, channel: string): void; + channels(set: AddSet | DelSet): string[]; + isEmpty(): boolean; +} +export {}; diff --git a/backend/node_modules/ioredis/built/SubscriptionSet.js b/backend/node_modules/ioredis/built/SubscriptionSet.js new file mode 100644 index 0000000..df39e61 --- /dev/null +++ b/backend/node_modules/ioredis/built/SubscriptionSet.js @@ -0,0 +1,41 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Tiny class to simplify dealing with subscription set + */ +class SubscriptionSet { + constructor() { + this.set = { + subscribe: {}, + psubscribe: {}, + ssubscribe: {}, + }; + } + add(set, channel) { + this.set[mapSet(set)][channel] = true; + } + del(set, channel) { + delete this.set[mapSet(set)][channel]; + } + channels(set) { + return Object.keys(this.set[mapSet(set)]); + } + isEmpty() { + return (this.channels("subscribe").length === 0 && + this.channels("psubscribe").length === 0 && + this.channels("ssubscribe").length === 0); + } +} +exports.default = SubscriptionSet; +function mapSet(set) { + if (set === "unsubscribe") { + return "subscribe"; + } + if (set === "punsubscribe") { + return "psubscribe"; + } + if (set === "sunsubscribe") { + return "ssubscribe"; + } + return set; +} diff --git a/backend/node_modules/ioredis/built/autoPipelining.d.ts b/backend/node_modules/ioredis/built/autoPipelining.d.ts new file mode 100644 index 0000000..64505fc --- /dev/null +++ b/backend/node_modules/ioredis/built/autoPipelining.d.ts @@ -0,0 +1,8 @@ +/// +import { ArgumentType } from "./Command"; +export declare const kExec: unique symbol; +export declare const kCallbacks: unique symbol; +export declare const notAllowedAutoPipelineCommands: string[]; +export declare function shouldUseAutoPipelining(client: any, functionName: string, commandName: string): boolean; +export declare function getFirstValueInFlattenedArray(args: ArgumentType[]): string | Buffer | number | null | undefined; +export declare function executeWithAutoPipelining(client: any, functionName: string, commandName: string, args: ArgumentType[], callback: any): Promise; diff --git a/backend/node_modules/ioredis/built/autoPipelining.js b/backend/node_modules/ioredis/built/autoPipelining.js new file mode 100644 index 0000000..b3d416a --- /dev/null +++ b/backend/node_modules/ioredis/built/autoPipelining.js @@ -0,0 +1,167 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.executeWithAutoPipelining = exports.getFirstValueInFlattenedArray = exports.shouldUseAutoPipelining = exports.notAllowedAutoPipelineCommands = exports.kCallbacks = exports.kExec = void 0; +const lodash_1 = require("./utils/lodash"); +const calculateSlot = require("cluster-key-slot"); +const standard_as_callback_1 = require("standard-as-callback"); +const commands_1 = require("@ioredis/commands"); +exports.kExec = Symbol("exec"); +exports.kCallbacks = Symbol("callbacks"); +exports.notAllowedAutoPipelineCommands = [ + "auth", + "info", + "script", + "quit", + "cluster", + "pipeline", + "multi", + "subscribe", + "psubscribe", + "unsubscribe", + "unpsubscribe", + "select", + "client", +]; +function executeAutoPipeline(client, slotKey) { + /* + If a pipeline is already executing, keep queueing up commands + since ioredis won't serve two pipelines at the same time + */ + if (client._runningAutoPipelines.has(slotKey)) { + return; + } + if (!client._autoPipelines.has(slotKey)) { + /* + Rare edge case. Somehow, something has deleted this running autopipeline in an immediate + call to executeAutoPipeline. + + Maybe the callback in the pipeline.exec is sometimes called in the same tick, + e.g. if redis is disconnected? + */ + return; + } + client._runningAutoPipelines.add(slotKey); + // Get the pipeline and immediately delete it so that new commands are queued on a new pipeline + const pipeline = client._autoPipelines.get(slotKey); + client._autoPipelines.delete(slotKey); + const callbacks = pipeline[exports.kCallbacks]; + // Stop keeping a reference to callbacks immediately after the callbacks stop being used. + // This allows the GC to reclaim objects referenced by callbacks, especially with 16384 slots + // in Redis.Cluster + pipeline[exports.kCallbacks] = null; + // Perform the call + pipeline.exec(function (err, results) { + client._runningAutoPipelines.delete(slotKey); + /* + Invoke all callback in nextTick so the stack is cleared + and callbacks can throw errors without affecting other callbacks. + */ + if (err) { + for (let i = 0; i < callbacks.length; i++) { + process.nextTick(callbacks[i], err); + } + } + else { + for (let i = 0; i < callbacks.length; i++) { + process.nextTick(callbacks[i], ...results[i]); + } + } + // If there is another pipeline on the same node, immediately execute it without waiting for nextTick + if (client._autoPipelines.has(slotKey)) { + executeAutoPipeline(client, slotKey); + } + }); +} +function shouldUseAutoPipelining(client, functionName, commandName) { + return (functionName && + client.options.enableAutoPipelining && + !client.isPipeline && + !exports.notAllowedAutoPipelineCommands.includes(commandName) && + !client.options.autoPipeliningIgnoredCommands.includes(commandName)); +} +exports.shouldUseAutoPipelining = shouldUseAutoPipelining; +function getFirstValueInFlattenedArray(args) { + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (typeof arg === "string") { + return arg; + } + else if (Array.isArray(arg) || (0, lodash_1.isArguments)(arg)) { + if (arg.length === 0) { + continue; + } + return arg[0]; + } + const flattened = [arg].flat(); + if (flattened.length > 0) { + return flattened[0]; + } + } + return undefined; +} +exports.getFirstValueInFlattenedArray = getFirstValueInFlattenedArray; +function executeWithAutoPipelining(client, functionName, commandName, args, callback) { + // On cluster mode let's wait for slots to be available + if (client.isCluster && !client.slots.length) { + if (client.status === "wait") + client.connect().catch(lodash_1.noop); + return (0, standard_as_callback_1.default)(new Promise(function (resolve, reject) { + client.delayUntilReady((err) => { + if (err) { + reject(err); + return; + } + executeWithAutoPipelining(client, functionName, commandName, args, null).then(resolve, reject); + }); + }), callback); + } + // If we have slot information, we can improve routing by grouping slots served by the same subset of nodes + // Note that the first value in args may be a (possibly empty) array. + // ioredis will only flatten one level of the array, in the Command constructor. + const prefix = client.options.keyPrefix || ""; + let slotKey = client.isCluster + ? client.slots[calculateSlot(`${prefix}${getFirstValueInFlattenedArray(args)}`)].join(",") + : "main"; + // When scaleReads is enabled, separate read and write commands into different pipelines + // so they can be routed to replicas and masters respectively + if (client.isCluster && client.options.scaleReads !== "master") { + const isReadOnly = (0, commands_1.exists)(commandName) && (0, commands_1.hasFlag)(commandName, "readonly"); + slotKey += isReadOnly ? ":read" : ":write"; + } + if (!client._autoPipelines.has(slotKey)) { + const pipeline = client.pipeline(); + pipeline[exports.kExec] = false; + pipeline[exports.kCallbacks] = []; + client._autoPipelines.set(slotKey, pipeline); + } + const pipeline = client._autoPipelines.get(slotKey); + /* + Mark the pipeline as scheduled. + The symbol will make sure that the pipeline is only scheduled once per tick. + New commands are appended to an already scheduled pipeline. + */ + if (!pipeline[exports.kExec]) { + pipeline[exports.kExec] = true; + /* + Deferring with setImmediate so we have a chance to capture multiple + commands that can be scheduled by I/O events already in the event loop queue. + */ + setImmediate(executeAutoPipeline, client, slotKey); + } + // Create the promise which will execute the command in the pipeline. + const autoPipelinePromise = new Promise(function (resolve, reject) { + pipeline[exports.kCallbacks].push(function (err, value) { + if (err) { + reject(err); + return; + } + resolve(value); + }); + if (functionName === "call") { + args.unshift(commandName); + } + pipeline[functionName](...args); + }); + return (0, standard_as_callback_1.default)(autoPipelinePromise, callback); +} +exports.executeWithAutoPipelining = executeWithAutoPipelining; diff --git a/backend/node_modules/ioredis/built/cluster/ClusterOptions.d.ts b/backend/node_modules/ioredis/built/cluster/ClusterOptions.d.ts new file mode 100644 index 0000000..80c7e2c --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ClusterOptions.d.ts @@ -0,0 +1,172 @@ +/// +import { SrvRecord } from "dns"; +import { RedisOptions } from "../redis/RedisOptions"; +import { CommanderOptions } from "../utils/Commander"; +import { NodeRole } from "./util"; +export declare type DNSResolveSrvFunction = (hostname: string, callback: (err: NodeJS.ErrnoException | null | undefined, records?: SrvRecord[]) => void) => void; +export declare type DNSLookupFunction = (hostname: string, callback: (err: NodeJS.ErrnoException | null | undefined, address: string, family?: number) => void) => void; +export declare type NatMapFunction = (key: string) => { + host: string; + port: number; +} | null; +export declare type NatMap = { + [key: string]: { + host: string; + port: number; + }; +} | NatMapFunction; +/** + * Options for Cluster constructor + */ +export interface ClusterOptions extends CommanderOptions { + /** + * See "Quick Start" section. + * + * @default (times) => Math.min(100 + times * 2, 2000) + */ + clusterRetryStrategy?: ((times: number, reason?: Error) => number | void | null) | undefined; + /** + * See Redis class. + * + * @default true + */ + enableOfflineQueue?: boolean | undefined; + /** + * When enabled, ioredis only emits "ready" event when `CLUSTER INFO` + * command reporting the cluster is ready for handling commands. + * + * @default true + */ + enableReadyCheck?: boolean | undefined; + /** + * Scale reads to the node with the specified role. + * + * @default "master" + */ + scaleReads?: NodeRole | Function | undefined; + /** + * When a MOVED or ASK error is received, client will redirect the + * command to another node. + * This option limits the max redirections allowed to send a command. + * + * @default 16 + */ + maxRedirections?: number | undefined; + /** + * When an error is received when sending a command (e.g. + * "Connection is closed." when the target Redis node is down), client will retry + * if `retryDelayOnFailover` is valid delay time (in ms). + * + * @default 100 + */ + retryDelayOnFailover?: number | undefined; + /** + * When a CLUSTERDOWN error is received, client will retry + * if `retryDelayOnClusterDown` is valid delay time (in ms). + * + * @default 100 + */ + retryDelayOnClusterDown?: number | undefined; + /** + * When a TRYAGAIN error is received, client will retry + * if `retryDelayOnTryAgain` is valid delay time (in ms). + * + * @default 100 + */ + retryDelayOnTryAgain?: number | undefined; + /** + * By default, this value is 0, which means when a `MOVED` error is received, + * the client will resend the command instantly to the node returned together with + * the `MOVED` error. However, sometimes it takes time for a cluster to become + * state stabilized after a failover, so adding a delay before resending can + * prevent a ping pong effect. + * + * @default 0 + */ + retryDelayOnMoved?: number | undefined; + /** + * The milliseconds before a timeout occurs while refreshing + * slots from the cluster. + * + * @default 1000 + */ + slotsRefreshTimeout?: number | undefined; + /** + * The milliseconds between every automatic slots refresh. + * + * @default 5000 + */ + slotsRefreshInterval?: number | undefined; + /** + * Use sharded subscribers instead of a single subscriber. + * + * If sharded subscribers are used, then one additional subscriber connection per master node + * is established. If you don't plan to use SPUBLISH/SSUBSCRIBE, then this should be disabled. + * + * @default false + */ + shardedSubscribers?: boolean | undefined; + /** + * Passed to the constructor of `Redis` + * + * @default null + */ + redisOptions?: Omit | undefined; + /** + * By default, When a new Cluster instance is created, + * it will connect to the Redis cluster automatically. + * If you want to keep the instance disconnected until the first command is called, + * set this option to `true`. + * + * @default false + */ + lazyConnect?: boolean | undefined; + /** + * Discover nodes using SRV records + * + * @default false + */ + useSRVRecords?: boolean | undefined; + /** + * SRV records will be resolved via this function. + * + * You may provide a custom `resolveSrv` function when you want to customize + * the cache behavior of the default function. + * + * @default require('dns').resolveSrv + */ + resolveSrv?: DNSResolveSrvFunction | undefined; + /** + * Hostnames will be resolved to IP addresses via this function. + * This is needed when the addresses of startup nodes are hostnames instead + * of IPs. + * + * You may provide a custom `lookup` function when you want to customize + * the cache behavior of the default function. + * + * @default require('dns').lookup + */ + dnsLookup?: DNSLookupFunction | undefined; + natMap?: NatMap | undefined; + /** + * See Redis class. + * + * @default false + */ + enableAutoPipelining?: boolean | undefined; + /** + * See Redis class. + * + * @default [] + */ + autoPipeliningIgnoredCommands?: string[] | undefined; + /** + * Custom LUA commands + */ + scripts?: Record | undefined; +} +export declare const DEFAULT_CLUSTER_OPTIONS: ClusterOptions; diff --git a/backend/node_modules/ioredis/built/cluster/ClusterOptions.js b/backend/node_modules/ioredis/built/cluster/ClusterOptions.js new file mode 100644 index 0000000..8c3e2e5 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ClusterOptions.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_CLUSTER_OPTIONS = void 0; +const dns_1 = require("dns"); +exports.DEFAULT_CLUSTER_OPTIONS = { + clusterRetryStrategy: (times) => Math.min(100 + times * 2, 2000), + enableOfflineQueue: true, + enableReadyCheck: true, + scaleReads: "master", + maxRedirections: 16, + retryDelayOnMoved: 0, + retryDelayOnFailover: 100, + retryDelayOnClusterDown: 100, + retryDelayOnTryAgain: 100, + slotsRefreshTimeout: 1000, + useSRVRecords: false, + resolveSrv: dns_1.resolveSrv, + dnsLookup: dns_1.lookup, + enableAutoPipelining: false, + autoPipeliningIgnoredCommands: [], + shardedSubscribers: false, +}; diff --git a/backend/node_modules/ioredis/built/cluster/ClusterSubscriber.d.ts b/backend/node_modules/ioredis/built/cluster/ClusterSubscriber.d.ts new file mode 100644 index 0000000..93a221a --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ClusterSubscriber.d.ts @@ -0,0 +1,29 @@ +/// +import { EventEmitter } from "events"; +import ConnectionPool from "./ConnectionPool"; +export default class ClusterSubscriber { + private connectionPool; + private emitter; + private isSharded; + private started; + private subscriber; + private lastActiveSubscriber; + private slotRange; + constructor(connectionPool: ConnectionPool, emitter: EventEmitter, isSharded?: boolean); + getInstance(): any; + /** + * Associate this subscriber to a specific slot range. + * + * Returns the range or an empty array if the slot range couldn't be associated. + * + * BTW: This is more for debugging and testing purposes. + * + * @param range + */ + associateSlotRange(range: number[]): number[]; + start(): void; + stop(): void; + isStarted(): boolean; + private onSubscriberEnd; + private selectSubscriber; +} diff --git a/backend/node_modules/ioredis/built/cluster/ClusterSubscriber.js b/backend/node_modules/ioredis/built/cluster/ClusterSubscriber.js new file mode 100644 index 0000000..ceb02cd --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ClusterSubscriber.js @@ -0,0 +1,223 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const util_1 = require("./util"); +const utils_1 = require("../utils"); +const Redis_1 = require("../Redis"); +const debug = (0, utils_1.Debug)("cluster:subscriber"); +class ClusterSubscriber { + constructor(connectionPool, emitter, isSharded = false) { + this.connectionPool = connectionPool; + this.emitter = emitter; + this.isSharded = isSharded; + this.started = false; + //There is only one connection for the entire pool + this.subscriber = null; + //The slot range for which this subscriber is responsible + this.slotRange = []; + this.onSubscriberEnd = () => { + if (!this.started) { + debug("subscriber has disconnected, but ClusterSubscriber is not started, so not reconnecting."); + return; + } + // If the subscriber closes whilst it's still the active connection, + // we might as well try to connecting to a new node if possible to + // minimise the number of missed publishes. + debug("subscriber has disconnected, selecting a new one..."); + this.selectSubscriber(); + }; + // If the current node we're using as the subscriber disappears + // from the node pool for some reason, we will select a new one + // to connect to. + // Note that this event is only triggered if the connection to + // the node has been used; cluster subscriptions are setup with + // lazyConnect = true. It's possible for the subscriber node to + // disappear without this method being called! + // See https://github.com/luin/ioredis/pull/1589 + this.connectionPool.on("-node", (_, key) => { + if (!this.started || !this.subscriber) { + return; + } + if ((0, util_1.getNodeKey)(this.subscriber.options) === key) { + debug("subscriber has left, selecting a new one..."); + this.selectSubscriber(); + } + }); + this.connectionPool.on("+node", () => { + if (!this.started || this.subscriber) { + return; + } + debug("a new node is discovered and there is no subscriber, selecting a new one..."); + this.selectSubscriber(); + }); + } + getInstance() { + return this.subscriber; + } + /** + * Associate this subscriber to a specific slot range. + * + * Returns the range or an empty array if the slot range couldn't be associated. + * + * BTW: This is more for debugging and testing purposes. + * + * @param range + */ + associateSlotRange(range) { + if (this.isSharded) { + this.slotRange = range; + } + return this.slotRange; + } + start() { + this.started = true; + this.selectSubscriber(); + debug("started"); + } + stop() { + this.started = false; + if (this.subscriber) { + this.subscriber.disconnect(); + this.subscriber = null; + } + } + isStarted() { + return this.started; + } + selectSubscriber() { + const lastActiveSubscriber = this.lastActiveSubscriber; + // Disconnect the previous subscriber even if there + // will not be a new one. + if (lastActiveSubscriber) { + lastActiveSubscriber.off("end", this.onSubscriberEnd); + lastActiveSubscriber.disconnect(); + } + if (this.subscriber) { + this.subscriber.off("end", this.onSubscriberEnd); + this.subscriber.disconnect(); + } + const sampleNode = (0, utils_1.sample)(this.connectionPool.getNodes()); + if (!sampleNode) { + debug("selecting subscriber failed since there is no node discovered in the cluster yet"); + this.subscriber = null; + return; + } + const { options } = sampleNode; + debug("selected a subscriber %s:%s", options.host, options.port); + /* + * Create a specialized Redis connection for the subscription. + * Note that auto reconnection is enabled here. + * + * `enableReadyCheck` is also enabled because although subscription is allowed + * while redis is loading data from the disk, we can check if the password + * provided for the subscriber is correct, and if not, the current subscriber + * will be disconnected and a new subscriber will be selected. + */ + let connectionPrefix = "subscriber"; + if (this.isSharded) + connectionPrefix = "ssubscriber"; + this.subscriber = new Redis_1.default({ + port: options.port, + host: options.host, + username: options.username, + password: options.password, + enableReadyCheck: true, + connectionName: (0, util_1.getConnectionName)(connectionPrefix, options.connectionName), + lazyConnect: true, + tls: options.tls, + // Don't try to reconnect the subscriber connection. If the connection fails + // we will get an end event (handled below), at which point we'll pick a new + // node from the pool and try to connect to that as the subscriber connection. + retryStrategy: null, + }); + // Ignore the errors since they're handled in the connection pool. + this.subscriber.on("error", utils_1.noop); + this.subscriber.on("moved", () => { + this.emitter.emit("forceRefresh"); + }); + // The node we lost connection to may not come back up in a + // reasonable amount of time (e.g. a slave that's taken down + // for maintainence), we could potentially miss many published + // messages so we should reconnect as quickly as possible, to + // a different node if needed. + this.subscriber.once("end", this.onSubscriberEnd); + // Re-subscribe previous channels + const previousChannels = { subscribe: [], psubscribe: [], ssubscribe: [] }; + if (lastActiveSubscriber) { + const condition = lastActiveSubscriber.condition || lastActiveSubscriber.prevCondition; + if (condition && condition.subscriber) { + previousChannels.subscribe = condition.subscriber.channels("subscribe"); + previousChannels.psubscribe = + condition.subscriber.channels("psubscribe"); + previousChannels.ssubscribe = + condition.subscriber.channels("ssubscribe"); + } + } + if (previousChannels.subscribe.length || + previousChannels.psubscribe.length || + previousChannels.ssubscribe.length) { + let pending = 0; + for (const type of ["subscribe", "psubscribe", "ssubscribe"]) { + const channels = previousChannels[type]; + if (channels.length == 0) { + continue; + } + debug("%s %d channels", type, channels.length); + if (type === "ssubscribe") { + for (const channel of channels) { + pending += 1; + this.subscriber[type](channel) + .then(() => { + if (!--pending) { + this.lastActiveSubscriber = this.subscriber; + } + }) + .catch(() => { + // TODO: should probably disconnect the subscriber and try again. + debug("failed to ssubscribe to channel: %s", channel); + }); + } + } + else { + pending += 1; + this.subscriber[type](channels) + .then(() => { + if (!--pending) { + this.lastActiveSubscriber = this.subscriber; + } + }) + .catch(() => { + // TODO: should probably disconnect the subscriber and try again. + debug("failed to %s %d channels", type, channels.length); + }); + } + } + } + else { + this.lastActiveSubscriber = this.subscriber; + } + for (const event of [ + "message", + "messageBuffer", + ]) { + this.subscriber.on(event, (arg1, arg2) => { + this.emitter.emit(event, arg1, arg2); + }); + } + for (const event of ["pmessage", "pmessageBuffer"]) { + this.subscriber.on(event, (arg1, arg2, arg3) => { + this.emitter.emit(event, arg1, arg2, arg3); + }); + } + if (this.isSharded == true) { + for (const event of [ + "smessage", + "smessageBuffer", + ]) { + this.subscriber.on(event, (arg1, arg2) => { + this.emitter.emit(event, arg1, arg2); + }); + } + } + } +} +exports.default = ClusterSubscriber; diff --git a/backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.d.ts b/backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.d.ts new file mode 100644 index 0000000..496b96d --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.d.ts @@ -0,0 +1,108 @@ +/// +import * as EventEmitter from "events"; +import ShardedSubscriber from "./ShardedSubscriber"; +import { ClusterOptions } from "./ClusterOptions"; +/** + * Redis distinguishes between "normal" and sharded PubSub. When using the normal PubSub feature, + * exactly one subscriber exists per cluster instance because the Redis cluster bus forwards + * messages between shards. Sharded PubSub removes this limitation by making each shard + * responsible for its own messages. + * + * This class coordinates one ShardedSubscriber per master node in the cluster, providing + * sharded PubSub support while keeping the public API backward compatible. + */ +export default class ClusterSubscriberGroup { + private readonly subscriberGroupEmitter; + private readonly options; + private shardedSubscribers; + private clusterSlots; + private subscriberToSlotsIndex; + private channels; + private failedAttemptsByNode; + private isResetting; + private pendingReset; + private static readonly MAX_RETRY_ATTEMPTS; + private static readonly MAX_BACKOFF_MS; + private static readonly BASE_BACKOFF_MS; + /** + * Register callbacks + * + * @param cluster + */ + constructor(subscriberGroupEmitter: EventEmitter, options: ClusterOptions); + /** + * Get the responsible subscriber. + * + * @param slot + */ + getResponsibleSubscriber(slot: number): ShardedSubscriber | undefined; + /** + * Adds a channel for which this subscriber group is responsible + * + * @param channels + */ + addChannels(channels: (string | Buffer)[]): number; + /** + * Removes channels for which the subscriber group is responsible by optionally unsubscribing + * @param channels + */ + removeChannels(channels: (string | Buffer)[]): number; + /** + * Disconnect all subscribers and clear some of the internal state. + */ + stop(): void; + /** + * Start all not yet started subscribers + */ + start(): Promise; + /** + * Resets the subscriber group by disconnecting all subscribers that are no longer needed and connecting new ones. + */ + reset(clusterSlots: string[][], clusterNodes: any[]): Promise; + /** + * Refreshes the subscriber-related slot ranges + * + * Returns false if no refresh was needed + * + * @param targetSlots + */ + private _refreshSlots; + /** + * Resubscribes to the previous channels + * + * @private + */ + private _resubscribe; + /** + * Deep equality of the cluster slots objects + * + * @param other + * @private + */ + private _slotsAreEqual; + /** + * Checks if any subscribers are in an unhealthy state. + * + * A subscriber is considered unhealthy if: + * - It exists but is not started (failed/disconnected) + * - It's missing entirely for a node that should have one + * + * @returns true if any subscribers need to be recreated + */ + private hasUnhealthySubscribers; + /** + * Handles failed subscriber connections by emitting an event to refresh the slots cache + * after a backoff period. + * + * @param error + * @param nodeKey + */ + private handleSubscriberConnectFailed; + /** + * Handles successful subscriber connections by resetting the failed attempts counter. + * + * @param nodeKey + */ + private handleSubscriberConnectSucceeded; + private shouldStartSubscriber; +} diff --git a/backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.js b/backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.js new file mode 100644 index 0000000..8f524a8 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ClusterSubscriberGroup.js @@ -0,0 +1,373 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("../utils"); +const util_1 = require("./util"); +const calculateSlot = require("cluster-key-slot"); +const ShardedSubscriber_1 = require("./ShardedSubscriber"); +const debug = (0, utils_1.Debug)("cluster:subscriberGroup"); +/** + * Redis distinguishes between "normal" and sharded PubSub. When using the normal PubSub feature, + * exactly one subscriber exists per cluster instance because the Redis cluster bus forwards + * messages between shards. Sharded PubSub removes this limitation by making each shard + * responsible for its own messages. + * + * This class coordinates one ShardedSubscriber per master node in the cluster, providing + * sharded PubSub support while keeping the public API backward compatible. + */ +class ClusterSubscriberGroup { + /** + * Register callbacks + * + * @param cluster + */ + constructor(subscriberGroupEmitter, options) { + this.subscriberGroupEmitter = subscriberGroupEmitter; + this.options = options; + this.shardedSubscribers = new Map(); + this.clusterSlots = []; + // Simple [min, max] slot ranges aren't enough because you can migrate single slots + this.subscriberToSlotsIndex = new Map(); + this.channels = new Map(); + this.failedAttemptsByNode = new Map(); + // Only latest pending reset kept; throttled by refreshSlotsCache's isRefreshing + backoff delay + this.isResetting = false; + this.pendingReset = null; + /** + * Handles failed subscriber connections by emitting an event to refresh the slots cache + * after a backoff period. + * + * @param error + * @param nodeKey + */ + this.handleSubscriberConnectFailed = (error, nodeKey) => { + const currentAttempts = this.failedAttemptsByNode.get(nodeKey) || 0; + const failedAttempts = currentAttempts + 1; + this.failedAttemptsByNode.set(nodeKey, failedAttempts); + const attempts = Math.min(failedAttempts, ClusterSubscriberGroup.MAX_RETRY_ATTEMPTS); + const backoff = Math.min(ClusterSubscriberGroup.BASE_BACKOFF_MS * 2 ** attempts, ClusterSubscriberGroup.MAX_BACKOFF_MS); + const jitter = Math.floor((Math.random() - 0.5) * (backoff * 0.5)); + const delay = Math.max(0, backoff + jitter); + debug("Failed to connect subscriber for %s. Refreshing slots in %dms", nodeKey, delay); + this.subscriberGroupEmitter.emit("subscriberConnectFailed", { + delay, + error, + }); + }; + /** + * Handles successful subscriber connections by resetting the failed attempts counter. + * + * @param nodeKey + */ + this.handleSubscriberConnectSucceeded = (nodeKey) => { + this.failedAttemptsByNode.delete(nodeKey); + }; + } + /** + * Get the responsible subscriber. + * + * @param slot + */ + getResponsibleSubscriber(slot) { + const nodeKey = this.clusterSlots[slot][0]; + const sub = this.shardedSubscribers.get(nodeKey); + if (sub && sub.subscriberStatus === "idle") { + sub + .start() + .then(() => { + this.handleSubscriberConnectSucceeded(sub.getNodeKey()); + }) + .catch((err) => { + this.handleSubscriberConnectFailed(err, sub.getNodeKey()); + }); + } + return sub; + } + /** + * Adds a channel for which this subscriber group is responsible + * + * @param channels + */ + addChannels(channels) { + const slot = calculateSlot(channels[0]); + // Check if the all channels belong to the same slot and otherwise reject the operation + for (const c of channels) { + if (calculateSlot(c) !== slot) { + return -1; + } + } + const currChannels = this.channels.get(slot); + if (!currChannels) { + this.channels.set(slot, channels); + } + else { + this.channels.set(slot, currChannels.concat(channels)); + } + return Array.from(this.channels.values()).reduce((sum, array) => sum + array.length, 0); + } + /** + * Removes channels for which the subscriber group is responsible by optionally unsubscribing + * @param channels + */ + removeChannels(channels) { + const slot = calculateSlot(channels[0]); + // Check if the all channels belong to the same slot and otherwise reject the operation + for (const c of channels) { + if (calculateSlot(c) !== slot) { + return -1; + } + } + const slotChannels = this.channels.get(slot); + if (slotChannels) { + const updatedChannels = slotChannels.filter((c) => !channels.includes(c)); + this.channels.set(slot, updatedChannels); + } + return Array.from(this.channels.values()).reduce((sum, array) => sum + array.length, 0); + } + /** + * Disconnect all subscribers and clear some of the internal state. + */ + stop() { + for (const s of this.shardedSubscribers.values()) { + s.stop(); + } + // Clear subscriber instances and pending operations. + // Channels are preserved for resubscription on reconnect. + this.pendingReset = null; + this.shardedSubscribers.clear(); + this.subscriberToSlotsIndex.clear(); + } + /** + * Start all not yet started subscribers + */ + start() { + const startPromises = []; + for (const s of this.shardedSubscribers.values()) { + if (this.shouldStartSubscriber(s)) { + startPromises.push(s + .start() + .then(() => { + this.handleSubscriberConnectSucceeded(s.getNodeKey()); + }) + .catch((err) => { + this.handleSubscriberConnectFailed(err, s.getNodeKey()); + })); + this.subscriberGroupEmitter.emit("+subscriber"); + } + } + return Promise.all(startPromises); + } + /** + * Resets the subscriber group by disconnecting all subscribers that are no longer needed and connecting new ones. + */ + async reset(clusterSlots, clusterNodes) { + if (this.isResetting) { + this.pendingReset = { slots: clusterSlots, nodes: clusterNodes }; + return; + } + this.isResetting = true; + try { + const hasTopologyChanged = this._refreshSlots(clusterSlots); + const hasFailedSubscribers = this.hasUnhealthySubscribers(); + if (!hasTopologyChanged && !hasFailedSubscribers) { + debug("No topology change detected or failed subscribers. Skipping reset."); + return; + } + // For each of the sharded subscribers + for (const [nodeKey, shardedSubscriber] of this.shardedSubscribers) { + if ( + // If the subscriber is still responsible for a slot range and is healthy then keep it + this.subscriberToSlotsIndex.has(nodeKey) && + shardedSubscriber.isHealthy()) { + debug("Skipping deleting subscriber for %s", nodeKey); + continue; + } + debug("Removing subscriber for %s", nodeKey); + // Otherwise stop the subscriber and remove it + shardedSubscriber.stop(); + this.shardedSubscribers.delete(nodeKey); + this.subscriberGroupEmitter.emit("-subscriber"); + } + const startPromises = []; + // For each node in slots cache + for (const [nodeKey, _] of this.subscriberToSlotsIndex) { + const existingSubscriber = this.shardedSubscribers.get(nodeKey); + // If we already have a subscriber for this node, only ensure it is healthy + // when it now owns slots with active channel subscriptions. + if (existingSubscriber && existingSubscriber.isHealthy()) { + debug("Skipping creating new subscriber for %s", nodeKey); + if (!existingSubscriber.isStarted() && + this.shouldStartSubscriber(existingSubscriber)) { + startPromises.push(existingSubscriber + .start() + .then(() => { + this.handleSubscriberConnectSucceeded(nodeKey); + }) + .catch((error) => { + this.handleSubscriberConnectFailed(error, nodeKey); + })); + } + continue; + } + // If we have an existing subscriber but it is not healthy, stop it + if (existingSubscriber && !existingSubscriber.isHealthy()) { + debug("Replacing subscriber for %s", nodeKey); + existingSubscriber.stop(); + this.shardedSubscribers.delete(nodeKey); + this.subscriberGroupEmitter.emit("-subscriber"); + } + debug("Creating new subscriber for %s", nodeKey); + // Otherwise create a new subscriber + const redis = clusterNodes.find((node) => { + return (0, util_1.getNodeKey)(node.options) === nodeKey; + }); + if (!redis) { + debug("Failed to find node for key %s", nodeKey); + continue; + } + const sub = new ShardedSubscriber_1.default(this.subscriberGroupEmitter, redis.options, this.options.redisOptions); + this.shardedSubscribers.set(nodeKey, sub); + if (this.shouldStartSubscriber(sub)) { + startPromises.push(sub + .start() + .then(() => { + this.handleSubscriberConnectSucceeded(nodeKey); + }) + .catch((error) => { + this.handleSubscriberConnectFailed(error, nodeKey); + })); + } + this.subscriberGroupEmitter.emit("+subscriber"); + } + // It's vital to await the start promises before resubscribing + // Otherwise we might try to resubscribe to a subscriber that is not yet connected + // This can cause a race condition + await Promise.all(startPromises); + this._resubscribe(); + this.subscriberGroupEmitter.emit("subscribersReady"); + } + finally { + this.isResetting = false; + if (this.pendingReset) { + const { slots, nodes } = this.pendingReset; + this.pendingReset = null; + await this.reset(slots, nodes); + } + } + } + /** + * Refreshes the subscriber-related slot ranges + * + * Returns false if no refresh was needed + * + * @param targetSlots + */ + _refreshSlots(targetSlots) { + //If there was an actual change, then reassign the slot ranges + // Also rebuild if subscriberToSlotsIndex is empty (e.g., after stop() was called) + if (this._slotsAreEqual(targetSlots) && this.subscriberToSlotsIndex.size > 0) { + debug("Nothing to refresh because the new cluster map is equal to the previous one."); + return false; + } + debug("Refreshing the slots of the subscriber group."); + //Rebuild the slots index + this.subscriberToSlotsIndex = new Map(); + for (let slot = 0; slot < targetSlots.length; slot++) { + const node = targetSlots[slot][0]; + if (!this.subscriberToSlotsIndex.has(node)) { + this.subscriberToSlotsIndex.set(node, []); + } + this.subscriberToSlotsIndex.get(node).push(Number(slot)); + } + //Update the cached slots map + this.clusterSlots = JSON.parse(JSON.stringify(targetSlots)); + return true; + } + /** + * Resubscribes to the previous channels + * + * @private + */ + _resubscribe() { + if (this.shardedSubscribers) { + this.shardedSubscribers.forEach((s, nodeKey) => { + const subscriberSlots = this.subscriberToSlotsIndex.get(nodeKey); + if (subscriberSlots) { + //Resubscribe on the underlying connection + subscriberSlots.forEach((ss) => { + //Might return null if being disconnected + const redis = s.getInstance(); + const channels = this.channels.get(ss); + if (channels && channels.length > 0) { + if (!redis || redis.status === "end") { + return; + } + if (redis.status === "ready") { + redis.ssubscribe(...channels).catch((err) => { + // TODO: Should we emit an error event here? + debug("Failed to ssubscribe on node %s: %s", nodeKey, err); + }); + } + else { + redis.once("ready", () => { + redis.ssubscribe(...channels).catch((err) => { + // TODO: Should we emit an error event here? + debug("Failed to ssubscribe on node %s: %s", nodeKey, err); + }); + }); + } + } + }); + } + }); + } + } + /** + * Deep equality of the cluster slots objects + * + * @param other + * @private + */ + _slotsAreEqual(other) { + if (this.clusterSlots === undefined) { + return false; + } + else { + return JSON.stringify(this.clusterSlots) === JSON.stringify(other); + } + } + /** + * Checks if any subscribers are in an unhealthy state. + * + * A subscriber is considered unhealthy if: + * - It exists but is not started (failed/disconnected) + * - It's missing entirely for a node that should have one + * + * @returns true if any subscribers need to be recreated + */ + hasUnhealthySubscribers() { + const hasFailedSubscribers = Array.from(this.shardedSubscribers.values()).some((sub) => !sub.isHealthy()); + const hasMissingSubscribers = Array.from(this.subscriberToSlotsIndex.keys()).some((nodeKey) => !this.shardedSubscribers.has(nodeKey)); + return hasFailedSubscribers || hasMissingSubscribers; + } + shouldStartSubscriber(sub) { + if (sub.isStarted()) { + return false; + } + if (!sub.isLazyConnect()) { + return true; + } + const subscriberSlots = this.subscriberToSlotsIndex.get(sub.getNodeKey()); + if (!subscriberSlots) { + return false; + } + return subscriberSlots.some((slot) => { + const channels = this.channels.get(slot); + return Boolean(channels && channels.length > 0); + }); + } +} +exports.default = ClusterSubscriberGroup; +// Retry strategy +ClusterSubscriberGroup.MAX_RETRY_ATTEMPTS = 10; +ClusterSubscriberGroup.MAX_BACKOFF_MS = 2000; +ClusterSubscriberGroup.BASE_BACKOFF_MS = 100; diff --git a/backend/node_modules/ioredis/built/cluster/ConnectionPool.d.ts b/backend/node_modules/ioredis/built/cluster/ConnectionPool.d.ts new file mode 100644 index 0000000..0de5d7a --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ConnectionPool.d.ts @@ -0,0 +1,37 @@ +/// +import { EventEmitter } from "events"; +import { RedisOptions, NodeKey, NodeRole } from "./util"; +import Redis from "../Redis"; +export default class ConnectionPool extends EventEmitter { + private redisOptions; + private nodes; + private specifiedOptions; + constructor(redisOptions: any); + getNodes(role?: NodeRole): Redis[]; + getInstanceByKey(key: NodeKey): Redis; + getSampleInstance(role: NodeRole): Redis; + /** + * Add a master node to the pool + * @param node + */ + addMasterNode(node: RedisOptions): boolean; + /** + * Creates a Redis connection instance from the node options + * @param node + * @param readOnly + */ + createRedisFromOptions(node: RedisOptions, readOnly: boolean): Redis; + /** + * Find or create a connection to the node + */ + findOrCreate(node: RedisOptions, readOnly?: boolean): Redis; + /** + * Reset the pool with a set of nodes. + * The old node will be removed. + */ + reset(nodes: RedisOptions[]): void; + /** + * Remove a node from the pool. + */ + private removeNode; +} diff --git a/backend/node_modules/ioredis/built/cluster/ConnectionPool.js b/backend/node_modules/ioredis/built/cluster/ConnectionPool.js new file mode 100644 index 0000000..4fef1b8 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ConnectionPool.js @@ -0,0 +1,154 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const events_1 = require("events"); +const utils_1 = require("../utils"); +const util_1 = require("./util"); +const Redis_1 = require("../Redis"); +const debug = (0, utils_1.Debug)("cluster:connectionPool"); +class ConnectionPool extends events_1.EventEmitter { + constructor(redisOptions) { + super(); + this.redisOptions = redisOptions; + // master + slave = all + this.nodes = { + all: {}, + master: {}, + slave: {}, + }; + this.specifiedOptions = {}; + } + getNodes(role = "all") { + const nodes = this.nodes[role]; + return Object.keys(nodes).map((key) => nodes[key]); + } + getInstanceByKey(key) { + return this.nodes.all[key]; + } + getSampleInstance(role) { + const keys = Object.keys(this.nodes[role]); + const sampleKey = (0, utils_1.sample)(keys); + return this.nodes[role][sampleKey]; + } + /** + * Add a master node to the pool + * @param node + */ + addMasterNode(node) { + const key = (0, util_1.getNodeKey)(node.options); + const redis = this.createRedisFromOptions(node, node.options.readOnly); + //Master nodes aren't read-only + if (!node.options.readOnly) { + this.nodes.all[key] = redis; + this.nodes.master[key] = redis; + return true; + } + return false; + } + /** + * Creates a Redis connection instance from the node options + * @param node + * @param readOnly + */ + createRedisFromOptions(node, readOnly) { + const redis = new Redis_1.default((0, utils_1.defaults)({ + // Never try to reconnect when a node is lose, + // instead, waiting for a `MOVED` error and + // fetch the slots again. + retryStrategy: null, + // Offline queue should be enabled so that + // we don't need to wait for the `ready` event + // before sending commands to the node. + enableOfflineQueue: true, + readOnly: readOnly, + }, node, this.redisOptions, { lazyConnect: true })); + return redis; + } + /** + * Find or create a connection to the node + */ + findOrCreate(node, readOnly = false) { + const key = (0, util_1.getNodeKey)(node); + readOnly = Boolean(readOnly); + if (this.specifiedOptions[key]) { + Object.assign(node, this.specifiedOptions[key]); + } + else { + this.specifiedOptions[key] = node; + } + let redis; + if (this.nodes.all[key]) { + redis = this.nodes.all[key]; + if (redis.options.readOnly !== readOnly) { + redis.options.readOnly = readOnly; + debug("Change role of %s to %s", key, readOnly ? "slave" : "master"); + redis[readOnly ? "readonly" : "readwrite"]().catch(utils_1.noop); + if (readOnly) { + delete this.nodes.master[key]; + this.nodes.slave[key] = redis; + } + else { + delete this.nodes.slave[key]; + this.nodes.master[key] = redis; + } + } + } + else { + debug("Connecting to %s as %s", key, readOnly ? "slave" : "master"); + redis = this.createRedisFromOptions(node, readOnly); + this.nodes.all[key] = redis; + this.nodes[readOnly ? "slave" : "master"][key] = redis; + redis.once("end", () => { + this.removeNode(key); + this.emit("-node", redis, key); + if (!Object.keys(this.nodes.all).length) { + this.emit("drain"); + } + }); + this.emit("+node", redis, key); + redis.on("error", function (error) { + this.emit("nodeError", error, key); + }); + } + return redis; + } + /** + * Reset the pool with a set of nodes. + * The old node will be removed. + */ + reset(nodes) { + debug("Reset with %O", nodes); + const newNodes = {}; + nodes.forEach((node) => { + const key = (0, util_1.getNodeKey)(node); + // Don't override the existing (master) node + // when the current one is slave. + if (!(node.readOnly && newNodes[key])) { + newNodes[key] = node; + } + }); + Object.keys(this.nodes.all).forEach((key) => { + if (!newNodes[key]) { + debug("Disconnect %s because the node does not hold any slot", key); + this.nodes.all[key].disconnect(); + this.removeNode(key); + } + }); + Object.keys(newNodes).forEach((key) => { + const node = newNodes[key]; + this.findOrCreate(node, node.readOnly); + }); + } + /** + * Remove a node from the pool. + */ + removeNode(key) { + const { nodes } = this; + if (nodes.all[key]) { + debug("Remove %s from the pool", key); + delete nodes.all[key]; + } + delete nodes.master[key]; + delete nodes.slave[key]; + } +} +exports.default = ConnectionPool; diff --git a/backend/node_modules/ioredis/built/cluster/DelayQueue.d.ts b/backend/node_modules/ioredis/built/cluster/DelayQueue.d.ts new file mode 100644 index 0000000..2d64896 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/DelayQueue.d.ts @@ -0,0 +1,20 @@ +export interface DelayQueueOptions { + callback?: Function; + timeout: number; +} +/** + * Queue that runs items after specified duration + */ +export default class DelayQueue { + private queues; + private timeouts; + /** + * Add a new item to the queue + * + * @param bucket bucket name + * @param item function that will run later + * @param options + */ + push(bucket: string, item: Function, options: DelayQueueOptions): void; + private execute; +} diff --git a/backend/node_modules/ioredis/built/cluster/DelayQueue.js b/backend/node_modules/ioredis/built/cluster/DelayQueue.js new file mode 100644 index 0000000..e17df51 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/DelayQueue.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("../utils"); +const Deque = require("denque"); +const debug = (0, utils_1.Debug)("delayqueue"); +/** + * Queue that runs items after specified duration + */ +class DelayQueue { + constructor() { + this.queues = {}; + this.timeouts = {}; + } + /** + * Add a new item to the queue + * + * @param bucket bucket name + * @param item function that will run later + * @param options + */ + push(bucket, item, options) { + const callback = options.callback || process.nextTick; + if (!this.queues[bucket]) { + this.queues[bucket] = new Deque(); + } + const queue = this.queues[bucket]; + queue.push(item); + if (!this.timeouts[bucket]) { + this.timeouts[bucket] = setTimeout(() => { + callback(() => { + this.timeouts[bucket] = null; + this.execute(bucket); + }); + }, options.timeout); + } + } + execute(bucket) { + const queue = this.queues[bucket]; + if (!queue) { + return; + } + const { length } = queue; + if (!length) { + return; + } + debug("send %d commands in %s queue", length, bucket); + this.queues[bucket] = null; + while (queue.length > 0) { + queue.shift()(); + } + } +} +exports.default = DelayQueue; diff --git a/backend/node_modules/ioredis/built/cluster/ShardedSubscriber.d.ts b/backend/node_modules/ioredis/built/cluster/ShardedSubscriber.d.ts new file mode 100644 index 0000000..921bcdb --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ShardedSubscriber.d.ts @@ -0,0 +1,36 @@ +/// +import EventEmitter = require("events"); +import { RedisOptions } from "./util"; +import Redis from "../Redis"; +import { ClusterOptions } from "./ClusterOptions"; +declare const SubscriberStatus: { + readonly IDLE: "idle"; + readonly STARTING: "starting"; + readonly CONNECTED: "connected"; + readonly STOPPING: "stopping"; + readonly ENDED: "ended"; +}; +declare type SubscriberStatus = typeof SubscriberStatus[keyof typeof SubscriberStatus]; +export default class ShardedSubscriber { + private readonly emitter; + private readonly nodeKey; + private status; + private instance; + private connectPromise; + private lazyConnect; + private readonly messageListeners; + constructor(emitter: EventEmitter, options: RedisOptions, redisOptions?: ClusterOptions["redisOptions"]); + start(): Promise; + stop(): void; + isStarted(): boolean; + get subscriberStatus(): SubscriberStatus; + isHealthy(): boolean; + getInstance(): Redis | null; + getNodeKey(): string; + isLazyConnect(): boolean; + private onEnd; + private onError; + private onMoved; + private updateStatus; +} +export {}; diff --git a/backend/node_modules/ioredis/built/cluster/ShardedSubscriber.js b/backend/node_modules/ioredis/built/cluster/ShardedSubscriber.js new file mode 100644 index 0000000..163fb63 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/ShardedSubscriber.js @@ -0,0 +1,147 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const util_1 = require("./util"); +const utils_1 = require("../utils"); +const Redis_1 = require("../Redis"); +const debug = (0, utils_1.Debug)("cluster:subscriberGroup:shardedSubscriber"); +const SubscriberStatus = { + IDLE: "idle", + STARTING: "starting", + CONNECTED: "connected", + STOPPING: "stopping", + ENDED: "ended", +}; +const ALLOWED_STATUS_UPDATES = { + [SubscriberStatus.IDLE]: [ + SubscriberStatus.STARTING, + SubscriberStatus.STOPPING, + SubscriberStatus.ENDED, + ], + [SubscriberStatus.STARTING]: [ + SubscriberStatus.CONNECTED, + SubscriberStatus.STOPPING, + SubscriberStatus.ENDED, + ], + [SubscriberStatus.CONNECTED]: [ + SubscriberStatus.STOPPING, + SubscriberStatus.ENDED, + ], + [SubscriberStatus.STOPPING]: [SubscriberStatus.ENDED], + [SubscriberStatus.ENDED]: [], +}; +class ShardedSubscriber { + constructor(emitter, options, redisOptions) { + var _a; + this.emitter = emitter; + this.status = SubscriberStatus.IDLE; + this.instance = null; + this.connectPromise = null; + // Store listener references for cleanup + this.messageListeners = new Map(); + this.onEnd = () => { + this.updateStatus(SubscriberStatus.ENDED); + this.emitter.emit("-node", this.instance, this.nodeKey); + }; + this.onError = (error) => { + this.emitter.emit("nodeError", error, this.nodeKey); + }; + this.onMoved = () => { + this.emitter.emit("moved"); + }; + this.instance = new Redis_1.default((0, utils_1.defaults)({ + enableReadyCheck: false, + enableOfflineQueue: true, + connectionName: (0, util_1.getConnectionName)("ssubscriber", options.connectionName), + /** + * Disable auto reconnection for subscribers. + * The ClusterSubscriberGroup will handle the reconnection. + */ + retryStrategy: null, + lazyConnect: true, + }, options, redisOptions)); + this.lazyConnect = (_a = redisOptions === null || redisOptions === void 0 ? void 0 : redisOptions.lazyConnect) !== null && _a !== void 0 ? _a : true; + this.nodeKey = (0, util_1.getNodeKey)(options); + // Register listeners + this.instance.on("end", this.onEnd); + this.instance.on("error", this.onError); + this.instance.on("moved", this.onMoved); + for (const event of ["smessage", "smessageBuffer"]) { + const listener = (...args) => { + this.emitter.emit(event, ...args); + }; + this.messageListeners.set(event, listener); + this.instance.on(event, listener); + } + } + async start() { + if (this.connectPromise) { + return this.connectPromise; + } + if (this.status === SubscriberStatus.STARTING || + this.status === SubscriberStatus.CONNECTED) { + return; + } + if (this.status === SubscriberStatus.ENDED || !this.instance) { + throw new Error(`Sharded subscriber ${this.nodeKey} cannot be restarted once ended.`); + } + this.updateStatus(SubscriberStatus.STARTING); + this.connectPromise = this.instance.connect(); + try { + await this.connectPromise; + this.updateStatus(SubscriberStatus.CONNECTED); + } + catch (err) { + this.updateStatus(SubscriberStatus.ENDED); + throw err; + } + finally { + this.connectPromise = null; + } + } + stop() { + this.updateStatus(SubscriberStatus.STOPPING); + if (this.instance) { + this.instance.disconnect(); + this.instance.removeAllListeners(); + this.messageListeners.clear(); + this.instance = null; + } + this.updateStatus(SubscriberStatus.ENDED); + debug("stopped %s", this.nodeKey); + } + isStarted() { + return [ + SubscriberStatus.CONNECTED, + SubscriberStatus.STARTING, + ].includes(this.status); + } + get subscriberStatus() { + return this.status; + } + isHealthy() { + return ((this.status === SubscriberStatus.IDLE || + this.status === SubscriberStatus.CONNECTED || + this.status === SubscriberStatus.STARTING) && + this.instance !== null); + } + getInstance() { + return this.instance; + } + getNodeKey() { + return this.nodeKey; + } + isLazyConnect() { + return this.lazyConnect; + } + updateStatus(nextStatus) { + if (this.status === nextStatus) { + return; + } + if (!ALLOWED_STATUS_UPDATES[this.status].includes(nextStatus)) { + debug("Invalid status transition for %s: %s -> %s", this.nodeKey, this.status, nextStatus); + return; + } + this.status = nextStatus; + } +} +exports.default = ShardedSubscriber; diff --git a/backend/node_modules/ioredis/built/cluster/index.d.ts b/backend/node_modules/ioredis/built/cluster/index.d.ts new file mode 100644 index 0000000..3f5e1b4 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/index.d.ts @@ -0,0 +1,163 @@ +/// +import { EventEmitter } from "events"; +import Command from "../Command"; +import Redis from "../Redis"; +import ScanStream from "../ScanStream"; +import { Transaction } from "../transaction"; +import { Callback, ScanStreamOptions, WriteableStream } from "../types"; +import Commander from "../utils/Commander"; +import { ClusterOptions } from "./ClusterOptions"; +import { NodeKey, NodeRole } from "./util"; +export declare type ClusterNode = string | number | { + host?: string | undefined; + port?: number | undefined; +}; +declare type ClusterStatus = "end" | "close" | "wait" | "connecting" | "connect" | "ready" | "reconnecting" | "disconnecting"; +/** + * Client for the official Redis Cluster + */ +declare class Cluster extends Commander { + options: ClusterOptions; + slots: NodeKey[][]; + status: ClusterStatus; + /** + * @ignore + */ + _groupsIds: { + [key: string]: number; + }; + /** + * @ignore + */ + _groupsBySlot: number[]; + /** + * @ignore + */ + isCluster: boolean; + private startupNodes; + private connectionPool; + private manuallyClosing; + private retryAttempts; + private delayQueue; + private offlineQueue; + private subscriber; + private shardedSubscribers; + private slotsTimer; + private reconnectTimeout; + private isRefreshing; + private _refreshSlotsCacheCallbacks; + private _autoPipelines; + private _runningAutoPipelines; + private _readyDelayedCallbacks; + private subscriberGroupEmitter; + /** + * Every time Cluster#connect() is called, this value will be + * auto-incrementing. The purpose of this value is used for + * discarding previous connect attampts when creating a new + * connection. + */ + private connectionEpoch; + /** + * Creates an instance of Cluster. + */ + constructor(startupNodes: ClusterNode[], options?: ClusterOptions); + /** + * Connect to a cluster + */ + connect(): Promise; + /** + * Disconnect from every node in the cluster. + */ + disconnect(reconnect?: boolean): void; + /** + * Quit the cluster gracefully. + */ + quit(callback?: Callback<"OK">): Promise<"OK">; + /** + * Create a new instance with the same startup nodes and options as the current one. + * + * @example + * ```js + * var cluster = new Redis.Cluster([{ host: "127.0.0.1", port: "30001" }]); + * var anotherCluster = cluster.duplicate(); + * ``` + */ + duplicate(overrideStartupNodes?: any[], overrideOptions?: {}): Cluster; + /** + * Get nodes with the specified role + */ + nodes(role?: NodeRole): Redis[]; + /** + * This is needed in order not to install a listener for each auto pipeline + * + * @ignore + */ + delayUntilReady(callback: Callback): void; + /** + * Get the number of commands queued in automatic pipelines. + * + * This is not available (and returns 0) until the cluster is connected and slots information have been received. + */ + get autoPipelineQueueSize(): number; + /** + * Refresh the slot cache + * + * @ignore + */ + refreshSlotsCache(callback?: Callback): void; + /** + * @ignore + */ + sendCommand(command: Command, stream?: WriteableStream, node?: any): unknown; + sscanStream(key: string, options?: ScanStreamOptions): ScanStream; + sscanBufferStream(key: string, options?: ScanStreamOptions): ScanStream; + hscanStream(key: string, options?: ScanStreamOptions): ScanStream; + hscanBufferStream(key: string, options?: ScanStreamOptions): ScanStream; + zscanStream(key: string, options?: ScanStreamOptions): ScanStream; + zscanBufferStream(key: string, options?: ScanStreamOptions): ScanStream; + /** + * @ignore + */ + handleError(error: Error, ttl: { + value?: any; + }, handlers: any): void; + private resetOfflineQueue; + private clearNodesRefreshInterval; + private resetNodesRefreshInterval; + /** + * Change cluster instance's status + */ + private setStatus; + /** + * Called when closed to check whether a reconnection should be made + */ + private handleCloseEvent; + /** + * Flush offline queue with error. + */ + private flushQueue; + private executeOfflineCommands; + private natMapper; + private getInfoFromNode; + private invokeReadyDelayedCallbacks; + /** + * Check whether Cluster is able to process commands + */ + private readyCheck; + private resolveSrv; + private dnsLookup; + /** + * Normalize startup nodes, and resolving hostnames to IPs. + * + * This process happens every time when #connect() is called since + * #startupNodes and DNS records may chanage. + */ + private resolveStartupNodeHostnames; + private createScanStream; + private createShardedSubscriberGroup; +} +interface Cluster extends EventEmitter { +} +interface Cluster extends Transaction { +} +export default Cluster; diff --git a/backend/node_modules/ioredis/built/cluster/index.js b/backend/node_modules/ioredis/built/cluster/index.js new file mode 100644 index 0000000..1c8d57b --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/index.js @@ -0,0 +1,937 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const commands_1 = require("@ioredis/commands"); +const events_1 = require("events"); +const redis_errors_1 = require("redis-errors"); +const standard_as_callback_1 = require("standard-as-callback"); +const Command_1 = require("../Command"); +const ClusterAllFailedError_1 = require("../errors/ClusterAllFailedError"); +const Redis_1 = require("../Redis"); +const ScanStream_1 = require("../ScanStream"); +const transaction_1 = require("../transaction"); +const utils_1 = require("../utils"); +const applyMixin_1 = require("../utils/applyMixin"); +const Commander_1 = require("../utils/Commander"); +const ClusterOptions_1 = require("./ClusterOptions"); +const ClusterSubscriber_1 = require("./ClusterSubscriber"); +const ConnectionPool_1 = require("./ConnectionPool"); +const DelayQueue_1 = require("./DelayQueue"); +const util_1 = require("./util"); +const Deque = require("denque"); +const ClusterSubscriberGroup_1 = require("./ClusterSubscriberGroup"); +const debug = (0, utils_1.Debug)("cluster"); +const REJECT_OVERWRITTEN_COMMANDS = new WeakSet(); +/** + * Client for the official Redis Cluster + */ +class Cluster extends Commander_1.default { + /** + * Creates an instance of Cluster. + */ + //TODO: Add an option that enables or disables sharded PubSub + constructor(startupNodes, options = {}) { + super(); + this.slots = []; + /** + * @ignore + */ + this._groupsIds = {}; + /** + * @ignore + */ + this._groupsBySlot = Array(16384); + /** + * @ignore + */ + this.isCluster = true; + this.retryAttempts = 0; + this.delayQueue = new DelayQueue_1.default(); + this.offlineQueue = new Deque(); + this.isRefreshing = false; + this._refreshSlotsCacheCallbacks = []; + this._autoPipelines = new Map(); + this._runningAutoPipelines = new Set(); + this._readyDelayedCallbacks = []; + /** + * Every time Cluster#connect() is called, this value will be + * auto-incrementing. The purpose of this value is used for + * discarding previous connect attampts when creating a new + * connection. + */ + this.connectionEpoch = 0; + events_1.EventEmitter.call(this); + this.startupNodes = startupNodes; + this.options = (0, utils_1.defaults)({}, options, ClusterOptions_1.DEFAULT_CLUSTER_OPTIONS, this.options); + if (this.options.shardedSubscribers) { + this.createShardedSubscriberGroup(); + } + if (this.options.redisOptions && + this.options.redisOptions.keyPrefix && + !this.options.keyPrefix) { + this.options.keyPrefix = this.options.redisOptions.keyPrefix; + } + // validate options + if (typeof this.options.scaleReads !== "function" && + ["all", "master", "slave"].indexOf(this.options.scaleReads) === -1) { + throw new Error('Invalid option scaleReads "' + + this.options.scaleReads + + '". Expected "all", "master", "slave" or a custom function'); + } + this.connectionPool = new ConnectionPool_1.default(this.options.redisOptions); + this.connectionPool.on("-node", (redis, key) => { + this.emit("-node", redis); + }); + this.connectionPool.on("+node", (redis) => { + this.emit("+node", redis); + }); + this.connectionPool.on("drain", () => { + this.setStatus("close"); + }); + this.connectionPool.on("nodeError", (error, key) => { + this.emit("node error", error, key); + }); + this.subscriber = new ClusterSubscriber_1.default(this.connectionPool, this); + if (this.options.scripts) { + Object.entries(this.options.scripts).forEach(([name, definition]) => { + this.defineCommand(name, definition); + }); + } + if (this.options.lazyConnect) { + this.setStatus("wait"); + } + else { + this.connect().catch((err) => { + debug("connecting failed: %s", err); + }); + } + } + /** + * Connect to a cluster + */ + connect() { + return new Promise((resolve, reject) => { + if (this.status === "connecting" || + this.status === "connect" || + this.status === "ready") { + reject(new Error("Redis is already connecting/connected")); + return; + } + const epoch = ++this.connectionEpoch; + this.setStatus("connecting"); + this.resolveStartupNodeHostnames() + .then((nodes) => { + if (this.connectionEpoch !== epoch) { + debug("discard connecting after resolving startup nodes because epoch not match: %d != %d", epoch, this.connectionEpoch); + reject(new redis_errors_1.RedisError("Connection is discarded because a new connection is made")); + return; + } + if (this.status !== "connecting") { + debug("discard connecting after resolving startup nodes because the status changed to %s", this.status); + reject(new redis_errors_1.RedisError("Connection is aborted")); + return; + } + this.connectionPool.reset(nodes); + if (this.options.shardedSubscribers) { + this.shardedSubscribers + .reset(this.slots, this.connectionPool.getNodes("all")) + .catch((err) => { + // TODO should we emit an error event here? + debug("Error while starting subscribers: %s", err); + }); + } + const readyHandler = () => { + this.setStatus("ready"); + this.retryAttempts = 0; + this.executeOfflineCommands(); + this.resetNodesRefreshInterval(); + resolve(); + }; + let closeListener = undefined; + const refreshListener = () => { + this.invokeReadyDelayedCallbacks(undefined); + this.removeListener("close", closeListener); + this.manuallyClosing = false; + this.setStatus("connect"); + if (this.options.enableReadyCheck) { + this.readyCheck((err, fail) => { + if (err || fail) { + debug("Ready check failed (%s). Reconnecting...", err || fail); + if (this.status === "connect") { + this.disconnect(true); + } + } + else { + readyHandler(); + } + }); + } + else { + readyHandler(); + } + }; + closeListener = () => { + const error = new Error("None of startup nodes is available"); + this.removeListener("refresh", refreshListener); + this.invokeReadyDelayedCallbacks(error); + reject(error); + }; + this.once("refresh", refreshListener); + this.once("close", closeListener); + this.once("close", this.handleCloseEvent.bind(this)); + this.refreshSlotsCache((err) => { + if (err && err.message === ClusterAllFailedError_1.default.defaultMessage) { + Redis_1.default.prototype.silentEmit.call(this, "error", err); + this.connectionPool.reset([]); + } + }); + this.subscriber.start(); + if (this.options.shardedSubscribers) { + this.shardedSubscribers.start().catch((err) => { + // TODO should we emit an error event here? + debug("Error while starting subscribers: %s", err); + }); + } + }) + .catch((err) => { + this.setStatus("close"); + this.handleCloseEvent(err); + this.invokeReadyDelayedCallbacks(err); + reject(err); + }); + }); + } + /** + * Disconnect from every node in the cluster. + */ + disconnect(reconnect = false) { + const status = this.status; + this.setStatus("disconnecting"); + if (!reconnect) { + this.manuallyClosing = true; + } + if (this.reconnectTimeout && !reconnect) { + clearTimeout(this.reconnectTimeout); + this.reconnectTimeout = null; + debug("Canceled reconnecting attempts"); + } + this.clearNodesRefreshInterval(); + this.subscriber.stop(); + if (this.options.shardedSubscribers) { + this.shardedSubscribers.stop(); + } + if (status === "wait") { + this.setStatus("close"); + this.handleCloseEvent(); + } + else { + this.connectionPool.reset([]); + } + } + /** + * Quit the cluster gracefully. + */ + quit(callback) { + const status = this.status; + this.setStatus("disconnecting"); + this.manuallyClosing = true; + if (this.reconnectTimeout) { + clearTimeout(this.reconnectTimeout); + this.reconnectTimeout = null; + } + this.clearNodesRefreshInterval(); + this.subscriber.stop(); + if (this.options.shardedSubscribers) { + this.shardedSubscribers.stop(); + } + if (status === "wait") { + const ret = (0, standard_as_callback_1.default)(Promise.resolve("OK"), callback); + // use setImmediate to make sure "close" event + // being emitted after quit() is returned + setImmediate(function () { + this.setStatus("close"); + this.handleCloseEvent(); + }.bind(this)); + return ret; + } + return (0, standard_as_callback_1.default)(Promise.all(this.nodes().map((node) => node.quit().catch((err) => { + // Ignore the error caused by disconnecting since + // we're disconnecting... + if (err.message === utils_1.CONNECTION_CLOSED_ERROR_MSG) { + return "OK"; + } + throw err; + }))).then(() => "OK"), callback); + } + /** + * Create a new instance with the same startup nodes and options as the current one. + * + * @example + * ```js + * var cluster = new Redis.Cluster([{ host: "127.0.0.1", port: "30001" }]); + * var anotherCluster = cluster.duplicate(); + * ``` + */ + duplicate(overrideStartupNodes = [], overrideOptions = {}) { + const startupNodes = overrideStartupNodes.length > 0 + ? overrideStartupNodes + : this.startupNodes.slice(0); + const options = Object.assign({}, this.options, overrideOptions); + return new Cluster(startupNodes, options); + } + /** + * Get nodes with the specified role + */ + nodes(role = "all") { + if (role !== "all" && role !== "master" && role !== "slave") { + throw new Error('Invalid role "' + role + '". Expected "all", "master" or "slave"'); + } + return this.connectionPool.getNodes(role); + } + /** + * This is needed in order not to install a listener for each auto pipeline + * + * @ignore + */ + delayUntilReady(callback) { + this._readyDelayedCallbacks.push(callback); + } + /** + * Get the number of commands queued in automatic pipelines. + * + * This is not available (and returns 0) until the cluster is connected and slots information have been received. + */ + get autoPipelineQueueSize() { + let queued = 0; + for (const pipeline of this._autoPipelines.values()) { + queued += pipeline.length; + } + return queued; + } + /** + * Refresh the slot cache + * + * @ignore + */ + refreshSlotsCache(callback) { + if (callback) { + this._refreshSlotsCacheCallbacks.push(callback); + } + if (this.isRefreshing) { + return; + } + this.isRefreshing = true; + const _this = this; + const wrapper = (error) => { + this.isRefreshing = false; + for (const callback of this._refreshSlotsCacheCallbacks) { + callback(error); + } + this._refreshSlotsCacheCallbacks = []; + }; + const nodes = (0, utils_1.shuffle)(this.connectionPool.getNodes()); + let lastNodeError = null; + function tryNode(index) { + if (index === nodes.length) { + const error = new ClusterAllFailedError_1.default(ClusterAllFailedError_1.default.defaultMessage, lastNodeError); + return wrapper(error); + } + const node = nodes[index]; + const key = `${node.options.host}:${node.options.port}`; + debug("getting slot cache from %s", key); + _this.getInfoFromNode(node, function (err) { + switch (_this.status) { + case "close": + case "end": + return wrapper(new Error("Cluster is disconnected.")); + case "disconnecting": + return wrapper(new Error("Cluster is disconnecting.")); + } + if (err) { + _this.emit("node error", err, key); + lastNodeError = err; + tryNode(index + 1); + } + else { + _this.emit("refresh"); + wrapper(); + } + }); + } + tryNode(0); + } + /** + * @ignore + */ + sendCommand(command, stream, node) { + if (this.status === "wait") { + this.connect().catch(utils_1.noop); + } + if (this.status === "end") { + command.reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG)); + return command.promise; + } + let to = this.options.scaleReads; + if (to !== "master") { + const isCommandReadOnly = command.isReadOnly || + ((0, commands_1.exists)(command.name) && (0, commands_1.hasFlag)(command.name, "readonly")); + if (!isCommandReadOnly) { + to = "master"; + } + } + let targetSlot = node ? node.slot : command.getSlot(); + const ttl = {}; + const _this = this; + if (!node && !REJECT_OVERWRITTEN_COMMANDS.has(command)) { + REJECT_OVERWRITTEN_COMMANDS.add(command); + const reject = command.reject; + command.reject = function (err) { + const partialTry = tryConnection.bind(null, true); + _this.handleError(err, ttl, { + moved: function (slot, key) { + debug("command %s is moved to %s", command.name, key); + targetSlot = Number(slot); + if (_this.slots[slot]) { + _this.slots[slot][0] = key; + } + else { + _this.slots[slot] = [key]; + } + _this._groupsBySlot[slot] = + _this._groupsIds[_this.slots[slot].join(";")]; + _this.connectionPool.findOrCreate(_this.natMapper(key)); + tryConnection(); + debug("refreshing slot caches... (triggered by MOVED error)"); + _this.refreshSlotsCache(); + }, + ask: function (slot, key) { + debug("command %s is required to ask %s:%s", command.name, key); + const mapped = _this.natMapper(key); + _this.connectionPool.findOrCreate(mapped); + tryConnection(false, `${mapped.host}:${mapped.port}`); + }, + tryagain: partialTry, + clusterDown: partialTry, + connectionClosed: partialTry, + maxRedirections: function (redirectionError) { + reject.call(command, redirectionError); + }, + defaults: function () { + reject.call(command, err); + }, + }); + }; + } + tryConnection(); + function tryConnection(random, asking) { + if (_this.status === "end") { + command.reject(new redis_errors_1.AbortError("Cluster is ended.")); + return; + } + let redis; + if (_this.status === "ready" || command.name === "cluster") { + if (node && node.redis) { + redis = node.redis; + } + else if (Command_1.default.checkFlag("ENTER_SUBSCRIBER_MODE", command.name) || + Command_1.default.checkFlag("EXIT_SUBSCRIBER_MODE", command.name)) { + if (_this.options.shardedSubscribers && + (command.name == "ssubscribe" || command.name == "sunsubscribe")) { + const sub = _this.shardedSubscribers.getResponsibleSubscriber(targetSlot); + if (!sub) { + command.reject(new redis_errors_1.AbortError(`No sharded subscriber for slot: ${targetSlot}`)); + return; + } + let status = -1; + if (command.name == "ssubscribe") { + status = _this.shardedSubscribers.addChannels(command.getKeys()); + } + if (command.name == "sunsubscribe") { + status = _this.shardedSubscribers.removeChannels(command.getKeys()); + } + if (status !== -1) { + redis = sub.getInstance(); + } + else { + command.reject(new redis_errors_1.AbortError("Possible CROSSSLOT error: All channels must hash to the same slot")); + } + } + else { + redis = _this.subscriber.getInstance(); + } + if (!redis) { + command.reject(new redis_errors_1.AbortError("No subscriber for the cluster")); + return; + } + } + else { + if (!random) { + if (typeof targetSlot === "number" && _this.slots[targetSlot]) { + const nodeKeys = _this.slots[targetSlot]; + if (typeof to === "function") { + const nodes = nodeKeys.map(function (key) { + return _this.connectionPool.getInstanceByKey(key); + }); + redis = to(nodes, command); + if (Array.isArray(redis)) { + redis = (0, utils_1.sample)(redis); + } + if (!redis) { + redis = nodes[0]; + } + } + else { + let key; + if (to === "all") { + key = (0, utils_1.sample)(nodeKeys); + } + else if (to === "slave" && nodeKeys.length > 1) { + key = (0, utils_1.sample)(nodeKeys, 1); + } + else { + key = nodeKeys[0]; + } + redis = _this.connectionPool.getInstanceByKey(key); + } + } + if (asking) { + redis = _this.connectionPool.getInstanceByKey(asking); + redis.asking(); + } + } + if (!redis) { + redis = + (typeof to === "function" + ? null + : _this.connectionPool.getSampleInstance(to)) || + _this.connectionPool.getSampleInstance("all"); + } + } + if (node && !node.redis) { + node.redis = redis; + } + } + if (redis) { + redis.sendCommand(command, stream); + } + else if (_this.options.enableOfflineQueue) { + _this.offlineQueue.push({ + command: command, + stream: stream, + node: node, + }); + } + else { + command.reject(new Error("Cluster isn't ready and enableOfflineQueue options is false")); + } + } + return command.promise; + } + sscanStream(key, options) { + return this.createScanStream("sscan", { key, options }); + } + sscanBufferStream(key, options) { + return this.createScanStream("sscanBuffer", { key, options }); + } + hscanStream(key, options) { + return this.createScanStream("hscan", { key, options }); + } + hscanBufferStream(key, options) { + return this.createScanStream("hscanBuffer", { key, options }); + } + zscanStream(key, options) { + return this.createScanStream("zscan", { key, options }); + } + zscanBufferStream(key, options) { + return this.createScanStream("zscanBuffer", { key, options }); + } + /** + * @ignore + */ + handleError(error, ttl, handlers) { + if (typeof ttl.value === "undefined") { + ttl.value = this.options.maxRedirections; + } + else { + ttl.value -= 1; + } + if (ttl.value <= 0) { + handlers.maxRedirections(new Error("Too many Cluster redirections. Last error: " + error)); + return; + } + const errv = error.message.split(" "); + if (errv[0] === "MOVED") { + const timeout = this.options.retryDelayOnMoved; + if (timeout && typeof timeout === "number") { + this.delayQueue.push("moved", handlers.moved.bind(null, errv[1], errv[2]), { timeout }); + } + else { + handlers.moved(errv[1], errv[2]); + } + } + else if (errv[0] === "ASK") { + handlers.ask(errv[1], errv[2]); + } + else if (errv[0] === "TRYAGAIN") { + this.delayQueue.push("tryagain", handlers.tryagain, { + timeout: this.options.retryDelayOnTryAgain, + }); + } + else if (errv[0] === "CLUSTERDOWN" && + this.options.retryDelayOnClusterDown > 0) { + this.delayQueue.push("clusterdown", handlers.connectionClosed, { + timeout: this.options.retryDelayOnClusterDown, + callback: this.refreshSlotsCache.bind(this), + }); + } + else if (error.message === utils_1.CONNECTION_CLOSED_ERROR_MSG && + this.options.retryDelayOnFailover > 0 && + this.status === "ready") { + this.delayQueue.push("failover", handlers.connectionClosed, { + timeout: this.options.retryDelayOnFailover, + callback: this.refreshSlotsCache.bind(this), + }); + } + else { + handlers.defaults(); + } + } + resetOfflineQueue() { + this.offlineQueue = new Deque(); + } + clearNodesRefreshInterval() { + if (this.slotsTimer) { + clearTimeout(this.slotsTimer); + this.slotsTimer = null; + } + } + resetNodesRefreshInterval() { + if (this.slotsTimer || !this.options.slotsRefreshInterval) { + return; + } + const nextRound = () => { + this.slotsTimer = setTimeout(() => { + debug('refreshing slot caches... (triggered by "slotsRefreshInterval" option)'); + this.refreshSlotsCache(() => { + nextRound(); + }); + }, this.options.slotsRefreshInterval); + }; + nextRound(); + } + /** + * Change cluster instance's status + */ + setStatus(status) { + debug("status: %s -> %s", this.status || "[empty]", status); + this.status = status; + process.nextTick(() => { + this.emit(status); + }); + } + /** + * Called when closed to check whether a reconnection should be made + */ + handleCloseEvent(reason) { + var _a; + if (reason) { + debug("closed because %s", reason); + } + let retryDelay; + if (!this.manuallyClosing && + typeof this.options.clusterRetryStrategy === "function") { + retryDelay = this.options.clusterRetryStrategy.call(this, ++this.retryAttempts, reason); + } + if (typeof retryDelay === "number") { + this.setStatus("reconnecting"); + this.reconnectTimeout = setTimeout(() => { + this.reconnectTimeout = null; + debug("Cluster is disconnected. Retrying after %dms", retryDelay); + this.connect().catch(function (err) { + debug("Got error %s when reconnecting. Ignoring...", err); + }); + }, retryDelay); + } + else { + if (this.options.shardedSubscribers) { + (_a = this.subscriberGroupEmitter) === null || _a === void 0 ? void 0 : _a.removeAllListeners(); + } + this.setStatus("end"); + this.flushQueue(new Error("None of startup nodes is available")); + } + } + /** + * Flush offline queue with error. + */ + flushQueue(error) { + let item; + while ((item = this.offlineQueue.shift())) { + item.command.reject(error); + } + } + executeOfflineCommands() { + if (this.offlineQueue.length) { + debug("send %d commands in offline queue", this.offlineQueue.length); + const offlineQueue = this.offlineQueue; + this.resetOfflineQueue(); + let item; + while ((item = offlineQueue.shift())) { + this.sendCommand(item.command, item.stream, item.node); + } + } + } + natMapper(nodeKey) { + const key = typeof nodeKey === "string" + ? nodeKey + : `${nodeKey.host}:${nodeKey.port}`; + let mapped = null; + if (this.options.natMap && typeof this.options.natMap === "function") { + mapped = this.options.natMap(key); + } + else if (this.options.natMap && typeof this.options.natMap === "object") { + mapped = this.options.natMap[key]; + } + if (mapped) { + debug("NAT mapping %s -> %O", key, mapped); + return Object.assign({}, mapped); + } + return typeof nodeKey === "string" + ? (0, util_1.nodeKeyToRedisOptions)(nodeKey) + : nodeKey; + } + getInfoFromNode(redis, callback) { + if (!redis) { + return callback(new Error("Node is disconnected")); + } + // Use a duplication of the connection to avoid + // timeouts when the connection is in the blocking + // mode (e.g. waiting for BLPOP). + const duplicatedConnection = redis.duplicate({ + enableOfflineQueue: true, + enableReadyCheck: false, + retryStrategy: null, + connectionName: (0, util_1.getConnectionName)("refresher", this.options.redisOptions && this.options.redisOptions.connectionName), + }); + // Ignore error events since we will handle + // exceptions for the CLUSTER SLOTS command. + duplicatedConnection.on("error", utils_1.noop); + duplicatedConnection.cluster("SLOTS", (0, utils_1.timeout)((err, result) => { + duplicatedConnection.disconnect(); + if (err) { + debug("error encountered running CLUSTER.SLOTS: %s", err); + return callback(err); + } + if (this.status === "disconnecting" || + this.status === "close" || + this.status === "end") { + debug("ignore CLUSTER.SLOTS results (count: %d) since cluster status is %s", result.length, this.status); + callback(); + return; + } + const nodes = []; + debug("cluster slots result count: %d", result.length); + for (let i = 0; i < result.length; ++i) { + const items = result[i]; + const slotRangeStart = items[0]; + const slotRangeEnd = items[1]; + const keys = []; + for (let j = 2; j < items.length; j++) { + if (!items[j][0]) { + continue; + } + const node = this.natMapper({ + host: items[j][0], + port: items[j][1], + }); + node.readOnly = j !== 2; + nodes.push(node); + keys.push(node.host + ":" + node.port); + } + debug("cluster slots result [%d]: slots %d~%d served by %s", i, slotRangeStart, slotRangeEnd, keys); + for (let slot = slotRangeStart; slot <= slotRangeEnd; slot++) { + this.slots[slot] = keys; + } + } + // Assign to each node keys a numeric value to make autopipeline comparison faster. + this._groupsIds = Object.create(null); + let j = 0; + for (let i = 0; i < 16384; i++) { + const target = (this.slots[i] || []).join(";"); + if (!target.length) { + this._groupsBySlot[i] = undefined; + continue; + } + if (!this._groupsIds[target]) { + this._groupsIds[target] = ++j; + } + this._groupsBySlot[i] = this._groupsIds[target]; + } + this.connectionPool.reset(nodes); + if (this.options.shardedSubscribers) { + this.shardedSubscribers + .reset(this.slots, this.connectionPool.getNodes("all")) + .catch((err) => { + // TODO should we emit an error event here? + debug("Error while starting subscribers: %s", err); + }); + } + callback(); + }, this.options.slotsRefreshTimeout)); + } + invokeReadyDelayedCallbacks(err) { + for (const c of this._readyDelayedCallbacks) { + process.nextTick(c, err); + } + this._readyDelayedCallbacks = []; + } + /** + * Check whether Cluster is able to process commands + */ + readyCheck(callback) { + this.cluster("INFO", (err, res) => { + if (err) { + return callback(err); + } + if (typeof res !== "string") { + return callback(); + } + let state; + const lines = res.split("\r\n"); + for (let i = 0; i < lines.length; ++i) { + const parts = lines[i].split(":"); + if (parts[0] === "cluster_state") { + state = parts[1]; + break; + } + } + if (state === "fail") { + debug("cluster state not ok (%s)", state); + callback(null, state); + } + else { + callback(); + } + }); + } + resolveSrv(hostname) { + return new Promise((resolve, reject) => { + this.options.resolveSrv(hostname, (err, records) => { + if (err) { + return reject(err); + } + const self = this, groupedRecords = (0, util_1.groupSrvRecords)(records), sortedKeys = Object.keys(groupedRecords).sort((a, b) => parseInt(a) - parseInt(b)); + function tryFirstOne(err) { + if (!sortedKeys.length) { + return reject(err); + } + const key = sortedKeys[0], group = groupedRecords[key], record = (0, util_1.weightSrvRecords)(group); + if (!group.records.length) { + sortedKeys.shift(); + } + self.dnsLookup(record.name).then((host) => resolve({ + host, + port: record.port, + }), tryFirstOne); + } + tryFirstOne(); + }); + }); + } + dnsLookup(hostname) { + return new Promise((resolve, reject) => { + this.options.dnsLookup(hostname, (err, address) => { + if (err) { + debug("failed to resolve hostname %s to IP: %s", hostname, err.message); + reject(err); + } + else { + debug("resolved hostname %s to IP %s", hostname, address); + resolve(address); + } + }); + }); + } + /** + * Normalize startup nodes, and resolving hostnames to IPs. + * + * This process happens every time when #connect() is called since + * #startupNodes and DNS records may chanage. + */ + async resolveStartupNodeHostnames() { + if (!Array.isArray(this.startupNodes) || this.startupNodes.length === 0) { + throw new Error("`startupNodes` should contain at least one node."); + } + const startupNodes = (0, util_1.normalizeNodeOptions)(this.startupNodes); + const hostnames = (0, util_1.getUniqueHostnamesFromOptions)(startupNodes); + if (hostnames.length === 0) { + return startupNodes; + } + const configs = await Promise.all(hostnames.map((this.options.useSRVRecords ? this.resolveSrv : this.dnsLookup).bind(this))); + const hostnameToConfig = (0, utils_1.zipMap)(hostnames, configs); + return startupNodes.map((node) => { + const config = hostnameToConfig.get(node.host); + if (!config) { + return node; + } + if (this.options.useSRVRecords) { + return Object.assign({}, node, config); + } + return Object.assign({}, node, { host: config }); + }); + } + createScanStream(command, { key, options = {} }) { + return new ScanStream_1.default({ + objectMode: true, + key: key, + redis: this, + command: command, + ...options, + }); + } + createShardedSubscriberGroup() { + this.subscriberGroupEmitter = new events_1.EventEmitter(); + this.shardedSubscribers = new ClusterSubscriberGroup_1.default(this.subscriberGroupEmitter, this.options); + // Error handler used only for sharded-subscriber-triggered slots cache refreshes. + // Normal (non-subscriber) connections are created with lazyConnect: true and can + // become zombied. For sharded subscribers, a ClusterAllFailedError means + // we have lost all nodes from the subscriber perspective and must tear down. + const refreshSlotsCacheCallback = (err) => { + // Disconnect only when refreshing the slots cache fails with ClusterAllFailedError + if (err instanceof ClusterAllFailedError_1.default) { + this.disconnect(true); + } + }; + this.subscriberGroupEmitter.on("-node", (redis, nodeKey) => { + this.emit("-node", redis, nodeKey); + this.refreshSlotsCache(refreshSlotsCacheCallback); + }); + this.subscriberGroupEmitter.on("subscriberConnectFailed", ({ delay, error }) => { + this.emit("error", error); + setTimeout(() => { + this.refreshSlotsCache(refreshSlotsCacheCallback); + }, delay); + }); + this.subscriberGroupEmitter.on("moved", () => { + this.refreshSlotsCache(refreshSlotsCacheCallback); + }); + this.subscriberGroupEmitter.on("-subscriber", () => { + this.emit("-subscriber"); + }); + this.subscriberGroupEmitter.on("+subscriber", () => { + this.emit("+subscriber"); + }); + this.subscriberGroupEmitter.on("nodeError", (error, nodeKey) => { + this.emit("nodeError", error, nodeKey); + }); + this.subscriberGroupEmitter.on("subscribersReady", () => { + this.emit("subscribersReady"); + }); + for (const event of ["smessage", "smessageBuffer"]) { + this.subscriberGroupEmitter.on(event, (arg1, arg2, arg3) => { + this.emit(event, arg1, arg2, arg3); + }); + } + } +} +(0, applyMixin_1.default)(Cluster, events_1.EventEmitter); +(0, transaction_1.addTransactionSupport)(Cluster.prototype); +exports.default = Cluster; diff --git a/backend/node_modules/ioredis/built/cluster/util.d.ts b/backend/node_modules/ioredis/built/cluster/util.d.ts new file mode 100644 index 0000000..d8629c3 --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/util.d.ts @@ -0,0 +1,25 @@ +/// +import { SrvRecord } from "dns"; +export declare type NodeKey = string; +export declare type NodeRole = "master" | "slave" | "all"; +export interface RedisOptions { + port: number; + host: string; + username?: string | undefined; + password?: string | undefined; + [key: string]: any; +} +export interface SrvRecordsGroup { + totalWeight: number; + records: SrvRecord[]; +} +export interface GroupedSrvRecords { + [key: number]: SrvRecordsGroup; +} +export declare function getNodeKey(node: RedisOptions): NodeKey; +export declare function nodeKeyToRedisOptions(nodeKey: NodeKey): RedisOptions; +export declare function normalizeNodeOptions(nodes: Array): RedisOptions[]; +export declare function getUniqueHostnamesFromOptions(nodes: RedisOptions[]): string[]; +export declare function groupSrvRecords(records: SrvRecord[]): GroupedSrvRecords; +export declare function weightSrvRecords(recordsGroup: SrvRecordsGroup): SrvRecord; +export declare function getConnectionName(component: any, nodeConnectionName: any): string; diff --git a/backend/node_modules/ioredis/built/cluster/util.js b/backend/node_modules/ioredis/built/cluster/util.js new file mode 100644 index 0000000..e3a779b --- /dev/null +++ b/backend/node_modules/ioredis/built/cluster/util.js @@ -0,0 +1,100 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getConnectionName = exports.weightSrvRecords = exports.groupSrvRecords = exports.getUniqueHostnamesFromOptions = exports.normalizeNodeOptions = exports.nodeKeyToRedisOptions = exports.getNodeKey = void 0; +const utils_1 = require("../utils"); +const net_1 = require("net"); +function getNodeKey(node) { + node.port = node.port || 6379; + node.host = node.host || "127.0.0.1"; + return node.host + ":" + node.port; +} +exports.getNodeKey = getNodeKey; +function nodeKeyToRedisOptions(nodeKey) { + const portIndex = nodeKey.lastIndexOf(":"); + if (portIndex === -1) { + throw new Error(`Invalid node key ${nodeKey}`); + } + return { + host: nodeKey.slice(0, portIndex), + port: Number(nodeKey.slice(portIndex + 1)), + }; +} +exports.nodeKeyToRedisOptions = nodeKeyToRedisOptions; +function normalizeNodeOptions(nodes) { + return nodes.map((node) => { + const options = {}; + if (typeof node === "object") { + Object.assign(options, node); + } + else if (typeof node === "string") { + Object.assign(options, (0, utils_1.parseURL)(node)); + } + else if (typeof node === "number") { + options.port = node; + } + else { + throw new Error("Invalid argument " + node); + } + if (typeof options.port === "string") { + options.port = parseInt(options.port, 10); + } + // Cluster mode only support db 0 + delete options.db; + if (!options.port) { + options.port = 6379; + } + if (!options.host) { + options.host = "127.0.0.1"; + } + return (0, utils_1.resolveTLSProfile)(options); + }); +} +exports.normalizeNodeOptions = normalizeNodeOptions; +function getUniqueHostnamesFromOptions(nodes) { + const uniqueHostsMap = {}; + nodes.forEach((node) => { + uniqueHostsMap[node.host] = true; + }); + return Object.keys(uniqueHostsMap).filter((host) => !(0, net_1.isIP)(host)); +} +exports.getUniqueHostnamesFromOptions = getUniqueHostnamesFromOptions; +function groupSrvRecords(records) { + const recordsByPriority = {}; + for (const record of records) { + if (!recordsByPriority.hasOwnProperty(record.priority)) { + recordsByPriority[record.priority] = { + totalWeight: record.weight, + records: [record], + }; + } + else { + recordsByPriority[record.priority].totalWeight += record.weight; + recordsByPriority[record.priority].records.push(record); + } + } + return recordsByPriority; +} +exports.groupSrvRecords = groupSrvRecords; +function weightSrvRecords(recordsGroup) { + if (recordsGroup.records.length === 1) { + recordsGroup.totalWeight = 0; + return recordsGroup.records.shift(); + } + // + `recordsGroup.records.length` to support `weight` 0 + const random = Math.floor(Math.random() * (recordsGroup.totalWeight + recordsGroup.records.length)); + let total = 0; + for (const [i, record] of recordsGroup.records.entries()) { + total += 1 + record.weight; + if (total > random) { + recordsGroup.totalWeight -= record.weight; + recordsGroup.records.splice(i, 1); + return record; + } + } +} +exports.weightSrvRecords = weightSrvRecords; +function getConnectionName(component, nodeConnectionName) { + const prefix = `ioredis-cluster(${component})`; + return nodeConnectionName ? `${prefix}:${nodeConnectionName}` : prefix; +} +exports.getConnectionName = getConnectionName; diff --git a/backend/node_modules/ioredis/built/connectors/AbstractConnector.d.ts b/backend/node_modules/ioredis/built/connectors/AbstractConnector.d.ts new file mode 100644 index 0000000..14bdbaa --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/AbstractConnector.d.ts @@ -0,0 +1,12 @@ +import { NetStream } from "../types"; +export declare type ErrorEmitter = (type: string, err: Error) => void; +export default abstract class AbstractConnector { + firstError?: Error; + protected connecting: boolean; + protected stream: NetStream; + private disconnectTimeout; + constructor(disconnectTimeout: number); + check(info: any): boolean; + disconnect(): void; + abstract connect(_: ErrorEmitter): Promise; +} diff --git a/backend/node_modules/ioredis/built/connectors/AbstractConnector.js b/backend/node_modules/ioredis/built/connectors/AbstractConnector.js new file mode 100644 index 0000000..2e2151d --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/AbstractConnector.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("../utils"); +const debug = (0, utils_1.Debug)("AbstractConnector"); +class AbstractConnector { + constructor(disconnectTimeout) { + this.connecting = false; + this.disconnectTimeout = disconnectTimeout; + } + check(info) { + return true; + } + disconnect() { + this.connecting = false; + if (this.stream) { + const stream = this.stream; // Make sure callbacks refer to the same instance + const timeout = setTimeout(() => { + debug("stream %s:%s still open, destroying it", stream.remoteAddress, stream.remotePort); + stream.destroy(); + }, this.disconnectTimeout); + stream.on("close", () => clearTimeout(timeout)); + stream.end(); + } + } +} +exports.default = AbstractConnector; diff --git a/backend/node_modules/ioredis/built/connectors/ConnectorConstructor.d.ts b/backend/node_modules/ioredis/built/connectors/ConnectorConstructor.d.ts new file mode 100644 index 0000000..2f332ae --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/ConnectorConstructor.d.ts @@ -0,0 +1,5 @@ +import AbstractConnector from "./AbstractConnector"; +interface ConnectorConstructor { + new (options: unknown): AbstractConnector; +} +export default ConnectorConstructor; diff --git a/backend/node_modules/ioredis/built/connectors/ConnectorConstructor.js b/backend/node_modules/ioredis/built/connectors/ConnectorConstructor.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/ConnectorConstructor.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.d.ts b/backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.d.ts new file mode 100644 index 0000000..abd44e5 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.d.ts @@ -0,0 +1,11 @@ +import SentinelConnector from "./index"; +import { Sentinel } from "./types"; +export declare class FailoverDetector { + private connector; + private sentinels; + private isDisconnected; + constructor(connector: SentinelConnector, sentinels: Sentinel[]); + cleanup(): void; + subscribe(): Promise; + private disconnect; +} diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.js b/backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.js new file mode 100644 index 0000000..8db28d0 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FailoverDetector = void 0; +const utils_1 = require("../../utils"); +const debug = (0, utils_1.Debug)("FailoverDetector"); +const CHANNEL_NAME = "+switch-master"; +class FailoverDetector { + // sentinels can't be used for regular commands after this + constructor(connector, sentinels) { + this.isDisconnected = false; + this.connector = connector; + this.sentinels = sentinels; + } + cleanup() { + this.isDisconnected = true; + for (const sentinel of this.sentinels) { + sentinel.client.disconnect(); + } + } + async subscribe() { + debug("Starting FailoverDetector"); + const promises = []; + for (const sentinel of this.sentinels) { + const promise = sentinel.client.subscribe(CHANNEL_NAME).catch((err) => { + debug("Failed to subscribe to failover messages on sentinel %s:%s (%s)", sentinel.address.host || "127.0.0.1", sentinel.address.port || 26739, err.message); + }); + promises.push(promise); + sentinel.client.on("message", (channel) => { + if (!this.isDisconnected && channel === CHANNEL_NAME) { + this.disconnect(); + } + }); + } + await Promise.all(promises); + } + disconnect() { + // Avoid disconnecting more than once per failover. + // A new FailoverDetector will be created after reconnecting. + this.isDisconnected = true; + debug("Failover detected, disconnecting"); + // Will call this.cleanup() + this.connector.disconnect(); + } +} +exports.FailoverDetector = FailoverDetector; diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.d.ts b/backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.d.ts new file mode 100644 index 0000000..fbe5f34 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.d.ts @@ -0,0 +1,13 @@ +import { SentinelAddress } from "./types"; +export default class SentinelIterator implements Iterator> { + private cursor; + private sentinels; + constructor(sentinels: Array>); + next(): { + done: boolean; + value: Partial; + }; + reset(moveCurrentEndpointToFirst: boolean): void; + add(sentinel: SentinelAddress): boolean; + toString(): string; +} diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.js b/backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.js new file mode 100644 index 0000000..3399bae --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.js @@ -0,0 +1,37 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function isSentinelEql(a, b) { + return ((a.host || "127.0.0.1") === (b.host || "127.0.0.1") && + (a.port || 26379) === (b.port || 26379)); +} +class SentinelIterator { + constructor(sentinels) { + this.cursor = 0; + this.sentinels = sentinels.slice(0); + } + next() { + const done = this.cursor >= this.sentinels.length; + return { done, value: done ? undefined : this.sentinels[this.cursor++] }; + } + reset(moveCurrentEndpointToFirst) { + if (moveCurrentEndpointToFirst && + this.sentinels.length > 1 && + this.cursor !== 1) { + this.sentinels.unshift(...this.sentinels.splice(this.cursor - 1)); + } + this.cursor = 0; + } + add(sentinel) { + for (let i = 0; i < this.sentinels.length; i++) { + if (isSentinelEql(sentinel, this.sentinels[i])) { + return false; + } + } + this.sentinels.push(sentinel); + return true; + } + toString() { + return `${JSON.stringify(this.sentinels)} @${this.cursor}`; + } +} +exports.default = SentinelIterator; diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/index.d.ts b/backend/node_modules/ioredis/built/connectors/SentinelConnector/index.d.ts new file mode 100644 index 0000000..66660e5 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/index.d.ts @@ -0,0 +1,72 @@ +/// +import { EventEmitter } from "events"; +import { NatMap } from "../../cluster/ClusterOptions"; +import { ConnectionOptions } from "tls"; +import SentinelIterator from "./SentinelIterator"; +import { SentinelAddress } from "./types"; +import AbstractConnector, { ErrorEmitter } from "../AbstractConnector"; +import { NetStream } from "../../types"; +interface AddressFromResponse { + port: string; + ip: string; + flags?: string | undefined; +} +declare type PreferredSlaves = ((slaves: AddressFromResponse[]) => AddressFromResponse | null) | Array<{ + port: string; + ip: string; + prio?: number | undefined; +}> | { + port: string; + ip: string; + prio?: number | undefined; +}; +export { SentinelAddress, SentinelIterator }; +export interface SentinelConnectionOptions { + /** + * Master group name of the Sentinel + */ + name?: string | undefined; + /** + * @default "master" + */ + role?: "master" | "slave" | undefined; + tls?: ConnectionOptions | undefined; + sentinelUsername?: string | undefined; + sentinelPassword?: string | undefined; + sentinels?: Array> | undefined; + sentinelRetryStrategy?: ((retryAttempts: number) => number | void | null) | undefined; + sentinelReconnectStrategy?: ((retryAttempts: number) => number | void | null) | undefined; + preferredSlaves?: PreferredSlaves | undefined; + connectTimeout?: number | undefined; + disconnectTimeout?: number | undefined; + sentinelCommandTimeout?: number | undefined; + enableTLSForSentinelMode?: boolean | undefined; + sentinelTLS?: ConnectionOptions | undefined; + natMap?: NatMap | undefined; + updateSentinels?: boolean | undefined; + /** + * @default 10 + */ + sentinelMaxConnections?: number | undefined; + failoverDetector?: boolean | undefined; +} +export default class SentinelConnector extends AbstractConnector { + protected options: SentinelConnectionOptions; + emitter: EventEmitter | null; + protected sentinelIterator: SentinelIterator; + private retryAttempts; + private failoverDetector; + constructor(options: SentinelConnectionOptions); + check(info: { + role?: string; + }): boolean; + disconnect(): void; + connect(eventEmitter: ErrorEmitter): Promise; + private updateSentinels; + private resolveMaster; + private resolveSlave; + private sentinelNatResolve; + private connectToSentinel; + private resolve; + private initFailoverDetector; +} diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/index.js b/backend/node_modules/ioredis/built/connectors/SentinelConnector/index.js new file mode 100644 index 0000000..5cb4b48 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/index.js @@ -0,0 +1,305 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SentinelIterator = void 0; +const net_1 = require("net"); +const utils_1 = require("../../utils"); +const tls_1 = require("tls"); +const SentinelIterator_1 = require("./SentinelIterator"); +exports.SentinelIterator = SentinelIterator_1.default; +const AbstractConnector_1 = require("../AbstractConnector"); +const Redis_1 = require("../../Redis"); +const FailoverDetector_1 = require("./FailoverDetector"); +const debug = (0, utils_1.Debug)("SentinelConnector"); +class SentinelConnector extends AbstractConnector_1.default { + constructor(options) { + super(options.disconnectTimeout); + this.options = options; + this.emitter = null; + this.failoverDetector = null; + if (!this.options.sentinels.length) { + throw new Error("Requires at least one sentinel to connect to."); + } + if (!this.options.name) { + throw new Error("Requires the name of master."); + } + this.sentinelIterator = new SentinelIterator_1.default(this.options.sentinels); + } + check(info) { + const roleMatches = !info.role || this.options.role === info.role; + if (!roleMatches) { + debug("role invalid, expected %s, but got %s", this.options.role, info.role); + // Start from the next item. + // Note that `reset` will move the cursor to the previous element, + // so we advance two steps here. + this.sentinelIterator.next(); + this.sentinelIterator.next(); + this.sentinelIterator.reset(true); + } + return roleMatches; + } + disconnect() { + super.disconnect(); + if (this.failoverDetector) { + this.failoverDetector.cleanup(); + } + } + connect(eventEmitter) { + this.connecting = true; + this.retryAttempts = 0; + let lastError; + const connectToNext = async () => { + const endpoint = this.sentinelIterator.next(); + if (endpoint.done) { + this.sentinelIterator.reset(false); + const retryDelay = typeof this.options.sentinelRetryStrategy === "function" + ? this.options.sentinelRetryStrategy(++this.retryAttempts) + : null; + let errorMsg = typeof retryDelay !== "number" + ? "All sentinels are unreachable and retry is disabled." + : `All sentinels are unreachable. Retrying from scratch after ${retryDelay}ms.`; + if (lastError) { + errorMsg += ` Last error: ${lastError.message}`; + } + debug(errorMsg); + const error = new Error(errorMsg); + if (typeof retryDelay === "number") { + eventEmitter("error", error); + await new Promise((resolve) => setTimeout(resolve, retryDelay)); + return connectToNext(); + } + else { + throw error; + } + } + let resolved = null; + let err = null; + try { + resolved = await this.resolve(endpoint.value); + } + catch (error) { + err = error; + } + if (!this.connecting) { + throw new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG); + } + const endpointAddress = endpoint.value.host + ":" + endpoint.value.port; + if (resolved) { + debug("resolved: %s:%s from sentinel %s", resolved.host, resolved.port, endpointAddress); + if (this.options.enableTLSForSentinelMode && this.options.tls) { + Object.assign(resolved, this.options.tls); + this.stream = (0, tls_1.connect)(resolved); + this.stream.once("secureConnect", this.initFailoverDetector.bind(this)); + } + else { + this.stream = (0, net_1.createConnection)(resolved); + this.stream.once("connect", this.initFailoverDetector.bind(this)); + } + this.stream.once("error", (err) => { + this.firstError = err; + }); + return this.stream; + } + else { + const errorMsg = err + ? "failed to connect to sentinel " + + endpointAddress + + " because " + + err.message + : "connected to sentinel " + + endpointAddress + + " successfully, but got an invalid reply: " + + resolved; + debug(errorMsg); + eventEmitter("sentinelError", new Error(errorMsg)); + if (err) { + lastError = err; + } + return connectToNext(); + } + }; + return connectToNext(); + } + async updateSentinels(client) { + if (!this.options.updateSentinels) { + return; + } + const result = await client.sentinel("sentinels", this.options.name); + if (!Array.isArray(result)) { + return; + } + result + .map(utils_1.packObject) + .forEach((sentinel) => { + const flags = sentinel.flags ? sentinel.flags.split(",") : []; + if (flags.indexOf("disconnected") === -1 && + sentinel.ip && + sentinel.port) { + const endpoint = this.sentinelNatResolve(addressResponseToAddress(sentinel)); + if (this.sentinelIterator.add(endpoint)) { + debug("adding sentinel %s:%s", endpoint.host, endpoint.port); + } + } + }); + debug("Updated internal sentinels: %s", this.sentinelIterator); + } + async resolveMaster(client) { + const result = await client.sentinel("get-master-addr-by-name", this.options.name); + await this.updateSentinels(client); + return this.sentinelNatResolve(Array.isArray(result) + ? { host: result[0], port: Number(result[1]) } + : null); + } + async resolveSlave(client) { + const result = await client.sentinel("slaves", this.options.name); + if (!Array.isArray(result)) { + return null; + } + const availableSlaves = result + .map(utils_1.packObject) + .filter((slave) => slave.flags && !slave.flags.match(/(disconnected|s_down|o_down)/)); + return this.sentinelNatResolve(selectPreferredSentinel(availableSlaves, this.options.preferredSlaves)); + } + sentinelNatResolve(item) { + if (!item || !this.options.natMap) + return item; + const key = `${item.host}:${item.port}`; + let result = item; + if (typeof this.options.natMap === "function") { + result = this.options.natMap(key) || item; + } + else if (typeof this.options.natMap === "object") { + result = this.options.natMap[key] || item; + } + return result; + } + connectToSentinel(endpoint, options) { + const redis = new Redis_1.default({ + port: endpoint.port || 26379, + host: endpoint.host, + username: this.options.sentinelUsername || null, + password: this.options.sentinelPassword || null, + family: endpoint.family || + // @ts-expect-error + ("path" in this.options && this.options.path + ? undefined + : // @ts-expect-error + this.options.family), + tls: this.options.sentinelTLS, + retryStrategy: null, + enableReadyCheck: false, + connectTimeout: this.options.connectTimeout, + commandTimeout: this.options.sentinelCommandTimeout, + ...options, + }); + // @ts-expect-error + return redis; + } + async resolve(endpoint) { + const client = this.connectToSentinel(endpoint); + // ignore the errors since resolve* methods will handle them + client.on("error", noop); + try { + if (this.options.role === "slave") { + return await this.resolveSlave(client); + } + else { + return await this.resolveMaster(client); + } + } + finally { + client.disconnect(); + } + } + async initFailoverDetector() { + var _a; + if (!this.options.failoverDetector) { + return; + } + // Move the current sentinel to the first position + this.sentinelIterator.reset(true); + const sentinels = []; + // In case of a large amount of sentinels, limit the number of concurrent connections + while (sentinels.length < this.options.sentinelMaxConnections) { + const { done, value } = this.sentinelIterator.next(); + if (done) { + break; + } + const client = this.connectToSentinel(value, { + lazyConnect: true, + retryStrategy: this.options.sentinelReconnectStrategy, + }); + client.on("reconnecting", () => { + var _a; + // Tests listen to this event + (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit("sentinelReconnecting"); + }); + sentinels.push({ address: value, client }); + } + this.sentinelIterator.reset(false); + if (this.failoverDetector) { + // Clean up previous detector + this.failoverDetector.cleanup(); + } + this.failoverDetector = new FailoverDetector_1.FailoverDetector(this, sentinels); + await this.failoverDetector.subscribe(); + // Tests listen to this event + (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit("failoverSubscribed"); + } +} +exports.default = SentinelConnector; +function selectPreferredSentinel(availableSlaves, preferredSlaves) { + if (availableSlaves.length === 0) { + return null; + } + let selectedSlave; + if (typeof preferredSlaves === "function") { + selectedSlave = preferredSlaves(availableSlaves); + } + else if (preferredSlaves !== null && typeof preferredSlaves === "object") { + const preferredSlavesArray = Array.isArray(preferredSlaves) + ? preferredSlaves + : [preferredSlaves]; + // sort by priority + preferredSlavesArray.sort((a, b) => { + // default the priority to 1 + if (!a.prio) { + a.prio = 1; + } + if (!b.prio) { + b.prio = 1; + } + // lowest priority first + if (a.prio < b.prio) { + return -1; + } + if (a.prio > b.prio) { + return 1; + } + return 0; + }); + // loop over preferred slaves and return the first match + for (let p = 0; p < preferredSlavesArray.length; p++) { + for (let a = 0; a < availableSlaves.length; a++) { + const slave = availableSlaves[a]; + if (slave.ip === preferredSlavesArray[p].ip) { + if (slave.port === preferredSlavesArray[p].port) { + selectedSlave = slave; + break; + } + } + } + if (selectedSlave) { + break; + } + } + } + // if none of the preferred slaves are available, a random available slave is returned + if (!selectedSlave) { + selectedSlave = (0, utils_1.sample)(availableSlaves); + } + return addressResponseToAddress(selectedSlave); +} +function addressResponseToAddress(input) { + return { host: input.ip, port: Number(input.port) }; +} +function noop() { } diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/types.d.ts b/backend/node_modules/ioredis/built/connectors/SentinelConnector/types.d.ts new file mode 100644 index 0000000..4734cdc --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/types.d.ts @@ -0,0 +1,21 @@ +import { RedisOptions } from "../../redis/RedisOptions"; +export interface SentinelAddress { + port: number; + host: string; + family?: number; +} +export interface RedisClient { + options: RedisOptions; + sentinel(subcommand: "sentinels", name: string): Promise; + sentinel(subcommand: "get-master-addr-by-name", name: string): Promise; + sentinel(subcommand: "slaves", name: string): Promise; + subscribe(...channelNames: string[]): Promise; + on(event: "message", callback: (channel: string, message: string) => void): void; + on(event: "error", callback: (error: Error) => void): void; + on(event: "reconnecting", callback: () => void): void; + disconnect(): void; +} +export interface Sentinel { + address: Partial; + client: RedisClient; +} diff --git a/backend/node_modules/ioredis/built/connectors/SentinelConnector/types.js b/backend/node_modules/ioredis/built/connectors/SentinelConnector/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/SentinelConnector/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/backend/node_modules/ioredis/built/connectors/StandaloneConnector.d.ts b/backend/node_modules/ioredis/built/connectors/StandaloneConnector.d.ts new file mode 100644 index 0000000..45fb552 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/StandaloneConnector.d.ts @@ -0,0 +1,17 @@ +/// +import { IpcNetConnectOpts, TcpNetConnectOpts } from "net"; +import { ConnectionOptions } from "tls"; +import { NetStream } from "../types"; +import AbstractConnector, { ErrorEmitter } from "./AbstractConnector"; +declare type TcpOptions = Pick; +declare type IpcOptions = Pick; +export declare type StandaloneConnectionOptions = Partial & { + disconnectTimeout?: number | undefined; + tls?: ConnectionOptions | undefined; +}; +export default class StandaloneConnector extends AbstractConnector { + protected options: StandaloneConnectionOptions; + constructor(options: StandaloneConnectionOptions); + connect(_: ErrorEmitter): Promise; +} +export {}; diff --git a/backend/node_modules/ioredis/built/connectors/StandaloneConnector.js b/backend/node_modules/ioredis/built/connectors/StandaloneConnector.js new file mode 100644 index 0000000..d17c91a --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/StandaloneConnector.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const net_1 = require("net"); +const tls_1 = require("tls"); +const utils_1 = require("../utils"); +const AbstractConnector_1 = require("./AbstractConnector"); +class StandaloneConnector extends AbstractConnector_1.default { + constructor(options) { + super(options.disconnectTimeout); + this.options = options; + } + connect(_) { + const { options } = this; + this.connecting = true; + let connectionOptions; + if ("path" in options && options.path) { + connectionOptions = { + path: options.path, + }; + } + else { + connectionOptions = {}; + if ("port" in options && options.port != null) { + connectionOptions.port = options.port; + } + if ("host" in options && options.host != null) { + connectionOptions.host = options.host; + } + if ("family" in options && options.family != null) { + connectionOptions.family = options.family; + } + } + if (options.tls) { + Object.assign(connectionOptions, options.tls); + } + // TODO: + // We use native Promise here since other Promise + // implementation may use different schedulers that + // cause issue when the stream is resolved in the + // next tick. + // Should use the provided promise in the next major + // version and do not connect before resolved. + return new Promise((resolve, reject) => { + process.nextTick(() => { + if (!this.connecting) { + reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG)); + return; + } + try { + if (options.tls) { + this.stream = (0, tls_1.connect)(connectionOptions); + } + else { + this.stream = (0, net_1.createConnection)(connectionOptions); + } + } + catch (err) { + reject(err); + return; + } + this.stream.once("error", (err) => { + this.firstError = err; + }); + resolve(this.stream); + }); + }); + } +} +exports.default = StandaloneConnector; diff --git a/backend/node_modules/ioredis/built/connectors/index.d.ts b/backend/node_modules/ioredis/built/connectors/index.d.ts new file mode 100644 index 0000000..fa74d6f --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/index.d.ts @@ -0,0 +1,3 @@ +import StandaloneConnector from "./StandaloneConnector"; +import SentinelConnector from "./SentinelConnector"; +export { StandaloneConnector, SentinelConnector }; diff --git a/backend/node_modules/ioredis/built/connectors/index.js b/backend/node_modules/ioredis/built/connectors/index.js new file mode 100644 index 0000000..49a03a2 --- /dev/null +++ b/backend/node_modules/ioredis/built/connectors/index.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SentinelConnector = exports.StandaloneConnector = void 0; +const StandaloneConnector_1 = require("./StandaloneConnector"); +exports.StandaloneConnector = StandaloneConnector_1.default; +const SentinelConnector_1 = require("./SentinelConnector"); +exports.SentinelConnector = SentinelConnector_1.default; diff --git a/backend/node_modules/ioredis/built/constants/TLSProfiles.d.ts b/backend/node_modules/ioredis/built/constants/TLSProfiles.d.ts new file mode 100644 index 0000000..7547966 --- /dev/null +++ b/backend/node_modules/ioredis/built/constants/TLSProfiles.d.ts @@ -0,0 +1,9 @@ +declare const TLSProfiles: { + readonly RedisCloudFixed: { + readonly ca: "-----BEGIN CERTIFICATE-----\nMIIDTzCCAjegAwIBAgIJAKSVpiDswLcwMA0GCSqGSIb3DQEBBQUAMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTAeFw0xMzEwMDExMjE0NTVaFw0yMzA5MjkxMjE0NTVaMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZqkh/DczWP\nJnxnHLQ7QL0T4B4CDKWBKCcisriGbA6ZePWVNo4hfKQC6JrzfR+081NeD6VcWUiz\nrmd+jtPhIY4c+WVQYm5PKaN6DT1imYdxQw7aqO5j2KUCEh/cznpLxeSHoTxlR34E\nQwF28Wl3eg2vc5ct8LjU3eozWVk3gb7alx9mSA2SgmuX5lEQawl++rSjsBStemY2\nBDwOpAMXIrdEyP/cVn8mkvi/BDs5M5G+09j0gfhyCzRWMQ7Hn71u1eolRxwVxgi3\nTMn+/vTaFSqxKjgck6zuAYjBRPaHe7qLxHNr1So/Mc9nPy+3wHebFwbIcnUojwbp\n4nctkWbjb2cCAwEAAaNQME4wHQYDVR0OBBYEFP1whtcrydmW3ZJeuSoKZIKjze3w\nMB8GA1UdIwQYMBaAFP1whtcrydmW3ZJeuSoKZIKjze3wMAwGA1UdEwQFMAMBAf8w\nDQYJKoZIhvcNAQEFBQADggEBAG2erXhwRAa7+ZOBs0B6X57Hwyd1R4kfmXcs0rta\nlbPpvgULSiB+TCbf3EbhJnHGyvdCY1tvlffLjdA7HJ0PCOn+YYLBA0pTU/dyvrN6\nSu8NuS5yubnt9mb13nDGYo1rnt0YRfxN+8DM3fXIVr038A30UlPX2Ou1ExFJT0MZ\nuFKY6ZvLdI6/1cbgmguMlAhM+DhKyV6Sr5699LM3zqeI816pZmlREETYkGr91q7k\nBpXJu/dtHaGxg1ZGu6w/PCsYGUcECWENYD4VQPd8N32JjOfu6vEgoEAwfPP+3oGp\nZ4m3ewACcWOAenqflb+cQYC4PsF7qbXDmRaWrbKntOlZ3n0=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIGMTCCBBmgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMx\nCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJDQTESMBAGA1UECgwJUmVkaXNMYWJzMS0w\nKwYDVQQDDCRSZWRpc0xhYnMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN\nMTgwMjI1MTUzNzM3WhcNMjgwMjIzMTUzNzM3WjBfMQswCQYDVQQGEwJVUzELMAkG\nA1UECAwCQ0ExEjAQBgNVBAoMCVJlZGlzTGFiczEvMC0GA1UEAwwmUkNQIEludGVy\nbWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA\nA4ICDwAwggIKAoICAQDf9dqbxc8Bq7Ctq9rWcxrGNKKHivqLAFpPq02yLPx6fsOv\nTq7GsDChAYBBc4v7Y2Ap9RD5Vs3dIhEANcnolf27QwrG9RMnnvzk8pCvp1o6zSU4\nVuOE1W66/O1/7e2rVxyrnTcP7UgK43zNIXu7+tiAqWsO92uSnuMoGPGpeaUm1jym\nhjWKtkAwDFSqvHY+XL5qDVBEjeUe+WHkYUg40cAXjusAqgm2hZt29c2wnVrxW25W\nP0meNlzHGFdA2AC5z54iRiqj57dTfBTkHoBczQxcyw6hhzxZQ4e5I5zOKjXXEhZN\nr0tA3YC14CTabKRus/JmZieyZzRgEy2oti64tmLYTqSlAD78pRL40VNoaSYetXLw\nhhNsXCHgWaY6d5bLOc/aIQMAV5oLvZQKvuXAF1IDmhPA+bZbpWipp0zagf1P1H3s\nUzsMdn2KM0ejzgotbtNlj5TcrVwpmvE3ktvUAuA+hi3FkVx1US+2Gsp5x4YOzJ7u\nP1WPk6ShF0JgnJH2ILdj6kttTWwFzH17keSFICWDfH/+kM+k7Y1v3EXMQXE7y0T9\nMjvJskz6d/nv+sQhY04xt64xFMGTnZjlJMzfQNi7zWFLTZnDD0lPowq7l3YiPoTT\nt5Xky83lu0KZsZBo0WlWaDG00gLVdtRgVbcuSWxpi5BdLb1kRab66JptWjxwXQID\nAQABo4HrMIHoMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHBzOi8vcmwtY2Etc2VydmVy\nLnJlZGlzbGFicy5jb20vdjEvY3JsMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcw\nAYYqaHR0cHM6Ly9ybC1jYS1zZXJ2ZXIucmVkaXNsYWJzLmNvbS92MS9vY3NwMB0G\nA1UdDgQWBBQHar5OKvQUpP2qWt6mckzToeCOHDAfBgNVHSMEGDAWgBQi42wH6hM4\nL2sujEvLM0/u8lRXTzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIB\nhjANBgkqhkiG9w0BAQsFAAOCAgEAirEn/iTsAKyhd+pu2W3Z5NjCko4NPU0EYUbr\nAP7+POK2rzjIrJO3nFYQ/LLuC7KCXG+2qwan2SAOGmqWst13Y+WHp44Kae0kaChW\nvcYLXXSoGQGC8QuFSNUdaeg3RbMDYFT04dOkqufeWVccoHVxyTSg9eD8LZuHn5jw\n7QDLiEECBmIJHk5Eeo2TAZrx4Yx6ufSUX5HeVjlAzqwtAqdt99uCJ/EL8bgpWbe+\nXoSpvUv0SEC1I1dCAhCKAvRlIOA6VBcmzg5Am12KzkqTul12/VEFIgzqu0Zy2Jbc\nAUPrYVu/+tOGXQaijy7YgwH8P8n3s7ZeUa1VABJHcxrxYduDDJBLZi+MjheUDaZ1\njQRHYevI2tlqeSBqdPKG4zBY5lS0GiAlmuze5oENt0P3XboHoZPHiqcK3VECgTVh\n/BkJcuudETSJcZDmQ8YfoKfBzRQNg2sv/hwvUv73Ss51Sco8GEt2lD8uEdib1Q6z\nzDT5lXJowSzOD5ZA9OGDjnSRL+2riNtKWKEqvtEG3VBJoBzu9GoxbAc7wIZLxmli\niF5a/Zf5X+UXD3s4TMmy6C4QZJpAA2egsSQCnraWO2ULhh7iXMysSkF/nzVfZn43\niqpaB8++9a37hWq14ZmOv0TJIDz//b2+KC4VFXWQ5W5QC6whsjT+OlG4p5ZYG0jo\n616pxqo=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n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\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIEjzCCA3egAwIBAgIQe55B/ALCKJDZtdNT8kD6hTANBgkqhkiG9w0BAQsFADBM\nMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv\nYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMjAxMjYxMjAwMDBaFw0y\nNTAxMjYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu\nIG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIE9WIFRMUyBDQSAy\nMDIyIFEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmGmg1LW9b7Lf\n8zDD83yBDTEkt+FOxKJZqF4veWc5KZsQj9HfnUS2e5nj/E+JImlGPsQuoiosLuXD\nBVBNAMcUFa11buFMGMeEMwiTmCXoXRrXQmH0qjpOfKgYc5gHG3BsRGaRrf7VR4eg\nofNMG9wUBw4/g/TT7+bQJdA4NfE7Y4d5gEryZiBGB/swaX6Jp/8MF4TgUmOWmalK\ndZCKyb4sPGQFRTtElk67F7vU+wdGcrcOx1tDcIB0ncjLPMnaFicagl+daWGsKqTh\ncounQb6QJtYHa91KvCfKWocMxQ7OIbB5UARLPmC4CJ1/f8YFm35ebfzAeULYdGXu\njE9CLor0OwIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW\nBBSH5Zq7a7B/t95GfJWkDBpA8HHqdjAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj\nmove4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw\nMi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1\ncmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w\nK6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwIQYD\nVR0gBBowGDAIBgZngQwBAgIwDAYKKwYBBAGgMgoBAjANBgkqhkiG9w0BAQsFAAOC\nAQEAKRic9/f+nmhQU/wz04APZLjgG5OgsuUOyUEZjKVhNGDwxGTvKhyXGGAMW2B/\n3bRi+aElpXwoxu3pL6fkElbX3B0BeS5LoDtxkyiVEBMZ8m+sXbocwlPyxrPbX6mY\n0rVIvnuUeBH8X0L5IwfpNVvKnBIilTbcebfHyXkPezGwz7E1yhUULjJFm2bt0SdX\ny+4X/WeiiYIv+fTVgZZgl+/2MKIsu/qdBJc3f3TvJ8nz+Eax1zgZmww+RSQWeOj3\n15Iw6Z5FX+NwzY/Ab+9PosR5UosSeq+9HhtaxZttXG1nVh+avYPGYddWmiMT90J5\nZgKnO/Fx2hBgTxhOTMYaD312kg==\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\nA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\nZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\nMTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\nA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\nRgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\ngHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\nKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\nXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\nDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\nLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\nRUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\njjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\nmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\nMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----"; + }; + readonly RedisCloudFlexible: { + readonly ca: "-----BEGIN CERTIFICATE-----\nMIIDTzCCAjegAwIBAgIJAKSVpiDswLcwMA0GCSqGSIb3DQEBBQUAMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTAeFw0xMzEwMDExMjE0NTVaFw0yMzA5MjkxMjE0NTVaMD4xFjAUBgNV\nBAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1\ndGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZqkh/DczWP\nJnxnHLQ7QL0T4B4CDKWBKCcisriGbA6ZePWVNo4hfKQC6JrzfR+081NeD6VcWUiz\nrmd+jtPhIY4c+WVQYm5PKaN6DT1imYdxQw7aqO5j2KUCEh/cznpLxeSHoTxlR34E\nQwF28Wl3eg2vc5ct8LjU3eozWVk3gb7alx9mSA2SgmuX5lEQawl++rSjsBStemY2\nBDwOpAMXIrdEyP/cVn8mkvi/BDs5M5G+09j0gfhyCzRWMQ7Hn71u1eolRxwVxgi3\nTMn+/vTaFSqxKjgck6zuAYjBRPaHe7qLxHNr1So/Mc9nPy+3wHebFwbIcnUojwbp\n4nctkWbjb2cCAwEAAaNQME4wHQYDVR0OBBYEFP1whtcrydmW3ZJeuSoKZIKjze3w\nMB8GA1UdIwQYMBaAFP1whtcrydmW3ZJeuSoKZIKjze3wMAwGA1UdEwQFMAMBAf8w\nDQYJKoZIhvcNAQEFBQADggEBAG2erXhwRAa7+ZOBs0B6X57Hwyd1R4kfmXcs0rta\nlbPpvgULSiB+TCbf3EbhJnHGyvdCY1tvlffLjdA7HJ0PCOn+YYLBA0pTU/dyvrN6\nSu8NuS5yubnt9mb13nDGYo1rnt0YRfxN+8DM3fXIVr038A30UlPX2Ou1ExFJT0MZ\nuFKY6ZvLdI6/1cbgmguMlAhM+DhKyV6Sr5699LM3zqeI816pZmlREETYkGr91q7k\nBpXJu/dtHaGxg1ZGu6w/PCsYGUcECWENYD4VQPd8N32JjOfu6vEgoEAwfPP+3oGp\nZ4m3ewACcWOAenqflb+cQYC4PsF7qbXDmRaWrbKntOlZ3n0=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIGMTCCBBmgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMx\nCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJDQTESMBAGA1UECgwJUmVkaXNMYWJzMS0w\nKwYDVQQDDCRSZWRpc0xhYnMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN\nMTgwMjI1MTUzNzM3WhcNMjgwMjIzMTUzNzM3WjBfMQswCQYDVQQGEwJVUzELMAkG\nA1UECAwCQ0ExEjAQBgNVBAoMCVJlZGlzTGFiczEvMC0GA1UEAwwmUkNQIEludGVy\nbWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA\nA4ICDwAwggIKAoICAQDf9dqbxc8Bq7Ctq9rWcxrGNKKHivqLAFpPq02yLPx6fsOv\nTq7GsDChAYBBc4v7Y2Ap9RD5Vs3dIhEANcnolf27QwrG9RMnnvzk8pCvp1o6zSU4\nVuOE1W66/O1/7e2rVxyrnTcP7UgK43zNIXu7+tiAqWsO92uSnuMoGPGpeaUm1jym\nhjWKtkAwDFSqvHY+XL5qDVBEjeUe+WHkYUg40cAXjusAqgm2hZt29c2wnVrxW25W\nP0meNlzHGFdA2AC5z54iRiqj57dTfBTkHoBczQxcyw6hhzxZQ4e5I5zOKjXXEhZN\nr0tA3YC14CTabKRus/JmZieyZzRgEy2oti64tmLYTqSlAD78pRL40VNoaSYetXLw\nhhNsXCHgWaY6d5bLOc/aIQMAV5oLvZQKvuXAF1IDmhPA+bZbpWipp0zagf1P1H3s\nUzsMdn2KM0ejzgotbtNlj5TcrVwpmvE3ktvUAuA+hi3FkVx1US+2Gsp5x4YOzJ7u\nP1WPk6ShF0JgnJH2ILdj6kttTWwFzH17keSFICWDfH/+kM+k7Y1v3EXMQXE7y0T9\nMjvJskz6d/nv+sQhY04xt64xFMGTnZjlJMzfQNi7zWFLTZnDD0lPowq7l3YiPoTT\nt5Xky83lu0KZsZBo0WlWaDG00gLVdtRgVbcuSWxpi5BdLb1kRab66JptWjxwXQID\nAQABo4HrMIHoMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHBzOi8vcmwtY2Etc2VydmVy\nLnJlZGlzbGFicy5jb20vdjEvY3JsMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcw\nAYYqaHR0cHM6Ly9ybC1jYS1zZXJ2ZXIucmVkaXNsYWJzLmNvbS92MS9vY3NwMB0G\nA1UdDgQWBBQHar5OKvQUpP2qWt6mckzToeCOHDAfBgNVHSMEGDAWgBQi42wH6hM4\nL2sujEvLM0/u8lRXTzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIB\nhjANBgkqhkiG9w0BAQsFAAOCAgEAirEn/iTsAKyhd+pu2W3Z5NjCko4NPU0EYUbr\nAP7+POK2rzjIrJO3nFYQ/LLuC7KCXG+2qwan2SAOGmqWst13Y+WHp44Kae0kaChW\nvcYLXXSoGQGC8QuFSNUdaeg3RbMDYFT04dOkqufeWVccoHVxyTSg9eD8LZuHn5jw\n7QDLiEECBmIJHk5Eeo2TAZrx4Yx6ufSUX5HeVjlAzqwtAqdt99uCJ/EL8bgpWbe+\nXoSpvUv0SEC1I1dCAhCKAvRlIOA6VBcmzg5Am12KzkqTul12/VEFIgzqu0Zy2Jbc\nAUPrYVu/+tOGXQaijy7YgwH8P8n3s7ZeUa1VABJHcxrxYduDDJBLZi+MjheUDaZ1\njQRHYevI2tlqeSBqdPKG4zBY5lS0GiAlmuze5oENt0P3XboHoZPHiqcK3VECgTVh\n/BkJcuudETSJcZDmQ8YfoKfBzRQNg2sv/hwvUv73Ss51Sco8GEt2lD8uEdib1Q6z\nzDT5lXJowSzOD5ZA9OGDjnSRL+2riNtKWKEqvtEG3VBJoBzu9GoxbAc7wIZLxmli\niF5a/Zf5X+UXD3s4TMmy6C4QZJpAA2egsSQCnraWO2ULhh7iXMysSkF/nzVfZn43\niqpaB8++9a37hWq14ZmOv0TJIDz//b2+KC4VFXWQ5W5QC6whsjT+OlG4p5ZYG0jo\n616pxqo=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n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\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIEjzCCA3egAwIBAgIQe55B/ALCKJDZtdNT8kD6hTANBgkqhkiG9w0BAQsFADBM\nMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv\nYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMjAxMjYxMjAwMDBaFw0y\nNTAxMjYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu\nIG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIE9WIFRMUyBDQSAy\nMDIyIFEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmGmg1LW9b7Lf\n8zDD83yBDTEkt+FOxKJZqF4veWc5KZsQj9HfnUS2e5nj/E+JImlGPsQuoiosLuXD\nBVBNAMcUFa11buFMGMeEMwiTmCXoXRrXQmH0qjpOfKgYc5gHG3BsRGaRrf7VR4eg\nofNMG9wUBw4/g/TT7+bQJdA4NfE7Y4d5gEryZiBGB/swaX6Jp/8MF4TgUmOWmalK\ndZCKyb4sPGQFRTtElk67F7vU+wdGcrcOx1tDcIB0ncjLPMnaFicagl+daWGsKqTh\ncounQb6QJtYHa91KvCfKWocMxQ7OIbB5UARLPmC4CJ1/f8YFm35ebfzAeULYdGXu\njE9CLor0OwIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG\nCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW\nBBSH5Zq7a7B/t95GfJWkDBpA8HHqdjAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj\nmove4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw\nMi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1\ncmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w\nK6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwIQYD\nVR0gBBowGDAIBgZngQwBAgIwDAYKKwYBBAGgMgoBAjANBgkqhkiG9w0BAQsFAAOC\nAQEAKRic9/f+nmhQU/wz04APZLjgG5OgsuUOyUEZjKVhNGDwxGTvKhyXGGAMW2B/\n3bRi+aElpXwoxu3pL6fkElbX3B0BeS5LoDtxkyiVEBMZ8m+sXbocwlPyxrPbX6mY\n0rVIvnuUeBH8X0L5IwfpNVvKnBIilTbcebfHyXkPezGwz7E1yhUULjJFm2bt0SdX\ny+4X/WeiiYIv+fTVgZZgl+/2MKIsu/qdBJc3f3TvJ8nz+Eax1zgZmww+RSQWeOj3\n15Iw6Z5FX+NwzY/Ab+9PosR5UosSeq+9HhtaxZttXG1nVh+avYPGYddWmiMT90J5\nZgKnO/Fx2hBgTxhOTMYaD312kg==\n-----END CERTIFICATE-----\n\n-----BEGIN CERTIFICATE-----\nMIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G\nA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp\nZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4\nMTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG\nA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8\nRgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT\ngHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm\nKPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd\nQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ\nXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw\nDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o\nLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU\nRUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp\njjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK\n6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX\nmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs\nMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH\nWD9f\n-----END CERTIFICATE-----"; + }; +}; +export default TLSProfiles; diff --git a/backend/node_modules/ioredis/built/constants/TLSProfiles.js b/backend/node_modules/ioredis/built/constants/TLSProfiles.js new file mode 100644 index 0000000..f90760d --- /dev/null +++ b/backend/node_modules/ioredis/built/constants/TLSProfiles.js @@ -0,0 +1,149 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * TLS settings for Redis Cloud. Updated on 2022-08-19. + */ +const RedisCloudCA = `-----BEGIN CERTIFICATE----- +MIIDTzCCAjegAwIBAgIJAKSVpiDswLcwMA0GCSqGSIb3DQEBBQUAMD4xFjAUBgNV +BAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0xMzEwMDExMjE0NTVaFw0yMzA5MjkxMjE0NTVaMD4xFjAUBgNV +BAoMDUdhcmFudGlhIERhdGExJDAiBgNVBAMMG1NTTCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZqkh/DczWP +JnxnHLQ7QL0T4B4CDKWBKCcisriGbA6ZePWVNo4hfKQC6JrzfR+081NeD6VcWUiz +rmd+jtPhIY4c+WVQYm5PKaN6DT1imYdxQw7aqO5j2KUCEh/cznpLxeSHoTxlR34E +QwF28Wl3eg2vc5ct8LjU3eozWVk3gb7alx9mSA2SgmuX5lEQawl++rSjsBStemY2 +BDwOpAMXIrdEyP/cVn8mkvi/BDs5M5G+09j0gfhyCzRWMQ7Hn71u1eolRxwVxgi3 +TMn+/vTaFSqxKjgck6zuAYjBRPaHe7qLxHNr1So/Mc9nPy+3wHebFwbIcnUojwbp +4nctkWbjb2cCAwEAAaNQME4wHQYDVR0OBBYEFP1whtcrydmW3ZJeuSoKZIKjze3w +MB8GA1UdIwQYMBaAFP1whtcrydmW3ZJeuSoKZIKjze3wMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAG2erXhwRAa7+ZOBs0B6X57Hwyd1R4kfmXcs0rta +lbPpvgULSiB+TCbf3EbhJnHGyvdCY1tvlffLjdA7HJ0PCOn+YYLBA0pTU/dyvrN6 +Su8NuS5yubnt9mb13nDGYo1rnt0YRfxN+8DM3fXIVr038A30UlPX2Ou1ExFJT0MZ +uFKY6ZvLdI6/1cbgmguMlAhM+DhKyV6Sr5699LM3zqeI816pZmlREETYkGr91q7k +BpXJu/dtHaGxg1ZGu6w/PCsYGUcECWENYD4VQPd8N32JjOfu6vEgoEAwfPP+3oGp +Z4m3ewACcWOAenqflb+cQYC4PsF7qbXDmRaWrbKntOlZ3n0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGMTCCBBmgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwajELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAkNBMQswCQYDVQQHDAJDQTESMBAGA1UECgwJUmVkaXNMYWJzMS0w +KwYDVQQDDCRSZWRpc0xhYnMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MTgwMjI1MTUzNzM3WhcNMjgwMjIzMTUzNzM3WjBfMQswCQYDVQQGEwJVUzELMAkG +A1UECAwCQ0ExEjAQBgNVBAoMCVJlZGlzTGFiczEvMC0GA1UEAwwmUkNQIEludGVy +bWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDf9dqbxc8Bq7Ctq9rWcxrGNKKHivqLAFpPq02yLPx6fsOv +Tq7GsDChAYBBc4v7Y2Ap9RD5Vs3dIhEANcnolf27QwrG9RMnnvzk8pCvp1o6zSU4 +VuOE1W66/O1/7e2rVxyrnTcP7UgK43zNIXu7+tiAqWsO92uSnuMoGPGpeaUm1jym +hjWKtkAwDFSqvHY+XL5qDVBEjeUe+WHkYUg40cAXjusAqgm2hZt29c2wnVrxW25W +P0meNlzHGFdA2AC5z54iRiqj57dTfBTkHoBczQxcyw6hhzxZQ4e5I5zOKjXXEhZN +r0tA3YC14CTabKRus/JmZieyZzRgEy2oti64tmLYTqSlAD78pRL40VNoaSYetXLw +hhNsXCHgWaY6d5bLOc/aIQMAV5oLvZQKvuXAF1IDmhPA+bZbpWipp0zagf1P1H3s +UzsMdn2KM0ejzgotbtNlj5TcrVwpmvE3ktvUAuA+hi3FkVx1US+2Gsp5x4YOzJ7u +P1WPk6ShF0JgnJH2ILdj6kttTWwFzH17keSFICWDfH/+kM+k7Y1v3EXMQXE7y0T9 +MjvJskz6d/nv+sQhY04xt64xFMGTnZjlJMzfQNi7zWFLTZnDD0lPowq7l3YiPoTT +t5Xky83lu0KZsZBo0WlWaDG00gLVdtRgVbcuSWxpi5BdLb1kRab66JptWjxwXQID +AQABo4HrMIHoMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHBzOi8vcmwtY2Etc2VydmVy +LnJlZGlzbGFicy5jb20vdjEvY3JsMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcw +AYYqaHR0cHM6Ly9ybC1jYS1zZXJ2ZXIucmVkaXNsYWJzLmNvbS92MS9vY3NwMB0G +A1UdDgQWBBQHar5OKvQUpP2qWt6mckzToeCOHDAfBgNVHSMEGDAWgBQi42wH6hM4 +L2sujEvLM0/u8lRXTzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIB +hjANBgkqhkiG9w0BAQsFAAOCAgEAirEn/iTsAKyhd+pu2W3Z5NjCko4NPU0EYUbr +AP7+POK2rzjIrJO3nFYQ/LLuC7KCXG+2qwan2SAOGmqWst13Y+WHp44Kae0kaChW +vcYLXXSoGQGC8QuFSNUdaeg3RbMDYFT04dOkqufeWVccoHVxyTSg9eD8LZuHn5jw +7QDLiEECBmIJHk5Eeo2TAZrx4Yx6ufSUX5HeVjlAzqwtAqdt99uCJ/EL8bgpWbe+ +XoSpvUv0SEC1I1dCAhCKAvRlIOA6VBcmzg5Am12KzkqTul12/VEFIgzqu0Zy2Jbc +AUPrYVu/+tOGXQaijy7YgwH8P8n3s7ZeUa1VABJHcxrxYduDDJBLZi+MjheUDaZ1 +jQRHYevI2tlqeSBqdPKG4zBY5lS0GiAlmuze5oENt0P3XboHoZPHiqcK3VECgTVh +/BkJcuudETSJcZDmQ8YfoKfBzRQNg2sv/hwvUv73Ss51Sco8GEt2lD8uEdib1Q6z +zDT5lXJowSzOD5ZA9OGDjnSRL+2riNtKWKEqvtEG3VBJoBzu9GoxbAc7wIZLxmli +iF5a/Zf5X+UXD3s4TMmy6C4QZJpAA2egsSQCnraWO2ULhh7iXMysSkF/nzVfZn43 +iqpaB8++9a37hWq14ZmOv0TJIDz//b2+KC4VFXWQ5W5QC6whsjT+OlG4p5ZYG0jo +616pxqo= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIEjzCCA3egAwIBAgIQe55B/ALCKJDZtdNT8kD6hTANBgkqhkiG9w0BAQsFADBM +MSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv +YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMjAxMjYxMjAwMDBaFw0y +NTAxMjYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu +IG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIE9WIFRMUyBDQSAy +MDIyIFEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmGmg1LW9b7Lf +8zDD83yBDTEkt+FOxKJZqF4veWc5KZsQj9HfnUS2e5nj/E+JImlGPsQuoiosLuXD +BVBNAMcUFa11buFMGMeEMwiTmCXoXRrXQmH0qjpOfKgYc5gHG3BsRGaRrf7VR4eg +ofNMG9wUBw4/g/TT7+bQJdA4NfE7Y4d5gEryZiBGB/swaX6Jp/8MF4TgUmOWmalK +dZCKyb4sPGQFRTtElk67F7vU+wdGcrcOx1tDcIB0ncjLPMnaFicagl+daWGsKqTh +counQb6QJtYHa91KvCfKWocMxQ7OIbB5UARLPmC4CJ1/f8YFm35ebfzAeULYdGXu +jE9CLor0OwIDAQABo4IBXzCCAVswDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW +BBSH5Zq7a7B/t95GfJWkDBpA8HHqdjAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj +move4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw +Mi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1 +cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w +K6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwIQYD +VR0gBBowGDAIBgZngQwBAgIwDAYKKwYBBAGgMgoBAjANBgkqhkiG9w0BAQsFAAOC +AQEAKRic9/f+nmhQU/wz04APZLjgG5OgsuUOyUEZjKVhNGDwxGTvKhyXGGAMW2B/ +3bRi+aElpXwoxu3pL6fkElbX3B0BeS5LoDtxkyiVEBMZ8m+sXbocwlPyxrPbX6mY +0rVIvnuUeBH8X0L5IwfpNVvKnBIilTbcebfHyXkPezGwz7E1yhUULjJFm2bt0SdX +y+4X/WeiiYIv+fTVgZZgl+/2MKIsu/qdBJc3f3TvJ8nz+Eax1zgZmww+RSQWeOj3 +15Iw6Z5FX+NwzY/Ab+9PosR5UosSeq+9HhtaxZttXG1nVh+avYPGYddWmiMT90J5 +ZgKnO/Fx2hBgTxhOTMYaD312kg== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE-----`; +const TLSProfiles = { + RedisCloudFixed: { ca: RedisCloudCA }, + RedisCloudFlexible: { ca: RedisCloudCA }, +}; +exports.default = TLSProfiles; diff --git a/backend/node_modules/ioredis/built/errors/ClusterAllFailedError.d.ts b/backend/node_modules/ioredis/built/errors/ClusterAllFailedError.d.ts new file mode 100644 index 0000000..870640f --- /dev/null +++ b/backend/node_modules/ioredis/built/errors/ClusterAllFailedError.d.ts @@ -0,0 +1,7 @@ +import { RedisError } from "redis-errors"; +export default class ClusterAllFailedError extends RedisError { + lastNodeError: RedisError; + static defaultMessage: string; + constructor(message: any, lastNodeError: RedisError); + get name(): string; +} diff --git a/backend/node_modules/ioredis/built/errors/ClusterAllFailedError.js b/backend/node_modules/ioredis/built/errors/ClusterAllFailedError.js new file mode 100644 index 0000000..c223f16 --- /dev/null +++ b/backend/node_modules/ioredis/built/errors/ClusterAllFailedError.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const redis_errors_1 = require("redis-errors"); +class ClusterAllFailedError extends redis_errors_1.RedisError { + constructor(message, lastNodeError) { + super(message); + this.lastNodeError = lastNodeError; + Error.captureStackTrace(this, this.constructor); + } + get name() { + return this.constructor.name; + } +} +exports.default = ClusterAllFailedError; +ClusterAllFailedError.defaultMessage = "Failed to refresh slots cache."; diff --git a/backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.d.ts b/backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.d.ts new file mode 100644 index 0000000..9c4b4e5 --- /dev/null +++ b/backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.d.ts @@ -0,0 +1,5 @@ +import { AbortError } from "redis-errors"; +export default class MaxRetriesPerRequestError extends AbortError { + constructor(maxRetriesPerRequest: number); + get name(): string; +} diff --git a/backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.js b/backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.js new file mode 100644 index 0000000..d8c8e1d --- /dev/null +++ b/backend/node_modules/ioredis/built/errors/MaxRetriesPerRequestError.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const redis_errors_1 = require("redis-errors"); +class MaxRetriesPerRequestError extends redis_errors_1.AbortError { + constructor(maxRetriesPerRequest) { + const message = `Reached the max retries per request limit (which is ${maxRetriesPerRequest}). Refer to "maxRetriesPerRequest" option for details.`; + super(message); + Error.captureStackTrace(this, this.constructor); + } + get name() { + return this.constructor.name; + } +} +exports.default = MaxRetriesPerRequestError; diff --git a/backend/node_modules/ioredis/built/errors/index.d.ts b/backend/node_modules/ioredis/built/errors/index.d.ts new file mode 100644 index 0000000..6d25308 --- /dev/null +++ b/backend/node_modules/ioredis/built/errors/index.d.ts @@ -0,0 +1,2 @@ +import MaxRetriesPerRequestError from "./MaxRetriesPerRequestError"; +export { MaxRetriesPerRequestError }; diff --git a/backend/node_modules/ioredis/built/errors/index.js b/backend/node_modules/ioredis/built/errors/index.js new file mode 100644 index 0000000..02b72a9 --- /dev/null +++ b/backend/node_modules/ioredis/built/errors/index.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MaxRetriesPerRequestError = void 0; +const MaxRetriesPerRequestError_1 = require("./MaxRetriesPerRequestError"); +exports.MaxRetriesPerRequestError = MaxRetriesPerRequestError_1.default; diff --git a/backend/node_modules/ioredis/built/index.d.ts b/backend/node_modules/ioredis/built/index.d.ts new file mode 100644 index 0000000..d98fa59 --- /dev/null +++ b/backend/node_modules/ioredis/built/index.d.ts @@ -0,0 +1,43 @@ +export { default } from "./Redis"; +export { default as Redis } from "./Redis"; +export { default as Cluster } from "./cluster"; +/** + * @ignore + */ +export { default as Command } from "./Command"; +/** + * @ignore + */ +export { default as RedisCommander, Result, ClientContext, } from "./utils/RedisCommander"; +/** + * @ignore + */ +export { default as ScanStream } from "./ScanStream"; +/** + * @ignore + */ +export { default as Pipeline } from "./Pipeline"; +/** + * @ignore + */ +export { default as AbstractConnector } from "./connectors/AbstractConnector"; +/** + * @ignore + */ +export { default as SentinelConnector, SentinelIterator, } from "./connectors/SentinelConnector"; +/** + * @ignore + */ +export { Callback } from "./types"; +export { SentinelAddress, SentinelConnectionOptions, } from "./connectors/SentinelConnector"; +export { StandaloneConnectionOptions } from "./connectors/StandaloneConnector"; +export { RedisOptions, CommonRedisOptions } from "./redis/RedisOptions"; +export { ClusterNode } from "./cluster"; +export { ClusterOptions, DNSLookupFunction, DNSResolveSrvFunction, NatMap, } from "./cluster/ClusterOptions"; +export { NodeRole } from "./cluster/util"; +export type { RedisKey, RedisValue, ChainableCommander, } from "./utils/RedisCommander"; +export declare const ReplyError: any; +/** + * @ignore + */ +export declare function print(err: Error | null, reply?: any): void; diff --git a/backend/node_modules/ioredis/built/index.js b/backend/node_modules/ioredis/built/index.js new file mode 100644 index 0000000..24a1895 --- /dev/null +++ b/backend/node_modules/ioredis/built/index.js @@ -0,0 +1,62 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.print = exports.ReplyError = exports.SentinelIterator = exports.SentinelConnector = exports.AbstractConnector = exports.Pipeline = exports.ScanStream = exports.Command = exports.Cluster = exports.Redis = exports.default = void 0; +exports = module.exports = require("./Redis").default; +var Redis_1 = require("./Redis"); +Object.defineProperty(exports, "default", { enumerable: true, get: function () { return Redis_1.default; } }); +var Redis_2 = require("./Redis"); +Object.defineProperty(exports, "Redis", { enumerable: true, get: function () { return Redis_2.default; } }); +var cluster_1 = require("./cluster"); +Object.defineProperty(exports, "Cluster", { enumerable: true, get: function () { return cluster_1.default; } }); +/** + * @ignore + */ +var Command_1 = require("./Command"); +Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return Command_1.default; } }); +/** + * @ignore + */ +var ScanStream_1 = require("./ScanStream"); +Object.defineProperty(exports, "ScanStream", { enumerable: true, get: function () { return ScanStream_1.default; } }); +/** + * @ignore + */ +var Pipeline_1 = require("./Pipeline"); +Object.defineProperty(exports, "Pipeline", { enumerable: true, get: function () { return Pipeline_1.default; } }); +/** + * @ignore + */ +var AbstractConnector_1 = require("./connectors/AbstractConnector"); +Object.defineProperty(exports, "AbstractConnector", { enumerable: true, get: function () { return AbstractConnector_1.default; } }); +/** + * @ignore + */ +var SentinelConnector_1 = require("./connectors/SentinelConnector"); +Object.defineProperty(exports, "SentinelConnector", { enumerable: true, get: function () { return SentinelConnector_1.default; } }); +Object.defineProperty(exports, "SentinelIterator", { enumerable: true, get: function () { return SentinelConnector_1.SentinelIterator; } }); +// No TS typings +exports.ReplyError = require("redis-errors").ReplyError; +/** + * @ignore + */ +Object.defineProperty(exports, "Promise", { + get() { + console.warn("ioredis v5 does not support plugging third-party Promise library anymore. Native Promise will be used."); + return Promise; + }, + set(_lib) { + console.warn("ioredis v5 does not support plugging third-party Promise library anymore. Native Promise will be used."); + }, +}); +/** + * @ignore + */ +function print(err, reply) { + if (err) { + console.log("Error: " + err); + } + else { + console.log("Reply: " + reply); + } +} +exports.print = print; diff --git a/backend/node_modules/ioredis/built/redis/RedisOptions.d.ts b/backend/node_modules/ioredis/built/redis/RedisOptions.d.ts new file mode 100644 index 0000000..6242728 --- /dev/null +++ b/backend/node_modules/ioredis/built/redis/RedisOptions.d.ts @@ -0,0 +1,197 @@ +import { CommanderOptions } from "../utils/Commander"; +import ConnectorConstructor from "../connectors/ConnectorConstructor"; +import { SentinelConnectionOptions } from "../connectors/SentinelConnector"; +import { StandaloneConnectionOptions } from "../connectors/StandaloneConnector"; +export declare type ReconnectOnError = (err: Error) => boolean | 1 | 2; +export interface CommonRedisOptions extends CommanderOptions { + Connector?: ConnectorConstructor | undefined; + retryStrategy?: ((times: number) => number | void | null) | undefined; + /** + * If a command does not return a reply within a set number of milliseconds, + * a "Command timed out" error will be thrown. + */ + commandTimeout?: number | undefined; + /** + * Enables client-side timeout protection for blocking commands when set + * to a positive number. If `blockingTimeout` is undefined, `0`, or + * negative (e.g. `-1`), the protection is disabled and no client-side + * timers are installed for blocking commands. + */ + blockingTimeout?: number | undefined; + /** + * Grace period (ms) added to blocking command timeouts. Only used when + * `blockingTimeout` is a positive number. Defaults to 100ms. + */ + blockingTimeoutGrace?: number | undefined; + /** + * If the socket does not receive data within a set number of milliseconds: + * 1. the socket is considered "dead" and will be destroyed + * 2. the client will reject any running commands (altought they might have been processed by the server) + * 3. the reconnect strategy will kick in (depending on the configuration) + */ + socketTimeout?: number | undefined; + /** + * Enable/disable keep-alive functionality. + * @link https://nodejs.org/api/net.html#socketsetkeepaliveenable-initialdelay + * @default 0 + */ + keepAlive?: number | undefined; + /** + * Enable/disable the use of Nagle's algorithm. + * @link https://nodejs.org/api/net.html#socketsetnodelaynodelay + * @default true + */ + noDelay?: boolean | undefined; + /** + * Set the name of the connection to make it easier to identity the connection + * in client list. + * @link https://redis.io/commands/client-setname + */ + connectionName?: string | undefined; + /** + * If true, skips setting library info via CLIENT SETINFO. + * @link https://redis.io/docs/latest/commands/client-setinfo/ + * @default false + */ + disableClientInfo?: boolean | undefined; + /** + * Tag to append to the library name in CLIENT SETINFO (ioredis(tag)). + * @link https://redis.io/docs/latest/commands/client-setinfo/ + * @default undefined + */ + clientInfoTag?: string | undefined; + /** + * If set, client will send AUTH command with the value of this option as the first argument when connected. + * This is supported since Redis 6. + */ + username?: string | undefined; + /** + * If set, client will send AUTH command with the value of this option when connected. + */ + password?: string | undefined; + /** + * Database index to use. + * + * @default 0 + */ + db?: number | undefined; + /** + * When the client reconnects, channels subscribed in the previous connection will be + * resubscribed automatically if `autoResubscribe` is `true`. + * @default true + */ + autoResubscribe?: boolean | undefined; + /** + * Whether or not to resend unfulfilled commands on reconnect. + * Unfulfilled commands are most likely to be blocking commands such as `brpop` or `blpop`. + * @default true + */ + autoResendUnfulfilledCommands?: boolean | undefined; + /** + * Whether or not to reconnect on certain Redis errors. + * This options by default is `null`, which means it should never reconnect on Redis errors. + * You can pass a function that accepts an Redis error, and returns: + * - `true` or `1` to trigger a reconnection. + * - `false` or `0` to not reconnect. + * - `2` to reconnect and resend the failed command (who triggered the error) after reconnection. + * @example + * ```js + * const redis = new Redis({ + * reconnectOnError(err) { + * const targetError = "READONLY"; + * if (err.message.includes(targetError)) { + * // Only reconnect when the error contains "READONLY" + * return true; // or `return 1;` + * } + * }, + * }); + * ``` + * @default null + */ + reconnectOnError?: ReconnectOnError | null | undefined; + /** + * @default false + */ + readOnly?: boolean | undefined; + /** + * When enabled, numbers returned by Redis will be converted to JavaScript strings instead of numbers. + * This is necessary if you want to handle big numbers (above `Number.MAX_SAFE_INTEGER` === 2^53). + * @default false + */ + stringNumbers?: boolean | undefined; + /** + * How long the client will wait before killing a socket due to inactivity during initial connection. + * @default 10000 + */ + connectTimeout?: number | undefined; + /** + * This option is used internally when you call `redis.monitor()` to tell Redis + * to enter the monitor mode when the connection is established. + * + * @default false + */ + monitor?: boolean | undefined; + /** + * The commands that don't get a reply due to the connection to the server is lost are + * put into a queue and will be resent on reconnect (if allowed by the `retryStrategy` option). + * This option is used to configure how many reconnection attempts should be allowed before + * the queue is flushed with a `MaxRetriesPerRequestError` error. + * Set this options to `null` instead of a number to let commands wait forever + * until the connection is alive again. + * + * @default 20 + */ + maxRetriesPerRequest?: number | null | undefined; + /** + * @default 10000 + */ + maxLoadingRetryTime?: number | undefined; + /** + * @default false + */ + enableAutoPipelining?: boolean | undefined; + /** + * @default [] + */ + autoPipeliningIgnoredCommands?: string[] | undefined; + offlineQueue?: boolean | undefined; + commandQueue?: boolean | undefined; + /** + * + * By default, if the connection to Redis server has not been established, commands are added to a queue + * and are executed once the connection is "ready" (when `enableReadyCheck` is true, "ready" means + * the Redis server has loaded the database from disk, otherwise means the connection to the Redis + * server has been established). If this option is false, when execute the command when the connection + * isn't ready, an error will be returned. + * + * @default true + */ + enableOfflineQueue?: boolean | undefined; + /** + * The client will sent an INFO command to check whether the server is still loading data from the disk ( + * which happens when the server is just launched) when the connection is established, and only wait until + * the loading process is finished before emitting the `ready` event. + * + * @default true + */ + enableReadyCheck?: boolean | undefined; + /** + * When a Redis instance is initialized, a connection to the server is immediately established. Set this to + * true will delay the connection to the server until the first command is sent or `redis.connect()` is called + * explicitly. When `redis.connect()` is called explicitly, a Promise is returned, which will be resolved + * when the connection is ready or rejected when it fails. The rejection should be handled by the user. + * + * @default false + */ + lazyConnect?: boolean | undefined; + /** + * @default undefined + */ + scripts?: Record | undefined; +} +export declare type RedisOptions = CommonRedisOptions & SentinelConnectionOptions & StandaloneConnectionOptions; +export declare const DEFAULT_REDIS_OPTIONS: RedisOptions; diff --git a/backend/node_modules/ioredis/built/redis/RedisOptions.js b/backend/node_modules/ioredis/built/redis/RedisOptions.js new file mode 100644 index 0000000..99ee7dc --- /dev/null +++ b/backend/node_modules/ioredis/built/redis/RedisOptions.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_REDIS_OPTIONS = void 0; +exports.DEFAULT_REDIS_OPTIONS = { + // Connection + port: 6379, + host: "localhost", + family: 0, + connectTimeout: 10000, + disconnectTimeout: 2000, + retryStrategy: function (times) { + return Math.min(times * 50, 2000); + }, + keepAlive: 0, + noDelay: true, + connectionName: null, + disableClientInfo: false, + clientInfoTag: undefined, + // Sentinel + sentinels: null, + name: null, + role: "master", + sentinelRetryStrategy: function (times) { + return Math.min(times * 10, 1000); + }, + sentinelReconnectStrategy: function () { + // This strategy only applies when sentinels are used for detecting + // a failover, not during initial master resolution. + // The deployment can still function when some of the sentinels are down + // for a long period of time, so we may not want to attempt reconnection + // very often. Therefore the default interval is fairly long (1 minute). + return 60000; + }, + natMap: null, + enableTLSForSentinelMode: false, + updateSentinels: true, + failoverDetector: false, + // Status + username: null, + password: null, + db: 0, + // Others + enableOfflineQueue: true, + enableReadyCheck: true, + autoResubscribe: true, + autoResendUnfulfilledCommands: true, + lazyConnect: false, + keyPrefix: "", + reconnectOnError: null, + readOnly: false, + stringNumbers: false, + maxRetriesPerRequest: 20, + maxLoadingRetryTime: 10000, + enableAutoPipelining: false, + autoPipeliningIgnoredCommands: [], + sentinelMaxConnections: 10, + blockingTimeoutGrace: 100, +}; diff --git a/backend/node_modules/ioredis/built/redis/event_handler.d.ts b/backend/node_modules/ioredis/built/redis/event_handler.d.ts new file mode 100644 index 0000000..1ce79dd --- /dev/null +++ b/backend/node_modules/ioredis/built/redis/event_handler.d.ts @@ -0,0 +1,4 @@ +export declare function connectHandler(self: any): () => void; +export declare function closeHandler(self: any): () => void; +export declare function errorHandler(self: any): (error: any) => void; +export declare function readyHandler(self: any): () => void; diff --git a/backend/node_modules/ioredis/built/redis/event_handler.js b/backend/node_modules/ioredis/built/redis/event_handler.js new file mode 100644 index 0000000..ba8b1dc --- /dev/null +++ b/backend/node_modules/ioredis/built/redis/event_handler.js @@ -0,0 +1,315 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.readyHandler = exports.errorHandler = exports.closeHandler = exports.connectHandler = void 0; +const redis_errors_1 = require("redis-errors"); +const Command_1 = require("../Command"); +const errors_1 = require("../errors"); +const utils_1 = require("../utils"); +const DataHandler_1 = require("../DataHandler"); +const debug = (0, utils_1.Debug)("connection"); +function connectHandler(self) { + return function () { + var _a; + self.setStatus("connect"); + self.resetCommandQueue(); + // AUTH command should be processed before any other commands + let flushed = false; + const { connectionEpoch } = self; + if (self.condition.auth) { + self.auth(self.condition.auth, function (err) { + if (connectionEpoch !== self.connectionEpoch) { + return; + } + if (err) { + if (err.message.indexOf("no password is set") !== -1) { + console.warn("[WARN] Redis server does not require a password, but a password was supplied."); + } + else if (err.message.indexOf("without any password configured for the default user") !== -1) { + console.warn("[WARN] This Redis server's `default` user does not require a password, but a password was supplied"); + } + else if (err.message.indexOf("wrong number of arguments for 'auth' command") !== -1) { + console.warn(`[ERROR] The server returned "wrong number of arguments for 'auth' command". You are probably passing both username and password to Redis version 5 or below. You should only pass the 'password' option for Redis version 5 and under.`); + } + else { + flushed = true; + self.recoverFromFatalError(err, err); + } + } + }); + } + if (self.condition.select) { + self.select(self.condition.select).catch((err) => { + // If the node is in cluster mode, select is disallowed. + // In this case, reconnect won't help. + self.silentEmit("error", err); + }); + } + /* + No need to keep the reference of DataHandler here + because we don't need to do the cleanup. + `Stream#end()` will remove all listeners for us. + */ + new DataHandler_1.default(self, { + stringNumbers: self.options.stringNumbers, + }); + const clientCommandPromises = []; + if (self.options.connectionName) { + debug("set the connection name [%s]", self.options.connectionName); + clientCommandPromises.push(self.client("setname", self.options.connectionName).catch(utils_1.noop)); + } + if (!self.options.disableClientInfo) { + debug("set the client info"); + clientCommandPromises.push((0, utils_1.getPackageMeta)() + .then((packageMeta) => { + return self + .client("SETINFO", "LIB-VER", packageMeta.version) + .catch(utils_1.noop); + }) + .catch(utils_1.noop)); + clientCommandPromises.push(self + .client("SETINFO", "LIB-NAME", ((_a = self.options) === null || _a === void 0 ? void 0 : _a.clientInfoTag) + ? `ioredis(${self.options.clientInfoTag})` + : "ioredis") + .catch(utils_1.noop)); + } + Promise.all(clientCommandPromises) + .catch(utils_1.noop) + .finally(() => { + if (!self.options.enableReadyCheck) { + exports.readyHandler(self)(); + } + if (self.options.enableReadyCheck) { + self._readyCheck(function (err, info) { + if (connectionEpoch !== self.connectionEpoch) { + return; + } + if (err) { + if (!flushed) { + self.recoverFromFatalError(new Error("Ready check failed: " + err.message), err); + } + } + else { + if (self.connector.check(info)) { + exports.readyHandler(self)(); + } + else { + self.disconnect(true); + } + } + }); + } + }); + }; +} +exports.connectHandler = connectHandler; +function abortError(command) { + const err = new redis_errors_1.AbortError("Command aborted due to connection close"); + err.command = { + name: command.name, + args: command.args, + }; + return err; +} +// If a contiguous set of pipeline commands starts from index zero then they +// can be safely reattempted. If however we have a chain of pipelined commands +// starting at index 1 or more it means we received a partial response before +// the connection close and those pipelined commands must be aborted. For +// example, if the queue looks like this: [2, 3, 4, 0, 1, 2] then after +// aborting and purging we'll have a queue that looks like this: [0, 1, 2] +function abortIncompletePipelines(commandQueue) { + var _a; + let expectedIndex = 0; + for (let i = 0; i < commandQueue.length;) { + const command = (_a = commandQueue.peekAt(i)) === null || _a === void 0 ? void 0 : _a.command; + const pipelineIndex = command.pipelineIndex; + if (pipelineIndex === undefined || pipelineIndex === 0) { + expectedIndex = 0; + } + if (pipelineIndex !== undefined && pipelineIndex !== expectedIndex++) { + commandQueue.remove(i, 1); + command.reject(abortError(command)); + continue; + } + i++; + } +} +// If only a partial transaction result was received before connection close, +// we have to abort any transaction fragments that may have ended up in the +// offline queue +function abortTransactionFragments(commandQueue) { + var _a; + for (let i = 0; i < commandQueue.length;) { + const command = (_a = commandQueue.peekAt(i)) === null || _a === void 0 ? void 0 : _a.command; + if (command.name === "multi") { + break; + } + if (command.name === "exec") { + commandQueue.remove(i, 1); + command.reject(abortError(command)); + break; + } + if (command.inTransaction) { + commandQueue.remove(i, 1); + command.reject(abortError(command)); + } + else { + i++; + } + } +} +function closeHandler(self) { + return function () { + const prevStatus = self.status; + self.setStatus("close"); + if (self.commandQueue.length) { + abortIncompletePipelines(self.commandQueue); + } + if (self.offlineQueue.length) { + abortTransactionFragments(self.offlineQueue); + } + if (prevStatus === "ready") { + if (!self.prevCondition) { + self.prevCondition = self.condition; + } + if (self.commandQueue.length) { + self.prevCommandQueue = self.commandQueue; + } + } + if (self.manuallyClosing) { + self.manuallyClosing = false; + debug("skip reconnecting since the connection is manually closed."); + return close(); + } + if (typeof self.options.retryStrategy !== "function") { + debug("skip reconnecting because `retryStrategy` is not a function"); + return close(); + } + const retryDelay = self.options.retryStrategy(++self.retryAttempts); + if (typeof retryDelay !== "number") { + debug("skip reconnecting because `retryStrategy` doesn't return a number"); + return close(); + } + debug("reconnect in %sms", retryDelay); + self.setStatus("reconnecting", retryDelay); + self.reconnectTimeout = setTimeout(function () { + self.reconnectTimeout = null; + self.connect().catch(utils_1.noop); + }, retryDelay); + const { maxRetriesPerRequest } = self.options; + if (typeof maxRetriesPerRequest === "number") { + if (maxRetriesPerRequest < 0) { + debug("maxRetriesPerRequest is negative, ignoring..."); + } + else { + const remainder = self.retryAttempts % (maxRetriesPerRequest + 1); + if (remainder === 0) { + debug("reach maxRetriesPerRequest limitation, flushing command queue..."); + self.flushQueue(new errors_1.MaxRetriesPerRequestError(maxRetriesPerRequest)); + } + } + } + }; + function close() { + self.setStatus("end"); + self.flushQueue(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG)); + } +} +exports.closeHandler = closeHandler; +function errorHandler(self) { + return function (error) { + debug("error: %s", error); + self.silentEmit("error", error); + }; +} +exports.errorHandler = errorHandler; +function readyHandler(self) { + return function () { + self.setStatus("ready"); + self.retryAttempts = 0; + if (self.options.monitor) { + self.call("monitor").then(() => self.setStatus("monitoring"), (error) => self.emit("error", error)); + const { sendCommand } = self; + self.sendCommand = function (command) { + if (Command_1.default.checkFlag("VALID_IN_MONITOR_MODE", command.name)) { + return sendCommand.call(self, command); + } + command.reject(new Error("Connection is in monitoring mode, can't process commands.")); + return command.promise; + }; + self.once("close", function () { + delete self.sendCommand; + }); + return; + } + const finalSelect = self.prevCondition + ? self.prevCondition.select + : self.condition.select; + if (self.options.readOnly) { + debug("set the connection to readonly mode"); + self.readonly().catch(utils_1.noop); + } + if (self.prevCondition) { + const condition = self.prevCondition; + self.prevCondition = null; + if (condition.subscriber && self.options.autoResubscribe) { + // We re-select the previous db first since + // `SELECT` command is not valid in sub mode. + if (self.condition.select !== finalSelect) { + debug("connect to db [%d]", finalSelect); + self.select(finalSelect); + } + const subscribeChannels = condition.subscriber.channels("subscribe"); + if (subscribeChannels.length) { + debug("subscribe %d channels", subscribeChannels.length); + self.subscribe(subscribeChannels); + } + const psubscribeChannels = condition.subscriber.channels("psubscribe"); + if (psubscribeChannels.length) { + debug("psubscribe %d channels", psubscribeChannels.length); + self.psubscribe(psubscribeChannels); + } + const ssubscribeChannels = condition.subscriber.channels("ssubscribe"); + if (ssubscribeChannels.length) { + debug("ssubscribe %s", ssubscribeChannels.length); + for (const channel of ssubscribeChannels) { + self.ssubscribe(channel); + } + } + } + } + if (self.prevCommandQueue) { + if (self.options.autoResendUnfulfilledCommands) { + debug("resend %d unfulfilled commands", self.prevCommandQueue.length); + while (self.prevCommandQueue.length > 0) { + const item = self.prevCommandQueue.shift(); + if (item.select !== self.condition.select && + item.command.name !== "select") { + self.select(item.select); + } + self.sendCommand(item.command, item.stream); + } + } + else { + self.prevCommandQueue = null; + } + } + if (self.offlineQueue.length) { + debug("send %d commands in offline queue", self.offlineQueue.length); + const offlineQueue = self.offlineQueue; + self.resetOfflineQueue(); + while (offlineQueue.length > 0) { + const item = offlineQueue.shift(); + if (item.select !== self.condition.select && + item.command.name !== "select") { + self.select(item.select); + } + self.sendCommand(item.command, item.stream); + } + } + if (self.condition.select !== finalSelect) { + debug("connect to db [%d]", finalSelect); + self.select(finalSelect); + } + }; +} +exports.readyHandler = readyHandler; diff --git a/backend/node_modules/ioredis/built/transaction.d.ts b/backend/node_modules/ioredis/built/transaction.d.ts new file mode 100644 index 0000000..d499f25 --- /dev/null +++ b/backend/node_modules/ioredis/built/transaction.d.ts @@ -0,0 +1,13 @@ +import { ChainableCommander } from "./utils/RedisCommander"; +export interface Transaction { + pipeline(commands?: unknown[][]): ChainableCommander; + multi(options: { + pipeline: false; + }): Promise<"OK">; + multi(): ChainableCommander; + multi(options: { + pipeline: true; + }): ChainableCommander; + multi(commands?: unknown[][]): ChainableCommander; +} +export declare function addTransactionSupport(redis: any): void; diff --git a/backend/node_modules/ioredis/built/transaction.js b/backend/node_modules/ioredis/built/transaction.js new file mode 100644 index 0000000..468fa8f --- /dev/null +++ b/backend/node_modules/ioredis/built/transaction.js @@ -0,0 +1,93 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.addTransactionSupport = void 0; +const utils_1 = require("./utils"); +const standard_as_callback_1 = require("standard-as-callback"); +const Pipeline_1 = require("./Pipeline"); +function addTransactionSupport(redis) { + redis.pipeline = function (commands) { + const pipeline = new Pipeline_1.default(this); + if (Array.isArray(commands)) { + pipeline.addBatch(commands); + } + return pipeline; + }; + const { multi } = redis; + redis.multi = function (commands, options) { + if (typeof options === "undefined" && !Array.isArray(commands)) { + options = commands; + commands = null; + } + if (options && options.pipeline === false) { + return multi.call(this); + } + const pipeline = new Pipeline_1.default(this); + // @ts-expect-error + pipeline.multi(); + if (Array.isArray(commands)) { + pipeline.addBatch(commands); + } + const exec = pipeline.exec; + pipeline.exec = function (callback) { + // Wait for the cluster to be connected, since we need nodes information before continuing + if (this.isCluster && !this.redis.slots.length) { + if (this.redis.status === "wait") + this.redis.connect().catch(utils_1.noop); + return (0, standard_as_callback_1.default)(new Promise((resolve, reject) => { + this.redis.delayUntilReady((err) => { + if (err) { + reject(err); + return; + } + this.exec(pipeline).then(resolve, reject); + }); + }), callback); + } + if (this._transactions > 0) { + exec.call(pipeline); + } + // Returns directly when the pipeline + // has been called multiple times (retries). + if (this.nodeifiedPromise) { + return exec.call(pipeline); + } + const promise = exec.call(pipeline); + return (0, standard_as_callback_1.default)(promise.then(function (result) { + const execResult = result[result.length - 1]; + if (typeof execResult === "undefined") { + throw new Error("Pipeline cannot be used to send any commands when the `exec()` has been called on it."); + } + if (execResult[0]) { + execResult[0].previousErrors = []; + for (let i = 0; i < result.length - 1; ++i) { + if (result[i][0]) { + execResult[0].previousErrors.push(result[i][0]); + } + } + throw execResult[0]; + } + return (0, utils_1.wrapMultiResult)(execResult[1]); + }), callback); + }; + // @ts-expect-error + const { execBuffer } = pipeline; + // @ts-expect-error + pipeline.execBuffer = function (callback) { + if (this._transactions > 0) { + execBuffer.call(pipeline); + } + return pipeline.exec(callback); + }; + return pipeline; + }; + const { exec } = redis; + redis.exec = function (callback) { + return (0, standard_as_callback_1.default)(exec.call(this).then(function (results) { + if (Array.isArray(results)) { + results = (0, utils_1.wrapMultiResult)(results); + } + return results; + }), callback); + }; +} +exports.addTransactionSupport = addTransactionSupport; diff --git a/backend/node_modules/ioredis/built/types.d.ts b/backend/node_modules/ioredis/built/types.d.ts new file mode 100644 index 0000000..e6d95a9 --- /dev/null +++ b/backend/node_modules/ioredis/built/types.d.ts @@ -0,0 +1,33 @@ +/// +import { Socket } from "net"; +import { TLSSocket } from "tls"; +export declare type Callback = (err?: Error | null, result?: T) => void; +export declare type NetStream = Socket | TLSSocket; +export declare type CommandParameter = string | Buffer | number | any[]; +export interface Respondable { + name: string; + args: CommandParameter[]; + resolve(result: any): void; + reject(error: Error): void; +} +export interface PipelineWriteableStream { + isPipeline: true; + write(data: string | Buffer): unknown; + destination: { + redis: { + stream: NetStream; + }; + }; +} +export declare type WriteableStream = NetStream | PipelineWriteableStream; +export interface CommandItem { + command: Respondable; + stream: WriteableStream; + select: number; +} +export interface ScanStreamOptions { + match?: string; + type?: string; + count?: number; + noValues?: boolean; +} diff --git a/backend/node_modules/ioredis/built/types.js b/backend/node_modules/ioredis/built/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/backend/node_modules/ioredis/built/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/backend/node_modules/ioredis/built/utils/Commander.d.ts b/backend/node_modules/ioredis/built/utils/Commander.d.ts new file mode 100644 index 0000000..cbee525 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/Commander.d.ts @@ -0,0 +1,50 @@ +import Command from "../Command"; +import { WriteableStream } from "../types"; +import RedisCommander, { ClientContext } from "./RedisCommander"; +export interface CommanderOptions { + keyPrefix?: string | undefined; + showFriendlyErrorStack?: boolean | undefined; +} +declare class Commander { + options: CommanderOptions; + /** + * @ignore + */ + scriptsSet: {}; + /** + * @ignore + */ + addedBuiltinSet: Set; + /** + * Return supported builtin commands + */ + getBuiltinCommands(): string[]; + /** + * Create a builtin command + */ + createBuiltinCommand(commandName: string): { + string: any; + buffer: any; + }; + /** + * Create add builtin command + */ + addBuiltinCommand(commandName: string): void; + /** + * Define a custom command using lua script + */ + defineCommand(name: string, definition: { + lua: string; + numberOfKeys?: number; + readOnly?: boolean; + }): void; + /** + * @ignore + */ + sendCommand(command: Command, stream?: WriteableStream, node?: unknown): unknown; +} +interface Commander extends RedisCommander { +} +export default Commander; diff --git a/backend/node_modules/ioredis/built/utils/Commander.js b/backend/node_modules/ioredis/built/utils/Commander.js new file mode 100644 index 0000000..31a9155 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/Commander.js @@ -0,0 +1,117 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const commands_1 = require("@ioredis/commands"); +const autoPipelining_1 = require("../autoPipelining"); +const Command_1 = require("../Command"); +const Script_1 = require("../Script"); +// eslint-disable-next-line @typescript-eslint/no-unused-vars +class Commander { + constructor() { + this.options = {}; + /** + * @ignore + */ + this.scriptsSet = {}; + /** + * @ignore + */ + this.addedBuiltinSet = new Set(); + } + /** + * Return supported builtin commands + */ + getBuiltinCommands() { + return commands.slice(0); + } + /** + * Create a builtin command + */ + createBuiltinCommand(commandName) { + return { + string: generateFunction(null, commandName, "utf8"), + buffer: generateFunction(null, commandName, null), + }; + } + /** + * Create add builtin command + */ + addBuiltinCommand(commandName) { + this.addedBuiltinSet.add(commandName); + this[commandName] = generateFunction(commandName, commandName, "utf8"); + this[commandName + "Buffer"] = generateFunction(commandName + "Buffer", commandName, null); + } + /** + * Define a custom command using lua script + */ + defineCommand(name, definition) { + const script = new Script_1.default(definition.lua, definition.numberOfKeys, this.options.keyPrefix, definition.readOnly); + this.scriptsSet[name] = script; + this[name] = generateScriptingFunction(name, name, script, "utf8"); + this[name + "Buffer"] = generateScriptingFunction(name + "Buffer", name, script, null); + } + /** + * @ignore + */ + sendCommand(command, stream, node) { + throw new Error('"sendCommand" is not implemented'); + } +} +const commands = commands_1.list.filter((command) => command !== "monitor"); +commands.push("sentinel"); +commands.forEach(function (commandName) { + Commander.prototype[commandName] = generateFunction(commandName, commandName, "utf8"); + Commander.prototype[commandName + "Buffer"] = generateFunction(commandName + "Buffer", commandName, null); +}); +Commander.prototype.call = generateFunction("call", "utf8"); +Commander.prototype.callBuffer = generateFunction("callBuffer", null); +// @ts-expect-error +Commander.prototype.send_command = Commander.prototype.call; +function generateFunction(functionName, _commandName, _encoding) { + if (typeof _encoding === "undefined") { + _encoding = _commandName; + _commandName = null; + } + return function (...args) { + const commandName = (_commandName || args.shift()); + let callback = args[args.length - 1]; + if (typeof callback === "function") { + args.pop(); + } + else { + callback = undefined; + } + const options = { + errorStack: this.options.showFriendlyErrorStack ? new Error() : undefined, + keyPrefix: this.options.keyPrefix, + replyEncoding: _encoding, + }; + // No auto pipeline, use regular command sending + if (!(0, autoPipelining_1.shouldUseAutoPipelining)(this, functionName, commandName)) { + return this.sendCommand( + // @ts-expect-error + new Command_1.default(commandName, args, options, callback)); + } + // Create a new pipeline and make sure it's scheduled + return (0, autoPipelining_1.executeWithAutoPipelining)(this, functionName, commandName, + // @ts-expect-error + args, callback); + }; +} +function generateScriptingFunction(functionName, commandName, script, encoding) { + return function (...args) { + const callback = typeof args[args.length - 1] === "function" ? args.pop() : undefined; + const options = { + replyEncoding: encoding, + }; + if (this.options.showFriendlyErrorStack) { + options.errorStack = new Error(); + } + // No auto pipeline, use regular command sending + if (!(0, autoPipelining_1.shouldUseAutoPipelining)(this, functionName, commandName)) { + return script.execute(this, args, options, callback); + } + // Create a new pipeline and make sure it's scheduled + return (0, autoPipelining_1.executeWithAutoPipelining)(this, functionName, commandName, args, callback); + }; +} +exports.default = Commander; diff --git a/backend/node_modules/ioredis/built/utils/RedisCommander.d.ts b/backend/node_modules/ioredis/built/utils/RedisCommander.d.ts new file mode 100644 index 0000000..4074af3 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/RedisCommander.d.ts @@ -0,0 +1,8950 @@ +/** + * This file is generated by @ioredis/interface-generator. + * Don't edit it manually. Instead, run `npm run generate` to update + * this file. + */ +/// +import { Callback } from "../types"; +export declare type RedisKey = string | Buffer; +export declare type RedisValue = string | Buffer | number; +export interface ResultTypes { + default: Promise; + pipeline: ChainableCommander; +} +export interface ChainableCommander extends RedisCommander<{ + type: "pipeline"; +}> { + length: number; +} +export declare type ClientContext = { + type: keyof ResultTypes; +}; +export declare type Result = ResultTypes[Context["type"]]; +interface RedisCommander { + /** + * Call arbitrary commands. + * + * `redis.call('set', 'foo', 'bar')` is the same as `redis.set('foo', 'bar')`, + * so the only case you need to use this method is when the command is not + * supported by ioredis. + * + * ```ts + * redis.call('set', 'foo', 'bar'); + * redis.call('get', 'foo', (err, value) => { + * // value === 'bar' + * }); + * ``` + */ + call(command: string, callback?: Callback): Result; + call(command: string, args: (string | Buffer | number)[], callback?: Callback): Result; + call(...args: [ + command: string, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + call(...args: [command: string, ...args: (string | Buffer | number)[]]): Result; + callBuffer(command: string, callback?: Callback): Result; + callBuffer(command: string, args: (string | Buffer | number)[], callback?: Callback): Result; + callBuffer(...args: [ + command: string, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + callBuffer(...args: [command: string, ...args: (string | Buffer | number)[]]): Result; + /** + * List the ACL categories or the commands inside a category + * - _group_: server + * - _complexity_: O(1) since the categories and commands are a fixed set. + * - _since_: 6.0.0 + */ + acl(subcommand: "CAT", callback?: Callback): Result; + acl(subcommand: "CAT", categoryname: string | Buffer, callback?: Callback): Result; + /** + * Remove the specified ACL users and the associated rules + * - _group_: server + * - _complexity_: O(1) amortized time considering the typical user. + * - _since_: 6.0.0 + */ + acl(...args: [ + subcommand: "DELUSER", + ...usernames: (string | Buffer)[], + callback: Callback + ]): Result; + acl(...args: [subcommand: "DELUSER", ...usernames: (string | Buffer)[]]): Result; + /** + * Returns whether the user can execute the given command without executing the command. + * - _group_: server + * - _complexity_: O(1). + * - _since_: 7.0.0 + */ + acl(subcommand: "DRYRUN", username: string | Buffer, command: string | Buffer, callback?: Callback): Result; + aclBuffer(subcommand: "DRYRUN", username: string | Buffer, command: string | Buffer, callback?: Callback): Result; + acl(...args: [ + subcommand: "DRYRUN", + username: string | Buffer, + command: string | Buffer, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + aclBuffer(...args: [ + subcommand: "DRYRUN", + username: string | Buffer, + command: string | Buffer, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + acl(...args: [ + subcommand: "DRYRUN", + username: string | Buffer, + command: string | Buffer, + ...args: (string | Buffer | number)[] + ]): Result; + aclBuffer(...args: [ + subcommand: "DRYRUN", + username: string | Buffer, + command: string | Buffer, + ...args: (string | Buffer | number)[] + ]): Result; + /** + * Generate a pseudorandom secure password to use for ACL users + * - _group_: server + * - _complexity_: O(1) + * - _since_: 6.0.0 + */ + acl(subcommand: "GENPASS", callback?: Callback): Result; + aclBuffer(subcommand: "GENPASS", callback?: Callback): Result; + acl(subcommand: "GENPASS", bits: number | string, callback?: Callback): Result; + aclBuffer(subcommand: "GENPASS", bits: number | string, callback?: Callback): Result; + /** + * Get the rules for a specific ACL user + * - _group_: server + * - _complexity_: O(N). Where N is the number of password, command and pattern rules that the user has. + * - _since_: 6.0.0 + */ + acl(subcommand: "GETUSER", username: string | Buffer, callback?: Callback): Result; + aclBuffer(subcommand: "GETUSER", username: string | Buffer, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: server + * - _complexity_: O(1) + * - _since_: 6.0.0 + */ + acl(subcommand: "HELP", callback?: Callback): Result; + /** + * List the current ACL rules in ACL config file format + * - _group_: server + * - _complexity_: O(N). Where N is the number of configured users. + * - _since_: 6.0.0 + */ + acl(subcommand: "LIST", callback?: Callback): Result; + aclBuffer(subcommand: "LIST", callback?: Callback): Result; + /** + * Reload the ACLs from the configured ACL file + * - _group_: server + * - _complexity_: O(N). Where N is the number of configured users. + * - _since_: 6.0.0 + */ + acl(subcommand: "LOAD", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * List latest events denied because of ACLs in place + * - _group_: server + * - _complexity_: O(N) with N being the number of entries shown. + * - _since_: 6.0.0 + */ + acl(subcommand: "LOG", callback?: Callback): Result; + acl(subcommand: "LOG", count: number | string, callback?: Callback): Result; + acl(subcommand: "LOG", reset: "RESET", callback?: Callback): Result; + /** + * Save the current ACL rules in the configured ACL file + * - _group_: server + * - _complexity_: O(N). Where N is the number of configured users. + * - _since_: 6.0.0 + */ + acl(subcommand: "SAVE", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Modify or create the rules for a specific ACL user + * - _group_: server + * - _complexity_: O(N). Where N is the number of rules provided. + * - _since_: 6.0.0 + */ + acl(subcommand: "SETUSER", username: string | Buffer, callback?: Callback<"OK">): Result<"OK", Context>; + acl(...args: [ + subcommand: "SETUSER", + username: string | Buffer, + ...rules: (string | Buffer)[], + callback: Callback<"OK"> + ]): Result<"OK", Context>; + acl(...args: [ + subcommand: "SETUSER", + username: string | Buffer, + ...rules: (string | Buffer)[] + ]): Result<"OK", Context>; + /** + * List the username of all the configured ACL rules + * - _group_: server + * - _complexity_: O(N). Where N is the number of configured users. + * - _since_: 6.0.0 + */ + acl(subcommand: "USERS", callback?: Callback): Result; + aclBuffer(subcommand: "USERS", callback?: Callback): Result; + /** + * Return the name of the user associated to the current connection + * - _group_: server + * - _complexity_: O(1) + * - _since_: 6.0.0 + */ + acl(subcommand: "WHOAMI", callback?: Callback): Result; + aclBuffer(subcommand: "WHOAMI", callback?: Callback): Result; + /** + * Append a value to a key + * - _group_: string + * - _complexity_: O(1). The amortized time complexity is O(1) assuming the appended value is small and the already present value is of any size, since the dynamic string library used by Redis will double the free space available on every reallocation. + * - _since_: 2.0.0 + */ + append(key: RedisKey, value: string | Buffer | number, callback?: Callback): Result; + /** + * Sent by cluster clients after an -ASK redirect + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + asking(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Authenticate to the server + * - _group_: connection + * - _complexity_: O(N) where N is the number of passwords defined for the user + * - _since_: 1.0.0 + */ + auth(password: string | Buffer, callback?: Callback<"OK">): Result<"OK", Context>; + auth(username: string | Buffer, password: string | Buffer, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Asynchronously rewrite the append-only file + * - _group_: server + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + bgrewriteaof(callback?: Callback): Result; + bgrewriteaofBuffer(callback?: Callback): Result; + /** + * Asynchronously save the dataset to disk + * - _group_: server + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + bgsave(callback?: Callback<"OK">): Result<"OK", Context>; + bgsave(schedule: "SCHEDULE", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Count set bits in a string + * - _group_: bitmap + * - _complexity_: O(N) + * - _since_: 2.6.0 + */ + bitcount(key: RedisKey, callback?: Callback): Result; + bitcount(key: RedisKey, start: number | string, end: number | string, callback?: Callback): Result; + bitcount(key: RedisKey, start: number | string, end: number | string, byte: "BYTE", callback?: Callback): Result; + bitcount(key: RedisKey, start: number | string, end: number | string, bit: "BIT", callback?: Callback): Result; + /** + * Perform arbitrary bitfield integer operations on strings + * - _group_: bitmap + * - _complexity_: O(1) for each subcommand specified + * - _since_: 3.2.0 + */ + bitfield(key: RedisKey, encodingOffsetToken: "GET", encoding: string | Buffer, offset: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, encodingOffsetValueToken: "SET", encoding: string | Buffer, offset: number | string, value: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, encodingOffsetIncrementToken: "INCRBY", encoding: string | Buffer, offset: number | string, increment: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, overflow: "OVERFLOW", wrap: "WRAP", encodingOffsetValueToken: "SET", encoding: string | Buffer, offset: number | string, value: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, overflow: "OVERFLOW", wrap: "WRAP", encodingOffsetIncrementToken: "INCRBY", encoding: string | Buffer, offset: number | string, increment: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, overflow: "OVERFLOW", sat: "SAT", encodingOffsetValueToken: "SET", encoding: string | Buffer, offset: number | string, value: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, overflow: "OVERFLOW", sat: "SAT", encodingOffsetIncrementToken: "INCRBY", encoding: string | Buffer, offset: number | string, increment: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, overflow: "OVERFLOW", fail: "FAIL", encodingOffsetValueToken: "SET", encoding: string | Buffer, offset: number | string, value: number | string, callback?: Callback): Result; + bitfield(key: RedisKey, overflow: "OVERFLOW", fail: "FAIL", encodingOffsetIncrementToken: "INCRBY", encoding: string | Buffer, offset: number | string, increment: number | string, callback?: Callback): Result; + /** + * Perform arbitrary bitfield integer operations on strings. Read-only variant of BITFIELD + * - _group_: bitmap + * - _complexity_: O(1) for each subcommand specified + * - _since_: 6.0.0 + */ + bitfield_ro(...args: [ + key: RedisKey, + encodingOffsetToken: "GET", + ...encodingOffsets: (string | Buffer | number)[], + callback: Callback + ]): Result; + bitfield_ro(...args: [ + key: RedisKey, + encodingOffsetToken: "GET", + ...encodingOffsets: (string | Buffer | number)[] + ]): Result; + /** + * Perform bitwise operations between strings + * - _group_: bitmap + * - _complexity_: O(N) + * - _since_: 2.6.0 + */ + bitop(...args: [ + operation: string | Buffer, + destkey: RedisKey, + ...keys: RedisKey[], + callback: Callback + ]): Result; + bitop(...args: [ + operation: string | Buffer, + destkey: RedisKey, + keys: RedisKey[], + callback: Callback + ]): Result; + bitop(...args: [ + operation: string | Buffer, + destkey: RedisKey, + ...keys: RedisKey[] + ]): Result; + bitop(...args: [operation: string | Buffer, destkey: RedisKey, keys: RedisKey[]]): Result; + /** + * Find first bit set or clear in a string + * - _group_: bitmap + * - _complexity_: O(N) + * - _since_: 2.8.7 + */ + bitpos(key: RedisKey, bit: number | string, callback?: Callback): Result; + bitpos(key: RedisKey, bit: number | string, start: number | string, callback?: Callback): Result; + bitpos(key: RedisKey, bit: number | string, start: number | string, end: number | string, callback?: Callback): Result; + bitpos(key: RedisKey, bit: number | string, start: number | string, end: number | string, byte: "BYTE", callback?: Callback): Result; + bitpos(key: RedisKey, bit: number | string, start: number | string, end: number | string, bit1: "BIT", callback?: Callback): Result; + /** + * Pop an element from a list, push it to another list and return it; or block until one is available + * - _group_: list + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + blmove(source: RedisKey, destination: RedisKey, left: "LEFT", left1: "LEFT", timeout: number | string, callback?: Callback): Result; + blmoveBuffer(source: RedisKey, destination: RedisKey, left: "LEFT", left1: "LEFT", timeout: number | string, callback?: Callback): Result; + blmove(source: RedisKey, destination: RedisKey, left: "LEFT", right: "RIGHT", timeout: number | string, callback?: Callback): Result; + blmoveBuffer(source: RedisKey, destination: RedisKey, left: "LEFT", right: "RIGHT", timeout: number | string, callback?: Callback): Result; + blmove(source: RedisKey, destination: RedisKey, right: "RIGHT", left: "LEFT", timeout: number | string, callback?: Callback): Result; + blmoveBuffer(source: RedisKey, destination: RedisKey, right: "RIGHT", left: "LEFT", timeout: number | string, callback?: Callback): Result; + blmove(source: RedisKey, destination: RedisKey, right: "RIGHT", right1: "RIGHT", timeout: number | string, callback?: Callback): Result; + blmoveBuffer(source: RedisKey, destination: RedisKey, right: "RIGHT", right1: "RIGHT", timeout: number | string, callback?: Callback): Result; + /** + * Pop elements from a list, or block until one is available + * - _group_: list + * - _complexity_: O(N+M) where N is the number of provided keys and M is the number of elements returned. + * - _since_: 7.0.0 + */ + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT" + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT" + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT" + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT" + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT" + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT" + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT" + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT" + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + blmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + blmpopBuffer(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + /** + * Remove and get the first element in a list, or block until one is available + * - _group_: list + * - _complexity_: O(N) where N is the number of provided keys. + * - _since_: 2.0.0 + */ + blpop(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[string, string] | null> + ]): Result<[string, string] | null, Context>; + blpopBuffer(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[Buffer, Buffer] | null> + ]): Result<[Buffer, Buffer] | null, Context>; + blpop(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[string, string] | null> + ]): Result<[string, string] | null, Context>; + blpopBuffer(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[Buffer, Buffer] | null> + ]): Result<[Buffer, Buffer] | null, Context>; + blpop(...args: [...keys: RedisKey[], timeout: number | string]): Result<[string, string] | null, Context>; + blpopBuffer(...args: [...keys: RedisKey[], timeout: number | string]): Result<[Buffer, Buffer] | null, Context>; + blpop(...args: [keys: RedisKey[], timeout: number | string]): Result<[string, string] | null, Context>; + blpopBuffer(...args: [keys: RedisKey[], timeout: number | string]): Result<[Buffer, Buffer] | null, Context>; + /** + * Remove and get the last element in a list, or block until one is available + * - _group_: list + * - _complexity_: O(N) where N is the number of provided keys. + * - _since_: 2.0.0 + */ + brpop(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[string, string] | null> + ]): Result<[string, string] | null, Context>; + brpopBuffer(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[Buffer, Buffer] | null> + ]): Result<[Buffer, Buffer] | null, Context>; + brpop(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[string, string] | null> + ]): Result<[string, string] | null, Context>; + brpopBuffer(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[Buffer, Buffer] | null> + ]): Result<[Buffer, Buffer] | null, Context>; + brpop(...args: [...keys: RedisKey[], timeout: number | string]): Result<[string, string] | null, Context>; + brpopBuffer(...args: [...keys: RedisKey[], timeout: number | string]): Result<[Buffer, Buffer] | null, Context>; + brpop(...args: [keys: RedisKey[], timeout: number | string]): Result<[string, string] | null, Context>; + brpopBuffer(...args: [keys: RedisKey[], timeout: number | string]): Result<[Buffer, Buffer] | null, Context>; + /** + * Pop an element from a list, push it to another list and return it; or block until one is available + * - _group_: list + * - _complexity_: O(1) + * - _since_: 2.2.0 + */ + brpoplpush(source: RedisKey, destination: RedisKey, timeout: number | string, callback?: Callback): Result; + brpoplpushBuffer(source: RedisKey, destination: RedisKey, timeout: number | string, callback?: Callback): Result; + /** + * Remove and return members with scores in a sorted set or block until one is available + * - _group_: sorted-set + * - _complexity_: O(K) + O(N*log(M)) where K is the number of provided keys, N being the number of elements in the sorted set, and M being the number of elements popped. + * - _since_: 7.0.0 + */ + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + min: "MIN", + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + min: "MIN", + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + min: "MIN" + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + min: "MIN" + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + max: "MAX", + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + max: "MAX", + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + max: "MAX" + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + max: "MAX" + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + ...keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string + ]): Result; + bzmpop(...args: [ + timeout: number | string, + numkeys: number | string, + keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string + ]): Result; + /** + * Remove and return the member with the highest score from one or more sorted sets, or block until one is available + * - _group_: sorted-set + * - _complexity_: O(log(N)) with N being the number of elements in the sorted set. + * - _since_: 5.0.0 + */ + bzpopmax(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: string, member: string, score: string] | null> + ]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopmaxBuffer(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: Buffer, member: Buffer, score: Buffer] | null> + ]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + bzpopmax(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: string, member: string, score: string] | null> + ]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopmaxBuffer(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: Buffer, member: Buffer, score: Buffer] | null> + ]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + bzpopmax(...args: [...keys: RedisKey[], timeout: number | string]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopmaxBuffer(...args: [...keys: RedisKey[], timeout: number | string]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + bzpopmax(...args: [keys: RedisKey[], timeout: number | string]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopmaxBuffer(...args: [keys: RedisKey[], timeout: number | string]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + /** + * Remove and return the member with the lowest score from one or more sorted sets, or block until one is available + * - _group_: sorted-set + * - _complexity_: O(log(N)) with N being the number of elements in the sorted set. + * - _since_: 5.0.0 + */ + bzpopmin(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: string, member: string, score: string] | null> + ]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopminBuffer(...args: [ + ...keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: Buffer, member: Buffer, score: Buffer] | null> + ]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + bzpopmin(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: string, member: string, score: string] | null> + ]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopminBuffer(...args: [ + keys: RedisKey[], + timeout: number | string, + callback: Callback<[key: Buffer, member: Buffer, score: Buffer] | null> + ]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + bzpopmin(...args: [...keys: RedisKey[], timeout: number | string]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopminBuffer(...args: [...keys: RedisKey[], timeout: number | string]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + bzpopmin(...args: [keys: RedisKey[], timeout: number | string]): Result<[key: string, member: string, score: string] | null, Context>; + bzpopminBuffer(...args: [keys: RedisKey[], timeout: number | string]): Result<[key: Buffer, member: Buffer, score: Buffer] | null, Context>; + /** + * Instruct the server about tracking or not keys in the next request + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 6.0.0 + */ + client(subcommand: "CACHING", yes: "YES", callback?: Callback<"OK">): Result<"OK", Context>; + client(subcommand: "CACHING", no: "NO", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Get the current connection name + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 2.6.9 + */ + client(subcommand: "GETNAME", callback?: Callback): Result; + clientBuffer(subcommand: "GETNAME", callback?: Callback): Result; + /** + * Get tracking notifications redirection client ID if any + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 6.0.0 + */ + client(subcommand: "GETREDIR", callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + client(subcommand: "HELP", callback?: Callback): Result; + /** + * Returns the client ID for the current connection + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + client(subcommand: "ID", callback?: Callback): Result; + /** + * Returns information about the current client connection. + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + client(subcommand: "INFO", callback?: Callback): Result; + clientBuffer(subcommand: "INFO", callback?: Callback): Result; + /** + * Kill the connection of a client + * - _group_: connection + * - _complexity_: O(N) where N is the number of client connections + * - _since_: 2.4.0 + */ + client(...args: [ + subcommand: "KILL", + ...args: RedisValue[], + callback: Callback + ]): Result; + client(...args: [subcommand: "KILL", ...args: RedisValue[]]): Result; + /** + * Get the list of client connections + * - _group_: connection + * - _complexity_: O(N) where N is the number of client connections + * - _since_: 2.4.0 + */ + client(subcommand: "LIST", callback?: Callback): Result; + client(...args: [ + subcommand: "LIST", + idToken: "ID", + ...clientIds: (number | string)[], + callback: Callback + ]): Result; + client(...args: [ + subcommand: "LIST", + idToken: "ID", + ...clientIds: (number | string)[] + ]): Result; + client(subcommand: "LIST", type: "TYPE", normal: "NORMAL", callback?: Callback): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + normal: "NORMAL", + idToken: "ID", + ...clientIds: (number | string)[], + callback: Callback + ]): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + normal: "NORMAL", + idToken: "ID", + ...clientIds: (number | string)[] + ]): Result; + client(subcommand: "LIST", type: "TYPE", master: "MASTER", callback?: Callback): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + master: "MASTER", + idToken: "ID", + ...clientIds: (number | string)[], + callback: Callback + ]): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + master: "MASTER", + idToken: "ID", + ...clientIds: (number | string)[] + ]): Result; + client(subcommand: "LIST", type: "TYPE", replica: "REPLICA", callback?: Callback): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + replica: "REPLICA", + idToken: "ID", + ...clientIds: (number | string)[], + callback: Callback + ]): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + replica: "REPLICA", + idToken: "ID", + ...clientIds: (number | string)[] + ]): Result; + client(subcommand: "LIST", type: "TYPE", pubsub: "PUBSUB", callback?: Callback): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + pubsub: "PUBSUB", + idToken: "ID", + ...clientIds: (number | string)[], + callback: Callback + ]): Result; + client(...args: [ + subcommand: "LIST", + type: "TYPE", + pubsub: "PUBSUB", + idToken: "ID", + ...clientIds: (number | string)[] + ]): Result; + /** + * Set client eviction mode for the current connection + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + client(subcommand: "NO-EVICT", on: "ON", callback?: Callback): Result; + client(subcommand: "NO-EVICT", off: "OFF", callback?: Callback): Result; + /** + * Stop processing commands from clients for some time + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 2.9.50 + */ + client(subcommand: "PAUSE", timeout: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + client(subcommand: "PAUSE", timeout: number | string, write: "WRITE", callback?: Callback<"OK">): Result<"OK", Context>; + client(subcommand: "PAUSE", timeout: number | string, all: "ALL", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Instruct the server whether to reply to commands + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 3.2.0 + */ + client(subcommand: "REPLY", on: "ON", callback?: Callback): Result; + client(subcommand: "REPLY", off: "OFF", callback?: Callback): Result; + client(subcommand: "REPLY", skip: "SKIP", callback?: Callback): Result; + /** + * Set the current connection name + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 2.6.9 + */ + client(subcommand: "SETNAME", connectionName: string | Buffer, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Enable or disable server assisted client side caching support + * - _group_: connection + * - _complexity_: O(1). Some options may introduce additional complexity. + * - _since_: 6.0.0 + */ + client(...args: [ + subcommand: "TRACKING", + ...args: RedisValue[], + callback: Callback + ]): Result; + client(...args: [subcommand: "TRACKING", ...args: RedisValue[]]): Result; + /** + * Return information about server assisted client side caching for the current connection + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + client(subcommand: "TRACKINGINFO", callback?: Callback): Result; + clientBuffer(subcommand: "TRACKINGINFO", callback?: Callback): Result; + /** + * Unblock a client blocked in a blocking command from a different connection + * - _group_: connection + * - _complexity_: O(log N) where N is the number of client connections + * - _since_: 5.0.0 + */ + client(subcommand: "UNBLOCK", clientId: number | string, callback?: Callback): Result; + client(subcommand: "UNBLOCK", clientId: number | string, timeout: "TIMEOUT", callback?: Callback): Result; + client(subcommand: "UNBLOCK", clientId: number | string, error: "ERROR", callback?: Callback): Result; + /** + * Resume processing of clients that were paused + * - _group_: connection + * - _complexity_: O(N) Where N is the number of paused clients + * - _since_: 6.2.0 + */ + client(subcommand: "UNPAUSE", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Assign new hash slots to receiving node + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of hash slot arguments + * - _since_: 3.0.0 + */ + cluster(...args: [ + subcommand: "ADDSLOTS", + ...slots: (number | string)[], + callback: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]> + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [ + subcommand: "ADDSLOTS", + slots: (number | string)[], + callback: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]> + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [subcommand: "ADDSLOTS", ...slots: (number | string)[]]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [subcommand: "ADDSLOTS", slots: (number | string)[]]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + /** + * Assign new hash slots to receiving node + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of the slots between the start slot and end slot arguments. + * - _since_: 7.0.0 + */ + cluster(...args: [ + subcommand: "ADDSLOTSRANGE", + ...startSlotEndSlots: (string | number)[], + callback: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]> + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [ + subcommand: "ADDSLOTSRANGE", + ...startSlotEndSlots: (string | number)[] + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + /** + * Advance the cluster config epoch + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "BUMPEPOCH", callback?: Callback<"BUMPED" | "STILL">): Result<"BUMPED" | "STILL", Context>; + /** + * Return the number of failure reports active for a given node + * - _group_: cluster + * - _complexity_: O(N) where N is the number of failure reports + * - _since_: 3.0.0 + */ + cluster(subcommand: "COUNT-FAILURE-REPORTS", nodeId: string | Buffer | number, callback?: Callback): Result; + /** + * Return the number of local keys in the specified hash slot + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "COUNTKEYSINSLOT", slot: number | string, callback?: Callback): Result; + /** + * Set hash slots as unbound in receiving node + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of hash slot arguments + * - _since_: 3.0.0 + */ + cluster(...args: [ + subcommand: "DELSLOTS", + ...slots: (number | string)[], + callback: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]> + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [ + subcommand: "DELSLOTS", + slots: (number | string)[], + callback: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]> + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [subcommand: "DELSLOTS", ...slots: (number | string)[]]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [subcommand: "DELSLOTS", slots: (number | string)[]]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + /** + * Set hash slots as unbound in receiving node + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of the slots between the start slot and end slot arguments. + * - _since_: 7.0.0 + */ + cluster(...args: [ + subcommand: "DELSLOTSRANGE", + ...startSlotEndSlots: (string | number)[], + callback: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]> + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + cluster(...args: [ + subcommand: "DELSLOTSRANGE", + ...startSlotEndSlots: (string | number)[] + ]): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + /** + * Forces a replica to perform a manual failover of its master. + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "FAILOVER", callback?: Callback<"OK">): Result<"OK", Context>; + cluster(subcommand: "FAILOVER", force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + cluster(subcommand: "FAILOVER", takeover: "TAKEOVER", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Delete a node's own slots information + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "FLUSHSLOTS", callback?: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]>): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + /** + * Remove a node from the nodes table + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "FORGET", nodeId: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Return local key names in the specified hash slot + * - _group_: cluster + * - _complexity_: O(log(N)) where N is the number of requested keys + * - _since_: 3.0.0 + */ + cluster(subcommand: "GETKEYSINSLOT", slot: number | string, count: number | string, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + cluster(subcommand: "HELP", callback?: Callback): Result; + /** + * Provides info about Redis Cluster node state + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "INFO", callback?: Callback): Result; + /** + * Returns the hash slot of the specified key + * - _group_: cluster + * - _complexity_: O(N) where N is the number of bytes in the key + * - _since_: 3.0.0 + */ + cluster(subcommand: "KEYSLOT", key: string | Buffer, callback?: Callback): Result; + /** + * Returns a list of all TCP links to and from peer nodes in cluster + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of Cluster nodes + * - _since_: 7.0.0 + */ + cluster(subcommand: "LINKS", callback?: Callback): Result; + /** + * Force a node cluster to handshake with another node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "MEET", ip: string | Buffer, port: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Return the node id + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "MYID", callback?: Callback): Result; + /** + * Get Cluster config for the node + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of Cluster nodes + * - _since_: 3.0.0 + */ + cluster(subcommand: "NODES", callback?: Callback): Result; + /** + * List replica nodes of the specified master node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + cluster(subcommand: "REPLICAS", nodeId: string | Buffer | number, callback?: Callback): Result; + /** + * Reconfigure a node as a replica of the specified master node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "REPLICATE", nodeId: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Reset a Redis Cluster node + * - _group_: cluster + * - _complexity_: O(N) where N is the number of known nodes. The command may execute a FLUSHALL as a side effect. + * - _since_: 3.0.0 + */ + cluster(subcommand: "RESET", callback?: Callback<"OK">): Result<"OK", Context>; + cluster(subcommand: "RESET", hard: "HARD", callback?: Callback<"OK">): Result<"OK", Context>; + cluster(subcommand: "RESET", soft: "SOFT", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Forces the node to save cluster state on disk + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "SAVECONFIG", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Set the configuration epoch in a new node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "SET-CONFIG-EPOCH", configEpoch: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Bind a hash slot to a specific node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "SETSLOT", slot: number | string, nodeIdToken: "IMPORTING", nodeId: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + cluster(subcommand: "SETSLOT", slot: number | string, nodeIdToken: "MIGRATING", nodeId: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + cluster(subcommand: "SETSLOT", slot: number | string, nodeIdToken: "NODE", nodeId: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + cluster(subcommand: "SETSLOT", slot: number | string, stable: "STABLE", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Get array of cluster slots to node mappings + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of cluster nodes + * - _since_: 7.0.0 + */ + cluster(subcommand: "SHARDS", callback?: Callback): Result; + /** + * List replica nodes of the specified master node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + cluster(subcommand: "SLAVES", nodeId: string | Buffer | number, callback?: Callback): Result; + /** + * Get array of Cluster slot to node mappings + * - _group_: cluster + * - _complexity_: O(N) where N is the total number of Cluster nodes + * - _since_: 3.0.0 + */ + cluster(subcommand: "SLOTS", callback?: Callback<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [ + host: string, + port: number, + nodeId: string, + info: unknown[] + ][] + ][]>): Result<[ + startSlotRange: number, + endSlotRange: number, + ...nodes: [host: string, port: number, nodeId: string, info: unknown[]][] + ][], Context>; + /** + * Get total number of Redis commands + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.13 + */ + command(subcommand: "COUNT", callback?: Callback): Result; + /** + * Get array of specific Redis command documentation + * - _group_: server + * - _complexity_: O(N) where N is the number of commands to look up + * - _since_: 7.0.0 + */ + command(subcommand: "DOCS", callback?: Callback): Result; + command(...args: [ + subcommand: "DOCS", + ...commandNames: (string | Buffer)[], + callback: Callback + ]): Result; + command(...args: [subcommand: "DOCS", ...commandNames: (string | Buffer)[]]): Result; + /** + * Extract keys given a full Redis command + * - _group_: server + * - _complexity_: O(N) where N is the number of arguments to the command + * - _since_: 2.8.13 + */ + command(subcommand: "GETKEYS", callback?: Callback): Result; + /** + * Extract keys and access flags given a full Redis command + * - _group_: server + * - _complexity_: O(N) where N is the number of arguments to the command + * - _since_: 7.0.0 + */ + command(subcommand: "GETKEYSANDFLAGS", callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: server + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + command(subcommand: "HELP", callback?: Callback): Result; + /** + * Get array of specific Redis command details, or all when no argument is given. + * - _group_: server + * - _complexity_: O(N) where N is the number of commands to look up + * - _since_: 2.8.13 + */ + command(subcommand: "INFO", callback?: Callback): Result; + command(...args: [ + subcommand: "INFO", + ...commandNames: (string | Buffer)[], + callback: Callback + ]): Result; + command(...args: [subcommand: "INFO", ...commandNames: (string | Buffer)[]]): Result; + /** + * Get an array of Redis command names + * - _group_: server + * - _complexity_: O(N) where N is the total number of Redis commands + * - _since_: 7.0.0 + */ + command(subcommand: "LIST", callback?: Callback): Result; + command(subcommand: "LIST", filterby: "FILTERBY", moduleNameToken: "MODULE", moduleName: string | Buffer, callback?: Callback): Result; + command(subcommand: "LIST", filterby: "FILTERBY", categoryToken: "ACLCAT", category: string | Buffer, callback?: Callback): Result; + command(subcommand: "LIST", filterby: "FILTERBY", patternToken: "PATTERN", pattern: string, callback?: Callback): Result; + /** + * Get the values of configuration parameters + * - _group_: server + * - _complexity_: O(N) when N is the number of configuration parameters provided + * - _since_: 2.0.0 + */ + config(...args: [ + subcommand: "GET", + ...parameters: (string | Buffer)[], + callback: Callback + ]): Result; + config(...args: [subcommand: "GET", ...parameters: (string | Buffer)[]]): Result; + /** + * Show helpful text about the different subcommands + * - _group_: server + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + config(subcommand: "HELP", callback?: Callback): Result; + /** + * Reset the stats returned by INFO + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.0.0 + */ + config(subcommand: "RESETSTAT", callback?: Callback): Result; + /** + * Rewrite the configuration file with the in memory configuration + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.0 + */ + config(subcommand: "REWRITE", callback?: Callback): Result; + /** + * Set configuration parameters to the given values + * - _group_: server + * - _complexity_: O(N) when N is the number of configuration parameters provided + * - _since_: 2.0.0 + */ + config(...args: [ + subcommand: "SET", + ...parameterValues: (string | Buffer | number)[], + callback: Callback + ]): Result; + config(...args: [ + subcommand: "SET", + ...parameterValues: (string | Buffer | number)[] + ]): Result; + /** + * Copy a key + * - _group_: generic + * - _complexity_: O(N) worst case for collections, where N is the number of nested items. O(1) for string values. + * - _since_: 6.2.0 + */ + copy(source: RedisKey, destination: RedisKey, callback?: Callback): Result; + copy(source: RedisKey, destination: RedisKey, replace: "REPLACE", callback?: Callback): Result; + copy(source: RedisKey, destination: RedisKey, destinationDbToken: "DB", destinationDb: number | string, callback?: Callback): Result; + copy(source: RedisKey, destination: RedisKey, destinationDbToken: "DB", destinationDb: number | string, replace: "REPLACE", callback?: Callback): Result; + /** + * Return the number of keys in the selected database + * - _group_: server + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + dbsize(callback?: Callback): Result; + /** + * A container for debugging commands + * - _group_: server + * - _complexity_: Depends on subcommand. + * - _since_: 1.0.0 + */ + debug(subcommand: string, callback?: Callback): Result; + debug(...args: [ + subcommand: string, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + debug(...args: [subcommand: string, ...args: (string | Buffer | number)[]]): Result; + /** + * Decrement the integer value of a key by one + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + decr(key: RedisKey, callback?: Callback): Result; + /** + * Decrement the integer value of a key by the given number + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + decrby(key: RedisKey, decrement: number | string, callback?: Callback): Result; + /** + * Delete a key + * - _group_: generic + * - _complexity_: O(N) where N is the number of keys that will be removed. When a key to remove holds a value other than a string, the individual complexity for this key is O(M) where M is the number of elements in the list, set, sorted set or hash. Removing a single key that holds a string value is O(1). + * - _since_: 1.0.0 + */ + del(...args: [...keys: RedisKey[], callback: Callback]): Result; + del(...args: [keys: RedisKey[], callback: Callback]): Result; + del(...args: [...keys: RedisKey[]]): Result; + del(...args: [keys: RedisKey[]]): Result; + /** + * Discard all commands issued after MULTI + * - _group_: transactions + * - _complexity_: O(N), when N is the number of queued commands + * - _since_: 2.0.0 + */ + discard(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Return a serialized version of the value stored at the specified key. + * - _group_: generic + * - _complexity_: O(1) to access the key and additional O(N*M) to serialize it, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1*M) where M is small, so simply O(1). + * - _since_: 2.6.0 + */ + dump(key: RedisKey, callback?: Callback): Result; + dumpBuffer(key: RedisKey, callback?: Callback): Result; + /** + * Echo the given string + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + echo(message: string | Buffer, callback?: Callback): Result; + echoBuffer(message: string | Buffer, callback?: Callback): Result; + /** + * Execute a Lua script server side + * - _group_: scripting + * - _complexity_: Depends on the script that is executed. + * - _since_: 2.6.0 + */ + eval(script: string | Buffer, numkeys: number | string, callback?: Callback): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + ...args: (string | Buffer | number)[] + ]): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + ...keys: RedisKey[] + ]): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + keys: RedisKey[] + ]): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + eval(...args: [ + script: string | Buffer, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Execute a read-only Lua script server side + * - _group_: scripting + * - _complexity_: Depends on the script that is executed. + * - _since_: 7.0.0 + */ + eval_ro(...args: [ + script: string | Buffer, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + eval_ro(...args: [ + script: string | Buffer, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Execute a Lua script server side + * - _group_: scripting + * - _complexity_: Depends on the script that is executed. + * - _since_: 2.6.0 + */ + evalsha(sha1: string | Buffer, numkeys: number | string, callback?: Callback): Result; + evalsha(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + evalsha(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...args: (string | Buffer | number)[] + ]): Result; + evalsha(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + evalsha(...args: [ + sha1: string | Buffer, + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + evalsha(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...keys: RedisKey[] + ]): Result; + evalsha(...args: [sha1: string | Buffer, numkeys: number | string, keys: RedisKey[]]): Result; + evalsha(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + evalsha(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Execute a read-only Lua script server side + * - _group_: scripting + * - _complexity_: Depends on the script that is executed. + * - _since_: 7.0.0 + */ + evalsha_ro(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + evalsha_ro(...args: [ + sha1: string | Buffer, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Execute all commands issued after MULTI + * - _group_: transactions + * - _complexity_: Depends on commands in the transaction + * - _since_: 1.2.0 + */ + exec(callback?: Callback<[error: Error | null, result: unknown][] | null>): Promise<[error: Error | null, result: unknown][] | null>; + /** + * Determine if a key exists + * - _group_: generic + * - _complexity_: O(N) where N is the number of keys to check. + * - _since_: 1.0.0 + */ + exists(...args: [...keys: RedisKey[], callback: Callback]): Result; + exists(...args: [keys: RedisKey[], callback: Callback]): Result; + exists(...args: [...keys: RedisKey[]]): Result; + exists(...args: [keys: RedisKey[]]): Result; + /** + * Set a key's time to live in seconds + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + expire(key: RedisKey, seconds: number | string, callback?: Callback): Result; + expire(key: RedisKey, seconds: number | string, nx: "NX", callback?: Callback): Result; + expire(key: RedisKey, seconds: number | string, xx: "XX", callback?: Callback): Result; + expire(key: RedisKey, seconds: number | string, gt: "GT", callback?: Callback): Result; + expire(key: RedisKey, seconds: number | string, lt: "LT", callback?: Callback): Result; + /** + * Set the expiration for a key as a UNIX timestamp + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.2.0 + */ + expireat(key: RedisKey, unixTimeSeconds: number | string, callback?: Callback): Result; + expireat(key: RedisKey, unixTimeSeconds: number | string, nx: "NX", callback?: Callback): Result; + expireat(key: RedisKey, unixTimeSeconds: number | string, xx: "XX", callback?: Callback): Result; + expireat(key: RedisKey, unixTimeSeconds: number | string, gt: "GT", callback?: Callback): Result; + expireat(key: RedisKey, unixTimeSeconds: number | string, lt: "LT", callback?: Callback): Result; + /** + * Get the expiration Unix timestamp for a key + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + expiretime(key: RedisKey, callback?: Callback): Result; + /** + * Start a coordinated failover between this server and one of its replicas. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + failover(callback?: Callback<"OK">): Result<"OK", Context>; + failover(millisecondsToken: "TIMEOUT", milliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + failover(abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + failover(abort: "ABORT", millisecondsToken: "TIMEOUT", milliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, millisecondsToken: "TIMEOUT", milliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, abort: "ABORT", millisecondsToken: "TIMEOUT", milliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, force: "FORCE", millisecondsToken: "TIMEOUT", milliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, force: "FORCE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + failover(targetToken: "TO", host: string | Buffer, port: number | string, force: "FORCE", abort: "ABORT", millisecondsToken: "TIMEOUT", milliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Invoke a function + * - _group_: scripting + * - _complexity_: Depends on the function that is executed. + * - _since_: 7.0.0 + */ + fcall(...args: [ + function: string | Buffer, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + fcall(...args: [ + function: string | Buffer, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Invoke a read-only function + * - _group_: scripting + * - _complexity_: Depends on the function that is executed. + * - _since_: 7.0.0 + */ + fcall_ro(...args: [ + function: string | Buffer, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + fcall_ro(...args: [ + function: string | Buffer, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Remove all keys from all databases + * - _group_: server + * - _complexity_: O(N) where N is the total number of keys in all databases + * - _since_: 1.0.0 + */ + flushall(callback?: Callback<"OK">): Result<"OK", Context>; + flushall(async: "ASYNC", callback?: Callback<"OK">): Result<"OK", Context>; + flushall(sync: "SYNC", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Remove all keys from the current database + * - _group_: server + * - _complexity_: O(N) where N is the number of keys in the selected database + * - _since_: 1.0.0 + */ + flushdb(callback?: Callback<"OK">): Result<"OK", Context>; + flushdb(async: "ASYNC", callback?: Callback<"OK">): Result<"OK", Context>; + flushdb(sync: "SYNC", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Delete a function by name + * - _group_: scripting + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + function(subcommand: "DELETE", libraryName: string | Buffer, callback?: Callback): Result; + functionBuffer(subcommand: "DELETE", libraryName: string | Buffer, callback?: Callback): Result; + /** + * Dump all functions into a serialized binary payload + * - _group_: scripting + * - _complexity_: O(N) where N is the number of functions + * - _since_: 7.0.0 + */ + function(subcommand: "DUMP", callback?: Callback): Result; + functionBuffer(subcommand: "DUMP", callback?: Callback): Result; + /** + * Deleting all functions + * - _group_: scripting + * - _complexity_: O(N) where N is the number of functions deleted + * - _since_: 7.0.0 + */ + function(subcommand: "FLUSH", callback?: Callback): Result; + functionBuffer(subcommand: "FLUSH", callback?: Callback): Result; + function(subcommand: "FLUSH", async: "ASYNC", callback?: Callback): Result; + functionBuffer(subcommand: "FLUSH", async: "ASYNC", callback?: Callback): Result; + function(subcommand: "FLUSH", sync: "SYNC", callback?: Callback): Result; + functionBuffer(subcommand: "FLUSH", sync: "SYNC", callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: scripting + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + function(subcommand: "HELP", callback?: Callback): Result; + /** + * Kill the function currently in execution. + * - _group_: scripting + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + function(subcommand: "KILL", callback?: Callback): Result; + functionBuffer(subcommand: "KILL", callback?: Callback): Result; + /** + * List information about all the functions + * - _group_: scripting + * - _complexity_: O(N) where N is the number of functions + * - _since_: 7.0.0 + */ + function(subcommand: "LIST", callback?: Callback): Result; + function(subcommand: "LIST", withcode: "WITHCODE", callback?: Callback): Result; + function(subcommand: "LIST", libraryNamePatternToken: "LIBRARYNAME", libraryNamePattern: string | Buffer, callback?: Callback): Result; + function(subcommand: "LIST", libraryNamePatternToken: "LIBRARYNAME", libraryNamePattern: string | Buffer, withcode: "WITHCODE", callback?: Callback): Result; + /** + * Create a function with the given arguments (name, code, description) + * - _group_: scripting + * - _complexity_: O(1) (considering compilation time is redundant) + * - _since_: 7.0.0 + */ + function(subcommand: "LOAD", functionCode: string | Buffer, callback?: Callback): Result; + functionBuffer(subcommand: "LOAD", functionCode: string | Buffer, callback?: Callback): Result; + function(subcommand: "LOAD", replace: "REPLACE", functionCode: string | Buffer, callback?: Callback): Result; + functionBuffer(subcommand: "LOAD", replace: "REPLACE", functionCode: string | Buffer, callback?: Callback): Result; + /** + * Restore all the functions on the given payload + * - _group_: scripting + * - _complexity_: O(N) where N is the number of functions on the payload + * - _since_: 7.0.0 + */ + function(subcommand: "RESTORE", serializedValue: string | Buffer | number, callback?: Callback): Result; + functionBuffer(subcommand: "RESTORE", serializedValue: string | Buffer | number, callback?: Callback): Result; + function(subcommand: "RESTORE", serializedValue: string | Buffer | number, flush: "FLUSH", callback?: Callback): Result; + functionBuffer(subcommand: "RESTORE", serializedValue: string | Buffer | number, flush: "FLUSH", callback?: Callback): Result; + function(subcommand: "RESTORE", serializedValue: string | Buffer | number, append: "APPEND", callback?: Callback): Result; + functionBuffer(subcommand: "RESTORE", serializedValue: string | Buffer | number, append: "APPEND", callback?: Callback): Result; + function(subcommand: "RESTORE", serializedValue: string | Buffer | number, replace: "REPLACE", callback?: Callback): Result; + functionBuffer(subcommand: "RESTORE", serializedValue: string | Buffer | number, replace: "REPLACE", callback?: Callback): Result; + /** + * Return information about the function currently running (name, description, duration) + * - _group_: scripting + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + function(subcommand: "STATS", callback?: Callback): Result; + /** + * Add one or more geospatial items in the geospatial index represented using a sorted set + * - _group_: geo + * - _complexity_: O(log(N)) for each item added, where N is the number of elements in the sorted set. + * - _since_: 3.2.0 + */ + geoadd(...args: [ + key: RedisKey, + ...longitudeLatitudeMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + geoadd(...args: [ + key: RedisKey, + ...longitudeLatitudeMembers: (string | Buffer | number)[] + ]): Result; + geoadd(...args: [ + key: RedisKey, + ch: "CH", + ...longitudeLatitudeMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + geoadd(...args: [ + key: RedisKey, + ch: "CH", + ...longitudeLatitudeMembers: (string | Buffer | number)[] + ]): Result; + geoadd(...args: [ + key: RedisKey, + nx: "NX", + ...longitudeLatitudeMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + geoadd(...args: [ + key: RedisKey, + nx: "NX", + ...longitudeLatitudeMembers: (string | Buffer | number)[] + ]): Result; + geoadd(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + ...longitudeLatitudeMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + geoadd(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + ...longitudeLatitudeMembers: (string | Buffer | number)[] + ]): Result; + geoadd(...args: [ + key: RedisKey, + xx: "XX", + ...longitudeLatitudeMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + geoadd(...args: [ + key: RedisKey, + xx: "XX", + ...longitudeLatitudeMembers: (string | Buffer | number)[] + ]): Result; + geoadd(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + ...longitudeLatitudeMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + geoadd(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + ...longitudeLatitudeMembers: (string | Buffer | number)[] + ]): Result; + /** + * Returns the distance between two members of a geospatial index + * - _group_: geo + * - _complexity_: O(log(N)) + * - _since_: 3.2.0 + */ + geodist(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, callback?: Callback): Result; + geodistBuffer(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, callback?: Callback): Result; + geodist(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, m: "M", callback?: Callback): Result; + geodistBuffer(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, m: "M", callback?: Callback): Result; + geodist(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, km: "KM", callback?: Callback): Result; + geodistBuffer(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, km: "KM", callback?: Callback): Result; + geodist(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, ft: "FT", callback?: Callback): Result; + geodistBuffer(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, ft: "FT", callback?: Callback): Result; + geodist(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, mi: "MI", callback?: Callback): Result; + geodistBuffer(key: RedisKey, member1: string | Buffer | number, member2: string | Buffer | number, mi: "MI", callback?: Callback): Result; + /** + * Returns members of a geospatial index as standard geohash strings + * - _group_: geo + * - _complexity_: O(log(N)) for each member requested, where N is the number of elements in the sorted set. + * - _since_: 3.2.0 + */ + geohash(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback + ]): Result; + geohashBuffer(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback + ]): Result; + geohash(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback + ]): Result; + geohashBuffer(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback + ]): Result; + geohash(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result; + geohashBuffer(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result; + geohash(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result; + geohashBuffer(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result; + /** + * Returns longitude and latitude of members of a geospatial index + * - _group_: geo + * - _complexity_: O(N) where N is the number of members requested. + * - _since_: 3.2.0 + */ + geopos(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback<([longitude: string, latitude: string] | null)[]> + ]): Result<([longitude: string, latitude: string] | null)[], Context>; + geopos(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback<([longitude: string, latitude: string] | null)[]> + ]): Result<([longitude: string, latitude: string] | null)[], Context>; + geopos(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result<([longitude: string, latitude: string] | null)[], Context>; + geopos(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result<([longitude: string, latitude: string] | null)[], Context>; + /** + * Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point + * - _group_: geo + * - _complexity_: O(N+log(M)) where N is the number of elements inside the bounding box of the circular area delimited by center and radius and M is the number of items inside the index. + * - _since_: 3.2.0 + */ + georadius(...args: [ + key: RedisKey, + longitude: number | string, + latitude: number | string, + radius: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + georadius(...args: [ + key: RedisKey, + longitude: number | string, + latitude: number | string, + radius: number | string, + ...args: RedisValue[] + ]): Result; + /** + * A read-only variant for GEORADIUS + * - _group_: geo + * - _complexity_: O(N+log(M)) where N is the number of elements inside the bounding box of the circular area delimited by center and radius and M is the number of items inside the index. + * - _since_: 3.2.10 + */ + georadius_ro(...args: [ + key: RedisKey, + longitude: number | string, + latitude: number | string, + radius: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + georadius_ro(...args: [ + key: RedisKey, + longitude: number | string, + latitude: number | string, + radius: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member + * - _group_: geo + * - _complexity_: O(N+log(M)) where N is the number of elements inside the bounding box of the circular area delimited by center and radius and M is the number of items inside the index. + * - _since_: 3.2.0 + */ + georadiusbymember(...args: [ + key: RedisKey, + member: string | Buffer | number, + radius: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + georadiusbymember(...args: [ + key: RedisKey, + member: string | Buffer | number, + radius: number | string, + ...args: RedisValue[] + ]): Result; + /** + * A read-only variant for GEORADIUSBYMEMBER + * - _group_: geo + * - _complexity_: O(N+log(M)) where N is the number of elements inside the bounding box of the circular area delimited by center and radius and M is the number of items inside the index. + * - _since_: 3.2.10 + */ + georadiusbymember_ro(...args: [ + key: RedisKey, + member: string | Buffer | number, + radius: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + georadiusbymember_ro(...args: [ + key: RedisKey, + member: string | Buffer | number, + radius: number | string, + ...args: RedisValue[] + ]): Result; + /** + * Query a sorted set representing a geospatial index to fetch members inside an area of a box or a circle. + * - _group_: geo + * - _complexity_: O(N+log(M)) where N is the number of elements in the grid-aligned bounding box area around the shape provided as the filter and M is the number of items inside the shape + * - _since_: 6.2.0 + */ + geosearch(...args: [ + key: RedisKey, + ...args: RedisValue[], + callback: Callback + ]): Result; + geosearch(...args: [key: RedisKey, ...args: RedisValue[]]): Result; + /** + * Query a sorted set representing a geospatial index to fetch members inside an area of a box or a circle, and store the result in another key. + * - _group_: geo + * - _complexity_: O(N+log(M)) where N is the number of elements in the grid-aligned bounding box area around the shape provided as the filter and M is the number of items inside the shape + * - _since_: 6.2.0 + */ + geosearchstore(...args: [ + destination: RedisKey, + source: RedisKey, + ...args: RedisValue[], + callback: Callback + ]): Result; + geosearchstore(...args: [destination: RedisKey, source: RedisKey, ...args: RedisValue[]]): Result; + /** + * Get the value of a key + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + get(key: RedisKey, callback?: Callback): Result; + getBuffer(key: RedisKey, callback?: Callback): Result; + /** + * Returns the bit value at offset in the string value stored at key + * - _group_: bitmap + * - _complexity_: O(1) + * - _since_: 2.2.0 + */ + getbit(key: RedisKey, offset: number | string, callback?: Callback): Result; + /** + * Get the value of a key and delete the key + * - _group_: string + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + getdel(key: RedisKey, callback?: Callback): Result; + getdelBuffer(key: RedisKey, callback?: Callback): Result; + /** + * Get the value of a key and optionally set its expiration + * - _group_: string + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + getex(key: RedisKey, callback?: Callback): Result; + getexBuffer(key: RedisKey, callback?: Callback): Result; + getex(key: RedisKey, secondsToken: "EX", seconds: number | string, callback?: Callback): Result; + getexBuffer(key: RedisKey, secondsToken: "EX", seconds: number | string, callback?: Callback): Result; + getex(key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, callback?: Callback): Result; + getexBuffer(key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, callback?: Callback): Result; + getex(key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, callback?: Callback): Result; + getexBuffer(key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, callback?: Callback): Result; + getex(key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, callback?: Callback): Result; + getexBuffer(key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, callback?: Callback): Result; + getex(key: RedisKey, persist: "PERSIST", callback?: Callback): Result; + getexBuffer(key: RedisKey, persist: "PERSIST", callback?: Callback): Result; + /** + * Get a substring of the string stored at a key + * - _group_: string + * - _complexity_: O(N) where N is the length of the returned string. The complexity is ultimately determined by the returned length, but because creating a substring from an existing string is very cheap, it can be considered O(1) for small strings. + * - _since_: 2.4.0 + */ + getrange(key: RedisKey, start: number | string, end: number | string, callback?: Callback): Result; + getrangeBuffer(key: RedisKey, start: number | string, end: number | string, callback?: Callback): Result; + /** + * Set the string value of a key and return its old value + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + getset(key: RedisKey, value: string | Buffer | number, callback?: Callback): Result; + getsetBuffer(key: RedisKey, value: string | Buffer | number, callback?: Callback): Result; + /** + * Delete one or more hash fields + * - _group_: hash + * - _complexity_: O(N) where N is the number of fields to be removed. + * - _since_: 2.0.0 + */ + hdel(...args: [ + key: RedisKey, + ...fields: (string | Buffer)[], + callback: Callback + ]): Result; + hdel(...args: [key: RedisKey, ...fields: (string | Buffer)[]]): Result; + /** + * Handshake with Redis + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 6.0.0 + */ + hello(callback?: Callback): Result; + hello(protover: number | string, callback?: Callback): Result; + hello(protover: number | string, clientnameToken: "SETNAME", clientname: string | Buffer, callback?: Callback): Result; + hello(protover: number | string, usernamePasswordToken: "AUTH", username: string | Buffer, password: string | Buffer, callback?: Callback): Result; + hello(protover: number | string, usernamePasswordToken: "AUTH", username: string | Buffer, password: string | Buffer, clientnameToken: "SETNAME", clientname: string | Buffer, callback?: Callback): Result; + /** + * Determine if a hash field exists + * - _group_: hash + * - _complexity_: O(1) + * - _since_: 2.0.0 + */ + hexists(key: RedisKey, field: string | Buffer, callback?: Callback): Result; + /** + * Set expiry for hash field using relative time to expire (seconds) + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hexpire(...args: [key: RedisKey, seconds: number | string, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, nx: 'NX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, nx: 'NX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, xx: 'XX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, xx: 'XX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, gt: 'GT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, gt: 'GT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, lt: 'LT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpire(...args: [key: RedisKey, seconds: number | string, lt: 'LT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Set expiry for hash field using an absolute Unix timestamp (seconds) + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, nx: 'NX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, nx: 'NX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, xx: 'XX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, xx: 'XX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, gt: 'GT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, gt: 'GT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, lt: 'LT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpireat(...args: [key: RedisKey, unixTimeSeconds: number | string, lt: 'LT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Returns the expiration time of a hash field as a Unix timestamp, in seconds. + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hexpiretime(...args: [key: RedisKey, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hexpiretime(...args: [key: RedisKey, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Get the value of a hash field + * - _group_: hash + * - _complexity_: O(1) + * - _since_: 2.0.0 + */ + hget(key: RedisKey, field: string | Buffer, callback?: Callback): Result; + hgetBuffer(key: RedisKey, field: string | Buffer, callback?: Callback): Result; + /** + * Get all the fields and values in a hash + * - _group_: hash + * - _complexity_: O(N) where N is the size of the hash. + * - _since_: 2.0.0 + */ + hgetall(key: RedisKey, callback?: Callback>): Result, Context>; + hgetallBuffer(key: RedisKey, callback?: Callback>): Result, Context>; + /** + * Returns the value of a field and deletes it from the hash. + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 8.0.0 + */ + hgetdel(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + hgetdelBuffer(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + hgetdel(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hgetdelBuffer(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + /** + * Get the value of one or more fields of a given hash key, and optionally set their expiration. + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 8.0.0 + */ + hgetex(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, persist: "PERSIST", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, persist: "PERSIST", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + hgetex(...args: [key: RedisKey, persist: "PERSIST", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hgetexBuffer(...args: [key: RedisKey, persist: "PERSIST", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + /** + * Increment the integer value of a hash field by the given number + * - _group_: hash + * - _complexity_: O(1) + * - _since_: 2.0.0 + */ + hincrby(key: RedisKey, field: string | Buffer, increment: number | string, callback?: Callback): Result; + /** + * Increment the float value of a hash field by the given amount + * - _group_: hash + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + hincrbyfloat(key: RedisKey, field: string | Buffer, increment: number | string, callback?: Callback): Result; + hincrbyfloatBuffer(key: RedisKey, field: string | Buffer, increment: number | string, callback?: Callback): Result; + /** + * Get all the fields in a hash + * - _group_: hash + * - _complexity_: O(N) where N is the size of the hash. + * - _since_: 2.0.0 + */ + hkeys(key: RedisKey, callback?: Callback): Result; + hkeysBuffer(key: RedisKey, callback?: Callback): Result; + /** + * Get the number of fields in a hash + * - _group_: hash + * - _complexity_: O(1) + * - _since_: 2.0.0 + */ + hlen(key: RedisKey, callback?: Callback): Result; + /** + * Get the values of all the given hash fields + * - _group_: hash + * - _complexity_: O(N) where N is the number of fields being requested. + * - _since_: 2.0.0 + */ + hmget(...args: [ + key: RedisKey, + ...fields: (string | Buffer)[], + callback: Callback<(string | null)[]> + ]): Result<(string | null)[], Context>; + hmgetBuffer(...args: [ + key: RedisKey, + ...fields: (string | Buffer)[], + callback: Callback<(Buffer | null)[]> + ]): Result<(Buffer | null)[], Context>; + hmget(...args: [key: RedisKey, ...fields: (string | Buffer)[]]): Result<(string | null)[], Context>; + hmgetBuffer(...args: [key: RedisKey, ...fields: (string | Buffer)[]]): Result<(Buffer | null)[], Context>; + /** + * Set multiple hash fields to multiple values + * - _group_: hash + * - _complexity_: O(N) where N is the number of fields being set. + * - _since_: 2.0.0 + */ + hmset(key: RedisKey, object: object, callback?: Callback<"OK">): Result<"OK", Context>; + hmset(key: RedisKey, map: Map, callback?: Callback<"OK">): Result<"OK", Context>; + hmset(...args: [ + key: RedisKey, + ...fieldValues: (string | Buffer | number)[], + callback: Callback<"OK"> + ]): Result<"OK", Context>; + hmset(...args: [key: RedisKey, ...fieldValues: (string | Buffer | number)[]]): Result<"OK", Context>; + /** + * Removes the expiration time for each specified field + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hpersist(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpersist(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Set expiry for hash field using relative time to expire (milliseconds) + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hpexpire(...args: [key: RedisKey, milliseconds: number | string, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, nx: 'NX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, nx: 'NX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, xx: 'XX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, xx: 'XX', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, gt: 'GT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, gt: 'GT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, lt: 'LT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpire(...args: [key: RedisKey, milliseconds: number | string, lt: 'LT', fieldsToken: 'FIELDS', numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Set expiry for hash field using an absolute Unix timestamp (milliseconds) + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, nx: "NX", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, nx: "NX", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, xx: "XX", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, xx: "XX", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, gt: "GT", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, gt: "GT", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, lt: "LT", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpireat(...args: [key: RedisKey, unixTimeMilliseconds: number | string, lt: "LT", fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Returns the expiration time of a hash field as a Unix timestamp, in msec. + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hpexpiretime(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpexpiretime(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Returns the TTL in milliseconds of a hash field. + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + hpttl(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + hpttl(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Get one or multiple random fields from a hash + * - _group_: hash + * - _complexity_: O(N) where N is the number of fields returned + * - _since_: 6.2.0 + */ + hrandfield(key: RedisKey, callback?: Callback): Result; + hrandfieldBuffer(key: RedisKey, callback?: Callback): Result; + hrandfield(key: RedisKey, count: number | string, callback?: Callback): Result; + hrandfieldBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + hrandfield(key: RedisKey, count: number | string, withvalues: "WITHVALUES", callback?: Callback): Result; + hrandfieldBuffer(key: RedisKey, count: number | string, withvalues: "WITHVALUES", callback?: Callback): Result; + /** + * Incrementally iterate hash fields and associated values + * - _group_: hash + * - _complexity_: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection.. + * - _since_: 2.8.0 + */ + hscan(key: RedisKey, cursor: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + hscanBuffer(key: RedisKey, cursor: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + hscan(key: RedisKey, cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + hscanBuffer(key: RedisKey, cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + hscan(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + hscanBuffer(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + hscan(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + hscanBuffer(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + /** + * Set the string value of a hash field + * - _group_: hash + * - _complexity_: O(1) for each field/value pair added, so O(N) to add N field/value pairs when the command is called with multiple field/value pairs. + * - _since_: 2.0.0 + */ + hset(key: RedisKey, object: object, callback?: Callback): Result; + hset(key: RedisKey, map: Map, callback?: Callback): Result; + hset(...args: [ + key: RedisKey, + ...fieldValues: (string | Buffer | number)[], + callback: Callback + ]): Result; + hset(...args: [key: RedisKey, ...fieldValues: (string | Buffer | number)[]]): Result; + /** + * Set the value of one or more fields of a given hash key, and optionally set their expiration. + * - _group_: hash + * - _complexity_: O(N) where N is the number of fields being set. + * - _since_: 8.0.0 + */ + hsetex(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, keepttl: "KEEPTTL", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, keepttl: "KEEPTTL", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", keepttl: "KEEPTTL", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fnx: "FNX", keepttl: "KEEPTTL", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", secondsToken: "EX", seconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", millisecondsToken: "PX", milliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", keepttl: "KEEPTTL", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[], callback: Callback]): Result; + hsetex(...args: [key: RedisKey, fxx: "FXX", keepttl: "KEEPTTL", fieldsToken: "FIELDS", numfields: number | string, ...data: (string | Buffer | number)[]]): Result; + /** + * Set the value of a hash field, only if the field does not exist + * - _group_: hash + * - _complexity_: O(1) + * - _since_: 2.0.0 + */ + hsetnx(key: RedisKey, field: string | Buffer, value: string | Buffer | number, callback?: Callback): Result; + /** + * Get the length of the value of a hash field + * - _group_: hash + * - _complexity_: O(1) + * - _since_: 3.2.0 + */ + hstrlen(key: RedisKey, field: string | Buffer, callback?: Callback): Result; + /** + * Returns the TTL in seconds of a hash field. + * - _group_: hash + * - _complexity_: O(N) where N is the number of specified fields + * - _since_: 7.4.0 + */ + httl(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[], callback: Callback]): Result; + httl(...args: [key: RedisKey, fieldsToken: "FIELDS", numfields: number | string, ...fields: (string | Buffer)[]]): Result; + /** + * Get all the values in a hash + * - _group_: hash + * - _complexity_: O(N) where N is the size of the hash. + * - _since_: 2.0.0 + */ + hvals(key: RedisKey, callback?: Callback): Result; + hvalsBuffer(key: RedisKey, callback?: Callback): Result; + /** + * Increment the integer value of a key by one + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + incr(key: RedisKey, callback?: Callback): Result; + /** + * Increment the integer value of a key by the given amount + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + incrby(key: RedisKey, increment: number | string, callback?: Callback): Result; + /** + * Increment the float value of a key by the given amount + * - _group_: string + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + incrbyfloat(key: RedisKey, increment: number | string, callback?: Callback): Result; + /** + * Get information and statistics about the server + * - _group_: server + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + info(callback?: Callback): Result; + info(...args: [...sections: (string | Buffer)[], callback: Callback]): Result; + info(...args: [...sections: (string | Buffer)[]]): Result; + /** + * Find all keys matching the given pattern + * - _group_: generic + * - _complexity_: O(N) with N being the number of keys in the database, under the assumption that the key names in the database and the given pattern have limited length. + * - _since_: 1.0.0 + */ + keys(pattern: string, callback?: Callback): Result; + keysBuffer(pattern: string, callback?: Callback): Result; + /** + * Get the UNIX time stamp of the last successful save to disk + * - _group_: server + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + lastsave(callback?: Callback): Result; + /** + * Return a human readable latency analysis report. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.13 + */ + latency(subcommand: "DOCTOR", callback?: Callback): Result; + /** + * Return a latency graph for the event. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.13 + */ + latency(subcommand: "GRAPH", event: string | Buffer, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.13 + */ + latency(subcommand: "HELP", callback?: Callback): Result; + /** + * Return the cumulative distribution of latencies of a subset of commands or all. + * - _group_: server + * - _complexity_: O(N) where N is the number of commands with latency information being retrieved. + * - _since_: 7.0.0 + */ + latency(subcommand: "HISTOGRAM", callback?: Callback): Result; + latency(...args: [ + subcommand: "HISTOGRAM", + ...commands: (string | Buffer)[], + callback: Callback + ]): Result; + latency(...args: [subcommand: "HISTOGRAM", ...commands: (string | Buffer)[]]): Result; + /** + * Return timestamp-latency samples for the event. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.13 + */ + latency(subcommand: "HISTORY", event: string | Buffer, callback?: Callback): Result; + /** + * Return the latest latency samples for all events. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.13 + */ + latency(subcommand: "LATEST", callback?: Callback): Result; + /** + * Reset latency data for one or more events. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.13 + */ + latency(subcommand: "RESET", callback?: Callback): Result; + latency(...args: [ + subcommand: "RESET", + ...events: (string | Buffer)[], + callback: Callback + ]): Result; + latency(...args: [subcommand: "RESET", ...events: (string | Buffer)[]]): Result; + /** + * Find longest common substring + * - _group_: string + * - _complexity_: O(N*M) where N and M are the lengths of s1 and s2, respectively + * - _since_: 7.0.0 + */ + lcs(key1: RedisKey, key2: RedisKey, callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, lenToken: "MINMATCHLEN", len: number | string, callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, lenToken: "MINMATCHLEN", len: number | string, withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, idx: "IDX", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, idx: "IDX", withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, idx: "IDX", lenToken: "MINMATCHLEN", len: number | string, callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, idx: "IDX", lenToken: "MINMATCHLEN", len: number | string, withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", lenToken: "MINMATCHLEN", len1: number | string, callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", lenToken: "MINMATCHLEN", len1: number | string, withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", idx: "IDX", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", idx: "IDX", withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", idx: "IDX", lenToken: "MINMATCHLEN", len1: number | string, callback?: Callback): Result; + lcs(key1: RedisKey, key2: RedisKey, len: "LEN", idx: "IDX", lenToken: "MINMATCHLEN", len1: number | string, withmatchlen: "WITHMATCHLEN", callback?: Callback): Result; + /** + * Get an element from a list by its index + * - _group_: list + * - _complexity_: O(N) where N is the number of elements to traverse to get to the element at index. This makes asking for the first or the last element of the list O(1). + * - _since_: 1.0.0 + */ + lindex(key: RedisKey, index: number | string, callback?: Callback): Result; + lindexBuffer(key: RedisKey, index: number | string, callback?: Callback): Result; + /** + * Insert an element before or after another element in a list + * - _group_: list + * - _complexity_: O(N) where N is the number of elements to traverse before seeing the value pivot. This means that inserting somewhere on the left end on the list (head) can be considered O(1) and inserting somewhere on the right end (tail) is O(N). + * - _since_: 2.2.0 + */ + linsert(key: RedisKey, before: "BEFORE", pivot: string | Buffer | number, element: string | Buffer | number, callback?: Callback): Result; + linsert(key: RedisKey, after: "AFTER", pivot: string | Buffer | number, element: string | Buffer | number, callback?: Callback): Result; + /** + * Get the length of a list + * - _group_: list + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + llen(key: RedisKey, callback?: Callback): Result; + /** + * Pop an element from a list, push it to another list and return it + * - _group_: list + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + lmove(source: RedisKey, destination: RedisKey, left: "LEFT", left1: "LEFT", callback?: Callback): Result; + lmoveBuffer(source: RedisKey, destination: RedisKey, left: "LEFT", left1: "LEFT", callback?: Callback): Result; + lmove(source: RedisKey, destination: RedisKey, left: "LEFT", right: "RIGHT", callback?: Callback): Result; + lmoveBuffer(source: RedisKey, destination: RedisKey, left: "LEFT", right: "RIGHT", callback?: Callback): Result; + lmove(source: RedisKey, destination: RedisKey, right: "RIGHT", left: "LEFT", callback?: Callback): Result; + lmoveBuffer(source: RedisKey, destination: RedisKey, right: "RIGHT", left: "LEFT", callback?: Callback): Result; + lmove(source: RedisKey, destination: RedisKey, right: "RIGHT", right1: "RIGHT", callback?: Callback): Result; + lmoveBuffer(source: RedisKey, destination: RedisKey, right: "RIGHT", right1: "RIGHT", callback?: Callback): Result; + /** + * Pop elements from a list + * - _group_: list + * - _complexity_: O(N+M) where N is the number of provided keys and M is the number of elements returned. + * - _since_: 7.0.0 + */ + lmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [numkeys: number | string, ...keys: RedisKey[], left: "LEFT"]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [numkeys: number | string, ...keys: RedisKey[], left: "LEFT"]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [numkeys: number | string, keys: RedisKey[], left: "LEFT"]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [numkeys: number | string, keys: RedisKey[], left: "LEFT"]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + left: "LEFT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [numkeys: number | string, ...keys: RedisKey[], right: "RIGHT"]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [numkeys: number | string, ...keys: RedisKey[], right: "RIGHT"]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [numkeys: number | string, keys: RedisKey[], right: "RIGHT"]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [numkeys: number | string, keys: RedisKey[], right: "RIGHT"]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: string, members: string[]] | null> + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string, + callback: Callback<[key: Buffer, members: Buffer[]] | null> + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + lmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: string, members: string[]] | null, Context>; + lmpopBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + right: "RIGHT", + countToken: "COUNT", + count: number | string + ]): Result<[key: Buffer, members: Buffer[]] | null, Context>; + /** + * Display some computer art and the Redis version + * - _group_: server + * - _complexity_: undefined + * - _since_: 5.0.0 + */ + lolwut(callback?: Callback): Result; + lolwut(versionToken: "VERSION", version: number | string, callback?: Callback): Result; + /** + * Remove and get the first elements in a list + * - _group_: list + * - _complexity_: O(N) where N is the number of elements returned + * - _since_: 1.0.0 + */ + lpop(key: RedisKey, callback?: Callback): Result; + lpopBuffer(key: RedisKey, callback?: Callback): Result; + lpop(key: RedisKey, count: number | string, callback?: Callback): Result; + lpopBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + /** + * Return the index of matching elements on a list + * - _group_: list + * - _complexity_: O(N) where N is the number of elements in the list, for the average case. When searching for elements near the head or the tail of the list, or when the MAXLEN option is provided, the command may run in constant time. + * - _since_: 6.0.6 + */ + lpos(key: RedisKey, element: string | Buffer | number, callback?: Callback): Result; + lpos(key: RedisKey, element: string | Buffer | number, lenToken: "MAXLEN", len: number | string, callback?: Callback): Result; + lpos(key: RedisKey, element: string | Buffer | number, numMatchesToken: "COUNT", numMatches: number | string, callback?: Callback): Result; + lpos(key: RedisKey, element: string | Buffer | number, numMatchesToken: "COUNT", numMatches: number | string, lenToken: "MAXLEN", len: number | string, callback?: Callback): Result; + lpos(key: RedisKey, element: string | Buffer | number, rankToken: "RANK", rank: number | string, callback?: Callback): Result; + lpos(key: RedisKey, element: string | Buffer | number, rankToken: "RANK", rank: number | string, lenToken: "MAXLEN", len: number | string, callback?: Callback): Result; + lpos(key: RedisKey, element: string | Buffer | number, rankToken: "RANK", rank: number | string, numMatchesToken: "COUNT", numMatches: number | string, callback?: Callback): Result; + lpos(key: RedisKey, element: string | Buffer | number, rankToken: "RANK", rank: number | string, numMatchesToken: "COUNT", numMatches: number | string, lenToken: "MAXLEN", len: number | string, callback?: Callback): Result; + /** + * Prepend one or multiple elements to a list + * - _group_: list + * - _complexity_: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments. + * - _since_: 1.0.0 + */ + lpush(...args: [ + key: RedisKey, + ...elements: (string | Buffer | number)[], + callback: Callback + ]): Result; + lpush(...args: [key: RedisKey, ...elements: (string | Buffer | number)[]]): Result; + /** + * Prepend an element to a list, only if the list exists + * - _group_: list + * - _complexity_: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments. + * - _since_: 2.2.0 + */ + lpushx(...args: [ + key: RedisKey, + ...elements: (string | Buffer | number)[], + callback: Callback + ]): Result; + lpushx(...args: [key: RedisKey, ...elements: (string | Buffer | number)[]]): Result; + /** + * Get a range of elements from a list + * - _group_: list + * - _complexity_: O(S+N) where S is the distance of start offset from HEAD for small lists, from nearest end (HEAD or TAIL) for large lists; and N is the number of elements in the specified range. + * - _since_: 1.0.0 + */ + lrange(key: RedisKey, start: number | string, stop: number | string, callback?: Callback): Result; + lrangeBuffer(key: RedisKey, start: number | string, stop: number | string, callback?: Callback): Result; + /** + * Remove elements from a list + * - _group_: list + * - _complexity_: O(N+M) where N is the length of the list and M is the number of elements removed. + * - _since_: 1.0.0 + */ + lrem(key: RedisKey, count: number | string, element: string | Buffer | number, callback?: Callback): Result; + /** + * Set the value of an element in a list by its index + * - _group_: list + * - _complexity_: O(N) where N is the length of the list. Setting either the first or the last element of the list is O(1). + * - _since_: 1.0.0 + */ + lset(key: RedisKey, index: number | string, element: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Trim a list to the specified range + * - _group_: list + * - _complexity_: O(N) where N is the number of elements to be removed by the operation. + * - _since_: 1.0.0 + */ + ltrim(key: RedisKey, start: number | string, stop: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Outputs memory problems report + * - _group_: server + * - _complexity_: O(1) + * - _since_: 4.0.0 + */ + memory(subcommand: "DOCTOR", callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: server + * - _complexity_: O(1) + * - _since_: 4.0.0 + */ + memory(subcommand: "HELP", callback?: Callback): Result; + /** + * Show allocator internal stats + * - _group_: server + * - _complexity_: Depends on how much memory is allocated, could be slow + * - _since_: 4.0.0 + */ + memory(subcommand: "MALLOC-STATS", callback?: Callback): Result; + /** + * Ask the allocator to release memory + * - _group_: server + * - _complexity_: Depends on how much memory is allocated, could be slow + * - _since_: 4.0.0 + */ + memory(subcommand: "PURGE", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Show memory usage details + * - _group_: server + * - _complexity_: O(1) + * - _since_: 4.0.0 + */ + memory(subcommand: "STATS", callback?: Callback): Result; + /** + * Estimate the memory usage of a key + * - _group_: server + * - _complexity_: O(N) where N is the number of samples. + * - _since_: 4.0.0 + */ + memory(subcommand: "USAGE", key: RedisKey, callback?: Callback): Result; + memory(subcommand: "USAGE", key: RedisKey, countToken: "SAMPLES", count: number | string, callback?: Callback): Result; + /** + * Get the values of all the given keys + * - _group_: string + * - _complexity_: O(N) where N is the number of keys to retrieve. + * - _since_: 1.0.0 + */ + mget(...args: [...keys: RedisKey[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + mgetBuffer(...args: [...keys: RedisKey[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + mget(...args: [keys: RedisKey[], callback: Callback<(string | null)[]>]): Result<(string | null)[], Context>; + mgetBuffer(...args: [keys: RedisKey[], callback: Callback<(Buffer | null)[]>]): Result<(Buffer | null)[], Context>; + mget(...args: [...keys: RedisKey[]]): Result<(string | null)[], Context>; + mgetBuffer(...args: [...keys: RedisKey[]]): Result<(Buffer | null)[], Context>; + mget(...args: [keys: RedisKey[]]): Result<(string | null)[], Context>; + mgetBuffer(...args: [keys: RedisKey[]]): Result<(Buffer | null)[], Context>; + /** + * Atomically transfer a key from a Redis instance to another one. + * - _group_: generic + * - _complexity_: This command actually executes a DUMP+DEL in the source instance, and a RESTORE in the target instance. See the pages of these commands for time complexity. Also an O(N) data transfer between the two instances is performed. + * - _since_: 2.6.0 + */ + migrate(...args: [ + host: string | Buffer, + port: number | string, + ...args: RedisValue[], + callback: Callback<"OK"> + ]): Result<"OK", Context>; + migrate(...args: [ + host: string | Buffer, + port: number | string, + ...args: RedisValue[] + ]): Result<"OK", Context>; + /** + * Show helpful text about the different subcommands + * - _group_: server + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + module(subcommand: "HELP", callback?: Callback): Result; + /** + * List all modules loaded by the server + * - _group_: server + * - _complexity_: O(N) where N is the number of loaded modules. + * - _since_: 4.0.0 + */ + module(subcommand: "LIST", callback?: Callback): Result; + /** + * Load a module + * - _group_: server + * - _complexity_: O(1) + * - _since_: 4.0.0 + */ + module(subcommand: "LOAD", path: string | Buffer, callback?: Callback): Result; + module(...args: [ + subcommand: "LOAD", + path: string | Buffer, + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + module(...args: [ + subcommand: "LOAD", + path: string | Buffer, + ...args: (string | Buffer | number)[] + ]): Result; + /** + * Load a module with extended parameters + * - _group_: server + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + module(subcommand: "LOADEX", path: string | Buffer, callback?: Callback): Result; + module(...args: [ + subcommand: "LOADEX", + path: string | Buffer, + argsToken: "ARGS", + ...args: (string | Buffer | number)[], + callback: Callback + ]): Result; + module(...args: [ + subcommand: "LOADEX", + path: string | Buffer, + argsToken: "ARGS", + ...args: (string | Buffer | number)[] + ]): Result; + module(...args: [ + subcommand: "LOADEX", + path: string | Buffer, + configsToken: "CONFIG", + ...configs: (string | Buffer | number)[], + callback: Callback + ]): Result; + module(...args: [ + subcommand: "LOADEX", + path: string | Buffer, + configsToken: "CONFIG", + ...configs: (string | Buffer | number)[] + ]): Result; + module(...args: [ + subcommand: "LOADEX", + path: string | Buffer, + configsToken: "CONFIG", + ...args: RedisValue[], + callback: Callback + ]): Result; + module(...args: [ + subcommand: "LOADEX", + path: string | Buffer, + configsToken: "CONFIG", + ...args: RedisValue[] + ]): Result; + /** + * Unload a module + * - _group_: server + * - _complexity_: O(1) + * - _since_: 4.0.0 + */ + module(subcommand: "UNLOAD", name: string | Buffer, callback?: Callback): Result; + /** + * Move a key to another database + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + move(key: RedisKey, db: number | string, callback?: Callback): Result; + /** + * Set multiple keys to multiple values + * - _group_: string + * - _complexity_: O(N) where N is the number of keys to set. + * - _since_: 1.0.1 + */ + mset(object: object, callback?: Callback<"OK">): Result<"OK", Context>; + mset(map: Map, callback?: Callback<"OK">): Result<"OK", Context>; + mset(...args: [ + ...keyValues: (RedisKey | string | Buffer | number)[], + callback: Callback<"OK"> + ]): Result<"OK", Context>; + mset(...args: [...keyValues: (RedisKey | string | Buffer | number)[]]): Result<"OK", Context>; + /** + * Set multiple keys to multiple values, only if none of the keys exist + * - _group_: string + * - _complexity_: O(N) where N is the number of keys to set. + * - _since_: 1.0.1 + */ + msetnx(object: object, callback?: Callback<"OK">): Result<"OK", Context>; + msetnx(map: Map, callback?: Callback<"OK">): Result<"OK", Context>; + msetnx(...args: [ + ...keyValues: (RedisKey | string | Buffer | number)[], + callback: Callback + ]): Result; + msetnx(...args: [...keyValues: (RedisKey | string | Buffer | number)[]]): Result; + /** + * Inspect the internal encoding of a Redis object + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 2.2.3 + */ + object(subcommand: "ENCODING", key: RedisKey, callback?: Callback): Result; + /** + * Get the logarithmic access frequency counter of a Redis object + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 4.0.0 + */ + object(subcommand: "FREQ", key: RedisKey, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + object(subcommand: "HELP", callback?: Callback): Result; + /** + * Get the time since a Redis object was last accessed + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 2.2.3 + */ + object(subcommand: "IDLETIME", key: RedisKey, callback?: Callback): Result; + /** + * Get the number of references to the value of the key + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 2.2.3 + */ + object(subcommand: "REFCOUNT", key: RedisKey, callback?: Callback): Result; + /** + * Remove the expiration from a key + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 2.2.0 + */ + persist(key: RedisKey, callback?: Callback): Result; + /** + * Set a key's time to live in milliseconds + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + pexpire(key: RedisKey, milliseconds: number | string, callback?: Callback): Result; + pexpire(key: RedisKey, milliseconds: number | string, nx: "NX", callback?: Callback): Result; + pexpire(key: RedisKey, milliseconds: number | string, xx: "XX", callback?: Callback): Result; + pexpire(key: RedisKey, milliseconds: number | string, gt: "GT", callback?: Callback): Result; + pexpire(key: RedisKey, milliseconds: number | string, lt: "LT", callback?: Callback): Result; + /** + * Set the expiration for a key as a UNIX timestamp specified in milliseconds + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + pexpireat(key: RedisKey, unixTimeMilliseconds: number | string, callback?: Callback): Result; + pexpireat(key: RedisKey, unixTimeMilliseconds: number | string, nx: "NX", callback?: Callback): Result; + pexpireat(key: RedisKey, unixTimeMilliseconds: number | string, xx: "XX", callback?: Callback): Result; + pexpireat(key: RedisKey, unixTimeMilliseconds: number | string, gt: "GT", callback?: Callback): Result; + pexpireat(key: RedisKey, unixTimeMilliseconds: number | string, lt: "LT", callback?: Callback): Result; + /** + * Get the expiration Unix timestamp for a key in milliseconds + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 7.0.0 + */ + pexpiretime(key: RedisKey, callback?: Callback): Result; + /** + * Adds the specified elements to the specified HyperLogLog. + * - _group_: hyperloglog + * - _complexity_: O(1) to add every element. + * - _since_: 2.8.9 + */ + pfadd(key: RedisKey, callback?: Callback): Result; + pfadd(...args: [ + key: RedisKey, + ...elements: (string | Buffer | number)[], + callback: Callback + ]): Result; + pfadd(...args: [key: RedisKey, ...elements: (string | Buffer | number)[]]): Result; + /** + * Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s). + * - _group_: hyperloglog + * - _complexity_: O(1) with a very small average constant time when called with a single key. O(N) with N being the number of keys, and much bigger constant times, when called with multiple keys. + * - _since_: 2.8.9 + */ + pfcount(...args: [...keys: RedisKey[], callback: Callback]): Result; + pfcount(...args: [keys: RedisKey[], callback: Callback]): Result; + pfcount(...args: [...keys: RedisKey[]]): Result; + pfcount(...args: [keys: RedisKey[]]): Result; + /** + * Internal commands for debugging HyperLogLog values + * - _group_: hyperloglog + * - _complexity_: N/A + * - _since_: 2.8.9 + */ + pfdebug(subcommand: string | Buffer, key: RedisKey, callback?: Callback): Result; + /** + * Merge N different HyperLogLogs into a single one. + * - _group_: hyperloglog + * - _complexity_: O(N) to merge N HyperLogLogs, but with high constant times. + * - _since_: 2.8.9 + */ + pfmerge(...args: [ + destkey: RedisKey, + ...sourcekeys: RedisKey[], + callback: Callback<"OK"> + ]): Result<"OK", Context>; + pfmerge(...args: [ + destkey: RedisKey, + sourcekeys: RedisKey[], + callback: Callback<"OK"> + ]): Result<"OK", Context>; + pfmerge(...args: [destkey: RedisKey, ...sourcekeys: RedisKey[]]): Result<"OK", Context>; + pfmerge(...args: [destkey: RedisKey, sourcekeys: RedisKey[]]): Result<"OK", Context>; + /** + * An internal command for testing HyperLogLog values + * - _group_: hyperloglog + * - _complexity_: N/A + * - _since_: 2.8.9 + */ + pfselftest(callback?: Callback): Result; + /** + * Ping the server + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + ping(callback?: Callback<"PONG">): Result<"PONG", Context>; + ping(message: string | Buffer, callback?: Callback): Result; + pingBuffer(message: string | Buffer, callback?: Callback): Result; + /** + * Set the value and expiration in milliseconds of a key + * - _group_: string + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + psetex(key: RedisKey, milliseconds: number | string, value: string | Buffer | number, callback?: Callback): Result; + /** + * Listen for messages published to channels matching the given patterns + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of patterns the client is already subscribed to. + * - _since_: 2.0.0 + */ + psubscribe(...args: [...patterns: string[], callback: Callback]): Result; + psubscribe(...args: [...patterns: string[]]): Result; + /** + * Internal command used for replication + * - _group_: server + * - _complexity_: undefined + * - _since_: 2.8.0 + */ + psync(replicationid: string | Buffer | number, offset: number | string, callback?: Callback): Result; + /** + * Get the time to live for a key in milliseconds + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + pttl(key: RedisKey, callback?: Callback): Result; + /** + * Post a message to a channel + * - _group_: pubsub + * - _complexity_: O(N+M) where N is the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client). + * - _since_: 2.0.0 + */ + publish(channel: string | Buffer, message: string | Buffer, callback?: Callback): Result; + /** + * List active channels + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of active channels, and assuming constant time pattern matching (relatively short channels and patterns) + * - _since_: 2.8.0 + */ + pubsub(subcommand: "CHANNELS", callback?: Callback): Result; + pubsub(subcommand: "CHANNELS", pattern: string, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: pubsub + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + pubsub(subcommand: "HELP", callback?: Callback): Result; + /** + * Get the count of unique patterns pattern subscriptions + * - _group_: pubsub + * - _complexity_: O(1) + * - _since_: 2.8.0 + */ + pubsub(subcommand: "NUMPAT", callback?: Callback): Result; + /** + * Get the count of subscribers for channels + * - _group_: pubsub + * - _complexity_: O(N) for the NUMSUB subcommand, where N is the number of requested channels + * - _since_: 2.8.0 + */ + pubsub(subcommand: "NUMSUB", callback?: Callback): Result; + pubsub(...args: [ + subcommand: "NUMSUB", + ...channels: (string | Buffer)[], + callback: Callback + ]): Result; + pubsub(...args: [subcommand: "NUMSUB", ...channels: (string | Buffer)[]]): Result; + /** + * List active shard channels + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of active shard channels, and assuming constant time pattern matching (relatively short shard channels). + * - _since_: 7.0.0 + */ + pubsub(subcommand: "SHARDCHANNELS", callback?: Callback): Result; + pubsub(subcommand: "SHARDCHANNELS", pattern: string, callback?: Callback): Result; + /** + * Get the count of subscribers for shard channels + * - _group_: pubsub + * - _complexity_: O(N) for the SHARDNUMSUB subcommand, where N is the number of requested shard channels + * - _since_: 7.0.0 + */ + pubsub(subcommand: "SHARDNUMSUB", callback?: Callback): Result; + pubsub(...args: [ + subcommand: "SHARDNUMSUB", + ...shardchannels: (string | Buffer)[], + callback: Callback + ]): Result; + pubsub(...args: [subcommand: "SHARDNUMSUB", ...shardchannels: (string | Buffer)[]]): Result; + /** + * Stop listening for messages posted to channels matching the given patterns + * - _group_: pubsub + * - _complexity_: O(N+M) where N is the number of patterns the client is already subscribed and M is the number of total patterns subscribed in the system (by any client). + * - _since_: 2.0.0 + */ + punsubscribe(callback?: Callback): Result; + punsubscribe(...args: [...patterns: string[], callback: Callback]): Result; + punsubscribe(...args: [...patterns: string[]]): Result; + /** + * Close the connection + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + quit(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Return a random key from the keyspace + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + randomkey(callback?: Callback): Result; + randomkeyBuffer(callback?: Callback): Result; + /** + * Enables read queries for a connection to a cluster replica node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + readonly(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Disables read queries for a connection to a cluster replica node + * - _group_: cluster + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + readwrite(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Rename a key + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + rename(key: RedisKey, newkey: RedisKey, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Rename a key, only if the new key does not exist + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + renamenx(key: RedisKey, newkey: RedisKey, callback?: Callback): Result; + /** + * An internal command for configuring the replication stream + * - _group_: server + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + replconf(callback?: Callback): Result; + /** + * Make the server a replica of another instance, or promote it as master. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + replicaof(host: string | Buffer, port: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Reset the connection + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + reset(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Create a key using the provided serialized value, previously obtained using DUMP. + * - _group_: generic + * - _complexity_: O(1) to create the new key and additional O(N*M) to reconstruct the serialized value, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1*M) where M is small, so simply O(1). However for sorted set values the complexity is O(N*M*log(N)) because inserting values into sorted sets is O(log(N)). + * - _since_: 2.6.0 + */ + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, secondsToken: "IDLETIME", seconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", secondsToken: "IDLETIME", seconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + restore(key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * An internal command for migrating keys in a cluster + * - _group_: server + * - _complexity_: O(1) to create the new key and additional O(N*M) to reconstruct the serialized value, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1*M) where M is small, so simply O(1). However for sorted set values the complexity is O(N*M*log(N)) because inserting values into sorted sets is O(log(N)). + * - _since_: 3.0.0 + */ + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, secondsToken: "IDLETIME", seconds: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", secondsToken: "IDLETIME", seconds: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, callback?: Callback): Result; + ["restore-asking"](key: RedisKey, ttl: number | string, serializedValue: string | Buffer | number, replace: "REPLACE", absttl: "ABSTTL", secondsToken: "IDLETIME", seconds: number | string, frequencyToken: "FREQ", frequency: number | string, callback?: Callback): Result; + /** + * Return the role of the instance in the context of replication + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.8.12 + */ + role(callback?: Callback): Result; + /** + * Remove and get the last elements in a list + * - _group_: list + * - _complexity_: O(N) where N is the number of elements returned + * - _since_: 1.0.0 + */ + rpop(key: RedisKey, callback?: Callback): Result; + rpopBuffer(key: RedisKey, callback?: Callback): Result; + rpop(key: RedisKey, count: number | string, callback?: Callback): Result; + rpopBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + /** + * Remove the last element in a list, prepend it to another list and return it + * - _group_: list + * - _complexity_: O(1) + * - _since_: 1.2.0 + */ + rpoplpush(source: RedisKey, destination: RedisKey, callback?: Callback): Result; + rpoplpushBuffer(source: RedisKey, destination: RedisKey, callback?: Callback): Result; + /** + * Append one or multiple elements to a list + * - _group_: list + * - _complexity_: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments. + * - _since_: 1.0.0 + */ + rpush(...args: [ + key: RedisKey, + ...elements: (string | Buffer | number)[], + callback: Callback + ]): Result; + rpush(...args: [key: RedisKey, ...elements: (string | Buffer | number)[]]): Result; + /** + * Append an element to a list, only if the list exists + * - _group_: list + * - _complexity_: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments. + * - _since_: 2.2.0 + */ + rpushx(...args: [ + key: RedisKey, + ...elements: (string | Buffer | number)[], + callback: Callback + ]): Result; + rpushx(...args: [key: RedisKey, ...elements: (string | Buffer | number)[]]): Result; + /** + * Add one or more members to a set + * - _group_: set + * - _complexity_: O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments. + * - _since_: 1.0.0 + */ + sadd(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback + ]): Result; + sadd(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback + ]): Result; + sadd(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result; + sadd(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result; + /** + * Synchronously save the dataset to disk + * - _group_: server + * - _complexity_: O(N) where N is the total number of keys in all databases + * - _since_: 1.0.0 + */ + save(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Incrementally iterate the keys space + * - _group_: generic + * - _complexity_: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection. + * - _since_: 2.8.0 + */ + scan(cursor: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + scan(cursor: number | string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + scan(cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + scan(cursor: number | string, countToken: "COUNT", count: number | string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, countToken: "COUNT", count: number | string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + scan(cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + scan(cursor: number | string, patternToken: "MATCH", pattern: string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, patternToken: "MATCH", pattern: string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + scan(cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + scan(cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + scanBuffer(cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, typeToken: "TYPE", type: string | Buffer, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + /** + * Get the number of members in a set + * - _group_: set + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + scard(key: RedisKey, callback?: Callback): Result; + /** + * Set the debug mode for executed scripts. + * - _group_: scripting + * - _complexity_: O(1) + * - _since_: 3.2.0 + */ + script(subcommand: "DEBUG", yes: "YES", callback?: Callback): Result; + script(subcommand: "DEBUG", sync: "SYNC", callback?: Callback): Result; + script(subcommand: "DEBUG", no: "NO", callback?: Callback): Result; + /** + * Check existence of scripts in the script cache. + * - _group_: scripting + * - _complexity_: O(N) with N being the number of scripts to check (so checking a single script is an O(1) operation). + * - _since_: 2.6.0 + */ + script(...args: [ + subcommand: "EXISTS", + ...sha1s: (string | Buffer)[], + callback: Callback + ]): Result; + script(...args: [subcommand: "EXISTS", ...sha1s: (string | Buffer)[]]): Result; + /** + * Remove all the scripts from the script cache. + * - _group_: scripting + * - _complexity_: O(N) with N being the number of scripts in cache + * - _since_: 2.6.0 + */ + script(subcommand: "FLUSH", callback?: Callback): Result; + script(subcommand: "FLUSH", async: "ASYNC", callback?: Callback): Result; + script(subcommand: "FLUSH", sync: "SYNC", callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: scripting + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + script(subcommand: "HELP", callback?: Callback): Result; + /** + * Kill the script currently in execution. + * - _group_: scripting + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + script(subcommand: "KILL", callback?: Callback): Result; + /** + * Load the specified Lua script into the script cache. + * - _group_: scripting + * - _complexity_: O(N) with N being the length in bytes of the script body. + * - _since_: 2.6.0 + */ + script(subcommand: "LOAD", script: string | Buffer, callback?: Callback): Result; + /** + * Subtract multiple sets + * - _group_: set + * - _complexity_: O(N) where N is the total number of elements in all given sets. + * - _since_: 1.0.0 + */ + sdiff(...args: [...keys: RedisKey[], callback: Callback]): Result; + sdiffBuffer(...args: [...keys: RedisKey[], callback: Callback]): Result; + sdiff(...args: [keys: RedisKey[], callback: Callback]): Result; + sdiffBuffer(...args: [keys: RedisKey[], callback: Callback]): Result; + sdiff(...args: [...keys: RedisKey[]]): Result; + sdiffBuffer(...args: [...keys: RedisKey[]]): Result; + sdiff(...args: [keys: RedisKey[]]): Result; + sdiffBuffer(...args: [keys: RedisKey[]]): Result; + /** + * Subtract multiple sets and store the resulting set in a key + * - _group_: set + * - _complexity_: O(N) where N is the total number of elements in all given sets. + * - _since_: 1.0.0 + */ + sdiffstore(...args: [ + destination: RedisKey, + ...keys: RedisKey[], + callback: Callback + ]): Result; + sdiffstore(...args: [ + destination: RedisKey, + keys: RedisKey[], + callback: Callback + ]): Result; + sdiffstore(...args: [destination: RedisKey, ...keys: RedisKey[]]): Result; + sdiffstore(...args: [destination: RedisKey, keys: RedisKey[]]): Result; + /** + * Change the selected database for the current connection + * - _group_: connection + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + select(index: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Set the string value of a key + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + set(key: RedisKey, value: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + set(key: RedisKey, value: string | Buffer | number, get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, nx: "NX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, nx: "NX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, nx: "NX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, xx: "XX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, xx: "XX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, xx: "XX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + set(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, nx: "NX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, xx: "XX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, secondsToken: "EX", seconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + set(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, nx: "NX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, xx: "XX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, millisecondsToken: "PX", milliseconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + set(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, nx: "NX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, xx: "XX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, unixTimeSecondsToken: "EXAT", unixTimeSeconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + set(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, nx: "NX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, nx: "NX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, xx: "XX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, unixTimeMillisecondsToken: "PXAT", unixTimeMilliseconds: number | string, xx: "XX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", callback?: Callback<"OK">): Result<"OK", Context>; + set(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", nx: "NX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", nx: "NX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", nx: "NX", get: "GET", callback?: Callback): Result; + set(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", xx: "XX", callback?: Callback<"OK" | null>): Result<"OK" | null, Context>; + set(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", xx: "XX", get: "GET", callback?: Callback): Result; + setBuffer(key: RedisKey, value: string | Buffer | number, keepttl: "KEEPTTL", xx: "XX", get: "GET", callback?: Callback): Result; + /** + * Sets or clears the bit at offset in the string value stored at key + * - _group_: bitmap + * - _complexity_: O(1) + * - _since_: 2.2.0 + */ + setbit(key: RedisKey, offset: number | string, value: number | string, callback?: Callback): Result; + /** + * Set the value and expiration of a key + * - _group_: string + * - _complexity_: O(1) + * - _since_: 2.0.0 + */ + setex(key: RedisKey, seconds: number | string, value: string | Buffer | number, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Set the value of a key, only if the key does not exist + * - _group_: string + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + setnx(key: RedisKey, value: string | Buffer | number, callback?: Callback): Result; + /** + * Overwrite part of a string at key starting at the specified offset + * - _group_: string + * - _complexity_: O(1), not counting the time taken to copy the new string in place. Usually, this string is very small so the amortized complexity is O(1). Otherwise, complexity is O(M) with M being the length of the value argument. + * - _since_: 2.2.0 + */ + setrange(key: RedisKey, offset: number | string, value: string | Buffer | number, callback?: Callback): Result; + /** + * Synchronously save the dataset to disk and then shut down the server + * - _group_: server + * - _complexity_: O(N) when saving, where N is the total number of keys in all databases when saving data, otherwise O(1) + * - _since_: 1.0.0 + */ + shutdown(callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(force: "FORCE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(now: "NOW", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(now: "NOW", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(now: "NOW", force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(now: "NOW", force: "FORCE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", force: "FORCE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", now: "NOW", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", now: "NOW", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", now: "NOW", force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(nosave: "NOSAVE", now: "NOW", force: "FORCE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", force: "FORCE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", now: "NOW", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", now: "NOW", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", now: "NOW", force: "FORCE", callback?: Callback<"OK">): Result<"OK", Context>; + shutdown(save: "SAVE", now: "NOW", force: "FORCE", abort: "ABORT", callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Intersect multiple sets + * - _group_: set + * - _complexity_: O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets. + * - _since_: 1.0.0 + */ + sinter(...args: [...keys: RedisKey[], callback: Callback]): Result; + sinterBuffer(...args: [...keys: RedisKey[], callback: Callback]): Result; + sinter(...args: [keys: RedisKey[], callback: Callback]): Result; + sinterBuffer(...args: [keys: RedisKey[], callback: Callback]): Result; + sinter(...args: [...keys: RedisKey[]]): Result; + sinterBuffer(...args: [...keys: RedisKey[]]): Result; + sinter(...args: [keys: RedisKey[]]): Result; + sinterBuffer(...args: [keys: RedisKey[]]): Result; + /** + * Intersect multiple sets and return the cardinality of the result + * - _group_: set + * - _complexity_: O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets. + * - _since_: 7.0.0 + */ + sintercard(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + sintercard(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + sintercard(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + sintercard(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + sintercard(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string, + callback: Callback + ]): Result; + sintercard(...args: [ + numkeys: number | string, + keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string, + callback: Callback + ]): Result; + sintercard(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string + ]): Result; + sintercard(...args: [ + numkeys: number | string, + keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string + ]): Result; + /** + * Intersect multiple sets and store the resulting set in a key + * - _group_: set + * - _complexity_: O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets. + * - _since_: 1.0.0 + */ + sinterstore(...args: [ + destination: RedisKey, + ...keys: RedisKey[], + callback: Callback + ]): Result; + sinterstore(...args: [ + destination: RedisKey, + keys: RedisKey[], + callback: Callback + ]): Result; + sinterstore(...args: [destination: RedisKey, ...keys: RedisKey[]]): Result; + sinterstore(...args: [destination: RedisKey, keys: RedisKey[]]): Result; + /** + * Determine if a given value is a member of a set + * - _group_: set + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + sismember(key: RedisKey, member: string | Buffer | number, callback?: Callback): Result; + /** + * Make the server a replica of another instance, or promote it as master. + * - _group_: server + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + slaveof(host: string | Buffer, port: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Get the slow log's entries + * - _group_: server + * - _complexity_: O(N) where N is the number of entries returned + * - _since_: 2.2.12 + */ + slowlog(subcommand: "GET", callback?: Callback): Result; + slowlog(subcommand: "GET", count: number | string, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: server + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + slowlog(subcommand: "HELP", callback?: Callback): Result; + /** + * Get the slow log's length + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.2.12 + */ + slowlog(subcommand: "LEN", callback?: Callback): Result; + /** + * Clear all entries from the slow log + * - _group_: server + * - _complexity_: O(N) where N is the number of entries in the slowlog + * - _since_: 2.2.12 + */ + slowlog(subcommand: "RESET", callback?: Callback): Result; + /** + * Get all the members in a set + * - _group_: set + * - _complexity_: O(N) where N is the set cardinality. + * - _since_: 1.0.0 + */ + smembers(key: RedisKey, callback?: Callback): Result; + smembersBuffer(key: RedisKey, callback?: Callback): Result; + /** + * Returns the membership associated with the given elements for a set + * - _group_: set + * - _complexity_: O(N) where N is the number of elements being checked for membership + * - _since_: 6.2.0 + */ + smismember(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback + ]): Result; + smismember(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback + ]): Result; + smismember(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result; + smismember(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result; + /** + * Move a member from one set to another + * - _group_: set + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + smove(source: RedisKey, destination: RedisKey, member: string | Buffer | number, callback?: Callback): Result; + /** + * Sort the elements in a list, set or sorted set + * - _group_: generic + * - _complexity_: O(N+M*log(M)) where N is the number of elements in the list or set to sort, and M the number of returned elements. When the elements are not sorted, complexity is O(N). + * - _since_: 1.0.0 + */ + sort(...args: [key: RedisKey, ...args: RedisValue[], callback: Callback]): Result; + sort(...args: [key: RedisKey, ...args: RedisValue[]]): Result; + /** + * Sort the elements in a list, set or sorted set. Read-only variant of SORT. + * - _group_: generic + * - _complexity_: O(N+M*log(M)) where N is the number of elements in the list or set to sort, and M the number of returned elements. When the elements are not sorted, complexity is O(N). + * - _since_: 7.0.0 + */ + sort_ro(key: RedisKey, callback?: Callback): Result; + sort_ro(key: RedisKey, alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, asc: "ASC", callback?: Callback): Result; + sort_ro(key: RedisKey, asc: "ASC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, desc: "DESC", callback?: Callback): Result; + sort_ro(key: RedisKey, desc: "DESC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + callback: Callback + ]): Result; + sort_ro(...args: [key: RedisKey, patternToken: "GET", ...patterns: string[]]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + asc: "ASC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + asc: "ASC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + asc: "ASC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + asc: "ASC", + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + desc: "DESC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + desc: "DESC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + desc: "DESC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "GET", + ...patterns: string[], + desc: "DESC", + alpha: "ALPHA" + ]): Result; + sort_ro(key: RedisKey, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + sort_ro(key: RedisKey, offsetCountToken: "LIMIT", offset: number | string, count: number | string, alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, offsetCountToken: "LIMIT", offset: number | string, count: number | string, asc: "ASC", callback?: Callback): Result; + sort_ro(key: RedisKey, offsetCountToken: "LIMIT", offset: number | string, count: number | string, asc: "ASC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, offsetCountToken: "LIMIT", offset: number | string, count: number | string, desc: "DESC", callback?: Callback): Result; + sort_ro(key: RedisKey, offsetCountToken: "LIMIT", offset: number | string, count: number | string, desc: "DESC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[] + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + asc: "ASC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + asc: "ASC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + asc: "ASC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + asc: "ASC", + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + desc: "DESC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + desc: "DESC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + desc: "DESC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken: "GET", + ...patterns: string[], + desc: "DESC", + alpha: "ALPHA" + ]): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, asc: "ASC", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, asc: "ASC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, desc: "DESC", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, desc: "DESC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[] + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC", + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC", + alpha: "ALPHA" + ]): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, asc: "ASC", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, asc: "ASC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, desc: "DESC", callback?: Callback): Result; + sort_ro(key: RedisKey, patternToken: "BY", pattern: string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, desc: "DESC", alpha: "ALPHA", callback?: Callback): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[] + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + asc: "ASC", + alpha: "ALPHA" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC" + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC", + alpha: "ALPHA", + callback: Callback + ]): Result; + sort_ro(...args: [ + key: RedisKey, + patternToken: "BY", + pattern: string, + offsetCountToken: "LIMIT", + offset: number | string, + count: number | string, + patternToken1: "GET", + ...pattern1s: string[], + desc: "DESC", + alpha: "ALPHA" + ]): Result; + /** + * Remove and return one or multiple random members from a set + * - _group_: set + * - _complexity_: Without the count argument O(1), otherwise O(N) where N is the value of the passed count. + * - _since_: 1.0.0 + */ + spop(key: RedisKey, callback?: Callback): Result; + spopBuffer(key: RedisKey, callback?: Callback): Result; + spop(key: RedisKey, count: number | string, callback?: Callback): Result; + spopBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + /** + * Post a message to a shard channel + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of clients subscribed to the receiving shard channel. + * - _since_: 7.0.0 + */ + spublish(shardchannel: string | Buffer, message: string | Buffer, callback?: Callback): Result; + /** + * Get one or multiple random members from a set + * - _group_: set + * - _complexity_: Without the count argument O(1), otherwise O(N) where N is the absolute value of the passed count. + * - _since_: 1.0.0 + */ + srandmember(key: RedisKey, callback?: Callback): Result; + srandmemberBuffer(key: RedisKey, callback?: Callback): Result; + srandmember(key: RedisKey, count: number | string, callback?: Callback): Result; + srandmemberBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + /** + * Remove one or more members from a set + * - _group_: set + * - _complexity_: O(N) where N is the number of members to be removed. + * - _since_: 1.0.0 + */ + srem(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback + ]): Result; + srem(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback + ]): Result; + srem(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result; + srem(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result; + /** + * Incrementally iterate Set elements + * - _group_: set + * - _complexity_: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection.. + * - _since_: 2.8.0 + */ + sscan(key: RedisKey, cursor: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + sscanBuffer(key: RedisKey, cursor: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + sscan(key: RedisKey, cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + sscanBuffer(key: RedisKey, cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + sscan(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + sscanBuffer(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + sscan(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + sscanBuffer(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + /** + * Listen for messages published to the given shard channels + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of shard channels to subscribe to. + * - _since_: 7.0.0 + */ + ssubscribe(...args: [ + ...shardchannels: (string | Buffer)[], + callback: Callback + ]): Result; + ssubscribe(...args: [...shardchannels: (string | Buffer)[]]): Result; + /** + * Get the length of the value stored in a key + * - _group_: string + * - _complexity_: O(1) + * - _since_: 2.2.0 + */ + strlen(key: RedisKey, callback?: Callback): Result; + /** + * Listen for messages published to the given channels + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of channels to subscribe to. + * - _since_: 2.0.0 + */ + subscribe(...args: [...channels: (string | Buffer)[], callback: Callback]): Result; + subscribe(...args: [...channels: (string | Buffer)[]]): Result; + /** + * Get a substring of the string stored at a key + * - _group_: string + * - _complexity_: O(N) where N is the length of the returned string. The complexity is ultimately determined by the returned length, but because creating a substring from an existing string is very cheap, it can be considered O(1) for small strings. + * - _since_: 1.0.0 + */ + substr(key: RedisKey, start: number | string, end: number | string, callback?: Callback): Result; + /** + * Add multiple sets + * - _group_: set + * - _complexity_: O(N) where N is the total number of elements in all given sets. + * - _since_: 1.0.0 + */ + sunion(...args: [...keys: RedisKey[], callback: Callback]): Result; + sunionBuffer(...args: [...keys: RedisKey[], callback: Callback]): Result; + sunion(...args: [keys: RedisKey[], callback: Callback]): Result; + sunionBuffer(...args: [keys: RedisKey[], callback: Callback]): Result; + sunion(...args: [...keys: RedisKey[]]): Result; + sunionBuffer(...args: [...keys: RedisKey[]]): Result; + sunion(...args: [keys: RedisKey[]]): Result; + sunionBuffer(...args: [keys: RedisKey[]]): Result; + /** + * Add multiple sets and store the resulting set in a key + * - _group_: set + * - _complexity_: O(N) where N is the total number of elements in all given sets. + * - _since_: 1.0.0 + */ + sunionstore(...args: [ + destination: RedisKey, + ...keys: RedisKey[], + callback: Callback + ]): Result; + sunionstore(...args: [ + destination: RedisKey, + keys: RedisKey[], + callback: Callback + ]): Result; + sunionstore(...args: [destination: RedisKey, ...keys: RedisKey[]]): Result; + sunionstore(...args: [destination: RedisKey, keys: RedisKey[]]): Result; + /** + * Stop listening for messages posted to the given shard channels + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of clients already subscribed to a shard channel. + * - _since_: 7.0.0 + */ + sunsubscribe(callback?: Callback): Result; + sunsubscribe(...args: [ + ...shardchannels: (string | Buffer)[], + callback: Callback + ]): Result; + sunsubscribe(...args: [...shardchannels: (string | Buffer)[]]): Result; + /** + * Swaps two Redis databases + * - _group_: server + * - _complexity_: O(N) where N is the count of clients watching or blocking on keys from both databases. + * - _since_: 4.0.0 + */ + swapdb(index1: number | string, index2: number | string, callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Internal command used for replication + * - _group_: server + * - _complexity_: undefined + * - _since_: 1.0.0 + */ + sync(callback?: Callback): Result; + /** + * Return the current server time + * - _group_: server + * - _complexity_: O(1) + * - _since_: 2.6.0 + */ + time(callback?: Callback): Result; + /** + * Alters the last access time of a key(s). Returns the number of existing keys specified. + * - _group_: generic + * - _complexity_: O(N) where N is the number of keys that will be touched. + * - _since_: 3.2.1 + */ + touch(...args: [...keys: RedisKey[], callback: Callback]): Result; + touch(...args: [keys: RedisKey[], callback: Callback]): Result; + touch(...args: [...keys: RedisKey[]]): Result; + touch(...args: [keys: RedisKey[]]): Result; + /** + * Get the time to live for a key in seconds + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + ttl(key: RedisKey, callback?: Callback): Result; + /** + * Determine the type stored at key + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 1.0.0 + */ + type(key: RedisKey, callback?: Callback): Result; + /** + * Delete a key asynchronously in another thread. Otherwise it is just as DEL, but non blocking. + * - _group_: generic + * - _complexity_: O(1) for each key removed regardless of its size. Then the command does O(N) work in a different thread in order to reclaim memory, where N is the number of allocations the deleted objects where composed of. + * - _since_: 4.0.0 + */ + unlink(...args: [...keys: RedisKey[], callback: Callback]): Result; + unlink(...args: [keys: RedisKey[], callback: Callback]): Result; + unlink(...args: [...keys: RedisKey[]]): Result; + unlink(...args: [keys: RedisKey[]]): Result; + /** + * Stop listening for messages posted to the given channels + * - _group_: pubsub + * - _complexity_: O(N) where N is the number of clients already subscribed to a channel. + * - _since_: 2.0.0 + */ + unsubscribe(callback?: Callback): Result; + unsubscribe(...args: [...channels: (string | Buffer)[], callback: Callback]): Result; + unsubscribe(...args: [...channels: (string | Buffer)[]]): Result; + /** + * Forget about all watched keys + * - _group_: transactions + * - _complexity_: O(1) + * - _since_: 2.2.0 + */ + unwatch(callback?: Callback<"OK">): Result<"OK", Context>; + /** + * Wait for the synchronous replication of all the write commands sent in the context of the current connection + * - _group_: generic + * - _complexity_: O(1) + * - _since_: 3.0.0 + */ + wait(numreplicas: number | string, timeout: number | string, callback?: Callback): Result; + /** + * Watch the given keys to determine execution of the MULTI/EXEC block + * - _group_: transactions + * - _complexity_: O(1) for every key. + * - _since_: 2.2.0 + */ + watch(...args: [...keys: RedisKey[], callback: Callback<"OK">]): Result<"OK", Context>; + watch(...args: [keys: RedisKey[], callback: Callback<"OK">]): Result<"OK", Context>; + watch(...args: [...keys: RedisKey[]]): Result<"OK", Context>; + watch(...args: [keys: RedisKey[]]): Result<"OK", Context>; + /** + * Marks a pending message as correctly processed, effectively removing it from the pending entries list of the consumer group. Return value of the command is the number of messages successfully acknowledged, that is, the IDs we were actually able to resolve in the PEL. + * - _group_: stream + * - _complexity_: O(1) for each message ID processed. + * - _since_: 5.0.0 + */ + xack(...args: [ + key: RedisKey, + group: string | Buffer, + ...ids: (string | Buffer | number)[], + callback: Callback + ]): Result; + xack(...args: [ + key: RedisKey, + group: string | Buffer, + ...ids: (string | Buffer | number)[] + ]): Result; + /** + * Appends a new entry to a stream + * - _group_: stream + * - _complexity_: O(1) when adding a new entry, O(N) when trimming where N being the number of entries evicted. + * - _since_: 5.0.0 + */ + xadd(...args: [ + key: RedisKey, + ...args: RedisValue[], + callback: Callback + ]): Result; + xaddBuffer(...args: [ + key: RedisKey, + ...args: RedisValue[], + callback: Callback + ]): Result; + xadd(...args: [key: RedisKey, ...args: RedisValue[]]): Result; + xaddBuffer(...args: [key: RedisKey, ...args: RedisValue[]]): Result; + /** + * Changes (or acquires) ownership of messages in a consumer group, as if the messages were delivered to the specified consumer. + * - _group_: stream + * - _complexity_: O(1) if COUNT is small. + * - _since_: 6.2.0 + */ + xautoclaim(key: RedisKey, group: string | Buffer, consumer: string | Buffer, minIdleTime: string | Buffer | number, start: string | Buffer | number, callback?: Callback): Result; + xautoclaim(key: RedisKey, group: string | Buffer, consumer: string | Buffer, minIdleTime: string | Buffer | number, start: string | Buffer | number, justid: "JUSTID", callback?: Callback): Result; + xautoclaim(key: RedisKey, group: string | Buffer, consumer: string | Buffer, minIdleTime: string | Buffer | number, start: string | Buffer | number, countToken: "COUNT", count: number | string, callback?: Callback): Result; + xautoclaim(key: RedisKey, group: string | Buffer, consumer: string | Buffer, minIdleTime: string | Buffer | number, start: string | Buffer | number, countToken: "COUNT", count: number | string, justid: "JUSTID", callback?: Callback): Result; + /** + * Changes (or acquires) ownership of a message in a consumer group, as if the message was delivered to the specified consumer. + * - _group_: stream + * - _complexity_: O(log N) with N being the number of messages in the PEL of the consumer group. + * - _since_: 5.0.0 + */ + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[] + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + force: "FORCE", + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string, + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE", + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + force: "FORCE", + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string, + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + force: "FORCE", + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + justid: "JUSTID" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE" + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID", + callback: Callback + ]): Result; + xclaim(...args: [ + key: RedisKey, + group: string | Buffer, + consumer: string | Buffer, + minIdleTime: string | Buffer | number, + ...ids: (string | Buffer | number)[], + msToken: "IDLE", + ms: number | string, + unixTimeMillisecondsToken: "TIME", + unixTimeMilliseconds: number | string, + countToken: "RETRYCOUNT", + count: number | string, + force: "FORCE", + justid: "JUSTID" + ]): Result; + /** + * Removes the specified entries from the stream. Returns the number of items actually deleted, that may be different from the number of IDs passed in case certain IDs do not exist. + * - _group_: stream + * - _complexity_: O(1) for each single item to delete in the stream, regardless of the stream size. + * - _since_: 5.0.0 + */ + xdel(...args: [ + key: RedisKey, + ...ids: (string | Buffer | number)[], + callback: Callback + ]): Result; + xdel(...args: [key: RedisKey, ...ids: (string | Buffer | number)[]]): Result; + /** + * Deletes one or multiple entries from the stream. + * - _group_: stream + * - _complexity_: O(1) for each single item to delete in the stream, regardless of the stream size. + * - _since_: 8.2.0 + */ + xdelex(...args: [ + key: RedisKey, + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[], + callback: Callback + ]): Result; + xdelex(...args: [ + key: RedisKey, + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[] + ]): Result; + xdelex(...args: [ + key: RedisKey, + keepref: "KEEPREF", + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[], + callback: Callback + ]): Result; + xdelex(...args: [ + key: RedisKey, + keepref: "KEEPREF", + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[] + ]): Result; + xdelex(...args: [ + key: RedisKey, + delref: "DELREF", + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[], + callback: Callback + ]): Result; + xdelex(...args: [ + key: RedisKey, + delref: "DELREF", + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[] + ]): Result; + xdelex(...args: [ + key: RedisKey, + acked: "ACKED", + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[], + callback: Callback + ]): Result; + xdelex(...args: [ + key: RedisKey, + acked: "ACKED", + idsToken: "IDS", + numids: number | string, + ...ids: (string | Buffer | number)[] + ]): Result; + /** + * Create a consumer group. + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, id: string | Buffer | number, callback?: Callback): Result; + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, id: string | Buffer | number, entriesReadToken: "ENTRIESREAD", entriesRead: number | string, callback?: Callback): Result; + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, id: string | Buffer | number, mkstream: "MKSTREAM", callback?: Callback): Result; + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, id: string | Buffer | number, mkstream: "MKSTREAM", entriesReadToken: "ENTRIESREAD", entriesRead: number | string, callback?: Callback): Result; + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, newId: "$", callback?: Callback): Result; + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, newId: "$", entriesReadToken: "ENTRIESREAD", entriesRead: number | string, callback?: Callback): Result; + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, newId: "$", mkstream: "MKSTREAM", callback?: Callback): Result; + xgroup(subcommand: "CREATE", key: RedisKey, groupname: string | Buffer, newId: "$", mkstream: "MKSTREAM", entriesReadToken: "ENTRIESREAD", entriesRead: number | string, callback?: Callback): Result; + /** + * Create a consumer in a consumer group. + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 6.2.0 + */ + xgroup(subcommand: "CREATECONSUMER", key: RedisKey, groupname: string | Buffer, consumername: string | Buffer, callback?: Callback): Result; + /** + * Delete a consumer from a consumer group. + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xgroup(subcommand: "DELCONSUMER", key: RedisKey, groupname: string | Buffer, consumername: string | Buffer, callback?: Callback): Result; + /** + * Destroy a consumer group. + * - _group_: stream + * - _complexity_: O(N) where N is the number of entries in the group's pending entries list (PEL). + * - _since_: 5.0.0 + */ + xgroup(subcommand: "DESTROY", key: RedisKey, groupname: string | Buffer, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xgroup(subcommand: "HELP", callback?: Callback): Result; + /** + * Set a consumer group to an arbitrary last delivered ID value. + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xgroup(subcommand: "SETID", key: RedisKey, groupname: string | Buffer, id: string | Buffer | number, callback?: Callback): Result; + xgroup(subcommand: "SETID", key: RedisKey, groupname: string | Buffer, id: string | Buffer | number, entriesReadToken: "ENTRIESREAD", entriesRead: number | string, callback?: Callback): Result; + xgroup(subcommand: "SETID", key: RedisKey, groupname: string | Buffer, newId: "$", callback?: Callback): Result; + xgroup(subcommand: "SETID", key: RedisKey, groupname: string | Buffer, newId: "$", entriesReadToken: "ENTRIESREAD", entriesRead: number | string, callback?: Callback): Result; + /** + * List the consumers in a consumer group + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xinfo(subcommand: "CONSUMERS", key: RedisKey, groupname: string | Buffer, callback?: Callback): Result; + /** + * List the consumer groups of a stream + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xinfo(subcommand: "GROUPS", key: RedisKey, callback?: Callback): Result; + /** + * Show helpful text about the different subcommands + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xinfo(subcommand: "HELP", callback?: Callback): Result; + /** + * Get information about a stream + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xinfo(subcommand: "STREAM", key: RedisKey, callback?: Callback): Result; + xinfo(subcommand: "STREAM", key: RedisKey, fullToken: "FULL", callback?: Callback): Result; + xinfo(subcommand: "STREAM", key: RedisKey, fullToken: "FULL", countToken: "COUNT", count: number | string, callback?: Callback): Result; + /** + * Return the number of entries in a stream + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xlen(key: RedisKey, callback?: Callback): Result; + /** + * Return information and entries from a stream consumer group pending entries list, that are messages fetched but never acknowledged. + * - _group_: stream + * - _complexity_: O(N) with N being the number of elements returned, so asking for a small fixed number of entries per call is O(1). O(M), where M is the total number of entries scanned when used with the IDLE filter. When the command returns just the summary and the list of consumers is small, it runs in O(1) time; otherwise, an additional O(N) time for iterating every consumer. + * - _since_: 5.0.0 + */ + xpending(key: RedisKey, group: string | Buffer, callback?: Callback): Result; + xpending(key: RedisKey, group: string | Buffer, start: string | Buffer | number, end: string | Buffer | number, count: number | string, callback?: Callback): Result; + xpending(key: RedisKey, group: string | Buffer, start: string | Buffer | number, end: string | Buffer | number, count: number | string, consumer: string | Buffer, callback?: Callback): Result; + xpending(key: RedisKey, group: string | Buffer, minIdleTimeToken: "IDLE", minIdleTime: number | string, start: string | Buffer | number, end: string | Buffer | number, count: number | string, callback?: Callback): Result; + xpending(key: RedisKey, group: string | Buffer, minIdleTimeToken: "IDLE", minIdleTime: number | string, start: string | Buffer | number, end: string | Buffer | number, count: number | string, consumer: string | Buffer, callback?: Callback): Result; + /** + * Return a range of elements in a stream, with IDs matching the specified IDs interval + * - _group_: stream + * - _complexity_: O(N) with N being the number of elements being returned. If N is constant (e.g. always asking for the first 10 elements with COUNT), you can consider it O(1). + * - _since_: 5.0.0 + */ + xrange(key: RedisKey, start: string | Buffer | number, end: string | Buffer | number, callback?: Callback<[id: string, fields: string[]][]>): Result<[id: string, fields: string[]][], Context>; + xrangeBuffer(key: RedisKey, start: string | Buffer | number, end: string | Buffer | number, callback?: Callback<[id: Buffer, fields: Buffer[]][]>): Result<[id: Buffer, fields: Buffer[]][], Context>; + xrange(key: RedisKey, start: string | Buffer | number, end: string | Buffer | number, countToken: "COUNT", count: number | string, callback?: Callback<[id: string, fields: string[]][]>): Result<[id: string, fields: string[]][], Context>; + xrangeBuffer(key: RedisKey, start: string | Buffer | number, end: string | Buffer | number, countToken: "COUNT", count: number | string, callback?: Callback<[id: Buffer, fields: Buffer[]][]>): Result<[id: Buffer, fields: Buffer[]][], Context>; + /** + * Return never seen elements in multiple streams, with IDs greater than the ones reported by the caller for each stream. Can block. + * - _group_: stream + * - _complexity_: For each stream mentioned: O(N) with N being the number of elements being returned, it means that XREAD-ing with a fixed COUNT is O(1). Note that when the BLOCK option is used, XADD will pay O(M) time in order to serve the M clients blocked on the stream getting new data. + * - _since_: 5.0.0 + */ + xread(...args: [ + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null> + ]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [ + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null> + ]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + xread(...args: [streamsToken: "STREAMS", ...args: RedisValue[]]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [streamsToken: "STREAMS", ...args: RedisValue[]]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + xread(...args: [ + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null> + ]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [ + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null> + ]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + xread(...args: [ + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [ + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + xread(...args: [ + countToken: "COUNT", + count: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null> + ]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [ + countToken: "COUNT", + count: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null> + ]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + xread(...args: [ + countToken: "COUNT", + count: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [ + countToken: "COUNT", + count: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + xread(...args: [ + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null> + ]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [ + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null> + ]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + xread(...args: [ + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result<[ + key: string, + items: [id: string, fields: string[]][] + ][] | null, Context>; + xreadBuffer(...args: [ + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result<[ + key: Buffer, + items: [id: Buffer, fields: Buffer[]][] + ][] | null, Context>; + /** + * Return new entries from a stream using a consumer group, or access the history of the pending entries for a given consumer. Can block. + * - _group_: stream + * - _complexity_: For each stream mentioned: O(M) with M being the number of elements returned. If M is constant (e.g. always asking for the first 10 elements with COUNT), you can consider it O(1). On the other side when XREADGROUP blocks, XADD will pay the O(N) time in order to serve the N clients blocked on the stream getting new data. + * - _since_: 5.0.0 + */ + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + millisecondsToken: "BLOCK", + milliseconds: number | string, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + millisecondsToken: "BLOCK", + milliseconds: number | string, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[], + callback: Callback + ]): Result; + xreadgroup(...args: [ + groupConsumerToken: "GROUP", + group: string | Buffer, + consumer: string | Buffer, + countToken: "COUNT", + count: number | string, + millisecondsToken: "BLOCK", + milliseconds: number | string, + noack: "NOACK", + streamsToken: "STREAMS", + ...args: RedisValue[] + ]): Result; + /** + * Return a range of elements in a stream, with IDs matching the specified IDs interval, in reverse order (from greater to smaller IDs) compared to XRANGE + * - _group_: stream + * - _complexity_: O(N) with N being the number of elements returned. If N is constant (e.g. always asking for the first 10 elements with COUNT), you can consider it O(1). + * - _since_: 5.0.0 + */ + xrevrange(key: RedisKey, end: string | Buffer | number, start: string | Buffer | number, callback?: Callback<[id: string, fields: string[]][]>): Result<[id: string, fields: string[]][], Context>; + xrevrangeBuffer(key: RedisKey, end: string | Buffer | number, start: string | Buffer | number, callback?: Callback<[id: Buffer, fields: Buffer[]][]>): Result<[id: Buffer, fields: Buffer[]][], Context>; + xrevrange(key: RedisKey, end: string | Buffer | number, start: string | Buffer | number, countToken: "COUNT", count: number | string, callback?: Callback<[id: string, fields: string[]][]>): Result<[id: string, fields: string[]][], Context>; + xrevrangeBuffer(key: RedisKey, end: string | Buffer | number, start: string | Buffer | number, countToken: "COUNT", count: number | string, callback?: Callback<[id: Buffer, fields: Buffer[]][]>): Result<[id: Buffer, fields: Buffer[]][], Context>; + /** + * An internal command for replicating stream values + * - _group_: stream + * - _complexity_: O(1) + * - _since_: 5.0.0 + */ + xsetid(key: RedisKey, lastId: string | Buffer | number, callback?: Callback): Result; + xsetid(key: RedisKey, lastId: string | Buffer | number, maxDeletedEntryIdToken: "MAXDELETEDID", maxDeletedEntryId: string | Buffer | number, callback?: Callback): Result; + xsetid(key: RedisKey, lastId: string | Buffer | number, entriesAddedToken: "ENTRIESADDED", entriesAdded: number | string, callback?: Callback): Result; + xsetid(key: RedisKey, lastId: string | Buffer | number, entriesAddedToken: "ENTRIESADDED", entriesAdded: number | string, maxDeletedEntryIdToken: "MAXDELETEDID", maxDeletedEntryId: string | Buffer | number, callback?: Callback): Result; + /** + * Deletes messages from the beginning of a stream. + * - _group_: stream + * - _complexity_: O(N), with N being the number of evicted entries. Constant times are very small however, since entries are organized in macro nodes containing multiple entries that can be released with a single deallocation. + * - _since_: 5.0.0 + */ + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, maxlen: "MAXLEN", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", equal: "=", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, acked: "ACKED", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, keepref: "KEEPREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, delref: "DELREF", callback?: Callback): Result; + xtrim(key: RedisKey, minid: "MINID", approximately: "~", threshold: string | Buffer | number, countToken: "LIMIT", count: number | string, acked: "ACKED", callback?: Callback): Result; + /** + * Add one or more members to a sorted set, or update its score if it already exists + * - _group_: sorted-set + * - _complexity_: O(log(N)) for each item added, where N is the number of elements in the sorted set. + * - _since_: 1.2.0 + */ + zadd(...args: [ + key: RedisKey, + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [key: RedisKey, ...scoreMembers: (string | Buffer | number)[]]): Result; + zadd(...args: [ + key: RedisKey, + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + nx: "NX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + gt: "GT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ch: "CH", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[], + callback: Callback + ]): Result; + zadd(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + zaddBuffer(...args: [ + key: RedisKey, + xx: "XX", + lt: "LT", + ch: "CH", + incr: "INCR", + ...scoreMembers: (string | Buffer | number)[] + ]): Result; + /** + * Get the number of members in a sorted set + * - _group_: sorted-set + * - _complexity_: O(1) + * - _since_: 1.2.0 + */ + zcard(key: RedisKey, callback?: Callback): Result; + /** + * Count the members in a sorted set with scores within the given values + * - _group_: sorted-set + * - _complexity_: O(log(N)) with N being the number of elements in the sorted set. + * - _since_: 2.0.0 + */ + zcount(key: RedisKey, min: number | string, max: number | string, callback?: Callback): Result; + /** + * Subtract multiple sorted sets + * - _group_: sorted-set + * - _complexity_: O(L + (N-K)log(N)) worst case where L is the total number of elements in all the sets, N is the size of the first set, and K is the size of the result set. + * - _since_: 6.2.0 + */ + zdiff(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zdiffBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zdiff(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zdiffBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zdiff(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + zdiffBuffer(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + zdiff(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + zdiffBuffer(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + zdiff(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zdiffBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zdiff(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zdiffBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zdiff(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zdiffBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zdiff(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zdiffBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + /** + * Subtract multiple sorted sets and store the resulting sorted set in a new key + * - _group_: sorted-set + * - _complexity_: O(L + (N-K)log(N)) worst case where L is the total number of elements in all the sets, N is the size of the first set, and K is the size of the result set. + * - _since_: 6.2.0 + */ + zdiffstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zdiffstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zdiffstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[] + ]): Result; + zdiffstore(...args: [destination: RedisKey, numkeys: number | string, keys: RedisKey[]]): Result; + /** + * Increment the score of a member in a sorted set + * - _group_: sorted-set + * - _complexity_: O(log(N)) where N is the number of elements in the sorted set. + * - _since_: 1.2.0 + */ + zincrby(key: RedisKey, increment: number | string, member: string | Buffer | number, callback?: Callback): Result; + zincrbyBuffer(key: RedisKey, increment: number | string, member: string | Buffer | number, callback?: Callback): Result; + /** + * Intersect multiple sorted sets + * - _group_: sorted-set + * - _complexity_: O(N*K)+O(M*log(M)) worst case with N being the smallest input sorted set, K being the number of input sorted sets and M being the number of elements in the resulting sorted set. + * - _since_: 6.2.0 + */ + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zinter(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + zinterBuffer(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + zinter(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + zinterBuffer(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + zinter(...args: [numkeys: number | string, ...args: RedisValue[]]): Result; + zinterBuffer(...args: [numkeys: number | string, ...args: RedisValue[]]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zinter(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zinterBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + /** + * Intersect multiple sorted sets and return the cardinality of the result + * - _group_: sorted-set + * - _complexity_: O(N*K) worst case with N being the smallest input sorted set, K being the number of input sorted sets. + * - _since_: 7.0.0 + */ + zintercard(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zintercard(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zintercard(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + zintercard(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + zintercard(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string, + callback: Callback + ]): Result; + zintercard(...args: [ + numkeys: number | string, + keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string, + callback: Callback + ]): Result; + zintercard(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string + ]): Result; + zintercard(...args: [ + numkeys: number | string, + keys: RedisKey[], + limitToken: "LIMIT", + limit: number | string + ]): Result; + /** + * Intersect multiple sorted sets and store the resulting sorted set in a new key + * - _group_: sorted-set + * - _complexity_: O(N*K)+O(M*log(M)) worst case with N being the smallest input sorted set, K being the number of input sorted sets and M being the number of elements in the resulting sorted set. + * - _since_: 2.0.0 + */ + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[] + ]): Result; + zinterstore(...args: [destination: RedisKey, numkeys: number | string, keys: RedisKey[]]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zinterstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + /** + * Count the number of members in a sorted set between a given lexicographical range + * - _group_: sorted-set + * - _complexity_: O(log(N)) with N being the number of elements in the sorted set. + * - _since_: 2.8.9 + */ + zlexcount(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, callback?: Callback): Result; + /** + * Remove and return members with scores in a sorted set + * - _group_: sorted-set + * - _complexity_: O(K) + O(N*log(M)) where K is the number of provided keys, N being the number of elements in the sorted set, and M being the number of elements popped. + * - _since_: 7.0.0 + */ + zmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + min: "MIN", + callback: Callback + ]): Result; + zmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + min: "MIN", + callback: Callback + ]): Result; + zmpop(...args: [numkeys: number | string, ...keys: RedisKey[], min: "MIN"]): Result; + zmpop(...args: [numkeys: number | string, keys: RedisKey[], min: "MIN"]): Result; + zmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + zmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + zmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string + ]): Result; + zmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + min: "MIN", + countToken: "COUNT", + count: number | string + ]): Result; + zmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + max: "MAX", + callback: Callback + ]): Result; + zmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + max: "MAX", + callback: Callback + ]): Result; + zmpop(...args: [numkeys: number | string, ...keys: RedisKey[], max: "MAX"]): Result; + zmpop(...args: [numkeys: number | string, keys: RedisKey[], max: "MAX"]): Result; + zmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + zmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string, + callback: Callback + ]): Result; + zmpop(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string + ]): Result; + zmpop(...args: [ + numkeys: number | string, + keys: RedisKey[], + max: "MAX", + countToken: "COUNT", + count: number | string + ]): Result; + /** + * Get the score associated with the given members in a sorted set + * - _group_: sorted-set + * - _complexity_: O(N) where N is the number of members being requested. + * - _since_: 6.2.0 + */ + zmscore(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback<(string | null)[]> + ]): Result<(string | null)[], Context>; + zmscoreBuffer(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback<(Buffer | null)[]> + ]): Result<(Buffer | null)[], Context>; + zmscore(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback<(string | null)[]> + ]): Result<(string | null)[], Context>; + zmscoreBuffer(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback<(Buffer | null)[]> + ]): Result<(Buffer | null)[], Context>; + zmscore(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result<(string | null)[], Context>; + zmscoreBuffer(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result<(Buffer | null)[], Context>; + zmscore(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result<(string | null)[], Context>; + zmscoreBuffer(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result<(Buffer | null)[], Context>; + /** + * Remove and return members with the highest scores in a sorted set + * - _group_: sorted-set + * - _complexity_: O(log(N)*M) with N being the number of elements in the sorted set, and M being the number of elements popped. + * - _since_: 5.0.0 + */ + zpopmax(key: RedisKey, callback?: Callback): Result; + zpopmaxBuffer(key: RedisKey, callback?: Callback): Result; + zpopmax(key: RedisKey, count: number | string, callback?: Callback): Result; + zpopmaxBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + /** + * Remove and return members with the lowest scores in a sorted set + * - _group_: sorted-set + * - _complexity_: O(log(N)*M) with N being the number of elements in the sorted set, and M being the number of elements popped. + * - _since_: 5.0.0 + */ + zpopmin(key: RedisKey, callback?: Callback): Result; + zpopminBuffer(key: RedisKey, callback?: Callback): Result; + zpopmin(key: RedisKey, count: number | string, callback?: Callback): Result; + zpopminBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + /** + * Get one or multiple random elements from a sorted set + * - _group_: sorted-set + * - _complexity_: O(N) where N is the number of elements returned + * - _since_: 6.2.0 + */ + zrandmember(key: RedisKey, callback?: Callback): Result; + zrandmemberBuffer(key: RedisKey, callback?: Callback): Result; + zrandmember(key: RedisKey, count: number | string, callback?: Callback): Result; + zrandmemberBuffer(key: RedisKey, count: number | string, callback?: Callback): Result; + zrandmember(key: RedisKey, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrandmemberBuffer(key: RedisKey, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + /** + * Return a range of members in a sorted set + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned. + * - _since_: 1.2.0 + */ + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", withscores: "WITHSCORES", callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrange(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangeBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + /** + * Return a range of members in a sorted set, by lexicographical range + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)). + * - _since_: 2.8.9 + */ + zrangebylex(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, callback?: Callback): Result; + zrangebylexBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, callback?: Callback): Result; + zrangebylex(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangebylexBuffer(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + /** + * Return a range of members in a sorted set, by score + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)). + * - _since_: 1.0.5 + */ + zrangebyscore(key: RedisKey, min: number | string, max: number | string, callback?: Callback): Result; + zrangebyscoreBuffer(key: RedisKey, min: number | string, max: number | string, callback?: Callback): Result; + zrangebyscore(key: RedisKey, min: number | string, max: number | string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangebyscoreBuffer(key: RedisKey, min: number | string, max: number | string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangebyscore(key: RedisKey, min: number | string, max: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangebyscoreBuffer(key: RedisKey, min: number | string, max: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrangebyscore(key: RedisKey, min: number | string, max: number | string, withscores: "WITHSCORES", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangebyscoreBuffer(key: RedisKey, min: number | string, max: number | string, withscores: "WITHSCORES", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + /** + * Store a range of members from sorted set into another key + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements stored into the destination key. + * - _since_: 6.2.0 + */ + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, byscore: "BYSCORE", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", callback?: Callback): Result; + zrangestore(dst: RedisKey, src: RedisKey, min: string | Buffer | number, max: string | Buffer | number, bylex: "BYLEX", rev: "REV", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + /** + * Determine the index of a member in a sorted set + * - _group_: sorted-set + * - _complexity_: O(log(N)) + * - _since_: 2.0.0 + */ + zrank(key: RedisKey, member: string | Buffer | number, callback?: Callback): Result; + /** + * Remove one or more members from a sorted set + * - _group_: sorted-set + * - _complexity_: O(M*log(N)) with N being the number of elements in the sorted set and M the number of elements to be removed. + * - _since_: 1.2.0 + */ + zrem(...args: [ + key: RedisKey, + ...members: (string | Buffer | number)[], + callback: Callback + ]): Result; + zrem(...args: [ + key: RedisKey, + members: (string | Buffer | number)[], + callback: Callback + ]): Result; + zrem(...args: [key: RedisKey, ...members: (string | Buffer | number)[]]): Result; + zrem(...args: [key: RedisKey, members: (string | Buffer | number)[]]): Result; + /** + * Remove all members in a sorted set between the given lexicographical range + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation. + * - _since_: 2.8.9 + */ + zremrangebylex(key: RedisKey, min: string | Buffer | number, max: string | Buffer | number, callback?: Callback): Result; + /** + * Remove all members in a sorted set within the given indexes + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation. + * - _since_: 2.0.0 + */ + zremrangebyrank(key: RedisKey, start: number | string, stop: number | string, callback?: Callback): Result; + /** + * Remove all members in a sorted set within the given scores + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation. + * - _since_: 1.2.0 + */ + zremrangebyscore(key: RedisKey, min: number | string, max: number | string, callback?: Callback): Result; + /** + * Return a range of members in a sorted set, by index, with scores ordered from high to low + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned. + * - _since_: 1.2.0 + */ + zrevrange(key: RedisKey, start: number | string, stop: number | string, callback?: Callback): Result; + zrevrangeBuffer(key: RedisKey, start: number | string, stop: number | string, callback?: Callback): Result; + zrevrange(key: RedisKey, start: number | string, stop: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrevrangeBuffer(key: RedisKey, start: number | string, stop: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + /** + * Return a range of members in a sorted set, by lexicographical range, ordered from higher to lower strings. + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)). + * - _since_: 2.8.9 + */ + zrevrangebylex(key: RedisKey, max: string | Buffer | number, min: string | Buffer | number, callback?: Callback): Result; + zrevrangebylexBuffer(key: RedisKey, max: string | Buffer | number, min: string | Buffer | number, callback?: Callback): Result; + zrevrangebylex(key: RedisKey, max: string | Buffer | number, min: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrevrangebylexBuffer(key: RedisKey, max: string | Buffer | number, min: string | Buffer | number, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + /** + * Return a range of members in a sorted set, by score, with scores ordered from high to low + * - _group_: sorted-set + * - _complexity_: O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)). + * - _since_: 2.2.0 + */ + zrevrangebyscore(key: RedisKey, max: number | string, min: number | string, callback?: Callback): Result; + zrevrangebyscoreBuffer(key: RedisKey, max: number | string, min: number | string, callback?: Callback): Result; + zrevrangebyscore(key: RedisKey, max: number | string, min: number | string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrevrangebyscoreBuffer(key: RedisKey, max: number | string, min: number | string, offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrevrangebyscore(key: RedisKey, max: number | string, min: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrevrangebyscoreBuffer(key: RedisKey, max: number | string, min: number | string, withscores: "WITHSCORES", callback?: Callback): Result; + zrevrangebyscore(key: RedisKey, max: number | string, min: number | string, withscores: "WITHSCORES", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + zrevrangebyscoreBuffer(key: RedisKey, max: number | string, min: number | string, withscores: "WITHSCORES", offsetCountToken: "LIMIT", offset: number | string, count: number | string, callback?: Callback): Result; + /** + * Determine the index of a member in a sorted set, with scores ordered from high to low + * - _group_: sorted-set + * - _complexity_: O(log(N)) + * - _since_: 2.0.0 + */ + zrevrank(key: RedisKey, member: string | Buffer | number, callback?: Callback): Result; + /** + * Incrementally iterate sorted sets elements and associated scores + * - _group_: sorted-set + * - _complexity_: O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection.. + * - _since_: 2.8.0 + */ + zscan(key: RedisKey, cursor: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + zscanBuffer(key: RedisKey, cursor: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + zscan(key: RedisKey, cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + zscanBuffer(key: RedisKey, cursor: number | string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + zscan(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + zscanBuffer(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + zscan(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: string, elements: string[]]>): Result<[cursor: string, elements: string[]], Context>; + zscanBuffer(key: RedisKey, cursor: number | string, patternToken: "MATCH", pattern: string, countToken: "COUNT", count: number | string, callback?: Callback<[cursor: Buffer, elements: Buffer[]]>): Result<[cursor: Buffer, elements: Buffer[]], Context>; + /** + * Get the score associated with the given member in a sorted set + * - _group_: sorted-set + * - _complexity_: O(1) + * - _since_: 1.2.0 + */ + zscore(key: RedisKey, member: string | Buffer | number, callback?: Callback): Result; + zscoreBuffer(key: RedisKey, member: string | Buffer | number, callback?: Callback): Result; + /** + * Add multiple sorted sets + * - _group_: sorted-set + * - _complexity_: O(N)+O(M*log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set. + * - _since_: 6.2.0 + */ + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zunion(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + zunionBuffer(...args: [numkeys: number | string, ...keys: RedisKey[]]): Result; + zunion(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + zunionBuffer(...args: [numkeys: number | string, keys: RedisKey[]]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + zunion(...args: [numkeys: number | string, ...args: RedisValue[]]): Result; + zunionBuffer(...args: [numkeys: number | string, ...args: RedisValue[]]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + withscores: "WITHSCORES" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES", + callback: Callback + ]): Result; + zunion(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + zunionBuffer(...args: [ + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + withscores: "WITHSCORES" + ]): Result; + /** + * Add multiple sorted sets and store the resulting sorted set in a new key + * - _group_: sorted-set + * - _complexity_: O(N)+O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set. + * - _since_: 2.0.0 + */ + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[] + ]): Result; + zunionstore(...args: [destination: RedisKey, numkeys: number | string, keys: RedisKey[]]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + keys: RedisKey[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[] + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + sum: "SUM" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + min: "MIN" + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX", + callback: Callback + ]): Result; + zunionstore(...args: [ + destination: RedisKey, + numkeys: number | string, + ...args: RedisValue[], + aggregate: "AGGREGATE", + max: "MAX" + ]): Result; +} +export default RedisCommander; diff --git a/backend/node_modules/ioredis/built/utils/RedisCommander.js b/backend/node_modules/ioredis/built/utils/RedisCommander.js new file mode 100644 index 0000000..c7431fc --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/RedisCommander.js @@ -0,0 +1,7 @@ +"use strict"; +/** + * This file is generated by @ioredis/interface-generator. + * Don't edit it manually. Instead, run `npm run generate` to update + * this file. + */ +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/backend/node_modules/ioredis/built/utils/applyMixin.d.ts b/backend/node_modules/ioredis/built/utils/applyMixin.d.ts new file mode 100644 index 0000000..cf5cdb4 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/applyMixin.d.ts @@ -0,0 +1,3 @@ +declare type Constructor = new (...args: any[]) => void; +declare function applyMixin(derivedConstructor: Constructor, mixinConstructor: Constructor): void; +export default applyMixin; diff --git a/backend/node_modules/ioredis/built/utils/applyMixin.js b/backend/node_modules/ioredis/built/utils/applyMixin.js new file mode 100644 index 0000000..0b2d5b9 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/applyMixin.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function applyMixin(derivedConstructor, mixinConstructor) { + Object.getOwnPropertyNames(mixinConstructor.prototype).forEach((name) => { + Object.defineProperty(derivedConstructor.prototype, name, Object.getOwnPropertyDescriptor(mixinConstructor.prototype, name)); + }); +} +exports.default = applyMixin; diff --git a/backend/node_modules/ioredis/built/utils/argumentParsers.d.ts b/backend/node_modules/ioredis/built/utils/argumentParsers.d.ts new file mode 100644 index 0000000..c451e14 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/argumentParsers.d.ts @@ -0,0 +1,14 @@ +import { CommandParameter } from "../types"; +/** + * Parses a command parameter as seconds and converts to milliseconds. + * @param arg - The command parameter representing seconds + * @returns The value in milliseconds, 0 if value is <= 0, or undefined if parsing fails + */ +export declare const parseSecondsArgument: (arg: CommandParameter | undefined) => number | undefined; +/** + * Parses the BLOCK option from Redis command arguments (e.g., XREAD, XREADGROUP). + * @param args - Array of command parameters to search for the BLOCK option + * @returns The block duration in milliseconds, 0 if duration is <= 0, + * null if BLOCK option is not found, or undefined if BLOCK is found but duration is invalid + */ +export declare const parseBlockOption: (args: CommandParameter[]) => number | null | undefined; diff --git a/backend/node_modules/ioredis/built/utils/argumentParsers.js b/backend/node_modules/ioredis/built/utils/argumentParsers.js new file mode 100644 index 0000000..7a80605 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/argumentParsers.js @@ -0,0 +1,74 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseBlockOption = exports.parseSecondsArgument = void 0; +/** + * Parses a command parameter to a number. + * @param arg - The command parameter to parse (number, string, or Buffer) + * @returns The parsed number, or undefined if parsing fails or arg is undefined + */ +const parseNumberArgument = (arg) => { + if (typeof arg === "number") { + return arg; + } + if (Buffer.isBuffer(arg)) { + return parseNumberArgument(arg.toString()); + } + if (typeof arg === "string") { + const value = Number(arg); + return Number.isFinite(value) ? value : undefined; + } + return undefined; +}; +/** + * Parses a command parameter to a string. + * @param arg - The command parameter to parse (string or Buffer) + * @returns The parsed string, or undefined if arg is not a string/Buffer or is undefined + */ +const parseStringArgument = (arg) => { + if (typeof arg === "string") { + return arg; + } + if (Buffer.isBuffer(arg)) { + return arg.toString(); + } + return undefined; +}; +/** + * Parses a command parameter as seconds and converts to milliseconds. + * @param arg - The command parameter representing seconds + * @returns The value in milliseconds, 0 if value is <= 0, or undefined if parsing fails + */ +const parseSecondsArgument = (arg) => { + const value = parseNumberArgument(arg); + if (value === undefined) { + return undefined; + } + if (value <= 0) { + return 0; + } + return value * 1000; +}; +exports.parseSecondsArgument = parseSecondsArgument; +/** + * Parses the BLOCK option from Redis command arguments (e.g., XREAD, XREADGROUP). + * @param args - Array of command parameters to search for the BLOCK option + * @returns The block duration in milliseconds, 0 if duration is <= 0, + * null if BLOCK option is not found, or undefined if BLOCK is found but duration is invalid + */ +const parseBlockOption = (args) => { + for (let i = 0; i < args.length; i++) { + const token = parseStringArgument(args[i]); + if (token && token.toLowerCase() === "block") { + const duration = parseNumberArgument(args[i + 1]); + if (duration === undefined) { + return undefined; + } + if (duration <= 0) { + return 0; + } + return duration; + } + } + return null; +}; +exports.parseBlockOption = parseBlockOption; diff --git a/backend/node_modules/ioredis/built/utils/debug.d.ts b/backend/node_modules/ioredis/built/utils/debug.d.ts new file mode 100644 index 0000000..e73b378 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/debug.d.ts @@ -0,0 +1,16 @@ +declare const MAX_ARGUMENT_LENGTH = 200; +/** + * helper function that tried to get a string value for + * arbitrary "debug" arg + */ +declare function getStringValue(v: any): string | void; +/** + * helper function that redacts a string representation of a "debug" arg + */ +declare function genRedactedString(str: string, maxLen: number): string; +/** + * a wrapper for the `debug` module, used to generate + * "debug functions" that trim the values in their output + */ +export default function genDebugFunction(namespace: string): (...args: any[]) => void; +export { MAX_ARGUMENT_LENGTH, getStringValue, genRedactedString }; diff --git a/backend/node_modules/ioredis/built/utils/debug.js b/backend/node_modules/ioredis/built/utils/debug.js new file mode 100644 index 0000000..6613511 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/debug.js @@ -0,0 +1,95 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.genRedactedString = exports.getStringValue = exports.MAX_ARGUMENT_LENGTH = void 0; +const debug_1 = require("debug"); +const MAX_ARGUMENT_LENGTH = 200; +exports.MAX_ARGUMENT_LENGTH = MAX_ARGUMENT_LENGTH; +const NAMESPACE_PREFIX = "ioredis"; +/** + * helper function that tried to get a string value for + * arbitrary "debug" arg + */ +function getStringValue(v) { + if (v === null) { + return; + } + switch (typeof v) { + case "boolean": + return; + case "number": + return; + case "object": + if (Buffer.isBuffer(v)) { + return v.toString("hex"); + } + if (Array.isArray(v)) { + return v.join(","); + } + try { + return JSON.stringify(v); + } + catch (e) { + return; + } + case "string": + return v; + } +} +exports.getStringValue = getStringValue; +/** + * helper function that redacts a string representation of a "debug" arg + */ +function genRedactedString(str, maxLen) { + const { length } = str; + return length <= maxLen + ? str + : str.slice(0, maxLen) + ' ... '; +} +exports.genRedactedString = genRedactedString; +/** + * a wrapper for the `debug` module, used to generate + * "debug functions" that trim the values in their output + */ +function genDebugFunction(namespace) { + const fn = (0, debug_1.default)(`${NAMESPACE_PREFIX}:${namespace}`); + function wrappedDebug(...args) { + if (!fn.enabled) { + return; // no-op + } + // we skip the first arg because that is the message + for (let i = 1; i < args.length; i++) { + const str = getStringValue(args[i]); + if (typeof str === "string" && str.length > MAX_ARGUMENT_LENGTH) { + args[i] = genRedactedString(str, MAX_ARGUMENT_LENGTH); + } + } + return fn.apply(null, args); + } + Object.defineProperties(wrappedDebug, { + namespace: { + get() { + return fn.namespace; + }, + }, + enabled: { + get() { + return fn.enabled; + }, + }, + destroy: { + get() { + return fn.destroy; + }, + }, + log: { + get() { + return fn.log; + }, + set(l) { + fn.log = l; + }, + }, + }); + return wrappedDebug; +} +exports.default = genDebugFunction; diff --git a/backend/node_modules/ioredis/built/utils/index.d.ts b/backend/node_modules/ioredis/built/utils/index.d.ts new file mode 100644 index 0000000..8c0772e --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/index.d.ts @@ -0,0 +1,124 @@ +/// +import { defaults, noop } from "./lodash"; +import { Callback } from "../types"; +import Debug from "./debug"; +/** + * Convert a buffer to string, supports buffer array + * + * @example + * ```js + * const input = [Buffer.from('foo'), [Buffer.from('bar')]] + * const res = convertBufferToString(input, 'utf8') + * expect(res).to.eql(['foo', ['bar']]) + * ``` + */ +export declare function convertBufferToString(value: any, encoding?: BufferEncoding): any; +/** + * Convert a list of results to node-style + * + * @example + * ```js + * const input = ['a', 'b', new Error('c'), 'd'] + * const output = exports.wrapMultiResult(input) + * expect(output).to.eql([[null, 'a'], [null, 'b'], [new Error('c')], [null, 'd']) + * ``` + */ +export declare function wrapMultiResult(arr: unknown[] | null): unknown[][] | null; +/** + * Detect if the argument is a int + * @example + * ```js + * > isInt('123') + * true + * > isInt('123.3') + * false + * > isInt('1x') + * false + * > isInt(123) + * true + * > isInt(true) + * false + * ``` + */ +export declare function isInt(value: any): value is string; +/** + * Pack an array to an Object + * + * @example + * ```js + * > packObject(['a', 'b', 'c', 'd']) + * { a: 'b', c: 'd' } + * ``` + */ +export declare function packObject(array: any[]): Record; +/** + * Return a callback with timeout + */ +export declare function timeout(callback: Callback, timeout: number): Callback; +/** + * Convert an object to an array + * @example + * ```js + * > convertObjectToArray({ a: '1' }) + * ['a', '1'] + * ``` + */ +export declare function convertObjectToArray(obj: Record): (string | T)[]; +/** + * Convert a map to an array + * @example + * ```js + * > convertMapToArray(new Map([[1, '2']])) + * [1, '2'] + * ``` + */ +export declare function convertMapToArray(map: Map): (K | V)[]; +/** + * Convert a non-string arg to a string + */ +export declare function toArg(arg: any): string; +/** + * Optimize error stack + * + * @param error actually error + * @param friendlyStack the stack that more meaningful + * @param filterPath only show stacks with the specified path + */ +export declare function optimizeErrorStack(error: Error, friendlyStack: string, filterPath: string): Error; +/** + * Parse the redis protocol url + */ +export declare function parseURL(url: string): Record; +interface TLSOptions { + port: number; + host: string; + [key: string]: any; +} +/** + * Resolve TLS profile shortcut in connection options + */ +export declare function resolveTLSProfile(options: TLSOptions): TLSOptions; +/** + * Get a random element from `array` + */ +export declare function sample(array: T[], from?: number): T; +/** + * Shuffle the array using the Fisher-Yates Shuffle. + * This method will mutate the original array. + */ +export declare function shuffle(array: T[]): T[]; +/** + * Error message for connection being disconnected + */ +export declare const CONNECTION_CLOSED_ERROR_MSG = "Connection is closed."; +export declare function zipMap(keys: K[], values: V[]): Map; +/** + * Retrieves cached package metadata from package.json. + * + * @internal + * @returns {Promise<{version: string} | null>} Package metadata or null if unavailable + */ +export declare function getPackageMeta(): Promise<{ + version: string; +}>; +export { Debug, defaults, noop }; diff --git a/backend/node_modules/ioredis/built/utils/index.js b/backend/node_modules/ioredis/built/utils/index.js new file mode 100644 index 0000000..cabc98a --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/index.js @@ -0,0 +1,332 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.noop = exports.defaults = exports.Debug = exports.getPackageMeta = exports.zipMap = exports.CONNECTION_CLOSED_ERROR_MSG = exports.shuffle = exports.sample = exports.resolveTLSProfile = exports.parseURL = exports.optimizeErrorStack = exports.toArg = exports.convertMapToArray = exports.convertObjectToArray = exports.timeout = exports.packObject = exports.isInt = exports.wrapMultiResult = exports.convertBufferToString = void 0; +const fs_1 = require("fs"); +const path_1 = require("path"); +const url_1 = require("url"); +const lodash_1 = require("./lodash"); +Object.defineProperty(exports, "defaults", { enumerable: true, get: function () { return lodash_1.defaults; } }); +Object.defineProperty(exports, "noop", { enumerable: true, get: function () { return lodash_1.noop; } }); +const debug_1 = require("./debug"); +exports.Debug = debug_1.default; +const TLSProfiles_1 = require("../constants/TLSProfiles"); +/** + * Convert a buffer to string, supports buffer array + * + * @example + * ```js + * const input = [Buffer.from('foo'), [Buffer.from('bar')]] + * const res = convertBufferToString(input, 'utf8') + * expect(res).to.eql(['foo', ['bar']]) + * ``` + */ +function convertBufferToString(value, encoding) { + if (value instanceof Buffer) { + return value.toString(encoding); + } + if (Array.isArray(value)) { + const length = value.length; + const res = Array(length); + for (let i = 0; i < length; ++i) { + res[i] = + value[i] instanceof Buffer && encoding === "utf8" + ? value[i].toString() + : convertBufferToString(value[i], encoding); + } + return res; + } + return value; +} +exports.convertBufferToString = convertBufferToString; +/** + * Convert a list of results to node-style + * + * @example + * ```js + * const input = ['a', 'b', new Error('c'), 'd'] + * const output = exports.wrapMultiResult(input) + * expect(output).to.eql([[null, 'a'], [null, 'b'], [new Error('c')], [null, 'd']) + * ``` + */ +function wrapMultiResult(arr) { + // When using WATCH/EXEC transactions, the EXEC will return + // a null instead of an array + if (!arr) { + return null; + } + const result = []; + const length = arr.length; + for (let i = 0; i < length; ++i) { + const item = arr[i]; + if (item instanceof Error) { + result.push([item]); + } + else { + result.push([null, item]); + } + } + return result; +} +exports.wrapMultiResult = wrapMultiResult; +/** + * Detect if the argument is a int + * @example + * ```js + * > isInt('123') + * true + * > isInt('123.3') + * false + * > isInt('1x') + * false + * > isInt(123) + * true + * > isInt(true) + * false + * ``` + */ +function isInt(value) { + const x = parseFloat(value); + return !isNaN(value) && (x | 0) === x; +} +exports.isInt = isInt; +/** + * Pack an array to an Object + * + * @example + * ```js + * > packObject(['a', 'b', 'c', 'd']) + * { a: 'b', c: 'd' } + * ``` + */ +function packObject(array) { + const result = {}; + const length = array.length; + for (let i = 1; i < length; i += 2) { + result[array[i - 1]] = array[i]; + } + return result; +} +exports.packObject = packObject; +/** + * Return a callback with timeout + */ +function timeout(callback, timeout) { + let timer = null; + const run = function () { + if (timer) { + clearTimeout(timer); + timer = null; + callback.apply(this, arguments); + } + }; + timer = setTimeout(run, timeout, new Error("timeout")); + return run; +} +exports.timeout = timeout; +/** + * Convert an object to an array + * @example + * ```js + * > convertObjectToArray({ a: '1' }) + * ['a', '1'] + * ``` + */ +function convertObjectToArray(obj) { + const result = []; + const keys = Object.keys(obj); // Object.entries requires node 7+ + for (let i = 0, l = keys.length; i < l; i++) { + result.push(keys[i], obj[keys[i]]); + } + return result; +} +exports.convertObjectToArray = convertObjectToArray; +/** + * Convert a map to an array + * @example + * ```js + * > convertMapToArray(new Map([[1, '2']])) + * [1, '2'] + * ``` + */ +function convertMapToArray(map) { + const result = []; + let pos = 0; + map.forEach(function (value, key) { + result[pos] = key; + result[pos + 1] = value; + pos += 2; + }); + return result; +} +exports.convertMapToArray = convertMapToArray; +/** + * Convert a non-string arg to a string + */ +function toArg(arg) { + if (arg === null || typeof arg === "undefined") { + return ""; + } + return String(arg); +} +exports.toArg = toArg; +/** + * Optimize error stack + * + * @param error actually error + * @param friendlyStack the stack that more meaningful + * @param filterPath only show stacks with the specified path + */ +function optimizeErrorStack(error, friendlyStack, filterPath) { + const stacks = friendlyStack.split("\n"); + let lines = ""; + let i; + for (i = 1; i < stacks.length; ++i) { + if (stacks[i].indexOf(filterPath) === -1) { + break; + } + } + for (let j = i; j < stacks.length; ++j) { + lines += "\n" + stacks[j]; + } + if (error.stack) { + const pos = error.stack.indexOf("\n"); + error.stack = error.stack.slice(0, pos) + lines; + } + return error; +} +exports.optimizeErrorStack = optimizeErrorStack; +/** + * Parse the redis protocol url + */ +function parseURL(url) { + if (isInt(url)) { + return { port: url }; + } + let parsed = (0, url_1.parse)(url, true, true); + if (!parsed.slashes && url[0] !== "/") { + url = "//" + url; + parsed = (0, url_1.parse)(url, true, true); + } + const options = parsed.query || {}; + const result = {}; + if (parsed.auth) { + const index = parsed.auth.indexOf(":"); + result.username = index === -1 ? parsed.auth : parsed.auth.slice(0, index); + result.password = index === -1 ? "" : parsed.auth.slice(index + 1); + } + if (parsed.pathname) { + if (parsed.protocol === "redis:" || parsed.protocol === "rediss:") { + if (parsed.pathname.length > 1) { + result.db = parsed.pathname.slice(1); + } + } + else { + result.path = parsed.pathname; + } + } + if (parsed.host) { + result.host = parsed.hostname; + } + if (parsed.port) { + result.port = parsed.port; + } + if (typeof options.family === "string") { + const intFamily = Number.parseInt(options.family, 10); + if (!Number.isNaN(intFamily)) { + result.family = intFamily; + } + } + (0, lodash_1.defaults)(result, options); + return result; +} +exports.parseURL = parseURL; +/** + * Resolve TLS profile shortcut in connection options + */ +function resolveTLSProfile(options) { + let tls = options === null || options === void 0 ? void 0 : options.tls; + if (typeof tls === "string") + tls = { profile: tls }; + const profile = TLSProfiles_1.default[tls === null || tls === void 0 ? void 0 : tls.profile]; + if (profile) { + tls = Object.assign({}, profile, tls); + delete tls.profile; + options = Object.assign({}, options, { tls }); + } + return options; +} +exports.resolveTLSProfile = resolveTLSProfile; +/** + * Get a random element from `array` + */ +function sample(array, from = 0) { + const length = array.length; + if (from >= length) { + return null; + } + return array[from + Math.floor(Math.random() * (length - from))]; +} +exports.sample = sample; +/** + * Shuffle the array using the Fisher-Yates Shuffle. + * This method will mutate the original array. + */ +function shuffle(array) { + let counter = array.length; + // While there are elements in the array + while (counter > 0) { + // Pick a random index + const index = Math.floor(Math.random() * counter); + // Decrease counter by 1 + counter--; + // And swap the last element with it + [array[counter], array[index]] = [array[index], array[counter]]; + } + return array; +} +exports.shuffle = shuffle; +/** + * Error message for connection being disconnected + */ +exports.CONNECTION_CLOSED_ERROR_MSG = "Connection is closed."; +function zipMap(keys, values) { + const map = new Map(); + keys.forEach((key, index) => { + map.set(key, values[index]); + }); + return map; +} +exports.zipMap = zipMap; +/** + * Memoized package metadata to avoid repeated file system reads. + * + * @internal + */ +let cachedPackageMeta = null; +/** + * Retrieves cached package metadata from package.json. + * + * @internal + * @returns {Promise<{version: string} | null>} Package metadata or null if unavailable + */ +async function getPackageMeta() { + if (cachedPackageMeta) { + return cachedPackageMeta; + } + try { + const filePath = (0, path_1.resolve)(__dirname, "..", "..", "package.json"); + const data = await fs_1.promises.readFile(filePath, "utf8"); + const parsed = JSON.parse(data); + cachedPackageMeta = { + version: parsed.version, + }; + return cachedPackageMeta; + } + catch (err) { + cachedPackageMeta = { + version: "error-fetching-version", + }; + return cachedPackageMeta; + } +} +exports.getPackageMeta = getPackageMeta; diff --git a/backend/node_modules/ioredis/built/utils/lodash.d.ts b/backend/node_modules/ioredis/built/utils/lodash.d.ts new file mode 100644 index 0000000..683e214 --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/lodash.d.ts @@ -0,0 +1,4 @@ +import defaults = require("lodash.defaults"); +import isArguments = require("lodash.isarguments"); +export declare function noop(): void; +export { defaults, isArguments }; diff --git a/backend/node_modules/ioredis/built/utils/lodash.js b/backend/node_modules/ioredis/built/utils/lodash.js new file mode 100644 index 0000000..5f5eccd --- /dev/null +++ b/backend/node_modules/ioredis/built/utils/lodash.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isArguments = exports.defaults = exports.noop = void 0; +const defaults = require("lodash.defaults"); +exports.defaults = defaults; +const isArguments = require("lodash.isarguments"); +exports.isArguments = isArguments; +function noop() { } +exports.noop = noop; diff --git a/backend/node_modules/ioredis/node_modules/debug/LICENSE b/backend/node_modules/ioredis/node_modules/debug/LICENSE new file mode 100644 index 0000000..1a9820e --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/debug/LICENSE @@ -0,0 +1,20 @@ +(The MIT License) + +Copyright (c) 2014-2017 TJ Holowaychuk +Copyright (c) 2018-2021 Josh Junon + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/backend/node_modules/ioredis/node_modules/debug/README.md b/backend/node_modules/ioredis/node_modules/debug/README.md new file mode 100644 index 0000000..9ebdfbf --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/debug/README.md @@ -0,0 +1,481 @@ +# debug +[![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors) + + + +A tiny JavaScript debugging utility modelled after Node.js core's debugging +technique. Works in Node.js and web browsers. + +## Installation + +```bash +$ npm install debug +``` + +## Usage + +`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. + +Example [_app.js_](./examples/node/app.js): + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %o', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example [_worker.js_](./examples/node/worker.js): + +```js +var a = require('debug')('worker:a') + , b = require('debug')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); +``` + +The `DEBUG` environment variable is then used to enable these based on space or +comma-delimited names. + +Here are some examples: + +screen shot 2017-08-08 at 12 53 04 pm +screen shot 2017-08-08 at 12 53 38 pm +screen shot 2017-08-08 at 12 53 25 pm + +#### Windows command prompt notes + +##### CMD + +On Windows the environment variable is set using the `set` command. + +```cmd +set DEBUG=*,-not_this +``` + +Example: + +```cmd +set DEBUG=* & node app.js +``` + +##### PowerShell (VS Code default) + +PowerShell uses different syntax to set environment variables. + +```cmd +$env:DEBUG = "*,-not_this" +``` + +Example: + +```cmd +$env:DEBUG='app';node app.js +``` + +Then, run the program to be debugged as usual. + +npm script example: +```js + "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js", +``` + +## Namespace Colors + +Every debug instance has a color generated for it based on its namespace name. +This helps when visually parsing the debug output to identify which debug instance +a debug line belongs to. + +#### Node.js + +In Node.js, colors are enabled when stderr is a TTY. You also _should_ install +the [`supports-color`](https://npmjs.org/supports-color) module alongside debug, +otherwise debug will only use a small handful of basic colors. + + + +#### Web Browser + +Colors are also enabled on "Web Inspectors" that understand the `%c` formatting +option. These are WebKit web inspectors, Firefox ([since version +31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) +and the Firebug plugin for Firefox (any version). + + + + +## Millisecond diff + +When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + + +When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below: + + + + +## Conventions + +If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output. + +## Wildcards + +The `*` character may be used as a wildcard. Suppose for example your library has +debuggers named "connect:bodyParser", "connect:compress", "connect:session", +instead of listing all three with +`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do +`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + +You can also exclude specific debuggers by prefixing them with a "-" character. +For example, `DEBUG=*,-connect:*` would include all debuggers except those +starting with "connect:". + +## Environment Variables + +When running through Node.js, you can set a few environment variables that will +change the behavior of the debug logging: + +| Name | Purpose | +|-----------|-------------------------------------------------| +| `DEBUG` | Enables/disables specific debugging namespaces. | +| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). | +| `DEBUG_COLORS`| Whether or not to use colors in the debug output. | +| `DEBUG_DEPTH` | Object inspection depth. | +| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | + + +__Note:__ The environment variables beginning with `DEBUG_` end up being +converted into an Options object that gets used with `%o`/`%O` formatters. +See the Node.js documentation for +[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) +for the complete list. + +## Formatters + +Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. +Below are the officially supported formatters: + +| Formatter | Representation | +|-----------|----------------| +| `%O` | Pretty-print an Object on multiple lines. | +| `%o` | Pretty-print an Object all on a single line. | +| `%s` | String. | +| `%d` | Number (both integer and float). | +| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | +| `%%` | Single percent sign ('%'). This does not consume an argument. | + + +### Custom formatters + +You can add custom formatters by extending the `debug.formatters` object. +For example, if you wanted to add support for rendering a Buffer as hex with +`%h`, you could do something like: + +```js +const createDebug = require('debug') +createDebug.formatters.h = (v) => { + return v.toString('hex') +} + +// …elsewhere +const debug = createDebug('foo') +debug('this is hex: %h', new Buffer('hello world')) +// foo this is hex: 68656c6c6f20776f726c6421 +0ms +``` + + +## Browser Support + +You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), +or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), +if you don't want to build it yourself. + +Debug's enable state is currently persisted by `localStorage`. +Consider the situation shown below where you have `worker:a` and `worker:b`, +and wish to debug both. You can enable this using `localStorage.debug`: + +```js +localStorage.debug = 'worker:*' +``` + +And then refresh the page. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + b('doing some work'); +}, 1200); +``` + +In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by `debug` if the "Verbose" log level is _enabled_. + + + +## Output streams + + By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: + +Example [_stdout.js_](./examples/node/stdout.js): + +```js +var debug = require('debug'); +var error = debug('app:error'); + +// by default stderr is used +error('goes to stderr!'); + +var log = debug('app:log'); +// set this namespace to log via console.log +log.log = console.log.bind(console); // don't forget to bind to console! +log('goes to stdout'); +error('still goes to stderr!'); + +// set all output to go via console.info +// overrides all per-namespace log settings +debug.log = console.info.bind(console); +error('now goes to stdout via console.info'); +log('still goes to stdout, but via console.info now'); +``` + +## Extend +You can simply extend debugger +```js +const log = require('debug')('auth'); + +//creates new debug instance with extended namespace +const logSign = log.extend('sign'); +const logLogin = log.extend('login'); + +log('hello'); // auth hello +logSign('hello'); //auth:sign hello +logLogin('hello'); //auth:login hello +``` + +## Set dynamically + +You can also enable debug dynamically by calling the `enable()` method : + +```js +let debug = require('debug'); + +console.log(1, debug.enabled('test')); + +debug.enable('test'); +console.log(2, debug.enabled('test')); + +debug.disable(); +console.log(3, debug.enabled('test')); + +``` + +print : +``` +1 false +2 true +3 false +``` + +Usage : +`enable(namespaces)` +`namespaces` can include modes separated by a colon and wildcards. + +Note that calling `enable()` completely overrides previously set DEBUG variable : + +``` +$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))' +=> false +``` + +`disable()` + +Will disable all namespaces. The functions returns the namespaces currently +enabled (and skipped). This can be useful if you want to disable debugging +temporarily without knowing what was enabled to begin with. + +For example: + +```js +let debug = require('debug'); +debug.enable('foo:*,-foo:bar'); +let namespaces = debug.disable(); +debug.enable(namespaces); +``` + +Note: There is no guarantee that the string will be identical to the initial +enable string, but semantically they will be identical. + +## Checking whether a debug target is enabled + +After you've created a debug instance, you can determine whether or not it is +enabled by checking the `enabled` property: + +```javascript +const debug = require('debug')('http'); + +if (debug.enabled) { + // do stuff... +} +``` + +You can also manually toggle this property to force the debug instance to be +enabled or disabled. + +## Usage in child processes + +Due to the way `debug` detects if the output is a TTY or not, colors are not shown in child processes when `stderr` is piped. A solution is to pass the `DEBUG_COLORS=1` environment variable to the child process. +For example: + +```javascript +worker = fork(WORKER_WRAP_PATH, [workerPath], { + stdio: [ + /* stdin: */ 0, + /* stdout: */ 'pipe', + /* stderr: */ 'pipe', + 'ipc', + ], + env: Object.assign({}, process.env, { + DEBUG_COLORS: 1 // without this settings, colors won't be shown + }), +}); + +worker.stderr.pipe(process.stderr, { end: false }); +``` + + +## Authors + + - TJ Holowaychuk + - Nathan Rajlich + - Andrew Rhyne + - Josh Junon + +## Backers + +Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Sponsors + +Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## License + +(The MIT License) + +Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca> +Copyright (c) 2018-2021 Josh Junon + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/backend/node_modules/ioredis/node_modules/debug/package.json b/backend/node_modules/ioredis/node_modules/debug/package.json new file mode 100644 index 0000000..ee8abb5 --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/debug/package.json @@ -0,0 +1,64 @@ +{ + "name": "debug", + "version": "4.4.3", + "repository": { + "type": "git", + "url": "git://github.com/debug-js/debug.git" + }, + "description": "Lightweight debugging utility for Node.js and the browser", + "keywords": [ + "debug", + "log", + "debugger" + ], + "files": [ + "src", + "LICENSE", + "README.md" + ], + "author": "Josh Junon (https://github.com/qix-)", + "contributors": [ + "TJ Holowaychuk ", + "Nathan Rajlich (http://n8.io)", + "Andrew Rhyne " + ], + "license": "MIT", + "scripts": { + "lint": "xo", + "test": "npm run test:node && npm run test:browser && npm run lint", + "test:node": "mocha test.js test.node.js", + "test:browser": "karma start --single-run", + "test:coverage": "cat ./coverage/lcov.info | coveralls" + }, + "dependencies": { + "ms": "^2.1.3" + }, + "devDependencies": { + "brfs": "^2.0.1", + "browserify": "^16.2.3", + "coveralls": "^3.0.2", + "karma": "^3.1.4", + "karma-browserify": "^6.0.0", + "karma-chrome-launcher": "^2.2.0", + "karma-mocha": "^1.3.0", + "mocha": "^5.2.0", + "mocha-lcov-reporter": "^1.2.0", + "sinon": "^14.0.0", + "xo": "^0.23.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + }, + "main": "./src/index.js", + "browser": "./src/browser.js", + "engines": { + "node": ">=6.0" + }, + "xo": { + "rules": { + "import/extensions": "off" + } + } +} diff --git a/backend/node_modules/ioredis/node_modules/debug/src/browser.js b/backend/node_modules/ioredis/node_modules/debug/src/browser.js new file mode 100644 index 0000000..5993451 --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/debug/src/browser.js @@ -0,0 +1,272 @@ +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + let m; + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + // eslint-disable-next-line no-return-assign + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = require('./common')(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; diff --git a/backend/node_modules/ioredis/node_modules/debug/src/common.js b/backend/node_modules/ioredis/node_modules/debug/src/common.js new file mode 100644 index 0000000..141cb57 --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/debug/src/common.js @@ -0,0 +1,292 @@ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require('ms'); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + + createDebug.names = []; + createDebug.skips = []; + + const split = (typeof namespaces === 'string' ? namespaces : '') + .trim() + .replace(/\s+/g, ',') + .split(',') + .filter(Boolean); + + for (const ns of split) { + if (ns[0] === '-') { + createDebug.skips.push(ns.slice(1)); + } else { + createDebug.names.push(ns); + } + } + } + + /** + * Checks if the given string matches a namespace template, honoring + * asterisks as wildcards. + * + * @param {String} search + * @param {String} template + * @return {Boolean} + */ + function matchesTemplate(search, template) { + let searchIndex = 0; + let templateIndex = 0; + let starIndex = -1; + let matchIndex = 0; + + while (searchIndex < search.length) { + if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) { + // Match character or proceed with wildcard + if (template[templateIndex] === '*') { + starIndex = templateIndex; + matchIndex = searchIndex; + templateIndex++; // Skip the '*' + } else { + searchIndex++; + templateIndex++; + } + } else if (starIndex !== -1) { // eslint-disable-line no-negated-condition + // Backtrack to the last '*' and try to match more characters + templateIndex = starIndex + 1; + matchIndex++; + searchIndex = matchIndex; + } else { + return false; // No match + } + } + + // Handle trailing '*' in template + while (templateIndex < template.length && template[templateIndex] === '*') { + templateIndex++; + } + + return templateIndex === template.length; + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names, + ...createDebug.skips.map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + for (const skip of createDebug.skips) { + if (matchesTemplate(name, skip)) { + return false; + } + } + + for (const ns of createDebug.names) { + if (matchesTemplate(name, ns)) { + return true; + } + } + + return false; + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; diff --git a/backend/node_modules/ioredis/node_modules/debug/src/index.js b/backend/node_modules/ioredis/node_modules/debug/src/index.js new file mode 100644 index 0000000..bf4c57f --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/debug/src/index.js @@ -0,0 +1,10 @@ +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = require('./browser.js'); +} else { + module.exports = require('./node.js'); +} diff --git a/backend/node_modules/ioredis/node_modules/debug/src/node.js b/backend/node_modules/ioredis/node_modules/debug/src/node.js new file mode 100644 index 0000000..715560a --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/debug/src/node.js @@ -0,0 +1,263 @@ +/** + * Module dependencies. + */ + +const tty = require('tty'); +const util = require('util'); + +/** + * This is the Node.js implementation of `debug()`. + */ + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.destroy = util.deprecate( + () => {}, + 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' +); + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = require('supports-color'); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; +} + +/** + * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr. + */ + +function log(...args) { + return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +module.exports = require('./common')(exports); + +const {formatters} = module.exports; + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); +}; + +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; diff --git a/backend/node_modules/ioredis/node_modules/ms/index.js b/backend/node_modules/ioredis/node_modules/ms/index.js new file mode 100644 index 0000000..ea734fb --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/ms/index.js @@ -0,0 +1,162 @@ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function (val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} diff --git a/backend/node_modules/ioredis/node_modules/ms/license.md b/backend/node_modules/ioredis/node_modules/ms/license.md new file mode 100644 index 0000000..fa5d39b --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/ms/license.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 Vercel, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/backend/node_modules/ioredis/node_modules/ms/package.json b/backend/node_modules/ioredis/node_modules/ms/package.json new file mode 100644 index 0000000..4997189 --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/ms/package.json @@ -0,0 +1,38 @@ +{ + "name": "ms", + "version": "2.1.3", + "description": "Tiny millisecond conversion utility", + "repository": "vercel/ms", + "main": "./index", + "files": [ + "index.js" + ], + "scripts": { + "precommit": "lint-staged", + "lint": "eslint lib/* bin/*", + "test": "mocha tests.js" + }, + "eslintConfig": { + "extends": "eslint:recommended", + "env": { + "node": true, + "es6": true + } + }, + "lint-staged": { + "*.js": [ + "npm run lint", + "prettier --single-quote --write", + "git add" + ] + }, + "license": "MIT", + "devDependencies": { + "eslint": "4.18.2", + "expect.js": "0.3.1", + "husky": "0.14.3", + "lint-staged": "5.0.0", + "mocha": "4.0.1", + "prettier": "2.0.5" + } +} diff --git a/backend/node_modules/ioredis/node_modules/ms/readme.md b/backend/node_modules/ioredis/node_modules/ms/readme.md new file mode 100644 index 0000000..0fc1abb --- /dev/null +++ b/backend/node_modules/ioredis/node_modules/ms/readme.md @@ -0,0 +1,59 @@ +# ms + +![CI](https://github.com/vercel/ms/workflows/CI/badge.svg) + +Use this package to easily convert various time formats to milliseconds. + +## Examples + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('1y') // 31557600000 +ms('100') // 100 +ms('-3 days') // -259200000 +ms('-1h') // -3600000 +ms('-200') // -200 +``` + +### Convert from Milliseconds + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(-3 * 60000) // "-3m" +ms(ms('10 hours')) // "10h" +``` + +### Time Format Written-Out + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(-3 * 60000, { long: true }) // "-3 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +## Features + +- Works both in [Node.js](https://nodejs.org) and in the browser +- If a number is supplied to `ms`, a string with a unit is returned +- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`) +- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned + +## Related Packages + +- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time. + +## Caught a Bug? + +1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device +2. Link the package to the global module directory: `npm link` +3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms! + +As always, you can run the tests using: `npm test` diff --git a/backend/node_modules/ioredis/package.json b/backend/node_modules/ioredis/package.json new file mode 100644 index 0000000..84d530f --- /dev/null +++ b/backend/node_modules/ioredis/package.json @@ -0,0 +1,102 @@ +{ + "name": "ioredis", + "version": "5.10.1", + "description": "A robust, performance-focused and full-featured Redis client for Node.js.", + "main": "./built/index.js", + "types": "./built/index.d.ts", + "files": [ + "built/" + ], + "scripts": { + "docker:setup": "docker compose -f test/docker-compose.yml up -d --wait", + "docker:teardown": "docker compose -f test/docker-compose.yml down --volumes --remove-orphans", + "test:tsd": "npm run build && tsd", + "test:js": "TS_NODE_TRANSPILE_ONLY=true NODE_ENV=test mocha --no-experimental-strip-types \"test/helpers/*.ts\" \"test/unit/**/*.ts\" \"test/functional/**/*.ts\"", + "test:cov": "nyc npm run test:js", + "test:cluster": "TS_NODE_TRANSPILE_ONLY=true NODE_ENV=test mocha --no-experimental-strip-types \"test/cluster/**/*.ts\"", + "test": "npm run test:js && npm run test:tsd", + "lint": "eslint --ext .js,.ts ./lib", + "docs": "npx typedoc --logLevel Error --excludeExternals --excludeProtected --excludePrivate --readme none lib/index.ts", + "format": "prettier --write \"{,!(node_modules)/**/}*.{js,ts}\"", + "format-check": "prettier --check \"{,!(node_modules)/**/}*.{js,ts}\"", + "build": "rm -rf built && tsc", + "prepublishOnly": "npm run build", + "semantic-release": "semantic-release" + }, + "repository": { + "type": "git", + "url": "git://github.com/luin/ioredis.git" + }, + "keywords": [ + "redis", + "cluster", + "sentinel", + "pipelining" + ], + "tsd": { + "directory": "test/typing" + }, + "author": "Zihua Li (http://zihua.li)", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + }, + "dependencies": { + "@ioredis/commands": "1.5.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "devDependencies": { + "@ioredis/interface-generator": "^1.3.0", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/commit-analyzer": "^9.0.2", + "@semantic-release/git": "^10.0.1", + "@types/chai": "^4.3.0", + "@types/chai-as-promised": "^7.1.5", + "@types/debug": "^4.1.5", + "@types/lodash.defaults": "^4.2.7", + "@types/lodash.isarguments": "^3.1.7", + "@types/mocha": "^9.1.0", + "@types/node": "^14.18.12", + "@types/redis-errors": "^1.2.1", + "@types/sinon": "^10.0.11", + "@typescript-eslint/eslint-plugin": "^5.48.1", + "@typescript-eslint/parser": "^5.48.1", + "chai": "^4.3.6", + "chai-as-promised": "^7.1.1", + "eslint": "^8.31.0", + "eslint-config-prettier": "^8.6.0", + "mocha": "^9.2.1", + "nyc": "^15.1.0", + "prettier": "^2.6.1", + "semantic-release": "^19.0.2", + "server-destroy": "^1.0.1", + "sinon": "^13.0.1", + "ts-node": "^10.4.0", + "tsd": "^0.19.1", + "typedoc": "^0.22.18", + "typescript": "^4.6.3", + "uuid": "^9.0.0" + }, + "nyc": { + "reporter": [ + "lcov" + ] + }, + "engines": { + "node": ">=12.22.0" + }, + "mocha": { + "exit": true, + "timeout": 8000, + "recursive": true, + "require": "ts-node/register" + } +} diff --git a/backend/node_modules/lodash.defaults/LICENSE b/backend/node_modules/lodash.defaults/LICENSE new file mode 100644 index 0000000..e0c69d5 --- /dev/null +++ b/backend/node_modules/lodash.defaults/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/backend/node_modules/lodash.defaults/README.md b/backend/node_modules/lodash.defaults/README.md new file mode 100644 index 0000000..a129849 --- /dev/null +++ b/backend/node_modules/lodash.defaults/README.md @@ -0,0 +1,18 @@ +# lodash.defaults v4.2.0 + +The [lodash](https://lodash.com/) method `_.defaults` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash.defaults +``` + +In Node.js: +```js +var defaults = require('lodash.defaults'); +``` + +See the [documentation](https://lodash.com/docs#defaults) or [package source](https://github.com/lodash/lodash/blob/4.2.0-npm-packages/lodash.defaults) for more details. diff --git a/backend/node_modules/lodash.defaults/index.js b/backend/node_modules/lodash.defaults/index.js new file mode 100644 index 0000000..25eba9c --- /dev/null +++ b/backend/node_modules/lodash.defaults/index.js @@ -0,0 +1,668 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + // Safari 9 makes `arguments.length` enumerable in strict mode. + var result = (isArray(value) || isArguments(value)) + ? baseTimes(value.length, String) + : []; + + var length = result.length, + skipIndexes = !!length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && (key == 'length' || isIndex(key, length)))) { + result.push(key); + } + } + return result; +} + +/** + * Used by `_.defaults` to customize its `_.assignIn` use. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ +function assignInDefaults(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; +} + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + object[key] = value; + } +} + +/** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; +} + +/** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ +function baseRest(func, start) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = array; + return apply(func, this, otherArgs); + }; +} + +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ +function copyObject(source, props, object, customizer) { + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + assignValue(object, key, newValue === undefined ? source[key] : newValue); + } + return object; +} + +/** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ +function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); +} + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); +} + +/** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ +function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; +} + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; +} + +/** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); +}); + +/** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var defaults = baseRest(function(args) { + args.push(undefined, assignInDefaults); + return apply(assignInWith, undefined, args); +}); + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); +} + +module.exports = defaults; diff --git a/backend/node_modules/lodash.defaults/package.json b/backend/node_modules/lodash.defaults/package.json new file mode 100644 index 0000000..3c49784 --- /dev/null +++ b/backend/node_modules/lodash.defaults/package.json @@ -0,0 +1,17 @@ +{ + "name": "lodash.defaults", + "version": "4.2.0", + "description": "The lodash method `_.defaults` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "keywords": "lodash-modularized, defaults", + "author": "John-David Dalton (http://allyoucanleet.com/)", + "contributors": [ + "John-David Dalton (http://allyoucanleet.com/)", + "Blaine Bublitz (https://github.com/phated)", + "Mathias Bynens (https://mathiasbynens.be/)" + ], + "repository": "lodash/lodash", + "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" } +} diff --git a/backend/node_modules/lodash.isarguments/LICENSE b/backend/node_modules/lodash.isarguments/LICENSE new file mode 100644 index 0000000..e0c69d5 --- /dev/null +++ b/backend/node_modules/lodash.isarguments/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/backend/node_modules/lodash.isarguments/README.md b/backend/node_modules/lodash.isarguments/README.md new file mode 100644 index 0000000..eb95fe1 --- /dev/null +++ b/backend/node_modules/lodash.isarguments/README.md @@ -0,0 +1,18 @@ +# lodash.isarguments v3.1.0 + +The [lodash](https://lodash.com/) method `_.isArguments` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash.isarguments +``` + +In Node.js: +```js +var isArguments = require('lodash.isarguments'); +``` + +See the [documentation](https://lodash.com/docs#isArguments) or [package source](https://github.com/lodash/lodash/blob/3.1.0-npm-packages/lodash.isarguments) for more details. diff --git a/backend/node_modules/lodash.isarguments/index.js b/backend/node_modules/lodash.isarguments/index.js new file mode 100644 index 0000000..042dac5 --- /dev/null +++ b/backend/node_modules/lodash.isarguments/index.js @@ -0,0 +1,229 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +module.exports = isArguments; diff --git a/backend/node_modules/lodash.isarguments/package.json b/backend/node_modules/lodash.isarguments/package.json new file mode 100644 index 0000000..3d32280 --- /dev/null +++ b/backend/node_modules/lodash.isarguments/package.json @@ -0,0 +1,17 @@ +{ + "name": "lodash.isarguments", + "version": "3.1.0", + "description": "The lodash method `_.isArguments` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "keywords": "lodash-modularized, isarguments", + "author": "John-David Dalton (http://allyoucanleet.com/)", + "contributors": [ + "John-David Dalton (http://allyoucanleet.com/)", + "Blaine Bublitz (https://github.com/phated)", + "Mathias Bynens (https://mathiasbynens.be/)" + ], + "repository": "lodash/lodash", + "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" } +} diff --git a/backend/node_modules/node-cron/LICENSE.md b/backend/node_modules/node-cron/LICENSE.md new file mode 100644 index 0000000..3da3ff0 --- /dev/null +++ b/backend/node_modules/node-cron/LICENSE.md @@ -0,0 +1,7 @@ +## ISC License + +Copyright (c) 2016, Lucas Merencia \ + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/backend/node_modules/node-cron/README.md b/backend/node_modules/node-cron/README.md new file mode 100644 index 0000000..8c1c3cc --- /dev/null +++ b/backend/node_modules/node-cron/README.md @@ -0,0 +1,117 @@ +# Node Cron + +[![npm](https://img.shields.io/npm/l/node-cron.svg)](https://github.com/merencia/node-cron/blob/master/LICENSE.md) +[![npm](https://img.shields.io/npm/v/node-cron.svg)](https://img.shields.io/npm/v/node-cron.svg) +![NPM Downloads](https://img.shields.io/npm/dm/node-cron) +[![Coverage Status](https://coveralls.io/repos/github/node-cron/node-cron/badge.svg?branch=main)](https://coveralls.io/github/node-cron/node-cron?branch=main) + +The node-cron module is tiny task scheduler in pure JavaScript for node.js based on [GNU crontab](https://www.gnu.org/software/mcron/manual/html_node/Crontab-file.html). This module allows you to schedule task in node.js using full crontab syntax. + +### [Node-Cron Documentation](http://nodecron.com) + +## Getting Started + +Install node-cron using npm: + +```console +npm install --save node-cron +``` + +Import node-cron and schedule a task: + +- commonjs + +```javascript +const cron = require('node-cron'); + +cron.schedule('* * * * *', () => { + console.log('running a task every minute'); +}); +``` + +- es6 (module) + +```javascript +import cron from 'node-cron'; + +cron.schedule('* * * * *', () => { + console.log('running a task every minute'); +}); +``` + +## Cron Syntax + +This is a quick reference to cron syntax and also shows the options supported by node-cron. + +### Allowed fields + +``` + # ┌────────────── second (optional) + # │ ┌──────────── minute + # │ │ ┌────────── hour + # │ │ │ ┌──────── day of month + # │ │ │ │ ┌────── month + # │ │ │ │ │ ┌──── day of week + # │ │ │ │ │ │ + # │ │ │ │ │ │ + # * * * * * * +``` + +### Allowed values + +| field | value | +| ------------ | --------------------------------- | +| second | 0-59 | +| minute | 0-59 | +| hour | 0-23 | +| day of month | 1-31 | +| month | 1-12 (or names) | +| day of week | 0-7 (or names, 0 or 7 are sunday) | + + +## Issues + +Feel free to submit issues and enhancement requests [here](https://github.com/merencia/node-cron/issues). + +## Contributing + +In general, we follow the "fork-and-pull" Git workflow. + +- Fork the repo on GitHub; +- Commit changes to a branch in your fork; +- Pull request "upstream" with your changes; + +NOTE: Be sure to merge the latest from "upstream" before making a pull request! + +Please do not contribute code you did not write yourself, unless you are certain you have the legal ability to do so. Also ensure all contributed code can be distributed under the ISC License. + +## Contributors + +This project exists thanks to all the people who contribute. + + + +## Backers + +Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/node-cron#backer)] + + + +## Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/node-cron#sponsor)] + + + + + + + + + + + + +## License + +node-cron is under [ISC License](https://github.com/merencia/node-cron/blob/master/LICENSE.md). diff --git a/backend/node_modules/node-cron/dist/cjs/create-id.d.ts b/backend/node_modules/node-cron/dist/cjs/create-id.d.ts new file mode 100644 index 0000000..039b33a --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/create-id.d.ts @@ -0,0 +1 @@ +export declare function createID(prefix?: string, length?: number): string; diff --git a/backend/node_modules/node-cron/dist/cjs/create-id.js b/backend/node_modules/node-cron/dist/cjs/create-id.js new file mode 100644 index 0000000..380ff18 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/create-id.js @@ -0,0 +1,14 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createID = createID; +const node_crypto_1 = __importDefault(require("node:crypto")); +function createID(prefix = '', length = 16) { + const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const values = node_crypto_1.default.randomBytes(length); + const id = Array.from(values, v => charset[v % charset.length]).join(''); + return prefix ? `${prefix}-${id}` : id; +} +//# sourceMappingURL=create-id.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/create-id.js.map b/backend/node_modules/node-cron/dist/cjs/create-id.js.map new file mode 100644 index 0000000..56bbebe --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/create-id.js.map @@ -0,0 +1 @@ +{"version":3,"file":"create-id.js","sourceRoot":"","sources":["../../src/create-id.ts"],"names":[],"mappings":";;;;;AAEA,4BAKC;AAPD,8DAAiC;AAEjC,SAAgB,QAAQ,CAAC,SAAiB,EAAE,EAAE,SAAiB,EAAE;IAC/D,MAAM,OAAO,GAAG,gEAAgE,CAAC;IACjF,MAAM,MAAM,GAAG,qBAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/logger.d.ts b/backend/node_modules/node-cron/dist/cjs/logger.d.ts new file mode 100644 index 0000000..2acbdf9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/logger.d.ts @@ -0,0 +1,7 @@ +declare const logger: { + info(message: string): void; + warn(message: string): void; + error(message: string | Error, err?: Error): void; + debug(message: string | Error, err?: Error): void; +}; +export default logger; diff --git a/backend/node_modules/node-cron/dist/cjs/logger.js b/backend/node_modules/node-cron/dist/cjs/logger.js new file mode 100644 index 0000000..e876e9b --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/logger.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const levelColors = { + INFO: '\x1b[36m', + WARN: '\x1b[33m', + ERROR: '\x1b[31m', + DEBUG: '\x1b[35m', +}; +const GREEN = '\x1b[32m'; +const RESET = '\x1b[0m'; +function log(level, message, extra) { + const timestamp = new Date().toISOString(); + const color = levelColors[level] ?? ''; + const prefix = `[${timestamp}] [PID: ${process.pid}] ${GREEN}[NODE-CRON]${GREEN} ${color}[${level}]${RESET}`; + const output = `${prefix} ${message}`; + switch (level) { + case 'ERROR': + console.error(output, extra ?? ''); + break; + case 'DEBUG': + console.debug(output, extra ?? ''); + break; + case 'WARN': + console.warn(output); + break; + case 'INFO': + default: + console.info(output); + break; + } +} +const logger = { + info(message) { + log('INFO', message); + }, + warn(message) { + log('WARN', message); + }, + error(message, err) { + if (message instanceof Error) { + log('ERROR', message.message, message); + } + else { + log('ERROR', message, err); + } + }, + debug(message, err) { + if (message instanceof Error) { + log('DEBUG', message.message, message); + } + else { + log('DEBUG', message, err); + } + }, +}; +exports.default = logger; +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/logger.js.map b/backend/node_modules/node-cron/dist/cjs/logger.js.map new file mode 100644 index 0000000..0f576ae --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":";;AAEA,MAAM,WAAW,GAA6B;IAC5C,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,KAAK,EAAE,UAAU;CAClB,CAAC;AAEF,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB,SAAS,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,KAAW;IACxD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,SAAS,WAAW,OAAO,CAAC,GAAG,KAAK,KAAK,cAAc,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;IAC7G,MAAM,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC;IAEtC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACR,KAAK,OAAO;YACR,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACV,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;QACR,KAAK,MAAM,CAAC;QACZ;YACE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;IACV,CAAC;AACH,CAAC;AAED,MAAM,MAAM,GAAG;IACb,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;CACF,CAAC;AAEF,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/node-cron.d.ts b/backend/node_modules/node-cron/dist/cjs/node-cron.d.ts new file mode 100644 index 0000000..3e221e8 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/node-cron.d.ts @@ -0,0 +1,18 @@ +import { ScheduledTask, TaskFn, TaskOptions } from "./tasks/scheduled-task"; +export declare function schedule(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask; +export declare function createTask(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask; +export declare function solvePath(filePath: string): string; +export declare function validate(expression: string): boolean; +export declare const getTasks: () => Map; +export declare const getTask: (taskId: string) => ScheduledTask | undefined; +export { ScheduledTask } from './tasks/scheduled-task'; +export type { TaskFn, TaskContext, TaskOptions } from './tasks/scheduled-task'; +export interface NodeCron { + schedule: typeof schedule; + createTask: typeof createTask; + validate: typeof validate; + getTasks: typeof getTasks; + getTask: typeof getTask; +} +export declare const nodeCron: NodeCron; +export default nodeCron; diff --git a/backend/node_modules/node-cron/dist/cjs/node-cron.js b/backend/node_modules/node-cron/dist/cjs/node-cron.js new file mode 100644 index 0000000..d378466 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/node-cron.js @@ -0,0 +1,71 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nodeCron = exports.getTask = exports.getTasks = void 0; +exports.schedule = schedule; +exports.createTask = createTask; +exports.solvePath = solvePath; +exports.validate = validate; +const inline_scheduled_task_1 = require("./tasks/inline-scheduled-task"); +const task_registry_1 = require("./task-registry"); +const pattern_validation_1 = __importDefault(require("./pattern/validation/pattern-validation")); +const background_scheduled_task_1 = __importDefault(require("./tasks/background-scheduled-task/background-scheduled-task")); +const path_1 = __importDefault(require("path")); +const url_1 = require("url"); +const registry = new task_registry_1.TaskRegistry(); +function schedule(expression, func, options) { + const task = createTask(expression, func, options); + task.start(); + return task; +} +function createTask(expression, func, options) { + let task; + if (func instanceof Function) { + task = new inline_scheduled_task_1.InlineScheduledTask(expression, func, options); + } + else { + const taskPath = solvePath(func); + task = new background_scheduled_task_1.default(expression, taskPath, options); + } + registry.add(task); + return task; +} +function solvePath(filePath) { + if (path_1.default.isAbsolute(filePath)) + return (0, url_1.pathToFileURL)(filePath).href; + if (filePath.startsWith('file://')) + return filePath; + const stackLines = new Error().stack?.split('\n'); + if (stackLines) { + stackLines?.shift(); + const callerLine = stackLines?.find((line) => { return line.indexOf(__filename) === -1; }); + const match = callerLine?.match(/(file:\/\/)?(((\/?)(\w:))?([/\\].+)):\d+:\d+/); + if (match) { + const dir = `${match[5] ?? ""}${path_1.default.dirname(match[6])}`; + return (0, url_1.pathToFileURL)(path_1.default.resolve(dir, filePath)).href; + } + } + throw new Error(`Could not locate task file ${filePath}`); +} +function validate(expression) { + try { + (0, pattern_validation_1.default)(expression); + return true; + } + catch (e) { + return false; + } +} +exports.getTasks = registry.all; +exports.getTask = registry.get; +exports.nodeCron = { + schedule, + createTask, + validate, + getTasks: exports.getTasks, + getTask: exports.getTask, +}; +exports.default = exports.nodeCron; +//# sourceMappingURL=node-cron.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/node-cron.js.map b/backend/node_modules/node-cron/dist/cjs/node-cron.js.map new file mode 100644 index 0000000..2fbda01 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/node-cron.js.map @@ -0,0 +1 @@ +{"version":3,"file":"node-cron.js","sourceRoot":"","sources":["../../src/node-cron.ts"],"names":[],"mappings":";;;;;;AA2CA,4BAIC;AAWD,gCAWC;AAUD,8BAoBC;AAQD,4BASC;AA1GD,yEAAoE;AAEpE,mDAA+C;AAE/C,iGAAiE;AACjE,4HAAkG;AAElG,gDAAwB;AACxB,6BAAoC;AAMpC,MAAM,QAAQ,GAAG,IAAI,4BAAY,EAAE,CAAC;AAmBpC,SAAgB,QAAQ,CAAC,UAAiB,EAAE,IAAqB,EAAE,OAAqB;IACpF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,OAAO,IAAI,CAAC;AAChB,CAAC;AAWD,SAAgB,UAAU,CAAC,UAAkB,EAAE,IAAqB,EAAE,OAAqB;IACvF,IAAI,IAAmB,CAAC;IACxB,IAAG,IAAI,YAAY,QAAQ,EAAC,CAAC;QAC3B,IAAI,GAAG,IAAI,2CAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,GAAG,IAAI,mCAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC;AAChB,CAAC;AAUD,SAAgB,SAAS,CAAC,QAAgB;IAExC,IAAG,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAA,mBAAa,EAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IAGlE,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEpD,MAAM,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,IAAG,UAAU,EAAC,CAAC;QACb,UAAU,EAAE,KAAK,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,UAAU,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,UAAU,EAAE,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAEhF,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,IAAA,mBAAa,EAAC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;AAC5D,CAAC;AAQD,SAAgB,QAAQ,CAAC,UAAkB;IACzC,IAAI,CAAC;QACD,IAAA,4BAAU,EAAC,UAAU,CAAC,CAAC;QAEvB,OAAO,IAAI,CAAC;IAEhB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAOY,QAAA,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC;AAQxB,QAAA,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC;AAavB,QAAA,QAAQ,GAAa;IAChC,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,QAAQ,EAAR,gBAAQ;IACR,OAAO,EAAP,eAAO;CACR,CAAC;AAKF,kBAAe,gBAAQ,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.d.ts b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.d.ts new file mode 100644 index 0000000..0184465 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expressions: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js new file mode 100644 index 0000000..d5666ea --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + function convertAsterisk(expression, replecement) { + if (expression.indexOf('*') !== -1) { + return expression.replace('*', replecement); + } + return expression; + } + function convertAsterisksToRanges(expressions) { + expressions[0] = convertAsterisk(expressions[0], '0-59'); + expressions[1] = convertAsterisk(expressions[1], '0-59'); + expressions[2] = convertAsterisk(expressions[2], '0-23'); + expressions[3] = convertAsterisk(expressions[3], '1-31'); + expressions[4] = convertAsterisk(expressions[4], '1-12'); + expressions[5] = convertAsterisk(expressions[5], '0-6'); + return expressions; + } + return convertAsterisksToRanges; +})(); +//# sourceMappingURL=asterisk-to-range-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js.map b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js.map new file mode 100644 index 0000000..882a6f9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/asterisk-to-range-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"asterisk-to-range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/asterisk-to-range-conversion.ts"],"names":[],"mappings":";;AACA,kBAAe,CAAC,GAAG,EAAE;IACjB,SAAS,eAAe,CAAC,UAAU,EAAE,WAAW;QAC5C,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAC,CAAC;YAC/B,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,wBAAwB,CAAC,WAAW;QACzC,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,wBAAwB,CAAC;AACpC,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.d.ts b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.d.ts new file mode 100644 index 0000000..9569786 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expression: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js new file mode 100644 index 0000000..2c5ade7 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js @@ -0,0 +1,42 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const month_names_conversion_1 = __importDefault(require("./month-names-conversion")); +const week_day_names_conversion_1 = __importDefault(require("./week-day-names-conversion")); +const asterisk_to_range_conversion_1 = __importDefault(require("./asterisk-to-range-conversion")); +const range_conversion_1 = __importDefault(require("./range-conversion")); +exports.default = (() => { + function appendSeccondExpression(expressions) { + if (expressions.length === 5) { + return ['0'].concat(expressions); + } + return expressions; + } + function removeSpaces(str) { + return str.replace(/\s{2,}/g, ' ').trim(); + } + function normalizeIntegers(expressions) { + for (let i = 0; i < expressions.length; i++) { + const numbers = expressions[i].split(','); + for (let j = 0; j < numbers.length; j++) { + numbers[j] = parseInt(numbers[j]); + } + expressions[i] = numbers; + } + return expressions; + } + function interprete(expression) { + let expressions = removeSpaces(`${expression}`).split(' '); + expressions = appendSeccondExpression(expressions); + expressions[4] = (0, month_names_conversion_1.default)(expressions[4]); + expressions[5] = (0, week_day_names_conversion_1.default)(expressions[5]); + expressions = (0, asterisk_to_range_conversion_1.default)(expressions); + expressions = (0, range_conversion_1.default)(expressions); + expressions = normalizeIntegers(expressions); + return expressions; + } + return interprete; +})(); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js.map b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js.map new file mode 100644 index 0000000..efd820f --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/index.ts"],"names":[],"mappings":";;;;;AAAA,sFAA4D;AAC5D,4FAAiE;AACjE,kGAAsE;AACtE,0EAA+C;AAE/C,kBAAe,CAAC,GAAG,EAAE;IAEjB,SAAS,uBAAuB,CAAC,WAAW;QACxC,IAAG,WAAW,CAAC,MAAM,KAAK,CAAC,EAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,SAAS,YAAY,CAAC,GAAG;QACrB,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAGD,SAAS,iBAAiB,CAAC,WAAW;QAClC,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACvC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;gBACjC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC;YACD,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;QAC7B,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAmBD,SAAS,UAAU,CAAC,UAAU;QAC1B,IAAI,WAAW,GAAG,YAAY,CAAC,GAAG,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;QACnD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,mCAAsB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,WAAW,GAAG,IAAA,sCAAwB,EAAC,WAAW,CAAC,CAAC;QACpD,WAAW,GAAG,IAAA,0BAAa,EAAC,WAAW,CAAC,CAAC;QAEzC,WAAW,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAE7C,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.d.ts b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.d.ts new file mode 100644 index 0000000..3204e9d --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (monthExpression: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js new file mode 100644 index 0000000..f69337c --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + const months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', + 'august', 'september', 'october', 'november', 'december']; + const shortMonths = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', + 'sep', 'oct', 'nov', 'dec']; + function convertMonthName(expression, items) { + for (let i = 0; i < items.length; i++) { + expression = expression.replace(new RegExp(items[i], 'gi'), i + 1); + } + return expression; + } + function interprete(monthExpression) { + monthExpression = convertMonthName(monthExpression, months); + monthExpression = convertMonthName(monthExpression, shortMonths); + return monthExpression; + } + return interprete; +})(); +//# sourceMappingURL=month-names-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js.map b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js.map new file mode 100644 index 0000000..6051f09 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/month-names-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"month-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/month-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,MAAM,GAAG,CAAC,SAAS,EAAC,UAAU,EAAC,OAAO,EAAC,OAAO,EAAC,KAAK,EAAC,MAAM,EAAC,MAAM;QACpE,QAAQ,EAAC,WAAW,EAAC,SAAS,EAAC,UAAU,EAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;QACvE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEhC,SAAS,gBAAgB,CAAC,UAAU,EAAE,KAAK;QACvC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,UAAU,CAAC,eAAe;QAC/B,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QAC5D,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QACjE,OAAO,eAAe,CAAC;IAC3B,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.d.ts b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.d.ts new file mode 100644 index 0000000..0184465 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expressions: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js new file mode 100644 index 0000000..5877e60 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + function replaceWithRange(expression, text, init, end, stepTxt) { + const step = parseInt(stepTxt); + const numbers = []; + let last = parseInt(end); + let first = parseInt(init); + if (first > last) { + last = parseInt(init); + first = parseInt(end); + } + for (let i = first; i <= last; i += step) { + numbers.push(i); + } + return expression.replace(new RegExp(text, 'i'), numbers.join()); + } + function convertRange(expression) { + const rangeRegEx = /(\d+)-(\d+)(\/(\d+)|)/; + let match = rangeRegEx.exec(expression); + while (match !== null && match.length > 0) { + expression = replaceWithRange(expression, match[0], match[1], match[2], match[4] || '1'); + match = rangeRegEx.exec(expression); + } + return expression; + } + function convertAllRanges(expressions) { + for (let i = 0; i < expressions.length; i++) { + expressions[i] = convertRange(expressions[i]); + } + return expressions; + } + return convertAllRanges; +})(); +//# sourceMappingURL=range-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js.map b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js.map new file mode 100644 index 0000000..dc42fdb --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/range-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/range-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAE,GAAG,EAAE;IAClB,SAAS,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE3B,IAAG,KAAK,GAAG,IAAI,EAAC,CAAC;YACb,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACtB,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,KAAI,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,SAAS,YAAY,CAAC,UAAU;QAC5B,MAAM,UAAU,GAAG,uBAAuB,CAAC;QAC3C,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAM,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAC,CAAC;YACtC,UAAU,GAAG,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YACzF,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,gBAAgB,CAAC,WAAW;QACjC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACxC,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC5B,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.d.ts b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.d.ts new file mode 100644 index 0000000..9569786 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expression: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js new file mode 100644 index 0000000..69719a9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', + 'friday', 'saturday']; + const shortWeekDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; + function convertWeekDayName(expression, items) { + for (let i = 0; i < items.length; i++) { + expression = expression.replace(new RegExp(items[i], 'gi'), i); + } + return expression; + } + function convertWeekDays(expression) { + expression = expression.replace('7', '0'); + expression = convertWeekDayName(expression, weekDays); + return convertWeekDayName(expression, shortWeekDays); + } + return convertWeekDays; +})(); +//# sourceMappingURL=week-day-names-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js.map b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js.map new file mode 100644 index 0000000..d2d6f43 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/convertion/week-day-names-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"week-day-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/week-day-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU;QACpE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC1B,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAExE,SAAS,kBAAkB,CAAC,UAAU,EAAE,KAAK;QACzC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,eAAe,CAAC,UAAU;QAC/B,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1C,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACtD,OAAO,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,eAAe,CAAC;AAC3B,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.d.ts b/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.d.ts new file mode 100644 index 0000000..67115b5 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.d.ts @@ -0,0 +1,2 @@ +declare function validate(pattern: any): void; +export default validate; diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js b/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js new file mode 100644 index 0000000..d64980f --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js @@ -0,0 +1,61 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const index_1 = __importDefault(require("../convertion/index")); +const validationRegex = /^(?:\d+|\*|\*\/\d+)$/; +function isValidExpression(expression, min, max) { + const options = expression; + for (const option of options) { + const optionAsInt = parseInt(option, 10); + if ((!Number.isNaN(optionAsInt) && + (optionAsInt < min || optionAsInt > max)) || + !validationRegex.test(option)) + return false; + } + return true; +} +function isInvalidSecond(expression) { + return !isValidExpression(expression, 0, 59); +} +function isInvalidMinute(expression) { + return !isValidExpression(expression, 0, 59); +} +function isInvalidHour(expression) { + return !isValidExpression(expression, 0, 23); +} +function isInvalidDayOfMonth(expression) { + return !isValidExpression(expression, 1, 31); +} +function isInvalidMonth(expression) { + return !isValidExpression(expression, 1, 12); +} +function isInvalidWeekDay(expression) { + return !isValidExpression(expression, 0, 7); +} +function validateFields(patterns, executablePatterns) { + if (isInvalidSecond(executablePatterns[0])) + throw new Error(`${patterns[0]} is a invalid expression for second`); + if (isInvalidMinute(executablePatterns[1])) + throw new Error(`${patterns[1]} is a invalid expression for minute`); + if (isInvalidHour(executablePatterns[2])) + throw new Error(`${patterns[2]} is a invalid expression for hour`); + if (isInvalidDayOfMonth(executablePatterns[3])) + throw new Error(`${patterns[3]} is a invalid expression for day of month`); + if (isInvalidMonth(executablePatterns[4])) + throw new Error(`${patterns[4]} is a invalid expression for month`); + if (isInvalidWeekDay(executablePatterns[5])) + throw new Error(`${patterns[5]} is a invalid expression for week day`); +} +function validate(pattern) { + if (typeof pattern !== 'string') + throw new TypeError('pattern must be a string!'); + const patterns = pattern.split(' '); + const executablePatterns = (0, index_1.default)(pattern); + if (patterns.length === 5) + patterns.unshift('0'); + validateFields(patterns, executablePatterns); +} +exports.default = validate; +//# sourceMappingURL=pattern-validation.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js.map b/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js.map new file mode 100644 index 0000000..b5c51e6 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/pattern/validation/pattern-validation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pattern-validation.js","sourceRoot":"","sources":["../../../../src/pattern/validation/pattern-validation.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.d.ts b/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.d.ts new file mode 100644 index 0000000..a5b3d6c --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.d.ts @@ -0,0 +1,19 @@ +type PromiseState = 'pending' | 'fulfilled' | 'rejected'; +export declare class TrackedPromise { + promise: Promise; + error: any; + state: PromiseState; + value?: T; + constructor(executor: (resolve: (value: T) => void, reject: (reason?: any) => void) => void); + getPromise(): Promise; + getState(): PromiseState; + isPending(): boolean; + isFulfilled(): boolean; + isRejected(): boolean; + getValue(): T | undefined; + getError(): any; + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; + finally(onfinally?: (() => void) | undefined | null): Promise; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js b/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js new file mode 100644 index 0000000..e81b2ef --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TrackedPromise = void 0; +class TrackedPromise { + promise; + error; + state; + value; + constructor(executor) { + this.state = 'pending'; + this.promise = new Promise((resolve, reject) => { + executor((value) => { + this.state = 'fulfilled'; + this.value = value; + resolve(value); + }, (error) => { + this.state = 'rejected'; + this.error = error; + reject(error); + }); + }); + } + getPromise() { + return this.promise; + } + getState() { + return this.state; + } + isPending() { + return this.state === 'pending'; + } + isFulfilled() { + return this.state === 'fulfilled'; + } + isRejected() { + return this.state === 'rejected'; + } + getValue() { + return this.value; + } + getError() { + return this.error; + } + then(onfulfilled, onrejected) { + return this.promise.then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.promise.catch(onrejected); + } + finally(onfinally) { + return this.promise.finally(onfinally); + } +} +exports.TrackedPromise = TrackedPromise; +//# sourceMappingURL=tracked-promise.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js.map b/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js.map new file mode 100644 index 0000000..d5d5c42 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/promise/tracked-promise.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tracked-promise.js","sourceRoot":"","sources":["../../../src/promise/tracked-promise.ts"],"names":[],"mappings":";;;AAEA,MAAa,cAAc;IACzB,OAAO,CAAa;IACpB,KAAK,CAAM;IACX,KAAK,CAAe;IACpB,KAAK,CAAK;IAEV,YAAY,QAA+E;QACzF,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QAEvB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChD,QAAQ,CACN,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;gBACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;gBACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;IAClC,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC;IACpC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC;IACnC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,CACF,WAAiF,EACjF,UAAmF;QAEnF,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CACH,UAAiF;QAEjF,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,SAA2C;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;CACF;AArED,wCAqEC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/scheduler/runner.d.ts b/backend/node_modules/node-cron/dist/cjs/scheduler/runner.d.ts new file mode 100644 index 0000000..2ff999c --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/scheduler/runner.d.ts @@ -0,0 +1,42 @@ +import { Execution } from "../tasks/scheduled-task"; +import { TimeMatcher } from "../time/time-matcher"; +type OnFn = (date: Date) => void | Promise; +type OnErrorHookFn = (date: Date, error: Error, execution: Execution) => void | Promise; +type OnHookFn = (date: Date, execution: Execution) => boolean | Promise; +type OnMatch = (date: Date, execution: Execution) => any | Promise; +export type RunnerOptions = { + noOverlap?: boolean; + timezone?: string; + maxExecutions?: number; + maxRandomDelay?: number; + onMissedExecution?: OnFn; + onOverlap?: OnFn; + onError?: OnErrorHookFn; + onFinished?: OnHookFn; + beforeRun?: OnHookFn; + onMaxExecutions?: OnFn; +}; +export declare class Runner { + timeMatcher: TimeMatcher; + onMatch: OnMatch; + noOverlap: boolean; + maxExecutions?: number; + maxRandomDelay: number; + runCount: number; + running: boolean; + heartBeatTimeout?: NodeJS.Timeout; + onMissedExecution: OnFn; + onOverlap: OnFn; + onError: OnErrorHookFn; + beforeRun: OnHookFn; + onFinished: OnHookFn; + onMaxExecutions: OnFn; + constructor(timeMatcher: TimeMatcher, onMatch: OnMatch, options?: RunnerOptions); + start(): void; + nextRun(): Date; + stop(): void; + isStarted(): boolean; + isStopped(): boolean; + execute(): Promise; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/cjs/scheduler/runner.js b/backend/node_modules/node-cron/dist/cjs/scheduler/runner.js new file mode 100644 index 0000000..11ffa77 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/scheduler/runner.js @@ -0,0 +1,192 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Runner = void 0; +const create_id_1 = require("../create-id"); +const logger_1 = __importDefault(require("../logger")); +const tracked_promise_1 = require("../promise/tracked-promise"); +function emptyOnFn() { } +; +function emptyHookFn() { return true; } +; +function defaultOnError(date, error) { + logger_1.default.error('Task failed with error!', error); +} +class Runner { + timeMatcher; + onMatch; + noOverlap; + maxExecutions; + maxRandomDelay; + runCount; + running; + heartBeatTimeout; + onMissedExecution; + onOverlap; + onError; + beforeRun; + onFinished; + onMaxExecutions; + constructor(timeMatcher, onMatch, options) { + this.timeMatcher = timeMatcher; + this.onMatch = onMatch; + this.noOverlap = options == undefined || options.noOverlap === undefined ? false : options.noOverlap; + this.maxExecutions = options?.maxExecutions; + this.maxRandomDelay = options?.maxRandomDelay || 0; + this.onMissedExecution = options?.onMissedExecution || emptyOnFn; + this.onOverlap = options?.onOverlap || emptyOnFn; + this.onError = options?.onError || defaultOnError; + this.onFinished = options?.onFinished || emptyHookFn; + this.beforeRun = options?.beforeRun || emptyHookFn; + this.onMaxExecutions = options?.onMaxExecutions || emptyOnFn; + this.runCount = 0; + this.running = false; + } + start() { + this.running = true; + let lastExecution; + let expectedNextExecution; + const scheduleNextHeartBeat = (currentDate) => { + if (this.running) { + clearTimeout(this.heartBeatTimeout); + this.heartBeatTimeout = setTimeout(heartBeat, getDelay(this.timeMatcher, currentDate)); + } + }; + const runTask = (date) => { + return new Promise(async (resolve) => { + const execution = { + id: (0, create_id_1.createID)('exec'), + reason: 'scheduled' + }; + const shouldExecute = await this.beforeRun(date, execution); + const randomDelay = Math.floor(Math.random() * this.maxRandomDelay); + if (shouldExecute) { + setTimeout(async () => { + try { + this.runCount++; + execution.startedAt = new Date(); + const result = await this.onMatch(date, execution); + execution.finishedAt = new Date(); + execution.result = result; + this.onFinished(date, execution); + if (this.maxExecutions && this.runCount >= this.maxExecutions) { + this.onMaxExecutions(date); + this.stop(); + } + } + catch (error) { + execution.finishedAt = new Date(); + execution.error = error; + this.onError(date, error, execution); + } + resolve(true); + }, randomDelay); + } + }); + }; + const checkAndRun = (date) => { + return new tracked_promise_1.TrackedPromise(async (resolve, reject) => { + try { + if (this.timeMatcher.match(date)) { + await runTask(date); + } + resolve(true); + } + catch (err) { + reject(err); + } + }); + }; + const heartBeat = async () => { + const currentDate = nowWithoutMs(); + if (expectedNextExecution && expectedNextExecution.getTime() < currentDate.getTime()) { + while (expectedNextExecution.getTime() < currentDate.getTime()) { + logger_1.default.warn(`missed execution at ${expectedNextExecution}! Possible blocking IO or high CPU user at the same process used by node-cron.`); + expectedNextExecution = this.timeMatcher.getNextMatch(expectedNextExecution); + runAsync(this.onMissedExecution, expectedNextExecution, defaultOnError); + } + } + if (lastExecution && lastExecution.getState() === 'pending') { + runAsync(this.onOverlap, currentDate, defaultOnError); + if (this.noOverlap) { + logger_1.default.warn('task still running, new execution blocked by overlap prevention!'); + expectedNextExecution = this.timeMatcher.getNextMatch(currentDate); + scheduleNextHeartBeat(currentDate); + return; + } + } + lastExecution = checkAndRun(currentDate); + expectedNextExecution = this.timeMatcher.getNextMatch(currentDate); + scheduleNextHeartBeat(currentDate); + }; + this.heartBeatTimeout = setTimeout(() => { + heartBeat(); + }, getDelay(this.timeMatcher, nowWithoutMs())); + } + nextRun() { + return this.timeMatcher.getNextMatch(new Date()); + } + stop() { + this.running = false; + if (this.heartBeatTimeout) { + clearTimeout(this.heartBeatTimeout); + this.heartBeatTimeout = undefined; + } + } + isStarted() { + return !!this.heartBeatTimeout && this.running; + } + isStopped() { + return !this.isStarted(); + } + async execute() { + const date = new Date(); + const execution = { + id: (0, create_id_1.createID)('exec'), + reason: 'invoked' + }; + try { + const shouldExecute = await this.beforeRun(date, execution); + if (shouldExecute) { + this.runCount++; + execution.startedAt = new Date(); + const result = await this.onMatch(date, execution); + execution.finishedAt = new Date(); + execution.result = result; + this.onFinished(date, execution); + } + } + catch (error) { + execution.finishedAt = new Date(); + execution.error = error; + this.onError(date, error, execution); + } + } +} +exports.Runner = Runner; +async function runAsync(fn, date, onError) { + try { + await fn(date); + } + catch (error) { + onError(date, error); + } +} +function getDelay(timeMatcher, currentDate) { + const maxDelay = 86400000; + const nextRun = timeMatcher.getNextMatch(currentDate); + const now = new Date(); + const delay = nextRun.getTime() - now.getTime(); + if (delay > maxDelay) { + return maxDelay; + } + return Math.max(0, delay); +} +function nowWithoutMs() { + const date = new Date(); + date.setMilliseconds(0); + return date; +} +//# sourceMappingURL=runner.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/scheduler/runner.js.map b/backend/node_modules/node-cron/dist/cjs/scheduler/runner.js.map new file mode 100644 index 0000000..112ddfa --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/scheduler/runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/scheduler/runner.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAwC;AACxC,uDAA+B;AAC/B,gEAA4D;AAW5D,SAAS,SAAS,KAAG,CAAC;AAAA,CAAC;AACvB,SAAS,WAAW,KAAI,OAAO,IAAI,CAAA,CAAC,CAAC;AAAA,CAAC;AAEtC,SAAS,cAAc,CAAC,IAAU,EAAE,KAAY;IAC9C,gBAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;AACjD,CAAC;AAeD,MAAa,MAAM;IACjB,WAAW,CAAc;IACzB,OAAO,CAAU;IACjB,SAAS,CAAU;IACnB,aAAa,CAAU;IACvB,cAAc,CAAS;IACvB,QAAQ,CAAS;IAEjB,OAAO,CAAU;IAEjB,gBAAgB,CAAkB;IAClC,iBAAiB,CAAO;IACxB,SAAS,CAAO;IAChB,OAAO,CAAgB;IACvB,SAAS,CAAW;IACpB,UAAU,CAAW;IACrB,eAAe,CAAO;IAEtB,YAAY,WAAwB,EAAE,OAAgB,EAAE,OAAuB;QAC3E,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,OAAO,IAAI,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;QACrG,IAAI,CAAC,aAAa,GAAG,OAAO,EAAE,aAAa,CAAC;QAC5C,IAAI,CAAC,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,CAAC,CAAC;QAEnD,IAAI,CAAC,iBAAiB,GAAG,OAAO,EAAE,iBAAiB,IAAI,SAAS,CAAC;QACjE,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,SAAS,CAAC;QAEjD,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,cAAc,CAAC;QAClD,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,WAAW,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,WAAW,CAAC;QAEnD,IAAI,CAAC,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,SAAS,CAAC;QAE7D,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,aAAkC,CAAC;QACvC,IAAI,qBAA2B,CAAC;QAEhC,MAAM,qBAAqB,GAAG,CAAC,WAAiB,EAAE,EAAE;YAClD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACf,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACpC,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,CAAC,IAAU,EAAgB,EAAE;YAC3C,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBACnC,MAAM,SAAS,GAAc;oBAC3B,EAAE,EAAE,IAAA,oBAAQ,EAAC,MAAM,CAAC;oBACpB,MAAM,EAAE,WAAW;iBACpB,CAAA;gBAED,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;gBAEpE,IAAG,aAAa,EAAC,CAAC;oBAEhB,UAAU,CAAC,KAAK,IAAI,EAAE;wBACpB,IAAI,CAAC;4BACH,IAAI,CAAC,QAAQ,EAAE,CAAC;4BAChB,SAAS,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;4BACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;4BACnD,SAAS,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;4BAClC,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;4BAC1B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;4BAEjC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,aAAa,EAAC,CAAC;gCAC7D,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;gCAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;4BACd,CAAC;wBACH,CAAC;wBAAC,OAAO,KAAU,EAAC,CAAC;4BACnB,SAAS,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;4BAClC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;4BACxB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;wBACvC,CAAC;wBAED,OAAO,CAAC,IAAI,CAAC,CAAC;oBAChB,CAAC,EAAE,WAAW,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;QAED,MAAM,WAAW,GAAG,CAAC,IAAU,EAAuB,EAAE;YACtD,OAAO,IAAI,gCAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;gBACpD,IAAI,CAAC;oBACH,IAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAC,CAAC;wBAC/B,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;oBACtB,CAAC;oBACD,OAAO,CAAC,IAAI,CAAC,CAAC;gBACf,CAAC;gBAAC,OAAM,GAAG,EAAE,CAAC;oBACZ,MAAM,CAAC,GAAG,CAAC,CAAA;gBACb,CAAC;YACF,CAAC,CAAC,CAAC;QACL,CAAC,CAAA;QAED,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;YAE3B,MAAM,WAAW,GAAG,YAAY,EAAE,CAAA;YAGlC,IAAG,qBAAqB,IAAI,qBAAqB,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,EAAC,CAAC;gBACnF,OAAM,qBAAqB,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,EAAC,CAAC;oBAC7D,gBAAM,CAAC,IAAI,CAAC,uBAAuB,qBAAqB,gFAAgF,CAAC,CAAC;oBAC1I,qBAAqB,GAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC;oBAC7E,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,CAAC,CAAC;gBAC1E,CAAC;YACH,CAAC;YAGD,IAAG,aAAa,IAAI,aAAa,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAC,CAAC;gBAC1D,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;gBACtD,IAAG,IAAI,CAAC,SAAS,EAAC,CAAC;oBACjB,gBAAM,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;oBAChF,qBAAqB,GAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;oBACnE,qBAAqB,CAAC,WAAW,CAAC,CAAC;oBACnC,OAAO;gBACT,CAAC;YACH,CAAC;YAGD,aAAa,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;YAEzC,qBAAqB,GAAG,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;YAGnE,qBAAqB,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC,CAAA;QAED,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,GAAE,EAAE;YACrC,SAAS,EAAE,CAAC;QACd,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,IAAI;QACF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QACpC,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,CAAC,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,OAAO,CAAC;IACjD,CAAC;IAED,SAAS;QACP,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,SAAS,GAAc;YAC3B,EAAE,EAAE,IAAA,oBAAQ,EAAC,MAAM,CAAC;YACpB,MAAM,EAAE,SAAS;SAClB,CAAA;QACD,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC5D,IAAG,aAAa,EAAC,CAAC;gBAChB,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,SAAS,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;gBACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;gBACnD,SAAS,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;gBAClC,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;gBAC1B,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAC,CAAC;YACnB,SAAS,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;YAClC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF;AApLD,wBAoLC;AAED,KAAK,UAAU,QAAQ,CAAC,EAAQ,EAAE,IAAU,EAAE,OAAkB;IAC9D,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAA,OAAO,KAAU,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,WAAwB,EAAE,WAAiB;IAC3D,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC1B,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IAEtD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IAMhD,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;QACrB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,YAAY;IACnB,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IACxB,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,IAAI,CAAC;AACd,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/task-registry.d.ts b/backend/node_modules/node-cron/dist/cjs/task-registry.d.ts new file mode 100644 index 0000000..91224ef --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/task-registry.d.ts @@ -0,0 +1,11 @@ +import { ScheduledTask } from "./tasks/scheduled-task"; +declare const tasks: Map; +export declare class TaskRegistry { + add(task: ScheduledTask): void; + get(taskId: string): ScheduledTask | undefined; + remove(task: ScheduledTask): void; + all(): typeof tasks; + has(taskId: string): boolean; + killAll(): void; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/cjs/task-registry.js b/backend/node_modules/node-cron/dist/cjs/task-registry.js new file mode 100644 index 0000000..138c30a --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/task-registry.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TaskRegistry = void 0; +const tasks = new Map(); +class TaskRegistry { + add(task) { + if (this.has(task.id)) { + throw Error(`task ${task.id} already registred!`); + } + tasks.set(task.id, task); + task.on('task:destroyed', () => { + this.remove(task); + }); + } + get(taskId) { + return tasks.get(taskId); + } + remove(task) { + if (this.has(task.id)) { + task?.destroy(); + tasks.delete(task.id); + } + } + all() { + return tasks; + } + has(taskId) { + return tasks.has(taskId); + } + killAll() { + tasks.forEach(id => this.remove(id)); + } +} +exports.TaskRegistry = TaskRegistry; +//# sourceMappingURL=task-registry.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/task-registry.js.map b/backend/node_modules/node-cron/dist/cjs/task-registry.js.map new file mode 100644 index 0000000..5ebc390 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/task-registry.js.map @@ -0,0 +1 @@ +{"version":3,"file":"task-registry.js","sourceRoot":"","sources":["../../src/task-registry.ts"],"names":[],"mappings":";;;AAEA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEhD,MAAa,YAAY;IACvB,GAAG,CAAC,IAAmB;QACrB,IAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAC,CAAC;YACpB,MAAM,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,qBAAqB,CAAC,CAAA;QACnD,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAEzB,IAAI,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,IAAmB;QACxB,IAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAC,CAAC;YACpB,IAAI,EAAE,OAAO,EAAE,CAAC;YAChB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,GAAG;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO;QACN,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACtC,CAAC;CACF;AAnCD,oCAmCC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.d.ts b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.d.ts new file mode 100644 index 0000000..3af9fb8 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.d.ts @@ -0,0 +1,28 @@ +import { ChildProcess } from 'child_process'; +import { ScheduledTask, TaskContext, TaskEvent, TaskOptions } from '../scheduled-task'; +import { EventEmitter } from 'stream'; +import { StateMachine } from '../state-machine'; +declare class TaskEmitter extends EventEmitter { +} +declare class BackgroundScheduledTask implements ScheduledTask { + emitter: TaskEmitter; + id: string; + name: string; + cronExpression: any; + taskPath: any; + options?: any; + forkProcess?: ChildProcess; + stateMachine: StateMachine; + constructor(cronExpression: string, taskPath: string, options?: TaskOptions); + getNextRun(): Date | null; + start(): Promise; + stop(): Promise; + getStatus(): string; + destroy(): Promise; + execute(): Promise; + on(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + off(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + once(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + private createContext; +} +export default BackgroundScheduledTask; diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js new file mode 100644 index 0000000..1b9f8af --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js @@ -0,0 +1,220 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const child_process_1 = require("child_process"); +const create_id_1 = require("../../create-id"); +const stream_1 = require("stream"); +const state_machine_1 = require("../state-machine"); +const localized_time_1 = require("../../time/localized-time"); +const logger_1 = __importDefault(require("../../logger")); +const time_matcher_1 = require("../../time/time-matcher"); +const daemonPath = (0, path_1.resolve)(__dirname, 'daemon.js'); +class TaskEmitter extends stream_1.EventEmitter { +} +class BackgroundScheduledTask { + emitter; + id; + name; + cronExpression; + taskPath; + options; + forkProcess; + stateMachine; + constructor(cronExpression, taskPath, options) { + this.cronExpression = cronExpression; + this.taskPath = taskPath; + this.options = options; + this.id = (0, create_id_1.createID)('task'); + this.name = options?.name || this.id; + this.emitter = new TaskEmitter(); + this.stateMachine = new state_machine_1.StateMachine('stopped'); + this.on('task:stopped', () => { + this.forkProcess?.kill(); + this.forkProcess = undefined; + this.stateMachine.changeState('stopped'); + }); + this.on('task:destroyed', () => { + this.forkProcess?.kill(); + this.forkProcess = undefined; + this.stateMachine.changeState('destroyed'); + }); + } + getNextRun() { + if (this.stateMachine.state !== 'stopped') { + const timeMatcher = new time_matcher_1.TimeMatcher(this.cronExpression, this.options?.timezone); + return timeMatcher.getNextMatch(new Date()); + } + return null; + } + start() { + return new Promise((resolve, reject) => { + if (this.forkProcess) { + return resolve(undefined); + } + const timeout = setTimeout(() => { + reject(new Error('Start operation timed out')); + }, 5000); + try { + this.forkProcess = (0, child_process_1.fork)(daemonPath); + this.forkProcess.on('error', (err) => { + clearTimeout(timeout); + reject(new Error(`Error on daemon: ${err.message}`)); + }); + this.forkProcess.on('exit', (code, signal) => { + if (code !== 0 && signal !== 'SIGTERM') { + const erro = new Error(`node-cron daemon exited with code ${code || signal}`); + logger_1.default.error(erro); + clearTimeout(timeout); + reject(erro); + } + }); + this.forkProcess.on('message', (message) => { + if (message.jsonError) { + if (message.context?.execution) { + message.context.execution.error = deserializeError(message.jsonError); + delete message.jsonError; + } + } + if (message.context?.task?.state) { + this.stateMachine.changeState(message.context?.task?.state); + } + if (message.context) { + const execution = message.context?.execution; + delete execution?.hasError; + const context = this.createContext(new Date(message.context.date), execution); + this.emitter.emit(message.event, context); + } + }); + this.once('task:started', () => { + this.stateMachine.changeState('idle'); + clearTimeout(timeout); + resolve(undefined); + }); + this.forkProcess.send({ + command: 'task:start', + path: this.taskPath, + cron: this.cronExpression, + options: this.options + }); + } + catch (error) { + reject(error); + } + }); + } + stop() { + return new Promise((resolve, reject) => { + if (!this.forkProcess) { + return resolve(undefined); + } + const timeoutId = setTimeout(() => { + clearTimeout(timeoutId); + reject(new Error('Stop operation timed out')); + }, 5000); + const cleanupAndResolve = () => { + clearTimeout(timeoutId); + this.off('task:stopped', onStopped); + this.forkProcess = undefined; + resolve(undefined); + }; + const onStopped = () => { + cleanupAndResolve(); + }; + this.once('task:stopped', onStopped); + this.forkProcess.send({ + command: 'task:stop' + }); + }); + } + getStatus() { + return this.stateMachine.state; + } + destroy() { + return new Promise((resolve, reject) => { + if (!this.forkProcess) { + return resolve(undefined); + } + const timeoutId = setTimeout(() => { + clearTimeout(timeoutId); + reject(new Error('Destroy operation timed out')); + }, 5000); + const onDestroy = () => { + clearTimeout(timeoutId); + this.off('task:destroyed', onDestroy); + resolve(undefined); + }; + this.once('task:destroyed', onDestroy); + this.forkProcess.send({ + command: 'task:destroy' + }); + }); + } + execute() { + return new Promise((resolve, reject) => { + if (!this.forkProcess) { + return reject(new Error('Cannot execute background task because it hasn\'t been started yet. Please initialize the task using the start() method before attempting to execute it.')); + } + const timeoutId = setTimeout(() => { + cleanupListeners(); + reject(new Error('Execution timeout exceeded')); + }, 5000); + const cleanupListeners = () => { + clearTimeout(timeoutId); + this.off('execution:finished', onFinished); + this.off('execution:failed', onFail); + }; + const onFinished = (context) => { + cleanupListeners(); + resolve(context.execution?.result); + }; + const onFail = (context) => { + cleanupListeners(); + reject(context.execution?.error || new Error('Execution failed without specific error')); + }; + this.once('execution:finished', onFinished); + this.once('execution:failed', onFail); + this.forkProcess.send({ + command: 'task:execute' + }); + }); + } + on(event, fun) { + this.emitter.on(event, fun); + } + off(event, fun) { + this.emitter.off(event, fun); + } + once(event, fun) { + this.emitter.once(event, fun); + } + createContext(executionDate, execution) { + const localTime = new localized_time_1.LocalizedTime(executionDate, this.options?.timezone); + const ctx = { + date: localTime.toDate(), + dateLocalIso: localTime.toISO(), + triggeredAt: new Date(), + task: this, + execution: execution + }; + return ctx; + } +} +function deserializeError(str) { + const data = JSON.parse(str); + const Err = globalThis[data.name] || Error; + const err = new Err(data.message); + if (data.stack) { + err.stack = data.stack; + } + Object.keys(data).forEach(key => { + if (!['name', 'message', 'stack'].includes(key)) { + err[key] = data[key]; + } + }); + return err; +} +exports.default = BackgroundScheduledTask; +//# sourceMappingURL=background-scheduled-task.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js.map b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js.map new file mode 100644 index 0000000..ee6ea1e --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/background-scheduled-task.js.map @@ -0,0 +1 @@ +{"version":3,"file":"background-scheduled-task.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/background-scheduled-task.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.d.ts b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.d.ts new file mode 100644 index 0000000..d7728e9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.d.ts @@ -0,0 +1,3 @@ +import { ScheduledTask } from "../scheduled-task"; +export declare function startDaemon(message: any): Promise; +export declare function bind(): void; diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js new file mode 100644 index 0000000..09bc447 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js @@ -0,0 +1,142 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.startDaemon = startDaemon; +exports.bind = bind; +const url_1 = require("url"); +const logger_1 = __importDefault(require("../../logger")); +const inline_scheduled_task_1 = require("../inline-scheduled-task"); +async function startDaemon(message) { + let script; + try { + script = await Promise.resolve(`${message.path}`).then(s => __importStar(require(s))); + } + catch { + script = await Promise.resolve(`${(0, url_1.fileURLToPath)(message.path)}`).then(s => __importStar(require(s))); + } + const task = new inline_scheduled_task_1.InlineScheduledTask(message.cron, script.task, message.options); + task.on('task:started', (context => sendEvent('task:started', context))); + task.on('task:stopped', (context => sendEvent('task:stopped', context))); + task.on('task:destroyed', (context => sendEvent('task:destroyed', context))); + task.on('execution:started', (context => sendEvent('execution:started', context))); + task.on('execution:finished', (context => sendEvent('execution:finished', context))); + task.on('execution:failed', (context => sendEvent('execution:failed', context))); + task.on('execution:missed', (context => sendEvent('execution:missed', context))); + task.on('execution:overlap', (context => sendEvent('execution:overlap', context))); + task.on('execution:maxReached', (context => sendEvent('execution:maxReached', context))); + if (process.send) + process.send({ event: 'daemon:started' }); + task.start(); + return task; +} +function sendEvent(event, context) { + const message = { event: event, context: safelySerializeContext(context) }; + if (context.execution?.error) { + message.jsonError = serializeError(context.execution?.error); + } + if (process.send) + process.send(message); +} +function serializeError(err) { + const plain = { + name: err.name, + message: err.message, + stack: err.stack, + ...Object.getOwnPropertyNames(err) + .filter(k => !['name', 'message', 'stack'].includes(k)) + .reduce((acc, k) => { + acc[k] = err[k]; + return acc; + }, {}) + }; + return JSON.stringify(plain); +} +function safelySerializeContext(context) { + const safeContext = { + date: context.date, + dateLocalIso: context.dateLocalIso, + triggeredAt: context.triggeredAt + }; + if (context.task) { + safeContext.task = { + id: context.task.id, + name: context.task.name, + status: context.task.getStatus() + }; + } + if (context.execution) { + safeContext.execution = { + id: context.execution.id, + reason: context.execution.reason, + startedAt: context.execution.startedAt, + finishedAt: context.execution.finishedAt, + hasError: !!context.execution.error, + result: context.execution.result + }; + } + return safeContext; +} +function bind() { + let task; + process.on('message', async (message) => { + switch (message.command) { + case 'task:start': + task = await startDaemon(message); + return task; + case 'task:stop': + if (task) + task.stop(); + return task; + case 'task:destroy': + if (task) + task.destroy(); + return task; + case 'task:execute': + try { + if (task) + await task.execute(); + } + catch (error) { + logger_1.default.debug('Daemon task:execute falied:', error); + } + return task; + } + }); +} +bind(); +//# sourceMappingURL=daemon.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js.map b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js.map new file mode 100644 index 0000000..3e8325a --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/daemon.js.map @@ -0,0 +1 @@ +{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/daemon.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.d.ts b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js new file mode 100644 index 0000000..fa69a5a --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js @@ -0,0 +1,2 @@ +"use strict"; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js.map b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js.map new file mode 100644 index 0000000..19beb39 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/background-scheduled-task/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.d.ts b/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.d.ts new file mode 100644 index 0000000..e118506 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.d.ts @@ -0,0 +1,30 @@ +import EventEmitter from "events"; +import { ScheduledTask, TaskContext, TaskEvent, TaskFn, TaskOptions } from "./scheduled-task"; +import { Runner } from "../scheduler/runner"; +import { TimeMatcher } from "../time/time-matcher"; +import { StateMachine } from "./state-machine"; +declare class TaskEmitter extends EventEmitter { +} +export declare class InlineScheduledTask implements ScheduledTask { + emitter: TaskEmitter; + cronExpression: string; + timeMatcher: TimeMatcher; + runner: Runner; + id: string; + name: string; + stateMachine: StateMachine; + timezone?: string; + constructor(cronExpression: string, taskFn: TaskFn, options?: TaskOptions); + getNextRun(): Date | null; + private changeState; + start(): void; + stop(): void; + getStatus(): string; + destroy(): void; + execute(): Promise; + on(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + off(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + once(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + private createContext; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js b/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js new file mode 100644 index 0000000..00e9fdd --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js @@ -0,0 +1,144 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InlineScheduledTask = void 0; +const events_1 = __importDefault(require("events")); +const runner_1 = require("../scheduler/runner"); +const time_matcher_1 = require("../time/time-matcher"); +const create_id_1 = require("../create-id"); +const state_machine_1 = require("./state-machine"); +const logger_1 = __importDefault(require("../logger")); +const localized_time_1 = require("../time/localized-time"); +class TaskEmitter extends events_1.default { +} +class InlineScheduledTask { + emitter; + cronExpression; + timeMatcher; + runner; + id; + name; + stateMachine; + timezone; + constructor(cronExpression, taskFn, options) { + this.emitter = new TaskEmitter(); + this.cronExpression = cronExpression; + this.id = (0, create_id_1.createID)('task', 12); + this.name = options?.name || this.id; + this.timezone = options?.timezone; + this.timeMatcher = new time_matcher_1.TimeMatcher(cronExpression, options?.timezone); + this.stateMachine = new state_machine_1.StateMachine(); + const runnerOptions = { + timezone: options?.timezone, + noOverlap: options?.noOverlap, + maxExecutions: options?.maxExecutions, + maxRandomDelay: options?.maxRandomDelay, + beforeRun: (date, execution) => { + if (execution.reason === 'scheduled') { + this.changeState('running'); + } + this.emitter.emit('execution:started', this.createContext(date, execution)); + return true; + }, + onFinished: (date, execution) => { + if (execution.reason === 'scheduled') { + this.changeState('idle'); + } + this.emitter.emit('execution:finished', this.createContext(date, execution)); + return true; + }, + onError: (date, error, execution) => { + logger_1.default.error(error); + this.emitter.emit('execution:failed', this.createContext(date, execution)); + this.changeState('idle'); + }, + onOverlap: (date) => { + this.emitter.emit('execution:overlap', this.createContext(date)); + }, + onMissedExecution: (date) => { + this.emitter.emit('execution:missed', this.createContext(date)); + }, + onMaxExecutions: (date) => { + this.emitter.emit('execution:maxReached', this.createContext(date)); + this.destroy(); + } + }; + this.runner = new runner_1.Runner(this.timeMatcher, (date, execution) => { + return taskFn(this.createContext(date, execution)); + }, runnerOptions); + } + getNextRun() { + if (this.stateMachine.state !== 'stopped') { + return this.runner.nextRun(); + } + return null; + } + changeState(state) { + if (this.runner.isStarted()) { + this.stateMachine.changeState(state); + } + } + start() { + if (this.runner.isStopped()) { + this.runner.start(); + this.stateMachine.changeState('idle'); + this.emitter.emit('task:started', this.createContext(new Date())); + } + } + stop() { + if (this.runner.isStarted()) { + this.runner.stop(); + this.stateMachine.changeState('stopped'); + this.emitter.emit('task:stopped', this.createContext(new Date())); + } + } + getStatus() { + return this.stateMachine.state; + } + destroy() { + if (this.stateMachine.state === 'destroyed') + return; + this.stop(); + this.stateMachine.changeState('destroyed'); + this.emitter.emit('task:destroyed', this.createContext(new Date())); + } + execute() { + return new Promise((resolve, reject) => { + const onFail = (context) => { + this.off('execution:finished', onFail); + reject(context.execution?.error); + }; + const onFinished = (context) => { + this.off('execution:failed', onFail); + resolve(context.execution?.result); + }; + this.once('execution:finished', onFinished); + this.once('execution:failed', onFail); + this.runner.execute(); + }); + } + on(event, fun) { + this.emitter.on(event, fun); + } + off(event, fun) { + this.emitter.off(event, fun); + } + once(event, fun) { + this.emitter.once(event, fun); + } + createContext(executionDate, execution) { + const localTime = new localized_time_1.LocalizedTime(executionDate, this.timezone); + const ctx = { + date: localTime.toDate(), + dateLocalIso: localTime.toISO(), + triggeredAt: new Date(), + task: this, + execution: execution + }; + return ctx; + } +} +exports.InlineScheduledTask = InlineScheduledTask; +//# sourceMappingURL=inline-scheduled-task.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js.map b/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js.map new file mode 100644 index 0000000..e62f7a3 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/inline-scheduled-task.js.map @@ -0,0 +1 @@ +{"version":3,"file":"inline-scheduled-task.js","sourceRoot":"","sources":["../../../src/tasks/inline-scheduled-task.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.d.ts b/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.d.ts new file mode 100644 index 0000000..878e04b --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.d.ts @@ -0,0 +1,37 @@ +export type TaskContext = { + date: Date; + dateLocalIso: string; + task?: ScheduledTask; + execution?: Execution; + triggeredAt: Date; +}; +export type TaskEvent = 'task:started' | 'task:stopped' | 'task:destroyed' | 'execution:started' | 'execution:finished' | 'execution:failed' | 'execution:missed' | 'execution:overlap' | 'execution:maxReached'; +export type TaskOptions = { + timezone?: string; + name?: string; + noOverlap?: boolean; + maxExecutions?: number; + maxRandomDelay?: number; +}; +export type Execution = { + id: string; + reason: 'invoked' | 'scheduled'; + startedAt?: Date; + finishedAt?: Date; + error?: Error; + result?: any; +}; +export type TaskFn = (context: TaskContext) => any | Promise; +export interface ScheduledTask { + id: string; + name?: string; + start(): void | Promise; + stop(): void | Promise; + getStatus(): string | Promise; + destroy(): void | Promise; + execute(): Promise; + getNextRun(): Date | null; + on(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + off(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + once(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; +} diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js b/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js new file mode 100644 index 0000000..8101c21 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=scheduled-task.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js.map b/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js.map new file mode 100644 index 0000000..7282f56 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/scheduled-task.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scheduled-task.js","sourceRoot":"","sources":["../../../src/tasks/scheduled-task.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.d.ts b/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.d.ts new file mode 100644 index 0000000..2f54ce1 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.d.ts @@ -0,0 +1,6 @@ +export type TaskState = 'stopped' | 'idle' | 'running' | 'destroyed'; +export declare class StateMachine { + state: TaskState; + constructor(initial?: TaskState); + changeState(state: TaskState): void; +} diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js b/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js new file mode 100644 index 0000000..8375037 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StateMachine = void 0; +const allowedTransitions = { + 'stopped': ['stopped', 'idle', 'destroyed'], + 'idle': ['idle', 'running', 'stopped', 'destroyed'], + 'running': ['running', 'idle', 'stopped', 'destroyed'], + 'destroyed': ['destroyed'] +}; +class StateMachine { + state; + constructor(initial = 'stopped') { + this.state = initial; + } + changeState(state) { + if (allowedTransitions[this.state].includes(state)) { + this.state = state; + } + else { + throw new Error(`invalid transition from ${this.state} to ${state}`); + } + } +} +exports.StateMachine = StateMachine; +//# sourceMappingURL=state-machine.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js.map b/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js.map new file mode 100644 index 0000000..3b83d2a --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/tasks/state-machine.js.map @@ -0,0 +1 @@ +{"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../../../src/tasks/state-machine.ts"],"names":[],"mappings":";;;AAEA,MAAM,kBAAkB,GAAmC;IACzD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC;IAC3C,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC;IACnD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC;IACtD,WAAW,EAAE,CAAC,WAAW,CAAC;CAC3B,CAAA;AAED,MAAa,YAAY;IACvB,KAAK,CAAY;IAEjB,YAAY,UAAqB,SAAS;QACxC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;IACvB,CAAC;IAED,WAAW,CAAC,KAAgB;QAC1B,IAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAC,CAAC;YACjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;CAEF;AAfD,oCAeC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/time/localized-time.d.ts b/backend/node_modules/node-cron/dist/cjs/time/localized-time.d.ts new file mode 100644 index 0000000..75b0c0b --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/localized-time.d.ts @@ -0,0 +1,22 @@ +type DateParts = { + day: number; + month: number; + year: number; + hour: number; + minute: number; + second: number; + milisecond: number; + weekday: string; + gmt: string; +}; +export declare class LocalizedTime { + timestamp: number; + parts: DateParts; + timezone?: string | undefined; + constructor(date: Date, timezone?: string); + toDate(): Date; + toISO(): string; + getParts(): DateParts; + set(field: string, value: number): void; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/cjs/time/localized-time.js b/backend/node_modules/node-cron/dist/cjs/time/localized-time.js new file mode 100644 index 0000000..af21865 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/localized-time.js @@ -0,0 +1,81 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LocalizedTime = void 0; +class LocalizedTime { + timestamp; + parts; + timezone; + constructor(date, timezone) { + this.timestamp = date.getTime(); + this.timezone = timezone; + this.parts = buildDateParts(date, timezone); + } + toDate() { + return new Date(this.timestamp); + } + toISO() { + const gmt = this.parts.gmt.replace(/^GMT/, ''); + const offset = gmt ? gmt : 'Z'; + const pad = (n) => String(n).padStart(2, '0'); + return `${this.parts.year}-${pad(this.parts.month)}-${pad(this.parts.day)}` + + `T${pad(this.parts.hour)}:${pad(this.parts.minute)}:${pad(this.parts.second)}` + + `.${String(this.parts.milisecond).padStart(3, '0')}` + + offset; + } + getParts() { + return this.parts; + } + set(field, value) { + this.parts[field] = value; + const newDate = new Date(this.toISO()); + this.timestamp = newDate.getTime(); + this.parts = buildDateParts(newDate, this.timezone); + } +} +exports.LocalizedTime = LocalizedTime; +function buildDateParts(date, timezone) { + const dftOptions = { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + weekday: 'short', + hour12: false + }; + if (timezone) { + dftOptions.timeZone = timezone; + } + const dateFormat = new Intl.DateTimeFormat('en-US', dftOptions); + const parts = dateFormat.formatToParts(date).filter(part => { + return part.type !== 'literal'; + }).reduce((acc, part) => { + acc[part.type] = part.value; + return acc; + }, {}); + return { + day: parseInt(parts.day), + month: parseInt(parts.month), + year: parseInt(parts.year), + hour: parts.hour === '24' ? 0 : parseInt(parts.hour), + minute: parseInt(parts.minute), + second: parseInt(parts.second), + milisecond: date.getMilliseconds(), + weekday: parts.weekday, + gmt: getTimezoneGMT(date, timezone) + }; +} +function getTimezoneGMT(date, timezone) { + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const tzDate = new Date(date.toLocaleString('en-US', { timeZone: timezone })); + let offsetInMinutes = (utcDate.getTime() - tzDate.getTime()) / 60000; + const sign = offsetInMinutes <= 0 ? '+' : '-'; + offsetInMinutes = Math.abs(offsetInMinutes); + if (offsetInMinutes === 0) + return 'Z'; + const hours = Math.floor(offsetInMinutes / 60).toString().padStart(2, '0'); + const minutes = Math.floor(offsetInMinutes % 60).toString().padStart(2, '0'); + return `GMT${sign}${hours}:${minutes}`; +} +//# sourceMappingURL=localized-time.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/time/localized-time.js.map b/backend/node_modules/node-cron/dist/cjs/time/localized-time.js.map new file mode 100644 index 0000000..b53db2a --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/localized-time.js.map @@ -0,0 +1 @@ +{"version":3,"file":"localized-time.js","sourceRoot":"","sources":["../../../src/time/localized-time.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.d.ts b/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.d.ts new file mode 100644 index 0000000..1676430 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.d.ts @@ -0,0 +1,13 @@ +import { LocalizedTime } from './localized-time'; +import { TimeMatcher } from './time-matcher'; +export declare class MatcherWalker { + cronExpression: string; + baseDate: Date; + pattern: any; + expressions: number[][]; + timeMatcher: TimeMatcher; + timezone?: string; + constructor(cronExpression: string, baseDate: Date, timezone?: string); + isMatching(): boolean; + matchNext(): LocalizedTime; +} diff --git a/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js b/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js new file mode 100644 index 0000000..8e6ff5b --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js @@ -0,0 +1,100 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MatcherWalker = void 0; +const convertion_1 = __importDefault(require("../pattern/convertion")); +const localized_time_1 = require("./localized-time"); +const time_matcher_1 = require("./time-matcher"); +const week_day_names_conversion_1 = __importDefault(require("../pattern/convertion/week-day-names-conversion")); +class MatcherWalker { + cronExpression; + baseDate; + pattern; + expressions; + timeMatcher; + timezone; + constructor(cronExpression, baseDate, timezone) { + this.cronExpression = cronExpression; + this.baseDate = baseDate; + this.timeMatcher = new time_matcher_1.TimeMatcher(cronExpression, timezone); + this.timezone = timezone; + this.expressions = (0, convertion_1.default)(cronExpression); + } + isMatching() { + return this.timeMatcher.match(this.baseDate); + } + matchNext() { + const findNextDateIgnoringWeekday = () => { + const baseDate = new Date(this.baseDate.getTime()); + baseDate.setMilliseconds(0); + const localTime = new localized_time_1.LocalizedTime(baseDate, this.timezone); + const dateParts = localTime.getParts(); + const date = new localized_time_1.LocalizedTime(localTime.toDate(), this.timezone); + const seconds = this.expressions[0]; + const nextSecond = availableValue(seconds, dateParts.second); + if (nextSecond) { + date.set('second', nextSecond); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('second', seconds[0]); + const minutes = this.expressions[1]; + const nextMinute = availableValue(minutes, dateParts.minute); + if (nextMinute) { + date.set('minute', nextMinute); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('minute', minutes[0]); + const hours = this.expressions[2]; + const nextHour = availableValue(hours, dateParts.hour); + if (nextHour) { + date.set('hour', nextHour); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('hour', hours[0]); + const days = this.expressions[3]; + const nextDay = availableValue(days, dateParts.day); + if (nextDay) { + date.set('day', nextDay); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('day', days[0]); + const months = this.expressions[4]; + const nextMonth = availableValue(months, dateParts.month); + if (nextMonth) { + date.set('month', nextMonth); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('year', date.getParts().year + 1); + date.set('month', months[0]); + return date; + }; + const date = findNextDateIgnoringWeekday(); + const weekdays = this.expressions[5]; + let currentWeekday = parseInt((0, week_day_names_conversion_1.default)(date.getParts().weekday)); + while (!(weekdays.indexOf(currentWeekday) > -1)) { + date.set('year', date.getParts().year + 1); + currentWeekday = parseInt((0, week_day_names_conversion_1.default)(date.getParts().weekday)); + } + return date; + } +} +exports.MatcherWalker = MatcherWalker; +function availableValue(values, currentValue) { + const availableValues = values.sort((a, b) => a - b).filter(s => s > currentValue); + if (availableValues.length > 0) + return availableValues[0]; + return false; +} +//# sourceMappingURL=matcher-walker.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js.map b/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js.map new file mode 100644 index 0000000..77f11e0 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/matcher-walker.js.map @@ -0,0 +1 @@ +{"version":3,"file":"matcher-walker.js","sourceRoot":"","sources":["../../../src/time/matcher-walker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/time/time-matcher.d.ts b/backend/node_modules/node-cron/dist/cjs/time/time-matcher.d.ts new file mode 100644 index 0000000..ed432fa --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/time-matcher.d.ts @@ -0,0 +1,8 @@ +export declare class TimeMatcher { + timezone?: string; + pattern: string; + expressions: any[]; + constructor(pattern: string, timezone?: string); + match(date: Date): boolean; + getNextMatch(date: Date): Date; +} diff --git a/backend/node_modules/node-cron/dist/cjs/time/time-matcher.js b/backend/node_modules/node-cron/dist/cjs/time/time-matcher.js new file mode 100644 index 0000000..0ebb066 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/time-matcher.js @@ -0,0 +1,41 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TimeMatcher = void 0; +const index_1 = __importDefault(require("../pattern/convertion/index")); +const week_day_names_conversion_1 = __importDefault(require("../pattern/convertion/week-day-names-conversion")); +const localized_time_1 = require("./localized-time"); +const matcher_walker_1 = require("./matcher-walker"); +function matchValue(allowedValues, value) { + return allowedValues.indexOf(value) !== -1; +} +class TimeMatcher { + timezone; + pattern; + expressions; + constructor(pattern, timezone) { + this.timezone = timezone; + this.pattern = pattern; + this.expressions = (0, index_1.default)(pattern); + } + match(date) { + const localizedTime = new localized_time_1.LocalizedTime(date, this.timezone); + const parts = localizedTime.getParts(); + const runOnSecond = matchValue(this.expressions[0], parts.second); + const runOnMinute = matchValue(this.expressions[1], parts.minute); + const runOnHour = matchValue(this.expressions[2], parts.hour); + const runOnDay = matchValue(this.expressions[3], parts.day); + const runOnMonth = matchValue(this.expressions[4], parts.month); + const runOnWeekDay = matchValue(this.expressions[5], parseInt((0, week_day_names_conversion_1.default)(parts.weekday))); + return runOnSecond && runOnMinute && runOnHour && runOnDay && runOnMonth && runOnWeekDay; + } + getNextMatch(date) { + const walker = new matcher_walker_1.MatcherWalker(this.pattern, date, this.timezone); + const next = walker.matchNext(); + return next.toDate(); + } +} +exports.TimeMatcher = TimeMatcher; +//# sourceMappingURL=time-matcher.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/cjs/time/time-matcher.js.map b/backend/node_modules/node-cron/dist/cjs/time/time-matcher.js.map new file mode 100644 index 0000000..4560713 --- /dev/null +++ b/backend/node_modules/node-cron/dist/cjs/time/time-matcher.js.map @@ -0,0 +1 @@ +{"version":3,"file":"time-matcher.js","sourceRoot":"","sources":["../../../src/time/time-matcher.ts"],"names":[],"mappings":";;;;;;AACA,wEAA4D;AAC5D,gHAAqF;AACrF,qDAAiD;AACjD,qDAAiD;AAEjD,SAAS,UAAU,CAAC,aAAuB,EAAE,KAAa;IACxD,OAAO,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAa,WAAW;IACpB,QAAQ,CAAU;IAClB,OAAO,CAAS;IAChB,WAAW,CAAQ;IAEnB,YAAY,OAAc,EAAE,QAAgB;QACxC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,WAAW,GAAG,IAAA,eAAiB,EAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,IAAU;QACZ,MAAM,aAAa,GAAG,IAAI,8BAAa,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC5D,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAA,mCAAsB,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAEtG,OAAO,WAAW,IAAI,WAAW,IAAI,SAAS,IAAI,QAAQ,IAAI,UAAU,IAAI,YAAY,CAAC;IAC7F,CAAC;IAED,YAAY,CAAC,IAAU;QACrB,MAAM,MAAM,GAAG,IAAI,8BAAa,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;CACJ;AA7BD,kCA6BC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/create-id.d.ts b/backend/node_modules/node-cron/dist/esm/create-id.d.ts new file mode 100644 index 0000000..039b33a --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/create-id.d.ts @@ -0,0 +1 @@ +export declare function createID(prefix?: string, length?: number): string; diff --git a/backend/node_modules/node-cron/dist/esm/create-id.js b/backend/node_modules/node-cron/dist/esm/create-id.js new file mode 100644 index 0000000..380ff18 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/create-id.js @@ -0,0 +1,14 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createID = createID; +const node_crypto_1 = __importDefault(require("node:crypto")); +function createID(prefix = '', length = 16) { + const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const values = node_crypto_1.default.randomBytes(length); + const id = Array.from(values, v => charset[v % charset.length]).join(''); + return prefix ? `${prefix}-${id}` : id; +} +//# sourceMappingURL=create-id.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/create-id.js.map b/backend/node_modules/node-cron/dist/esm/create-id.js.map new file mode 100644 index 0000000..56bbebe --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/create-id.js.map @@ -0,0 +1 @@ +{"version":3,"file":"create-id.js","sourceRoot":"","sources":["../../src/create-id.ts"],"names":[],"mappings":";;;;;AAEA,4BAKC;AAPD,8DAAiC;AAEjC,SAAgB,QAAQ,CAAC,SAAiB,EAAE,EAAE,SAAiB,EAAE;IAC/D,MAAM,OAAO,GAAG,gEAAgE,CAAC;IACjF,MAAM,MAAM,GAAG,qBAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/logger.d.ts b/backend/node_modules/node-cron/dist/esm/logger.d.ts new file mode 100644 index 0000000..2acbdf9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/logger.d.ts @@ -0,0 +1,7 @@ +declare const logger: { + info(message: string): void; + warn(message: string): void; + error(message: string | Error, err?: Error): void; + debug(message: string | Error, err?: Error): void; +}; +export default logger; diff --git a/backend/node_modules/node-cron/dist/esm/logger.js b/backend/node_modules/node-cron/dist/esm/logger.js new file mode 100644 index 0000000..e876e9b --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/logger.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const levelColors = { + INFO: '\x1b[36m', + WARN: '\x1b[33m', + ERROR: '\x1b[31m', + DEBUG: '\x1b[35m', +}; +const GREEN = '\x1b[32m'; +const RESET = '\x1b[0m'; +function log(level, message, extra) { + const timestamp = new Date().toISOString(); + const color = levelColors[level] ?? ''; + const prefix = `[${timestamp}] [PID: ${process.pid}] ${GREEN}[NODE-CRON]${GREEN} ${color}[${level}]${RESET}`; + const output = `${prefix} ${message}`; + switch (level) { + case 'ERROR': + console.error(output, extra ?? ''); + break; + case 'DEBUG': + console.debug(output, extra ?? ''); + break; + case 'WARN': + console.warn(output); + break; + case 'INFO': + default: + console.info(output); + break; + } +} +const logger = { + info(message) { + log('INFO', message); + }, + warn(message) { + log('WARN', message); + }, + error(message, err) { + if (message instanceof Error) { + log('ERROR', message.message, message); + } + else { + log('ERROR', message, err); + } + }, + debug(message, err) { + if (message instanceof Error) { + log('DEBUG', message.message, message); + } + else { + log('DEBUG', message, err); + } + }, +}; +exports.default = logger; +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/logger.js.map b/backend/node_modules/node-cron/dist/esm/logger.js.map new file mode 100644 index 0000000..0f576ae --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":";;AAEA,MAAM,WAAW,GAA6B;IAC5C,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,KAAK,EAAE,UAAU;CAClB,CAAC;AAEF,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB,SAAS,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,KAAW;IACxD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,SAAS,WAAW,OAAO,CAAC,GAAG,KAAK,KAAK,cAAc,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;IAC7G,MAAM,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC;IAEtC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACR,KAAK,OAAO;YACR,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YACnC,MAAM;QACV,KAAK,MAAM;YACT,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;QACR,KAAK,MAAM,CAAC;QACZ;YACE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,MAAM;IACV,CAAC;AACH,CAAC;AAED,MAAM,MAAM,GAAG;IACb,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,KAAK,CAAC,OAAuB,EAAE,GAAW;QACxC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;CACF,CAAC;AAEF,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/node-cron.d.ts b/backend/node_modules/node-cron/dist/esm/node-cron.d.ts new file mode 100644 index 0000000..3e221e8 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/node-cron.d.ts @@ -0,0 +1,18 @@ +import { ScheduledTask, TaskFn, TaskOptions } from "./tasks/scheduled-task"; +export declare function schedule(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask; +export declare function createTask(expression: string, func: TaskFn | string, options?: TaskOptions): ScheduledTask; +export declare function solvePath(filePath: string): string; +export declare function validate(expression: string): boolean; +export declare const getTasks: () => Map; +export declare const getTask: (taskId: string) => ScheduledTask | undefined; +export { ScheduledTask } from './tasks/scheduled-task'; +export type { TaskFn, TaskContext, TaskOptions } from './tasks/scheduled-task'; +export interface NodeCron { + schedule: typeof schedule; + createTask: typeof createTask; + validate: typeof validate; + getTasks: typeof getTasks; + getTask: typeof getTask; +} +export declare const nodeCron: NodeCron; +export default nodeCron; diff --git a/backend/node_modules/node-cron/dist/esm/node-cron.js b/backend/node_modules/node-cron/dist/esm/node-cron.js new file mode 100644 index 0000000..d378466 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/node-cron.js @@ -0,0 +1,71 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nodeCron = exports.getTask = exports.getTasks = void 0; +exports.schedule = schedule; +exports.createTask = createTask; +exports.solvePath = solvePath; +exports.validate = validate; +const inline_scheduled_task_1 = require("./tasks/inline-scheduled-task"); +const task_registry_1 = require("./task-registry"); +const pattern_validation_1 = __importDefault(require("./pattern/validation/pattern-validation")); +const background_scheduled_task_1 = __importDefault(require("./tasks/background-scheduled-task/background-scheduled-task")); +const path_1 = __importDefault(require("path")); +const url_1 = require("url"); +const registry = new task_registry_1.TaskRegistry(); +function schedule(expression, func, options) { + const task = createTask(expression, func, options); + task.start(); + return task; +} +function createTask(expression, func, options) { + let task; + if (func instanceof Function) { + task = new inline_scheduled_task_1.InlineScheduledTask(expression, func, options); + } + else { + const taskPath = solvePath(func); + task = new background_scheduled_task_1.default(expression, taskPath, options); + } + registry.add(task); + return task; +} +function solvePath(filePath) { + if (path_1.default.isAbsolute(filePath)) + return (0, url_1.pathToFileURL)(filePath).href; + if (filePath.startsWith('file://')) + return filePath; + const stackLines = new Error().stack?.split('\n'); + if (stackLines) { + stackLines?.shift(); + const callerLine = stackLines?.find((line) => { return line.indexOf(__filename) === -1; }); + const match = callerLine?.match(/(file:\/\/)?(((\/?)(\w:))?([/\\].+)):\d+:\d+/); + if (match) { + const dir = `${match[5] ?? ""}${path_1.default.dirname(match[6])}`; + return (0, url_1.pathToFileURL)(path_1.default.resolve(dir, filePath)).href; + } + } + throw new Error(`Could not locate task file ${filePath}`); +} +function validate(expression) { + try { + (0, pattern_validation_1.default)(expression); + return true; + } + catch (e) { + return false; + } +} +exports.getTasks = registry.all; +exports.getTask = registry.get; +exports.nodeCron = { + schedule, + createTask, + validate, + getTasks: exports.getTasks, + getTask: exports.getTask, +}; +exports.default = exports.nodeCron; +//# sourceMappingURL=node-cron.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/node-cron.js.map b/backend/node_modules/node-cron/dist/esm/node-cron.js.map new file mode 100644 index 0000000..2fbda01 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/node-cron.js.map @@ -0,0 +1 @@ +{"version":3,"file":"node-cron.js","sourceRoot":"","sources":["../../src/node-cron.ts"],"names":[],"mappings":";;;;;;AA2CA,4BAIC;AAWD,gCAWC;AAUD,8BAoBC;AAQD,4BASC;AA1GD,yEAAoE;AAEpE,mDAA+C;AAE/C,iGAAiE;AACjE,4HAAkG;AAElG,gDAAwB;AACxB,6BAAoC;AAMpC,MAAM,QAAQ,GAAG,IAAI,4BAAY,EAAE,CAAC;AAmBpC,SAAgB,QAAQ,CAAC,UAAiB,EAAE,IAAqB,EAAE,OAAqB;IACpF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,OAAO,IAAI,CAAC;AAChB,CAAC;AAWD,SAAgB,UAAU,CAAC,UAAkB,EAAE,IAAqB,EAAE,OAAqB;IACvF,IAAI,IAAmB,CAAC;IACxB,IAAG,IAAI,YAAY,QAAQ,EAAC,CAAC;QAC3B,IAAI,GAAG,IAAI,2CAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,GAAG,IAAI,mCAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC;AAChB,CAAC;AAUD,SAAgB,SAAS,CAAC,QAAgB;IAExC,IAAG,cAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAA,mBAAa,EAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IAGlE,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEpD,MAAM,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,IAAG,UAAU,EAAC,CAAC;QACb,UAAU,EAAE,KAAK,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,UAAU,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,UAAU,EAAE,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAEhF,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,cAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,IAAA,mBAAa,EAAC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;AAC5D,CAAC;AAQD,SAAgB,QAAQ,CAAC,UAAkB;IACzC,IAAI,CAAC;QACD,IAAA,4BAAU,EAAC,UAAU,CAAC,CAAC;QAEvB,OAAO,IAAI,CAAC;IAEhB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAOY,QAAA,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC;AAQxB,QAAA,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC;AAavB,QAAA,QAAQ,GAAa;IAChC,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,QAAQ,EAAR,gBAAQ;IACR,OAAO,EAAP,eAAO;CACR,CAAC;AAKF,kBAAe,gBAAQ,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.d.ts b/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.d.ts new file mode 100644 index 0000000..0184465 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expressions: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js b/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js new file mode 100644 index 0000000..d5666ea --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + function convertAsterisk(expression, replecement) { + if (expression.indexOf('*') !== -1) { + return expression.replace('*', replecement); + } + return expression; + } + function convertAsterisksToRanges(expressions) { + expressions[0] = convertAsterisk(expressions[0], '0-59'); + expressions[1] = convertAsterisk(expressions[1], '0-59'); + expressions[2] = convertAsterisk(expressions[2], '0-23'); + expressions[3] = convertAsterisk(expressions[3], '1-31'); + expressions[4] = convertAsterisk(expressions[4], '1-12'); + expressions[5] = convertAsterisk(expressions[5], '0-6'); + return expressions; + } + return convertAsterisksToRanges; +})(); +//# sourceMappingURL=asterisk-to-range-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js.map b/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js.map new file mode 100644 index 0000000..882a6f9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/asterisk-to-range-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"asterisk-to-range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/asterisk-to-range-conversion.ts"],"names":[],"mappings":";;AACA,kBAAe,CAAC,GAAG,EAAE;IACjB,SAAS,eAAe,CAAC,UAAU,EAAE,WAAW;QAC5C,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAC,CAAC;YAC/B,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,wBAAwB,CAAC,WAAW;QACzC,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,wBAAwB,CAAC;AACpC,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.d.ts b/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.d.ts new file mode 100644 index 0000000..9569786 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expression: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js b/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js new file mode 100644 index 0000000..2c5ade7 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js @@ -0,0 +1,42 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const month_names_conversion_1 = __importDefault(require("./month-names-conversion")); +const week_day_names_conversion_1 = __importDefault(require("./week-day-names-conversion")); +const asterisk_to_range_conversion_1 = __importDefault(require("./asterisk-to-range-conversion")); +const range_conversion_1 = __importDefault(require("./range-conversion")); +exports.default = (() => { + function appendSeccondExpression(expressions) { + if (expressions.length === 5) { + return ['0'].concat(expressions); + } + return expressions; + } + function removeSpaces(str) { + return str.replace(/\s{2,}/g, ' ').trim(); + } + function normalizeIntegers(expressions) { + for (let i = 0; i < expressions.length; i++) { + const numbers = expressions[i].split(','); + for (let j = 0; j < numbers.length; j++) { + numbers[j] = parseInt(numbers[j]); + } + expressions[i] = numbers; + } + return expressions; + } + function interprete(expression) { + let expressions = removeSpaces(`${expression}`).split(' '); + expressions = appendSeccondExpression(expressions); + expressions[4] = (0, month_names_conversion_1.default)(expressions[4]); + expressions[5] = (0, week_day_names_conversion_1.default)(expressions[5]); + expressions = (0, asterisk_to_range_conversion_1.default)(expressions); + expressions = (0, range_conversion_1.default)(expressions); + expressions = normalizeIntegers(expressions); + return expressions; + } + return interprete; +})(); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js.map b/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js.map new file mode 100644 index 0000000..efd820f --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/index.ts"],"names":[],"mappings":";;;;;AAAA,sFAA4D;AAC5D,4FAAiE;AACjE,kGAAsE;AACtE,0EAA+C;AAE/C,kBAAe,CAAC,GAAG,EAAE;IAEjB,SAAS,uBAAuB,CAAC,WAAW;QACxC,IAAG,WAAW,CAAC,MAAM,KAAK,CAAC,EAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,SAAS,YAAY,CAAC,GAAG;QACrB,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAGD,SAAS,iBAAiB,CAAC,WAAW;QAClC,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACvC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAC,CAAC,EAAE,CAAC,GAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;gBACjC,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC;YACD,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;QAC7B,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAmBD,SAAS,UAAU,CAAC,UAAU;QAC1B,IAAI,WAAW,GAAG,YAAY,CAAC,GAAG,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,WAAW,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;QACnD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,gCAAoB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,WAAW,CAAC,CAAC,CAAC,GAAG,IAAA,mCAAsB,EAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,WAAW,GAAG,IAAA,sCAAwB,EAAC,WAAW,CAAC,CAAC;QACpD,WAAW,GAAG,IAAA,0BAAa,EAAC,WAAW,CAAC,CAAC;QAEzC,WAAW,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAE7C,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.d.ts b/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.d.ts new file mode 100644 index 0000000..3204e9d --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (monthExpression: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js b/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js new file mode 100644 index 0000000..f69337c --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + const months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', + 'august', 'september', 'october', 'november', 'december']; + const shortMonths = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', + 'sep', 'oct', 'nov', 'dec']; + function convertMonthName(expression, items) { + for (let i = 0; i < items.length; i++) { + expression = expression.replace(new RegExp(items[i], 'gi'), i + 1); + } + return expression; + } + function interprete(monthExpression) { + monthExpression = convertMonthName(monthExpression, months); + monthExpression = convertMonthName(monthExpression, shortMonths); + return monthExpression; + } + return interprete; +})(); +//# sourceMappingURL=month-names-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js.map b/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js.map new file mode 100644 index 0000000..6051f09 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/month-names-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"month-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/month-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,MAAM,GAAG,CAAC,SAAS,EAAC,UAAU,EAAC,OAAO,EAAC,OAAO,EAAC,KAAK,EAAC,MAAM,EAAC,MAAM;QACpE,QAAQ,EAAC,WAAW,EAAC,SAAS,EAAC,UAAU,EAAC,UAAU,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;QACvE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEhC,SAAS,gBAAgB,CAAC,UAAU,EAAE,KAAK;QACvC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,UAAU,CAAC,eAAe;QAC/B,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QAC5D,eAAe,GAAG,gBAAgB,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QACjE,OAAO,eAAe,CAAC;IAC3B,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.d.ts b/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.d.ts new file mode 100644 index 0000000..0184465 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expressions: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js b/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js new file mode 100644 index 0000000..5877e60 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + function replaceWithRange(expression, text, init, end, stepTxt) { + const step = parseInt(stepTxt); + const numbers = []; + let last = parseInt(end); + let first = parseInt(init); + if (first > last) { + last = parseInt(init); + first = parseInt(end); + } + for (let i = first; i <= last; i += step) { + numbers.push(i); + } + return expression.replace(new RegExp(text, 'i'), numbers.join()); + } + function convertRange(expression) { + const rangeRegEx = /(\d+)-(\d+)(\/(\d+)|)/; + let match = rangeRegEx.exec(expression); + while (match !== null && match.length > 0) { + expression = replaceWithRange(expression, match[0], match[1], match[2], match[4] || '1'); + match = rangeRegEx.exec(expression); + } + return expression; + } + function convertAllRanges(expressions) { + for (let i = 0; i < expressions.length; i++) { + expressions[i] = convertRange(expressions[i]); + } + return expressions; + } + return convertAllRanges; +})(); +//# sourceMappingURL=range-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js.map b/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js.map new file mode 100644 index 0000000..dc42fdb --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/range-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"range-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/range-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAE,GAAG,EAAE;IAClB,SAAS,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE3B,IAAG,KAAK,GAAG,IAAI,EAAC,CAAC;YACb,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACtB,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,KAAI,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAED,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,SAAS,YAAY,CAAC,UAAU;QAC5B,MAAM,UAAU,GAAG,uBAAuB,CAAC;QAC3C,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAM,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAC,CAAC;YACtC,UAAU,GAAG,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;YACzF,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,gBAAgB,CAAC,WAAW;QACjC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YACxC,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC5B,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.d.ts b/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.d.ts new file mode 100644 index 0000000..9569786 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.d.ts @@ -0,0 +1,2 @@ +declare const _default: (expression: any) => any; +export default _default; diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js b/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js new file mode 100644 index 0000000..69719a9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = (() => { + const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', + 'friday', 'saturday']; + const shortWeekDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; + function convertWeekDayName(expression, items) { + for (let i = 0; i < items.length; i++) { + expression = expression.replace(new RegExp(items[i], 'gi'), i); + } + return expression; + } + function convertWeekDays(expression) { + expression = expression.replace('7', '0'); + expression = convertWeekDayName(expression, weekDays); + return convertWeekDayName(expression, shortWeekDays); + } + return convertWeekDays; +})(); +//# sourceMappingURL=week-day-names-conversion.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js.map b/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js.map new file mode 100644 index 0000000..d2d6f43 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/convertion/week-day-names-conversion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"week-day-names-conversion.js","sourceRoot":"","sources":["../../../../src/pattern/convertion/week-day-names-conversion.ts"],"names":[],"mappings":";;AAAA,kBAAe,CAAC,GAAG,EAAE;IACjB,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU;QACpE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC1B,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAExE,SAAS,kBAAkB,CAAC,UAAU,EAAE,KAAK;QACzC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAC,CAAC;YAClC,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,SAAS,eAAe,CAAC,UAAU;QAC/B,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1C,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACtD,OAAO,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,eAAe,CAAC;AAC3B,CAAC,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.d.ts b/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.d.ts new file mode 100644 index 0000000..67115b5 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.d.ts @@ -0,0 +1,2 @@ +declare function validate(pattern: any): void; +export default validate; diff --git a/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js b/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js new file mode 100644 index 0000000..d64980f --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js @@ -0,0 +1,61 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const index_1 = __importDefault(require("../convertion/index")); +const validationRegex = /^(?:\d+|\*|\*\/\d+)$/; +function isValidExpression(expression, min, max) { + const options = expression; + for (const option of options) { + const optionAsInt = parseInt(option, 10); + if ((!Number.isNaN(optionAsInt) && + (optionAsInt < min || optionAsInt > max)) || + !validationRegex.test(option)) + return false; + } + return true; +} +function isInvalidSecond(expression) { + return !isValidExpression(expression, 0, 59); +} +function isInvalidMinute(expression) { + return !isValidExpression(expression, 0, 59); +} +function isInvalidHour(expression) { + return !isValidExpression(expression, 0, 23); +} +function isInvalidDayOfMonth(expression) { + return !isValidExpression(expression, 1, 31); +} +function isInvalidMonth(expression) { + return !isValidExpression(expression, 1, 12); +} +function isInvalidWeekDay(expression) { + return !isValidExpression(expression, 0, 7); +} +function validateFields(patterns, executablePatterns) { + if (isInvalidSecond(executablePatterns[0])) + throw new Error(`${patterns[0]} is a invalid expression for second`); + if (isInvalidMinute(executablePatterns[1])) + throw new Error(`${patterns[1]} is a invalid expression for minute`); + if (isInvalidHour(executablePatterns[2])) + throw new Error(`${patterns[2]} is a invalid expression for hour`); + if (isInvalidDayOfMonth(executablePatterns[3])) + throw new Error(`${patterns[3]} is a invalid expression for day of month`); + if (isInvalidMonth(executablePatterns[4])) + throw new Error(`${patterns[4]} is a invalid expression for month`); + if (isInvalidWeekDay(executablePatterns[5])) + throw new Error(`${patterns[5]} is a invalid expression for week day`); +} +function validate(pattern) { + if (typeof pattern !== 'string') + throw new TypeError('pattern must be a string!'); + const patterns = pattern.split(' '); + const executablePatterns = (0, index_1.default)(pattern); + if (patterns.length === 5) + patterns.unshift('0'); + validateFields(patterns, executablePatterns); +} +exports.default = validate; +//# sourceMappingURL=pattern-validation.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js.map b/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js.map new file mode 100644 index 0000000..b5c51e6 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/pattern/validation/pattern-validation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pattern-validation.js","sourceRoot":"","sources":["../../../../src/pattern/validation/pattern-validation.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.d.ts b/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.d.ts new file mode 100644 index 0000000..a5b3d6c --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.d.ts @@ -0,0 +1,19 @@ +type PromiseState = 'pending' | 'fulfilled' | 'rejected'; +export declare class TrackedPromise { + promise: Promise; + error: any; + state: PromiseState; + value?: T; + constructor(executor: (resolve: (value: T) => void, reject: (reason?: any) => void) => void); + getPromise(): Promise; + getState(): PromiseState; + isPending(): boolean; + isFulfilled(): boolean; + isRejected(): boolean; + getValue(): T | undefined; + getError(): any; + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; + finally(onfinally?: (() => void) | undefined | null): Promise; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js b/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js new file mode 100644 index 0000000..e81b2ef --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TrackedPromise = void 0; +class TrackedPromise { + promise; + error; + state; + value; + constructor(executor) { + this.state = 'pending'; + this.promise = new Promise((resolve, reject) => { + executor((value) => { + this.state = 'fulfilled'; + this.value = value; + resolve(value); + }, (error) => { + this.state = 'rejected'; + this.error = error; + reject(error); + }); + }); + } + getPromise() { + return this.promise; + } + getState() { + return this.state; + } + isPending() { + return this.state === 'pending'; + } + isFulfilled() { + return this.state === 'fulfilled'; + } + isRejected() { + return this.state === 'rejected'; + } + getValue() { + return this.value; + } + getError() { + return this.error; + } + then(onfulfilled, onrejected) { + return this.promise.then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.promise.catch(onrejected); + } + finally(onfinally) { + return this.promise.finally(onfinally); + } +} +exports.TrackedPromise = TrackedPromise; +//# sourceMappingURL=tracked-promise.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js.map b/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js.map new file mode 100644 index 0000000..d5d5c42 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/promise/tracked-promise.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tracked-promise.js","sourceRoot":"","sources":["../../../src/promise/tracked-promise.ts"],"names":[],"mappings":";;;AAEA,MAAa,cAAc;IACzB,OAAO,CAAa;IACpB,KAAK,CAAM;IACX,KAAK,CAAe;IACpB,KAAK,CAAK;IAEV,YAAY,QAA+E;QACzF,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QAEvB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChD,QAAQ,CACN,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;gBACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;gBACR,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;gBACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;IAClC,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC;IACpC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC;IACnC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,CACF,WAAiF,EACjF,UAAmF;QAEnF,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CACH,UAAiF;QAEjF,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,SAA2C;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;CACF;AArED,wCAqEC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/scheduler/runner.d.ts b/backend/node_modules/node-cron/dist/esm/scheduler/runner.d.ts new file mode 100644 index 0000000..2ff999c --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/scheduler/runner.d.ts @@ -0,0 +1,42 @@ +import { Execution } from "../tasks/scheduled-task"; +import { TimeMatcher } from "../time/time-matcher"; +type OnFn = (date: Date) => void | Promise; +type OnErrorHookFn = (date: Date, error: Error, execution: Execution) => void | Promise; +type OnHookFn = (date: Date, execution: Execution) => boolean | Promise; +type OnMatch = (date: Date, execution: Execution) => any | Promise; +export type RunnerOptions = { + noOverlap?: boolean; + timezone?: string; + maxExecutions?: number; + maxRandomDelay?: number; + onMissedExecution?: OnFn; + onOverlap?: OnFn; + onError?: OnErrorHookFn; + onFinished?: OnHookFn; + beforeRun?: OnHookFn; + onMaxExecutions?: OnFn; +}; +export declare class Runner { + timeMatcher: TimeMatcher; + onMatch: OnMatch; + noOverlap: boolean; + maxExecutions?: number; + maxRandomDelay: number; + runCount: number; + running: boolean; + heartBeatTimeout?: NodeJS.Timeout; + onMissedExecution: OnFn; + onOverlap: OnFn; + onError: OnErrorHookFn; + beforeRun: OnHookFn; + onFinished: OnHookFn; + onMaxExecutions: OnFn; + constructor(timeMatcher: TimeMatcher, onMatch: OnMatch, options?: RunnerOptions); + start(): void; + nextRun(): Date; + stop(): void; + isStarted(): boolean; + isStopped(): boolean; + execute(): Promise; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/esm/scheduler/runner.js b/backend/node_modules/node-cron/dist/esm/scheduler/runner.js new file mode 100644 index 0000000..11ffa77 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/scheduler/runner.js @@ -0,0 +1,192 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Runner = void 0; +const create_id_1 = require("../create-id"); +const logger_1 = __importDefault(require("../logger")); +const tracked_promise_1 = require("../promise/tracked-promise"); +function emptyOnFn() { } +; +function emptyHookFn() { return true; } +; +function defaultOnError(date, error) { + logger_1.default.error('Task failed with error!', error); +} +class Runner { + timeMatcher; + onMatch; + noOverlap; + maxExecutions; + maxRandomDelay; + runCount; + running; + heartBeatTimeout; + onMissedExecution; + onOverlap; + onError; + beforeRun; + onFinished; + onMaxExecutions; + constructor(timeMatcher, onMatch, options) { + this.timeMatcher = timeMatcher; + this.onMatch = onMatch; + this.noOverlap = options == undefined || options.noOverlap === undefined ? false : options.noOverlap; + this.maxExecutions = options?.maxExecutions; + this.maxRandomDelay = options?.maxRandomDelay || 0; + this.onMissedExecution = options?.onMissedExecution || emptyOnFn; + this.onOverlap = options?.onOverlap || emptyOnFn; + this.onError = options?.onError || defaultOnError; + this.onFinished = options?.onFinished || emptyHookFn; + this.beforeRun = options?.beforeRun || emptyHookFn; + this.onMaxExecutions = options?.onMaxExecutions || emptyOnFn; + this.runCount = 0; + this.running = false; + } + start() { + this.running = true; + let lastExecution; + let expectedNextExecution; + const scheduleNextHeartBeat = (currentDate) => { + if (this.running) { + clearTimeout(this.heartBeatTimeout); + this.heartBeatTimeout = setTimeout(heartBeat, getDelay(this.timeMatcher, currentDate)); + } + }; + const runTask = (date) => { + return new Promise(async (resolve) => { + const execution = { + id: (0, create_id_1.createID)('exec'), + reason: 'scheduled' + }; + const shouldExecute = await this.beforeRun(date, execution); + const randomDelay = Math.floor(Math.random() * this.maxRandomDelay); + if (shouldExecute) { + setTimeout(async () => { + try { + this.runCount++; + execution.startedAt = new Date(); + const result = await this.onMatch(date, execution); + execution.finishedAt = new Date(); + execution.result = result; + this.onFinished(date, execution); + if (this.maxExecutions && this.runCount >= this.maxExecutions) { + this.onMaxExecutions(date); + this.stop(); + } + } + catch (error) { + execution.finishedAt = new Date(); + execution.error = error; + this.onError(date, error, execution); + } + resolve(true); + }, randomDelay); + } + }); + }; + const checkAndRun = (date) => { + return new tracked_promise_1.TrackedPromise(async (resolve, reject) => { + try { + if (this.timeMatcher.match(date)) { + await runTask(date); + } + resolve(true); + } + catch (err) { + reject(err); + } + }); + }; + const heartBeat = async () => { + const currentDate = nowWithoutMs(); + if (expectedNextExecution && expectedNextExecution.getTime() < currentDate.getTime()) { + while (expectedNextExecution.getTime() < currentDate.getTime()) { + logger_1.default.warn(`missed execution at ${expectedNextExecution}! Possible blocking IO or high CPU user at the same process used by node-cron.`); + expectedNextExecution = this.timeMatcher.getNextMatch(expectedNextExecution); + runAsync(this.onMissedExecution, expectedNextExecution, defaultOnError); + } + } + if (lastExecution && lastExecution.getState() === 'pending') { + runAsync(this.onOverlap, currentDate, defaultOnError); + if (this.noOverlap) { + logger_1.default.warn('task still running, new execution blocked by overlap prevention!'); + expectedNextExecution = this.timeMatcher.getNextMatch(currentDate); + scheduleNextHeartBeat(currentDate); + return; + } + } + lastExecution = checkAndRun(currentDate); + expectedNextExecution = this.timeMatcher.getNextMatch(currentDate); + scheduleNextHeartBeat(currentDate); + }; + this.heartBeatTimeout = setTimeout(() => { + heartBeat(); + }, getDelay(this.timeMatcher, nowWithoutMs())); + } + nextRun() { + return this.timeMatcher.getNextMatch(new Date()); + } + stop() { + this.running = false; + if (this.heartBeatTimeout) { + clearTimeout(this.heartBeatTimeout); + this.heartBeatTimeout = undefined; + } + } + isStarted() { + return !!this.heartBeatTimeout && this.running; + } + isStopped() { + return !this.isStarted(); + } + async execute() { + const date = new Date(); + const execution = { + id: (0, create_id_1.createID)('exec'), + reason: 'invoked' + }; + try { + const shouldExecute = await this.beforeRun(date, execution); + if (shouldExecute) { + this.runCount++; + execution.startedAt = new Date(); + const result = await this.onMatch(date, execution); + execution.finishedAt = new Date(); + execution.result = result; + this.onFinished(date, execution); + } + } + catch (error) { + execution.finishedAt = new Date(); + execution.error = error; + this.onError(date, error, execution); + } + } +} +exports.Runner = Runner; +async function runAsync(fn, date, onError) { + try { + await fn(date); + } + catch (error) { + onError(date, error); + } +} +function getDelay(timeMatcher, currentDate) { + const maxDelay = 86400000; + const nextRun = timeMatcher.getNextMatch(currentDate); + const now = new Date(); + const delay = nextRun.getTime() - now.getTime(); + if (delay > maxDelay) { + return maxDelay; + } + return Math.max(0, delay); +} +function nowWithoutMs() { + const date = new Date(); + date.setMilliseconds(0); + return date; +} +//# sourceMappingURL=runner.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/scheduler/runner.js.map b/backend/node_modules/node-cron/dist/esm/scheduler/runner.js.map new file mode 100644 index 0000000..112ddfa --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/scheduler/runner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/scheduler/runner.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/task-registry.d.ts b/backend/node_modules/node-cron/dist/esm/task-registry.d.ts new file mode 100644 index 0000000..91224ef --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/task-registry.d.ts @@ -0,0 +1,11 @@ +import { ScheduledTask } from "./tasks/scheduled-task"; +declare const tasks: Map; +export declare class TaskRegistry { + add(task: ScheduledTask): void; + get(taskId: string): ScheduledTask | undefined; + remove(task: ScheduledTask): void; + all(): typeof tasks; + has(taskId: string): boolean; + killAll(): void; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/esm/task-registry.js b/backend/node_modules/node-cron/dist/esm/task-registry.js new file mode 100644 index 0000000..138c30a --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/task-registry.js @@ -0,0 +1,35 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TaskRegistry = void 0; +const tasks = new Map(); +class TaskRegistry { + add(task) { + if (this.has(task.id)) { + throw Error(`task ${task.id} already registred!`); + } + tasks.set(task.id, task); + task.on('task:destroyed', () => { + this.remove(task); + }); + } + get(taskId) { + return tasks.get(taskId); + } + remove(task) { + if (this.has(task.id)) { + task?.destroy(); + tasks.delete(task.id); + } + } + all() { + return tasks; + } + has(taskId) { + return tasks.has(taskId); + } + killAll() { + tasks.forEach(id => this.remove(id)); + } +} +exports.TaskRegistry = TaskRegistry; +//# sourceMappingURL=task-registry.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/task-registry.js.map b/backend/node_modules/node-cron/dist/esm/task-registry.js.map new file mode 100644 index 0000000..5ebc390 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/task-registry.js.map @@ -0,0 +1 @@ +{"version":3,"file":"task-registry.js","sourceRoot":"","sources":["../../src/task-registry.ts"],"names":[],"mappings":";;;AAEA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEhD,MAAa,YAAY;IACvB,GAAG,CAAC,IAAmB;QACrB,IAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAC,CAAC;YACpB,MAAM,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,qBAAqB,CAAC,CAAA;QACnD,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAEzB,IAAI,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,IAAmB;QACxB,IAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAC,CAAC;YACpB,IAAI,EAAE,OAAO,EAAE,CAAC;YAChB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,GAAG;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO;QACN,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACtC,CAAC;CACF;AAnCD,oCAmCC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.d.ts b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.d.ts new file mode 100644 index 0000000..3af9fb8 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.d.ts @@ -0,0 +1,28 @@ +import { ChildProcess } from 'child_process'; +import { ScheduledTask, TaskContext, TaskEvent, TaskOptions } from '../scheduled-task'; +import { EventEmitter } from 'stream'; +import { StateMachine } from '../state-machine'; +declare class TaskEmitter extends EventEmitter { +} +declare class BackgroundScheduledTask implements ScheduledTask { + emitter: TaskEmitter; + id: string; + name: string; + cronExpression: any; + taskPath: any; + options?: any; + forkProcess?: ChildProcess; + stateMachine: StateMachine; + constructor(cronExpression: string, taskPath: string, options?: TaskOptions); + getNextRun(): Date | null; + start(): Promise; + stop(): Promise; + getStatus(): string; + destroy(): Promise; + execute(): Promise; + on(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + off(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + once(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + private createContext; +} +export default BackgroundScheduledTask; diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js new file mode 100644 index 0000000..1b9f8af --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js @@ -0,0 +1,220 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const child_process_1 = require("child_process"); +const create_id_1 = require("../../create-id"); +const stream_1 = require("stream"); +const state_machine_1 = require("../state-machine"); +const localized_time_1 = require("../../time/localized-time"); +const logger_1 = __importDefault(require("../../logger")); +const time_matcher_1 = require("../../time/time-matcher"); +const daemonPath = (0, path_1.resolve)(__dirname, 'daemon.js'); +class TaskEmitter extends stream_1.EventEmitter { +} +class BackgroundScheduledTask { + emitter; + id; + name; + cronExpression; + taskPath; + options; + forkProcess; + stateMachine; + constructor(cronExpression, taskPath, options) { + this.cronExpression = cronExpression; + this.taskPath = taskPath; + this.options = options; + this.id = (0, create_id_1.createID)('task'); + this.name = options?.name || this.id; + this.emitter = new TaskEmitter(); + this.stateMachine = new state_machine_1.StateMachine('stopped'); + this.on('task:stopped', () => { + this.forkProcess?.kill(); + this.forkProcess = undefined; + this.stateMachine.changeState('stopped'); + }); + this.on('task:destroyed', () => { + this.forkProcess?.kill(); + this.forkProcess = undefined; + this.stateMachine.changeState('destroyed'); + }); + } + getNextRun() { + if (this.stateMachine.state !== 'stopped') { + const timeMatcher = new time_matcher_1.TimeMatcher(this.cronExpression, this.options?.timezone); + return timeMatcher.getNextMatch(new Date()); + } + return null; + } + start() { + return new Promise((resolve, reject) => { + if (this.forkProcess) { + return resolve(undefined); + } + const timeout = setTimeout(() => { + reject(new Error('Start operation timed out')); + }, 5000); + try { + this.forkProcess = (0, child_process_1.fork)(daemonPath); + this.forkProcess.on('error', (err) => { + clearTimeout(timeout); + reject(new Error(`Error on daemon: ${err.message}`)); + }); + this.forkProcess.on('exit', (code, signal) => { + if (code !== 0 && signal !== 'SIGTERM') { + const erro = new Error(`node-cron daemon exited with code ${code || signal}`); + logger_1.default.error(erro); + clearTimeout(timeout); + reject(erro); + } + }); + this.forkProcess.on('message', (message) => { + if (message.jsonError) { + if (message.context?.execution) { + message.context.execution.error = deserializeError(message.jsonError); + delete message.jsonError; + } + } + if (message.context?.task?.state) { + this.stateMachine.changeState(message.context?.task?.state); + } + if (message.context) { + const execution = message.context?.execution; + delete execution?.hasError; + const context = this.createContext(new Date(message.context.date), execution); + this.emitter.emit(message.event, context); + } + }); + this.once('task:started', () => { + this.stateMachine.changeState('idle'); + clearTimeout(timeout); + resolve(undefined); + }); + this.forkProcess.send({ + command: 'task:start', + path: this.taskPath, + cron: this.cronExpression, + options: this.options + }); + } + catch (error) { + reject(error); + } + }); + } + stop() { + return new Promise((resolve, reject) => { + if (!this.forkProcess) { + return resolve(undefined); + } + const timeoutId = setTimeout(() => { + clearTimeout(timeoutId); + reject(new Error('Stop operation timed out')); + }, 5000); + const cleanupAndResolve = () => { + clearTimeout(timeoutId); + this.off('task:stopped', onStopped); + this.forkProcess = undefined; + resolve(undefined); + }; + const onStopped = () => { + cleanupAndResolve(); + }; + this.once('task:stopped', onStopped); + this.forkProcess.send({ + command: 'task:stop' + }); + }); + } + getStatus() { + return this.stateMachine.state; + } + destroy() { + return new Promise((resolve, reject) => { + if (!this.forkProcess) { + return resolve(undefined); + } + const timeoutId = setTimeout(() => { + clearTimeout(timeoutId); + reject(new Error('Destroy operation timed out')); + }, 5000); + const onDestroy = () => { + clearTimeout(timeoutId); + this.off('task:destroyed', onDestroy); + resolve(undefined); + }; + this.once('task:destroyed', onDestroy); + this.forkProcess.send({ + command: 'task:destroy' + }); + }); + } + execute() { + return new Promise((resolve, reject) => { + if (!this.forkProcess) { + return reject(new Error('Cannot execute background task because it hasn\'t been started yet. Please initialize the task using the start() method before attempting to execute it.')); + } + const timeoutId = setTimeout(() => { + cleanupListeners(); + reject(new Error('Execution timeout exceeded')); + }, 5000); + const cleanupListeners = () => { + clearTimeout(timeoutId); + this.off('execution:finished', onFinished); + this.off('execution:failed', onFail); + }; + const onFinished = (context) => { + cleanupListeners(); + resolve(context.execution?.result); + }; + const onFail = (context) => { + cleanupListeners(); + reject(context.execution?.error || new Error('Execution failed without specific error')); + }; + this.once('execution:finished', onFinished); + this.once('execution:failed', onFail); + this.forkProcess.send({ + command: 'task:execute' + }); + }); + } + on(event, fun) { + this.emitter.on(event, fun); + } + off(event, fun) { + this.emitter.off(event, fun); + } + once(event, fun) { + this.emitter.once(event, fun); + } + createContext(executionDate, execution) { + const localTime = new localized_time_1.LocalizedTime(executionDate, this.options?.timezone); + const ctx = { + date: localTime.toDate(), + dateLocalIso: localTime.toISO(), + triggeredAt: new Date(), + task: this, + execution: execution + }; + return ctx; + } +} +function deserializeError(str) { + const data = JSON.parse(str); + const Err = globalThis[data.name] || Error; + const err = new Err(data.message); + if (data.stack) { + err.stack = data.stack; + } + Object.keys(data).forEach(key => { + if (!['name', 'message', 'stack'].includes(key)) { + err[key] = data[key]; + } + }); + return err; +} +exports.default = BackgroundScheduledTask; +//# sourceMappingURL=background-scheduled-task.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js.map b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js.map new file mode 100644 index 0000000..ee6ea1e --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/background-scheduled-task.js.map @@ -0,0 +1 @@ +{"version":3,"file":"background-scheduled-task.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/background-scheduled-task.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.d.ts b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.d.ts new file mode 100644 index 0000000..d7728e9 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.d.ts @@ -0,0 +1,3 @@ +import { ScheduledTask } from "../scheduled-task"; +export declare function startDaemon(message: any): Promise; +export declare function bind(): void; diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js new file mode 100644 index 0000000..4d1eb2a --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js @@ -0,0 +1,109 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.startDaemon = startDaemon; +exports.bind = bind; +const url_1 = require("url"); +const logger_1 = __importDefault(require("../../logger")); +const inline_scheduled_task_1 = require("../inline-scheduled-task"); +async function startDaemon(message) { + let script; + try { + script = await import(message.path); + } + catch { + script = await import((0, url_1.fileURLToPath)(message.path)); + } + const task = new inline_scheduled_task_1.InlineScheduledTask(message.cron, script.task, message.options); + task.on('task:started', (context => sendEvent('task:started', context))); + task.on('task:stopped', (context => sendEvent('task:stopped', context))); + task.on('task:destroyed', (context => sendEvent('task:destroyed', context))); + task.on('execution:started', (context => sendEvent('execution:started', context))); + task.on('execution:finished', (context => sendEvent('execution:finished', context))); + task.on('execution:failed', (context => sendEvent('execution:failed', context))); + task.on('execution:missed', (context => sendEvent('execution:missed', context))); + task.on('execution:overlap', (context => sendEvent('execution:overlap', context))); + task.on('execution:maxReached', (context => sendEvent('execution:maxReached', context))); + if (process.send) + process.send({ event: 'daemon:started' }); + task.start(); + return task; +} +function sendEvent(event, context) { + const message = { event: event, context: safelySerializeContext(context) }; + if (context.execution?.error) { + message.jsonError = serializeError(context.execution?.error); + } + if (process.send) + process.send(message); +} +function serializeError(err) { + const plain = { + name: err.name, + message: err.message, + stack: err.stack, + ...Object.getOwnPropertyNames(err) + .filter(k => !['name', 'message', 'stack'].includes(k)) + .reduce((acc, k) => { + acc[k] = err[k]; + return acc; + }, {}) + }; + return JSON.stringify(plain); +} +function safelySerializeContext(context) { + const safeContext = { + date: context.date, + dateLocalIso: context.dateLocalIso, + triggeredAt: context.triggeredAt + }; + if (context.task) { + safeContext.task = { + id: context.task.id, + name: context.task.name, + status: context.task.getStatus() + }; + } + if (context.execution) { + safeContext.execution = { + id: context.execution.id, + reason: context.execution.reason, + startedAt: context.execution.startedAt, + finishedAt: context.execution.finishedAt, + hasError: !!context.execution.error, + result: context.execution.result + }; + } + return safeContext; +} +function bind() { + let task; + process.on('message', async (message) => { + switch (message.command) { + case 'task:start': + task = await startDaemon(message); + return task; + case 'task:stop': + if (task) + task.stop(); + return task; + case 'task:destroy': + if (task) + task.destroy(); + return task; + case 'task:execute': + try { + if (task) + await task.execute(); + } + catch (error) { + logger_1.default.debug('Daemon task:execute falied:', error); + } + return task; + } + }); +} +bind(); +//# sourceMappingURL=daemon.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js.map b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js.map new file mode 100644 index 0000000..3cd7fd7 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/daemon.js.map @@ -0,0 +1 @@ +{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/daemon.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.d.ts b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js new file mode 100644 index 0000000..aa219d8 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js.map b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js.map new file mode 100644 index 0000000..19beb39 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/background-scheduled-task/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/tasks/background-scheduled-task/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.d.ts b/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.d.ts new file mode 100644 index 0000000..e118506 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.d.ts @@ -0,0 +1,30 @@ +import EventEmitter from "events"; +import { ScheduledTask, TaskContext, TaskEvent, TaskFn, TaskOptions } from "./scheduled-task"; +import { Runner } from "../scheduler/runner"; +import { TimeMatcher } from "../time/time-matcher"; +import { StateMachine } from "./state-machine"; +declare class TaskEmitter extends EventEmitter { +} +export declare class InlineScheduledTask implements ScheduledTask { + emitter: TaskEmitter; + cronExpression: string; + timeMatcher: TimeMatcher; + runner: Runner; + id: string; + name: string; + stateMachine: StateMachine; + timezone?: string; + constructor(cronExpression: string, taskFn: TaskFn, options?: TaskOptions); + getNextRun(): Date | null; + private changeState; + start(): void; + stop(): void; + getStatus(): string; + destroy(): void; + execute(): Promise; + on(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + off(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + once(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + private createContext; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js b/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js new file mode 100644 index 0000000..00e9fdd --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js @@ -0,0 +1,144 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InlineScheduledTask = void 0; +const events_1 = __importDefault(require("events")); +const runner_1 = require("../scheduler/runner"); +const time_matcher_1 = require("../time/time-matcher"); +const create_id_1 = require("../create-id"); +const state_machine_1 = require("./state-machine"); +const logger_1 = __importDefault(require("../logger")); +const localized_time_1 = require("../time/localized-time"); +class TaskEmitter extends events_1.default { +} +class InlineScheduledTask { + emitter; + cronExpression; + timeMatcher; + runner; + id; + name; + stateMachine; + timezone; + constructor(cronExpression, taskFn, options) { + this.emitter = new TaskEmitter(); + this.cronExpression = cronExpression; + this.id = (0, create_id_1.createID)('task', 12); + this.name = options?.name || this.id; + this.timezone = options?.timezone; + this.timeMatcher = new time_matcher_1.TimeMatcher(cronExpression, options?.timezone); + this.stateMachine = new state_machine_1.StateMachine(); + const runnerOptions = { + timezone: options?.timezone, + noOverlap: options?.noOverlap, + maxExecutions: options?.maxExecutions, + maxRandomDelay: options?.maxRandomDelay, + beforeRun: (date, execution) => { + if (execution.reason === 'scheduled') { + this.changeState('running'); + } + this.emitter.emit('execution:started', this.createContext(date, execution)); + return true; + }, + onFinished: (date, execution) => { + if (execution.reason === 'scheduled') { + this.changeState('idle'); + } + this.emitter.emit('execution:finished', this.createContext(date, execution)); + return true; + }, + onError: (date, error, execution) => { + logger_1.default.error(error); + this.emitter.emit('execution:failed', this.createContext(date, execution)); + this.changeState('idle'); + }, + onOverlap: (date) => { + this.emitter.emit('execution:overlap', this.createContext(date)); + }, + onMissedExecution: (date) => { + this.emitter.emit('execution:missed', this.createContext(date)); + }, + onMaxExecutions: (date) => { + this.emitter.emit('execution:maxReached', this.createContext(date)); + this.destroy(); + } + }; + this.runner = new runner_1.Runner(this.timeMatcher, (date, execution) => { + return taskFn(this.createContext(date, execution)); + }, runnerOptions); + } + getNextRun() { + if (this.stateMachine.state !== 'stopped') { + return this.runner.nextRun(); + } + return null; + } + changeState(state) { + if (this.runner.isStarted()) { + this.stateMachine.changeState(state); + } + } + start() { + if (this.runner.isStopped()) { + this.runner.start(); + this.stateMachine.changeState('idle'); + this.emitter.emit('task:started', this.createContext(new Date())); + } + } + stop() { + if (this.runner.isStarted()) { + this.runner.stop(); + this.stateMachine.changeState('stopped'); + this.emitter.emit('task:stopped', this.createContext(new Date())); + } + } + getStatus() { + return this.stateMachine.state; + } + destroy() { + if (this.stateMachine.state === 'destroyed') + return; + this.stop(); + this.stateMachine.changeState('destroyed'); + this.emitter.emit('task:destroyed', this.createContext(new Date())); + } + execute() { + return new Promise((resolve, reject) => { + const onFail = (context) => { + this.off('execution:finished', onFail); + reject(context.execution?.error); + }; + const onFinished = (context) => { + this.off('execution:failed', onFail); + resolve(context.execution?.result); + }; + this.once('execution:finished', onFinished); + this.once('execution:failed', onFail); + this.runner.execute(); + }); + } + on(event, fun) { + this.emitter.on(event, fun); + } + off(event, fun) { + this.emitter.off(event, fun); + } + once(event, fun) { + this.emitter.once(event, fun); + } + createContext(executionDate, execution) { + const localTime = new localized_time_1.LocalizedTime(executionDate, this.timezone); + const ctx = { + date: localTime.toDate(), + dateLocalIso: localTime.toISO(), + triggeredAt: new Date(), + task: this, + execution: execution + }; + return ctx; + } +} +exports.InlineScheduledTask = InlineScheduledTask; +//# sourceMappingURL=inline-scheduled-task.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js.map b/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js.map new file mode 100644 index 0000000..e62f7a3 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/inline-scheduled-task.js.map @@ -0,0 +1 @@ +{"version":3,"file":"inline-scheduled-task.js","sourceRoot":"","sources":["../../../src/tasks/inline-scheduled-task.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.d.ts b/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.d.ts new file mode 100644 index 0000000..878e04b --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.d.ts @@ -0,0 +1,37 @@ +export type TaskContext = { + date: Date; + dateLocalIso: string; + task?: ScheduledTask; + execution?: Execution; + triggeredAt: Date; +}; +export type TaskEvent = 'task:started' | 'task:stopped' | 'task:destroyed' | 'execution:started' | 'execution:finished' | 'execution:failed' | 'execution:missed' | 'execution:overlap' | 'execution:maxReached'; +export type TaskOptions = { + timezone?: string; + name?: string; + noOverlap?: boolean; + maxExecutions?: number; + maxRandomDelay?: number; +}; +export type Execution = { + id: string; + reason: 'invoked' | 'scheduled'; + startedAt?: Date; + finishedAt?: Date; + error?: Error; + result?: any; +}; +export type TaskFn = (context: TaskContext) => any | Promise; +export interface ScheduledTask { + id: string; + name?: string; + start(): void | Promise; + stop(): void | Promise; + getStatus(): string | Promise; + destroy(): void | Promise; + execute(): Promise; + getNextRun(): Date | null; + on(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + off(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; + once(event: TaskEvent, fun: (context: TaskContext) => Promise | void): void; +} diff --git a/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js b/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js new file mode 100644 index 0000000..8101c21 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=scheduled-task.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js.map b/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js.map new file mode 100644 index 0000000..7282f56 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/scheduled-task.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scheduled-task.js","sourceRoot":"","sources":["../../../src/tasks/scheduled-task.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/state-machine.d.ts b/backend/node_modules/node-cron/dist/esm/tasks/state-machine.d.ts new file mode 100644 index 0000000..2f54ce1 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/state-machine.d.ts @@ -0,0 +1,6 @@ +export type TaskState = 'stopped' | 'idle' | 'running' | 'destroyed'; +export declare class StateMachine { + state: TaskState; + constructor(initial?: TaskState); + changeState(state: TaskState): void; +} diff --git a/backend/node_modules/node-cron/dist/esm/tasks/state-machine.js b/backend/node_modules/node-cron/dist/esm/tasks/state-machine.js new file mode 100644 index 0000000..8375037 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/state-machine.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StateMachine = void 0; +const allowedTransitions = { + 'stopped': ['stopped', 'idle', 'destroyed'], + 'idle': ['idle', 'running', 'stopped', 'destroyed'], + 'running': ['running', 'idle', 'stopped', 'destroyed'], + 'destroyed': ['destroyed'] +}; +class StateMachine { + state; + constructor(initial = 'stopped') { + this.state = initial; + } + changeState(state) { + if (allowedTransitions[this.state].includes(state)) { + this.state = state; + } + else { + throw new Error(`invalid transition from ${this.state} to ${state}`); + } + } +} +exports.StateMachine = StateMachine; +//# sourceMappingURL=state-machine.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/tasks/state-machine.js.map b/backend/node_modules/node-cron/dist/esm/tasks/state-machine.js.map new file mode 100644 index 0000000..3b83d2a --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/tasks/state-machine.js.map @@ -0,0 +1 @@ +{"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../../../src/tasks/state-machine.ts"],"names":[],"mappings":";;;AAEA,MAAM,kBAAkB,GAAmC;IACzD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC;IAC3C,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC;IACnD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC;IACtD,WAAW,EAAE,CAAC,WAAW,CAAC;CAC3B,CAAA;AAED,MAAa,YAAY;IACvB,KAAK,CAAY;IAEjB,YAAY,UAAqB,SAAS;QACxC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;IACvB,CAAC;IAED,WAAW,CAAC,KAAgB;QAC1B,IAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAC,CAAC;YACjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;CAEF;AAfD,oCAeC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/time/localized-time.d.ts b/backend/node_modules/node-cron/dist/esm/time/localized-time.d.ts new file mode 100644 index 0000000..75b0c0b --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/localized-time.d.ts @@ -0,0 +1,22 @@ +type DateParts = { + day: number; + month: number; + year: number; + hour: number; + minute: number; + second: number; + milisecond: number; + weekday: string; + gmt: string; +}; +export declare class LocalizedTime { + timestamp: number; + parts: DateParts; + timezone?: string | undefined; + constructor(date: Date, timezone?: string); + toDate(): Date; + toISO(): string; + getParts(): DateParts; + set(field: string, value: number): void; +} +export {}; diff --git a/backend/node_modules/node-cron/dist/esm/time/localized-time.js b/backend/node_modules/node-cron/dist/esm/time/localized-time.js new file mode 100644 index 0000000..af21865 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/localized-time.js @@ -0,0 +1,81 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LocalizedTime = void 0; +class LocalizedTime { + timestamp; + parts; + timezone; + constructor(date, timezone) { + this.timestamp = date.getTime(); + this.timezone = timezone; + this.parts = buildDateParts(date, timezone); + } + toDate() { + return new Date(this.timestamp); + } + toISO() { + const gmt = this.parts.gmt.replace(/^GMT/, ''); + const offset = gmt ? gmt : 'Z'; + const pad = (n) => String(n).padStart(2, '0'); + return `${this.parts.year}-${pad(this.parts.month)}-${pad(this.parts.day)}` + + `T${pad(this.parts.hour)}:${pad(this.parts.minute)}:${pad(this.parts.second)}` + + `.${String(this.parts.milisecond).padStart(3, '0')}` + + offset; + } + getParts() { + return this.parts; + } + set(field, value) { + this.parts[field] = value; + const newDate = new Date(this.toISO()); + this.timestamp = newDate.getTime(); + this.parts = buildDateParts(newDate, this.timezone); + } +} +exports.LocalizedTime = LocalizedTime; +function buildDateParts(date, timezone) { + const dftOptions = { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + weekday: 'short', + hour12: false + }; + if (timezone) { + dftOptions.timeZone = timezone; + } + const dateFormat = new Intl.DateTimeFormat('en-US', dftOptions); + const parts = dateFormat.formatToParts(date).filter(part => { + return part.type !== 'literal'; + }).reduce((acc, part) => { + acc[part.type] = part.value; + return acc; + }, {}); + return { + day: parseInt(parts.day), + month: parseInt(parts.month), + year: parseInt(parts.year), + hour: parts.hour === '24' ? 0 : parseInt(parts.hour), + minute: parseInt(parts.minute), + second: parseInt(parts.second), + milisecond: date.getMilliseconds(), + weekday: parts.weekday, + gmt: getTimezoneGMT(date, timezone) + }; +} +function getTimezoneGMT(date, timezone) { + const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })); + const tzDate = new Date(date.toLocaleString('en-US', { timeZone: timezone })); + let offsetInMinutes = (utcDate.getTime() - tzDate.getTime()) / 60000; + const sign = offsetInMinutes <= 0 ? '+' : '-'; + offsetInMinutes = Math.abs(offsetInMinutes); + if (offsetInMinutes === 0) + return 'Z'; + const hours = Math.floor(offsetInMinutes / 60).toString().padStart(2, '0'); + const minutes = Math.floor(offsetInMinutes % 60).toString().padStart(2, '0'); + return `GMT${sign}${hours}:${minutes}`; +} +//# sourceMappingURL=localized-time.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/time/localized-time.js.map b/backend/node_modules/node-cron/dist/esm/time/localized-time.js.map new file mode 100644 index 0000000..b53db2a --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/localized-time.js.map @@ -0,0 +1 @@ +{"version":3,"file":"localized-time.js","sourceRoot":"","sources":["../../../src/time/localized-time.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/time/matcher-walker.d.ts b/backend/node_modules/node-cron/dist/esm/time/matcher-walker.d.ts new file mode 100644 index 0000000..1676430 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/matcher-walker.d.ts @@ -0,0 +1,13 @@ +import { LocalizedTime } from './localized-time'; +import { TimeMatcher } from './time-matcher'; +export declare class MatcherWalker { + cronExpression: string; + baseDate: Date; + pattern: any; + expressions: number[][]; + timeMatcher: TimeMatcher; + timezone?: string; + constructor(cronExpression: string, baseDate: Date, timezone?: string); + isMatching(): boolean; + matchNext(): LocalizedTime; +} diff --git a/backend/node_modules/node-cron/dist/esm/time/matcher-walker.js b/backend/node_modules/node-cron/dist/esm/time/matcher-walker.js new file mode 100644 index 0000000..8e6ff5b --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/matcher-walker.js @@ -0,0 +1,100 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MatcherWalker = void 0; +const convertion_1 = __importDefault(require("../pattern/convertion")); +const localized_time_1 = require("./localized-time"); +const time_matcher_1 = require("./time-matcher"); +const week_day_names_conversion_1 = __importDefault(require("../pattern/convertion/week-day-names-conversion")); +class MatcherWalker { + cronExpression; + baseDate; + pattern; + expressions; + timeMatcher; + timezone; + constructor(cronExpression, baseDate, timezone) { + this.cronExpression = cronExpression; + this.baseDate = baseDate; + this.timeMatcher = new time_matcher_1.TimeMatcher(cronExpression, timezone); + this.timezone = timezone; + this.expressions = (0, convertion_1.default)(cronExpression); + } + isMatching() { + return this.timeMatcher.match(this.baseDate); + } + matchNext() { + const findNextDateIgnoringWeekday = () => { + const baseDate = new Date(this.baseDate.getTime()); + baseDate.setMilliseconds(0); + const localTime = new localized_time_1.LocalizedTime(baseDate, this.timezone); + const dateParts = localTime.getParts(); + const date = new localized_time_1.LocalizedTime(localTime.toDate(), this.timezone); + const seconds = this.expressions[0]; + const nextSecond = availableValue(seconds, dateParts.second); + if (nextSecond) { + date.set('second', nextSecond); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('second', seconds[0]); + const minutes = this.expressions[1]; + const nextMinute = availableValue(minutes, dateParts.minute); + if (nextMinute) { + date.set('minute', nextMinute); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('minute', minutes[0]); + const hours = this.expressions[2]; + const nextHour = availableValue(hours, dateParts.hour); + if (nextHour) { + date.set('hour', nextHour); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('hour', hours[0]); + const days = this.expressions[3]; + const nextDay = availableValue(days, dateParts.day); + if (nextDay) { + date.set('day', nextDay); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('day', days[0]); + const months = this.expressions[4]; + const nextMonth = availableValue(months, dateParts.month); + if (nextMonth) { + date.set('month', nextMonth); + if (this.timeMatcher.match(date.toDate())) { + return date; + } + } + date.set('year', date.getParts().year + 1); + date.set('month', months[0]); + return date; + }; + const date = findNextDateIgnoringWeekday(); + const weekdays = this.expressions[5]; + let currentWeekday = parseInt((0, week_day_names_conversion_1.default)(date.getParts().weekday)); + while (!(weekdays.indexOf(currentWeekday) > -1)) { + date.set('year', date.getParts().year + 1); + currentWeekday = parseInt((0, week_day_names_conversion_1.default)(date.getParts().weekday)); + } + return date; + } +} +exports.MatcherWalker = MatcherWalker; +function availableValue(values, currentValue) { + const availableValues = values.sort((a, b) => a - b).filter(s => s > currentValue); + if (availableValues.length > 0) + return availableValues[0]; + return false; +} +//# sourceMappingURL=matcher-walker.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/time/matcher-walker.js.map b/backend/node_modules/node-cron/dist/esm/time/matcher-walker.js.map new file mode 100644 index 0000000..77f11e0 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/matcher-walker.js.map @@ -0,0 +1 @@ +{"version":3,"file":"matcher-walker.js","sourceRoot":"","sources":["../../../src/time/matcher-walker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/time/time-matcher.d.ts b/backend/node_modules/node-cron/dist/esm/time/time-matcher.d.ts new file mode 100644 index 0000000..ed432fa --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/time-matcher.d.ts @@ -0,0 +1,8 @@ +export declare class TimeMatcher { + timezone?: string; + pattern: string; + expressions: any[]; + constructor(pattern: string, timezone?: string); + match(date: Date): boolean; + getNextMatch(date: Date): Date; +} diff --git a/backend/node_modules/node-cron/dist/esm/time/time-matcher.js b/backend/node_modules/node-cron/dist/esm/time/time-matcher.js new file mode 100644 index 0000000..0ebb066 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/time-matcher.js @@ -0,0 +1,41 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TimeMatcher = void 0; +const index_1 = __importDefault(require("../pattern/convertion/index")); +const week_day_names_conversion_1 = __importDefault(require("../pattern/convertion/week-day-names-conversion")); +const localized_time_1 = require("./localized-time"); +const matcher_walker_1 = require("./matcher-walker"); +function matchValue(allowedValues, value) { + return allowedValues.indexOf(value) !== -1; +} +class TimeMatcher { + timezone; + pattern; + expressions; + constructor(pattern, timezone) { + this.timezone = timezone; + this.pattern = pattern; + this.expressions = (0, index_1.default)(pattern); + } + match(date) { + const localizedTime = new localized_time_1.LocalizedTime(date, this.timezone); + const parts = localizedTime.getParts(); + const runOnSecond = matchValue(this.expressions[0], parts.second); + const runOnMinute = matchValue(this.expressions[1], parts.minute); + const runOnHour = matchValue(this.expressions[2], parts.hour); + const runOnDay = matchValue(this.expressions[3], parts.day); + const runOnMonth = matchValue(this.expressions[4], parts.month); + const runOnWeekDay = matchValue(this.expressions[5], parseInt((0, week_day_names_conversion_1.default)(parts.weekday))); + return runOnSecond && runOnMinute && runOnHour && runOnDay && runOnMonth && runOnWeekDay; + } + getNextMatch(date) { + const walker = new matcher_walker_1.MatcherWalker(this.pattern, date, this.timezone); + const next = walker.matchNext(); + return next.toDate(); + } +} +exports.TimeMatcher = TimeMatcher; +//# sourceMappingURL=time-matcher.js.map \ No newline at end of file diff --git a/backend/node_modules/node-cron/dist/esm/time/time-matcher.js.map b/backend/node_modules/node-cron/dist/esm/time/time-matcher.js.map new file mode 100644 index 0000000..4560713 --- /dev/null +++ b/backend/node_modules/node-cron/dist/esm/time/time-matcher.js.map @@ -0,0 +1 @@ +{"version":3,"file":"time-matcher.js","sourceRoot":"","sources":["../../../src/time/time-matcher.ts"],"names":[],"mappings":";;;;;;AACA,wEAA4D;AAC5D,gHAAqF;AACrF,qDAAiD;AACjD,qDAAiD;AAEjD,SAAS,UAAU,CAAC,aAAuB,EAAE,KAAa;IACxD,OAAO,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAa,WAAW;IACpB,QAAQ,CAAU;IAClB,OAAO,CAAS;IAChB,WAAW,CAAQ;IAEnB,YAAY,OAAc,EAAE,QAAgB;QACxC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,WAAW,GAAG,IAAA,eAAiB,EAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,IAAU;QACZ,MAAM,aAAa,GAAG,IAAI,8BAAa,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC5D,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAChE,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAA,mCAAsB,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAEtG,OAAO,WAAW,IAAI,WAAW,IAAI,SAAS,IAAI,QAAQ,IAAI,UAAU,IAAI,YAAY,CAAC;IAC7F,CAAC;IAED,YAAY,CAAC,IAAU;QACrB,MAAM,MAAM,GAAG,IAAI,8BAAa,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;CACJ;AA7BD,kCA6BC"} \ No newline at end of file diff --git a/backend/node_modules/node-cron/package.json b/backend/node_modules/node-cron/package.json new file mode 100644 index 0000000..1b17804 --- /dev/null +++ b/backend/node_modules/node-cron/package.json @@ -0,0 +1,85 @@ +{ + "name": "node-cron", + "version": "4.2.1", + "description": "A Lightweight Task Scheduler for Node.js", + "author": "Lucas Merencia", + "license": "ISC", + "homepage": "https://github.com/merencia/node-cron", + "main": "./dist/cjs/node-cron.js", + "module": "./dist/esm/node-cron.js", + "type": "commonjs", + "exports": { + ".": { + "require": { + "types": "./dist/cjs/node-cron.d.ts", + "default": "./dist/cjs/node-cron.js" + }, + "import": { + "types": "./dist/esm/node-cron.d.ts", + "default": "./dist/esm/node-cron.js" + } + } + }, + "scripts": { + "test": "c8 --reporter text --reporter=lcov --exclude '**/*.test.ts' mocha --recursive './src/**/*.test.ts'", + "test:nocov": "mocha --recursive **/*.test.ts", + "lint": "./node_modules/.bin/eslint ./src", + "check": "npm run lint && npm test", + "build:esm": "tsc -p tsconfig.esm.json", + "build:cjs": "tsc -p tsconfig.cjs.json", + "build": "npm run build:esm; npm run build:cjs", + "prepublishOnly": "npm run build" + }, + "engines": { + "node": ">=6.0.0" + }, + "files": [ + "dist/" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/merencia/node-cron.git" + }, + "keywords": [ + "cron", + "scheduler", + "schedule", + "task", + "job" + ], + "bugs": { + "url": "https://github.com/merencia/node-cron/issues" + }, + "devDependencies": { + "@eslint/js": "^9.26.0", + "@tsconfig/recommended": "^1.0.8", + "@types/chai": "^5.2.1", + "@types/expect": "^1.20.4", + "@types/mocha": "^10.0.10", + "@types/node": "^22.15.3", + "@types/sinon": "^17.0.4", + "@typescript-eslint/eslint-plugin": "^8.32.0", + "@typescript-eslint/parser": "^8.32.0", + "c8": "^10.1.3", + "chai": "^5.2.0", + "eslint": "^9.26.0", + "eslint-plugin-mocha": "^10.5.0", + "eslint-plugin-node": "^11.1.0", + "globals": "^16.1.0", + "mocha": "^11.1.0", + "sinon": "^20.0.0", + "tsup": "^8.4.0", + "tsx": "^4.19.3", + "typescript": "^5.8.3", + "typescript-eslint": "^8.32.0" + }, + "c8": { + "reporter": [ + "html", + "text" + ], + "exclude": [ + "src/test-assets/**" + ] + } +} diff --git a/backend/node_modules/redis-errors/.npmignore b/backend/node_modules/redis-errors/.npmignore new file mode 100644 index 0000000..7eee456 --- /dev/null +++ b/backend/node_modules/redis-errors/.npmignore @@ -0,0 +1,15 @@ +# IntelliJ project files +.idea +*.iml +out +gen + +# Irrelevant files and folders +benchmark +coverage +test +.travis.yml +.gitignore +*.log +.vscode +.codeclimate.yml \ No newline at end of file diff --git a/backend/node_modules/redis-errors/LICENSE b/backend/node_modules/redis-errors/LICENSE new file mode 100644 index 0000000..14cc840 --- /dev/null +++ b/backend/node_modules/redis-errors/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2017 Ruben Bridgewater + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/backend/node_modules/redis-errors/README.md b/backend/node_modules/redis-errors/README.md new file mode 100644 index 0000000..b470d29 --- /dev/null +++ b/backend/node_modules/redis-errors/README.md @@ -0,0 +1,116 @@ +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) + +# redis-errors + +All error classes used in [node_redis](https://github.com/NodeRedis/node_redis) +from v.3.0.0 are in here. They can be required as needed. + +## Install + +Install with [NPM](https://npmjs.org/): + + npm install redis-errors + +## Usage + +```js +const { ReplyError, InterruptError } = require('redis-errors'); + +// Using async await +try { + await client.set('foo') // Missing value +} catch (err) { + if (err instanceof InterruptError) { + console.error('Command might have been processed') + } + if (err instanceof ReplyError) { + // ... + } + throw err +} + +// Using callbacks +client.set('foo', (err, res) => { + if (err) { + if (err instanceof InterruptError) { + // ... + } + } +}) +``` + +### Error classes + +All errors returned by NodeRedis use own Error classes. You can distinguish +different errors easily by checking for these classes. + +To know what caused the error they might contain properties to know in more +detail what happened. + +Each error contains a `message`, a `name` and a `stack` property. Please be aware +that the stack might not be useful due to the async nature and is in those cases +therefore limited to two frames. + +There might be more not yet documented properties as well. Please feel free to +open a pull request to document those as well. + +#### RedisError + +`Properties`: + +Properties depend on the individual error. + +All errors returned by NodeRedis (client) are `RedisError`s. +Subclass of `Error` + +#### ReplyError + +`Properties`: + +* `args`: The arguments passed to the command. +* `command`: The command name. +* `code`: The `Redis` error code. Redis itself uses some internal error codes. + +All errors returned by Redis itself (server) will be a `ReplyError`. +Subclass of `RedisError` + +#### ParserError + +`Properties`: + +* `buffer`: The raw buffer input stringified. +* `offset`: The character count where the parsing error occurred. + +Parsing errors are returned as `ParserError`. +Subclass of `RedisError` +**Note:** If you encounter one of these please report that error including the +attached `offset` and `buffer` properties! + +#### AbortError + +`Properties`: + +* `args`: The arguments passed to the command. +* `command`: The command name. + +If a command was not yet executed but rejected, it'll return a `AbortError`. +Subclass of `RedisError` + +#### InterruptError + +`Properties`: + +* `args`: The arguments passed to the command. +* `command`: The command name. +* `origin`: The original error that caused the interrupt + +All executed commands that could not fulfill (e.g. network drop while +executing) return a `InterruptError`. +Subclass of `AbortError` +**Note:** Interrupt errors can happen for multiple reasons that are out of the +scope of NodeRedis itself. There is nothing that can be done on library side +to prevent those. + +## License + +[MIT](./LICENSE) diff --git a/backend/node_modules/redis-errors/index.js b/backend/node_modules/redis-errors/index.js new file mode 100644 index 0000000..84323b4 --- /dev/null +++ b/backend/node_modules/redis-errors/index.js @@ -0,0 +1,7 @@ +'use strict' + +const Errors = process.version.charCodeAt(1) < 55 && process.version.charCodeAt(2) === 46 + ? require('./lib/old') // Node.js < 7 + : require('./lib/modern') + +module.exports = Errors diff --git a/backend/node_modules/redis-errors/lib/modern.js b/backend/node_modules/redis-errors/lib/modern.js new file mode 100644 index 0000000..0f1d1db --- /dev/null +++ b/backend/node_modules/redis-errors/lib/modern.js @@ -0,0 +1,59 @@ +'use strict' + +const assert = require('assert') + +class RedisError extends Error { + get name () { + return this.constructor.name + } +} + +class ParserError extends RedisError { + constructor (message, buffer, offset) { + assert(buffer) + assert.strictEqual(typeof offset, 'number') + + const tmp = Error.stackTraceLimit + Error.stackTraceLimit = 2 + super(message) + Error.stackTraceLimit = tmp + this.offset = offset + this.buffer = buffer + } + + get name () { + return this.constructor.name + } +} + +class ReplyError extends RedisError { + constructor (message) { + const tmp = Error.stackTraceLimit + Error.stackTraceLimit = 2 + super(message) + Error.stackTraceLimit = tmp + } + get name () { + return this.constructor.name + } +} + +class AbortError extends RedisError { + get name () { + return this.constructor.name + } +} + +class InterruptError extends AbortError { + get name () { + return this.constructor.name + } +} + +module.exports = { + RedisError, + ParserError, + ReplyError, + AbortError, + InterruptError +} diff --git a/backend/node_modules/redis-errors/lib/old.js b/backend/node_modules/redis-errors/lib/old.js new file mode 100644 index 0000000..76fc6de --- /dev/null +++ b/backend/node_modules/redis-errors/lib/old.js @@ -0,0 +1,119 @@ +'use strict' + +const assert = require('assert') +const util = require('util') + +// RedisError + +function RedisError (message) { + Object.defineProperty(this, 'message', { + value: message || '', + configurable: true, + writable: true + }) + Error.captureStackTrace(this, this.constructor) +} + +util.inherits(RedisError, Error) + +Object.defineProperty(RedisError.prototype, 'name', { + value: 'RedisError', + configurable: true, + writable: true +}) + +// ParserError + +function ParserError (message, buffer, offset) { + assert(buffer) + assert.strictEqual(typeof offset, 'number') + + Object.defineProperty(this, 'message', { + value: message || '', + configurable: true, + writable: true + }) + + const tmp = Error.stackTraceLimit + Error.stackTraceLimit = 2 + Error.captureStackTrace(this, this.constructor) + Error.stackTraceLimit = tmp + this.offset = offset + this.buffer = buffer +} + +util.inherits(ParserError, RedisError) + +Object.defineProperty(ParserError.prototype, 'name', { + value: 'ParserError', + configurable: true, + writable: true +}) + +// ReplyError + +function ReplyError (message) { + Object.defineProperty(this, 'message', { + value: message || '', + configurable: true, + writable: true + }) + const tmp = Error.stackTraceLimit + Error.stackTraceLimit = 2 + Error.captureStackTrace(this, this.constructor) + Error.stackTraceLimit = tmp +} + +util.inherits(ReplyError, RedisError) + +Object.defineProperty(ReplyError.prototype, 'name', { + value: 'ReplyError', + configurable: true, + writable: true +}) + +// AbortError + +function AbortError (message) { + Object.defineProperty(this, 'message', { + value: message || '', + configurable: true, + writable: true + }) + Error.captureStackTrace(this, this.constructor) +} + +util.inherits(AbortError, RedisError) + +Object.defineProperty(AbortError.prototype, 'name', { + value: 'AbortError', + configurable: true, + writable: true +}) + +// InterruptError + +function InterruptError (message) { + Object.defineProperty(this, 'message', { + value: message || '', + configurable: true, + writable: true + }) + Error.captureStackTrace(this, this.constructor) +} + +util.inherits(InterruptError, AbortError) + +Object.defineProperty(InterruptError.prototype, 'name', { + value: 'InterruptError', + configurable: true, + writable: true +}) + +module.exports = { + RedisError, + ParserError, + ReplyError, + AbortError, + InterruptError +} diff --git a/backend/node_modules/redis-errors/package.json b/backend/node_modules/redis-errors/package.json new file mode 100644 index 0000000..cdf45ba --- /dev/null +++ b/backend/node_modules/redis-errors/package.json @@ -0,0 +1,41 @@ +{ + "name": "redis-errors", + "version": "1.2.0", + "description": "Error classes used in node_redis", + "main": "index.js", + "scripts": { + "test": "npm run coverage", + "lint": "standard --fix", + "posttest": "npm run lint && npm run coverage:check", + "coverage": "node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec", + "coverage:check": "node ./node_modules/istanbul/lib/cli.js check-coverage --statement 100" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/NodeRedis/redis-errors.git" + }, + "keywords": [ + "redis", + "javascript", + "node", + "error" + ], + "engines": { + "node": ">=4" + }, + "devDependencies": { + "istanbul": "^0.4.0", + "mocha": "^3.1.2", + "standard": "^10.0.0" + }, + "author": "Ruben Bridgewater", + "license": "MIT", + "bugs": { + "url": "https://github.com/NodeRedis/redis-errors/issues" + }, + "homepage": "https://github.com/NodeRedis/redis-errors#readme", + "directories": { + "test": "test", + "lib": "lib" + } +} diff --git a/backend/node_modules/redis-parser/.npmignore b/backend/node_modules/redis-parser/.npmignore new file mode 100644 index 0000000..af7d371 --- /dev/null +++ b/backend/node_modules/redis-parser/.npmignore @@ -0,0 +1,15 @@ +# IntelliJ project files +.idea +*.iml +out +gen + +# Unrelevant files and folders +benchmark +coverage +test +.travis.yml +.gitignore +*.log +.vscode +.codeclimate.yml \ No newline at end of file diff --git a/backend/node_modules/redis-parser/LICENSE b/backend/node_modules/redis-parser/LICENSE new file mode 100644 index 0000000..39d23f8 --- /dev/null +++ b/backend/node_modules/redis-parser/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 NodeRedis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/backend/node_modules/redis-parser/README.md b/backend/node_modules/redis-parser/README.md new file mode 100644 index 0000000..1d9c27d --- /dev/null +++ b/backend/node_modules/redis-parser/README.md @@ -0,0 +1,166 @@ +[![Build Status](https://travis-ci.org/NodeRedis/node-redis-parser.png?branch=master)](https://travis-ci.org/NodeRedis/node-redis-parser) +[![Test Coverage](https://codeclimate.com/github/NodeRedis/node-redis-parser/badges/coverage.svg)](https://codeclimate.com/github/NodeRedis/node-redis-parser/coverage) +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) + +# redis-parser + +A high performance javascript redis parser built for [node_redis](https://github.com/NodeRedis/node_redis) and [ioredis](https://github.com/luin/ioredis). Parses all [RESP](http://redis.io/topics/protocol) data. + +## Install + +Install with [NPM](https://npmjs.org/): + + npm install redis-parser + +## Usage + +```js +const Parser = require('redis-parser'); + +const myParser = new Parser(options); +``` + +### Options + +* `returnReply`: *function*; mandatory +* `returnError`: *function*; mandatory +* `returnFatalError`: *function*; optional, defaults to the returnError function +* `returnBuffers`: *boolean*; optional, defaults to false +* `stringNumbers`: *boolean*; optional, defaults to false + +### Functions + +* `reset()`: reset the parser to it's initial state +* `setReturnBuffers(boolean)`: set the returnBuffers option on/off without resetting the parser +* `setStringNumbers(boolean)`: set the stringNumbers option on/off without resetting the parser + +### Error classes + +* `RedisError` sub class of Error +* `ReplyError` sub class of RedisError +* `ParserError` sub class of RedisError + +All Redis errors will be returned as `ReplyErrors` while a parser error is returned as `ParserError`. +All error classes can be imported by the npm `redis-errors` package. + +### Example + +```js +const Parser = require("redis-parser"); + +class Library { + returnReply(reply) { /* ... */ } + returnError(err) { /* ... */ } + returnFatalError(err) { /* ... */ } + + streamHandler() { + this.stream.on('data', (buffer) => { + // Here the data (e.g. `Buffer.from('$5\r\nHello\r\n'`)) + // is passed to the parser and the result is passed to + // either function depending on the provided data. + parser.execute(buffer); + }); + } +} + +const lib = new Library(); + +const parser = new Parser({ + returnReply(reply) { + lib.returnReply(reply); + }, + returnError(err) { + lib.returnError(err); + }, + returnFatalError(err) { + lib.returnFatalError(err); + } +}); +``` + +You do not have to use the returnFatalError function. Fatal errors will be returned in the normal error function in that case. + +And if you want to return buffers instead of strings, you can do this by adding the `returnBuffers` option. + +If you handle with big numbers that are to large for JS (Number.MAX_SAFE_INTEGER === 2^53 - 16) please use the `stringNumbers` option. That way all numbers are going to be returned as String and you can handle them safely. + +```js +// Same functions as in the first example + +const parser = new Parser({ + returnReply(reply) { + lib.returnReply(reply); + }, + returnError(err) { + lib.returnError(err); + }, + returnBuffers: true, // All strings are returned as Buffer e.g. + stringNumbers: true // All numbers are returned as String +}); + +// The streamHandler as above +``` + +## Protocol errors + +To handle protocol errors (this is very unlikely to happen) gracefully you should add the returnFatalError option, reject any still running command (they might have been processed properly but the reply is just wrong), destroy the socket and reconnect. Note that while doing this no new command may be added, so all new commands have to be buffered in the meantime, otherwise a chunk might still contain partial data of a following command that was already processed properly but answered in the same chunk as the command that resulted in the protocol error. + +## Contribute + +The parser is highly optimized but there may still be further optimizations possible. + + npm install + npm test + npm run benchmark + +Currently the benchmark compares the performance against the hiredis parser: + + HIREDIS: $ multiple chunks in a bulk string x 994,387 ops/sec ±0.22% (554 runs sampled) + JS PARSER: $ multiple chunks in a bulk string x 1,010,728 ops/sec ±0.28% (559 runs sampled) + HIREDIS BUF: $ multiple chunks in a bulk string x 648,742 ops/sec ±0.80% (526 runs sampled) + JS PARSER BUF: $ multiple chunks in a bulk string x 1,728,849 ops/sec ±0.41% (555 runs sampled) + + HIREDIS: + multiple chunks in a string x 1,861,132 ops/sec ±0.18% (564 runs sampled) + JS PARSER: + multiple chunks in a string x 2,131,892 ops/sec ±0.31% (558 runs sampled) + HIREDIS BUF: + multiple chunks in a string x 965,132 ops/sec ±0.58% (521 runs sampled) + JS PARSER BUF: + multiple chunks in a string x 2,304,482 ops/sec ±0.31% (559 runs sampled) + + HIREDIS: $ 4mb bulk string x 269 ops/sec ±0.56% (452 runs sampled) + JS PARSER: $ 4mb bulk string x 763 ops/sec ±0.25% (466 runs sampled) + HIREDIS BUF: $ 4mb bulk string x 336 ops/sec ±0.59% (459 runs sampled) + JS PARSER BUF: $ 4mb bulk string x 994 ops/sec ±0.36% (482 runs sampled) + + HIREDIS: + simple string x 2,504,305 ops/sec ±0.19% (563 runs sampled) + JS PARSER: + simple string x 5,121,952 ops/sec ±0.30% (560 runs sampled) + HIREDIS BUF: + simple string x 1,122,899 ops/sec ±0.52% (516 runs sampled) + JS PARSER BUF: + simple string x 5,907,323 ops/sec ±0.23% (562 runs sampled) + + HIREDIS: : integer x 2,461,376 ops/sec ±0.14% (561 runs sampled) + JS PARSER: : integer x 18,543,688 ops/sec ±0.19% (539 runs sampled) + JS PARSER STR: : integer x 14,149,305 ops/sec ±0.24% (561 runs sampled) + + HIREDIS: : big integer x 2,114,270 ops/sec ±0.15% (561 runs sampled) + JS PARSER: : big integer x 10,794,439 ops/sec ±0.25% (560 runs sampled) + JS PARSER STR: : big integer x 4,594,807 ops/sec ±0.24% (558 runs sampled) + + HIREDIS: * array x 45,597 ops/sec ±0.23% (565 runs sampled) + JS PARSER: * array x 68,396 ops/sec ±0.30% (563 runs sampled) + HIREDIS BUF: * array x 14,726 ops/sec ±0.39% (498 runs sampled) + JS PARSER BUF: * array x 80,961 ops/sec ±0.25% (561 runs sampled) + + HIREDIS: * big nested array x 212 ops/sec ±0.17% (511 runs sampled) + JS PARSER: * big nested array x 243 ops/sec ±0.21% (496 runs sampled) + HIREDIS BUF: * big nested array x 207 ops/sec ±0.37% (430 runs sampled) + JS PARSER BUF: * big nested array x 297 ops/sec ±1.10% (421 runs sampled) + + HIREDIS: - error x 168,761 ops/sec ±0.28% (559 runs sampled) + JS PARSER: - error x 424,257 ops/sec ±0.28% (557 runs sampled) + + Platform info: + Ubuntu 17.04 + Node.js 7.10.0 + Intel(R) Core(TM) i7-5600U CPU + +## License + +[MIT](./LICENSE) diff --git a/backend/node_modules/redis-parser/changelog.md b/backend/node_modules/redis-parser/changelog.md new file mode 100644 index 0000000..551b9b5 --- /dev/null +++ b/backend/node_modules/redis-parser/changelog.md @@ -0,0 +1,156 @@ +# Changelog + +## v.3.0.0 - 25 May, 2017 + +Breaking Changes + +- Drop support for Node.js < 4 +- Removed support for hiredis completely + +Internals + +- Due to the changes to ES6 the error performance improved by factor 2-3x +- Improved length calculation performance (bulk strings + arrays) + +Features + +- The parser now handles weird input graceful + +## v.2.6.0 - 03 Apr, 2017 + +Internals + +- Use Buffer.allocUnsafe instead of new Buffer() with modern Node.js versions + +## v.2.5.0 - 11 Mar, 2017 + +Features + +- Added a `ParserError` class to differentiate them to ReplyErrors. The class is also exported + +Bugfixes + +- All errors now show their error message again next to the error name in the stack trace +- ParserErrors now show the offset and buffer attributes while being logged + +## v.2.4.1 - 05 Feb, 2017 + +Bugfixes + +- Fixed minimal memory consumption overhead for chunked buffers + +## v.2.4.0 - 25 Jan, 2017 + +Features + +- Added `reset` function to reset the parser to it's initial values +- Added `setReturnBuffers` function to reset the returnBuffers option (Only for the JSParser) +- Added `setStringNumbers` function to reset the stringNumbers option (Only for the JSParser) +- All Errors are now of sub classes of the new `RedisError` class. It is also exported. +- Improved bulk string chunked data handling performance + +Bugfixes + +- Parsing time for big nested arrays is now linear + +## v.2.3.0 - 25 Nov, 2016 + +Features + +- Parsing time for big arrays (e.g. 4mb+) is now linear and works well for arbitrary array sizes + +This case is a magnitude faster than before + + OLD STR: * big array x 1.09 ops/sec ±2.15% (7 runs sampled) + OLD BUF: * big array x 1.23 ops/sec ±2.67% (8 runs sampled) + + NEW STR: * big array x 273 ops/sec ±2.09% (85 runs sampled) + NEW BUF: * big array x 259 ops/sec ±1.32% (85 runs sampled) + (~10mb array with 1000 entries) + +## v.2.2.0 - 18 Nov, 2016 + +Features + +- Improve `stringNumbers` parsing performance by up to 100% + +Bugfixes + +- Do not unref the interval anymore due to issues with NodeJS + +## v.2.1.1 - 31 Oct, 2016 + +Bugfixes + +- Remove erroneously added const to support Node.js 0.10 + +## v.2.1.0 - 30 Oct, 2016 + +Features + +- Improve parser errors by adding more detailed information to them +- Accept manipulated Object.prototypes +- Unref the interval if used + +## v.2.0.4 - 21 Jul, 2016 + +Bugfixes + +- Fixed multi byte characters getting corrupted + +## v.2.0.3 - 17 Jun, 2016 + +Bugfixes + +- Fixed parser not working with huge buffers (e.g. 300 MB) + +## v.2.0.2 - 08 Jun, 2016 + +Bugfixes + +- Fixed parser with returnBuffers option returning corrupted data + +## v.2.0.1 - 04 Jun, 2016 + +Bugfixes + +- Fixed multiple parsers working concurrently resulting in faulty data in some cases + +## v.2.0.0 - 29 May, 2016 + +The javascript parser got completely rewritten by [Michael Diarmid](https://github.com/Salakar) and [Ruben Bridgewater](https://github.com/BridgeAR) and is now a lot faster than the hiredis parser. +Therefore the hiredis parser was deprecated and should only be used for testing purposes and benchmarking comparison. + +All Errors returned by the parser are from now on of class ReplyError + +Features + +- Improved performance by up to 15x as fast as before +- Improved options validation +- Added ReplyError Class +- Added parser benchmark +- Switched default parser from hiredis to JS, no matter if hiredis is installed or not + +Removed + +- Deprecated hiredis support + +## v.1.3.0 - 27 Mar, 2016 + +Features + +- Added `auto` as parser name option to check what parser is available +- Non existing requested parsers falls back into auto mode instead of always choosing the JS parser + +## v.1.2.0 - 27 Mar, 2016 + +Features + +- Added `stringNumbers` option to make sure all numbers are returned as string instead of a js number for precision +- The parser is from now on going to print warnings if a parser is explicitly requested that does not exist and gracefully chooses the JS parser + +## v.1.1.0 - 26 Jan, 2016 + +Features + +- The parser is from now on going to reset itself on protocol errors diff --git a/backend/node_modules/redis-parser/index.js b/backend/node_modules/redis-parser/index.js new file mode 100644 index 0000000..f5de376 --- /dev/null +++ b/backend/node_modules/redis-parser/index.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = require('./lib/parser') diff --git a/backend/node_modules/redis-parser/lib/parser.js b/backend/node_modules/redis-parser/lib/parser.js new file mode 100644 index 0000000..5d2532a --- /dev/null +++ b/backend/node_modules/redis-parser/lib/parser.js @@ -0,0 +1,552 @@ +'use strict' + +const Buffer = require('buffer').Buffer +const StringDecoder = require('string_decoder').StringDecoder +const decoder = new StringDecoder() +const errors = require('redis-errors') +const ReplyError = errors.ReplyError +const ParserError = errors.ParserError +var bufferPool = Buffer.allocUnsafe(32 * 1024) +var bufferOffset = 0 +var interval = null +var counter = 0 +var notDecreased = 0 + +/** + * Used for integer numbers only + * @param {JavascriptRedisParser} parser + * @returns {undefined|number} + */ +function parseSimpleNumbers (parser) { + const length = parser.buffer.length - 1 + var offset = parser.offset + var number = 0 + var sign = 1 + + if (parser.buffer[offset] === 45) { + sign = -1 + offset++ + } + + while (offset < length) { + const c1 = parser.buffer[offset++] + if (c1 === 13) { // \r\n + parser.offset = offset + 1 + return sign * number + } + number = (number * 10) + (c1 - 48) + } +} + +/** + * Used for integer numbers in case of the returnNumbers option + * + * Reading the string as parts of n SMI is more efficient than + * using a string directly. + * + * @param {JavascriptRedisParser} parser + * @returns {undefined|string} + */ +function parseStringNumbers (parser) { + const length = parser.buffer.length - 1 + var offset = parser.offset + var number = 0 + var res = '' + + if (parser.buffer[offset] === 45) { + res += '-' + offset++ + } + + while (offset < length) { + var c1 = parser.buffer[offset++] + if (c1 === 13) { // \r\n + parser.offset = offset + 1 + if (number !== 0) { + res += number + } + return res + } else if (number > 429496728) { + res += (number * 10) + (c1 - 48) + number = 0 + } else if (c1 === 48 && number === 0) { + res += 0 + } else { + number = (number * 10) + (c1 - 48) + } + } +} + +/** + * Parse a '+' redis simple string response but forward the offsets + * onto convertBufferRange to generate a string. + * @param {JavascriptRedisParser} parser + * @returns {undefined|string|Buffer} + */ +function parseSimpleString (parser) { + const start = parser.offset + const buffer = parser.buffer + const length = buffer.length - 1 + var offset = start + + while (offset < length) { + if (buffer[offset++] === 13) { // \r\n + parser.offset = offset + 1 + if (parser.optionReturnBuffers === true) { + return parser.buffer.slice(start, offset - 1) + } + return parser.buffer.toString('utf8', start, offset - 1) + } + } +} + +/** + * Returns the read length + * @param {JavascriptRedisParser} parser + * @returns {undefined|number} + */ +function parseLength (parser) { + const length = parser.buffer.length - 1 + var offset = parser.offset + var number = 0 + + while (offset < length) { + const c1 = parser.buffer[offset++] + if (c1 === 13) { + parser.offset = offset + 1 + return number + } + number = (number * 10) + (c1 - 48) + } +} + +/** + * Parse a ':' redis integer response + * + * If stringNumbers is activated the parser always returns numbers as string + * This is important for big numbers (number > Math.pow(2, 53)) as js numbers + * are 64bit floating point numbers with reduced precision + * + * @param {JavascriptRedisParser} parser + * @returns {undefined|number|string} + */ +function parseInteger (parser) { + if (parser.optionStringNumbers === true) { + return parseStringNumbers(parser) + } + return parseSimpleNumbers(parser) +} + +/** + * Parse a '$' redis bulk string response + * @param {JavascriptRedisParser} parser + * @returns {undefined|null|string} + */ +function parseBulkString (parser) { + const length = parseLength(parser) + if (length === undefined) { + return + } + if (length < 0) { + return null + } + const offset = parser.offset + length + if (offset + 2 > parser.buffer.length) { + parser.bigStrSize = offset + 2 + parser.totalChunkSize = parser.buffer.length + parser.bufferCache.push(parser.buffer) + return + } + const start = parser.offset + parser.offset = offset + 2 + if (parser.optionReturnBuffers === true) { + return parser.buffer.slice(start, offset) + } + return parser.buffer.toString('utf8', start, offset) +} + +/** + * Parse a '-' redis error response + * @param {JavascriptRedisParser} parser + * @returns {ReplyError} + */ +function parseError (parser) { + var string = parseSimpleString(parser) + if (string !== undefined) { + if (parser.optionReturnBuffers === true) { + string = string.toString() + } + return new ReplyError(string) + } +} + +/** + * Parsing error handler, resets parser buffer + * @param {JavascriptRedisParser} parser + * @param {number} type + * @returns {undefined} + */ +function handleError (parser, type) { + const err = new ParserError( + 'Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte', + JSON.stringify(parser.buffer), + parser.offset + ) + parser.buffer = null + parser.returnFatalError(err) +} + +/** + * Parse a '*' redis array response + * @param {JavascriptRedisParser} parser + * @returns {undefined|null|any[]} + */ +function parseArray (parser) { + const length = parseLength(parser) + if (length === undefined) { + return + } + if (length < 0) { + return null + } + const responses = new Array(length) + return parseArrayElements(parser, responses, 0) +} + +/** + * Push a partly parsed array to the stack + * + * @param {JavascriptRedisParser} parser + * @param {any[]} array + * @param {number} pos + * @returns {undefined} + */ +function pushArrayCache (parser, array, pos) { + parser.arrayCache.push(array) + parser.arrayPos.push(pos) +} + +/** + * Parse chunked redis array response + * @param {JavascriptRedisParser} parser + * @returns {undefined|any[]} + */ +function parseArrayChunks (parser) { + const tmp = parser.arrayCache.pop() + var pos = parser.arrayPos.pop() + if (parser.arrayCache.length) { + const res = parseArrayChunks(parser) + if (res === undefined) { + pushArrayCache(parser, tmp, pos) + return + } + tmp[pos++] = res + } + return parseArrayElements(parser, tmp, pos) +} + +/** + * Parse redis array response elements + * @param {JavascriptRedisParser} parser + * @param {Array} responses + * @param {number} i + * @returns {undefined|null|any[]} + */ +function parseArrayElements (parser, responses, i) { + const bufferLength = parser.buffer.length + while (i < responses.length) { + const offset = parser.offset + if (parser.offset >= bufferLength) { + pushArrayCache(parser, responses, i) + return + } + const response = parseType(parser, parser.buffer[parser.offset++]) + if (response === undefined) { + if (!(parser.arrayCache.length || parser.bufferCache.length)) { + parser.offset = offset + } + pushArrayCache(parser, responses, i) + return + } + responses[i] = response + i++ + } + + return responses +} + +/** + * Called the appropriate parser for the specified type. + * + * 36: $ + * 43: + + * 42: * + * 58: : + * 45: - + * + * @param {JavascriptRedisParser} parser + * @param {number} type + * @returns {*} + */ +function parseType (parser, type) { + switch (type) { + case 36: + return parseBulkString(parser) + case 43: + return parseSimpleString(parser) + case 42: + return parseArray(parser) + case 58: + return parseInteger(parser) + case 45: + return parseError(parser) + default: + return handleError(parser, type) + } +} + +/** + * Decrease the bufferPool size over time + * + * Balance between increasing and decreasing the bufferPool. + * Decrease the bufferPool by 10% by removing the first 10% of the current pool. + * @returns {undefined} + */ +function decreaseBufferPool () { + if (bufferPool.length > 50 * 1024) { + if (counter === 1 || notDecreased > counter * 2) { + const minSliceLen = Math.floor(bufferPool.length / 10) + const sliceLength = minSliceLen < bufferOffset + ? bufferOffset + : minSliceLen + bufferOffset = 0 + bufferPool = bufferPool.slice(sliceLength, bufferPool.length) + } else { + notDecreased++ + counter-- + } + } else { + clearInterval(interval) + counter = 0 + notDecreased = 0 + interval = null + } +} + +/** + * Check if the requested size fits in the current bufferPool. + * If it does not, reset and increase the bufferPool accordingly. + * + * @param {number} length + * @returns {undefined} + */ +function resizeBuffer (length) { + if (bufferPool.length < length + bufferOffset) { + const multiplier = length > 1024 * 1024 * 75 ? 2 : 3 + if (bufferOffset > 1024 * 1024 * 111) { + bufferOffset = 1024 * 1024 * 50 + } + bufferPool = Buffer.allocUnsafe(length * multiplier + bufferOffset) + bufferOffset = 0 + counter++ + if (interval === null) { + interval = setInterval(decreaseBufferPool, 50) + } + } +} + +/** + * Concat a bulk string containing multiple chunks + * + * Notes: + * 1) The first chunk might contain the whole bulk string including the \r + * 2) We are only safe to fully add up elements that are neither the first nor any of the last two elements + * + * @param {JavascriptRedisParser} parser + * @returns {String} + */ +function concatBulkString (parser) { + const list = parser.bufferCache + const oldOffset = parser.offset + var chunks = list.length + var offset = parser.bigStrSize - parser.totalChunkSize + parser.offset = offset + if (offset <= 2) { + if (chunks === 2) { + return list[0].toString('utf8', oldOffset, list[0].length + offset - 2) + } + chunks-- + offset = list[list.length - 2].length + offset + } + var res = decoder.write(list[0].slice(oldOffset)) + for (var i = 1; i < chunks - 1; i++) { + res += decoder.write(list[i]) + } + res += decoder.end(list[i].slice(0, offset - 2)) + return res +} + +/** + * Concat the collected chunks from parser.bufferCache. + * + * Increases the bufferPool size beforehand if necessary. + * + * @param {JavascriptRedisParser} parser + * @returns {Buffer} + */ +function concatBulkBuffer (parser) { + const list = parser.bufferCache + const oldOffset = parser.offset + const length = parser.bigStrSize - oldOffset - 2 + var chunks = list.length + var offset = parser.bigStrSize - parser.totalChunkSize + parser.offset = offset + if (offset <= 2) { + if (chunks === 2) { + return list[0].slice(oldOffset, list[0].length + offset - 2) + } + chunks-- + offset = list[list.length - 2].length + offset + } + resizeBuffer(length) + const start = bufferOffset + list[0].copy(bufferPool, start, oldOffset, list[0].length) + bufferOffset += list[0].length - oldOffset + for (var i = 1; i < chunks - 1; i++) { + list[i].copy(bufferPool, bufferOffset) + bufferOffset += list[i].length + } + list[i].copy(bufferPool, bufferOffset, 0, offset - 2) + bufferOffset += offset - 2 + return bufferPool.slice(start, bufferOffset) +} + +class JavascriptRedisParser { + /** + * Javascript Redis Parser constructor + * @param {{returnError: Function, returnReply: Function, returnFatalError?: Function, returnBuffers: boolean, stringNumbers: boolean }} options + * @constructor + */ + constructor (options) { + if (!options) { + throw new TypeError('Options are mandatory.') + } + if (typeof options.returnError !== 'function' || typeof options.returnReply !== 'function') { + throw new TypeError('The returnReply and returnError options have to be functions.') + } + this.setReturnBuffers(!!options.returnBuffers) + this.setStringNumbers(!!options.stringNumbers) + this.returnError = options.returnError + this.returnFatalError = options.returnFatalError || options.returnError + this.returnReply = options.returnReply + this.reset() + } + + /** + * Reset the parser values to the initial state + * + * @returns {undefined} + */ + reset () { + this.offset = 0 + this.buffer = null + this.bigStrSize = 0 + this.totalChunkSize = 0 + this.bufferCache = [] + this.arrayCache = [] + this.arrayPos = [] + } + + /** + * Set the returnBuffers option + * + * @param {boolean} returnBuffers + * @returns {undefined} + */ + setReturnBuffers (returnBuffers) { + if (typeof returnBuffers !== 'boolean') { + throw new TypeError('The returnBuffers argument has to be a boolean') + } + this.optionReturnBuffers = returnBuffers + } + + /** + * Set the stringNumbers option + * + * @param {boolean} stringNumbers + * @returns {undefined} + */ + setStringNumbers (stringNumbers) { + if (typeof stringNumbers !== 'boolean') { + throw new TypeError('The stringNumbers argument has to be a boolean') + } + this.optionStringNumbers = stringNumbers + } + + /** + * Parse the redis buffer + * @param {Buffer} buffer + * @returns {undefined} + */ + execute (buffer) { + if (this.buffer === null) { + this.buffer = buffer + this.offset = 0 + } else if (this.bigStrSize === 0) { + const oldLength = this.buffer.length + const remainingLength = oldLength - this.offset + const newBuffer = Buffer.allocUnsafe(remainingLength + buffer.length) + this.buffer.copy(newBuffer, 0, this.offset, oldLength) + buffer.copy(newBuffer, remainingLength, 0, buffer.length) + this.buffer = newBuffer + this.offset = 0 + if (this.arrayCache.length) { + const arr = parseArrayChunks(this) + if (arr === undefined) { + return + } + this.returnReply(arr) + } + } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) { + this.bufferCache.push(buffer) + var tmp = this.optionReturnBuffers ? concatBulkBuffer(this) : concatBulkString(this) + this.bigStrSize = 0 + this.bufferCache = [] + this.buffer = buffer + if (this.arrayCache.length) { + this.arrayCache[0][this.arrayPos[0]++] = tmp + tmp = parseArrayChunks(this) + if (tmp === undefined) { + return + } + } + this.returnReply(tmp) + } else { + this.bufferCache.push(buffer) + this.totalChunkSize += buffer.length + return + } + + while (this.offset < this.buffer.length) { + const offset = this.offset + const type = this.buffer[this.offset++] + const response = parseType(this, type) + if (response === undefined) { + if (!(this.arrayCache.length || this.bufferCache.length)) { + this.offset = offset + } + return + } + + if (type === 45) { + this.returnError(response) + } else { + this.returnReply(response) + } + } + + this.buffer = null + } +} + +module.exports = JavascriptRedisParser diff --git a/backend/node_modules/redis-parser/package.json b/backend/node_modules/redis-parser/package.json new file mode 100644 index 0000000..0c3287b --- /dev/null +++ b/backend/node_modules/redis-parser/package.json @@ -0,0 +1,53 @@ +{ + "name": "redis-parser", + "version": "3.0.0", + "description": "Javascript Redis protocol (RESP) parser", + "main": "index.js", + "scripts": { + "test": "npm run coverage", + "benchmark": "node ./benchmark", + "lint": "standard --fix", + "posttest": "npm run lint && npm run coverage:check", + "coverage": "node ./node_modules/istanbul/lib/cli.js cover --preserve-comments ./node_modules/mocha/bin/_mocha -- -R spec", + "coverage:check": "node ./node_modules/istanbul/lib/cli.js check-coverage --branch 100 --statement 100" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/NodeRedis/node-redis-parser.git" + }, + "keywords": [ + "redis", + "protocol", + "parser", + "database", + "javascript", + "node", + "nodejs", + "resp", + "hiredis" + ], + "engines": { + "node": ">=4" + }, + "dependencies": { + "redis-errors": "^1.0.0" + }, + "devDependencies": { + "benchmark": "^2.1.0", + "codeclimate-test-reporter": "^0.4.0", + "hiredis": "^0.5.0", + "istanbul": "^0.4.0", + "mocha": "^3.1.2", + "standard": "^10.0.0" + }, + "author": "Ruben Bridgewater", + "license": "MIT", + "bugs": { + "url": "https://github.com/NodeRedis/node-redis-parser/issues" + }, + "homepage": "https://github.com/NodeRedis/node-redis-parser#readme", + "directories": { + "test": "test", + "lib": "lib" + } +} diff --git a/backend/node_modules/standard-as-callback/LICENSE b/backend/node_modules/standard-as-callback/LICENSE new file mode 100644 index 0000000..d1c994e --- /dev/null +++ b/backend/node_modules/standard-as-callback/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018 Zihua Li +Copyright (c) 2013-2017 Petka Antonov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/backend/node_modules/standard-as-callback/README.md b/backend/node_modules/standard-as-callback/README.md new file mode 100644 index 0000000..4b52cd0 --- /dev/null +++ b/backend/node_modules/standard-as-callback/README.md @@ -0,0 +1,33 @@ +# Standard asCallback +A performant and standard (Bluebird) library that registers a node-style callback on a promise. + +[![Build Status](https://travis-ci.org/luin/asCallback.svg?branch=master)](https://travis-ci.org/luin/asCallback) + +## Install + +``` +$ npm install standard-as-callback +``` + +## Usage + +```javascript +const asCallback = require('standard-as-callback') + +const promise = new Promise(function (resolve) { + setTimeout(function () { + resolve('hello world!') + }, 1000) +}) + +asCallback(promise, function callback (err, res) { + console.log(err, res) // null, 'hello world!' +}) +``` + +## Thanks + +Most code of this library are ported from the awesome Bluebird library. + +## License +The MIT License. diff --git a/backend/node_modules/standard-as-callback/built/index.d.ts b/backend/node_modules/standard-as-callback/built/index.d.ts new file mode 100644 index 0000000..0d7e11f --- /dev/null +++ b/backend/node_modules/standard-as-callback/built/index.d.ts @@ -0,0 +1,5 @@ +import { CallbackFunction } from "./types"; +export interface IOptions { + spread: boolean; +} +export default function asCallback(promise: Promise, nodeback: CallbackFunction, options?: IOptions): Promise; diff --git a/backend/node_modules/standard-as-callback/built/index.js b/backend/node_modules/standard-as-callback/built/index.js new file mode 100644 index 0000000..7f4db27 --- /dev/null +++ b/backend/node_modules/standard-as-callback/built/index.js @@ -0,0 +1,41 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const utils_1 = require("./utils"); +function throwLater(e) { + setTimeout(function () { + throw e; + }, 0); +} +function asCallback(promise, nodeback, options) { + if (typeof nodeback === "function") { + promise.then((val) => { + let ret; + if (options !== undefined && + Object(options).spread && + Array.isArray(val)) { + ret = utils_1.tryCatch(nodeback).apply(undefined, [null].concat(val)); + } + else { + ret = + val === undefined + ? utils_1.tryCatch(nodeback)(null) + : utils_1.tryCatch(nodeback)(null, val); + } + if (ret === utils_1.errorObj) { + throwLater(ret.e); + } + }, (cause) => { + if (!cause) { + const newReason = new Error(cause + ""); + Object.assign(newReason, { cause }); + cause = newReason; + } + const ret = utils_1.tryCatch(nodeback)(cause); + if (ret === utils_1.errorObj) { + throwLater(ret.e); + } + }); + } + return promise; +} +exports.default = asCallback; diff --git a/backend/node_modules/standard-as-callback/built/types.d.ts b/backend/node_modules/standard-as-callback/built/types.d.ts new file mode 100644 index 0000000..94eaede --- /dev/null +++ b/backend/node_modules/standard-as-callback/built/types.d.ts @@ -0,0 +1 @@ +export declare type CallbackFunction = ((err: null, val: T) => void) | ((err: Error) => void); diff --git a/backend/node_modules/standard-as-callback/built/types.js b/backend/node_modules/standard-as-callback/built/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/backend/node_modules/standard-as-callback/built/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/backend/node_modules/standard-as-callback/built/utils.d.ts b/backend/node_modules/standard-as-callback/built/utils.d.ts new file mode 100644 index 0000000..b3fac29 --- /dev/null +++ b/backend/node_modules/standard-as-callback/built/utils.d.ts @@ -0,0 +1,9 @@ +import { CallbackFunction } from "./types"; +export declare const errorObj: { + e: {}; +}; +declare function tryCatcher(err: Error, val?: T): void | { + e: Error; +}; +export declare function tryCatch(fn: CallbackFunction): typeof tryCatcher; +export {}; diff --git a/backend/node_modules/standard-as-callback/built/utils.js b/backend/node_modules/standard-as-callback/built/utils.js new file mode 100644 index 0000000..328c31e --- /dev/null +++ b/backend/node_modules/standard-as-callback/built/utils.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tryCatch = exports.errorObj = void 0; +//Try catch is not supported in optimizing +//compiler, so it is isolated +exports.errorObj = { e: {} }; +let tryCatchTarget; +function tryCatcher(err, val) { + try { + const target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } + catch (e) { + exports.errorObj.e = e; + return exports.errorObj; + } +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; +} +exports.tryCatch = tryCatch; diff --git a/backend/node_modules/standard-as-callback/package.json b/backend/node_modules/standard-as-callback/package.json new file mode 100644 index 0000000..7a71978 --- /dev/null +++ b/backend/node_modules/standard-as-callback/package.json @@ -0,0 +1,40 @@ +{ + "name": "standard-as-callback", + "version": "2.1.0", + "description": "A performant and standard (Bluebird) library that registers a node-style callback on a promise", + "main": "built/index.js", + "types": "built/index.d.ts", + "directories": { + "lib": "built" + }, + "files": [ + "built/" + ], + "scripts": { + "build": "rm -rf built && tsc", + "test": "npm run build && mocha", + "prepublishOnly": "npm test" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/luin/asCallback.git" + }, + "keywords": [ + "ascallback", + "nodeify", + "promise", + "bluebird" + ], + "author": "luin ", + "license": "MIT", + "bugs": { + "url": "https://github.com/luin/asCallback/issues" + }, + "homepage": "https://github.com/luin/asCallback#readme", + "devDependencies": { + "mocha": "^8.3.2", + "promise-timeout": "^1.3.0", + "sinon": "^9.2.4", + "typescript": "^4.2.3" + } +} diff --git a/backend/package-lock.json b/backend/package-lock.json index bab6fbf..deefdd3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -13,13 +13,21 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "ioredis": "^5.10.1", "jsonwebtoken": "^9.0.2", + "node-cron": "^4.2.1", "pg": "^8.12.0" }, "devDependencies": { "nodemon": "^3.1.4" } }, + "node_modules/@ioredis/commands": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.1.tgz", + "integrity": "sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw==", + "license": "MIT" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -254,6 +262,15 @@ "fsevents": "~2.3.2" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -337,6 +354,15 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -813,6 +839,53 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ioredis": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.10.1.tgz", + "integrity": "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "1.5.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ioredis/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -917,12 +990,24 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", "license": "MIT" }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", @@ -1059,6 +1144,15 @@ "node": ">= 0.6" } }, + "node_modules/node-cron": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.2.1.tgz", + "integrity": "sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==", + "license": "ISC", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "3.1.14", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", @@ -1393,6 +1487,27 @@ "node": ">=8.10.0" } }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1576,6 +1691,12 @@ "node": ">= 10.x" } }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", diff --git a/backend/package.json b/backend/package.json index 3901269..c95704f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,16 +4,18 @@ "main": "server.js", "scripts": { "start": "node server.js", - "dev": "nodemon server.js" + "dev": "nodemon server.js" }, "dependencies": { - "axios": "^1.7.2", - "bcryptjs": "^2.4.3", - "cors": "^2.8.5", - "dotenv": "^16.4.5", - "express": "^4.19.2", + "axios": "^1.7.2", + "bcryptjs": "^2.4.3", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "ioredis": "^5.10.1", "jsonwebtoken": "^9.0.2", - "pg": "^8.12.0" + "node-cron": "^4.2.1", + "pg": "^8.12.0" }, "devDependencies": { "nodemon": "^3.1.4" diff --git a/backend/server.js b/backend/server.js index 7055371..2af9d56 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,7 +1,24 @@ require('dotenv').config(); -const app = require('./src/app'); +const app = require('./src/app'); +const redis = require('./src/config/redis'); +const { registrarGpsJob } = require('./src/jobs/gps.job'); + const PORT = process.env.PORT || 3000; -app.listen(PORT, () => { - console.log(`🚀 Servidor corriendo en http://localhost:${PORT}`); -}); +async function iniciar() { + // Conectar Redis + await redis.connect(); + + // Levantar servidor Express + app.listen(PORT, () => { + console.log(`🚀 Servidor corriendo en http://localhost:${PORT}`); + }); + + // Registrar Cron Job del simulador GPS + registrarGpsJob(); +} + +iniciar().catch((err) => { + console.error('❌ Error al iniciar el servidor:', err.message); + process.exit(1); +}); \ No newline at end of file diff --git a/backend/src/config/redis.js b/backend/src/config/redis.js new file mode 100644 index 0000000..c9c7390 --- /dev/null +++ b/backend/src/config/redis.js @@ -0,0 +1,12 @@ +const Redis = require('ioredis'); + +const redis = new Redis({ + host: process.env.REDIS_HOST || 'localhost', + port: parseInt(process.env.REDIS_PORT || '6380'), + lazyConnect: true, +}); + +redis.on('connect', () => console.log('✅ Redis conectado')); +redis.on('error', (err) => console.error('❌ Redis error:', err.message)); + +module.exports = redis; diff --git a/backend/src/jobs/gps.job.js b/backend/src/jobs/gps.job.js new file mode 100644 index 0000000..df42096 --- /dev/null +++ b/backend/src/jobs/gps.job.js @@ -0,0 +1,29 @@ +/** + * ================================================================ + * GPS JOB - Cron Job del simulador + * + * Se registra al iniciar el servidor y corre automáticamente. + * Por defecto cada 1 minuto. Combinado con TIME_MULTIPLIER=60 + * en el .env, 1 minuto real = 1 hora simulada, suficiente para + * ver el camión avanzar durante una demo en vivo. + * ================================================================ + */ + +const cron = require('node-cron'); +const { ejecutarSimulacion } = require('../services/simulator.service'); + +function registrarGpsJob() { + // '*/1 * * * *' = cada 1 minuto + // Cambiar a '*/30 * * * * *' para cada 30 segundos (si el paquete lo soporta) + const SCHEDULE = process.env.CRON_SCHEDULE || '*/1 * * * *'; + + const job = cron.schedule(SCHEDULE, async () => { + console.log(`\n⏱️ [${new Date().toLocaleTimeString()}] Ejecutando simulador GPS...`); + await ejecutarSimulacion(); + }); + + console.log(`✅ Simulador GPS registrado (schedule: "${SCHEDULE}", x${process.env.TIME_MULTIPLIER || 60} velocidad)`); + return job; +} + +module.exports = { registrarGpsJob }; diff --git a/backend/src/services/simulator.service.js b/backend/src/services/simulator.service.js new file mode 100644 index 0000000..124673d --- /dev/null +++ b/backend/src/services/simulator.service.js @@ -0,0 +1,179 @@ +/** + * ================================================================ + * SIMULADOR GPS - Lógica central + * + * Cada vez que el Cron Job llama a `ejecutarSimulacion()`: + * 1. Obtiene todas las rutas activas con sus posiciones + * 2. Calcula en qué positionId debería estar cada camión + * según la hora actual y los offset_seg del JSON + * 3. Actualiza estado_ruta en la BD + * 4. Si cruzó un umbral de notificación (positionId 2, 4 u 8) + * publica un evento en Redis para que P2 lo consuma + * ================================================================ + */ + +const pool = require('../config/db'); +const redis = require('../config/redis'); + +// positionIds que disparan notificación push (del notificaciones.json) +const TRIGGERS = new Set([2, 4, 8]); + +// Multiplicador de tiempo para demo: +// 1 = tiempo real (el camión tarda horas) +// 60 = 1 minuto real = 1 hora simulada (recomendado para demo) +// 120 = aún más rápido +const TIME_MULTIPLIER = parseInt(process.env.TIME_MULTIPLIER || '60'); + +/** + * Convierte un TIME de Postgres ("06:30:00") a segundos desde medianoche + */ +function timeToSegundos(timeStr) { + const [h, m, s = 0] = timeStr.split(':').map(Number); + return h * 3600 + m * 60 + s; +} + +/** + * Calcula cuántos segundos simulados han pasado desde que la ruta debió iniciar hoy + */ +function segundosTranscurridos(horaInicioStr) { + const ahora = new Date(); + const segAhora = ahora.getHours() * 3600 + ahora.getMinutes() * 60 + ahora.getSeconds(); + const segInicio = timeToSegundos(horaInicioStr); + const segReales = segAhora - segInicio; + return segReales * TIME_MULTIPLIER; +} + +/** + * Dado los segundos transcurridos y las posiciones de la ruta, + * devuelve la posición actual (la última cuyo offset_seg ya fue alcanzado) + */ +function calcularPosicionActual(posiciones, segTranscurridos) { + // posiciones ordenadas por position_id ASC + const ordenadas = [...posiciones].sort((a, b) => a.position_id - b.position_id); + + let actual = ordenadas[0]; // posición 1 por defecto + + for (const pos of ordenadas) { + if (segTranscurridos >= pos.offset_seg) { + actual = pos; + } else { + break; + } + } + + return actual; +} + +/** + * Publica un evento en Redis para que P2 (FCM service) lo consuma + */ +async function publicarTrigger(ruta, posicion) { + const eventos = { + 2: 'ROUTE_START', + 4: 'TRUCK_PROXIMITY', + 8: 'ROUTE_COMPLETED', + }; + + const evento = { + trigger_event: eventos[posicion.position_id], + routeId: ruta.route_id, + ruta_id: ruta.id, + position_id: posicion.position_id, + lat: posicion.lat, + lng: posicion.lng, + timestamp: new Date().toISOString(), + }; + + // Canal: 'notificaciones:trigger' — P2 se suscribe a este canal + await redis.publish('notificaciones:trigger', JSON.stringify(evento)); + console.log(` 📡 Trigger publicado: ${evento.trigger_event} para ${ruta.route_id}`); +} + +/** + * Función principal del simulador — llamada por el Cron Job + */ +async function ejecutarSimulacion() { + const client = await pool.connect(); + + try { + // ── 1. Obtener rutas activas con sus posiciones ──────────── + const { rows: rutas } = await client.query( + `SELECT r.id, r.route_id, r.hora_inicio, + e.estado, e.position_id_actual + FROM rutas r + JOIN estado_ruta e ON e.ruta_id = r.id + WHERE r.activa = TRUE` + ); + + for (const ruta of rutas) { + const segTrans = segundosTranscurridos(ruta.hora_inicio); + + // Ruta que no ha iniciado aún + if (segTrans < 0) { + if (ruta.estado !== 'INACTIVA') { + await client.query( + `UPDATE estado_ruta SET estado = 'INACTIVA', position_id_actual = 1, + actualizado_at = NOW() WHERE ruta_id = $1`, + [ruta.id] + ); + } + continue; + } + + // ── 2. Obtener posiciones de esta ruta ───────────────── + const { rows: posiciones } = await client.query( + `SELECT position_id, lat, lng, offset_seg + FROM ruta_posiciones + WHERE ruta_id = $1 + ORDER BY position_id ASC`, + [ruta.id] + ); + + if (posiciones.length === 0) continue; + + const posActual = calcularPosicionActual(posiciones, segTrans); + const posIdAnterior = ruta.position_id_actual; + const posIdActual = posActual.position_id; + const ultimaPosId = posiciones[posiciones.length - 1].position_id; + + // Estado según posición + const nuevoEstado = posIdActual >= ultimaPosId ? 'FINALIZADA' : 'EN_RUTA'; + + // ── 3. Calcular ETA estimado de fin ──────────────────── + const ultimaPos = posiciones[posiciones.length - 1]; + const segRestantes = Math.max(0, (ultimaPos.offset_seg - segTrans) / TIME_MULTIPLIER); + const horaEstimFin = new Date(Date.now() + segRestantes * 1000); + + // ── 4. Actualizar estado_ruta ────────────────────────── + await client.query( + `UPDATE estado_ruta + SET estado = $1, + position_id_actual = $2, + lat_actual = $3, + lng_actual = $4, + hora_estim_fin = $5, + actualizado_at = NOW() + WHERE ruta_id = $6`, + [nuevoEstado, posIdActual, posActual.lat, posActual.lng, + horaEstimFin.toISOString(), ruta.id] + ); + + console.log( + ` 🚛 ${ruta.route_id} → pos ${posIdActual}/${ultimaPosId} ` + + `[${nuevoEstado}] (${Math.round(segTrans / 60)} min simulados)` + ); + + // ── 5. Disparar trigger si cruzamos un umbral ────────── + if (TRIGGERS.has(posIdActual) && posIdActual !== posIdAnterior) { + await publicarTrigger(ruta, posActual); + } + } + + } catch (err) { + console.error('❌ Error en simulación:', err.message); + } finally { + client.release(); + } +} + +module.exports = { ejecutarSimulacion };