@valkey/valkey-glide 2.1.1 → 2.2.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
3
+ */
1
4
  import * as net from "net";
2
5
  import { Buffer, Writer } from "protobufjs/minimal";
3
6
  import { AggregationType, BaseScanOptions, BitFieldGet, // eslint-disable-line @typescript-eslint/no-unused-vars
@@ -109,8 +112,27 @@ export type ReturnTypeXinfoStream = Record<string, StreamEntries | Record<string
109
112
  * See {@link ReturnTypeXinfoStream}.
110
113
  */
111
114
  export type StreamEntries = GlideString | number | (GlideString | number | GlideString[])[][];
115
+ /** Represents the types of services that can be used for IAM authentication. */
116
+ export declare enum ServiceType {
117
+ Elasticache = "Elasticache",
118
+ MemoryDB = "MemoryDB"
119
+ }
120
+ /** Configuration settings for IAM authentication. */
121
+ export interface IamAuthConfig {
122
+ /** The name of the ElastiCache/MemoryDB cluster. */
123
+ clusterName: string;
124
+ /** The type of service being used (ElastiCache or MemoryDB). */
125
+ service: ServiceType;
126
+ /** The AWS region where the ElastiCache/MemoryDB cluster is located. */
127
+ region: string;
128
+ /**
129
+ * Optional refresh interval in seconds for renewing IAM authentication tokens.
130
+ * If not provided, defaults to 300 seconds (5 min).
131
+ */
132
+ refreshIntervalSeconds?: number;
133
+ }
112
134
  /** Represents the credentials for connecting to a server. */
113
- export interface ServerCredentials {
135
+ export type ServerCredentials = {
114
136
  /**
115
137
  * The username that will be used for authenticating connections to the Valkey servers.
116
138
  * If not supplied, "default" will be used.
@@ -118,9 +140,18 @@ export interface ServerCredentials {
118
140
  username?: string;
119
141
  /**
120
142
  * The password that will be used for authenticating connections to the Valkey servers.
143
+ * (mutually exclusive with iamConfig).
121
144
  */
122
145
  password: string;
123
- }
146
+ } | {
147
+ /** Username is REQUIRED for IAM (Valkey AUTH <username> <token>). */
148
+ username: string;
149
+ /**
150
+ * IAM config (mutually exclusive with password).
151
+ * The client will automatically generate and refresh the authentication token based on the provided configuration.
152
+ */
153
+ iamConfig: IamAuthConfig;
154
+ };
124
155
  /** Represents the client's read from strategy. */
125
156
  export type ReadFrom =
126
157
  /** Always get from primary, in order to get the freshest data.*/
@@ -450,6 +481,17 @@ export interface AdvancedBaseClientConfiguration {
450
481
  * - Default: false (verification is enforced).
451
482
  */
452
483
  insecure?: boolean;
484
+ /**
485
+ * Custom root certificate data for TLS connections.
486
+ *
487
+ * - When provided, these certificates will be used instead of the system's default trust store.
488
+ * If not provided, the system's default certificate trust store will be used.
489
+ *
490
+ * - The certificate data should be in PEM format as a string or Buffer.
491
+ *
492
+ * - This is useful when connecting to servers with self-signed certificates or custom certificate authorities.
493
+ */
494
+ rootCertificates?: string | Buffer;
453
495
  };
454
496
  }
455
497
  /**
@@ -502,6 +544,7 @@ export declare class BaseClient {
502
544
  private writeBufferedRequestsToSocket;
503
545
  protected ensureClientIsOpen(): void;
504
546
  protected createUpdateConnectionPasswordPromise(command: command_request.UpdateConnectionPassword): Promise<GlideString>;
547
+ protected createRefreshIamTokenPromise(command: command_request.RefreshIamToken): Promise<GlideString>;
505
548
  protected createScriptInvocationPromise<T = GlideString>(command: command_request.ScriptInvocation, options?: {
506
549
  keys?: GlideString[];
507
550
  args?: GlideString[];
@@ -6377,6 +6420,19 @@ export declare class BaseClient {
6377
6420
  * ```
6378
6421
  */
6379
6422
  updateConnectionPassword(password: string | null, immediateAuth?: boolean): Promise<GlideString>;
6423
+ /**
6424
+ * Manually refresh the IAM token for the current connection.
6425
+ *
6426
+ * This method is only available if the client was created with IAM authentication.
6427
+ * It triggers an immediate refresh of the IAM token and updates the connection.
6428
+ *
6429
+ * @throws ConfigurationError if the client is not using IAM authentication.
6430
+ * @example
6431
+ * ```typescript
6432
+ * await client.refreshToken();
6433
+ * ```
6434
+ */
6435
+ refreshIamToken(): Promise<GlideString>;
6380
6436
  /**
6381
6437
  * Return a statistics
6382
6438
  *
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ /**
3
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
4
+ */
2
5
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
6
  if (k2 === undefined) k2 = k;
4
7
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -36,13 +39,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
39
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
40
  };
38
41
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.BaseClient = exports.ObjectType = exports.Decoder = exports.ProtocolVersion = void 0;
42
+ exports.BaseClient = exports.ObjectType = exports.ServiceType = exports.Decoder = exports.ProtocolVersion = void 0;
40
43
  exports.convertGlideRecord = convertGlideRecord;
41
44
  exports.convertGlideRecordToRecord = convertGlideRecordToRecord;
42
45
  exports.isGlideRecord = isGlideRecord;
43
46
  exports.convertRecordToGlideRecord = convertRecordToGlideRecord;
44
47
  /**
45
- * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
48
+ * Note: 'eslint-disable-line @typescript-eslint/no-unused-vars' is used intentionally
49
+ * to suppress unused import errors for types referenced only in JSDoc.
46
50
  */
47
51
  const long_1 = __importDefault(require("long"));
48
52
  const net = __importStar(require("net"));
@@ -155,6 +159,12 @@ class PointerResponse {
155
159
  this.low = low;
156
160
  }
157
161
  }
162
+ /** Represents the types of services that can be used for IAM authentication. */
163
+ var ServiceType;
164
+ (function (ServiceType) {
165
+ ServiceType["Elasticache"] = "Elasticache";
166
+ ServiceType["MemoryDB"] = "MemoryDB";
167
+ })(ServiceType || (exports.ServiceType = ServiceType = {}));
158
168
  /**
159
169
  * Enum of Valkey data types
160
170
  * `STRING`
@@ -509,6 +519,19 @@ class BaseClient {
509
519
  });
510
520
  });
511
521
  }
522
+ createRefreshIamTokenPromise(command) {
523
+ this.ensureClientIsOpen();
524
+ return new Promise((resolve, reject) => {
525
+ const callbackIdx = this.getCallbackIndex();
526
+ this.promiseCallbackFunctions[callbackIdx] = [resolve, reject];
527
+ this.writeOrBufferRequest(new ProtobufMessage_1.command_request.CommandRequest({
528
+ callbackIdx,
529
+ refreshIamToken: command,
530
+ }), (message, writer) => {
531
+ ProtobufMessage_1.command_request.CommandRequest.encodeDelimited(message, writer);
532
+ });
533
+ });
534
+ }
512
535
  createScriptInvocationPromise(command, options = {}) {
513
536
  this.ensureClientIsOpen();
514
537
  return new Promise((resolve, reject) => {
@@ -6938,13 +6961,42 @@ class BaseClient {
6938
6961
  const readFrom = options.readFrom
6939
6962
  ? this.MAP_READ_FROM_STRATEGY[options.readFrom]
6940
6963
  : ProtobufMessage_1.connection_request.ReadFrom.Primary;
6941
- const authenticationInfo = options.credentials !== undefined &&
6942
- "password" in options.credentials
6943
- ? {
6944
- password: options.credentials.password,
6945
- username: options.credentials.username,
6964
+ const creds = options.credentials;
6965
+ // Build a protobuf AuthenticationInfo
6966
+ let authenticationInfo;
6967
+ if (creds) {
6968
+ if ("iamConfig" in creds) {
6969
+ if (!creds.username) {
6970
+ throw new _1.ConfigurationError("IAM authentication requires a username.");
6971
+ }
6972
+ const iamCredentials = ProtobufMessage_1.connection_request.IamCredentials.create({
6973
+ clusterName: creds.iamConfig.clusterName,
6974
+ region: creds.iamConfig.region,
6975
+ serviceType: creds.iamConfig.service === ServiceType.Elasticache
6976
+ ? ProtobufMessage_1.connection_request.ServiceType.ELASTICACHE
6977
+ : ProtobufMessage_1.connection_request.ServiceType.MEMORYDB,
6978
+ // leave undefined if not provided (optional field)
6979
+ refreshIntervalSeconds: creds.iamConfig.refreshIntervalSeconds,
6980
+ });
6981
+ authenticationInfo =
6982
+ ProtobufMessage_1.connection_request.AuthenticationInfo.create({
6983
+ username: creds.username, // REQUIRED for IAM
6984
+ iamCredentials,
6985
+ // do NOT set password in IAM mode
6986
+ });
6946
6987
  }
6947
- : undefined;
6988
+ else if ("password" in creds) {
6989
+ // Password branch
6990
+ authenticationInfo =
6991
+ ProtobufMessage_1.connection_request.AuthenticationInfo.create({
6992
+ username: creds.username ?? "", // optional
6993
+ password: creds.password ?? "", // empty means “no password”
6994
+ });
6995
+ }
6996
+ else {
6997
+ authenticationInfo = undefined;
6998
+ }
6999
+ }
6948
7000
  const protocol = options.protocol;
6949
7001
  // Validate that clientAz is set when using AZ affinity strategies
6950
7002
  if ((options.readFrom === "AZAffinity" ||
@@ -6978,12 +7030,21 @@ class BaseClient {
6978
7030
  options.connectionTimeout ??
6979
7031
  _1.DEFAULT_CONNECTION_TIMEOUT_IN_MILLISECONDS;
6980
7032
  // Apply TLS configuration if present
6981
- if (options.tlsAdvancedConfiguration?.insecure) {
6982
- if (request.tlsMode === ProtobufMessage_1.connection_request.TlsMode.SecureTls) {
7033
+ if (options.tlsAdvancedConfiguration) {
7034
+ // request.tlsMode is either SecureTls or InsecureTls here
7035
+ if (request.tlsMode === ProtobufMessage_1.connection_request.TlsMode.NoTls) {
7036
+ throw new _1.ConfigurationError("TLS advanced configuration cannot be set when useTLS is disabled.");
7037
+ }
7038
+ // If options.tlsAdvancedConfiguration.insecure is true then use InsecureTls mode
7039
+ if (options.tlsAdvancedConfiguration.insecure) {
6983
7040
  request.tlsMode = ProtobufMessage_1.connection_request.TlsMode.InsecureTls;
6984
7041
  }
6985
- else if (request.tlsMode === ProtobufMessage_1.connection_request.TlsMode.NoTls) {
6986
- throw new _1.ConfigurationError("InsecureTls cannot be enabled when useTLS is disabled.");
7042
+ if (options.tlsAdvancedConfiguration.rootCertificates) {
7043
+ const certData = typeof options.tlsAdvancedConfiguration.rootCertificates ===
7044
+ "string"
7045
+ ? Buffer.from(options.tlsAdvancedConfiguration.rootCertificates, "utf-8")
7046
+ : options.tlsAdvancedConfiguration.rootCertificates;
7047
+ request.rootCerts = [new Uint8Array(certData)];
6987
7048
  }
6988
7049
  }
6989
7050
  }
@@ -7025,8 +7086,10 @@ class BaseClient {
7025
7086
  */
7026
7087
  static async __createClientInternal(options, connectedSocket, constructor) {
7027
7088
  const connection = constructor(connectedSocket, options);
7089
+ const connectStart = Date.now();
7028
7090
  await connection.connectToServer(options);
7029
- _1.Logger.log("info", "Client lifetime", "connected to server");
7091
+ const connectTime = Date.now() - connectStart;
7092
+ _1.Logger.log("info", "Client lifetime", `connected to server in ${connectTime}ms`);
7030
7093
  return connection;
7031
7094
  }
7032
7095
  /**
@@ -7045,10 +7108,17 @@ class BaseClient {
7045
7108
  * @internal
7046
7109
  */
7047
7110
  static async createClientInternal(options, constructor) {
7111
+ const overallStart = Date.now();
7048
7112
  const path = await (0, _1.StartSocketConnection)();
7113
+ const socketStart = Date.now();
7049
7114
  const socket = await this.GetSocket(path);
7115
+ const socketTime = Date.now() - socketStart;
7116
+ _1.Logger.log("info", "Client lifetime", `socket connection established in ${socketTime}ms`);
7050
7117
  try {
7051
- return await this.__createClientInternal(options, socket, constructor);
7118
+ const client = await this.__createClientInternal(options, socket, constructor);
7119
+ const totalTime = Date.now() - overallStart;
7120
+ _1.Logger.log("info", "Client lifetime", `total client creation time: ${totalTime}ms`);
7121
+ return client;
7052
7122
  }
7053
7123
  catch (err) {
7054
7124
  // Ensure socket is closed
@@ -7077,6 +7147,12 @@ class BaseClient {
7077
7147
  * ```
7078
7148
  */
7079
7149
  async updateConnectionPassword(password, immediateAuth = false) {
7150
+ // If we’re on IAM, forbid password updates to avoid confusion.
7151
+ const creds = this.config?.credentials;
7152
+ const usingIam = !!creds && "iamConfig" in creds;
7153
+ if (usingIam) {
7154
+ throw new _1.ConfigurationError("updateConnectionPassword is not supported when IAM authentication is enabled.");
7155
+ }
7080
7156
  const updateConnectionPassword = ProtobufMessage_1.command_request.UpdateConnectionPassword.create({
7081
7157
  password,
7082
7158
  immediateAuth,
@@ -7093,6 +7169,27 @@ class BaseClient {
7093
7169
  }
7094
7170
  return response;
7095
7171
  }
7172
+ /**
7173
+ * Manually refresh the IAM token for the current connection.
7174
+ *
7175
+ * This method is only available if the client was created with IAM authentication.
7176
+ * It triggers an immediate refresh of the IAM token and updates the connection.
7177
+ *
7178
+ * @throws ConfigurationError if the client is not using IAM authentication.
7179
+ * @example
7180
+ * ```typescript
7181
+ * await client.refreshToken();
7182
+ * ```
7183
+ */
7184
+ async refreshIamToken() {
7185
+ if (!this.config?.credentials ||
7186
+ !("iamConfig" in this.config.credentials)) {
7187
+ throw new _1.ConfigurationError("refreshIamToken is only available when IAM authentication is enabled.");
7188
+ }
7189
+ const refresh = ProtobufMessage_1.command_request.RefreshIamToken.create({});
7190
+ const response = await this.createRefreshIamTokenPromise(refresh);
7191
+ return response; // "OK"
7192
+ }
7096
7193
  /**
7097
7194
  * Return a statistics
7098
7195
  *
@@ -1,6 +1,10 @@
1
1
  /**
2
2
  * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
3
3
  */
4
+ /**
5
+ * Note: 'eslint-disable-line @typescript-eslint/no-unused-vars' is used intentionally
6
+ * to suppress unused import errors for types referenced only in JSDoc.
7
+ */
4
8
  import { AggregationType, BaseScanOptions, BitFieldGet, // eslint-disable-line @typescript-eslint/no-unused-vars
5
9
  BitFieldSubCommands, // eslint-disable-line @typescript-eslint/no-unused-vars
6
10
  BitOffsetOptions, BitwiseOperation, Boundary, // eslint-disable-line @typescript-eslint/no-unused-vars
package/build-ts/Batch.js CHANGED
@@ -4,6 +4,10 @@
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Transaction = exports.ClusterTransaction = exports.ClusterBatch = exports.Batch = exports.BaseBatch = void 0;
7
+ /**
8
+ * Note: 'eslint-disable-line @typescript-eslint/no-unused-vars' is used intentionally
9
+ * to suppress unused import errors for types referenced only in JSDoc.
10
+ */
7
11
  const _1 = require(".");
8
12
  /**
9
13
  * Base class encompassing shared commands for both standalone and cluster mode implementations in a Batch.
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
3
3
  */
4
- import { GlideString, HashDataType, ObjectType, SingleNodeRoute } from ".";
4
+ import { GlideString, HashDataType, ObjectType } from "./BaseClient";
5
+ import { SingleNodeRoute } from "./GlideClusterClient";
5
6
  /**
6
7
  * @test
7
8
  */
@@ -227,15 +227,20 @@ exports.createXGroupSetid = createXGroupSetid;
227
227
  exports.createScriptExists = createScriptExists;
228
228
  exports.createScriptFlush = createScriptFlush;
229
229
  exports.createScriptKill = createScriptKill;
230
+ /**
231
+ * Note: 'eslint-disable-line @typescript-eslint/no-unused-vars' is used intentionally
232
+ * to suppress unused import errors for types referenced only in JSDoc.
233
+ */
230
234
  const long_1 = __importDefault(require("long"));
231
- const _1 = require(".");
235
+ const BaseClient_1 = require("./BaseClient");
236
+ const native_1 = require("../build-ts/native");
232
237
  const ProtobufMessage_1 = require("../build-ts/ProtobufMessage");
233
238
  var RequestType = ProtobufMessage_1.command_request.RequestType;
234
239
  function isLargeCommand(args) {
235
240
  let lenSum = 0;
236
241
  for (const arg of args) {
237
242
  lenSum += arg.length;
238
- if (lenSum >= _1.MAX_REQUEST_ARGS_LEN) {
243
+ if (lenSum >= native_1.MAX_REQUEST_ARGS_LEN) {
239
244
  return true;
240
245
  }
241
246
  }
@@ -278,7 +283,7 @@ function createCommand(requestType, args) {
278
283
  const argsBytes = toBuffersArray(args);
279
284
  if (isLargeCommand(args)) {
280
285
  // pass as a pointer
281
- const pointerArr = (0, _1.createLeakedStringVec)(argsBytes);
286
+ const pointerArr = (0, native_1.createLeakedStringVec)(argsBytes);
282
287
  const pointer = new long_1.default(pointerArr[0], pointerArr[1]);
283
288
  singleCommand.argsVecPointer = pointer;
284
289
  }
@@ -2100,7 +2105,7 @@ var FlushMode;
2100
2105
  */
2101
2106
  function convertKeysAndEntries(record) {
2102
2107
  if (!Array.isArray(record)) {
2103
- return (0, _1.convertRecordToGlideRecord)(record);
2108
+ return (0, BaseClient_1.convertRecordToGlideRecord)(record);
2104
2109
  }
2105
2110
  return record;
2106
2111
  }
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
3
3
  */
4
- import { AdvancedBaseClientConfiguration, BaseClient, BaseClientConfiguration, Batch, BatchOptions, DecoderOption, FlushMode, FunctionListOptions, FunctionListResponse, FunctionRestorePolicy, FunctionStatsFullResponse, GlideReturnType, GlideString, InfoOptions, LolwutOptions, PubSubMsg, ScanOptions } from ".";
4
+ import { AdvancedBaseClientConfiguration, BaseClient, BaseClientConfiguration, DecoderOption, GlideReturnType, GlideString, PubSubMsg } from "./BaseClient";
5
+ import { Batch } from "./Batch";
6
+ import { BatchOptions, FlushMode, FunctionListOptions, FunctionListResponse, FunctionRestorePolicy, FunctionStatsFullResponse, InfoOptions, LolwutOptions, ScanOptions } from "./Commands";
5
7
  export declare namespace GlideClientConfiguration {
6
8
  /**
7
9
  * Enum representing pubsub subscription modes.