@restatedev/restate-sdk 0.7.3-worker → 0.8.1

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 (231) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +29 -51
  3. package/dist/clients/workflow_client.d.ts +77 -0
  4. package/dist/clients/workflow_client.d.ts.map +1 -0
  5. package/dist/clients/workflow_client.js +172 -0
  6. package/dist/clients/workflow_client.js.map +1 -0
  7. package/dist/connection/buffered_connection.js +44 -0
  8. package/dist/connection/buffered_connection.js.map +1 -0
  9. package/dist/connection/connection.js +13 -0
  10. package/dist/connection/connection.js.map +1 -0
  11. package/dist/connection/embedded_connection.js +59 -0
  12. package/dist/connection/embedded_connection.js.map +1 -0
  13. package/dist/connection/http_connection.js +203 -0
  14. package/dist/connection/http_connection.js.map +1 -0
  15. package/dist/connection/lambda_connection.js +58 -0
  16. package/dist/connection/lambda_connection.js.map +1 -0
  17. package/dist/{restate_context.d.ts → context.d.ts} +239 -170
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +113 -0
  20. package/dist/context.js.map +1 -0
  21. package/dist/{restate_context_impl.d.ts → context_impl.d.ts} +26 -30
  22. package/dist/context_impl.d.ts.map +1 -0
  23. package/dist/context_impl.js +439 -0
  24. package/dist/context_impl.js.map +1 -0
  25. package/dist/embedded/api.d.ts +2 -2
  26. package/dist/embedded/api.d.ts.map +1 -1
  27. package/dist/embedded/api.js +35 -0
  28. package/dist/embedded/api.js.map +1 -0
  29. package/dist/embedded/handler.d.ts +2 -2
  30. package/dist/embedded/handler.d.ts.map +1 -1
  31. package/dist/embedded/handler.js +26 -0
  32. package/dist/embedded/handler.js.map +1 -0
  33. package/dist/embedded/http2_remote.js +91 -0
  34. package/dist/embedded/http2_remote.js.map +1 -0
  35. package/dist/embedded/invocation.d.ts.map +1 -1
  36. package/dist/embedded/invocation.js +94 -0
  37. package/dist/embedded/invocation.js.map +1 -0
  38. package/dist/endpoint/endpoint_impl.d.ts +35 -0
  39. package/dist/endpoint/endpoint_impl.d.ts.map +1 -0
  40. package/dist/endpoint/endpoint_impl.js +405 -0
  41. package/dist/endpoint/endpoint_impl.js.map +1 -0
  42. package/dist/endpoint/http2_handler.d.ts +11 -0
  43. package/dist/endpoint/http2_handler.d.ts.map +1 -0
  44. package/dist/endpoint/http2_handler.js +119 -0
  45. package/dist/endpoint/http2_handler.js.map +1 -0
  46. package/dist/endpoint/lambda_handler.d.ts +15 -0
  47. package/dist/endpoint/lambda_handler.d.ts.map +1 -0
  48. package/dist/endpoint/lambda_handler.js +144 -0
  49. package/dist/endpoint/lambda_handler.js.map +1 -0
  50. package/dist/endpoint.d.ts +161 -0
  51. package/dist/endpoint.d.ts.map +1 -0
  52. package/dist/endpoint.js +22 -0
  53. package/dist/endpoint.js.map +1 -0
  54. package/dist/generated/dev/restate/events.js +371 -0
  55. package/dist/generated/dev/restate/events.js.map +1 -0
  56. package/dist/generated/dev/restate/ext.js +215 -0
  57. package/dist/generated/dev/restate/ext.js.map +1 -0
  58. package/dist/generated/google/protobuf/descriptor.js +6676 -0
  59. package/dist/generated/google/protobuf/descriptor.js.map +1 -0
  60. package/dist/generated/google/protobuf/empty.js +107 -0
  61. package/dist/generated/google/protobuf/empty.js.map +1 -0
  62. package/dist/generated/google/protobuf/struct.js +754 -0
  63. package/dist/generated/google/protobuf/struct.js.map +1 -0
  64. package/dist/generated/proto/discovery.js +364 -0
  65. package/dist/generated/proto/discovery.js.map +1 -0
  66. package/dist/generated/proto/dynrpc.js +668 -0
  67. package/dist/generated/proto/dynrpc.js.map +1 -0
  68. package/dist/generated/proto/javascript.d.ts +13 -0
  69. package/dist/generated/proto/javascript.d.ts.map +1 -1
  70. package/dist/generated/proto/javascript.js +416 -0
  71. package/dist/generated/proto/javascript.js.map +1 -0
  72. package/dist/generated/proto/protocol.d.ts +43 -0
  73. package/dist/generated/proto/protocol.d.ts.map +1 -1
  74. package/dist/generated/proto/protocol.js +2641 -0
  75. package/dist/generated/proto/protocol.js.map +1 -0
  76. package/dist/generated/proto/services.js +1535 -0
  77. package/dist/generated/proto/services.js.map +1 -0
  78. package/dist/generated/proto/test.js +321 -0
  79. package/dist/generated/proto/test.js.map +1 -0
  80. package/dist/invocation.d.ts +4 -1
  81. package/dist/invocation.d.ts.map +1 -1
  82. package/dist/invocation.js +157 -0
  83. package/dist/invocation.js.map +1 -0
  84. package/dist/io/decoder.d.ts +1 -0
  85. package/dist/io/decoder.d.ts.map +1 -1
  86. package/dist/io/decoder.js +140 -0
  87. package/dist/io/decoder.js.map +1 -0
  88. package/dist/io/encoder.d.ts +1 -2
  89. package/dist/io/encoder.d.ts.map +1 -1
  90. package/dist/io/encoder.js +68 -0
  91. package/dist/io/encoder.js.map +1 -0
  92. package/dist/journal.d.ts +13 -4
  93. package/dist/journal.d.ts.map +1 -1
  94. package/dist/journal.js +405 -0
  95. package/dist/journal.js.map +1 -0
  96. package/dist/local_state_store.d.ts +5 -3
  97. package/dist/local_state_store.d.ts.map +1 -1
  98. package/dist/local_state_store.js +82 -0
  99. package/dist/local_state_store.js.map +1 -0
  100. package/dist/logger.d.ts +19 -0
  101. package/dist/logger.d.ts.map +1 -0
  102. package/dist/logger.js +90 -0
  103. package/dist/logger.js.map +1 -0
  104. package/dist/promise_combinator_tracker.d.ts +29 -0
  105. package/dist/promise_combinator_tracker.d.ts.map +1 -0
  106. package/dist/promise_combinator_tracker.js +128 -0
  107. package/dist/promise_combinator_tracker.js.map +1 -0
  108. package/dist/public_api.d.ts +5 -5
  109. package/dist/public_api.d.ts.map +1 -1
  110. package/dist/public_api.js +60 -0
  111. package/dist/public_api.js.map +1 -0
  112. package/dist/state_machine.d.ts +19 -12
  113. package/dist/state_machine.d.ts.map +1 -1
  114. package/dist/state_machine.js +437 -0
  115. package/dist/state_machine.js.map +1 -0
  116. package/dist/types/errors.d.ts +12 -3
  117. package/dist/types/errors.d.ts.map +1 -1
  118. package/dist/types/errors.js +273 -0
  119. package/dist/types/errors.js.map +1 -0
  120. package/dist/types/grpc.d.ts +6 -4
  121. package/dist/types/grpc.d.ts.map +1 -1
  122. package/dist/types/grpc.js +81 -0
  123. package/dist/types/grpc.js.map +1 -0
  124. package/dist/types/protocol.d.ts +9 -5
  125. package/dist/types/protocol.d.ts.map +1 -1
  126. package/dist/types/protocol.js +147 -0
  127. package/dist/types/protocol.js.map +1 -0
  128. package/dist/types/router.d.ts +8 -8
  129. package/dist/types/router.d.ts.map +1 -1
  130. package/dist/types/router.js +36 -0
  131. package/dist/types/router.js.map +1 -0
  132. package/dist/types/types.d.ts +1 -0
  133. package/dist/types/types.d.ts.map +1 -1
  134. package/dist/types/types.js +138 -0
  135. package/dist/types/types.js.map +1 -0
  136. package/dist/utils/{assumpsions.d.ts → assumptions.d.ts} +1 -1
  137. package/dist/utils/{assumpsions.d.ts.map → assumptions.d.ts.map} +1 -1
  138. package/dist/utils/assumptions.js +101 -0
  139. package/dist/utils/assumptions.js.map +1 -0
  140. package/dist/utils/message_logger.d.ts +28 -0
  141. package/dist/utils/message_logger.d.ts.map +1 -0
  142. package/dist/utils/message_logger.js +88 -0
  143. package/dist/utils/message_logger.js.map +1 -0
  144. package/dist/utils/promises.d.ts +15 -0
  145. package/dist/utils/promises.d.ts.map +1 -0
  146. package/dist/utils/promises.js +67 -0
  147. package/dist/utils/promises.js.map +1 -0
  148. package/dist/utils/public_utils.js +49 -0
  149. package/dist/utils/public_utils.js.map +1 -0
  150. package/dist/utils/rand.d.ts +1 -1
  151. package/dist/utils/rand.d.ts.map +1 -1
  152. package/dist/utils/rand.js +114 -0
  153. package/dist/utils/rand.js.map +1 -0
  154. package/dist/utils/utils.d.ts +1 -10
  155. package/dist/utils/utils.d.ts.map +1 -1
  156. package/dist/utils/utils.js +122 -0
  157. package/dist/utils/utils.js.map +1 -0
  158. package/dist/workflows/workflow.d.ts +101 -0
  159. package/dist/workflows/workflow.d.ts.map +1 -0
  160. package/dist/workflows/workflow.js +80 -0
  161. package/dist/workflows/workflow.js.map +1 -0
  162. package/dist/workflows/workflow_state_service.d.ts +35 -0
  163. package/dist/workflows/workflow_state_service.d.ts.map +1 -0
  164. package/dist/workflows/workflow_state_service.js +201 -0
  165. package/dist/workflows/workflow_state_service.js.map +1 -0
  166. package/dist/workflows/workflow_wrapper_service.d.ts +10 -0
  167. package/dist/workflows/workflow_wrapper_service.d.ts.map +1 -0
  168. package/dist/workflows/workflow_wrapper_service.js +264 -0
  169. package/dist/workflows/workflow_wrapper_service.js.map +1 -0
  170. package/package.json +38 -39
  171. package/src/clients/workflow_client.ts +290 -0
  172. package/src/connection/buffered_connection.ts +47 -0
  173. package/src/connection/connection.ts +34 -0
  174. package/src/connection/embedded_connection.ts +62 -0
  175. package/src/connection/http_connection.ts +228 -0
  176. package/src/connection/lambda_connection.ts +69 -0
  177. package/src/context.ts +633 -0
  178. package/src/context_impl.ts +721 -0
  179. package/src/embedded/api.ts +57 -0
  180. package/src/embedded/handler.ts +36 -0
  181. package/src/embedded/http2_remote.ts +103 -0
  182. package/src/embedded/invocation.ts +126 -0
  183. package/src/endpoint/endpoint_impl.ts +623 -0
  184. package/src/endpoint/http2_handler.ts +151 -0
  185. package/src/endpoint/lambda_handler.ts +181 -0
  186. package/src/endpoint.ts +187 -0
  187. package/src/generated/dev/restate/events.ts +430 -0
  188. package/src/generated/dev/restate/ext.ts +238 -0
  189. package/src/generated/google/protobuf/descriptor.ts +7889 -0
  190. package/src/generated/google/protobuf/empty.ts +150 -0
  191. package/src/generated/google/protobuf/struct.ts +878 -0
  192. package/src/generated/proto/discovery.ts +423 -0
  193. package/src/generated/proto/dynrpc.ts +768 -0
  194. package/src/generated/proto/javascript.ts +488 -0
  195. package/src/generated/proto/protocol.ts +3091 -0
  196. package/src/generated/proto/services.ts +1834 -0
  197. package/src/generated/proto/test.ts +387 -0
  198. package/src/invocation.ts +212 -0
  199. package/src/io/decoder.ts +171 -0
  200. package/src/io/encoder.ts +72 -0
  201. package/src/journal.ts +537 -0
  202. package/src/local_state_store.ts +94 -0
  203. package/src/logger.ts +121 -0
  204. package/src/promise_combinator_tracker.ts +191 -0
  205. package/src/public_api.ts +53 -0
  206. package/src/state_machine.ts +635 -0
  207. package/src/types/errors.ts +297 -0
  208. package/src/types/grpc.ts +97 -0
  209. package/src/types/protocol.ts +201 -0
  210. package/src/types/router.ts +118 -0
  211. package/src/types/types.ts +160 -0
  212. package/src/utils/assumptions.ts +131 -0
  213. package/src/utils/message_logger.ts +112 -0
  214. package/src/utils/promises.ts +118 -0
  215. package/src/utils/public_utils.ts +91 -0
  216. package/src/utils/rand.ts +142 -0
  217. package/src/utils/utils.ts +178 -0
  218. package/src/workflows/workflow.ts +178 -0
  219. package/src/workflows/workflow_state_service.ts +299 -0
  220. package/src/workflows/workflow_wrapper_service.ts +314 -0
  221. package/dist/cloudflare_bundle.js +0 -27387
  222. package/dist/restate_context.d.ts.map +0 -1
  223. package/dist/restate_context_impl.d.ts.map +0 -1
  224. package/dist/server/base_restate_server.d.ts +0 -32
  225. package/dist/server/base_restate_server.d.ts.map +0 -1
  226. package/dist/server/restate_lambda_handler.d.ts +0 -104
  227. package/dist/server/restate_lambda_handler.d.ts.map +0 -1
  228. package/dist/server/restate_server.d.ts +0 -97
  229. package/dist/server/restate_server.d.ts.map +0 -1
  230. package/dist/utils/logger.d.ts +0 -60
  231. package/dist/utils/logger.d.ts.map +0 -1
@@ -1,33 +1,11 @@
1
1
  /// <reference types="node" />
2
- import "./utils/logger";
2
+ /// <reference types="node" />
3
3
  import { RetrySettings } from "./utils/public_utils";
4
4
  import { Client, SendClient } from "./types/router";
5
5
  /**
6
- * Base Restate context, which contains all operations that are the same in the gRPC-based API
7
- * as in the dynamic rpc-handler-based API.
8
- *
9
- * Those operations include state access/updates, side-effects, awakeables, or sleeps.
6
+ * Key value store operations. Only keyed services have an attached key-value store.
10
7
  */
11
- export interface RestateBaseContext {
12
- /**
13
- * The unique id that identifies the current function invocation. This id is guaranteed to be
14
- * unique across invocations, but constant across reties and suspensions.
15
- */
16
- id: Buffer;
17
- /**
18
- * Name of the service.
19
- */
20
- serviceName: string;
21
- /**
22
- * Deterministic random methods; these are inherently predictable (seeded on the invocation ID, which is not secret)
23
- * and so should not be used for any cryptographic purposes. They are useful for identifiers, idempotency keys,
24
- * and for uniform sampling from a set of options. If a cryptographically secure value is needed, please generate that
25
- * externally and capture the result with a side effect.
26
- *
27
- * Calls to these methods from inside side effects are disallowed and will fail - side effects must be idempotent, and
28
- * these calls are not.
29
- */
30
- rand: Rand;
8
+ export interface KeyValueStore {
31
9
  /**
32
10
  * Get/retrieve state from the Restate runtime.
33
11
  * Note that state objects are serialized with `Buffer.from(JSON.stringify(theObject))`
@@ -41,6 +19,7 @@ export interface RestateBaseContext {
41
19
  * const state = await ctx.get<string>("STATE");
42
20
  */
43
21
  get<T>(name: string): Promise<T | null>;
22
+ stateKeys(): Promise<Array<string>>;
44
23
  /**
45
24
  * Set/store state in the Restate runtime.
46
25
  * Note that state objects are serialized with `Buffer.from(JSON.stringify(theObject))`
@@ -51,7 +30,7 @@ export interface RestateBaseContext {
51
30
  *
52
31
  * @example
53
32
  * const ctx = restate.useContext(this);
54
- * const state = ctx.set("STATE", "Hello");
33
+ * ctx.set("STATE", "Hello");
55
34
  */
56
35
  set<T>(name: string, value: T): void;
57
36
  /**
@@ -60,9 +39,55 @@ export interface RestateBaseContext {
60
39
  *
61
40
  * @example
62
41
  * const ctx = restate.useContext(this);
63
- * const state = ctx.clear("STATE");
42
+ * ctx.clear("STATE");
64
43
  */
65
44
  clear(name: string): void;
45
+ /**
46
+ * Clear/delete all the state entries in the Restate runtime.
47
+ *
48
+ * @example
49
+ * const ctx = restate.useContext(this);
50
+ * ctx.clearAll();
51
+ */
52
+ clearAll(): void;
53
+ }
54
+ /**
55
+ * The context that gives access to all Restate-backed operations, for example
56
+ * - sending reliable messages / RPC through Restate
57
+ * - side effects
58
+ * - sleeps and delayed calls
59
+ * - awakeables
60
+ * - ...
61
+ *
62
+ * Keyed services can also access their key-value store using the {@link KeyedContext}.
63
+ *
64
+ * In gRPC-based API, to access this context, use {@link useContext}.
65
+ */
66
+ export interface Context {
67
+ /**
68
+ * The unique id that identifies the current function invocation. This id is guaranteed to be
69
+ * unique across invocations, but constant across reties and suspensions.
70
+ */
71
+ id: Buffer;
72
+ /**
73
+ * Name of the service.
74
+ */
75
+ serviceName: string;
76
+ /**
77
+ * Deterministic random methods; these are inherently predictable (seeded on the invocation ID, which is not secret)
78
+ * and so should not be used for any cryptographic purposes. They are useful for identifiers, idempotency keys,
79
+ * and for uniform sampling from a set of options. If a cryptographically secure value is needed, please generate that
80
+ * externally and capture the result with a side effect.
81
+ *
82
+ * Calls to these methods from inside side effects are disallowed and will fail - side effects must be idempotent, and
83
+ * these calls are not.
84
+ */
85
+ rand: Rand;
86
+ /**
87
+ * Console to use for logging. It attaches to each log message some contextual information,
88
+ * such as invoked service method and invocation id, and automatically excludes logs during replay.
89
+ */
90
+ console: Console;
66
91
  /**
67
92
  * Execute a side effect and store the result in Restate. The side effect will thus not
68
93
  * be re-executed during a later replay, but take the durable result from Restate.
@@ -127,7 +152,7 @@ export interface RestateBaseContext {
127
152
  */
128
153
  awakeable<T>(): {
129
154
  id: string;
130
- promise: Promise<T>;
155
+ promise: CombineablePromise<T>;
131
156
  };
132
157
  /**
133
158
  * Resolve an awakeable of another service.
@@ -142,7 +167,7 @@ export interface RestateBaseContext {
142
167
  * // The sleeping service should have sent the awakeableIdentifier string to this service.
143
168
  * ctx.resolveAwakeable(awakeableIdentifier, "hello");
144
169
  */
145
- resolveAwakeable<T>(id: string, payload: T): void;
170
+ resolveAwakeable<T>(id: string, payload?: T): void;
146
171
  /**
147
172
  * Reject an awakeable of another service. When rejecting, the service waiting on this awakeable will be woken up with a terminal error with the provided reason.
148
173
  * @param id the string ID of the awakeable.
@@ -164,140 +189,7 @@ export interface RestateBaseContext {
164
189
  * const ctx = restate.useContext(this);
165
190
  * await ctx.sleep(1000);
166
191
  */
167
- sleep(millis: number): Promise<void>;
168
- }
169
- export interface Rand {
170
- /**
171
- * Equivalent of JS `Math.random()` but deterministic; seeded by the invocation ID of the current invocation,
172
- * each call will return a new pseudorandom float within the range [0,1)
173
- */
174
- random(): number;
175
- /**
176
- * Using the same random source and seed as random(), produce a UUID version 4 string. This is inherently predictable
177
- * based on the invocation ID and should not be used in cryptographic contexts
178
- */
179
- uuidv4(): string;
180
- }
181
- /**
182
- * Interface to interact with **gRPC** based services.
183
- */
184
- export interface RestateGrpcChannel {
185
- /**
186
- * Unidirectional call to other Restate services ( = in background / async / not waiting on response).
187
- * To do this, wrap the call via the proto-ts client with oneWayCall, as shown in the example.
188
- *
189
- * NOTE: this returns a Promise because we override the gRPC clients provided by proto-ts.
190
- * So we are required to return a Promise.
191
- *
192
- * @param call Invoke another service by using the generated proto-ts client.
193
- * @example
194
- * const ctx = restate.useContext(this);
195
- * const client = new GreeterClientImpl(ctx);
196
- * await ctx.oneWayCall(() =>
197
- * client.greet(Request.create({ name: "Peter" }))
198
- * )
199
- */
200
- oneWayCall(call: () => Promise<any>): Promise<void>;
201
- /**
202
- * Delayed unidirectional call to other Restate services ( = in background / async / not waiting on response).
203
- * To do this, wrap the call via the proto-ts client with delayedCall, as shown in the example.
204
- * Add the delay in millis as the second parameter.
205
- *
206
- * NOTE: this returns a Promise because we override the gRPC clients provided by proto-ts.
207
- * So we are required to return a Promise.
208
- *
209
- * @param call Invoke another service by using the generated proto-ts client.
210
- * @param delayMillis millisecond delay duration to delay the execution of the call
211
- * @example
212
- * const ctx = restate.useContext(this);
213
- * const client = new GreeterClientImpl(ctx);
214
- * await ctx.delayedCall(() =>
215
- * client.greet(Request.create({ name: "Peter" })),
216
- * 5000
217
- * )
218
- */
219
- delayedCall(call: () => Promise<any>, delayMillis?: number): Promise<void>;
220
- /**
221
- * Call another Restate service and await the response.
222
- *
223
- * This function is not recommended to be called directly. Instead, use the generated gRPC client
224
- * that was generated based on the Protobuf service definitions (which internally use this method):
225
- *
226
- * @example
227
- * ```
228
- * const ctx = restate.useContext(this);
229
- * const client = new GreeterClientImpl(ctx);
230
- * client.greet(Request.create({ name: "Peter" }))
231
- * ```
232
- *
233
- * @param service name of the service to call
234
- * @param method name of the method to call
235
- * @param data payload as Uint8Array
236
- * @returns a Promise that is resolved with the response of the called service
237
- */
238
- request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
239
- }
240
- /**
241
- * The context that gives access to all Restate-backed operations, for example
242
- * - sending reliable messages / rpc through Restate
243
- * - access/update state (for keyed services)
244
- * - side effects
245
- * - sleeps and delayed calls
246
- * - awakeables
247
- * - ...
248
- *
249
- * This context is for use in **gRPC service** implementations.
250
- * For the rpc-handler API, use the {@link RpcContext} instead.
251
- */
252
- export interface RestateGrpcContext extends RestateBaseContext, RestateGrpcChannel {
253
- /**
254
- * Get the {@link RpcGateway} to invoke Handler-API based services.
255
- */
256
- rpcGateway(): RpcGateway;
257
- }
258
- /**
259
- * For compatibility, we make the support 'RestateContext' as the type for the Grpc-based API context.
260
- */
261
- export type RestateContext = RestateGrpcContext;
262
- /**
263
- * Returns the RestateContext which is the entrypoint for all interaction with Restate.
264
- * Use this from within a method to retrieve the RestateContext.
265
- * The context is bounded to a single invocation.
266
- *
267
- * @example
268
- * const ctx = restate.useContext(this);
269
- *
270
- */
271
- export declare function useContext<T>(instance: T): RestateGrpcContext;
272
- export declare function setContext<T>(instance: T, context: RestateGrpcContext): T;
273
- /**
274
- * ServiceApi captures the type and parameters to make RPC calls and send messages to
275
- * a set of RPC handlers in a router.
276
- *
277
- * @example
278
- * **Service Side:**
279
- * ```ts
280
- * const router = restate.router({
281
- * someAction: async(ctx: restate.RpcContext, req: string) => { ... },
282
- * anotherAction: async(ctx: restate.RpcContext, count: number) => { ... }
283
- * });
284
- *
285
- * export const myApi: restate.ServiceApi<typeof router> = { path : "myservice" };
286
- *
287
- * restate.createServer().bindRouter("myservice", router).listen(9080);
288
- * ```
289
- * **Client side:**
290
- * ```ts
291
- * ctx.rpc(myApi).someAction("hello!");
292
- * ```
293
- */
294
- export type ServiceApi<_M = unknown> = {
295
- path: string;
296
- };
297
- /**
298
- * Interface to interact with **rpc-handler API** based services.
299
- */
300
- export interface RpcGateway {
192
+ sleep(millis: number): CombineablePromise<void>;
301
193
  /**
302
194
  * Makes a type-safe request/response RPC to the specified target service.
303
195
  *
@@ -423,23 +315,200 @@ export interface RpcGateway {
423
315
  * ```
424
316
  */
425
317
  sendDelayed<M>(opts: ServiceApi<M>, delay: number): SendClient<M>;
318
+ /**
319
+ * Get the {@link RestateGrpcChannel} to invoke gRPC based services.
320
+ */
321
+ grpcChannel(): RestateGrpcChannel;
426
322
  }
427
323
  /**
428
324
  * The context that gives access to all Restate-backed operations, for example
429
325
  * - sending reliable messages / RPC through Restate
430
- * - access/update state (for keyed services)
326
+ * - access/update state
431
327
  * - side effects
432
328
  * - sleeps and delayed calls
433
329
  * - awakeables
434
330
  * - ...
435
331
  *
436
- * This context is for use with the **rpc-handler API**.
437
- * For gRPC-based API, use the {@link RestateContext} instead.
332
+ * This context can be used only within keyed services/routers.
333
+ *
334
+ * In gRPC-based API, to access this context, use {@link useKeyedContext}.
438
335
  */
439
- export interface RpcContext extends RestateBaseContext, RpcGateway {
336
+ export interface KeyedContext extends Context, KeyValueStore {
337
+ }
338
+ export interface Rand {
440
339
  /**
441
- * Get the {@link RestateGrpcChannel} to invoke gRPC based services.
340
+ * Equivalent of JS `Math.random()` but deterministic; seeded by the invocation ID of the current invocation,
341
+ * each call will return a new pseudorandom float within the range [0,1)
442
342
  */
443
- grpcChannel(): RestateGrpcChannel;
343
+ random(): number;
344
+ /**
345
+ * Using the same random source and seed as random(), produce a UUID version 4 string. This is inherently predictable
346
+ * based on the invocation ID and should not be used in cryptographic contexts
347
+ */
348
+ uuidv4(): string;
444
349
  }
445
- //# sourceMappingURL=restate_context.d.ts.map
350
+ /**
351
+ * A promise that can be combined using Promise combinators in RestateContext.
352
+ */
353
+ export type CombineablePromise<T> = Promise<T> & {
354
+ __restate_context: Context;
355
+ /**
356
+ * Creates a promise that awaits for the current promise up to the specified timeout duration.
357
+ * If the timeout is fired, this Promise will be rejected with a {@link TimeoutError}.
358
+ *
359
+ * @param millis duration of the sleep in millis.
360
+ * This is a lower-bound.
361
+ */
362
+ orTimeout(millis: number): Promise<T>;
363
+ };
364
+ export declare const CombineablePromise: {
365
+ /**
366
+ * Creates a Promise that is resolved with an array of results when all of the provided Promises
367
+ * resolve, or rejected when any Promise is rejected.
368
+ *
369
+ * See {@link Promise.all} for more details.
370
+ *
371
+ * @param values An iterable of Promises.
372
+ * @returns A new Promise.
373
+ */
374
+ all<T extends [] | readonly CombineablePromise<unknown>[]>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]>; }>;
375
+ /**
376
+ * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
377
+ * or rejected.
378
+ *
379
+ * See {@link Promise.race} for more details.
380
+ *
381
+ * @param values An iterable of Promises.
382
+ * @returns A new Promise.
383
+ */
384
+ race<T_1 extends [] | readonly CombineablePromise<unknown>[]>(values: T_1): Promise<Awaited<T_1[number]>>;
385
+ /**
386
+ * Creates a promise that fulfills when any of the input's promises fulfills, with this first fulfillment value.
387
+ * It rejects when all the input's promises reject (including when an empty iterable is passed),
388
+ * with an AggregateError containing an array of rejection reasons.
389
+ *
390
+ * See {@link Promise.any} for more details.
391
+ *
392
+ * @param values An iterable of Promises.
393
+ * @returns A new Promise.
394
+ */
395
+ any<T_2 extends [] | readonly CombineablePromise<unknown>[]>(values: T_2): Promise<Awaited<T_2[number]>>;
396
+ /**
397
+ * Creates a promise that fulfills when all the input's promises settle (including when an empty iterable is passed),
398
+ * with an array of objects that describe the outcome of each promise.
399
+ *
400
+ * See {@link Promise.allSettled} for more details.
401
+ *
402
+ * @param values An iterable of Promises.
403
+ * @returns A new Promise.
404
+ */
405
+ allSettled<T_3 extends [] | readonly CombineablePromise<unknown>[]>(values: T_3): Promise<{ -readonly [P_1 in keyof T_3]: PromiseSettledResult<Awaited<T_3[P_1]>>; }>;
406
+ };
407
+ /**
408
+ * Interface to interact with **gRPC** based services. You can use this interface to instantiate a gRPC generated client.
409
+ */
410
+ export interface RestateGrpcChannel {
411
+ /**
412
+ * Unidirectional call to other Restate services ( = in background / async / not waiting on response).
413
+ * To do this, wrap the call via the proto-ts client with oneWayCall, as shown in the example.
414
+ *
415
+ * NOTE: this returns a Promise because we override the gRPC clients provided by proto-ts.
416
+ * So we are required to return a Promise.
417
+ *
418
+ * @param call Invoke another service by using the generated proto-ts client.
419
+ * @example
420
+ * const ctx = restate.useContext(this);
421
+ * const client = new GreeterClientImpl(ctx);
422
+ * await ctx.oneWayCall(() =>
423
+ * client.greet(Request.create({ name: "Peter" }))
424
+ * )
425
+ */
426
+ oneWayCall(call: () => Promise<any>): Promise<void>;
427
+ /**
428
+ * Delayed unidirectional call to other Restate services ( = in background / async / not waiting on response).
429
+ * To do this, wrap the call via the proto-ts client with delayedCall, as shown in the example.
430
+ * Add the delay in millis as the second parameter.
431
+ *
432
+ * NOTE: this returns a Promise because we override the gRPC clients provided by proto-ts.
433
+ * So we are required to return a Promise.
434
+ *
435
+ * @param call Invoke another service by using the generated proto-ts client.
436
+ * @param delayMillis millisecond delay duration to delay the execution of the call
437
+ * @example
438
+ * const ctx = restate.useContext(this);
439
+ * const client = new GreeterClientImpl(ctx);
440
+ * await ctx.delayedCall(() =>
441
+ * client.greet(Request.create({ name: "Peter" })),
442
+ * 5000
443
+ * )
444
+ */
445
+ delayedCall(call: () => Promise<any>, delayMillis?: number): Promise<void>;
446
+ /**
447
+ * Call another Restate service and await the response.
448
+ *
449
+ * This function is not recommended to be called directly. Instead, use the generated gRPC client
450
+ * that was generated based on the Protobuf service definitions (which internally use this method):
451
+ *
452
+ * @example
453
+ * ```
454
+ * const ctx = restate.useContext(this);
455
+ * const client = new GreeterClientImpl(ctx);
456
+ * client.greet(Request.create({ name: "Peter" }))
457
+ * ```
458
+ *
459
+ * @param service name of the service to call
460
+ * @param method name of the method to call
461
+ * @param data payload as Uint8Array
462
+ * @returns a Promise that is resolved with the response of the called service
463
+ */
464
+ request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
465
+ }
466
+ /**
467
+ * @deprecated use {@link KeyedContext}.
468
+ */
469
+ export type RestateContext = KeyedContext;
470
+ /**
471
+ * Returns the {@link Context} which is the entrypoint for all interaction with Restate.
472
+ * Use this from within a method to retrieve the {@link Context}.
473
+ * The context is bounded to a single invocation.
474
+ *
475
+ * @example
476
+ * const ctx = restate.useContext(this);
477
+ *
478
+ */
479
+ export declare function useContext<T>(instance: T): Context;
480
+ /**
481
+ * Returns the {@link KeyedContext} which is the entrypoint for all interaction with Restate.
482
+ * Use this from within a method of a keyed service to retrieve the {@link KeyedContext}.
483
+ * The context is bounded to a single invocation.
484
+ *
485
+ * @example
486
+ * const ctx = restate.useKeyedContext(this);
487
+ *
488
+ */
489
+ export declare function useKeyedContext<T>(instance: T): KeyedContext;
490
+ /**
491
+ * ServiceApi captures the type and parameters to make RPC calls and send messages to
492
+ * a set of RPC handlers in a router.
493
+ *
494
+ * @example
495
+ * **Service Side:**
496
+ * ```ts
497
+ * const router = restate.router({
498
+ * someAction: async(ctx: restate.RpcContext, req: string) => { ... },
499
+ * anotherAction: async(ctx: restate.RpcContext, count: number) => { ... }
500
+ * });
501
+ *
502
+ * export const myApi: restate.ServiceApi<typeof router> = { path : "myservice" };
503
+ *
504
+ * restate.createServer().bindRouter("myservice", router).listen(9080);
505
+ * ```
506
+ * **Client side:**
507
+ * ```ts
508
+ * ctx.rpc(myApi).someAction("hello!");
509
+ * ```
510
+ */
511
+ export type ServiceApi<_M = unknown> = {
512
+ path: string;
513
+ };
514
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH
4
+ *
5
+ * This file is part of the Restate SDK for Node.js/TypeScript,
6
+ * which is released under the MIT license.
7
+ *
8
+ * You can find a copy of the license in file LICENSE in the root
9
+ * directory of this repository or package, or at
10
+ * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.useKeyedContext = exports.useContext = exports.CombineablePromise = void 0;
14
+ exports.CombineablePromise = {
15
+ /**
16
+ * Creates a Promise that is resolved with an array of results when all of the provided Promises
17
+ * resolve, or rejected when any Promise is rejected.
18
+ *
19
+ * See {@link Promise.all} for more details.
20
+ *
21
+ * @param values An iterable of Promises.
22
+ * @returns A new Promise.
23
+ */
24
+ all(values) {
25
+ if (values.length == 0) {
26
+ return Promise.all(values);
27
+ }
28
+ return values[0].__restate_context.createCombinator(Promise.all.bind(Promise), values);
29
+ },
30
+ /**
31
+ * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
32
+ * or rejected.
33
+ *
34
+ * See {@link Promise.race} for more details.
35
+ *
36
+ * @param values An iterable of Promises.
37
+ * @returns A new Promise.
38
+ */
39
+ race(values) {
40
+ if (values.length == 0) {
41
+ return Promise.race(values);
42
+ }
43
+ return values[0].__restate_context.createCombinator(Promise.race.bind(Promise), values);
44
+ },
45
+ /**
46
+ * Creates a promise that fulfills when any of the input's promises fulfills, with this first fulfillment value.
47
+ * It rejects when all the input's promises reject (including when an empty iterable is passed),
48
+ * with an AggregateError containing an array of rejection reasons.
49
+ *
50
+ * See {@link Promise.any} for more details.
51
+ *
52
+ * @param values An iterable of Promises.
53
+ * @returns A new Promise.
54
+ */
55
+ any(values) {
56
+ if (values.length == 0) {
57
+ return Promise.any(values);
58
+ }
59
+ return values[0].__restate_context.createCombinator(Promise.any.bind(Promise), values);
60
+ },
61
+ /**
62
+ * Creates a promise that fulfills when all the input's promises settle (including when an empty iterable is passed),
63
+ * with an array of objects that describe the outcome of each promise.
64
+ *
65
+ * See {@link Promise.allSettled} for more details.
66
+ *
67
+ * @param values An iterable of Promises.
68
+ * @returns A new Promise.
69
+ */
70
+ allSettled(values) {
71
+ if (values.length == 0) {
72
+ return Promise.allSettled(values);
73
+ }
74
+ return values[0].__restate_context.createCombinator(Promise.allSettled.bind(Promise), values);
75
+ },
76
+ };
77
+ /**
78
+ * Returns the {@link Context} which is the entrypoint for all interaction with Restate.
79
+ * Use this from within a method to retrieve the {@link Context}.
80
+ * The context is bounded to a single invocation.
81
+ *
82
+ * @example
83
+ * const ctx = restate.useContext(this);
84
+ *
85
+ */
86
+ function useContext(instance) {
87
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
+ const wrapper = instance;
89
+ if (wrapper.$$restate === undefined || wrapper.$$restate === null) {
90
+ throw new Error(`not running within a Restate call.`);
91
+ }
92
+ return wrapper.$$restate;
93
+ }
94
+ exports.useContext = useContext;
95
+ /**
96
+ * Returns the {@link KeyedContext} which is the entrypoint for all interaction with Restate.
97
+ * Use this from within a method of a keyed service to retrieve the {@link KeyedContext}.
98
+ * The context is bounded to a single invocation.
99
+ *
100
+ * @example
101
+ * const ctx = restate.useKeyedContext(this);
102
+ *
103
+ */
104
+ function useKeyedContext(instance) {
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
+ const wrapper = instance;
107
+ if (wrapper.$$restate === undefined || wrapper.$$restate === null) {
108
+ throw new Error(`not running within a Restate call.`);
109
+ }
110
+ return wrapper.$$restate;
111
+ }
112
+ exports.useKeyedContext = useKeyedContext;
113
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAgYU,QAAA,kBAAkB,GAAG;IAChC;;;;;;;;OAQG;IACH,GAAG,CACD,MAAS;QAET,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;YACtB,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;SAC5B;QAED,OAAQ,MAAM,CAAC,CAAC,CAAC,CAAC,iBAAiC,CAAC,gBAAgB,CAClE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EACzB,MAAM,CAGN,CAAC;IACL,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,CACF,MAAS;QAET,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;YACtB,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAC7B;QAED,OAAQ,MAAM,CAAC,CAAC,CAAC,CAAC,iBAAiC,CAAC,gBAAgB,CAClE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAC1B,MAAM,CACwB,CAAC;IACnC,CAAC;IAED;;;;;;;;;OASG;IACH,GAAG,CACD,MAAS;QAET,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;YACtB,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;SAC5B;QAED,OAAQ,MAAM,CAAC,CAAC,CAAC,CAAC,iBAAiC,CAAC,gBAAgB,CAClE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EACzB,MAAM,CACwB,CAAC;IACnC,CAAC;IAED;;;;;;;;OAQG;IACH,UAAU,CACR,MAAS;QAIT,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;YACtB,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;SACnC;QAED,OAAQ,MAAM,CAAC,CAAC,CAAC,CAAC,iBAAiC,CAAC,gBAAgB,CAClE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAChC,MAAM,CAGN,CAAC;IACL,CAAC;CACF,CAAC;AA+EF;;;;;;;;GAQG;AACH,SAAgB,UAAU,CAAI,QAAW;IACvC,8DAA8D;IAC9D,MAAM,OAAO,GAAG,QAAe,CAAC;IAChC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,EAAE;QACjE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;KACvD;IACD,OAAO,OAAO,CAAC,SAAS,CAAC;AAC3B,CAAC;AAPD,gCAOC;AAED;;;;;;;;GAQG;AACH,SAAgB,eAAe,CAAI,QAAW;IAC5C,8DAA8D;IAC9D,MAAM,OAAO,GAAG,QAAe,CAAC;IAChC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,EAAE;QACjE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;KACvD;IACD,OAAO,OAAO,CAAC,SAAS,CAAC;AAC3B,CAAC;AAPD,0CAOC"}