js-redis-server 0.0.2 → 0.0.3

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.
Files changed (133) hide show
  1. package/README.md +1 -35
  2. package/dist/cluster.d.ts +7 -1
  3. package/dist/cluster.d.ts.map +1 -1
  4. package/dist/cluster.js +103 -7
  5. package/dist/cluster.js.map +1 -1
  6. package/dist/commands/cluster.d.ts +3 -0
  7. package/dist/commands/cluster.d.ts.map +1 -1
  8. package/dist/commands/cluster.js +63 -20
  9. package/dist/commands/cluster.js.map +1 -1
  10. package/dist/commands/command.js +27 -18
  11. package/dist/commands/command.js.map +1 -1
  12. package/dist/commands/config.d.ts +9 -0
  13. package/dist/commands/config.d.ts.map +1 -0
  14. package/dist/commands/config.js +142 -0
  15. package/dist/commands/config.js.map +1 -0
  16. package/dist/commands/connection.d.ts.map +1 -1
  17. package/dist/commands/connection.js +73 -9
  18. package/dist/commands/connection.js.map +1 -1
  19. package/dist/commands/hashes.d.ts.map +1 -1
  20. package/dist/commands/hashes.js +5 -7
  21. package/dist/commands/hashes.js.map +1 -1
  22. package/dist/commands/index.d.ts +5 -4
  23. package/dist/commands/index.d.ts.map +1 -1
  24. package/dist/commands/index.js +25 -4
  25. package/dist/commands/index.js.map +1 -1
  26. package/dist/commands/keys.d.ts +19 -0
  27. package/dist/commands/keys.d.ts.map +1 -1
  28. package/dist/commands/keys.js +112 -5
  29. package/dist/commands/keys.js.map +1 -1
  30. package/dist/commands/lists.d.ts +13 -0
  31. package/dist/commands/lists.d.ts.map +1 -1
  32. package/dist/commands/lists.js +140 -26
  33. package/dist/commands/lists.js.map +1 -1
  34. package/dist/commands/scripts.d.ts.map +1 -1
  35. package/dist/commands/scripts.js +9 -12
  36. package/dist/commands/scripts.js.map +1 -1
  37. package/dist/commands/sets.d.ts +1 -0
  38. package/dist/commands/sets.d.ts.map +1 -1
  39. package/dist/commands/sets.js +33 -8
  40. package/dist/commands/sets.js.map +1 -1
  41. package/dist/commands/streams.d.ts +63 -0
  42. package/dist/commands/streams.d.ts.map +1 -0
  43. package/dist/commands/streams.js +504 -0
  44. package/dist/commands/streams.js.map +1 -0
  45. package/dist/commands/strings.d.ts +5 -0
  46. package/dist/commands/strings.d.ts.map +1 -1
  47. package/dist/commands/strings.js +20 -2
  48. package/dist/commands/strings.js.map +1 -1
  49. package/dist/commands/zsets.d.ts +13 -3
  50. package/dist/commands/zsets.d.ts.map +1 -1
  51. package/dist/commands/zsets.js +174 -30
  52. package/dist/commands/zsets.js.map +1 -1
  53. package/dist/core/client-session.d.ts +114 -2
  54. package/dist/core/client-session.d.ts.map +1 -1
  55. package/dist/core/client-session.js +181 -12
  56. package/dist/core/client-session.js.map +1 -1
  57. package/dist/core/command-executor.d.ts +79 -0
  58. package/dist/core/command-executor.d.ts.map +1 -1
  59. package/dist/core/command-executor.js +130 -3
  60. package/dist/core/command-executor.js.map +1 -1
  61. package/dist/core/command-schema.d.ts +3 -0
  62. package/dist/core/command-schema.d.ts.map +1 -1
  63. package/dist/core/command-schema.js +2 -1
  64. package/dist/core/command-schema.js.map +1 -1
  65. package/dist/core/execution-policies/auth-policy.d.ts +10 -0
  66. package/dist/core/execution-policies/auth-policy.d.ts.map +1 -0
  67. package/dist/core/execution-policies/auth-policy.js +39 -0
  68. package/dist/core/execution-policies/auth-policy.js.map +1 -0
  69. package/dist/core/execution-policies/cluster-policy.d.ts.map +1 -1
  70. package/dist/core/execution-policies/cluster-policy.js +8 -2
  71. package/dist/core/execution-policies/cluster-policy.js.map +1 -1
  72. package/dist/core/execution-policies/index.d.ts +1 -0
  73. package/dist/core/execution-policies/index.d.ts.map +1 -1
  74. package/dist/core/execution-policies/index.js +3 -1
  75. package/dist/core/execution-policies/index.js.map +1 -1
  76. package/dist/core/execution-policies/transaction-policy.d.ts.map +1 -1
  77. package/dist/core/execution-policies/transaction-policy.js +0 -4
  78. package/dist/core/execution-policies/transaction-policy.js.map +1 -1
  79. package/dist/core/lua-runtime.d.ts +1 -1
  80. package/dist/core/lua-runtime.d.ts.map +1 -1
  81. package/dist/core/lua-runtime.js +26 -34
  82. package/dist/core/lua-runtime.js.map +1 -1
  83. package/dist/core/redis-context.d.ts +6 -1
  84. package/dist/core/redis-context.d.ts.map +1 -1
  85. package/dist/core/redis-context.js.map +1 -1
  86. package/dist/core/redis-error.d.ts +55 -1
  87. package/dist/core/redis-error.d.ts.map +1 -1
  88. package/dist/core/redis-error.js +105 -3
  89. package/dist/core/redis-error.js.map +1 -1
  90. package/dist/core/redis-value.d.ts +4 -0
  91. package/dist/core/redis-value.d.ts.map +1 -1
  92. package/dist/core/redis-value.js +4 -0
  93. package/dist/core/redis-value.js.map +1 -1
  94. package/dist/core/resp-encoder.js +5 -0
  95. package/dist/core/resp-encoder.js.map +1 -1
  96. package/dist/core/transports/resp2/decoder.d.ts +5 -1
  97. package/dist/core/transports/resp2/decoder.d.ts.map +1 -1
  98. package/dist/core/transports/resp2/decoder.js +20 -8
  99. package/dist/core/transports/resp2/decoder.js.map +1 -1
  100. package/dist/core/transports/resp2/server.d.ts +3 -1
  101. package/dist/core/transports/resp2/server.d.ts.map +1 -1
  102. package/dist/core/transports/resp2/server.js +3 -0
  103. package/dist/core/transports/resp2/server.js.map +1 -1
  104. package/dist/core/transports/resp2/session-adapter.d.ts.map +1 -1
  105. package/dist/core/transports/resp2/session-adapter.js +8 -1
  106. package/dist/core/transports/resp2/session-adapter.js.map +1 -1
  107. package/dist/index.d.ts +3 -3
  108. package/dist/index.d.ts.map +1 -1
  109. package/dist/index.js +19 -3
  110. package/dist/index.js.map +1 -1
  111. package/dist/state/cluster-topology.d.ts +6 -0
  112. package/dist/state/cluster-topology.d.ts.map +1 -1
  113. package/dist/state/cluster-topology.js +21 -0
  114. package/dist/state/cluster-topology.js.map +1 -1
  115. package/dist/state/data-types.d.ts +11 -0
  116. package/dist/state/data-types.d.ts.map +1 -1
  117. package/dist/state/data-types.js +12 -1
  118. package/dist/state/data-types.js.map +1 -1
  119. package/dist/state/database.d.ts +3 -1
  120. package/dist/state/database.d.ts.map +1 -1
  121. package/dist/state/database.js +6 -0
  122. package/dist/state/database.js.map +1 -1
  123. package/dist/state/keyspace.d.ts.map +1 -1
  124. package/dist/state/keyspace.js +1 -0
  125. package/dist/state/keyspace.js.map +1 -1
  126. package/dist/state/mutation-events.d.ts +1 -0
  127. package/dist/state/mutation-events.d.ts.map +1 -1
  128. package/dist/state/mutation-events.js.map +1 -1
  129. package/dist/state/server-state.d.ts +7 -0
  130. package/dist/state/server-state.d.ts.map +1 -1
  131. package/dist/state/server-state.js +2 -0
  132. package/dist/state/server-state.js.map +1 -1
  133. package/package.json +5 -5
@@ -4,56 +4,168 @@ import { type ClientSessionMode, type ParkHandler, type RedisClientSession, type
4
4
  import { RedisResult } from './redis-result';
5
5
  import type { RespVersion } from './resp-encoder';
6
6
  import { type RedisTurnHandle, type RedisTurnQueue } from './turn-queue';
7
- import type { RedisDatabase, RedisServerState } from '../state';
7
+ import type { RedisClusterNodeRole, RedisDatabase, RedisServerState } from '../state';
8
8
  export type ClientSessionOptions = {
9
9
  id?: string;
10
10
  server: RedisServerState;
11
11
  executor: CommandExecutor;
12
12
  database?: number;
13
+ nodeRole?: RedisClusterNodeRole;
13
14
  signal?: AbortSignal;
14
15
  park?: ParkHandler;
15
16
  turnQueue?: RedisTurnQueue;
16
17
  };
18
+ /**
19
+ * Mutable view of the turn currently held by an in-flight command. A blocking
20
+ * command suspends its turn while parked and is later resumed on a *new* handle,
21
+ * so the holder must be able to both read the current turn and swap it.
22
+ */
17
23
  type TurnAccess = {
18
24
  get(): RedisTurnHandle | undefined;
19
25
  set(turn: RedisTurnHandle | undefined): void;
20
26
  };
27
+ /**
28
+ * Per-connection server state and the concrete {@link RedisClientSession}.
29
+ *
30
+ * One instance exists per connected client and owns everything that is scoped
31
+ * to that connection rather than to the shared server:
32
+ * - the selected database index and the resolved {@link RedisDatabase};
33
+ * - the session {@link ClientSessionMode} (normal / transaction / subscribed);
34
+ * - the negotiated RESP protocol version (HELLO);
35
+ * - the cluster READONLY flag (replica reads via READONLY/READWRITE);
36
+ * - the MULTI command queue and its dirty bit;
37
+ * - WATCH key registrations for optimistic locking.
38
+ *
39
+ * Commands are serialized through a per-database turn queue so that, even though
40
+ * execution is async, only one command mutates a given database at a time. This
41
+ * is also what makes blocking commands (BLPOP, ...) cooperate instead of
42
+ * deadlock — see {@link createTurnAwareParkHandler}.
43
+ */
21
44
  export declare class ClientSession implements RedisClientSession {
22
45
  private static nextId;
23
46
  readonly id: string;
24
47
  readonly server: RedisServerState;
48
+ /** Aborted when the connection closes; threaded into every command's ctx. */
25
49
  readonly signal: AbortSignal;
26
50
  private readonly executor;
27
51
  private readonly signalSource?;
52
+ private readonly nodeRole?;
28
53
  private readonly parkHandler;
29
54
  private readonly turnQueueOverride?;
55
+ /**
56
+ * The turn handle of the command currently executing on this session,
57
+ * exposed so {@link executeTransaction} can hand the turn off to another
58
+ * database's queue when a queued SELECT switches databases mid-EXEC.
59
+ */
60
+ private activeTurnAccess?;
30
61
  private selectedDatabaseId;
31
62
  private sessionMode;
32
63
  private respVersion;
64
+ private authenticated;
65
+ /** Set by READONLY, cleared by READWRITE/RESET; lets a replica serve reads. */
66
+ private clusterReadOnlyMode;
67
+ /** Commands buffered between MULTI and EXEC, in submission order. */
33
68
  private transactionPlans;
69
+ /** True once a queued command errored — forces EXEC to abort with EXECABORT. */
34
70
  private transactionDirty;
71
+ /** Active WATCH registrations, keyed by `db:keyHex`. */
35
72
  private readonly watches;
73
+ /** Subset of watched keys mutated since WATCH — non-empty fails the next EXEC. */
36
74
  private readonly dirtyWatches;
37
75
  constructor(options: ClientSessionOptions);
38
76
  get selectedDatabase(): number;
39
77
  get mode(): ClientSessionMode;
40
78
  get protocolVersion(): RespVersion;
79
+ get clusterReadOnly(): boolean;
80
+ get isAuthenticated(): boolean;
81
+ setAuthenticated(value: boolean): void;
82
+ /** The live database object for the currently selected index. */
41
83
  get db(): RedisDatabase;
42
84
  setProtocolVersion(version: RespVersion): void;
85
+ /** Toggle replica read mode for this connection (READONLY / READWRITE). */
86
+ setClusterReadOnly(value: boolean): void;
43
87
  selectDatabase(database: number): void;
88
+ /** MULTI: enter transaction mode. Redis forbids nesting. */
44
89
  beginTransaction(): void;
90
+ /** Buffer one command while in MULTI; replies "+QUEUED" to the client. */
45
91
  queueTransaction(plan: CommandPlan): void;
92
+ /**
93
+ * EXEC step 1: hand back the queued plans and atomically reset the session to
94
+ * normal mode (clearing the queue, dirty bit, and WATCHes). The caller is
95
+ * responsible for actually running the returned plans via
96
+ * {@link executeTransaction}. Returns an empty list if not in MULTI.
97
+ */
46
98
  drainTransaction(): CommandPlan[];
99
+ /** DISCARD: drop the queued commands and leave transaction mode. */
47
100
  discardTransaction(): void;
101
+ /** Flag the transaction as poisoned (a queued command failed). No-op outside MULTI. */
48
102
  markTransactionDirty(): void;
49
103
  isTransactionDirty(): boolean;
104
+ /**
105
+ * EXEC step 2: run the drained plans in order and collect their replies into a
106
+ * single array reply. Each command runs in its own fresh execution context.
107
+ * Streaming commands (SUBSCRIBE/MONITOR) are not permitted inside a
108
+ * transaction: the stream is closed immediately and replaced with an error
109
+ * entry so the array stays positionally aligned with the queued commands.
110
+ */
50
111
  executeTransaction(plans: readonly CommandPlan[]): Promise<RedisResult>;
112
+ /**
113
+ * Release the currently held serialization turn and acquire a fresh one on
114
+ * the selected database's queue. Called when a queued SELECT switches
115
+ * databases mid-EXEC so subsequent commands run under the correct
116
+ * per-database turn (see {@link executeTransaction}).
117
+ *
118
+ * No-op when a fixed turn-queue override is in force (a single queue already
119
+ * serializes every database) or when no managed turn is active.
120
+ */
121
+ private handoffTurnToSelectedDb;
122
+ /**
123
+ * WATCH the given keys for optimistic locking. Each key is subscribed in the
124
+ * keyspace; any mutation flips its entry into {@link dirtyWatches}, which a
125
+ * subsequent EXEC checks via {@link isWatchDirty}. Already-watched keys are
126
+ * skipped so re-WATCHing is idempotent.
127
+ */
51
128
  watch(keys: readonly Buffer[]): void;
129
+ /** UNWATCH / cleanup: drop every keyspace subscription and clear dirty state. */
52
130
  unwatch(): void;
131
+ /** True if any watched key was mutated since WATCH — EXEC must return nil. */
53
132
  isWatchDirty(): boolean;
133
+ /**
134
+ * Public entry point for executing one client command.
135
+ *
136
+ * Acquires a turn on the database's turn queue before running, guaranteeing
137
+ * serialized access to the keyspace, and always releases it afterward. The
138
+ * acquired turn is exposed to the command via a turn-aware park handler so a
139
+ * blocking command can yield the turn while parked (see
140
+ * {@link createTurnAwareParkHandler}); `turn` is reassigned through the
141
+ * {@link TurnAccess} closure because suspending returns a *new* handle.
142
+ */
54
143
  execute(rawCommand: Buffer | string, rawArgs: readonly Buffer[]): Promise<ExecutorResult>;
55
- createExecutionContext(turnAccess?: TurnAccess): RedisExecutionContext;
144
+ /**
145
+ * Build the {@link RedisExecutionContext} passed to a command's `execute`.
146
+ * When a turn is supplied (the normal client path) the context gets a
147
+ * turn-aware park handler so blocking commands release their turn while
148
+ * waiting; without one (e.g. nested transaction execution) the plain park
149
+ * handler is used.
150
+ */
151
+ createExecutionContext(turnAccess?: TurnAccess, parkOverride?: ParkHandler): RedisExecutionContext;
152
+ /** Tear down the session: abort in-flight work and reset all per-connection state. */
56
153
  close(): void;
154
+ /**
155
+ * Wrap the base park handler so that parking also yields the command's turn.
156
+ *
157
+ * Blocking commands (BLPOP, BRPOP, ...) must not hold the database turn while
158
+ * they wait, or no other client could ever produce the value that unblocks
159
+ * them — a deadlock. The flow:
160
+ * 1. Start the underlying park, capturing its eventual value.
161
+ * 2. Clear the local turn and call `turn.suspend(parked)`, which releases the
162
+ * turn back to the queue and resolves with a fresh turn once the park
163
+ * settles and this session is scheduled again.
164
+ * 3. Store the new turn (so `finally`/subsequent parks see it) and return the
165
+ * parked value.
166
+ *
167
+ * If there is no current turn, fall back to plain parking.
168
+ */
57
169
  private createTurnAwareParkHandler;
58
170
  }
59
171
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"client-session.d.ts","sourceRoot":"","sources":["../../src/core/client-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client-session.d.ts","sourceRoot":"","sources":["../../src/core/client-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEhB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC3B,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AACxE,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAEjB,MAAM,UAAU,CAAA;AAEjB,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,gBAAgB,CAAA;IACxB,QAAQ,EAAE,eAAe,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,oBAAoB,CAAA;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,SAAS,CAAC,EAAE,cAAc,CAAA;CAC3B,CAAA;AAED;;;;GAIG;AACH,KAAK,UAAU,GAAG;IAChB,GAAG,IAAI,eAAe,GAAG,SAAS,CAAA;IAClC,GAAG,CAAC,IAAI,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,CAAA;CAC7C,CAAA;AAQD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAc,YAAW,kBAAkB;IACtD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAI;IAEzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAiB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAgB;IACnD;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAC,CAAY;IACrC,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,aAAa,CAAQ;IAC7B,+EAA+E;IAC/E,OAAO,CAAC,mBAAmB,CAAQ;IACnC,qEAAqE;IACrE,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,gFAAgF;IAChF,OAAO,CAAC,gBAAgB,CAAQ;IAChC,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;gBAErC,OAAO,EAAE,oBAAoB;IAmBzC,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,IAAI,IAAI,IAAI,iBAAiB,CAE5B;IAED,IAAI,eAAe,IAAI,WAAW,CAEjC;IAED,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAItC,iEAAiE;IACjE,IAAI,EAAE,IAAI,aAAa,CAEtB;IAED,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAI9C,2EAA2E;IAC3E,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAIxC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYtC,4DAA4D;IAC5D,gBAAgB,IAAI,IAAI;IAUxB,0EAA0E;IAC1E,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAQzC;;;;;OAKG;IACH,gBAAgB,IAAI,WAAW,EAAE;IAajC,oEAAoE;IACpE,kBAAkB,IAAI,IAAI;IAO1B,uFAAuF;IACvF,oBAAoB,IAAI,IAAI;IAM5B,kBAAkB,IAAI,OAAO;IAI7B;;;;;;OAMG;IACG,kBAAkB,CACtB,KAAK,EAAE,SAAS,WAAW,EAAE,GAC5B,OAAO,CAAC,WAAW,CAAC;IAuDvB;;;;;;;;OAQG;YACW,uBAAuB;IAcrC;;;;;OAKG;IACH,KAAK,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAsBpC,iFAAiF;IACjF,OAAO,IAAI,IAAI;IASf,8EAA8E;IAC9E,YAAY,IAAI,OAAO;IAIvB;;;;;;;;;OASG;IACG,OAAO,CACX,UAAU,EAAE,MAAM,GAAG,MAAM,EAC3B,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAAC,cAAc,CAAC;IAuB1B;;;;;;OAMG;IACH,sBAAsB,CACpB,UAAU,CAAC,EAAE,UAAU,EACvB,YAAY,CAAC,EAAE,WAAW,GACzB,qBAAqB;IAuBxB,sFAAsF;IACtF,KAAK,IAAI,IAAI;IASb;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,0BAA0B;CAkBnC"}
@@ -5,27 +5,60 @@ const redis_context_1 = require("./redis-context");
5
5
  const redis_error_1 = require("./redis-error");
6
6
  const redis_result_1 = require("./redis-result");
7
7
  const redis_value_1 = require("./redis-value");
8
+ /**
9
+ * Per-connection server state and the concrete {@link RedisClientSession}.
10
+ *
11
+ * One instance exists per connected client and owns everything that is scoped
12
+ * to that connection rather than to the shared server:
13
+ * - the selected database index and the resolved {@link RedisDatabase};
14
+ * - the session {@link ClientSessionMode} (normal / transaction / subscribed);
15
+ * - the negotiated RESP protocol version (HELLO);
16
+ * - the cluster READONLY flag (replica reads via READONLY/READWRITE);
17
+ * - the MULTI command queue and its dirty bit;
18
+ * - WATCH key registrations for optimistic locking.
19
+ *
20
+ * Commands are serialized through a per-database turn queue so that, even though
21
+ * execution is async, only one command mutates a given database at a time. This
22
+ * is also what makes blocking commands (BLPOP, ...) cooperate instead of
23
+ * deadlock — see {@link createTurnAwareParkHandler}.
24
+ */
8
25
  class ClientSession {
9
26
  static nextId = 0;
10
27
  id;
11
28
  server;
29
+ /** Aborted when the connection closes; threaded into every command's ctx. */
12
30
  signal;
13
31
  executor;
14
32
  signalSource;
33
+ nodeRole;
15
34
  parkHandler;
16
35
  turnQueueOverride;
36
+ /**
37
+ * The turn handle of the command currently executing on this session,
38
+ * exposed so {@link executeTransaction} can hand the turn off to another
39
+ * database's queue when a queued SELECT switches databases mid-EXEC.
40
+ */
41
+ activeTurnAccess;
17
42
  selectedDatabaseId;
18
43
  sessionMode = 'normal';
19
44
  respVersion = 2;
45
+ authenticated = false;
46
+ /** Set by READONLY, cleared by READWRITE/RESET; lets a replica serve reads. */
47
+ clusterReadOnlyMode = false;
48
+ /** Commands buffered between MULTI and EXEC, in submission order. */
20
49
  transactionPlans = [];
50
+ /** True once a queued command errored — forces EXEC to abort with EXECABORT. */
21
51
  transactionDirty = false;
52
+ /** Active WATCH registrations, keyed by `db:keyHex`. */
22
53
  watches = new Map();
54
+ /** Subset of watched keys mutated since WATCH — non-empty fails the next EXEC. */
23
55
  dirtyWatches = new Set();
24
56
  constructor(options) {
25
57
  this.id = options.id ?? `client-${++ClientSession.nextId}`;
26
58
  this.server = options.server;
27
59
  this.executor = options.executor;
28
60
  this.selectedDatabaseId = options.database ?? 0;
61
+ this.nodeRole = options.nodeRole;
29
62
  this.parkHandler = options.park ?? (0, redis_context_1.createDefaultParkHandler)();
30
63
  this.turnQueueOverride = options.turnQueue;
31
64
  if (options.signal) {
@@ -46,12 +79,26 @@ class ClientSession {
46
79
  get protocolVersion() {
47
80
  return this.respVersion;
48
81
  }
82
+ get clusterReadOnly() {
83
+ return this.clusterReadOnlyMode;
84
+ }
85
+ get isAuthenticated() {
86
+ return this.authenticated;
87
+ }
88
+ setAuthenticated(value) {
89
+ this.authenticated = value;
90
+ }
91
+ /** The live database object for the currently selected index. */
49
92
  get db() {
50
93
  return this.server.getDatabase(this.selectedDatabaseId);
51
94
  }
52
95
  setProtocolVersion(version) {
53
96
  this.respVersion = version;
54
97
  }
98
+ /** Toggle replica read mode for this connection (READONLY / READWRITE). */
99
+ setClusterReadOnly(value) {
100
+ this.clusterReadOnlyMode = value;
101
+ }
55
102
  selectDatabase(database) {
56
103
  if (!Number.isInteger(database) ||
57
104
  database < 0 ||
@@ -60,6 +107,7 @@ class ClientSession {
60
107
  }
61
108
  this.selectedDatabaseId = database;
62
109
  }
110
+ /** MULTI: enter transaction mode. Redis forbids nesting. */
63
111
  beginTransaction() {
64
112
  if (this.sessionMode === 'transaction') {
65
113
  throw new redis_error_1.RedisCommandError('MULTI calls can not be nested');
@@ -68,12 +116,19 @@ class ClientSession {
68
116
  this.transactionPlans = [];
69
117
  this.transactionDirty = false;
70
118
  }
119
+ /** Buffer one command while in MULTI; replies "+QUEUED" to the client. */
71
120
  queueTransaction(plan) {
72
121
  if (this.sessionMode !== 'transaction') {
73
122
  throw new redis_error_1.RedisCommandError('MULTI has not been called');
74
123
  }
75
124
  this.transactionPlans.push(plan);
76
125
  }
126
+ /**
127
+ * EXEC step 1: hand back the queued plans and atomically reset the session to
128
+ * normal mode (clearing the queue, dirty bit, and WATCHes). The caller is
129
+ * responsible for actually running the returned plans via
130
+ * {@link executeTransaction}. Returns an empty list if not in MULTI.
131
+ */
77
132
  drainTransaction() {
78
133
  if (this.sessionMode !== 'transaction') {
79
134
  return [];
@@ -85,12 +140,14 @@ class ClientSession {
85
140
  this.unwatch();
86
141
  return plans;
87
142
  }
143
+ /** DISCARD: drop the queued commands and leave transaction mode. */
88
144
  discardTransaction() {
89
145
  this.transactionPlans = [];
90
146
  this.sessionMode = 'normal';
91
147
  this.transactionDirty = false;
92
148
  this.unwatch();
93
149
  }
150
+ /** Flag the transaction as poisoned (a queued command failed). No-op outside MULTI. */
94
151
  markTransactionDirty() {
95
152
  if (this.sessionMode === 'transaction') {
96
153
  this.transactionDirty = true;
@@ -99,13 +156,50 @@ class ClientSession {
99
156
  isTransactionDirty() {
100
157
  return this.transactionDirty;
101
158
  }
159
+ /**
160
+ * EXEC step 2: run the drained plans in order and collect their replies into a
161
+ * single array reply. Each command runs in its own fresh execution context.
162
+ * Streaming commands (SUBSCRIBE/MONITOR) are not permitted inside a
163
+ * transaction: the stream is closed immediately and replaced with an error
164
+ * entry so the array stays positionally aligned with the queued commands.
165
+ */
102
166
  async executeTransaction(plans) {
103
167
  const values = [];
168
+ // Blocking commands must not park while the EXEC turn is held — that would
169
+ // deadlock because no other session could produce the wakeup write. Override
170
+ // park so any blocking command queued in MULTI behaves non-blocking (returns
171
+ // null immediately), matching real Redis BLPOP-inside-MULTI semantics.
172
+ const noBlockCtx = this.createExecutionContext(undefined, async () => null);
173
+ let currentDbId = this.selectedDatabaseId;
104
174
  for (const plan of plans) {
105
175
  if (this.signal.aborted) {
106
176
  throw createAbortError();
107
177
  }
108
- const result = await this.executor.executePlan(plan, this.createExecutionContext());
178
+ // A queued SELECT on a previous iteration may have switched databases.
179
+ // Move the held turn onto the now-selected database's queue so its
180
+ // keyspace stays serialized against other sessions (#94 follow-up). Only
181
+ // one turn is ever held at a time (release-then-acquire), so this cannot
182
+ // deadlock even if two transactions select databases in opposite orders.
183
+ if (this.selectedDatabaseId !== currentDbId) {
184
+ await this.handoffTurnToSelectedDb();
185
+ currentDbId = this.selectedDatabaseId;
186
+ }
187
+ // executePlan converts RedisCommandErrors into error results, but a
188
+ // command whose execute() throws an unexpected runtime error (TypeError,
189
+ // etc.) would otherwise propagate out and abandon the partial results
190
+ // array. Real Redis always replies with an N-element EXEC array, so trap
191
+ // the failure into this command's slot and keep running the rest (#83).
192
+ let result;
193
+ try {
194
+ result = await this.executor.executePlan(plan, noBlockCtx);
195
+ }
196
+ catch (err) {
197
+ if (this.signal.aborted) {
198
+ throw err;
199
+ }
200
+ values.push(redis_value_1.RedisValue.error(err.message));
201
+ continue;
202
+ }
109
203
  if (result instanceof redis_result_1.RedisResult) {
110
204
  values.push(result.value);
111
205
  continue;
@@ -115,6 +209,33 @@ class ClientSession {
115
209
  }
116
210
  return redis_result_1.RedisResult.create(redis_value_1.RedisValue.array(values));
117
211
  }
212
+ /**
213
+ * Release the currently held serialization turn and acquire a fresh one on
214
+ * the selected database's queue. Called when a queued SELECT switches
215
+ * databases mid-EXEC so subsequent commands run under the correct
216
+ * per-database turn (see {@link executeTransaction}).
217
+ *
218
+ * No-op when a fixed turn-queue override is in force (a single queue already
219
+ * serializes every database) or when no managed turn is active.
220
+ */
221
+ async handoffTurnToSelectedDb() {
222
+ if (this.turnQueueOverride) {
223
+ return;
224
+ }
225
+ const turnAccess = this.activeTurnAccess;
226
+ if (!turnAccess) {
227
+ return;
228
+ }
229
+ turnAccess.get()?.release();
230
+ const nextTurn = await this.db.turnQueue.waitTurn();
231
+ turnAccess.set(nextTurn);
232
+ }
233
+ /**
234
+ * WATCH the given keys for optimistic locking. Each key is subscribed in the
235
+ * keyspace; any mutation flips its entry into {@link dirtyWatches}, which a
236
+ * subsequent EXEC checks via {@link isWatchDirty}. Already-watched keys are
237
+ * skipped so re-WATCHing is idempotent.
238
+ */
118
239
  watch(keys) {
119
240
  const database = this.selectedDatabaseId;
120
241
  const db = this.db;
@@ -133,6 +254,7 @@ class ClientSession {
133
254
  });
134
255
  }
135
256
  }
257
+ /** UNWATCH / cleanup: drop every keyspace subscription and clear dirty state. */
136
258
  unwatch() {
137
259
  for (const watch of this.watches.values()) {
138
260
  watch.unsubscribe();
@@ -140,47 +262,94 @@ class ClientSession {
140
262
  this.watches.clear();
141
263
  this.dirtyWatches.clear();
142
264
  }
265
+ /** True if any watched key was mutated since WATCH — EXEC must return nil. */
143
266
  isWatchDirty() {
144
267
  return this.dirtyWatches.size > 0;
145
268
  }
269
+ /**
270
+ * Public entry point for executing one client command.
271
+ *
272
+ * Acquires a turn on the database's turn queue before running, guaranteeing
273
+ * serialized access to the keyspace, and always releases it afterward. The
274
+ * acquired turn is exposed to the command via a turn-aware park handler so a
275
+ * blocking command can yield the turn while parked (see
276
+ * {@link createTurnAwareParkHandler}); `turn` is reassigned through the
277
+ * {@link TurnAccess} closure because suspending returns a *new* handle.
278
+ */
146
279
  async execute(rawCommand, rawArgs) {
147
280
  if (this.signal.aborted) {
148
281
  throw createAbortError();
149
282
  }
150
283
  const turnQueue = this.turnQueueOverride ?? this.db.turnQueue;
151
284
  let turn = await turnQueue.waitTurn();
285
+ const turnAccess = {
286
+ get: () => turn,
287
+ set: nextTurn => {
288
+ turn = nextTurn;
289
+ },
290
+ };
291
+ this.activeTurnAccess = turnAccess;
152
292
  try {
153
- const ctx = this.createExecutionContext({
154
- get: () => turn,
155
- set: nextTurn => {
156
- turn = nextTurn;
157
- },
158
- });
293
+ const ctx = this.createExecutionContext(turnAccess);
159
294
  return await this.executor.executeRaw(rawCommand, rawArgs, ctx);
160
295
  }
161
296
  finally {
297
+ this.activeTurnAccess = undefined;
162
298
  turn?.release();
163
299
  }
164
300
  }
165
- createExecutionContext(turnAccess) {
301
+ /**
302
+ * Build the {@link RedisExecutionContext} passed to a command's `execute`.
303
+ * When a turn is supplied (the normal client path) the context gets a
304
+ * turn-aware park handler so blocking commands release their turn while
305
+ * waiting; without one (e.g. nested transaction execution) the plain park
306
+ * handler is used.
307
+ */
308
+ createExecutionContext(turnAccess, parkOverride) {
309
+ // `db` is a live getter, not a snapshot: a queued `SELECT N` runs mid-EXEC
310
+ // and updates `selectedDatabaseId`, so every command must resolve the
311
+ // currently selected database at access time, not at context-build time
312
+ // (issue #94). Arrow keeps `this` bound to the session without aliasing.
313
+ const resolveDb = () => this.db;
166
314
  return {
167
- db: this.db,
315
+ get db() {
316
+ return resolveDb();
317
+ },
168
318
  server: this.server,
169
319
  session: this,
170
320
  executor: this.executor,
321
+ ...(this.nodeRole ? { nodeRole: this.nodeRole } : {}),
171
322
  signal: this.signal,
172
- park: turnAccess
173
- ? this.createTurnAwareParkHandler(turnAccess)
174
- : this.parkHandler,
323
+ park: parkOverride ??
324
+ (turnAccess
325
+ ? this.createTurnAwareParkHandler(turnAccess)
326
+ : this.parkHandler),
175
327
  };
176
328
  }
329
+ /** Tear down the session: abort in-flight work and reset all per-connection state. */
177
330
  close() {
178
331
  this.signalSource?.abort();
179
332
  this.unwatch();
180
333
  this.transactionPlans = [];
181
334
  this.transactionDirty = false;
182
335
  this.sessionMode = 'normal';
336
+ this.clusterReadOnlyMode = false;
183
337
  }
338
+ /**
339
+ * Wrap the base park handler so that parking also yields the command's turn.
340
+ *
341
+ * Blocking commands (BLPOP, BRPOP, ...) must not hold the database turn while
342
+ * they wait, or no other client could ever produce the value that unblocks
343
+ * them — a deadlock. The flow:
344
+ * 1. Start the underlying park, capturing its eventual value.
345
+ * 2. Clear the local turn and call `turn.suspend(parked)`, which releases the
346
+ * turn back to the queue and resolves with a fresh turn once the park
347
+ * settles and this session is scheduled again.
348
+ * 3. Store the new turn (so `finally`/subsequent parks see it) and return the
349
+ * parked value.
350
+ *
351
+ * If there is no current turn, fall back to plain parking.
352
+ */
184
353
  createTurnAwareParkHandler(turnAccess) {
185
354
  return async (request) => {
186
355
  const turn = turnAccess.get();
@@ -1 +1 @@
1
- {"version":3,"file":"client-session.js","sourceRoot":"","sources":["../../src/core/client-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client-session.js","sourceRoot":"","sources":["../../src/core/client-session.ts"],"names":[],"mappings":"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"}
@@ -4,21 +4,100 @@ import type { ExecutionPolicy } from './execution-policies';
4
4
  import type { RedisExecutionContext } from './redis-context';
5
5
  import { RedisResult } from './redis-result';
6
6
  import { ResponseStream } from './response-stream';
7
+ /**
8
+ * The result of running a command: either a finished {@link RedisResult} or a
9
+ * long-lived {@link ResponseStream} (e.g. SUBSCRIBE / MONITOR) whose frames the
10
+ * transport drains over time.
11
+ */
7
12
  export type ExecutorResult = RedisResult | ResponseStream;
8
13
  export type CommandExecutorOptions = {
9
14
  registry: CommandRegistry;
10
15
  policies?: readonly ExecutionPolicy[];
11
16
  };
17
+ /**
18
+ * Central command pipeline shared by every client session.
19
+ *
20
+ * Responsibilities:
21
+ * 1. Resolve a raw command name to a {@link CommandDefinition} (case-insensitive).
22
+ * 2. Parse raw argument buffers into typed args and extract routing keys,
23
+ * producing a {@link CommandPlan}.
24
+ * 3. Run the configured {@link ExecutionPolicy} chain around the command's own
25
+ * `execute`, giving policies (transaction, cluster, ...) a chance to
26
+ * short-circuit, rewrite, or wrap the result.
27
+ *
28
+ * Two execution paths exist on purpose:
29
+ * - {@link executePlan} / {@link executeRaw} — async, used for real network
30
+ * clients; may return a {@link ResponseStream} and may await async commands.
31
+ * - {@link executePlanSync} — synchronous mirror used by the Lua runtime, where
32
+ * `redis.call` must complete in a single tick. Streams and promises are
33
+ * rejected rather than awaited.
34
+ *
35
+ * The executor is stateless per-call: all mutable state lives on the
36
+ * {@link RedisExecutionContext} (and the session it carries).
37
+ */
12
38
  export declare class CommandExecutor {
13
39
  private readonly registry;
14
40
  private readonly policies;
15
41
  constructor(options: CommandExecutorOptions);
16
42
  getCommandDefinition(name: string): CommandDefinition<unknown> | undefined;
17
43
  getCommandDefinitions(): readonly CommandDefinition<unknown>[];
44
+ /**
45
+ * Resolve a raw command + args into a {@link CommandPlan} without executing it.
46
+ * The command name is matched case-insensitively against the registry.
47
+ *
48
+ * @throws {UnknownRedisCommandError} if no command is registered under the name.
49
+ */
18
50
  plan(rawCommand: Buffer | string, rawArgs: readonly Buffer[]): CommandPlan;
51
+ /**
52
+ * Plan and execute a raw command in one step — the normal entry point for a
53
+ * network client.
54
+ *
55
+ * Errors thrown during *planning* (unknown command, arity/parse failures) are
56
+ * caught here and converted into a RESP error reply. Such a failure also marks
57
+ * any open MULTI transaction dirty so a later EXEC is aborted, matching Redis:
58
+ * a command that cannot even be parsed must not silently vanish from the queue.
59
+ * Execution-time errors are handled inside {@link executePlan}.
60
+ */
19
61
  executeRaw(rawCommand: Buffer | string, rawArgs: readonly Buffer[], ctx: RedisExecutionContext): Promise<ExecutorResult>;
62
+ private static normalizeCommandName;
63
+ /**
64
+ * Run a pre-built plan through the full async pipeline.
65
+ *
66
+ * Order of operations:
67
+ * 1. `beforeExecute` for each policy. The first policy that returns a result
68
+ * short-circuits execution (e.g. the transaction policy queues the command
69
+ * and returns "+QUEUED"; the cluster policy returns a MOVED/CROSSSLOT
70
+ * error). A short-circuit error during MULTI also dirties the transaction.
71
+ * 2. The command's own `execute`.
72
+ * 3. If a {@link ResponseStream} is produced, run it through every policy's
73
+ * `onStream` hook; otherwise await the value and run it through every
74
+ * `afterExecute` hook (each may replace the result).
75
+ *
76
+ * Execution-time {@link RedisCommandError}s become RESP error replies (and
77
+ * dirty an open transaction when appropriate). Non-Redis errors propagate.
78
+ */
20
79
  executePlan(plan: CommandPlan, ctx: RedisExecutionContext): Promise<ExecutorResult>;
80
+ /**
81
+ * Synchronous counterpart to {@link executePlan}, used by the Lua runtime for
82
+ * `redis.call` / `redis.pcall`. Lua expects each nested command to resolve
83
+ * immediately, so anything that would require awaiting — a command that
84
+ * returns a promise, a {@link ResponseStream}, or an async policy hook — is
85
+ * rejected with a {@link RedisCommandError} instead of being awaited. Async
86
+ * command definitions are rejected before invocation so they cannot leave
87
+ * orphaned work running after the script error (see
88
+ * {@link assertSyncCommandDefinition}, {@link assertSyncCommandResult}, and
89
+ * {@link assertSyncPolicyResult}).
90
+ *
91
+ * The policy chain and transaction-dirty handling otherwise mirror the async
92
+ * path exactly.
93
+ */
21
94
  executePlanSync(plan: CommandPlan, ctx: RedisExecutionContext): RedisResult;
95
+ /**
96
+ * Build a {@link CommandPlan} from a resolved definition: parse the raw buffers
97
+ * against the command's schema (may throw arity/type errors) and extract the
98
+ * routing keys used for cluster slot validation. Flags are copied onto the plan
99
+ * so policies can inspect them without re-resolving the definition.
100
+ */
22
101
  private createPlan;
23
102
  }
24
103
  //# sourceMappingURL=command-executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-executor.d.ts","sourceRoot":"","sources":["../../src/core/command-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAoB,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEpE,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,cAAc,CAAA;AAEzD,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,eAAe,CAAA;IACzB,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;CACtC,CAAA;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;gBAEzC,OAAO,EAAE,sBAAsB;IAK3C,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI1E,qBAAqB,IAAI,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAI9D,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW;IAcpE,UAAU,CACd,UAAU,EAAE,MAAM,GAAG,MAAM,EAC3B,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,cAAc,CAAC;IAapB,WAAW,CACf,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,cAAc,CAAC;IAgD1B,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,qBAAqB,GAAG,WAAW;IA4C3E,OAAO,CAAC,UAAU;CAcnB"}
1
+ {"version":3,"file":"command-executor.d.ts","sourceRoot":"","sources":["../../src/core/command-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAO3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAoB,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEpE;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,cAAc,CAAA;AAEzD,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,eAAe,CAAA;IACzB,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;CACtC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;gBAEzC,OAAO,EAAE,sBAAsB;IAK3C,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,SAAS;IAI1E,qBAAqB,IAAI,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAI9D;;;;;OAKG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW;IAW1E;;;;;;;;;OASG;IACG,UAAU,CACd,UAAU,EAAE,MAAM,GAAG,MAAM,EAC3B,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,cAAc,CAAC;IA2B1B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAMnC;;;;;;;;;;;;;;;OAeG;IACG,WAAW,CACf,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,cAAc,CAAC;IAgD1B;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,qBAAqB,GAAG,WAAW;IA6C3E;;;;;OAKG;IACH,OAAO,CAAC,UAAU;CAcnB"}