@sinecloud/api-client 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sine Cloud
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,11 @@
1
- # Temporary Holding Version
1
+ # @sinecloud/api-client
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Shared runtime contracts for the first-party clients. Published alongside `@sinecloud/sdk` with the same version; it has no dependencies.
4
+
5
+ - `waitForTerminal`: the one polling loop used by the CLI and the SDK. Read-only by design; a
6
+ timeout, an unreadable status or an abort raises `WaitError` so callers can classify the
7
+ outcome as unknown instead of failed.
8
+ - Terminal status tables per product. `unknown` and `reconciliation` are deliberately absent:
9
+ they need inspection, not a retry.
10
+
11
+ Nothing here performs I/O; both clients supply their own `read` function and transport.
@@ -0,0 +1,4 @@
1
+ export { WaitError, waitForTerminal } from './wait.js';
2
+ export type { WaitFailure, WaitForTerminalOptions } from './wait.js';
3
+ export { boxExecutionTerminalStatuses, gatewayTaskTerminalStatuses, powersRunTerminalStatuses } from './statuses.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { WaitError, waitForTerminal } from './wait.js';
2
+ export { boxExecutionTerminalStatuses, gatewayTaskTerminalStatuses, powersRunTerminalStatuses } from './statuses.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEvD,OAAO,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Terminal status sets for the durable work the first-party clients poll.
3
+ *
4
+ * These are contract facts, not OpenAPI data: a document can list a status enum but cannot say
5
+ * which values mean "stop waiting". Keeping them here means the CLI and the SDK cannot disagree
6
+ * about when a paid submission is finished, and `unknown`/`reconciliation` are never mistaken
7
+ * for failure.
8
+ */
9
+ /** Box execution status: `reconciliation` still awaits financial resolution. */
10
+ export declare const boxExecutionTerminalStatuses: Readonly<Record<string, true>>;
11
+ /** Gateway task status: `unknown` needs inspection, not a retry. */
12
+ export declare const gatewayTaskTerminalStatuses: Readonly<Record<string, true>>;
13
+ /** Powers run status: `UNKNOWN` is an undetermined outcome, not a failure. */
14
+ export declare const powersRunTerminalStatuses: Readonly<Record<string, true>>;
15
+ //# sourceMappingURL=statuses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statuses.d.ts","sourceRoot":"","sources":["../src/statuses.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gFAAgF;AAChF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAqC,CAAC;AAE9G,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAEtE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAEpE,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Terminal status sets for the durable work the first-party clients poll.
3
+ *
4
+ * These are contract facts, not OpenAPI data: a document can list a status enum but cannot say
5
+ * which values mean "stop waiting". Keeping them here means the CLI and the SDK cannot disagree
6
+ * about when a paid submission is finished, and `unknown`/`reconciliation` are never mistaken
7
+ * for failure.
8
+ */
9
+ /** Box execution status: `reconciliation` still awaits financial resolution. */
10
+ export const boxExecutionTerminalStatuses = { settled: true, released: true };
11
+ /** Gateway task status: `unknown` needs inspection, not a retry. */
12
+ export const gatewayTaskTerminalStatuses = {
13
+ completed: true, failed: true, cancelled: true, expired: true,
14
+ };
15
+ /** Powers run status: `UNKNOWN` is an undetermined outcome, not a failure. */
16
+ export const powersRunTerminalStatuses = {
17
+ SUCCEEDED: true, PROVIDER_ERROR: true, EXECUTOR_ERROR: true, FAILED: true,
18
+ };
19
+ //# sourceMappingURL=statuses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statuses.js","sourceRoot":"","sources":["../src/statuses.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gFAAgF;AAChF,MAAM,CAAC,MAAM,4BAA4B,GAAmC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAE9G,oEAAoE;AACpE,MAAM,CAAC,MAAM,2BAA2B,GAAmC;IACzE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI;CAC9D,CAAC;AAEF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,yBAAyB,GAAmC;IACvE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI;CAC1E,CAAC"}
package/dist/wait.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ export type WaitFailure = 'timeout' | 'unreadableStatus' | 'aborted';
2
+ /** The wait ended without a terminal state; the work may still be running. */
3
+ export declare class WaitError extends Error {
4
+ readonly reason: WaitFailure;
5
+ constructor(message: string, reason: WaitFailure);
6
+ }
7
+ export interface WaitForTerminalOptions<T> {
8
+ /** One read of the durable resource. Must not submit or mutate anything. */
9
+ read: () => Promise<T>;
10
+ statusOf: (value: T) => unknown;
11
+ terminal: Readonly<Record<string, true>>;
12
+ timeoutMs: number;
13
+ initialDelayMs?: number;
14
+ maxDelayMs?: number;
15
+ now?: () => number;
16
+ sleep?: (milliseconds: number) => Promise<void>;
17
+ signal?: AbortSignal;
18
+ onPoll?: (status: string | undefined, value: T) => void;
19
+ }
20
+ /**
21
+ * Poll a durable resource until it reaches a terminal status.
22
+ *
23
+ * The first read happens after the initial delay: the caller has just received the submission
24
+ * response, so an immediate read only adds a round trip. Exponential backoff caps at
25
+ * `maxDelayMs`. A timeout, an unreadable status or an abort raises `WaitError`; callers translate
26
+ * that into "unknown outcome" and must recover with the original identity instead of resending.
27
+ */
28
+ export declare function waitForTerminal<T>(options: WaitForTerminalOptions<T>): Promise<T>;
29
+ //# sourceMappingURL=wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAAC;AAErE,8EAA8E;AAC9E,qBAAa,SAAU,SAAQ,KAAK;IACL,QAAQ,CAAC,MAAM,EAAE,WAAW;IAAzD,YAAY,OAAO,EAAE,MAAM,EAAW,MAAM,EAAE,WAAW,EAGxD;CACF;AAED,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAChC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CACzD;AAQD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAmBvF"}
package/dist/wait.js ADDED
@@ -0,0 +1,48 @@
1
+ /** The wait ended without a terminal state; the work may still be running. */
2
+ export class WaitError extends Error {
3
+ reason;
4
+ constructor(message, reason) {
5
+ super(message);
6
+ this.reason = reason;
7
+ this.name = 'WaitError';
8
+ }
9
+ }
10
+ function defaultSleep(milliseconds) {
11
+ const { promise, resolve } = Promise.withResolvers();
12
+ setTimeout(resolve, milliseconds);
13
+ return promise;
14
+ }
15
+ /**
16
+ * Poll a durable resource until it reaches a terminal status.
17
+ *
18
+ * The first read happens after the initial delay: the caller has just received the submission
19
+ * response, so an immediate read only adds a round trip. Exponential backoff caps at
20
+ * `maxDelayMs`. A timeout, an unreadable status or an abort raises `WaitError`; callers translate
21
+ * that into "unknown outcome" and must recover with the original identity instead of resending.
22
+ */
23
+ export async function waitForTerminal(options) {
24
+ const now = options.now ?? (() => Date.now());
25
+ const sleep = options.sleep ?? defaultSleep;
26
+ const deadline = now() + options.timeoutMs;
27
+ let delay = options.initialDelayMs ?? 1_000;
28
+ for (;;) {
29
+ if (options.signal?.aborted)
30
+ throw new WaitError('The wait was aborted.', 'aborted');
31
+ const remaining = deadline - now();
32
+ if (remaining <= 0)
33
+ throw new WaitError('The resource did not reach a terminal state before the deadline.', 'timeout');
34
+ await sleep(Math.min(delay, remaining));
35
+ delay = Math.min(options.maxDelayMs ?? 5_000, delay * 2);
36
+ if (options.signal?.aborted)
37
+ throw new WaitError('The wait was aborted.', 'aborted');
38
+ const value = await options.read();
39
+ const raw = options.statusOf(value);
40
+ const status = typeof raw === 'string' && raw !== '' ? raw : undefined;
41
+ options.onPoll?.(status, value);
42
+ if (status !== undefined && Object.hasOwn(options.terminal, status))
43
+ return value;
44
+ if (status === undefined)
45
+ throw new WaitError('The resource has no readable status.', 'unreadableStatus');
46
+ }
47
+ }
48
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.js","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,MAAM,OAAO,SAAU,SAAQ,KAAK;IACI,MAAM;IAA5C,YAAY,OAAe,EAAW,MAAmB;QACvD,KAAK,CAAC,OAAO,CAAC,CAAC;sBADqB,MAAM;QAE1C,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAgBD,SAAS,YAAY,CAAC,YAAoB;IACxC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAC3D,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAI,OAAkC;IACzE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC;IAC5C,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAC3C,IAAI,KAAK,GAAG,OAAO,CAAC,cAAc,IAAI,KAAK,CAAC;IAC5C,SAAS,CAAC;QACR,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,SAAS,CAAC,uBAAuB,EAAE,SAAS,CAAC,CAAC;QACrF,MAAM,SAAS,GAAG,QAAQ,GAAG,GAAG,EAAE,CAAC;QACnC,IAAI,SAAS,IAAI,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,kEAAkE,EAAE,SAAS,CAAC,CAAC;QACvH,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;QACxC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACzD,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,SAAS,CAAC,uBAAuB,EAAE,SAAS,CAAC,CAAC;QACrF,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACvE,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QAClF,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,IAAI,SAAS,CAAC,sCAAsC,EAAE,kBAAkB,CAAC,CAAC;IAC5G,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "@sinecloud/api-client",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Shared polling and terminal-status contracts for the first-party Sine Cloud clients.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "README.md",
16
+ "LICENSE"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/fei-bai-inc/sinecloud.git",
21
+ "directory": "packages/api-client"
22
+ },
23
+ "homepage": "https://docs.sinecloud.dev/sdk",
24
+ "bugs": {
25
+ "url": "https://github.com/fei-bai-inc/sinecloud/issues"
26
+ },
27
+ "keywords": [
28
+ "sinecloud",
29
+ "sdk",
30
+ "polling",
31
+ "task"
32
+ ],
33
+ "engines": {
34
+ "node": ">=22.12.0"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public",
38
+ "registry": "https://registry.npmjs.org/"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.build.json",
42
+ "typecheck": "tsc --noEmit -p tsconfig.json"
43
+ }
6
44
  }