@tapi-dev/sdk 0.1.17 → 0.1.20

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/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { CatalogResource } from "./catalog.js";
3
3
  import { RunnersResource } from "./runners.js";
4
4
  import { RunsResource } from "./runs.js";
5
5
  import { RuntimeResource } from "./runtime.js";
6
+ import { SessionsResource } from "./sessions.js";
6
7
  import { TriggersResource } from "./triggers.js";
7
8
  import type { TapiClientOptions } from "./types.js";
8
9
  import { WebsiteApisResource } from "./website-apis.js";
@@ -12,10 +13,13 @@ export declare class TapiClient {
12
13
  readonly runners: RunnersResource;
13
14
  readonly runs: RunsResource;
14
15
  readonly runtime: RuntimeResource;
16
+ readonly sessions: SessionsResource;
15
17
  readonly triggers: TriggersResource;
16
18
  readonly websiteApis: WebsiteApisResource;
17
19
  constructor(options: TapiClientOptions);
18
20
  }
19
21
  export * from "./errors.js";
22
+ export * from "./late-input.js";
23
+ export * from "./sessions.js";
20
24
  export * from "./types.js";
21
25
  export * from "./workspace.js";
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { CatalogResource } from "./catalog.js";
4
4
  import { RunnersResource } from "./runners.js";
5
5
  import { RunsResource } from "./runs.js";
6
6
  import { RuntimeResource } from "./runtime.js";
7
+ import { SessionsResource } from "./sessions.js";
7
8
  import { TriggersResource } from "./triggers.js";
8
9
  import { WebsiteApisResource } from "./website-apis.js";
9
10
  export class TapiClient {
@@ -12,6 +13,7 @@ export class TapiClient {
12
13
  runners;
13
14
  runs;
14
15
  runtime;
16
+ sessions;
15
17
  triggers;
16
18
  websiteApis;
17
19
  constructor(options) {
@@ -21,10 +23,13 @@ export class TapiClient {
21
23
  this.runners = new RunnersResource(http);
22
24
  this.runs = new RunsResource(http);
23
25
  this.runtime = new RuntimeResource(http, options);
26
+ this.sessions = new SessionsResource(http);
24
27
  this.triggers = new TriggersResource(http);
25
- this.websiteApis = new WebsiteApisResource(http);
28
+ this.websiteApis = new WebsiteApisResource(http, options);
26
29
  }
27
30
  }
28
31
  export * from "./errors.js";
32
+ export * from "./late-input.js";
33
+ export * from "./sessions.js";
29
34
  export * from "./types.js";
30
35
  export * from "./workspace.js";
@@ -0,0 +1,24 @@
1
+ export interface LateInputOptions<T> {
2
+ resolve?: () => T | Promise<T>;
3
+ timeoutMs?: number;
4
+ }
5
+ export interface LateInput<T = unknown> {
6
+ readonly __tapiLateInput: true;
7
+ set(value: T): Promise<void>;
8
+ waitForProvides(): Promise<void>;
9
+ }
10
+ type Provider = (runId: string, inputKey: string, value: unknown) => Promise<unknown>;
11
+ export declare function lateInput<T = unknown>(options?: LateInputOptions<T>): LateInput<T>;
12
+ export declare function isLateInput(value: unknown): value is LateInput<unknown>;
13
+ export declare function serializeInputs(inputs: Record<string, unknown> | undefined): {
14
+ bodyInputs: Record<string, unknown> | undefined;
15
+ lateInputs: Array<{
16
+ key: string;
17
+ input: LateInput<unknown>;
18
+ }>;
19
+ };
20
+ export declare function attachLateInputs(lateInputs: Array<{
21
+ key: string;
22
+ input: LateInput<unknown>;
23
+ }>, runId: string, provider: Provider): void;
24
+ export {};
@@ -0,0 +1,112 @@
1
+ class TapiLateInput {
2
+ __tapiLateInput = true;
3
+ timeoutMs;
4
+ resolver;
5
+ resolverStarted = false;
6
+ resolverPromise;
7
+ hasResolverError = false;
8
+ resolverError;
9
+ resolved = false;
10
+ resolvedValue;
11
+ bindings = [];
12
+ providePromises = [];
13
+ constructor(options = {}) {
14
+ this.resolver = options.resolve;
15
+ this.timeoutMs = options.timeoutMs;
16
+ }
17
+ async set(value) {
18
+ if (this.resolved) {
19
+ throw new Error("late input has already been set");
20
+ }
21
+ this.resolved = true;
22
+ this.resolvedValue = value;
23
+ this.provide(value);
24
+ await Promise.all(this.providePromises);
25
+ }
26
+ provide(value) {
27
+ for (const binding of this.bindings) {
28
+ this.providePromises.push(binding.provider(binding.runId, binding.inputKey, value));
29
+ }
30
+ }
31
+ async waitForProvides() {
32
+ if (this.resolverPromise) {
33
+ await this.resolverPromise;
34
+ }
35
+ if (this.hasResolverError) {
36
+ throw this.resolverError;
37
+ }
38
+ await Promise.all(this.providePromises);
39
+ }
40
+ attach(binding) {
41
+ this.bindings.push(binding);
42
+ if (this.resolved) {
43
+ this.provide(this.resolvedValue);
44
+ return;
45
+ }
46
+ this.startResolver();
47
+ }
48
+ toWire() {
49
+ return {
50
+ __tapiLateInput: true,
51
+ ...(typeof this.timeoutMs === "number" ? { timeoutMs: this.timeoutMs } : {}),
52
+ };
53
+ }
54
+ startResolver() {
55
+ if (!this.resolver || this.resolverStarted) {
56
+ return;
57
+ }
58
+ this.resolverStarted = true;
59
+ let resolverClaimedValue = false;
60
+ this.resolverPromise = Promise.resolve()
61
+ .then(() => this.resolver?.())
62
+ .then(async (value) => {
63
+ if (this.resolved) {
64
+ return;
65
+ }
66
+ resolverClaimedValue = true;
67
+ this.resolved = true;
68
+ this.resolvedValue = value;
69
+ this.provide(this.resolvedValue);
70
+ await Promise.all(this.providePromises);
71
+ })
72
+ .catch((error) => {
73
+ if (resolverClaimedValue || !this.resolved) {
74
+ this.hasResolverError = true;
75
+ this.resolverError = error;
76
+ }
77
+ });
78
+ }
79
+ }
80
+ export function lateInput(options = {}) {
81
+ return new TapiLateInput(options);
82
+ }
83
+ export function isLateInput(value) {
84
+ return Boolean(value
85
+ && typeof value === "object"
86
+ && value.__tapiLateInput === true
87
+ && typeof value.set === "function");
88
+ }
89
+ export function serializeInputs(inputs) {
90
+ if (inputs === undefined) {
91
+ return { bodyInputs: undefined, lateInputs: [] };
92
+ }
93
+ const bodyInputs = {};
94
+ const lateInputs = [];
95
+ for (const [key, value] of Object.entries(inputs)) {
96
+ if (isLateInput(value)) {
97
+ const late = value;
98
+ bodyInputs[key] = late.toWire();
99
+ lateInputs.push({ key, input: value });
100
+ }
101
+ else {
102
+ bodyInputs[key] = value;
103
+ }
104
+ }
105
+ return { bodyInputs, lateInputs };
106
+ }
107
+ export function attachLateInputs(lateInputs, runId, provider) {
108
+ for (const item of lateInputs) {
109
+ const late = item.input;
110
+ late.attach({ runId, inputKey: item.key, provider });
111
+ }
112
+ }
package/dist/runs.d.ts CHANGED
@@ -5,6 +5,7 @@ export declare class RunsResource {
5
5
  constructor(http: HttpClient);
6
6
  get(runId: string): Promise<TapiRun>;
7
7
  cancel(runId: string): Promise<TapiRun>;
8
+ provideInput(runId: string, inputKey: string, value: unknown): Promise<TapiRun>;
8
9
  wait(runId: string, options?: {
9
10
  intervalMs?: number;
10
11
  timeoutMs?: number;
package/dist/runs.js CHANGED
@@ -9,6 +9,9 @@ export class RunsResource {
9
9
  cancel(runId) {
10
10
  return this.http.post(`/api/sdk/v1/runs/${encodeURIComponent(runId)}/cancel`);
11
11
  }
12
+ provideInput(runId, inputKey, value) {
13
+ return this.http.post(`/api/sdk/v1/runs/${encodeURIComponent(runId)}/inputs/${encodeURIComponent(inputKey)}`, { value });
14
+ }
12
15
  async wait(runId, options = {}) {
13
16
  const intervalMs = options.intervalMs ?? 1000;
14
17
  const deadline = Date.now() + (options.timeoutMs ?? 300000);
@@ -0,0 +1,10 @@
1
+ import type { HttpClient } from "./client.js";
2
+ import type { TapiDevSessionsList } from "./types.js";
3
+ export interface TapiDevSessionsListOptions {
4
+ site?: string;
5
+ }
6
+ export declare class SessionsResource {
7
+ private readonly http;
8
+ constructor(http: HttpClient);
9
+ list(options?: TapiDevSessionsListOptions): Promise<TapiDevSessionsList>;
10
+ }
@@ -0,0 +1,14 @@
1
+ export class SessionsResource {
2
+ http;
3
+ constructor(http) {
4
+ this.http = http;
5
+ }
6
+ list(options = {}) {
7
+ const params = new URLSearchParams();
8
+ if (options.site) {
9
+ params.set("site", options.site);
10
+ }
11
+ const query = params.toString();
12
+ return this.http.get(`/api/sdk/v1/dev/sessions${query ? `?${query}` : ""}`);
13
+ }
14
+ }
package/dist/types.d.ts CHANGED
@@ -1,14 +1,16 @@
1
- export type RunStatus = "queued" | "running" | "completed" | "failed" | "cancelled" | "needs_developer_attention";
1
+ import type { LateInput } from "./late-input.js";
2
+ export type RunStatus = "queued" | "running" | "waiting_for_input" | "completed" | "failed" | "cancelled" | "needs_developer_attention";
2
3
  export interface TapiClientOptions {
3
4
  baseUrl: string;
4
5
  apiKey: string;
5
6
  projectId?: string;
7
+ dev?: boolean;
6
8
  fetch?: typeof fetch;
7
9
  localControlUrl?: string;
8
10
  webSocket?: LocalWebSocketConstructor;
9
11
  }
10
12
  export interface WebsiteApiRunRequest {
11
- inputs?: Record<string, unknown>;
13
+ inputs?: Record<string, unknown | LateInput<unknown>>;
12
14
  runtime?: RuntimeRunOptions;
13
15
  priority?: number;
14
16
  runnerId?: string;
@@ -218,10 +220,51 @@ export interface TapiRun {
218
220
  result?: Record<string, unknown> | null;
219
221
  error?: Record<string, unknown> | null;
220
222
  runtime?: RuntimeRunOptions | Record<string, unknown> | null;
223
+ waitingInput?: WebsiteApiWaitingInput | null;
224
+ pendingInputs?: WebsiteApiWaitingInput[];
221
225
  createdAt?: string;
222
226
  updatedAt?: string;
223
227
  [key: string]: unknown;
224
228
  }
229
+ export type TapiDevSessionStatus = "queued" | "running" | "waiting_for_input" | "awaiting_takeover" | "needs_developer_attention" | "completed" | "failed" | "cancelled" | string;
230
+ export interface TapiDevSession {
231
+ id: string;
232
+ projectId: string;
233
+ sitemap: string;
234
+ site?: string;
235
+ apiName: string;
236
+ requestKey: string;
237
+ status: TapiDevSessionStatus;
238
+ stateId?: number | null;
239
+ stateLabel?: string;
240
+ currentUrl?: string;
241
+ profileRef?: string;
242
+ runtimeSessionId?: string;
243
+ deviceId?: string;
244
+ live: boolean;
245
+ openable: boolean;
246
+ dev: boolean;
247
+ updatedAt?: string;
248
+ createdAt?: string;
249
+ [key: string]: unknown;
250
+ }
251
+ export interface TapiDevSessionGroup {
252
+ sitemap: string;
253
+ sessions: TapiDevSession[];
254
+ }
255
+ export interface TapiDevSessionsList {
256
+ projectId: string;
257
+ groups: TapiDevSessionGroup[];
258
+ }
259
+ export interface WebsiteApiWaitingInput {
260
+ key: string;
261
+ label?: string;
262
+ stateId?: number;
263
+ actionId?: string;
264
+ control?: string;
265
+ timeoutMs?: number;
266
+ [key: string]: unknown;
267
+ }
225
268
  export interface TapiRunner {
226
269
  id: string;
227
270
  status: string;
@@ -1,8 +1,10 @@
1
1
  import type { HttpClient } from "./client.js";
2
2
  import type { CloudBatchRun, CloudRunQuote, TapiRun, WebsiteApiCloudBatchRequest, WebsiteApiCloudQuoteRequest, WebsiteApiOperation, WebsiteApiRunRequest } from "./types.js";
3
+ import type { TapiClientOptions } from "./types.js";
3
4
  export declare class WebsiteApisResource {
4
5
  private readonly http;
5
- constructor(http: HttpClient);
6
+ private readonly dev;
7
+ constructor(http: HttpClient, options: TapiClientOptions);
6
8
  run(apiRequest: string, request?: WebsiteApiRunRequest): Promise<TapiRun>;
7
9
  quoteCloud(apiRequest: string, request?: WebsiteApiCloudQuoteRequest): Promise<CloudRunQuote>;
8
10
  runCloud(apiRequest: string, request?: WebsiteApiRunRequest & {
@@ -1,12 +1,25 @@
1
1
  import { TapiError } from "./errors.js";
2
+ import { attachLateInputs, serializeInputs } from "./late-input.js";
2
3
  export class WebsiteApisResource {
3
4
  http;
4
- constructor(http) {
5
+ dev;
6
+ constructor(http, options) {
5
7
  this.http = http;
8
+ this.dev = options.dev === true;
6
9
  }
7
- run(apiRequest, request = {}) {
10
+ async run(apiRequest, request = {}) {
8
11
  const { apiName, requestKey } = splitApiRequest(apiRequest);
9
- return this.http.post(`/api/sdk/v1/website-apis/${encodeURIComponent(apiName)}/requests/${encodeURIComponent(requestKey)}/runs`, request);
12
+ const { bodyInputs, lateInputs } = serializeInputs(request.inputs);
13
+ const body = {
14
+ ...request,
15
+ ...(bodyInputs === undefined ? {} : { inputs: bodyInputs }),
16
+ ...(this.dev ? { dev: true } : {}),
17
+ };
18
+ const run = await this.http.post(`/api/sdk/v1/website-apis/${encodeURIComponent(apiName)}/requests/${encodeURIComponent(requestKey)}/runs`, body);
19
+ if (run.id && lateInputs.length > 0) {
20
+ attachLateInputs(lateInputs, run.id, (runId, inputKey, value) => this.http.post(`/api/sdk/v1/runs/${encodeURIComponent(runId)}/inputs/${encodeURIComponent(inputKey)}`, { value }));
21
+ }
22
+ return run;
10
23
  }
11
24
  quoteCloud(apiRequest, request = {}) {
12
25
  const { apiName, requestKey } = splitApiRequest(apiRequest);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapi-dev/sdk",
3
- "version": "0.1.17",
3
+ "version": "0.1.20",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",