index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. 'use strict'
  2. var commands = require('./commands.json')
  3. /**
  4. * Redis command list
  5. *
  6. * All commands are lowercased.
  7. *
  8. * @var {string[]}
  9. * @public
  10. */
  11. exports.list = Object.keys(commands)
  12. var flags = {}
  13. exports.list.forEach(function (commandName) {
  14. flags[commandName] = commands[commandName].flags.reduce(function (flags, flag) {
  15. flags[flag] = true
  16. return flags
  17. }, {})
  18. })
  19. /**
  20. * Check if the command exists
  21. *
  22. * @param {string} commandName - the command name
  23. * @return {boolean} result
  24. * @public
  25. */
  26. exports.exists = function (commandName) {
  27. return Boolean(commands[commandName])
  28. }
  29. /**
  30. * Check if the command has the flag
  31. *
  32. * Some of possible flags: readonly, noscript, loading
  33. * @param {string} commandName - the command name
  34. * @param {string} flag - the flag to check
  35. * @return {boolean} result
  36. * @public
  37. */
  38. exports.hasFlag = function (commandName, flag) {
  39. if (!flags[commandName]) {
  40. throw new Error('Unknown command ' + commandName)
  41. }
  42. return Boolean(flags[commandName][flag])
  43. }
  44. /**
  45. * Get indexes of keys in the command arguments
  46. *
  47. * @param {string} commandName - the command name
  48. * @param {string[]} args - the arguments of the command
  49. * @param {object} [options] - options
  50. * @param {boolean} [options.parseExternalKey] - parse external keys
  51. * @return {number[]} - the list of the index
  52. * @public
  53. *
  54. * @example
  55. * ```javascript
  56. * getKeyIndexes('set', ['key', 'value']) // [0]
  57. * getKeyIndexes('mget', ['key1', 'key2']) // [0, 1]
  58. * ```
  59. */
  60. exports.getKeyIndexes = function (commandName, args, options) {
  61. var command = commands[commandName]
  62. if (!command) {
  63. throw new Error('Unknown command ' + commandName)
  64. }
  65. if (!Array.isArray(args)) {
  66. throw new Error('Expect args to be an array')
  67. }
  68. var keys = []
  69. var i, keyStart, keyStop, parseExternalKey
  70. switch (commandName) {
  71. case 'zunionstore':
  72. case 'zinterstore':
  73. keys.push(0)
  74. // fall through
  75. case 'eval':
  76. case 'evalsha':
  77. keyStop = Number(args[1]) + 2
  78. for (i = 2; i < keyStop; i++) {
  79. keys.push(i)
  80. }
  81. break
  82. case 'sort':
  83. parseExternalKey = options && options.parseExternalKey
  84. keys.push(0)
  85. for (i = 1; i < args.length - 1; i++) {
  86. if (typeof args[i] !== 'string') {
  87. continue
  88. }
  89. var directive = args[i].toUpperCase()
  90. if (directive === 'GET') {
  91. i += 1
  92. if (args[i] !== '#') {
  93. if (parseExternalKey) {
  94. keys.push([i, getExternalKeyNameLength(args[i])])
  95. } else {
  96. keys.push(i)
  97. }
  98. }
  99. } else if (directive === 'BY') {
  100. i += 1
  101. if (parseExternalKey) {
  102. keys.push([i, getExternalKeyNameLength(args[i])])
  103. } else {
  104. keys.push(i)
  105. }
  106. } else if (directive === 'STORE') {
  107. i += 1
  108. keys.push(i)
  109. }
  110. }
  111. break
  112. case 'migrate':
  113. if (args[2] === '') {
  114. for (i = 5; i < args.length - 1; i++) {
  115. if (args[i].toUpperCase() === 'KEYS') {
  116. for (var j = i + 1; j < args.length; j++) {
  117. keys.push(j)
  118. }
  119. break
  120. }
  121. }
  122. } else {
  123. keys.push(2)
  124. }
  125. break
  126. default:
  127. // step has to be at least one in this case, otherwise the command does not contain a key
  128. if (command.step > 0) {
  129. keyStart = command.keyStart - 1
  130. keyStop = command.keyStop > 0 ? command.keyStop : args.length + command.keyStop + 1
  131. for (i = keyStart; i < keyStop; i += command.step) {
  132. keys.push(i)
  133. }
  134. }
  135. break
  136. }
  137. return keys
  138. }
  139. function getExternalKeyNameLength (key) {
  140. if (typeof key !== 'string') {
  141. key = String(key)
  142. }
  143. var hashPos = key.indexOf('->')
  144. return hashPos === -1 ? key.length : hashPos
  145. }