@restatedev/restate-sdk-testcontainers 1.11.0 → 1.12.0

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 (44) hide show
  1. package/dist/index.d.cts +4 -3
  2. package/dist/index.d.ts +4 -3
  3. package/dist/restate-sdk/src/common_api.d.ts +3 -1
  4. package/dist/restate-sdk/src/context.d.cts +16 -2
  5. package/dist/restate-sdk/src/context.d.cts.map +1 -1
  6. package/dist/restate-sdk/src/context.d.ts +16 -2
  7. package/dist/restate-sdk/src/context.d.ts.map +1 -1
  8. package/dist/restate-sdk/src/context_impl.d.ts +2 -0
  9. package/dist/restate-sdk/src/endpoint/endpoint.d.ts +1 -0
  10. package/dist/restate-sdk/src/endpoint/handlers/types.d.ts +1 -0
  11. package/dist/restate-sdk/src/endpoint/types.d.cts +1 -2
  12. package/dist/restate-sdk/src/endpoint/types.d.cts.map +1 -1
  13. package/dist/restate-sdk/src/endpoint/types.d.ts +1 -1
  14. package/dist/restate-sdk/src/endpoint.d.cts +87 -5
  15. package/dist/restate-sdk/src/endpoint.d.cts.map +1 -1
  16. package/dist/restate-sdk/src/endpoint.d.ts +87 -5
  17. package/dist/restate-sdk/src/endpoint.d.ts.map +1 -1
  18. package/dist/restate-sdk/src/hooks.d.cts +87 -0
  19. package/dist/restate-sdk/src/hooks.d.cts.map +1 -0
  20. package/dist/restate-sdk/src/hooks.d.ts +87 -0
  21. package/dist/restate-sdk/src/hooks.d.ts.map +1 -0
  22. package/dist/restate-sdk/src/index.d.cts +2 -1
  23. package/dist/restate-sdk/src/index.d.ts +2 -1
  24. package/dist/restate-sdk/src/io.d.ts +1 -0
  25. package/dist/restate-sdk/src/node.d.cts +2 -2
  26. package/dist/restate-sdk/src/node.d.ts +2 -1
  27. package/dist/restate-sdk/src/promises.d.ts +2 -0
  28. package/dist/restate-sdk/src/types/errors.d.cts +0 -4
  29. package/dist/restate-sdk/src/types/errors.d.cts.map +1 -1
  30. package/dist/restate-sdk/src/types/errors.d.ts +0 -4
  31. package/dist/restate-sdk/src/types/errors.d.ts.map +1 -1
  32. package/dist/restate-sdk/src/types/rpc.d.cts +63 -0
  33. package/dist/restate-sdk/src/types/rpc.d.cts.map +1 -1
  34. package/dist/restate-sdk/src/types/rpc.d.ts +63 -0
  35. package/dist/restate-sdk/src/types/rpc.d.ts.map +1 -1
  36. package/dist/restate_test_environment.cjs +32 -2
  37. package/dist/restate_test_environment.d.cts +29 -3
  38. package/dist/restate_test_environment.d.cts.map +1 -1
  39. package/dist/restate_test_environment.d.ts +29 -3
  40. package/dist/restate_test_environment.d.ts.map +1 -1
  41. package/dist/restate_test_environment.js +32 -2
  42. package/dist/restate_test_environment.js.map +1 -1
  43. package/package.json +4 -4
  44. package/dist/restate-sdk/src/common_api.d.cts +0 -10
@@ -3,10 +3,10 @@ import { Serde } from "../../restate-sdk-core/src/serde_api.cjs";
3
3
  import { Duration } from "../../restate-sdk-core/src/duration.cjs";
4
4
  import { JournalValueCodec } from "../../restate-sdk-core/src/entry_codec.cjs";
5
5
  import { RestateError, TerminalError } from "./types/errors.cjs";
6
+ import { Hooks, HooksProvider, Interceptor } from "./hooks.cjs";
6
7
  import { ObjectOptions, RetryPolicy, ServiceOptions, WorkflowOptions } from "./types/rpc.cjs";
7
- import { Request, TypedState, UntypedState } from "./context.cjs";
8
+ import { InvocationId, Request, Target, TypedState, UntypedState } from "./context.cjs";
8
9
  import { LogMetadata, LogSource, LoggerContext, LoggerTransport, RestateLogLevel } from "./logging/logger_transport.cjs";
9
10
  import { DefaultServiceOptions, RestateEndpoint, RestateEndpointBase } from "./endpoint.cjs";
10
11
  import { EndpointOptions } from "./endpoint/types.cjs";
11
- import "./common_api.cjs";
12
12
  import "http2";
@@ -3,8 +3,9 @@ import { Serde } from "../../restate-sdk-core/src/serde_api.js";
3
3
  import { Duration } from "../../restate-sdk-core/src/duration.js";
4
4
  import { JournalValueCodec } from "../../restate-sdk-core/src/entry_codec.js";
5
5
  import { RestateError, TerminalError } from "./types/errors.js";
6
+ import { Hooks, HooksProvider, Interceptor } from "./hooks.js";
6
7
  import { ObjectOptions, RetryPolicy, ServiceOptions, WorkflowOptions } from "./types/rpc.js";
7
- import { Request, TypedState, UntypedState } from "./context.js";
8
+ import { InvocationId, Request, Target, TypedState, UntypedState } from "./context.js";
8
9
  import { LogMetadata, LogSource, LoggerContext, LoggerTransport, RestateLogLevel } from "./logging/logger_transport.js";
9
10
  import { DefaultServiceOptions, RestateEndpoint, RestateEndpointBase } from "./endpoint.js";
10
11
  import { EndpointOptions } from "./endpoint/types.js";
@@ -0,0 +1,2 @@
1
+ import "./context_impl.js";
2
+ import "./io.js";
@@ -21,10 +21,6 @@ declare class TerminalError extends RestateError {
21
21
  * Error code. This should be an HTTP status code, and in case the service was invoked from the ingress, this will be propagated back to the caller.
22
22
  */
23
23
  errorCode?: number;
24
- /**
25
- * @deprecated YOU MUST NOT USE THIS FIELD, AS IT WON'T BE RECORDED AND CAN LEAD TO NON-DETERMINISM! From the next SDK version, the constructor won't accept this field anymore.
26
- */
27
- cause?: any;
28
24
  /**
29
25
  * Metadata key-value pairs to attach to the terminal error.
30
26
  * These will be recorded together with error message and code.
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.cts","names":[],"sources":["../../../../../restate-sdk/src/types/errors.ts"],"sourcesContent":[],"mappings":";;cA6Ea,YAAA,SAAqB,KAAA;;;;;;;;;;;;;cAerB,aAAA,SAAsB,YAAA;;sBAEN;;;;;;;;;;;;;;;;eAmBZ"}
1
+ {"version":3,"file":"errors.d.cts","names":[],"sources":["../../../../../restate-sdk/src/types/errors.ts"],"sourcesContent":[],"mappings":";;cA6Ea,YAAA,SAAqB,KAAA;;;;;;;;;;;;;cAerB,aAAA,SAAsB,YAAA;;sBAEN;;;;;;;;;;;;eAeZ"}
@@ -21,10 +21,6 @@ declare class TerminalError extends RestateError {
21
21
  * Error code. This should be an HTTP status code, and in case the service was invoked from the ingress, this will be propagated back to the caller.
22
22
  */
23
23
  errorCode?: number;
24
- /**
25
- * @deprecated YOU MUST NOT USE THIS FIELD, AS IT WON'T BE RECORDED AND CAN LEAD TO NON-DETERMINISM! From the next SDK version, the constructor won't accept this field anymore.
26
- */
27
- cause?: any;
28
24
  /**
29
25
  * Metadata key-value pairs to attach to the terminal error.
30
26
  * These will be recorded together with error message and code.
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","names":[],"sources":["../../../../../restate-sdk/src/types/errors.ts"],"sourcesContent":[],"mappings":";;cA6Ea,YAAA,SAAqB,KAAA;;;;;;;;;;;;;cAerB,aAAA,SAAsB,YAAA;;sBAEN;;;;;;;;;;;;;;;;eAmBZ"}
1
+ {"version":3,"file":"errors.d.ts","names":[],"sources":["../../../../../restate-sdk/src/types/errors.ts"],"sourcesContent":[],"mappings":";;cA6Ea,YAAA,SAAqB,KAAA;;;;;;;;;;;;;cAerB,aAAA,SAAsB,YAAA;;sBAEN;;;;;;;;;;;;eAeZ"}
@@ -1,6 +1,7 @@
1
1
  import { Serde } from "../../../restate-sdk-core/src/serde_api.cjs";
2
2
  import { Duration } from "../../../restate-sdk-core/src/duration.cjs";
3
3
  import { TerminalError } from "./errors.cjs";
4
+ import { HooksProvider } from "../hooks.cjs";
4
5
 
5
6
  //#region ../restate-sdk/src/types/rpc.d.ts
6
7
 
@@ -129,6 +130,68 @@ type ServiceOptions = {
129
130
  * If not provided, defaults to `serde.json`.
130
131
  */
131
132
  serde?: Serde<any>;
133
+ /**
134
+ * Hooks providers for this service. Service-level hooks wrap outermost —
135
+ * they run before handler-level hooks. Both levels are merged: service
136
+ * hooks first, then handler hooks. Within each level, hooks execute in
137
+ * array order: for `[A, B]`: A before → B before → handler → B after → A after.
138
+ *
139
+ * The `handler` interceptor fires on every attempt. The `run` interceptor
140
+ * fires only when the `ctx.run()` closure actually executes — replayed
141
+ * runs (already in the journal) are skipped.
142
+ *
143
+ * Errors thrown at any point (before or after `next()`) affect the invocation:
144
+ * {@link TerminalError} fails immediately, any other error triggers a retry.
145
+ * On suspension or pause, `next()` also rejects — do any cleanup and rethrow.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * const myService = restate.service({
150
+ * name: "MyService",
151
+ * handlers: { greet: async (ctx, name) => `Hello, ${name}!` },
152
+ * options: {
153
+ * hooks: [
154
+ * (ctx) => ({
155
+ * interceptor: {
156
+ * handler: async (next) => {
157
+ * console.log(`before ${ctx.request.target}`);
158
+ * try {
159
+ * await next();
160
+ * console.log(`after ${ctx.request.target}`);
161
+ * } catch (e) {
162
+ * console.log(`error ${ctx.request.target}: ${e}`);
163
+ * // Always rethrow — swallowing the error changes the
164
+ * // invocation outcome. You can also throw a different
165
+ * // error (e.g. TerminalError to fail immediately).
166
+ * throw e;
167
+ * }
168
+ * },
169
+ * run: async (name, next) => {
170
+ * console.log(` before run "${name}"`);
171
+ * try {
172
+ * await next();
173
+ * console.log(` after run "${name}"`);
174
+ * } catch (e) {
175
+ * console.log(` error run "${name}": ${e}`);
176
+ * throw e;
177
+ * }
178
+ * },
179
+ * },
180
+ * }),
181
+ * ],
182
+ * },
183
+ * });
184
+ * ```
185
+ */
186
+ hooks?: HooksProvider[];
187
+ /**
188
+ * When set to `true`, the SDK will stop automatically propagating cancellations when awaiting {@link RestatePromise}s.
189
+ *
190
+ * Instead, the user code must explicitly listen to cancellations using the `ctx.cancellation()` API in {@link ContextInternal}.
191
+ *
192
+ * @experimental
193
+ */
194
+ explicitCancellation?: boolean;
132
195
  };
133
196
  type ObjectOptions = ServiceOptions & {
134
197
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"rpc.d.cts","names":[],"sources":["../../../../../restate-sdk/src/types/rpc.ts"],"sourcesContent":[],"mappings":";;;;;;KAwvBY,WAAA;;;;;;;;;;;;;;;;;;;;oBAsBQ;;;;;;;gBAQJ;;;;;;KAQJ,cAAA;;;;;;yBAMa;;;;;;;;qBASJ;;;;;;;;;;;sBAYC;;;;;;;;;;;;iBAaL;;;;;;;;;;;gBAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCAsCoB;;;;;;UAO1B;;KA8FE,aAAA,GAAgB;;;;;;;;;KA4HhB,eAAA,GAAkB;;;;;;;sBAOR"}
1
+ {"version":3,"file":"rpc.d.cts","names":[],"sources":["../../../../../restate-sdk/src/types/rpc.ts"],"sourcesContent":[],"mappings":";;;;;;;KA+0BY,WAAA;;;;;;;;;;;;;;;;;;;;oBAsBQ;;;;;;;gBAQJ;;;;;;KAQJ,cAAA;;;;;;yBAMa;;;;;;;;qBASJ;;;;;;;;;;;sBAYC;;;;;;;;;;;;iBAaL;;;;;;;;;;;gBAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCAsCoB;;;;;;UAO1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAuDA;;;;;;;;;;KAuGE,aAAA,GAAgB;;;;;;;;;KA4HhB,eAAA,GAAkB;;;;;;;sBAOR"}
@@ -1,6 +1,7 @@
1
1
  import { Serde } from "../../../restate-sdk-core/src/serde_api.js";
2
2
  import { Duration } from "../../../restate-sdk-core/src/duration.js";
3
3
  import { TerminalError } from "./errors.js";
4
+ import { HooksProvider } from "../hooks.js";
4
5
 
5
6
  //#region ../restate-sdk/src/types/rpc.d.ts
6
7
 
@@ -129,6 +130,68 @@ type ServiceOptions = {
129
130
  * If not provided, defaults to `serde.json`.
130
131
  */
131
132
  serde?: Serde<any>;
133
+ /**
134
+ * Hooks providers for this service. Service-level hooks wrap outermost —
135
+ * they run before handler-level hooks. Both levels are merged: service
136
+ * hooks first, then handler hooks. Within each level, hooks execute in
137
+ * array order: for `[A, B]`: A before → B before → handler → B after → A after.
138
+ *
139
+ * The `handler` interceptor fires on every attempt. The `run` interceptor
140
+ * fires only when the `ctx.run()` closure actually executes — replayed
141
+ * runs (already in the journal) are skipped.
142
+ *
143
+ * Errors thrown at any point (before or after `next()`) affect the invocation:
144
+ * {@link TerminalError} fails immediately, any other error triggers a retry.
145
+ * On suspension or pause, `next()` also rejects — do any cleanup and rethrow.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * const myService = restate.service({
150
+ * name: "MyService",
151
+ * handlers: { greet: async (ctx, name) => `Hello, ${name}!` },
152
+ * options: {
153
+ * hooks: [
154
+ * (ctx) => ({
155
+ * interceptor: {
156
+ * handler: async (next) => {
157
+ * console.log(`before ${ctx.request.target}`);
158
+ * try {
159
+ * await next();
160
+ * console.log(`after ${ctx.request.target}`);
161
+ * } catch (e) {
162
+ * console.log(`error ${ctx.request.target}: ${e}`);
163
+ * // Always rethrow — swallowing the error changes the
164
+ * // invocation outcome. You can also throw a different
165
+ * // error (e.g. TerminalError to fail immediately).
166
+ * throw e;
167
+ * }
168
+ * },
169
+ * run: async (name, next) => {
170
+ * console.log(` before run "${name}"`);
171
+ * try {
172
+ * await next();
173
+ * console.log(` after run "${name}"`);
174
+ * } catch (e) {
175
+ * console.log(` error run "${name}": ${e}`);
176
+ * throw e;
177
+ * }
178
+ * },
179
+ * },
180
+ * }),
181
+ * ],
182
+ * },
183
+ * });
184
+ * ```
185
+ */
186
+ hooks?: HooksProvider[];
187
+ /**
188
+ * When set to `true`, the SDK will stop automatically propagating cancellations when awaiting {@link RestatePromise}s.
189
+ *
190
+ * Instead, the user code must explicitly listen to cancellations using the `ctx.cancellation()` API in {@link ContextInternal}.
191
+ *
192
+ * @experimental
193
+ */
194
+ explicitCancellation?: boolean;
132
195
  };
133
196
  type ObjectOptions = ServiceOptions & {
134
197
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"rpc.d.ts","names":[],"sources":["../../../../../restate-sdk/src/types/rpc.ts"],"sourcesContent":[],"mappings":";;;;;;KAwvBY,WAAA;;;;;;;;;;;;;;;;;;;;oBAsBQ;;;;;;;gBAQJ;;;;;;KAQJ,cAAA;;;;;;yBAMa;;;;;;;;qBASJ;;;;;;;;;;;sBAYC;;;;;;;;;;;;iBAaL;;;;;;;;;;;gBAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCAsCoB;;;;;;UAO1B;;KA8FE,aAAA,GAAgB;;;;;;;;;KA4HhB,eAAA,GAAkB;;;;;;;sBAOR"}
1
+ {"version":3,"file":"rpc.d.ts","names":[],"sources":["../../../../../restate-sdk/src/types/rpc.ts"],"sourcesContent":[],"mappings":";;;;;;;KA+0BY,WAAA;;;;;;;;;;;;;;;;;;;;oBAsBQ;;;;;;;gBAQJ;;;;;;KAQJ,cAAA;;;;;;yBAMa;;;;;;;;qBASJ;;;;;;;;;;;sBAYC;;;;;;;;;;;;iBAaL;;;;;;;;;;;gBAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCAsCoB;;;;;;UAO1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAuDA;;;;;;;;;;KAuGE,aAAA,GAAgB;;;;;;;;;KA4HhB,eAAA,GAAkB;;;;;;;sBAOR"}
@@ -110,15 +110,45 @@ var RestateTestEnvironment = class RestateTestEnvironment {
110
110
  await this.startedRestateContainer.stop();
111
111
  this.startedRestateHttpServer.close();
112
112
  }
113
- static async start(param, restateContainerFactory = () => new RestateContainer()) {
113
+ static async start(param, restateContainerFactory) {
114
+ let containerFactory;
115
+ if (restateContainerFactory) containerFactory = restateContainerFactory;
116
+ else if (typeof param !== "function") containerFactory = () => {
117
+ const container = new RestateContainer();
118
+ if (param.alwaysReplay) container.alwaysReplay();
119
+ if (param.disableRetries) container.disableRetries();
120
+ return container;
121
+ };
122
+ else containerFactory = () => new RestateContainer();
114
123
  const startedRestateHttpServer = typeof param === "function" ? await prepareRestateEndpoint(param) : await prepareRestateEndpoint(param);
115
- return new RestateTestEnvironment(startedRestateHttpServer, await prepareRestateTestContainer(startedRestateHttpServer.address().port, restateContainerFactory));
124
+ return new RestateTestEnvironment(startedRestateHttpServer, await prepareRestateTestContainer(startedRestateHttpServer.address().port, containerFactory));
116
125
  }
117
126
  };
118
127
  var RestateContainer = class extends testcontainers.GenericContainer {
119
128
  constructor(version = "latest") {
120
129
  super(`docker.io/restatedev/restate:${version}`);
121
130
  }
131
+ /**
132
+ * Forces restate-server to always replay on a suspension point.
133
+ * This is useful to hunt non-deterministic bugs that might prevent
134
+ * your code from replaying correctly.
135
+ */
136
+ alwaysReplay() {
137
+ this.withEnvironment({ RESTATE_WORKER__INVOKER__INACTIVITY_TIMEOUT: "0s" });
138
+ return this;
139
+ }
140
+ /**
141
+ * Disables retries in the restate-server invoker.
142
+ * This is useful in tests so that failures surface immediately
143
+ * instead of hanging through retry backoff.
144
+ */
145
+ disableRetries() {
146
+ this.withEnvironment({
147
+ RESTATE_DEFAULT_RETRY_POLICY__MAX_ATTEMPTS: "1",
148
+ RESTATE_DEFAULT_RETRY_POLICY__ON_MAX_ATTEMPTS: "kill"
149
+ });
150
+ return this;
151
+ }
122
152
  };
123
153
  var StateProxy = class {
124
154
  constructor(adminAPIBaseUrl, service, serviceKey) {
@@ -8,6 +8,20 @@ import * as http2 from "http2";
8
8
  import { GenericContainer, StartedTestContainer } from "testcontainers";
9
9
 
10
10
  //#region src/restate_test_environment.d.ts
11
+ interface TestEnvironmentOptions extends EndpointOptions {
12
+ /**
13
+ * Forces restate-server to always replay on a suspension point.
14
+ * This is useful to hunt non-deterministic bugs that might prevent
15
+ * your code from replaying correctly.
16
+ */
17
+ alwaysReplay?: boolean;
18
+ /**
19
+ * Disables retries in the restate-server invoker.
20
+ * This is useful in tests so that failures surface immediately
21
+ * instead of hanging through retry backoff.
22
+ */
23
+ disableRetries?: boolean;
24
+ }
11
25
  declare class RestateTestEnvironment {
12
26
  readonly startedRestateHttpServer: http2.Http2Server;
13
27
  readonly startedRestateContainer: StartedTestContainer;
@@ -18,17 +32,29 @@ declare class RestateTestEnvironment {
18
32
  stop(): Promise<void>;
19
33
  /**
20
34
  *
21
- * @deprecated Please use {@link EndpointOptions} instead of this.
35
+ * @deprecated Please use {@link TestEnvironmentOptions} instead of this.
22
36
  * @example
23
37
  * ```
24
38
  * RestateTestEnvironment.start({ services: [mysService] })
25
39
  * ```
26
40
  */
27
41
  static start(mountServicesFn: (server: RestateEndpoint) => void, restateContainerFactory?: () => GenericContainer): Promise<RestateTestEnvironment>;
28
- static start(options: EndpointOptions, restateContainerFactory?: () => GenericContainer): Promise<RestateTestEnvironment>;
42
+ static start(options: TestEnvironmentOptions, restateContainerFactory?: () => GenericContainer): Promise<RestateTestEnvironment>;
29
43
  }
30
44
  declare class RestateContainer extends GenericContainer {
31
45
  constructor(version?: string);
46
+ /**
47
+ * Forces restate-server to always replay on a suspension point.
48
+ * This is useful to hunt non-deterministic bugs that might prevent
49
+ * your code from replaying correctly.
50
+ */
51
+ alwaysReplay(): this;
52
+ /**
53
+ * Disables retries in the restate-server invoker.
54
+ * This is useful in tests so that failures surface immediately
55
+ * instead of hanging through retry backoff.
56
+ */
57
+ disableRetries(): this;
32
58
  }
33
59
  declare class StateProxy<TState extends TypedState> {
34
60
  private adminAPIBaseUrl;
@@ -43,5 +69,5 @@ declare class StateProxy<TState extends TypedState> {
43
69
  private setAllRaw;
44
70
  }
45
71
  //#endregion
46
- export { RestateContainer, RestateTestEnvironment, StateProxy };
72
+ export { RestateContainer, RestateTestEnvironment, StateProxy, TestEnvironmentOptions };
47
73
  //# sourceMappingURL=restate_test_environment.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"restate_test_environment.d.cts","names":[],"sources":["../src/restate_test_environment.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAkNa,sBAAA;qCAE0B,KAAA,CAAM;oCACP;wCADC,KAAA,CAAM,sCACP;;;yBAgBN,aAAa,uBAErC,2CACA,mDAEH,WAAW;EAxBH,IAAA,CAAA,CAAA,EA4BM,OA5BN,CAAA,IAAA,CAAA;EAE0B;;;;;;;;EAsBvB,OAAA,KAAA,CAAA,eAAA,EAAA,CAAA,MAAA,EAkBc,eAlBd,EAAA,GAAA,IAAA,EAAA,uBAAA,CAAA,EAAA,GAAA,GAmBoB,gBAnBpB,CAAA,EAoBX,OApBW,CAoBH,sBApBG,CAAA;EAAX,OAAA,KAAA,CAAA,OAAA,EAsBQ,eAtBR,EAAA,uBAAA,CAAA,EAAA,GAAA,GAuB+B,gBAvB/B,CAAA,EAwBA,OAxBA,CAwBQ,sBAxBR,CAAA;;AAkByB,cA2BjB,gBAAA,SAAyB,gBAAA,CA3BR;EACM,WAAA,CAAA,OAAA,CAAA,EAAA,MAAA;;AAC/B,cA8BQ,UA9BR,CAAA,eA8BkC,UA9BlC,CAAA,CAAA;EAEQ,QAAA,eAAA;EACuB,QAAA,OAAA;EACvB,QAAA,UAAA;EAAR,WAAA,CAAA,eAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA;EAAO,GAAA,CAAA,MAAA,EAAA,aAAA,MAkCkC,MAlClC,GAAA,MAAA,CAAA,CAAA,IAAA,EAmCF,MAnCE,SAmCa,YAnCb,GAAA,MAAA,GAmCqC,IAnCrC,EAAA,KAAA,CAAA,EAoCA,KApCA,CAoCM,MApCN,SAoCqB,YApCrB,GAoCoC,MApCpC,GAoC6C,MApC7C,CAoCoD,IApCpD,CAAA,CAAA,CAAA,EAqCP,OArCO,CAAA,CAqCE,MArCF,SAqCiB,YArCjB,GAqCgC,MArChC,GAqCyC,MArCzC,CAqCgD,IArChD,CAAA,CAAA,GAAA,IAAA,CAAA;EAqBC,MAAA,CAAA,gBAkDyB,UAlDA,CAAA,CAAA,KAAgB,CAAhB,EAmD1B,KAnD0C,CAoDhD,MApDgD,SAoDjC,YApDiC,GAqD5C,OArD4C,CAAA,MAqD9B,OArD8B,CAAA,GAsD5C,MAtD4C,CAAA,MAsD/B,MAtD+B,CAAA,CAAA,CAAA,EAwDjD,OAxDiD,CAwDzC,MAxDyC,SAwD1B,YAxD0B,GAwDX,OAxDW,GAwDD,MAxDC,CAAA;EAKzC,QAAA,SAAU;EAAgB,GAAA,CAAA,MAAA,EAAA,aAAA,MA6FO,MA7FP,GAAA,MAAA,CAAA,CAAA,IAAA,EA8F7B,MA9F6B,SA8Fd,YA9Fc,GAAA,MAAA,GA8FU,IA9FV,EAAA,KAAA,EA+F5B,MA/F4B,SA+Fb,YA/Fa,GA+FE,MA/FF,GA+FW,MA/FX,CA+FkB,IA/FlB,CAAA,EAAA,KAAA,CAAA,EAgG3B,KAhG2B,CAgGrB,MAhGqB,SAgGN,YAhGM,GAgGS,MAhGT,GAgGkB,MAhGlB,CAgGyB,IAhGzB,CAAA,CAAA,CAAA,EAiGlC,OAjGkC,CAAA,IAAA,CAAA;EAQO,MAAA,CAAA,gBAuGR,UAvGQ,CAAA,CAAA,MAAA,EAwGlC,MAxGkC,SAwGnB,YAxGmB,GAwGJ,OAxGI,GAwGM,MAxGN,EAAA,KAAA,CAAA,EAyGlC,KAzGkC,CA0GxC,MA1GwC,SA0GzB,YA1GyB,GA2GpC,OA3GoC,CAAA,MA2GtB,OA3GsB,CAAA,GA4GpC,MA5GoC,CAAA,MA4GvB,MA5GuB,CAAA,CAAA,CAAA,EA6GzC,OA7GyC,CAAA,IAAA,CAAA;EACpC,QAAA,SAAA"}
1
+ {"version":3,"file":"restate_test_environment.d.cts","names":[],"sources":["../src/restate_test_environment.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;UAkNiB,sBAAA,SAA+B;;;;;;;EAA/B;AAgBjB;;;;EAGsC,cAAA,CAAA,EAAA,OAAA;;AAgBO,cAnBhC,sBAAA,CAmBgC;EAErC,SAAA,wBAAA,EAnB+B,KAAA,CAAM,WAmBrC;EACA,SAAA,uBAAA,EAnB8B,oBAmB9B;EAEQ,WAAA,CAAA,wBAAA,EAtBuB,KAAA,CAAM,WAsB7B,EAAA,uBAAA,EArBsB,oBAqBtB;EAAX,OAAA,CAAA,CAAA,EAAA,MAAA;EAIc,eAAA,CAAA,CAAA,EAAA,MAAA;EAcW,OAAA,CAAA,eAvBE,UAuBF,GAvBe,YAuBf,CAAA,CAAA,OAAA,EArBtB,uBAqBsB,CAAA,MAAA,EAAA,OAAA,CAAA,GApBtB,kBAoBsB,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,EAAA,MAAA,CAAA,EAlBzB,UAkByB,CAlBd,MAkBc,CAAA;EACM,IAAA,CAAA,CAAA,EAfjB,OAeiB,CAAA,IAAA,CAAA;EACvB;;;;;;;AA0Cb;EA8Ba,OAAA,KAAA,CAAU,eAAA,EAAA,CAAA,MAAA,EA1EO,eA0EP,EAAA,GAAA,IAAA,EAAA,uBAAA,CAAA,EAAA,GAAA,GAzEa,gBAyEb,CAAA,EAxElB,OAwEkB,CAxEV,sBAwEU,CAAA;EAAgB,OAAA,KAAA,CAAA,OAAA,EAtE1B,sBAsE0B,EAAA,uBAAA,CAAA,EAAA,GAAA,GArEH,gBAqEG,CAAA,EApElC,OAoEkC,CApE1B,sBAoE0B,CAAA;;AAS7B,cAvCG,gBAAA,SAAyB,gBAAA,CAuC5B;EAAe,WAAA,CAAA,OAAA,CAAA,EAAA,MAAA;EAAwB;;;;;EACe,YAAA,CAAA,CAAA,EAAA,IAAA;EAApD;;;;;EACgD,cAAA,CAAA,CAAA,EAAA,IAAA;;AAkCtB,cA7CzB,UA6CyB,CAAA,eA7CC,UA6CD,CAAA,CAAA;EAEhC,QAAA,eAAA;EAAe,QAAA,OAAA;EACX,QAAA,UAAA;EAAc,WAAA,CAAA,eAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA;EACd,GAAA,CAAA,MAAA,EAAA,aAAA,MAzCoC,MAyCpC,GAAA,MAAA,CAAA,CAAA,IAAA,EAxCA,MAwCA,SAxCe,YAwCf,GAAA,MAAA,GAxCuC,IAwCvC,EAAA,KAAA,CAAA,EAvCE,KAuCF,CAvCQ,MAuCR,SAvCuB,YAuCvB,GAvCsC,MAuCtC,GAvC+C,MAuC/C,CAvCsD,IAuCtD,CAAA,CAAA,CAAA,EAtCL,OAsCK,CAAA,CAtCI,MAsCJ,SAtCmB,YAsCnB,GAtCkC,MAsClC,GAtC2C,MAsC3C,CAtCkD,IAsClD,CAAA,CAAA,GAAA,IAAA,CAAA;EAAa,MAAA,CAAA,gBAJe,UAIf,CAAA,CAAA,KAAA,CAAA,EAHX,KAGW,CAFjB,MAEiB,SAFF,YAEE,GADb,OACa,CAAA,MADC,OACD,CAAA,GAAb,MAAa,CAAA,MAAA,MAAA,CAAA,CAAA,CAAA,EAElB,OAFkB,CAEV,MAFU,SAEK,YAFL,GAEoB,OAFpB,GAE8B,MAF9B,CAAA;EAHX,QAAA,SAAA;EAKC,GAAA,CAAA,MAAA,EAAA,aAAA,MA0CiC,MA1CjC,GAAA,MAAA,CAAA,CAAA,IAAA,EA2CH,MA3CG,SA2CY,YA3CZ,GAAA,MAAA,GA2CoC,IA3CpC,EAAA,KAAA,EA4CF,MA5CE,SA4Ca,YA5Cb,GA4C4B,MA5C5B,GA4CqC,MA5CrC,CA4C4C,IA5C5C,CAAA,EAAA,KAAA,CAAA,EA6CD,KA7CC,CA6CK,MA7CL,SA6CoB,YA7CpB,GA6CmC,MA7CnC,GA6C4C,MA7C5C,CA6CmD,IA7CnD,CAAA,CAAA,CAAA,EA8CR,OA9CQ,CAAA,IAAA,CAAA;EAAe,MAAA,CAAA,gBA4DU,UA5DV,CAAA,CAAA,MAAA,EA6DhB,MA7DgB,SA6DD,YA7DC,GA6Dc,OA7Dd,GA6DwB,MA7DxB,EAAA,KAAA,CAAA,EA8DhB,KA9DgB,CA+DtB,MA/DsB,SA+DP,YA/DO,GAgElB,OAhEkB,CAAA,MAgEJ,OAhEI,CAAA,GAiElB,MAjEkB,CAAA,MAiEL,MAjEK,CAAA,CAAA,CAAA,EAkEvB,OAlEuB,CAAA,IAAA,CAAA;EAAe,QAAA,SAAA"}
@@ -8,6 +8,20 @@ import { GenericContainer, StartedTestContainer } from "testcontainers";
8
8
  import * as http2 from "http2";
9
9
 
10
10
  //#region src/restate_test_environment.d.ts
11
+ interface TestEnvironmentOptions extends EndpointOptions {
12
+ /**
13
+ * Forces restate-server to always replay on a suspension point.
14
+ * This is useful to hunt non-deterministic bugs that might prevent
15
+ * your code from replaying correctly.
16
+ */
17
+ alwaysReplay?: boolean;
18
+ /**
19
+ * Disables retries in the restate-server invoker.
20
+ * This is useful in tests so that failures surface immediately
21
+ * instead of hanging through retry backoff.
22
+ */
23
+ disableRetries?: boolean;
24
+ }
11
25
  declare class RestateTestEnvironment {
12
26
  readonly startedRestateHttpServer: http2.Http2Server;
13
27
  readonly startedRestateContainer: StartedTestContainer;
@@ -18,17 +32,29 @@ declare class RestateTestEnvironment {
18
32
  stop(): Promise<void>;
19
33
  /**
20
34
  *
21
- * @deprecated Please use {@link EndpointOptions} instead of this.
35
+ * @deprecated Please use {@link TestEnvironmentOptions} instead of this.
22
36
  * @example
23
37
  * ```
24
38
  * RestateTestEnvironment.start({ services: [mysService] })
25
39
  * ```
26
40
  */
27
41
  static start(mountServicesFn: (server: RestateEndpoint) => void, restateContainerFactory?: () => GenericContainer): Promise<RestateTestEnvironment>;
28
- static start(options: EndpointOptions, restateContainerFactory?: () => GenericContainer): Promise<RestateTestEnvironment>;
42
+ static start(options: TestEnvironmentOptions, restateContainerFactory?: () => GenericContainer): Promise<RestateTestEnvironment>;
29
43
  }
30
44
  declare class RestateContainer extends GenericContainer {
31
45
  constructor(version?: string);
46
+ /**
47
+ * Forces restate-server to always replay on a suspension point.
48
+ * This is useful to hunt non-deterministic bugs that might prevent
49
+ * your code from replaying correctly.
50
+ */
51
+ alwaysReplay(): this;
52
+ /**
53
+ * Disables retries in the restate-server invoker.
54
+ * This is useful in tests so that failures surface immediately
55
+ * instead of hanging through retry backoff.
56
+ */
57
+ disableRetries(): this;
32
58
  }
33
59
  declare class StateProxy<TState extends TypedState> {
34
60
  private adminAPIBaseUrl;
@@ -43,5 +69,5 @@ declare class StateProxy<TState extends TypedState> {
43
69
  private setAllRaw;
44
70
  }
45
71
  //#endregion
46
- export { RestateContainer, RestateTestEnvironment, StateProxy };
72
+ export { RestateContainer, RestateTestEnvironment, StateProxy, TestEnvironmentOptions };
47
73
  //# sourceMappingURL=restate_test_environment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"restate_test_environment.d.ts","names":[],"sources":["../src/restate_test_environment.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAkNa,sBAAA;qCAE0B,KAAA,CAAM;oCACP;wCADC,KAAA,CAAM,sCACP;;;yBAgBN,aAAa,uBAErC,2CACA,mDAEH,WAAW;EAxBH,IAAA,CAAA,CAAA,EA4BM,OA5BN,CAAA,IAAA,CAAA;EAE0B;;;;;;;;EAsBvB,OAAA,KAAA,CAAA,eAAA,EAAA,CAAA,MAAA,EAkBc,eAlBd,EAAA,GAAA,IAAA,EAAA,uBAAA,CAAA,EAAA,GAAA,GAmBoB,gBAnBpB,CAAA,EAoBX,OApBW,CAoBH,sBApBG,CAAA;EAAX,OAAA,KAAA,CAAA,OAAA,EAsBQ,eAtBR,EAAA,uBAAA,CAAA,EAAA,GAAA,GAuB+B,gBAvB/B,CAAA,EAwBA,OAxBA,CAwBQ,sBAxBR,CAAA;;AAkByB,cA2BjB,gBAAA,SAAyB,gBAAA,CA3BR;EACM,WAAA,CAAA,OAAA,CAAA,EAAA,MAAA;;AAC/B,cA8BQ,UA9BR,CAAA,eA8BkC,UA9BlC,CAAA,CAAA;EAEQ,QAAA,eAAA;EACuB,QAAA,OAAA;EACvB,QAAA,UAAA;EAAR,WAAA,CAAA,eAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA;EAAO,GAAA,CAAA,MAAA,EAAA,aAAA,MAkCkC,MAlClC,GAAA,MAAA,CAAA,CAAA,IAAA,EAmCF,MAnCE,SAmCa,YAnCb,GAAA,MAAA,GAmCqC,IAnCrC,EAAA,KAAA,CAAA,EAoCA,KApCA,CAoCM,MApCN,SAoCqB,YApCrB,GAoCoC,MApCpC,GAoC6C,MApC7C,CAoCoD,IApCpD,CAAA,CAAA,CAAA,EAqCP,OArCO,CAAA,CAqCE,MArCF,SAqCiB,YArCjB,GAqCgC,MArChC,GAqCyC,MArCzC,CAqCgD,IArChD,CAAA,CAAA,GAAA,IAAA,CAAA;EAqBC,MAAA,CAAA,gBAkDyB,UAlDA,CAAA,CAAA,KAAgB,CAAhB,EAmD1B,KAnD0C,CAoDhD,MApDgD,SAoDjC,YApDiC,GAqD5C,OArD4C,CAAA,MAqD9B,OArD8B,CAAA,GAsD5C,MAtD4C,CAAA,MAsD/B,MAtD+B,CAAA,CAAA,CAAA,EAwDjD,OAxDiD,CAwDzC,MAxDyC,SAwD1B,YAxD0B,GAwDX,OAxDW,GAwDD,MAxDC,CAAA;EAKzC,QAAA,SAAU;EAAgB,GAAA,CAAA,MAAA,EAAA,aAAA,MA6FO,MA7FP,GAAA,MAAA,CAAA,CAAA,IAAA,EA8F7B,MA9F6B,SA8Fd,YA9Fc,GAAA,MAAA,GA8FU,IA9FV,EAAA,KAAA,EA+F5B,MA/F4B,SA+Fb,YA/Fa,GA+FE,MA/FF,GA+FW,MA/FX,CA+FkB,IA/FlB,CAAA,EAAA,KAAA,CAAA,EAgG3B,KAhG2B,CAgGrB,MAhGqB,SAgGN,YAhGM,GAgGS,MAhGT,GAgGkB,MAhGlB,CAgGyB,IAhGzB,CAAA,CAAA,CAAA,EAiGlC,OAjGkC,CAAA,IAAA,CAAA;EAQO,MAAA,CAAA,gBAuGR,UAvGQ,CAAA,CAAA,MAAA,EAwGlC,MAxGkC,SAwGnB,YAxGmB,GAwGJ,OAxGI,GAwGM,MAxGN,EAAA,KAAA,CAAA,EAyGlC,KAzGkC,CA0GxC,MA1GwC,SA0GzB,YA1GyB,GA2GpC,OA3GoC,CAAA,MA2GtB,OA3GsB,CAAA,GA4GpC,MA5GoC,CAAA,MA4GvB,MA5GuB,CAAA,CAAA,CAAA,EA6GzC,OA7GyC,CAAA,IAAA,CAAA;EACpC,QAAA,SAAA"}
1
+ {"version":3,"file":"restate_test_environment.d.ts","names":[],"sources":["../src/restate_test_environment.ts"],"sourcesContent":[],"mappings":"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"}
@@ -105,15 +105,45 @@ var RestateTestEnvironment = class RestateTestEnvironment {
105
105
  await this.startedRestateContainer.stop();
106
106
  this.startedRestateHttpServer.close();
107
107
  }
108
- static async start(param, restateContainerFactory = () => new RestateContainer()) {
108
+ static async start(param, restateContainerFactory) {
109
+ let containerFactory;
110
+ if (restateContainerFactory) containerFactory = restateContainerFactory;
111
+ else if (typeof param !== "function") containerFactory = () => {
112
+ const container = new RestateContainer();
113
+ if (param.alwaysReplay) container.alwaysReplay();
114
+ if (param.disableRetries) container.disableRetries();
115
+ return container;
116
+ };
117
+ else containerFactory = () => new RestateContainer();
109
118
  const startedRestateHttpServer = typeof param === "function" ? await prepareRestateEndpoint(param) : await prepareRestateEndpoint(param);
110
- return new RestateTestEnvironment(startedRestateHttpServer, await prepareRestateTestContainer(startedRestateHttpServer.address().port, restateContainerFactory));
119
+ return new RestateTestEnvironment(startedRestateHttpServer, await prepareRestateTestContainer(startedRestateHttpServer.address().port, containerFactory));
111
120
  }
112
121
  };
113
122
  var RestateContainer = class extends GenericContainer {
114
123
  constructor(version = "latest") {
115
124
  super(`docker.io/restatedev/restate:${version}`);
116
125
  }
126
+ /**
127
+ * Forces restate-server to always replay on a suspension point.
128
+ * This is useful to hunt non-deterministic bugs that might prevent
129
+ * your code from replaying correctly.
130
+ */
131
+ alwaysReplay() {
132
+ this.withEnvironment({ RESTATE_WORKER__INVOKER__INACTIVITY_TIMEOUT: "0s" });
133
+ return this;
134
+ }
135
+ /**
136
+ * Disables retries in the restate-server invoker.
137
+ * This is useful in tests so that failures surface immediately
138
+ * instead of hanging through retry backoff.
139
+ */
140
+ disableRetries() {
141
+ this.withEnvironment({
142
+ RESTATE_DEFAULT_RETRY_POLICY__MAX_ATTEMPTS: "1",
143
+ RESTATE_DEFAULT_RETRY_POLICY__ON_MAX_ATTEMPTS: "kill"
144
+ });
145
+ return this;
146
+ }
117
147
  };
118
148
  var StateProxy = class {
119
149
  constructor(adminAPIBaseUrl, service, serviceKey) {
@@ -1 +1 @@
1
- {"version":3,"file":"restate_test_environment.js","names":["handler: (\n request: http2.Http2ServerRequest,\n response: http2.Http2ServerResponse\n ) => void","startedRestateHttpServer: http2.Http2Server","startedRestateContainer: StartedTestContainer","adminAPIBaseUrl: string","service: string","serviceKey: string","serde","value"],"sources":["../src/restate_test_environment.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport {\n endpoint,\n createEndpointHandler,\n serde,\n} from \"@restatedev/restate-sdk\";\nimport type {\n TypedState,\n UntypedState,\n Serde,\n RestateEndpoint,\n VirtualObjectDefinition,\n WorkflowDefinition,\n EndpointOptions,\n} from \"@restatedev/restate-sdk\";\n\nimport {\n GenericContainer,\n type StartedTestContainer,\n TestContainers,\n Wait,\n type WaitStrategy,\n type BoundPorts,\n getContainerRuntimeClient,\n} from \"testcontainers\";\nimport { tableFromIPC } from \"apache-arrow\";\nimport * as http2 from \"http2\";\nimport type * as net from \"net\";\n\n/**\n * Custom wait strategy that waits for Restate partitions to be ready by\n * executing a SQL query against the admin API. This ensures all partitions\n * are initialized and queryable before the container is considered ready.\n */\nclass PartitionsReadyWaitStrategy implements WaitStrategy {\n private startupTimeoutMs = 60_000;\n private startupTimeoutSet = false;\n private readonly port: number;\n private readonly pollIntervalMs: number;\n\n constructor(port = 9070, pollIntervalMs = 200) {\n this.port = port;\n this.pollIntervalMs = pollIntervalMs;\n }\n\n public withStartupTimeout(startupTimeoutMs: number): this {\n this.startupTimeoutMs = startupTimeoutMs;\n this.startupTimeoutSet = true;\n return this;\n }\n\n public isStartupTimeoutSet(): boolean {\n return this.startupTimeoutSet;\n }\n\n public getStartupTimeout(): number {\n return this.startupTimeoutMs;\n }\n\n public async waitUntilReady(\n container: { id: string },\n boundPorts: BoundPorts\n ): Promise<void> {\n const client = await getContainerRuntimeClient();\n const host = client.info.containerRuntime.host;\n const mappedPort = boundPorts.getBinding(this.port);\n const adminUrl = `http://${host}:${mappedPort}`;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < this.startupTimeoutMs) {\n try {\n const res = await fetch(`${adminUrl}/query`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n query: \"SELECT count(1) FROM sys_invocation\",\n }),\n });\n\n if (res.ok) {\n // Partitions are ready\n return;\n }\n } catch {\n // Ignore errors, keep polling\n }\n\n await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));\n }\n\n throw new Error(\n `Restate partitions not ready after ${this.startupTimeoutMs}ms`\n );\n }\n}\n\n// Prepare the restate server\nasync function prepareRestateEndpoint(\n param: (server: RestateEndpoint) => void\n): Promise<http2.Http2Server>;\nasync function prepareRestateEndpoint(\n param: EndpointOptions\n): Promise<http2.Http2Server>;\nasync function prepareRestateEndpoint(\n param: EndpointOptions | ((server: RestateEndpoint) => void)\n): Promise<http2.Http2Server> {\n // Prepare RestateServer\n let handler: (\n request: http2.Http2ServerRequest,\n response: http2.Http2ServerResponse\n ) => void;\n if (typeof param === \"function\") {\n const restateEndpoint = endpoint();\n param(restateEndpoint);\n handler = restateEndpoint.http2Handler();\n } else {\n handler = createEndpointHandler(param);\n }\n\n // Start HTTP2 server on random port\n const restateHttpServer = http2.createServer(handler);\n await new Promise((resolve, reject) => {\n restateHttpServer\n .listen(0)\n .once(\"listening\", resolve)\n .once(\"error\", reject);\n });\n const restateServerPort = (restateHttpServer.address() as net.AddressInfo)\n .port;\n console.info(`Restate container listening on port ${restateServerPort}`);\n\n return restateHttpServer;\n}\n\n// Prepare the restate testcontainer\nasync function prepareRestateTestContainer(\n restateServerPort: number,\n restateContainerFactory: () => GenericContainer\n): Promise<StartedTestContainer> {\n const restateContainer = restateContainerFactory()\n // Expose ports\n .withExposedPorts(8080, 9070)\n // Wait start on health checks and partition readiness\n .withWaitStrategy(\n Wait.forAll([\n Wait.forHttp(\"/restate/health\", 8080),\n Wait.forHttp(\"/health\", 9070),\n new PartitionsReadyWaitStrategy(),\n ])\n );\n\n // This MUST be executed before starting the restate container\n // Expose host port to access the restate server\n await TestContainers.exposeHostPorts(restateServerPort);\n\n // Start restate container\n const startedRestateContainer = await restateContainer.start();\n\n // From now on, if something fails, stop the container to cleanup the environment\n try {\n console.info(\n `Registering services at http://host.testcontainers.internal:${restateServerPort}...`\n );\n\n // Register this service endpoint\n const res = await fetch(\n `http://${startedRestateContainer.getHost()}:${startedRestateContainer.getMappedPort(\n 9070\n )}/deployments`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n // See https://node.testcontainers.org/features/networking/#expose-host-ports-to-container\n uri: `http://host.testcontainers.internal:${restateServerPort}`,\n }),\n }\n );\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(\n `Error ${res.status} during registration: ${badResponse}`\n );\n }\n\n const resp = (await res.json()) as { services: { name: string }[] };\n console.info(\n \"Registered services:\",\n resp?.services?.map((s) => s.name)\n );\n return startedRestateContainer;\n } catch (e) {\n await startedRestateContainer.stop();\n throw e;\n }\n}\n\nexport class RestateTestEnvironment {\n constructor(\n readonly startedRestateHttpServer: http2.Http2Server,\n readonly startedRestateContainer: StartedTestContainer\n ) {}\n\n public baseUrl(): string {\n return `http://${this.startedRestateContainer.getHost()}:${this.startedRestateContainer.getMappedPort(\n 8080\n )}`;\n }\n\n public adminAPIBaseUrl(): string {\n return `http://${this.startedRestateContainer.getHost()}:${this.startedRestateContainer.getMappedPort(\n 9070\n )}`;\n }\n\n // Create a handle that allows read/write of state under a given Virtual Object/Workflow key.\n public stateOf<TState extends TypedState = UntypedState>(\n service:\n | VirtualObjectDefinition<string, unknown>\n | WorkflowDefinition<string, unknown>,\n key: string\n ): StateProxy<TState> {\n return new StateProxy(this.adminAPIBaseUrl(), service.name, key);\n }\n\n public async stop() {\n await this.startedRestateContainer.stop();\n this.startedRestateHttpServer.close();\n }\n\n /**\n *\n * @deprecated Please use {@link EndpointOptions} instead of this.\n * @example\n * ```\n * RestateTestEnvironment.start({ services: [mysService] })\n * ```\n */\n public static async start(\n mountServicesFn: (server: RestateEndpoint) => void,\n restateContainerFactory?: () => GenericContainer\n ): Promise<RestateTestEnvironment>;\n public static async start(\n options: EndpointOptions,\n restateContainerFactory?: () => GenericContainer\n ): Promise<RestateTestEnvironment>;\n public static async start(\n param: EndpointOptions | ((server: RestateEndpoint) => void),\n restateContainerFactory: () => GenericContainer = () =>\n new RestateContainer()\n ): Promise<RestateTestEnvironment> {\n const startedRestateHttpServer =\n typeof param === \"function\"\n ? await prepareRestateEndpoint(param)\n : await prepareRestateEndpoint(param);\n const startedRestateContainer = await prepareRestateTestContainer(\n (startedRestateHttpServer.address() as net.AddressInfo).port,\n restateContainerFactory\n );\n return new RestateTestEnvironment(\n startedRestateHttpServer,\n startedRestateContainer\n );\n }\n}\n\nexport class RestateContainer extends GenericContainer {\n constructor(version = \"latest\") {\n super(`docker.io/restatedev/restate:${version}`);\n }\n}\nexport class StateProxy<TState extends TypedState> {\n constructor(\n private adminAPIBaseUrl: string,\n private service: string,\n private serviceKey: string\n ) {}\n\n // Read a single value from state under a given Virtual Object or Workflow key\n public async get<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n serde?: Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): Promise<(TState extends UntypedState ? TValue : TState[TKey]) | null> {\n serde = serde ?? defaultSerde();\n\n const res = await fetch(`${this.adminAPIBaseUrl}/query`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n query: `SELECT value from state where service_name = '${\n this.service\n }' and service_key = '${this.serviceKey}' and key = '${String(name)}';`,\n }),\n });\n\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(`Error ${res.status} during read state: ${badResponse}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/await-thenable\n const table = (await tableFromIPC(res.body)).toArray() as {\n key: string;\n value: Uint8Array;\n }[];\n\n if (table.length === 0) {\n return null;\n }\n\n return serde.deserialize(table[0]!.value);\n }\n\n // Read all values from state under a given Virtual Object or Workflow key\n public async getAll<TValues extends TypedState>(\n serde?: Serde<\n TState extends UntypedState\n ? TValues[keyof TValues]\n : TState[keyof TState]\n >\n ): Promise<TState extends UntypedState ? TValues : TState> {\n serde = serde ?? defaultSerde();\n\n const items = await this.getAllRaw();\n\n return Object.fromEntries(\n items.map(({ key, value }) => {\n return [key, serde.deserialize(value)];\n })\n ) as TState extends UntypedState ? TValues : TState;\n }\n\n private async getAllRaw(): Promise<{ key: string; value: Uint8Array }[]> {\n const res = await fetch(`${this.adminAPIBaseUrl}/query`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n query: `SELECT key, value from state where service_name = '${this.service}' and service_key = '${this.serviceKey}';`,\n }),\n });\n\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(`Error ${res.status} during read state: ${badResponse}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/await-thenable\n const table = (await tableFromIPC(res.body)).toArray() as {\n key: string;\n value: Uint8Array;\n }[];\n\n return table;\n }\n\n // Asynchronously set a single value from state under a given Virtual Object or Workflow key.\n // This will first read all values, then insert the update and submit the new set of values to Restate;\n // as such it is possible to overwrite changes that happened between the read and the mutation being applied.\n // A successful return from this function does not imply that the set has finished, only that the mutation\n // was submitted to Restate for processing.\n public async set<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n value: TState extends UntypedState ? TValue : TState[TKey],\n serde?: Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): Promise<void> {\n serde = serde ?? defaultSerde();\n const serialisedValue = serde.serialize(value);\n\n const items = await this.getAllRaw();\n\n items.push({ key: String(name), value: serialisedValue });\n\n await this.setAllRaw(items.map(({ key, value }) => [key, value]));\n }\n\n // Asynchronously set all state values under a given Virtual Object or Workflow key.\n // A successful return from this function does not imply that the set has finished,\n // only that the mutation was submitted to Restate for processing.\n public async setAll<TValues extends TypedState>(\n values: TState extends UntypedState ? TValues : TState,\n serde?: Serde<\n TState extends UntypedState\n ? TValues[keyof TValues]\n : TState[keyof TState]\n >\n ) {\n serde = serde ?? defaultSerde();\n\n return this.setAllRaw(\n Object.entries<\n TState extends UntypedState\n ? TValues[keyof TValues]\n : TState[keyof TState]\n >(values).map(([key, value]) => {\n return [key, serde.serialize(value)];\n })\n );\n }\n\n private async setAllRaw(\n entries: [key: string, value: Uint8Array][],\n version?: string\n ) {\n const res = await fetch(\n `${this.adminAPIBaseUrl}/services/${this.service}/state`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(\n {\n version,\n object_key: this.serviceKey,\n new_state: Object.fromEntries(entries),\n },\n (key, value) => {\n if (value instanceof Uint8Array) {\n return Array.from(value);\n } else {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return value;\n }\n }\n ),\n }\n );\n\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(\n `Error ${res.status} during modify state: ${badResponse}`\n );\n }\n }\n}\n\nexport const defaultSerde = <T>(): Serde<T> => {\n return serde.json as Serde<T>;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"restate_test_environment.js","names":["handler: (\n request: http2.Http2ServerRequest,\n response: http2.Http2ServerResponse\n ) => void","startedRestateHttpServer: http2.Http2Server","startedRestateContainer: StartedTestContainer","containerFactory: () => GenericContainer","adminAPIBaseUrl: string","service: string","serviceKey: string","serde","value"],"sources":["../src/restate_test_environment.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport {\n endpoint,\n createEndpointHandler,\n serde,\n} from \"@restatedev/restate-sdk\";\nimport type {\n TypedState,\n UntypedState,\n Serde,\n RestateEndpoint,\n VirtualObjectDefinition,\n WorkflowDefinition,\n EndpointOptions,\n} from \"@restatedev/restate-sdk\";\n\nimport {\n GenericContainer,\n type StartedTestContainer,\n TestContainers,\n Wait,\n type WaitStrategy,\n type BoundPorts,\n getContainerRuntimeClient,\n} from \"testcontainers\";\nimport { tableFromIPC } from \"apache-arrow\";\nimport * as http2 from \"http2\";\nimport type * as net from \"net\";\n\n/**\n * Custom wait strategy that waits for Restate partitions to be ready by\n * executing a SQL query against the admin API. This ensures all partitions\n * are initialized and queryable before the container is considered ready.\n */\nclass PartitionsReadyWaitStrategy implements WaitStrategy {\n private startupTimeoutMs = 60_000;\n private startupTimeoutSet = false;\n private readonly port: number;\n private readonly pollIntervalMs: number;\n\n constructor(port = 9070, pollIntervalMs = 200) {\n this.port = port;\n this.pollIntervalMs = pollIntervalMs;\n }\n\n public withStartupTimeout(startupTimeoutMs: number): this {\n this.startupTimeoutMs = startupTimeoutMs;\n this.startupTimeoutSet = true;\n return this;\n }\n\n public isStartupTimeoutSet(): boolean {\n return this.startupTimeoutSet;\n }\n\n public getStartupTimeout(): number {\n return this.startupTimeoutMs;\n }\n\n public async waitUntilReady(\n container: { id: string },\n boundPorts: BoundPorts\n ): Promise<void> {\n const client = await getContainerRuntimeClient();\n const host = client.info.containerRuntime.host;\n const mappedPort = boundPorts.getBinding(this.port);\n const adminUrl = `http://${host}:${mappedPort}`;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < this.startupTimeoutMs) {\n try {\n const res = await fetch(`${adminUrl}/query`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n query: \"SELECT count(1) FROM sys_invocation\",\n }),\n });\n\n if (res.ok) {\n // Partitions are ready\n return;\n }\n } catch {\n // Ignore errors, keep polling\n }\n\n await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));\n }\n\n throw new Error(\n `Restate partitions not ready after ${this.startupTimeoutMs}ms`\n );\n }\n}\n\n// Prepare the restate server\nasync function prepareRestateEndpoint(\n param: (server: RestateEndpoint) => void\n): Promise<http2.Http2Server>;\nasync function prepareRestateEndpoint(\n param: EndpointOptions\n): Promise<http2.Http2Server>;\nasync function prepareRestateEndpoint(\n param: EndpointOptions | ((server: RestateEndpoint) => void)\n): Promise<http2.Http2Server> {\n // Prepare RestateServer\n let handler: (\n request: http2.Http2ServerRequest,\n response: http2.Http2ServerResponse\n ) => void;\n if (typeof param === \"function\") {\n const restateEndpoint = endpoint();\n param(restateEndpoint);\n handler = restateEndpoint.http2Handler();\n } else {\n handler = createEndpointHandler(param);\n }\n\n // Start HTTP2 server on random port\n const restateHttpServer = http2.createServer(handler);\n await new Promise((resolve, reject) => {\n restateHttpServer\n .listen(0)\n .once(\"listening\", resolve)\n .once(\"error\", reject);\n });\n const restateServerPort = (restateHttpServer.address() as net.AddressInfo)\n .port;\n console.info(`Restate container listening on port ${restateServerPort}`);\n\n return restateHttpServer;\n}\n\n// Prepare the restate testcontainer\nasync function prepareRestateTestContainer(\n restateServerPort: number,\n restateContainerFactory: () => GenericContainer\n): Promise<StartedTestContainer> {\n const restateContainer = restateContainerFactory()\n // Expose ports\n .withExposedPorts(8080, 9070)\n // Wait start on health checks and partition readiness\n .withWaitStrategy(\n Wait.forAll([\n Wait.forHttp(\"/restate/health\", 8080),\n Wait.forHttp(\"/health\", 9070),\n new PartitionsReadyWaitStrategy(),\n ])\n );\n\n // This MUST be executed before starting the restate container\n // Expose host port to access the restate server\n await TestContainers.exposeHostPorts(restateServerPort);\n\n // Start restate container\n const startedRestateContainer = await restateContainer.start();\n\n // From now on, if something fails, stop the container to cleanup the environment\n try {\n console.info(\n `Registering services at http://host.testcontainers.internal:${restateServerPort}...`\n );\n\n // Register this service endpoint\n const res = await fetch(\n `http://${startedRestateContainer.getHost()}:${startedRestateContainer.getMappedPort(\n 9070\n )}/deployments`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n // See https://node.testcontainers.org/features/networking/#expose-host-ports-to-container\n uri: `http://host.testcontainers.internal:${restateServerPort}`,\n }),\n }\n );\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(\n `Error ${res.status} during registration: ${badResponse}`\n );\n }\n\n const resp = (await res.json()) as { services: { name: string }[] };\n console.info(\n \"Registered services:\",\n resp?.services?.map((s) => s.name)\n );\n return startedRestateContainer;\n } catch (e) {\n await startedRestateContainer.stop();\n throw e;\n }\n}\n\nexport interface TestEnvironmentOptions extends EndpointOptions {\n /**\n * Forces restate-server to always replay on a suspension point.\n * This is useful to hunt non-deterministic bugs that might prevent\n * your code from replaying correctly.\n */\n alwaysReplay?: boolean;\n\n /**\n * Disables retries in the restate-server invoker.\n * This is useful in tests so that failures surface immediately\n * instead of hanging through retry backoff.\n */\n disableRetries?: boolean;\n}\n\nexport class RestateTestEnvironment {\n constructor(\n readonly startedRestateHttpServer: http2.Http2Server,\n readonly startedRestateContainer: StartedTestContainer\n ) {}\n\n public baseUrl(): string {\n return `http://${this.startedRestateContainer.getHost()}:${this.startedRestateContainer.getMappedPort(\n 8080\n )}`;\n }\n\n public adminAPIBaseUrl(): string {\n return `http://${this.startedRestateContainer.getHost()}:${this.startedRestateContainer.getMappedPort(\n 9070\n )}`;\n }\n\n // Create a handle that allows read/write of state under a given Virtual Object/Workflow key.\n public stateOf<TState extends TypedState = UntypedState>(\n service:\n | VirtualObjectDefinition<string, unknown>\n | WorkflowDefinition<string, unknown>,\n key: string\n ): StateProxy<TState> {\n return new StateProxy(this.adminAPIBaseUrl(), service.name, key);\n }\n\n public async stop() {\n await this.startedRestateContainer.stop();\n this.startedRestateHttpServer.close();\n }\n\n /**\n *\n * @deprecated Please use {@link TestEnvironmentOptions} instead of this.\n * @example\n * ```\n * RestateTestEnvironment.start({ services: [mysService] })\n * ```\n */\n public static async start(\n mountServicesFn: (server: RestateEndpoint) => void,\n restateContainerFactory?: () => GenericContainer\n ): Promise<RestateTestEnvironment>;\n public static async start(\n options: TestEnvironmentOptions,\n restateContainerFactory?: () => GenericContainer\n ): Promise<RestateTestEnvironment>;\n public static async start(\n param: TestEnvironmentOptions | ((server: RestateEndpoint) => void),\n restateContainerFactory?: () => GenericContainer\n ): Promise<RestateTestEnvironment> {\n let containerFactory: () => GenericContainer;\n if (restateContainerFactory) {\n containerFactory = restateContainerFactory;\n } else if (typeof param !== \"function\") {\n containerFactory = () => {\n const container = new RestateContainer();\n if (param.alwaysReplay) {\n container.alwaysReplay();\n }\n if (param.disableRetries) {\n container.disableRetries();\n }\n return container;\n };\n } else {\n containerFactory = () => new RestateContainer();\n }\n\n const startedRestateHttpServer =\n typeof param === \"function\"\n ? await prepareRestateEndpoint(param)\n : await prepareRestateEndpoint(param);\n const startedRestateContainer = await prepareRestateTestContainer(\n (startedRestateHttpServer.address() as net.AddressInfo).port,\n containerFactory\n );\n return new RestateTestEnvironment(\n startedRestateHttpServer,\n startedRestateContainer\n );\n }\n}\n\nexport class RestateContainer extends GenericContainer {\n constructor(version = \"latest\") {\n super(`docker.io/restatedev/restate:${version}`);\n }\n\n /**\n * Forces restate-server to always replay on a suspension point.\n * This is useful to hunt non-deterministic bugs that might prevent\n * your code from replaying correctly.\n */\n alwaysReplay(): this {\n this.withEnvironment({\n RESTATE_WORKER__INVOKER__INACTIVITY_TIMEOUT: \"0s\",\n });\n return this;\n }\n\n /**\n * Disables retries in the restate-server invoker.\n * This is useful in tests so that failures surface immediately\n * instead of hanging through retry backoff.\n */\n disableRetries(): this {\n this.withEnvironment({\n RESTATE_DEFAULT_RETRY_POLICY__MAX_ATTEMPTS: \"1\",\n RESTATE_DEFAULT_RETRY_POLICY__ON_MAX_ATTEMPTS: \"kill\",\n });\n return this;\n }\n}\nexport class StateProxy<TState extends TypedState> {\n constructor(\n private adminAPIBaseUrl: string,\n private service: string,\n private serviceKey: string\n ) {}\n\n // Read a single value from state under a given Virtual Object or Workflow key\n public async get<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n serde?: Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): Promise<(TState extends UntypedState ? TValue : TState[TKey]) | null> {\n serde = serde ?? defaultSerde();\n\n const res = await fetch(`${this.adminAPIBaseUrl}/query`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n query: `SELECT value from state where service_name = '${\n this.service\n }' and service_key = '${this.serviceKey}' and key = '${String(name)}';`,\n }),\n });\n\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(`Error ${res.status} during read state: ${badResponse}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/await-thenable\n const table = (await tableFromIPC(res.body)).toArray() as {\n key: string;\n value: Uint8Array;\n }[];\n\n if (table.length === 0) {\n return null;\n }\n\n return serde.deserialize(table[0]!.value);\n }\n\n // Read all values from state under a given Virtual Object or Workflow key\n public async getAll<TValues extends TypedState>(\n serde?: Serde<\n TState extends UntypedState\n ? TValues[keyof TValues]\n : TState[keyof TState]\n >\n ): Promise<TState extends UntypedState ? TValues : TState> {\n serde = serde ?? defaultSerde();\n\n const items = await this.getAllRaw();\n\n return Object.fromEntries(\n items.map(({ key, value }) => {\n return [key, serde.deserialize(value)];\n })\n ) as TState extends UntypedState ? TValues : TState;\n }\n\n private async getAllRaw(): Promise<{ key: string; value: Uint8Array }[]> {\n const res = await fetch(`${this.adminAPIBaseUrl}/query`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n query: `SELECT key, value from state where service_name = '${this.service}' and service_key = '${this.serviceKey}';`,\n }),\n });\n\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(`Error ${res.status} during read state: ${badResponse}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/await-thenable\n const table = (await tableFromIPC(res.body)).toArray() as {\n key: string;\n value: Uint8Array;\n }[];\n\n return table;\n }\n\n // Asynchronously set a single value from state under a given Virtual Object or Workflow key.\n // This will first read all values, then insert the update and submit the new set of values to Restate;\n // as such it is possible to overwrite changes that happened between the read and the mutation being applied.\n // A successful return from this function does not imply that the set has finished, only that the mutation\n // was submitted to Restate for processing.\n public async set<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n value: TState extends UntypedState ? TValue : TState[TKey],\n serde?: Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): Promise<void> {\n serde = serde ?? defaultSerde();\n const serialisedValue = serde.serialize(value);\n\n const items = await this.getAllRaw();\n\n items.push({ key: String(name), value: serialisedValue });\n\n await this.setAllRaw(items.map(({ key, value }) => [key, value]));\n }\n\n // Asynchronously set all state values under a given Virtual Object or Workflow key.\n // A successful return from this function does not imply that the set has finished,\n // only that the mutation was submitted to Restate for processing.\n public async setAll<TValues extends TypedState>(\n values: TState extends UntypedState ? TValues : TState,\n serde?: Serde<\n TState extends UntypedState\n ? TValues[keyof TValues]\n : TState[keyof TState]\n >\n ) {\n serde = serde ?? defaultSerde();\n\n return this.setAllRaw(\n Object.entries<\n TState extends UntypedState\n ? TValues[keyof TValues]\n : TState[keyof TState]\n >(values).map(([key, value]) => {\n return [key, serde.serialize(value)];\n })\n );\n }\n\n private async setAllRaw(\n entries: [key: string, value: Uint8Array][],\n version?: string\n ) {\n const res = await fetch(\n `${this.adminAPIBaseUrl}/services/${this.service}/state`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(\n {\n version,\n object_key: this.serviceKey,\n new_state: Object.fromEntries(entries),\n },\n (key, value) => {\n if (value instanceof Uint8Array) {\n return Array.from(value);\n } else {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return value;\n }\n }\n ),\n }\n );\n\n if (!res.ok) {\n const badResponse = await res.text();\n throw new Error(\n `Error ${res.status} during modify state: ${badResponse}`\n );\n }\n }\n}\n\nexport const defaultSerde = <T>(): Serde<T> => {\n return serde.json as Serde<T>;\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@restatedev/restate-sdk-testcontainers",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Typescript SDK for Restate",
5
5
  "author": "Restate Developers",
6
6
  "email": "code@restate.dev",
@@ -33,9 +33,9 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "apache-arrow": "^18.0.0",
36
- "testcontainers": "^10.24.1",
37
- "@restatedev/restate-sdk": "1.11.0",
38
- "@restatedev/restate-sdk-clients": "1.11.0"
36
+ "testcontainers": "^11.12.0",
37
+ "@restatedev/restate-sdk": "1.12.0",
38
+ "@restatedev/restate-sdk-clients": "1.12.0"
39
39
  },
40
40
  "devDependencies": {},
41
41
  "scripts": {
@@ -1,10 +0,0 @@
1
- import { ServiceDefinition, VirtualObjectDefinition, WorkflowDefinition } from "../../restate-sdk-core/src/core.cjs";
2
- import { Serde } from "../../restate-sdk-core/src/serde_api.cjs";
3
- import { Duration } from "../../restate-sdk-core/src/duration.cjs";
4
- import { JournalValueCodec } from "../../restate-sdk-core/src/entry_codec.cjs";
5
- import { RestateError, TerminalError } from "./types/errors.cjs";
6
- import { ObjectOptions, RetryPolicy, ServiceOptions, WorkflowOptions } from "./types/rpc.cjs";
7
- import { Request, TypedState, UntypedState } from "./context.cjs";
8
- import { LogMetadata, LogSource, LoggerContext, LoggerTransport, RestateLogLevel } from "./logging/logger_transport.cjs";
9
- import { DefaultServiceOptions, RestateEndpoint, RestateEndpointBase } from "./endpoint.cjs";
10
- import { EndpointOptions } from "./endpoint/types.cjs";