@andersondacampo/volt-cli
Version:
CLI for Volt.js ⚡ type-safe client generation
1 lines • 1.21 MB
Source Map (JSON)
{"version":3,"sources":["../src/lib/spinner.ts","../src/adapters/logger.ts","../../../node_modules/@ioredis/commands/built/commands.json","../../../node_modules/@ioredis/commands/built/index.js","../../../node_modules/standard-as-callback/built/utils.js","../../../node_modules/standard-as-callback/built/index.js","../../../node_modules/redis-errors/lib/old.js","../../../node_modules/redis-errors/lib/modern.js","../../../node_modules/redis-errors/index.js","../../../node_modules/cluster-key-slot/lib/index.js","../../../node_modules/lodash.defaults/index.js","../../../node_modules/lodash.isarguments/index.js","../../../node_modules/ioredis/built/utils/lodash.js","../../../node_modules/ms/index.js","../../../node_modules/debug/src/common.js","../../../node_modules/debug/src/browser.js","../../../node_modules/has-flag/index.js","../../../node_modules/supports-color/index.js","../../../node_modules/debug/src/node.js","../../../node_modules/debug/src/index.js","../../../node_modules/ioredis/built/utils/debug.js","../../../node_modules/ioredis/built/constants/TLSProfiles.js","../../../node_modules/ioredis/built/utils/index.js","../../../node_modules/ioredis/built/Command.js","../../../node_modules/ioredis/built/errors/ClusterAllFailedError.js","../../../node_modules/ioredis/built/ScanStream.js","../../../node_modules/ioredis/built/autoPipelining.js","../../../node_modules/ioredis/built/Script.js","../../../node_modules/ioredis/built/utils/Commander.js","../../../node_modules/ioredis/built/Pipeline.js","../../../node_modules/ioredis/built/transaction.js","../../../node_modules/ioredis/built/utils/applyMixin.js","../../../node_modules/ioredis/built/cluster/ClusterOptions.js","../../../node_modules/ioredis/built/cluster/util.js","../../../node_modules/ioredis/built/cluster/ClusterSubscriber.js","../../../node_modules/ioredis/built/cluster/ConnectionPool.js","../../../node_modules/denque/index.js","../../../node_modules/ioredis/built/cluster/DelayQueue.js","../../../node_modules/ioredis/built/cluster/ClusterSubscriberGroup.js","../../../node_modules/ioredis/built/cluster/index.js","../../../node_modules/ioredis/built/connectors/AbstractConnector.js","../../../node_modules/ioredis/built/connectors/StandaloneConnector.js","../../../node_modules/ioredis/built/connectors/SentinelConnector/SentinelIterator.js","../../../node_modules/ioredis/built/connectors/SentinelConnector/FailoverDetector.js","../../../node_modules/ioredis/built/connectors/SentinelConnector/index.js","../../../node_modules/ioredis/built/connectors/index.js","../../../node_modules/ioredis/built/errors/MaxRetriesPerRequestError.js","../../../node_modules/ioredis/built/errors/index.js","../../../node_modules/redis-parser/lib/parser.js","../../../node_modules/redis-parser/index.js","../../../node_modules/ioredis/built/SubscriptionSet.js","../../../node_modules/ioredis/built/DataHandler.js","../../../node_modules/ioredis/built/redis/event_handler.js","../../../node_modules/ioredis/built/redis/RedisOptions.js","../../../node_modules/ioredis/built/Redis.js","../../../node_modules/ioredis/built/index.js","../src/adapters/framework/concurrent-processes.ts","../../../node_modules/zod-to-json-schema/dist/esm/Options.js","../../../node_modules/zod-to-json-schema/dist/esm/Refs.js","../../../node_modules/zod-to-json-schema/dist/esm/errorMessages.js","../../../node_modules/zod-to-json-schema/dist/esm/getRelativePath.js","../../../node_modules/zod/v3/helpers/util.js","../../../node_modules/zod/v3/ZodError.js","../../../node_modules/zod/v3/locales/en.js","../../../node_modules/zod/v3/errors.js","../../../node_modules/zod/v3/helpers/parseUtil.js","../../../node_modules/zod/v3/helpers/typeAliases.js","../../../node_modules/zod/v3/helpers/errorUtil.js","../../../node_modules/zod/v3/types.js","../../../node_modules/zod/v3/external.js","../../../node_modules/zod/index.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/any.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/array.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/branded.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/catch.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/date.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/default.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/effects.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/enum.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/literal.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/string.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/record.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/map.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/never.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/null.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/union.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/number.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/object.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/optional.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/promise.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/set.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js","../../../node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js","../../../node_modules/zod-to-json-schema/dist/esm/selectParser.js","../../../node_modules/zod-to-json-schema/dist/esm/parseDef.js","../../../node_modules/zod-to-json-schema/dist/esm/parseTypes.js","../../../node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js","../../../node_modules/zod-to-json-schema/dist/esm/index.js","../src/adapters/build/introspector.ts","../src/adapters/build/generator.ts","../src/adapters/docs/openapi-generator.ts","../src/adapters/build/watcher.ts","../src/index.ts","../src/adapters/framework/framework-detector.ts","../src/adapters/framework/index.ts","../src/adapters/setup/init.setup.ts","../src/adapters/setup/prompts.ts","../src/adapters/setup/generator.ts","../src/adapters/setup/features.ts","../src/adapters/setup/templates.ts","../src/adapters/scaffold.ts","../src/adapters/scaffold/providers/prisma.ts"],"sourcesContent":["import chalk from 'chalk';\r\n\r\n// Browser detection - check for Node.js specific objects\r\nconst isBrowser = typeof process === 'undefined' || typeof process.versions === 'undefined' || typeof process.versions.node === 'undefined';\r\n\r\n// Dynamic import for yocto-spinner (only on server)\r\nlet yoctoSpinner: any = null;\r\nif (!isBrowser) {\r\n try {\r\n yoctoSpinner = require('yocto-spinner');\r\n } catch (error) {\r\n // Fallback if yocto-spinner is not available\r\n console.warn('yocto-spinner not available, using static spinner');\r\n }\r\n}\r\n\r\nexport class SpinnerManager {\r\n private readonly colorize: boolean;\r\n private readonly disableSpinner: boolean;\r\n private readonly indentLevel: number;\r\n private activeSpinners: Map<string, any> = new Map();\r\n\r\n constructor(options: { colorize: boolean; disableSpinner: boolean; indentLevel: number }) {\r\n this.colorize = options.colorize;\r\n this.disableSpinner = options.disableSpinner;\r\n this.indentLevel = options.indentLevel;\r\n }\r\n\r\n /**\r\n * Create a spinner with Volt.js styling\r\n * If disableSpinner is true or running in browser, uses static ANSI icons instead\r\n */\r\n createSpinner(text: string, id?: string): {\r\n start: () => any,\r\n success: (successText?: string) => void,\r\n error: (errorText?: string) => void,\r\n warn: (warnText?: string) => void,\r\n stop: (finalText?: string) => void,\r\n update: (newText: string) => void\r\n } {\r\n const spinnerId = id || Math.random().toString(36).substr(2, 9);\r\n\r\n // If spinners are disabled, in browser, or yocto-spinner not available, use static icons\r\n if (this.disableSpinner || isBrowser || !yoctoSpinner) {\r\n return this.createStaticSpinner(text, spinnerId);\r\n }\r\n\r\n return {\r\n start: () => {\r\n // Clear any existing spinner with the same ID\r\n const existingSpinner = this.activeSpinners.get(spinnerId);\r\n if (existingSpinner) {\r\n existingSpinner.stop();\r\n this.activeSpinners.delete(spinnerId);\r\n }\r\n\r\n const spinner = yoctoSpinner.default || yoctoSpinner;\r\n const spinnerInstance = spinner({\r\n text: this.colorize ? chalk.white(text) : text,\r\n color: 'cyan',\r\n spinner: {\r\n frames: ['◒', '◐', '◓', '◑'], // Volt.js spinner frames\r\n interval: 120\r\n }\r\n });\r\n\r\n this.activeSpinners.set(spinnerId, spinnerInstance);\r\n return spinnerInstance.start();\r\n },\r\n\r\n success: (successText?: string) => {\r\n const spinner = this.activeSpinners.get(spinnerId);\r\n if (spinner) {\r\n const finalText = successText || text;\r\n spinner.success(this.colorize ? chalk.green(finalText) : finalText);\r\n this.activeSpinners.delete(spinnerId);\r\n // Ensure clean line after spinner completion\r\n process.stdout.write('');\r\n }\r\n },\r\n\r\n error: (errorText?: string) => {\r\n const spinner = this.activeSpinners.get(spinnerId);\r\n if (spinner) {\r\n const finalText = errorText || text;\r\n spinner.error(this.colorize ? chalk.red(finalText) : finalText);\r\n this.activeSpinners.delete(spinnerId);\r\n // Ensure clean line after spinner completion\r\n process.stdout.write('');\r\n }\r\n },\r\n\r\n warn: (warnText?: string) => {\r\n const spinner = this.activeSpinners.get(spinnerId);\r\n if (spinner) {\r\n const finalText = warnText || text;\r\n spinner.warning(this.colorize ? chalk.yellow(finalText) : finalText);\r\n this.activeSpinners.delete(spinnerId);\r\n // Ensure clean line after spinner completion\r\n process.stdout.write('');\r\n }\r\n },\r\n\r\n stop: (finalText?: string) => {\r\n const spinner = this.activeSpinners.get(spinnerId);\r\n if (spinner) {\r\n if (finalText) {\r\n spinner.stop(finalText);\r\n } else {\r\n spinner.stop();\r\n }\r\n this.activeSpinners.delete(spinnerId);\r\n // Ensure clean line after spinner stop\r\n process.stdout.write('');\r\n }\r\n },\r\n\r\n update: (newText: string) => {\r\n const spinner = this.activeSpinners.get(spinnerId);\r\n if (spinner) {\r\n spinner.text = this.colorize ? chalk.white(newText) : newText;\r\n }\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Create a static spinner (no animation, just ANSI icons)\r\n * Perfect for multi-process environments to avoid terminal pollution\r\n */\r\n private createStaticSpinner(text: string, spinnerId: string): {\r\n start: () => any,\r\n success: (successText?: string) => void,\r\n error: (errorText?: string) => void,\r\n warn: (warnText?: string) => void,\r\n stop: (finalText?: string) => void,\r\n update: (newText: string) => void\r\n } {\r\n let currentText = text;\r\n let isActive = false;\r\n\r\n const connector = this.indentLevel > 0 ? '│ ' : '';\r\n\r\n return {\r\n start: () => {\r\n isActive = true;\r\n const line = this.colorize\r\n ? `${connector}${chalk.cyan('◐')} ${chalk.white(currentText)}`\r\n : `${connector}◐ ${currentText}`;\r\n console.log(line);\r\n return { stop: () => { } }; // Mock spinner interface\r\n },\r\n\r\n success: (successText?: string) => {\r\n if (isActive) {\r\n const finalText = successText || currentText;\r\n const line = this.colorize\r\n ? `${connector}${chalk.green('◆')} ${chalk.green(finalText)}`\r\n : `${connector}◆ ${finalText}`;\r\n console.log(line);\r\n isActive = false;\r\n }\r\n },\r\n\r\n error: (errorText?: string) => {\r\n if (isActive) {\r\n const finalText = errorText || currentText;\r\n const line = this.colorize\r\n ? `${connector}${chalk.red('◇')} ${chalk.red(finalText)}`\r\n : `${connector}◇ ${finalText}`;\r\n console.log(line);\r\n isActive = false;\r\n }\r\n },\r\n\r\n warn: (warnText?: string) => {\r\n if (isActive) {\r\n const finalText = warnText || currentText;\r\n const line = this.colorize\r\n ? `${connector}${chalk.yellow('◇')} ${chalk.yellow(finalText)}`\r\n : `${connector}◇ ${finalText}`;\r\n console.log(line);\r\n isActive = false;\r\n }\r\n },\r\n\r\n stop: (finalText?: string) => {\r\n if (isActive) {\r\n if (finalText) {\r\n const line = this.colorize\r\n ? `${connector}${chalk.gray('○')} ${chalk.gray(finalText)}`\r\n : `${connector}○ ${finalText}`;\r\n console.log(line);\r\n }\r\n isActive = false;\r\n }\r\n },\r\n\r\n update: (newText: string) => {\r\n currentText = newText;\r\n if (isActive) {\r\n const line = this.colorize\r\n ? `${connector}${chalk.cyan('◐')} ${chalk.white(newText)}`\r\n : `${connector}◐ ${newText}`;\r\n console.log(line);\r\n }\r\n }\r\n };\r\n }\r\n\r\n clearSpinners(): void {\r\n for (const [id, spinner] of this.activeSpinners) {\r\n spinner.stop();\r\n }\r\n this.activeSpinners.clear();\r\n }\r\n\r\n pauseSpinners(): void {\r\n for (const [id, spinner] of this.activeSpinners) {\r\n if (spinner && typeof spinner.stop === 'function') {\r\n spinner.stop();\r\n }\r\n }\r\n // Clear the line to ensure clean output\r\n process.stdout.write('\\r\\x1b[K');\r\n }\r\n\r\n resumeSpinners(): void {\r\n // Note: Due to yocto-spinner's design, we can't truly \"resume\" a stopped spinner\r\n // This method is kept for API compatibility but won't restart spinners\r\n // Users should handle spinner lifecycle manually for better control\r\n }\r\n}\r\n\r\n/**\r\n * Create a detached spinner (not tied to logger instance)\r\n * Browser-safe implementation\r\n */\r\nexport function createDetachedSpinner(text: string, options?: { color?: string }): {\r\n start: () => any,\r\n success: (successText?: string) => void,\r\n error: (errorText?: string) => void,\r\n warn: (warnText?: string) => void,\r\n stop: (finalText?: string) => void,\r\n update: (newText: string) => void\r\n} {\r\n let spinner: any = null;\r\n\r\n // Browser-safe fallback\r\n if (isBrowser || !yoctoSpinner) {\r\n return {\r\n start: () => {\r\n console.log(chalk.cyan('◐') + ' ' + chalk.white(text));\r\n return {};\r\n },\r\n success: (successText?: string) => {\r\n console.log(chalk.green('◆') + ' ' + chalk.green(successText || text));\r\n },\r\n error: (errorText?: string) => {\r\n console.log(chalk.red('◇') + ' ' + chalk.red(errorText || text));\r\n },\r\n warn: (warnText?: string) => {\r\n console.log(chalk.yellow('◇') + ' ' + chalk.yellow(warnText || text));\r\n },\r\n stop: (finalText?: string) => {\r\n if (finalText) {\r\n console.log(chalk.gray('○') + ' ' + chalk.gray(finalText));\r\n }\r\n },\r\n update: (newText: string) => {\r\n console.log(chalk.cyan('◐') + ' ' + chalk.white(newText));\r\n }\r\n };\r\n }\r\n\r\n return {\r\n start: () => {\r\n // Clear any existing spinner first\r\n if (spinner) {\r\n spinner.stop();\r\n spinner = null;\r\n }\r\n\r\n const spinnerFn = yoctoSpinner.default || yoctoSpinner;\r\n spinner = spinnerFn({\r\n text: chalk.white(text),\r\n color: options?.color || 'cyan',\r\n spinner: {\r\n frames: ['◒', '◐', '◓', '◑'], // Volt.js spinner frames\r\n interval: 120\r\n },\r\n });\r\n return spinner.start();\r\n },\r\n\r\n success: (successText?: string) => {\r\n if (spinner) {\r\n const finalText = successText || text;\r\n spinner.success(chalk.green(finalText));\r\n process.stdout.write(''); // Ensure clean line after completion\r\n spinner = null;\r\n }\r\n },\r\n\r\n error: (errorText?: string) => {\r\n if (spinner) {\r\n const finalText = errorText || text;\r\n spinner.error(chalk.red(finalText));\r\n process.stdout.write(''); // Ensure clean line after completion\r\n spinner = null;\r\n }\r\n },\r\n\r\n warn: (warnText?: string) => {\r\n if (spinner) {\r\n const finalText = warnText || text;\r\n spinner.warning(chalk.yellow(finalText));\r\n process.stdout.write(''); // Ensure clean line after completion\r\n spinner = null;\r\n }\r\n },\r\n\r\n stop: (finalText?: string) => {\r\n if (spinner) {\r\n if (finalText) {\r\n spinner.stop(finalText);\r\n } else {\r\n spinner.stop();\r\n }\r\n process.stdout.write('\\r\\x1b[K'); // Clear the line and ensure clean output\r\n spinner = null;\r\n }\r\n },\r\n\r\n update: (newText: string) => {\r\n if (spinner) {\r\n spinner.text = chalk.white(newText);\r\n }\r\n }\r\n };\r\n}","import { VoltLogLevel, createConsoleLogger } from '@volt-js/core';\r\n\r\n/**\r\n * Get the log level from environment variables\r\n * Supports DEBUG=true for debug level and LOG_LEVEL for explicit level\r\n */\r\nfunction getLogLevel(): VoltLogLevel {\r\n if (process.env.DEBUG === 'true') {\r\n return VoltLogLevel.DEBUG;\r\n }\r\n\r\n const envLevel = process.env.LOG_LEVEL?.toUpperCase();\r\n if (envLevel && envLevel in VoltLogLevel) {\r\n return VoltLogLevel[envLevel as keyof typeof VoltLogLevel];\r\n }\r\n\r\n return VoltLogLevel.INFO;\r\n}\r\n\r\n/**\r\n * Detect if we're running in concurrent mode (as a child process)\r\n * This helps us avoid spinner conflicts in concurrently\r\n */\r\nfunction isConcurrentMode(): boolean {\r\n return !!(\r\n process.env.FORCE_COLOR || // concurrently sets this\r\n process.env.npm_config_color ||\r\n process.argv.includes('--concurrent') ||\r\n process.title.includes('concurrently')\r\n );\r\n}\r\n\r\n/**\r\n * Detect if we're running in interactive mode\r\n * This helps us avoid spinner conflicts in interactive process switching\r\n */\r\nfunction isInteractiveMode(): boolean {\r\n return !!(\r\n process.argv.includes('--interactive') ||\r\n process.env.VOLT_INTERACTIVE_MODE === 'true'\r\n );\r\n}\r\n\r\n/**\r\n * Centralized logger instance for the CLI\r\n * Uses the ConsoleLogger adapter with CLI-specific configuration\r\n * Automatically disables spinners in concurrent/interactive mode\r\n */\r\nimport { SpinnerManager } from '../lib/spinner';\r\n\r\nexport const logger = createConsoleLogger({\r\n level: getLogLevel(),\r\n colorize: true,\r\n context: {\r\n concurrent: isConcurrentMode(),\r\n interactive: isInteractiveMode()\r\n }\r\n});\r\n\r\n// Initialize SpinnerManager with CLI-specific options\r\nconst cliSpinnerManager = new SpinnerManager({\r\n colorize: true,\r\n disableSpinner: isConcurrentMode() || isInteractiveMode(),\r\n indentLevel: 0 // CLI usually starts at indent level 0\r\n});\r\n\r\n// Override the logger's spinner method to use the CLI's SpinnerManager\r\n// This is a temporary measure until the core logger is refactored to remove spinner logic\r\n(logger as any).spinner = (text: string, id?: string) => cliSpinnerManager.createSpinner(text, id);\r\n\r\n/**\r\n * Creates a child logger with additional context\r\n * @param context Additional context to add to log entries\r\n * @param options Optional logger configuration overrides\r\n */\r\nexport function createChildLogger(\r\n context: Record<string, unknown>,\r\n options: { level?: VoltLogLevel; colorize?: boolean } = {}\r\n) {\r\n const childLogger = logger.child(context);\r\n\r\n // Ensure the child logger also has access to the spinner factory\r\n (childLogger as any).spinner = (text: string, id?: string) => cliSpinnerManager.createSpinner(text, id);\r\n\r\n if (options.level) {\r\n childLogger?.setLevel?.(options.level);\r\n }\r\n\r\n return childLogger;\r\n}\r\n\r\n/**\r\n * Reconfigures the CLI logger based on command-line options\r\n * @param options CLI options, e.g., { debug: true }\r\n */\r\nexport function setupCliLogger(options: { debug?: boolean }) {\r\n if (options.debug) {\r\n logger.setLevel(VoltLogLevel.DEBUG);\r\n logger.debug('Debug mode enabled.');\r\n }\r\n}\r\n\r\n\r\n\r\n/**\r\n * Helper to format error objects for logging\r\n * Extracts useful information from various error types\r\n */\r\nexport function formatError(error: unknown): Record<string, unknown> {\r\n if (error instanceof Error) {\r\n return {\r\n name: error.name,\r\n message: error.message,\r\n stack: error.stack,\r\n ...(error as any).code ? { code: (error as any).code } : {},\r\n ...(error as any).syscall ? { syscall: (error as any).syscall } : {},\r\n };\r\n }\r\n\r\n if (typeof error === 'string') {\r\n return { message: error };\r\n }\r\n\r\n return { error };\r\n}\r\n","{\n \"acl\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"append\": {\n \"arity\": 3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"asking\": {\n \"arity\": 1,\n \"flags\": [\n \"fast\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"auth\": {\n \"arity\": -2,\n \"flags\": [\n \"noscript\",\n \"loading\",\n \"stale\",\n \"fast\",\n \"no_auth\",\n \"allow_busy\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"bgrewriteaof\": {\n \"arity\": 1,\n \"flags\": [\n \"admin\",\n \"noscript\",\n \"no_async_loading\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"bgsave\": {\n \"arity\": -1,\n \"flags\": [\n \"admin\",\n \"noscript\",\n \"no_async_loading\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"bitcount\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"bitfield\": {\n \"arity\": -2,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"bitfield_ro\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"bitop\": {\n \"arity\": -4,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 2,\n \"keyStop\": -1,\n \"step\": 1\n },\n \"bitpos\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"blmove\": {\n \"arity\": 6,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"noscript\",\n \"blocking\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 2,\n \"step\": 1\n },\n \"blmpop\": {\n \"arity\": -5,\n \"flags\": [\n \"write\",\n \"blocking\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"blpop\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"noscript\",\n \"blocking\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -2,\n \"step\": 1\n },\n \"brpop\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"noscript\",\n \"blocking\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -2,\n \"step\": 1\n },\n \"brpoplpush\": {\n \"arity\": 4,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"noscript\",\n \"blocking\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 2,\n \"step\": 1\n },\n \"bzmpop\": {\n \"arity\": -5,\n \"flags\": [\n \"write\",\n \"blocking\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"bzpopmax\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"noscript\",\n \"blocking\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -2,\n \"step\": 1\n },\n \"bzpopmin\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"noscript\",\n \"blocking\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -2,\n \"step\": 1\n },\n \"client\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"cluster\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"command\": {\n \"arity\": -1,\n \"flags\": [\n \"loading\",\n \"stale\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"config\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"copy\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 2,\n \"step\": 1\n },\n \"dbsize\": {\n \"arity\": 1,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"debug\": {\n \"arity\": -2,\n \"flags\": [\n \"admin\",\n \"noscript\",\n \"loading\",\n \"stale\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"decr\": {\n \"arity\": 2,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"decrby\": {\n \"arity\": 3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"del\": {\n \"arity\": -2,\n \"flags\": [\n \"write\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -1,\n \"step\": 1\n },\n \"discard\": {\n \"arity\": 1,\n \"flags\": [\n \"noscript\",\n \"loading\",\n \"stale\",\n \"fast\",\n \"allow_busy\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"dump\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"echo\": {\n \"arity\": 2,\n \"flags\": [\n \"fast\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"eval\": {\n \"arity\": -3,\n \"flags\": [\n \"noscript\",\n \"stale\",\n \"skip_monitor\",\n \"no_mandatory_keys\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"eval_ro\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\",\n \"noscript\",\n \"stale\",\n \"skip_monitor\",\n \"no_mandatory_keys\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"evalsha\": {\n \"arity\": -3,\n \"flags\": [\n \"noscript\",\n \"stale\",\n \"skip_monitor\",\n \"no_mandatory_keys\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"evalsha_ro\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\",\n \"noscript\",\n \"stale\",\n \"skip_monitor\",\n \"no_mandatory_keys\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"exec\": {\n \"arity\": 1,\n \"flags\": [\n \"noscript\",\n \"loading\",\n \"stale\",\n \"skip_slowlog\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"exists\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -1,\n \"step\": 1\n },\n \"expire\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"expireat\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"expiretime\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"failover\": {\n \"arity\": -1,\n \"flags\": [\n \"admin\",\n \"noscript\",\n \"stale\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"fcall\": {\n \"arity\": -3,\n \"flags\": [\n \"noscript\",\n \"stale\",\n \"skip_monitor\",\n \"no_mandatory_keys\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"fcall_ro\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\",\n \"noscript\",\n \"stale\",\n \"skip_monitor\",\n \"no_mandatory_keys\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"flushall\": {\n \"arity\": -1,\n \"flags\": [\n \"write\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"flushdb\": {\n \"arity\": -1,\n \"flags\": [\n \"write\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"function\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"geoadd\": {\n \"arity\": -5,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"geodist\": {\n \"arity\": -4,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"geohash\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"geopos\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"georadius\": {\n \"arity\": -6,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"movablekeys\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"georadius_ro\": {\n \"arity\": -6,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"georadiusbymember\": {\n \"arity\": -5,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"movablekeys\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"georadiusbymember_ro\": {\n \"arity\": -5,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"geosearch\": {\n \"arity\": -7,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"geosearchstore\": {\n \"arity\": -8,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 2,\n \"step\": 1\n },\n \"get\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"getbit\": {\n \"arity\": 3,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"getdel\": {\n \"arity\": 2,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"getex\": {\n \"arity\": -2,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"getrange\": {\n \"arity\": 4,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"getset\": {\n \"arity\": 3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hdel\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hello\": {\n \"arity\": -1,\n \"flags\": [\n \"noscript\",\n \"loading\",\n \"stale\",\n \"fast\",\n \"no_auth\",\n \"allow_busy\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"hexists\": {\n \"arity\": 3,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hget\": {\n \"arity\": 3,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hgetall\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hincrby\": {\n \"arity\": 4,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hincrbyfloat\": {\n \"arity\": 4,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hkeys\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hlen\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hmget\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hmset\": {\n \"arity\": -4,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hrandfield\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hscan\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hset\": {\n \"arity\": -4,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hsetnx\": {\n \"arity\": 4,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hstrlen\": {\n \"arity\": 3,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"hvals\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"incr\": {\n \"arity\": 2,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"incrby\": {\n \"arity\": 3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"incrbyfloat\": {\n \"arity\": 3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"info\": {\n \"arity\": -1,\n \"flags\": [\n \"loading\",\n \"stale\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"keys\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"lastsave\": {\n \"arity\": 1,\n \"flags\": [\n \"loading\",\n \"stale\",\n \"fast\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"latency\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"lcs\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 2,\n \"step\": 1\n },\n \"lindex\": {\n \"arity\": 3,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"linsert\": {\n \"arity\": 5,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"llen\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"lmove\": {\n \"arity\": 5,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 2,\n \"step\": 1\n },\n \"lmpop\": {\n \"arity\": -4,\n \"flags\": [\n \"write\",\n \"movablekeys\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"lolwut\": {\n \"arity\": -1,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"lpop\": {\n \"arity\": -2,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"lpos\": {\n \"arity\": -3,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"lpush\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"lpushx\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"lrange\": {\n \"arity\": 4,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"lrem\": {\n \"arity\": 4,\n \"flags\": [\n \"write\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"lset\": {\n \"arity\": 4,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"ltrim\": {\n \"arity\": 4,\n \"flags\": [\n \"write\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"memory\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"mget\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -1,\n \"step\": 1\n },\n \"migrate\": {\n \"arity\": -6,\n \"flags\": [\n \"write\",\n \"movablekeys\"\n ],\n \"keyStart\": 3,\n \"keyStop\": 3,\n \"step\": 1\n },\n \"module\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"monitor\": {\n \"arity\": 1,\n \"flags\": [\n \"admin\",\n \"noscript\",\n \"loading\",\n \"stale\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"move\": {\n \"arity\": 3,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"mset\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -1,\n \"step\": 2\n },\n \"msetnx\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -1,\n \"step\": 2\n },\n \"multi\": {\n \"arity\": 1,\n \"flags\": [\n \"noscript\",\n \"loading\",\n \"stale\",\n \"fast\",\n \"allow_busy\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"object\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"persist\": {\n \"arity\": 2,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"pexpire\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"pexpireat\": {\n \"arity\": -3,\n \"flags\": [\n \"write\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"pexpiretime\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"pfadd\": {\n \"arity\": -2,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"pfcount\": {\n \"arity\": -2,\n \"flags\": [\n \"readonly\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -1,\n \"step\": 1\n },\n \"pfdebug\": {\n \"arity\": 3,\n \"flags\": [\n \"write\",\n \"denyoom\",\n \"admin\"\n ],\n \"keyStart\": 2,\n \"keyStop\": 2,\n \"step\": 1\n },\n \"pfmerge\": {\n \"arity\": -2,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": -1,\n \"step\": 1\n },\n \"pfselftest\": {\n \"arity\": 1,\n \"flags\": [\n \"admin\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"ping\": {\n \"arity\": -1,\n \"flags\": [\n \"fast\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"psetex\": {\n \"arity\": 4,\n \"flags\": [\n \"write\",\n \"denyoom\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"psubscribe\": {\n \"arity\": -2,\n \"flags\": [\n \"pubsub\",\n \"noscript\",\n \"loading\",\n \"stale\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"psync\": {\n \"arity\": -3,\n \"flags\": [\n \"admin\",\n \"noscript\",\n \"no_async_loading\",\n \"no_multi\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"pttl\": {\n \"arity\": 2,\n \"flags\": [\n \"readonly\",\n \"fast\"\n ],\n \"keyStart\": 1,\n \"keyStop\": 1,\n \"step\": 1\n },\n \"publish\": {\n \"arity\": 3,\n \"flags\": [\n \"pubsub\",\n \"loading\",\n \"stale\",\n \"fast\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"pubsub\": {\n \"arity\": -2,\n \"flags\": [],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"punsubscribe\": {\n \"arity\": -1,\n \"flags\": [\n \"pubsub\",\n \"noscript\",\n \"loading\",\n \"stale\"\n ],\n \"keyStart\": 0,\n \"keyStop\": 0,\n \"step\": 0\n },\n \"quit\": {\n \"arity\": -1,\n \"flags\": [\n \"noscript\",\n \"loading\",\n \"stale\",\n \"fast\"