@flowcore/sdk 1.4.4 → 1.5.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.5.0](https://github.com/flowcore-io/flowcore-sdk/compare/v1.4.5...v1.5.0) (2024-12-19)
4
+
5
+
6
+ ### Features
7
+
8
+ * add retry to client ([b202c56](https://github.com/flowcore-io/flowcore-sdk/commit/b202c5660f42a02bbd45db043d48713effe658a6))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * update readme ([bf233bc](https://github.com/flowcore-io/flowcore-sdk/commit/bf233bc27b15892b5813c2121b7221d08c7b7d63))
14
+ * update readme ([3ffbe49](https://github.com/flowcore-io/flowcore-sdk/commit/3ffbe499e6014e64a8c420eead2763539cb5412c))
15
+ * use retryable status codes ([89a8919](https://github.com/flowcore-io/flowcore-sdk/commit/89a8919492c55614851779ff77ddc3f7fcde51e0))
16
+
17
+ ## [1.4.5](https://github.com/flowcore-io/flowcore-sdk/compare/v1.4.4...v1.4.5) (2024-12-19)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * expose flowcore event ([cd20a6c](https://github.com/flowcore-io/flowcore-sdk/commit/cd20a6c10591613f7813a52120395aa87311aba2))
23
+
3
24
  ## [1.4.4](https://github.com/flowcore-io/flowcore-sdk/compare/v1.4.3...v1.4.4) (2024-12-09)
4
25
 
5
26
 
package/README.md CHANGED
@@ -32,6 +32,18 @@ const client = new FlowcoreClient({
32
32
  apiKey: "my-api-key",
33
33
  })
34
34
 
35
+ // With retry
36
+ // NOTE! When retry is not set it will default to 250ms delay and 3 max retries.
37
+ // To disable retry set retry to null.
38
+ const client = new FlowcoreClient({
39
+ apiKeyId: "my-api-key-id",
40
+ apiKey: "my-api-key",
41
+ retry: {
42
+ delay: 100,
43
+ maxRetries: 5,
44
+ },
45
+ })
46
+
35
47
  // Execute a command
36
48
  const command = new DataCoreFetchCommand({
37
49
  dataCoreId: "my-data-core-id",
@@ -6,6 +6,10 @@ interface ClientOptionsBearer {
6
6
  getBearerToken: () => Promise<string | null> | string | null;
7
7
  apiKeyId?: never;
8
8
  apiKey?: never;
9
+ retry?: {
10
+ delay: number;
11
+ maxRetries: number;
12
+ } | null;
9
13
  }
10
14
  /**
11
15
  * The options for the api key
@@ -14,6 +18,10 @@ interface ClientOptionsApiKey {
14
18
  apiKeyId: string;
15
19
  apiKey: string;
16
20
  getBearerToken?: never;
21
+ retry?: {
22
+ delay: number;
23
+ maxRetries: number;
24
+ } | null;
17
25
  }
18
26
  /**
19
27
  * The options for the client
@@ -30,6 +38,10 @@ export declare class FlowcoreClient {
30
38
  * Get the auth header
31
39
  */
32
40
  private getAuthHeader;
41
+ /**
42
+ * Execute a command (inner method)
43
+ */
44
+ private innerExecute;
33
45
  /**
34
46
  * Execute a command
35
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"flowcore-client.d.ts","sourceRoot":"","sources":["../../src/common/flowcore-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C;;GAEG;AACH,UAAU,mBAAmB;IAC3B,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAA;CACf;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,KAAK,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAErE;;GAEG;AACH,qBAAa,cAAc;IAEb,OAAO,CAAC,QAAQ,CAAC,OAAO;IADpC,OAAO,CAAC,IAAI,CAAqB;gBACJ,OAAO,EAAE,aAAa;IAUnD;;OAEG;YACW,aAAa;IAc3B;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CA+B/E"}
1
+ {"version":3,"file":"flowcore-client.d.ts","sourceRoot":"","sources":["../../src/common/flowcore-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAI3C;;GAEG;AACH,UAAU,mBAAmB;IAC3B,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;KACnB,GAAG,IAAI,CAAA;CACT;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;KACnB,GAAG,IAAI,CAAA;CACT;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAErE;;GAEG;AACH,qBAAa,cAAc;IAEb,OAAO,CAAC,QAAQ,CAAC,OAAO;IADpC,OAAO,CAAC,IAAI,CAAqB;gBACJ,OAAO,EAAE,aAAa;IAiBnD;;OAEG;YACW,aAAa;IAc3B;;OAEG;YACW,YAAY;IAyD1B;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CAGzE"}
@@ -1,5 +1,6 @@
1
1
  import { ClientError } from "../exceptions/client-error.js";
2
2
  import { CommandError } from "../exceptions/command-error.js";
3
+ const RETRYABLE_ERROR_CODES = [408, 429, 500, 502, 503, 504];
3
4
  /**
4
5
  * A base client for executing commands
5
6
  */
@@ -26,6 +27,12 @@ export class FlowcoreClient {
26
27
  else {
27
28
  throw new Error("Invalid client options");
28
29
  }
30
+ if (this.options.retry === undefined) {
31
+ this.options.retry = {
32
+ delay: 250,
33
+ maxRetries: 3,
34
+ };
35
+ }
29
36
  }
30
37
  /**
31
38
  * Get the auth header
@@ -44,23 +51,44 @@ export class FlowcoreClient {
44
51
  return null;
45
52
  }
46
53
  /**
47
- * Execute a command
54
+ * Execute a command (inner method)
48
55
  */
49
- async execute(command) {
56
+ async innerExecute(command, retryCount = 0) {
50
57
  const request = await command.getRequest(this);
51
58
  if (!request.allowedModes.includes(this.mode)) {
52
59
  throw new CommandError(command.constructor.name, `Not allowed in "${this.mode}" mode`);
53
60
  }
54
61
  const authHeader = await this.getAuthHeader();
55
- const response = await fetch(request.baseUrl + request.path, {
56
- method: request.method,
57
- headers: {
58
- ...request.headers,
59
- ...(authHeader ? { Authorization: authHeader } : {}),
60
- },
61
- body: request.body,
62
- });
62
+ let response;
63
+ try {
64
+ response = await fetch(request.baseUrl + request.path, {
65
+ method: request.method,
66
+ headers: {
67
+ ...request.headers,
68
+ ...(authHeader ? { Authorization: authHeader } : {}),
69
+ },
70
+ body: request.body,
71
+ });
72
+ }
73
+ catch (error) {
74
+ if (this.options.retry && retryCount < this.options.retry.maxRetries) {
75
+ const delay = this.options.retry.delay;
76
+ await new Promise((resolve) => setTimeout(resolve, delay));
77
+ return this.innerExecute(command, retryCount + 1);
78
+ }
79
+ const message = error instanceof Error ? error.message : "Unknown error";
80
+ throw new ClientError(`Failed to execute command: ${message}`, 0, {
81
+ command: command.constructor.name,
82
+ error: error,
83
+ });
84
+ }
63
85
  if (!response.ok) {
86
+ if (this.options.retry && RETRYABLE_ERROR_CODES.includes(response.status) &&
87
+ retryCount < this.options.retry.maxRetries) {
88
+ const delay = this.options.retry.delay;
89
+ await new Promise((resolve) => setTimeout(resolve, delay));
90
+ return this.innerExecute(command, retryCount + 1);
91
+ }
64
92
  const body = await response.json().catch(() => undefined);
65
93
  const commandName = command.constructor.name;
66
94
  throw new ClientError(`${commandName} failed with ${response.status}: ${response.statusText}`, response.status, body);
@@ -69,4 +97,10 @@ export class FlowcoreClient {
69
97
  const parsedBody = await request.parseResponse(body, this);
70
98
  return request.waitForResponse(this, parsedBody);
71
99
  }
100
+ /**
101
+ * Execute a command
102
+ */
103
+ execute(command) {
104
+ return this.innerExecute(command, 0);
105
+ }
72
106
  }
@@ -1,4 +1,5 @@
1
1
  export type { DataCore } from "./data-core.js";
2
2
  export type { EventType } from "./event-type.js";
3
3
  export type { FlowType } from "./flow-type.js";
4
+ export type { FlowcoreEvent } from "./event.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowcore/sdk",
3
- "version": "1.4.4",
3
+ "version": "1.5.0",
4
4
  "description": "Flowcore SDK",
5
5
  "homepage": "https://github.com/flowcore-io/flowcore-sdk#readme",
6
6
  "repository": {
@@ -6,6 +6,10 @@ interface ClientOptionsBearer {
6
6
  getBearerToken: () => Promise<string | null> | string | null;
7
7
  apiKeyId?: never;
8
8
  apiKey?: never;
9
+ retry?: {
10
+ delay: number;
11
+ maxRetries: number;
12
+ } | null;
9
13
  }
10
14
  /**
11
15
  * The options for the api key
@@ -14,6 +18,10 @@ interface ClientOptionsApiKey {
14
18
  apiKeyId: string;
15
19
  apiKey: string;
16
20
  getBearerToken?: never;
21
+ retry?: {
22
+ delay: number;
23
+ maxRetries: number;
24
+ } | null;
17
25
  }
18
26
  /**
19
27
  * The options for the client
@@ -30,6 +38,10 @@ export declare class FlowcoreClient {
30
38
  * Get the auth header
31
39
  */
32
40
  private getAuthHeader;
41
+ /**
42
+ * Execute a command (inner method)
43
+ */
44
+ private innerExecute;
33
45
  /**
34
46
  * Execute a command
35
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"flowcore-client.d.ts","sourceRoot":"","sources":["../../src/common/flowcore-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C;;GAEG;AACH,UAAU,mBAAmB;IAC3B,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAA;CACf;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,KAAK,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAErE;;GAEG;AACH,qBAAa,cAAc;IAEb,OAAO,CAAC,QAAQ,CAAC,OAAO;IADpC,OAAO,CAAC,IAAI,CAAqB;gBACJ,OAAO,EAAE,aAAa;IAUnD;;OAEG;YACW,aAAa;IAc3B;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CA+B/E"}
1
+ {"version":3,"file":"flowcore-client.d.ts","sourceRoot":"","sources":["../../src/common/flowcore-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAI3C;;GAEG;AACH,UAAU,mBAAmB;IAC3B,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;KACnB,GAAG,IAAI,CAAA;CACT;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;KACnB,GAAG,IAAI,CAAA;CACT;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAErE;;GAEG;AACH,qBAAa,cAAc;IAEb,OAAO,CAAC,QAAQ,CAAC,OAAO;IADpC,OAAO,CAAC,IAAI,CAAqB;gBACJ,OAAO,EAAE,aAAa;IAiBnD;;OAEG;YACW,aAAa;IAc3B;;OAEG;YACW,YAAY;IAyD1B;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CAGzE"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FlowcoreClient = void 0;
4
4
  const client_error_js_1 = require("../exceptions/client-error.js");
5
5
  const command_error_js_1 = require("../exceptions/command-error.js");
6
+ const RETRYABLE_ERROR_CODES = [408, 429, 500, 502, 503, 504];
6
7
  /**
7
8
  * A base client for executing commands
8
9
  */
@@ -29,6 +30,12 @@ class FlowcoreClient {
29
30
  else {
30
31
  throw new Error("Invalid client options");
31
32
  }
33
+ if (this.options.retry === undefined) {
34
+ this.options.retry = {
35
+ delay: 250,
36
+ maxRetries: 3,
37
+ };
38
+ }
32
39
  }
33
40
  /**
34
41
  * Get the auth header
@@ -47,23 +54,44 @@ class FlowcoreClient {
47
54
  return null;
48
55
  }
49
56
  /**
50
- * Execute a command
57
+ * Execute a command (inner method)
51
58
  */
52
- async execute(command) {
59
+ async innerExecute(command, retryCount = 0) {
53
60
  const request = await command.getRequest(this);
54
61
  if (!request.allowedModes.includes(this.mode)) {
55
62
  throw new command_error_js_1.CommandError(command.constructor.name, `Not allowed in "${this.mode}" mode`);
56
63
  }
57
64
  const authHeader = await this.getAuthHeader();
58
- const response = await fetch(request.baseUrl + request.path, {
59
- method: request.method,
60
- headers: {
61
- ...request.headers,
62
- ...(authHeader ? { Authorization: authHeader } : {}),
63
- },
64
- body: request.body,
65
- });
65
+ let response;
66
+ try {
67
+ response = await fetch(request.baseUrl + request.path, {
68
+ method: request.method,
69
+ headers: {
70
+ ...request.headers,
71
+ ...(authHeader ? { Authorization: authHeader } : {}),
72
+ },
73
+ body: request.body,
74
+ });
75
+ }
76
+ catch (error) {
77
+ if (this.options.retry && retryCount < this.options.retry.maxRetries) {
78
+ const delay = this.options.retry.delay;
79
+ await new Promise((resolve) => setTimeout(resolve, delay));
80
+ return this.innerExecute(command, retryCount + 1);
81
+ }
82
+ const message = error instanceof Error ? error.message : "Unknown error";
83
+ throw new client_error_js_1.ClientError(`Failed to execute command: ${message}`, 0, {
84
+ command: command.constructor.name,
85
+ error: error,
86
+ });
87
+ }
66
88
  if (!response.ok) {
89
+ if (this.options.retry && RETRYABLE_ERROR_CODES.includes(response.status) &&
90
+ retryCount < this.options.retry.maxRetries) {
91
+ const delay = this.options.retry.delay;
92
+ await new Promise((resolve) => setTimeout(resolve, delay));
93
+ return this.innerExecute(command, retryCount + 1);
94
+ }
67
95
  const body = await response.json().catch(() => undefined);
68
96
  const commandName = command.constructor.name;
69
97
  throw new client_error_js_1.ClientError(`${commandName} failed with ${response.status}: ${response.statusText}`, response.status, body);
@@ -72,5 +100,11 @@ class FlowcoreClient {
72
100
  const parsedBody = await request.parseResponse(body, this);
73
101
  return request.waitForResponse(this, parsedBody);
74
102
  }
103
+ /**
104
+ * Execute a command
105
+ */
106
+ execute(command) {
107
+ return this.innerExecute(command, 0);
108
+ }
75
109
  }
76
110
  exports.FlowcoreClient = FlowcoreClient;
@@ -1,4 +1,5 @@
1
1
  export type { DataCore } from "./data-core.js";
2
2
  export type { EventType } from "./event-type.js";
3
3
  export type { FlowType } from "./flow-type.js";
4
+ export type { FlowcoreEvent } from "./event.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}