@getuserfeedback/protocol 3.1.2 → 3.1.4

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.
@@ -0,0 +1,16 @@
1
+ export type FlowCommandHandleController<THandleId extends string, TSettlement> = {
2
+ runCommand<TPayload>(buildPayload: (handleId: THandleId | undefined) => TPayload, dispatchAndWait: (payload: TPayload) => Promise<TSettlement>): Promise<TSettlement>;
3
+ getHandleId(): THandleId | undefined;
4
+ hasHandleId(handleId: string): boolean;
5
+ hasPendingCommands(): boolean;
6
+ subscribeHandle(subscriber: (handleId: THandleId) => void): () => void;
7
+ clearResolvedHandle(): THandleId | undefined;
8
+ reset(): void;
9
+ };
10
+ export type CreateFlowCommandHandleControllerOptions<THandleId extends string, TSettlement> = {
11
+ getHandleIdFromSettlement: (settlement: TSettlement) => THandleId | undefined;
12
+ isStaleHandleError: (error: unknown) => boolean;
13
+ onClearResolvedHandle?: (handleId: THandleId) => void;
14
+ };
15
+ export declare function createFlowCommandHandleController<THandleId extends string, TSettlement>({ getHandleIdFromSettlement, isStaleHandleError, onClearResolvedHandle, }: CreateFlowCommandHandleControllerOptions<THandleId, TSettlement>): FlowCommandHandleController<THandleId, TSettlement>;
16
+ //# sourceMappingURL=flow-command-handle-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-command-handle-controller.d.ts","sourceRoot":"","sources":["../../src/host/flow-command-handle-controller.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,2BAA2B,CACtC,SAAS,SAAS,MAAM,EACxB,WAAW,IACR;IACH,UAAU,CAAC,QAAQ,EAClB,YAAY,EAAE,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,KAAK,QAAQ,EAC3D,eAAe,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,WAAW,CAAC,GAC1D,OAAO,CAAC,WAAW,CAAC,CAAC;IACxB,WAAW,IAAI,SAAS,GAAG,SAAS,CAAC;IACrC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,kBAAkB,IAAI,OAAO,CAAC;IAC9B,eAAe,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvE,mBAAmB,IAAI,SAAS,GAAG,SAAS,CAAC;IAC7C,KAAK,IAAI,IAAI,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,wCAAwC,CACnD,SAAS,SAAS,MAAM,EACxB,WAAW,IACR;IACH,yBAAyB,EAAE,CAAC,UAAU,EAAE,WAAW,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9E,kBAAkB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IAChD,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,wBAAgB,iCAAiC,CAChD,SAAS,SAAS,MAAM,EACxB,WAAW,EACV,EACD,yBAAyB,EACzB,kBAAkB,EAClB,qBAAqB,GACrB,EAAE,wCAAwC,CAC1C,SAAS,EACT,WAAW,CACX,GAAG,2BAA2B,CAAC,SAAS,EAAE,WAAW,CAAC,CA6CtD"}
@@ -0,0 +1,39 @@
1
+ import { createLazyHandleClient, } from "./lazy-handle-client.js";
2
+ export function createFlowCommandHandleController({ getHandleIdFromSettlement, isStaleHandleError, onClearResolvedHandle, }) {
3
+ const handleClient = createLazyHandleClient({
4
+ getHandleIdFromSettlement,
5
+ });
6
+ const clearResolvedHandle = () => {
7
+ const previousHandleId = handleClient.getHandleId();
8
+ if (!previousHandleId) {
9
+ return undefined;
10
+ }
11
+ handleClient.reset();
12
+ onClearResolvedHandle?.(previousHandleId);
13
+ return previousHandleId;
14
+ };
15
+ const reset = () => {
16
+ const previousHandleId = handleClient.getHandleId();
17
+ handleClient.reset();
18
+ if (previousHandleId) {
19
+ onClearResolvedHandle?.(previousHandleId);
20
+ }
21
+ };
22
+ const runCommand = async (buildPayload, dispatchAndWait) => {
23
+ return handleClient.runCommandWithRetry(buildPayload, dispatchAndWait, {
24
+ shouldRetry: isStaleHandleError,
25
+ onBeforeRetry: () => {
26
+ clearResolvedHandle();
27
+ },
28
+ });
29
+ };
30
+ return {
31
+ runCommand,
32
+ getHandleId: () => handleClient.getHandleId(),
33
+ hasHandleId: (handleId) => handleClient.getHandleId() === handleId,
34
+ hasPendingCommands: () => handleClient.hasPendingCommands(),
35
+ subscribeHandle: (subscriber) => handleClient.subscribeHandle(subscriber),
36
+ clearResolvedHandle,
37
+ reset,
38
+ };
39
+ }
@@ -6,6 +6,7 @@ export * from "./command-envelope.js";
6
6
  export * from "./command-settlement.js";
7
7
  export * from "./constants.js";
8
8
  export * from "./external-id-argument-guards.js";
9
+ export * from "./flow-command-handle-controller.js";
9
10
  export * from "./host-event-contract.js";
10
11
  export * from "./lazy-handle-client.js";
11
12
  export { createCommandRequestId } from "./request-id.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kCAAkC,CAAC;AACjD,cAAc,qCAAqC,CAAC;AACpD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC"}
@@ -6,6 +6,7 @@ export * from "./command-envelope.js";
6
6
  export * from "./command-settlement.js";
7
7
  export * from "./constants.js";
8
8
  export * from "./external-id-argument-guards.js";
9
+ export * from "./flow-command-handle-controller.js";
9
10
  export * from "./host-event-contract.js";
10
11
  export * from "./lazy-handle-client.js";
11
12
  export { createCommandRequestId } from "./request-id.js";
@@ -8,7 +8,12 @@ type StageMap<TStage extends string> = {
8
8
  };
9
9
  export type LazyHandleClient<THandleId extends string, TSettlement, TStage extends string = LifecycleStage> = {
10
10
  runCommand<TPayload>(buildPayload: (handleId: THandleId | undefined) => TPayload, dispatchAndWait: (payload: TPayload) => Promise<TSettlement>): Promise<TSettlement>;
11
+ runCommandWithRetry<TPayload>(buildPayload: (handleId: THandleId | undefined) => TPayload, dispatchAndWait: (payload: TPayload) => Promise<TSettlement>, options: {
12
+ shouldRetry: (error: unknown) => boolean;
13
+ onBeforeRetry?: (error: unknown) => void;
14
+ }): Promise<TSettlement>;
11
15
  getHandleId(): THandleId | undefined;
16
+ hasPendingCommands(): boolean;
12
17
  subscribeHandle(subscriber: Subscriber<THandleId>): () => void;
13
18
  getStage(): TStage;
14
19
  setStage(stage: TStage): void;
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-handle-client.d.ts","sourceRoot":"","sources":["../../src/host/lazy-handle-client.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,CAAC,SAAS,SAAS,MAAM,IAAI,CAAC,QAAQ,EAAE,SAAS,KAAK,IAAI,CAAC;AAC1E,KAAK,eAAe,CAAC,MAAM,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAEtE,KAAK,cAAc,GAAG,eAAe,GAAG,OAAO,GAAG,aAAa,CAAC;AAChE,KAAK,QAAQ,CAAC,MAAM,SAAS,MAAM,IAAI;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF,MAAM,MAAM,gBAAgB,CAC3B,SAAS,SAAS,MAAM,EACxB,WAAW,EACX,MAAM,SAAS,MAAM,GAAG,cAAc,IACnC;IACH,UAAU,CAAC,QAAQ,EAClB,YAAY,EAAE,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,KAAK,QAAQ,EAC3D,eAAe,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,WAAW,CAAC,GAC1D,OAAO,CAAC,WAAW,CAAC,CAAC;IACxB,WAAW,IAAI,SAAS,GAAG,SAAS,CAAC;IACrC,eAAe,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,MAAM,IAAI,CAAC;IAC/D,QAAQ,IAAI,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC;IAChE,KAAK,IAAI,IAAI,CAAC;IACd,UAAU,IAAI,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,6BAA6B,CACxC,SAAS,SAAS,MAAM,EACxB,WAAW,EACX,MAAM,SAAS,MAAM,GAAG,cAAc,IACnC;IACH,yBAAyB,EAAE,CAAC,UAAU,EAAE,WAAW,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9E,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,KAAK,oCAAoC,CACxC,SAAS,SAAS,MAAM,EACxB,WAAW,IACR;IACH,yBAAyB,EAAE,CAAC,UAAU,EAAE,WAAW,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9E,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,KAAK,mCAAmC,CACvC,SAAS,SAAS,MAAM,EACxB,WAAW,EACX,MAAM,SAAS,MAAM,IAClB;IACH,yBAAyB,EAAE,CAAC,UAAU,EAAE,WAAW,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9E,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAuHF,wBAAgB,sBAAsB,CAAC,SAAS,SAAS,MAAM,EAAE,WAAW,EAC3E,OAAO,EAAE,oCAAoC,CAAC,SAAS,EAAE,WAAW,CAAC,GACnE,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;AAC5D,wBAAgB,sBAAsB,CACrC,SAAS,SAAS,MAAM,EACxB,WAAW,EACX,MAAM,SAAS,MAAM,EAErB,OAAO,EAAE,mCAAmC,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,GAC1E,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"lazy-handle-client.d.ts","sourceRoot":"","sources":["../../src/host/lazy-handle-client.ts"],"names":[],"mappings":"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"}
@@ -62,9 +62,49 @@ const createLazyHandleClientWithStages = (input) => {
62
62
  });
63
63
  return run;
64
64
  };
65
+ const runCommandWithRetry = (buildPayload, dispatchAndWait, options) => {
66
+ const execute = async () => {
67
+ let didRetry = false;
68
+ for (;;) {
69
+ if (stage === stages.invalidated) {
70
+ throw new Error("Handle client is invalidated");
71
+ }
72
+ const commandEpoch = epoch;
73
+ const payload = buildPayload(handleId);
74
+ try {
75
+ const settlement = await dispatchAndWait(payload);
76
+ const settledHandleId = input.getHandleIdFromSettlement(settlement);
77
+ if (settledHandleId && commandEpoch === epoch) {
78
+ publishHandle(settledHandleId);
79
+ }
80
+ return settlement;
81
+ }
82
+ catch (error) {
83
+ if (commandEpoch === epoch &&
84
+ !didRetry &&
85
+ options.shouldRetry(error)) {
86
+ didRetry = true;
87
+ options.onBeforeRetry?.(error);
88
+ continue;
89
+ }
90
+ throw error;
91
+ }
92
+ }
93
+ };
94
+ const run = queuedCommandCount === 0 ? execute() : tail.then(execute, execute);
95
+ queuedCommandCount += 1;
96
+ tail = run.then(() => {
97
+ queuedCommandCount -= 1;
98
+ }, () => {
99
+ queuedCommandCount -= 1;
100
+ });
101
+ return run;
102
+ };
65
103
  return {
66
104
  runCommand,
105
+ runCommandWithRetry,
67
106
  getHandleId: () => handleId,
107
+ hasPendingCommands: () => queuedCommandCount > 0,
68
108
  subscribeHandle: (subscriber) => {
69
109
  subscribers.add(subscriber);
70
110
  if (handleId) {
@@ -4,6 +4,8 @@
4
4
  */
5
5
  export { createCommandDispatch } from "./command-dispatch.js";
6
6
  export { COMMAND_SETTLEMENT_TIMEOUT_CODE, CommandSettlementError, CommandSettlementTimeoutError, toCommandSettlementError, waitForCommandSettlement, } from "./command-settlement.js";
7
+ export type { FlowCommandHandleController } from "./flow-command-handle-controller.js";
8
+ export { createFlowCommandHandleController } from "./flow-command-handle-controller.js";
7
9
  export type { FlowHandleFromSettlement, FlowState, } from "./host-event-contract.js";
8
10
  export { getFlowHandleFromSettlementDetail, isFlowStateChangedDetail, isHandleInvalidatedDetail, isInstanceFlowStateChangedDetail, } from "./host-event-contract.js";
9
11
  export type { AppEventCapability, AppEventFlag, AppEventFlagProvider, AppEventFlagValue, AppEventPayload, CapabilitiesInput, ClientMeta, ClientOptions, Command, CommandEnvelope, ConfigureOptions, ContainerPolicy, FlagsInput, InitOptions, PublicCommandPayload, ResponseMetadataInput, TelemetryEvent, } from "./sdk-types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/host/sdk.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACN,+BAA+B,EAC/B,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,GACxB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,wBAAwB,EACxB,SAAS,GACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,iCAAiC,EACjC,wBAAwB,EACxB,yBAAyB,EACzB,gCAAgC,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACX,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EAErB,cAAc,GACd,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/host/sdk.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACN,+BAA+B,EAC/B,sBAAsB,EACtB,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,GACxB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AACvF,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACxF,YAAY,EACX,wBAAwB,EACxB,SAAS,GACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,iCAAiC,EACjC,wBAAwB,EACxB,yBAAyB,EACzB,gCAAgC,GAChC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACX,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EAErB,cAAc,GACd,MAAM,gBAAgB,CAAC"}
package/dist/host/sdk.js CHANGED
@@ -4,4 +4,5 @@
4
4
  */
5
5
  export { createCommandDispatch } from "./command-dispatch.js";
6
6
  export { COMMAND_SETTLEMENT_TIMEOUT_CODE, CommandSettlementError, CommandSettlementTimeoutError, toCommandSettlementError, waitForCommandSettlement, } from "./command-settlement.js";
7
+ export { createFlowCommandHandleController } from "./flow-command-handle-controller.js";
7
8
  export { getFlowHandleFromSettlementDetail, isFlowStateChangedDetail, isHandleInvalidatedDetail, isInstanceFlowStateChangedDetail, } from "./host-event-contract.js";
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export { type FlowDisplaySyncRequest, type FlowDisplaySyncResponse, flowDisplayS
11
11
  export { buildIdentityTypeGuidanceMessage, getIdentityTypeSuggestion, IDENTITY_TYPE_VALUES, type IdentityTypeValue, isIdentityTypeValue, type StandardIdentityTypeValue, } from "./identity-type.js";
12
12
  export { type CaptureInstanceFeedbackRequest, type CaptureInstanceFeedbackResponse, captureInstanceFeedbackRequestSchema, captureInstanceFeedbackResponseSchema, type InstanceFeedbackDataType, type InstanceFeedbackMineFeedback, type InstanceFeedbackValence, instanceFeedbackDataTypeSchema, instanceFeedbackMineFeedbackSchema, instanceFeedbackValenceSchema, type ListInstanceFeedbackMineRequest, type ListInstanceFeedbackMineResponse, listInstanceFeedbackMineRequestSchema, listInstanceFeedbackMineResponseSchema, } from "./instance-feedback.js";
13
13
  export { type PreviewConnectionPairRequest, type PreviewConnectionPairResponse, previewConnectionPairRequestSchema, previewConnectionPairResponseSchema, } from "./preview-connection.js";
14
+ export { PREVIEW_FLOW_TRANSPORT_SOURCE, type PreviewFlowOpenCommand, type PreviewFlowOpenRequest, type PreviewFlowOpenResult, previewFlowOpenCommandSchema, previewFlowOpenRequestSchema, previewFlowOpenResultSchema, } from "./preview-flow-transport.js";
14
15
  export { PREVIEW_PAIRING_TRANSPORT_SOURCE, type PreviewPairingHostAck, type PreviewPairingHostRequest, type PreviewPairingHostResult, previewPairingHostAckSchema, previewPairingHostRequestSchema, previewPairingHostResultSchema, } from "./preview-pairing-transport.js";
15
16
  export { isPublicGrantScope, type PublicGrantScope, publicGrantScopeIdSchema, } from "./public-grant-scope.js";
16
17
  export { type RuntimeEndpoints, resolveApiBaseUrl, resolveCoreUrl, resolveRealtimeUrl, resolveTrpcBaseUrl, runtimeEndpointsSchema, } from "./runtime-endpoints.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ export { flowDisplaySyncRequestSchema, flowDisplaySyncResponseSchema, resolveFlo
10
10
  export { buildIdentityTypeGuidanceMessage, getIdentityTypeSuggestion, IDENTITY_TYPE_VALUES, isIdentityTypeValue, } from "./identity-type.js";
11
11
  export { captureInstanceFeedbackRequestSchema, captureInstanceFeedbackResponseSchema, instanceFeedbackDataTypeSchema, instanceFeedbackMineFeedbackSchema, instanceFeedbackValenceSchema, listInstanceFeedbackMineRequestSchema, listInstanceFeedbackMineResponseSchema, } from "./instance-feedback.js";
12
12
  export { previewConnectionPairRequestSchema, previewConnectionPairResponseSchema, } from "./preview-connection.js";
13
+ export { PREVIEW_FLOW_TRANSPORT_SOURCE, previewFlowOpenCommandSchema, previewFlowOpenRequestSchema, previewFlowOpenResultSchema, } from "./preview-flow-transport.js";
13
14
  export { PREVIEW_PAIRING_TRANSPORT_SOURCE, previewPairingHostAckSchema, previewPairingHostRequestSchema, previewPairingHostResultSchema, } from "./preview-pairing-transport.js";
14
15
  export { isPublicGrantScope, publicGrantScopeIdSchema, } from "./public-grant-scope.js";
15
16
  export { resolveApiBaseUrl, resolveCoreUrl, resolveRealtimeUrl, resolveTrpcBaseUrl, runtimeEndpointsSchema, } from "./runtime-endpoints.js";
@@ -0,0 +1,61 @@
1
+ import * as z from "zod/mini";
2
+ export declare const PREVIEW_FLOW_TRANSPORT_SOURCE = "getuserfeedback.preview";
3
+ export declare const previewFlowOpenCommandSchema: z.ZodMiniObject<{
4
+ kind: z.ZodMiniLiteral<"open">;
5
+ flow: z.ZodMiniObject<{
6
+ definition: z.ZodMiniUnknown;
7
+ theme: z.ZodMiniOptional<z.ZodMiniObject<{
8
+ css: z.ZodMiniOptional<z.ZodMiniString<string>>;
9
+ themeRuntimeArtifactId: z.ZodMiniOptional<z.ZodMiniString<string>>;
10
+ themeVersionId: z.ZodMiniOptional<z.ZodMiniString<string>>;
11
+ }, z.core.$strict>>;
12
+ }, z.core.$strict>;
13
+ flowHandleId: z.ZodMiniOptional<z.ZodMiniString<string>>;
14
+ metadata: z.ZodMiniOptional<z.ZodMiniObject<{
15
+ tags: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>>;
16
+ }, z.core.$strict>>;
17
+ hideCloseButton: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
18
+ }, z.core.$strict>;
19
+ export declare const previewFlowOpenRequestSchema: z.ZodMiniObject<{
20
+ source: z.ZodMiniLiteral<"getuserfeedback.preview">;
21
+ type: z.ZodMiniLiteral<"preview.flow.open.request">;
22
+ requestId: z.ZodMiniString<string>;
23
+ command: z.ZodMiniObject<{
24
+ kind: z.ZodMiniLiteral<"open">;
25
+ flow: z.ZodMiniObject<{
26
+ definition: z.ZodMiniUnknown;
27
+ theme: z.ZodMiniOptional<z.ZodMiniObject<{
28
+ css: z.ZodMiniOptional<z.ZodMiniString<string>>;
29
+ themeRuntimeArtifactId: z.ZodMiniOptional<z.ZodMiniString<string>>;
30
+ themeVersionId: z.ZodMiniOptional<z.ZodMiniString<string>>;
31
+ }, z.core.$strict>>;
32
+ }, z.core.$strict>;
33
+ flowHandleId: z.ZodMiniOptional<z.ZodMiniString<string>>;
34
+ metadata: z.ZodMiniOptional<z.ZodMiniObject<{
35
+ tags: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>>;
36
+ }, z.core.$strict>>;
37
+ hideCloseButton: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
38
+ }, z.core.$strict>;
39
+ }, z.core.$strict>;
40
+ export declare const previewFlowOpenResultSchema: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
41
+ source: z.ZodMiniLiteral<"getuserfeedback.preview">;
42
+ type: z.ZodMiniLiteral<"preview.flow.open.result">;
43
+ requestId: z.ZodMiniString<string>;
44
+ ok: z.ZodMiniLiteral<true>;
45
+ result: z.ZodMiniObject<{
46
+ flowHandleId: z.ZodMiniString<string>;
47
+ }, z.core.$strict>;
48
+ }, z.core.$strict>, z.ZodMiniObject<{
49
+ source: z.ZodMiniLiteral<"getuserfeedback.preview">;
50
+ type: z.ZodMiniLiteral<"preview.flow.open.result">;
51
+ requestId: z.ZodMiniString<string>;
52
+ ok: z.ZodMiniLiteral<false>;
53
+ error: z.ZodMiniObject<{
54
+ code: z.ZodMiniOptional<z.ZodMiniString<string>>;
55
+ message: z.ZodMiniString<string>;
56
+ }, z.core.$strict>;
57
+ }, z.core.$strict>], "ok">;
58
+ export type PreviewFlowOpenCommand = z.output<typeof previewFlowOpenCommandSchema>;
59
+ export type PreviewFlowOpenRequest = z.output<typeof previewFlowOpenRequestSchema>;
60
+ export type PreviewFlowOpenResult = z.output<typeof previewFlowOpenResultSchema>;
61
+ //# sourceMappingURL=preview-flow-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-flow-transport.d.ts","sourceRoot":"","sources":["../src/preview-flow-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAI9B,eAAO,MAAM,6BAA6B,4BAAmC,CAAC;AA8B9E,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;kBAMvC,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;kBAKvC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;0BAoBtC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAC5C,OAAO,4BAA4B,CACnC,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAC5C,OAAO,4BAA4B,CACnC,CAAC;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAC3C,OAAO,2BAA2B,CAClC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import * as z from "zod/mini";
2
+ import { PREVIEW_PAIRING_TRANSPORT_SOURCE } from "./preview-pairing-transport.js";
3
+ import { responseMetadataInputSchema } from "./response-metadata.js";
4
+ export const PREVIEW_FLOW_TRANSPORT_SOURCE = PREVIEW_PAIRING_TRANSPORT_SOURCE;
5
+ const requestIdSchema = z.string().check(z.trim(), z.minLength(1));
6
+ const flowHandleIdSchema = z.string().check(z.trim(), z.minLength(1));
7
+ const inlineFlowThemeSchema = z.strictObject({
8
+ css: z.optional(z.string()),
9
+ themeRuntimeArtifactId: z.optional(z.string().check(z.trim(), z.minLength(1))),
10
+ themeVersionId: z.optional(z.string().check(z.trim(), z.minLength(1))),
11
+ });
12
+ const inlineFlowSchema = z.strictObject({
13
+ definition: z.unknown().check(z.check((ctx) => {
14
+ if (ctx.value !== undefined) {
15
+ return;
16
+ }
17
+ ctx.issues.push({
18
+ code: "custom",
19
+ input: ctx.value,
20
+ message: "Inline flow definition is required.",
21
+ continue: false,
22
+ });
23
+ })),
24
+ theme: z.optional(inlineFlowThemeSchema),
25
+ });
26
+ export const previewFlowOpenCommandSchema = z.strictObject({
27
+ kind: z.literal("open"),
28
+ flow: inlineFlowSchema,
29
+ flowHandleId: z.optional(flowHandleIdSchema),
30
+ metadata: z.optional(responseMetadataInputSchema),
31
+ hideCloseButton: z.optional(z.boolean()),
32
+ });
33
+ export const previewFlowOpenRequestSchema = z.strictObject({
34
+ source: z.literal(PREVIEW_FLOW_TRANSPORT_SOURCE),
35
+ type: z.literal("preview.flow.open.request"),
36
+ requestId: requestIdSchema,
37
+ command: previewFlowOpenCommandSchema,
38
+ });
39
+ export const previewFlowOpenResultSchema = z.discriminatedUnion("ok", [
40
+ z.strictObject({
41
+ source: z.literal(PREVIEW_FLOW_TRANSPORT_SOURCE),
42
+ type: z.literal("preview.flow.open.result"),
43
+ requestId: requestIdSchema,
44
+ ok: z.literal(true),
45
+ result: z.strictObject({
46
+ flowHandleId: flowHandleIdSchema,
47
+ }),
48
+ }),
49
+ z.strictObject({
50
+ source: z.literal(PREVIEW_FLOW_TRANSPORT_SOURCE),
51
+ type: z.literal("preview.flow.open.result"),
52
+ requestId: requestIdSchema,
53
+ ok: z.literal(false),
54
+ error: z.strictObject({
55
+ code: z.optional(z.string().check(z.trim(), z.minLength(1))),
56
+ message: z.string().check(z.trim(), z.minLength(1)),
57
+ }),
58
+ }),
59
+ ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getuserfeedback/protocol",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
4
4
  "description": "getuserfeedback widget protocol — host surface and (later) wire protocol",
5
5
  "keywords": [
6
6
  "getuserfeedback",
@@ -0,0 +1,239 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { createFlowCommandHandleController } from "./flow-command-handle-controller";
3
+
4
+ describe("flow command handle controller", () => {
5
+ it("serializes commands and publishes settled handles to later payloads", async () => {
6
+ const dispatched: Array<{ flowHandleId?: string; kind: string }> = [];
7
+ const controller = createFlowCommandHandleController<
8
+ string,
9
+ { result?: { flowHandleId?: string } }
10
+ >({
11
+ getHandleIdFromSettlement: (settlement) =>
12
+ settlement.result?.flowHandleId,
13
+ isStaleHandleError: () => false,
14
+ });
15
+
16
+ await controller.runCommand(
17
+ (flowHandleId) => ({ kind: "prefetch", flowHandleId }),
18
+ async (payload) => {
19
+ dispatched.push(payload);
20
+ return { result: { flowHandleId: "handle_123" } };
21
+ },
22
+ );
23
+ await controller.runCommand(
24
+ (flowHandleId) => ({ kind: "open", flowHandleId }),
25
+ async (payload) => {
26
+ dispatched.push(payload);
27
+ return { result: { flowHandleId: "handle_123" } };
28
+ },
29
+ );
30
+
31
+ expect(dispatched).toEqual([
32
+ { kind: "prefetch", flowHandleId: undefined },
33
+ { kind: "open", flowHandleId: "handle_123" },
34
+ ]);
35
+ expect(controller.getHandleId()).toBe("handle_123");
36
+ expect(controller.hasHandleId("handle_123")).toBe(true);
37
+ });
38
+
39
+ it("clears stale handles and retries once without the handle", async () => {
40
+ const dispatched: Array<{ flowHandleId?: string; kind: string }> = [];
41
+ const clearedHandles: string[] = [];
42
+ const controller = createFlowCommandHandleController<
43
+ string,
44
+ { result?: { flowHandleId?: string } }
45
+ >({
46
+ getHandleIdFromSettlement: (settlement) =>
47
+ settlement.result?.flowHandleId,
48
+ isStaleHandleError: (error) =>
49
+ error instanceof Error && error.message === "stale",
50
+ onClearResolvedHandle: (flowHandleId) => {
51
+ clearedHandles.push(flowHandleId);
52
+ },
53
+ });
54
+
55
+ await controller.runCommand(
56
+ (flowHandleId) => ({ kind: "prefetch", flowHandleId }),
57
+ async (payload) => {
58
+ dispatched.push(payload);
59
+ return { result: { flowHandleId: "handle_stale" } };
60
+ },
61
+ );
62
+ let didFailOnce = false;
63
+ await controller.runCommand(
64
+ (flowHandleId) => ({ kind: "open", flowHandleId }),
65
+ async (payload) => {
66
+ dispatched.push(payload);
67
+ if (!didFailOnce) {
68
+ didFailOnce = true;
69
+ throw new Error("stale");
70
+ }
71
+ return { result: { flowHandleId: "handle_recovered" } };
72
+ },
73
+ );
74
+
75
+ expect(dispatched).toEqual([
76
+ { kind: "prefetch", flowHandleId: undefined },
77
+ { kind: "open", flowHandleId: "handle_stale" },
78
+ { kind: "open", flowHandleId: undefined },
79
+ ]);
80
+ expect(clearedHandles).toEqual(["handle_stale"]);
81
+ expect(controller.getHandleId()).toBe("handle_recovered");
82
+ });
83
+
84
+ it("keeps stale-handle retry in the same serialized command slot", async () => {
85
+ const dispatched: Array<{ flowHandleId?: string; kind: string }> = [];
86
+ const controller = createFlowCommandHandleController<
87
+ string,
88
+ { result?: { flowHandleId?: string } }
89
+ >({
90
+ getHandleIdFromSettlement: (settlement) =>
91
+ settlement.result?.flowHandleId,
92
+ isStaleHandleError: (error) =>
93
+ error instanceof Error && error.message === "stale",
94
+ });
95
+
96
+ await controller.runCommand(
97
+ (flowHandleId) => ({ kind: "prefetch", flowHandleId }),
98
+ async (payload) => {
99
+ dispatched.push(payload);
100
+ return { result: { flowHandleId: "handle_stale" } };
101
+ },
102
+ );
103
+ let didFailOnce = false;
104
+ const staleOpen = controller.runCommand(
105
+ (flowHandleId) => ({ kind: "open", flowHandleId }),
106
+ async (payload) => {
107
+ dispatched.push(payload);
108
+ if (!didFailOnce) {
109
+ didFailOnce = true;
110
+ throw new Error("stale");
111
+ }
112
+ return { result: { flowHandleId: "handle_recovered" } };
113
+ },
114
+ );
115
+ const queuedPrerender = controller.runCommand(
116
+ (flowHandleId) => ({ kind: "prerender", flowHandleId }),
117
+ async (payload) => {
118
+ dispatched.push(payload);
119
+ return { result: { flowHandleId: "handle_second" } };
120
+ },
121
+ );
122
+
123
+ await staleOpen;
124
+ await queuedPrerender;
125
+
126
+ expect(dispatched).toEqual([
127
+ { kind: "prefetch", flowHandleId: undefined },
128
+ { kind: "open", flowHandleId: "handle_stale" },
129
+ { kind: "open", flowHandleId: undefined },
130
+ { kind: "prerender", flowHandleId: "handle_recovered" },
131
+ ]);
132
+ expect(controller.getHandleId()).toBe("handle_second");
133
+ });
134
+
135
+ it("does not retry non-stale failures", async () => {
136
+ const dispatched: Array<{ flowHandleId?: string; kind: string }> = [];
137
+ const controller = createFlowCommandHandleController<
138
+ string,
139
+ { result?: { flowHandleId?: string } }
140
+ >({
141
+ getHandleIdFromSettlement: (settlement) =>
142
+ settlement.result?.flowHandleId,
143
+ isStaleHandleError: () => false,
144
+ });
145
+
146
+ await expect(
147
+ controller.runCommand(
148
+ (flowHandleId) => ({ kind: "open", flowHandleId }),
149
+ async (payload) => {
150
+ dispatched.push(payload);
151
+ throw new Error("boom");
152
+ },
153
+ ),
154
+ ).rejects.toThrow("boom");
155
+
156
+ expect(dispatched).toEqual([{ kind: "open", flowHandleId: undefined }]);
157
+ });
158
+
159
+ it("ignores handles from commands that settle after reset", async () => {
160
+ const dispatched: Array<{ flowHandleId?: string; kind: string }> = [];
161
+ let resolveSettlement:
162
+ | ((settlement: { result?: { flowHandleId?: string } }) => void)
163
+ | undefined;
164
+ const controller = createFlowCommandHandleController<
165
+ string,
166
+ { result?: { flowHandleId?: string } }
167
+ >({
168
+ getHandleIdFromSettlement: (settlement) =>
169
+ settlement.result?.flowHandleId,
170
+ isStaleHandleError: () => false,
171
+ });
172
+
173
+ const pendingCommand = controller.runCommand(
174
+ (flowHandleId) => ({ kind: "prefetch", flowHandleId }),
175
+ (payload) => {
176
+ dispatched.push(payload);
177
+ return new Promise((resolve) => {
178
+ resolveSettlement = resolve;
179
+ });
180
+ },
181
+ );
182
+ controller.reset();
183
+ resolveSettlement?.({ result: { flowHandleId: "handle_from_old_epoch" } });
184
+ await pendingCommand;
185
+ await controller.runCommand(
186
+ (flowHandleId) => ({ kind: "open", flowHandleId }),
187
+ async (payload) => {
188
+ dispatched.push(payload);
189
+ return { result: { flowHandleId: "handle_current" } };
190
+ },
191
+ );
192
+
193
+ expect(dispatched).toEqual([
194
+ { kind: "prefetch", flowHandleId: undefined },
195
+ { kind: "open", flowHandleId: undefined },
196
+ ]);
197
+ expect(controller.getHandleId()).toBe("handle_current");
198
+ });
199
+
200
+ it("does not retry stale failures from commands that fail after reset", async () => {
201
+ const dispatched: Array<{ flowHandleId?: string; kind: string }> = [];
202
+ let rejectSettlement: ((error: Error) => void) | undefined;
203
+ const controller = createFlowCommandHandleController<
204
+ string,
205
+ { result?: { flowHandleId?: string } }
206
+ >({
207
+ getHandleIdFromSettlement: (settlement) =>
208
+ settlement.result?.flowHandleId,
209
+ isStaleHandleError: (error) =>
210
+ error instanceof Error && error.message === "stale",
211
+ });
212
+
213
+ await controller.runCommand(
214
+ (flowHandleId) => ({ kind: "prefetch", flowHandleId }),
215
+ async (payload) => {
216
+ dispatched.push(payload);
217
+ return { result: { flowHandleId: "handle_before_reset" } };
218
+ },
219
+ );
220
+ const pendingCommand = controller.runCommand(
221
+ (flowHandleId) => ({ kind: "open", flowHandleId }),
222
+ (payload) => {
223
+ dispatched.push(payload);
224
+ return new Promise((_resolve, reject) => {
225
+ rejectSettlement = reject;
226
+ });
227
+ },
228
+ );
229
+ controller.reset();
230
+ rejectSettlement?.(new Error("stale"));
231
+
232
+ await expect(pendingCommand).rejects.toThrow("stale");
233
+ expect(dispatched).toEqual([
234
+ { kind: "prefetch", flowHandleId: undefined },
235
+ { kind: "open", flowHandleId: "handle_before_reset" },
236
+ ]);
237
+ expect(controller.getHandleId()).toBeUndefined();
238
+ });
239
+ });
@@ -0,0 +1,86 @@
1
+ import {
2
+ createLazyHandleClient,
3
+ type LazyHandleClient,
4
+ } from "./lazy-handle-client.js";
5
+
6
+ export type FlowCommandHandleController<
7
+ THandleId extends string,
8
+ TSettlement,
9
+ > = {
10
+ runCommand<TPayload>(
11
+ buildPayload: (handleId: THandleId | undefined) => TPayload,
12
+ dispatchAndWait: (payload: TPayload) => Promise<TSettlement>,
13
+ ): Promise<TSettlement>;
14
+ getHandleId(): THandleId | undefined;
15
+ hasHandleId(handleId: string): boolean;
16
+ hasPendingCommands(): boolean;
17
+ subscribeHandle(subscriber: (handleId: THandleId) => void): () => void;
18
+ clearResolvedHandle(): THandleId | undefined;
19
+ reset(): void;
20
+ };
21
+
22
+ export type CreateFlowCommandHandleControllerOptions<
23
+ THandleId extends string,
24
+ TSettlement,
25
+ > = {
26
+ getHandleIdFromSettlement: (settlement: TSettlement) => THandleId | undefined;
27
+ isStaleHandleError: (error: unknown) => boolean;
28
+ onClearResolvedHandle?: (handleId: THandleId) => void;
29
+ };
30
+
31
+ export function createFlowCommandHandleController<
32
+ THandleId extends string,
33
+ TSettlement,
34
+ >({
35
+ getHandleIdFromSettlement,
36
+ isStaleHandleError,
37
+ onClearResolvedHandle,
38
+ }: CreateFlowCommandHandleControllerOptions<
39
+ THandleId,
40
+ TSettlement
41
+ >): FlowCommandHandleController<THandleId, TSettlement> {
42
+ const handleClient: LazyHandleClient<THandleId, TSettlement> =
43
+ createLazyHandleClient<THandleId, TSettlement>({
44
+ getHandleIdFromSettlement,
45
+ });
46
+
47
+ const clearResolvedHandle = (): THandleId | undefined => {
48
+ const previousHandleId = handleClient.getHandleId();
49
+ if (!previousHandleId) {
50
+ return undefined;
51
+ }
52
+ handleClient.reset();
53
+ onClearResolvedHandle?.(previousHandleId);
54
+ return previousHandleId;
55
+ };
56
+
57
+ const reset = (): void => {
58
+ const previousHandleId = handleClient.getHandleId();
59
+ handleClient.reset();
60
+ if (previousHandleId) {
61
+ onClearResolvedHandle?.(previousHandleId);
62
+ }
63
+ };
64
+
65
+ const runCommand: FlowCommandHandleController<
66
+ THandleId,
67
+ TSettlement
68
+ >["runCommand"] = async (buildPayload, dispatchAndWait) => {
69
+ return handleClient.runCommandWithRetry(buildPayload, dispatchAndWait, {
70
+ shouldRetry: isStaleHandleError,
71
+ onBeforeRetry: () => {
72
+ clearResolvedHandle();
73
+ },
74
+ });
75
+ };
76
+
77
+ return {
78
+ runCommand,
79
+ getHandleId: () => handleClient.getHandleId(),
80
+ hasHandleId: (handleId) => handleClient.getHandleId() === handleId,
81
+ hasPendingCommands: () => handleClient.hasPendingCommands(),
82
+ subscribeHandle: (subscriber) => handleClient.subscribeHandle(subscriber),
83
+ clearResolvedHandle,
84
+ reset,
85
+ };
86
+ }
package/src/host/index.ts CHANGED
@@ -7,6 +7,7 @@ export * from "./command-envelope.js";
7
7
  export * from "./command-settlement.js";
8
8
  export * from "./constants.js";
9
9
  export * from "./external-id-argument-guards.js";
10
+ export * from "./flow-command-handle-controller.js";
10
11
  export * from "./host-event-contract.js";
11
12
  export * from "./lazy-handle-client.js";
12
13
  export { createCommandRequestId } from "./request-id.js";
@@ -23,7 +23,16 @@ export type LazyHandleClient<
23
23
  buildPayload: (handleId: THandleId | undefined) => TPayload,
24
24
  dispatchAndWait: (payload: TPayload) => Promise<TSettlement>,
25
25
  ): Promise<TSettlement>;
26
+ runCommandWithRetry<TPayload>(
27
+ buildPayload: (handleId: THandleId | undefined) => TPayload,
28
+ dispatchAndWait: (payload: TPayload) => Promise<TSettlement>,
29
+ options: {
30
+ shouldRetry: (error: unknown) => boolean;
31
+ onBeforeRetry?: (error: unknown) => void;
32
+ },
33
+ ): Promise<TSettlement>;
26
34
  getHandleId(): THandleId | undefined;
35
+ hasPendingCommands(): boolean;
27
36
  subscribeHandle(subscriber: Subscriber<THandleId>): () => void;
28
37
  getStage(): TStage;
29
38
  setStage(stage: TStage): void;
@@ -141,9 +150,60 @@ const createLazyHandleClientWithStages = <
141
150
  return run;
142
151
  };
143
152
 
153
+ const runCommandWithRetry: LazyHandleClient<
154
+ THandleId,
155
+ TSettlement,
156
+ TStage
157
+ >["runCommandWithRetry"] = (buildPayload, dispatchAndWait, options) => {
158
+ const execute = async (): Promise<TSettlement> => {
159
+ let didRetry = false;
160
+ for (;;) {
161
+ if (stage === stages.invalidated) {
162
+ throw new Error("Handle client is invalidated");
163
+ }
164
+ const commandEpoch = epoch;
165
+ const payload = buildPayload(handleId);
166
+ try {
167
+ const settlement = await dispatchAndWait(payload);
168
+ const settledHandleId = input.getHandleIdFromSettlement(settlement);
169
+ if (settledHandleId && commandEpoch === epoch) {
170
+ publishHandle(settledHandleId);
171
+ }
172
+ return settlement;
173
+ } catch (error) {
174
+ if (
175
+ commandEpoch === epoch &&
176
+ !didRetry &&
177
+ options.shouldRetry(error)
178
+ ) {
179
+ didRetry = true;
180
+ options.onBeforeRetry?.(error);
181
+ continue;
182
+ }
183
+ throw error;
184
+ }
185
+ }
186
+ };
187
+
188
+ const run =
189
+ queuedCommandCount === 0 ? execute() : tail.then(execute, execute);
190
+ queuedCommandCount += 1;
191
+ tail = run.then(
192
+ () => {
193
+ queuedCommandCount -= 1;
194
+ },
195
+ () => {
196
+ queuedCommandCount -= 1;
197
+ },
198
+ );
199
+ return run;
200
+ };
201
+
144
202
  return {
145
203
  runCommand,
204
+ runCommandWithRetry,
146
205
  getHandleId: () => handleId,
206
+ hasPendingCommands: () => queuedCommandCount > 0,
147
207
  subscribeHandle: (subscriber) => {
148
208
  subscribers.add(subscriber);
149
209
  if (handleId) {
package/src/host/sdk.ts CHANGED
@@ -11,6 +11,8 @@ export {
11
11
  toCommandSettlementError,
12
12
  waitForCommandSettlement,
13
13
  } from "./command-settlement.js";
14
+ export type { FlowCommandHandleController } from "./flow-command-handle-controller.js";
15
+ export { createFlowCommandHandleController } from "./flow-command-handle-controller.js";
14
16
  export type {
15
17
  FlowHandleFromSettlement,
16
18
  FlowState,
package/src/index.ts CHANGED
@@ -125,6 +125,15 @@ export {
125
125
  previewConnectionPairRequestSchema,
126
126
  previewConnectionPairResponseSchema,
127
127
  } from "./preview-connection.js";
128
+ export {
129
+ PREVIEW_FLOW_TRANSPORT_SOURCE,
130
+ type PreviewFlowOpenCommand,
131
+ type PreviewFlowOpenRequest,
132
+ type PreviewFlowOpenResult,
133
+ previewFlowOpenCommandSchema,
134
+ previewFlowOpenRequestSchema,
135
+ previewFlowOpenResultSchema,
136
+ } from "./preview-flow-transport.js";
128
137
  export {
129
138
  PREVIEW_PAIRING_TRANSPORT_SOURCE,
130
139
  type PreviewPairingHostAck,
@@ -0,0 +1,95 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import {
3
+ PREVIEW_FLOW_TRANSPORT_SOURCE,
4
+ previewFlowOpenRequestSchema,
5
+ previewFlowOpenResultSchema,
6
+ } from "./preview-flow-transport";
7
+
8
+ describe("preview flow transport protocol", () => {
9
+ it("parses inline flow open requests", () => {
10
+ expect(
11
+ previewFlowOpenRequestSchema.parse({
12
+ source: PREVIEW_FLOW_TRANSPORT_SOURCE,
13
+ type: "preview.flow.open.request",
14
+ requestId: "req_123",
15
+ command: {
16
+ kind: "open",
17
+ flow: {
18
+ definition: {
19
+ blocks: [],
20
+ config: {},
21
+ presenter: null,
22
+ },
23
+ },
24
+ flowHandleId: "handle_123",
25
+ hideCloseButton: true,
26
+ },
27
+ }),
28
+ ).toMatchObject({
29
+ requestId: "req_123",
30
+ command: {
31
+ kind: "open",
32
+ flowHandleId: "handle_123",
33
+ flow: {
34
+ definition: {
35
+ blocks: [],
36
+ },
37
+ },
38
+ },
39
+ });
40
+ });
41
+
42
+ it("rejects undefined inline definitions", () => {
43
+ expect(() =>
44
+ previewFlowOpenRequestSchema.parse({
45
+ source: PREVIEW_FLOW_TRANSPORT_SOURCE,
46
+ type: "preview.flow.open.request",
47
+ requestId: "req_123",
48
+ command: {
49
+ kind: "open",
50
+ flow: {
51
+ definition: undefined,
52
+ },
53
+ },
54
+ }),
55
+ ).toThrow();
56
+ });
57
+
58
+ it("parses success and failure results", () => {
59
+ expect(
60
+ previewFlowOpenResultSchema.parse({
61
+ source: PREVIEW_FLOW_TRANSPORT_SOURCE,
62
+ type: "preview.flow.open.result",
63
+ requestId: "req_123",
64
+ ok: true,
65
+ result: {
66
+ flowHandleId: "handle_123",
67
+ },
68
+ }),
69
+ ).toEqual({
70
+ source: PREVIEW_FLOW_TRANSPORT_SOURCE,
71
+ type: "preview.flow.open.result",
72
+ requestId: "req_123",
73
+ ok: true,
74
+ result: {
75
+ flowHandleId: "handle_123",
76
+ },
77
+ });
78
+
79
+ expect(
80
+ previewFlowOpenResultSchema.parse({
81
+ source: PREVIEW_FLOW_TRANSPORT_SOURCE,
82
+ type: "preview.flow.open.result",
83
+ requestId: "req_123",
84
+ ok: false,
85
+ error: {
86
+ code: "DISPATCH_FAILED",
87
+ message: "Preview dispatch failed",
88
+ },
89
+ }),
90
+ ).toMatchObject({
91
+ ok: false,
92
+ error: { code: "DISPATCH_FAILED" },
93
+ });
94
+ });
95
+ });
@@ -0,0 +1,80 @@
1
+ import * as z from "zod/mini";
2
+ import { PREVIEW_PAIRING_TRANSPORT_SOURCE } from "./preview-pairing-transport.js";
3
+ import { responseMetadataInputSchema } from "./response-metadata.js";
4
+
5
+ export const PREVIEW_FLOW_TRANSPORT_SOURCE = PREVIEW_PAIRING_TRANSPORT_SOURCE;
6
+
7
+ const requestIdSchema = z.string().check(z.trim(), z.minLength(1));
8
+ const flowHandleIdSchema = z.string().check(z.trim(), z.minLength(1));
9
+
10
+ const inlineFlowThemeSchema = z.strictObject({
11
+ css: z.optional(z.string()),
12
+ themeRuntimeArtifactId: z.optional(
13
+ z.string().check(z.trim(), z.minLength(1)),
14
+ ),
15
+ themeVersionId: z.optional(z.string().check(z.trim(), z.minLength(1))),
16
+ });
17
+
18
+ const inlineFlowSchema = z.strictObject({
19
+ definition: z.unknown().check(
20
+ z.check((ctx) => {
21
+ if (ctx.value !== undefined) {
22
+ return;
23
+ }
24
+ ctx.issues.push({
25
+ code: "custom",
26
+ input: ctx.value,
27
+ message: "Inline flow definition is required.",
28
+ continue: false,
29
+ });
30
+ }),
31
+ ),
32
+ theme: z.optional(inlineFlowThemeSchema),
33
+ });
34
+
35
+ export const previewFlowOpenCommandSchema = z.strictObject({
36
+ kind: z.literal("open"),
37
+ flow: inlineFlowSchema,
38
+ flowHandleId: z.optional(flowHandleIdSchema),
39
+ metadata: z.optional(responseMetadataInputSchema),
40
+ hideCloseButton: z.optional(z.boolean()),
41
+ });
42
+
43
+ export const previewFlowOpenRequestSchema = z.strictObject({
44
+ source: z.literal(PREVIEW_FLOW_TRANSPORT_SOURCE),
45
+ type: z.literal("preview.flow.open.request"),
46
+ requestId: requestIdSchema,
47
+ command: previewFlowOpenCommandSchema,
48
+ });
49
+
50
+ export const previewFlowOpenResultSchema = z.discriminatedUnion("ok", [
51
+ z.strictObject({
52
+ source: z.literal(PREVIEW_FLOW_TRANSPORT_SOURCE),
53
+ type: z.literal("preview.flow.open.result"),
54
+ requestId: requestIdSchema,
55
+ ok: z.literal(true),
56
+ result: z.strictObject({
57
+ flowHandleId: flowHandleIdSchema,
58
+ }),
59
+ }),
60
+ z.strictObject({
61
+ source: z.literal(PREVIEW_FLOW_TRANSPORT_SOURCE),
62
+ type: z.literal("preview.flow.open.result"),
63
+ requestId: requestIdSchema,
64
+ ok: z.literal(false),
65
+ error: z.strictObject({
66
+ code: z.optional(z.string().check(z.trim(), z.minLength(1))),
67
+ message: z.string().check(z.trim(), z.minLength(1)),
68
+ }),
69
+ }),
70
+ ]);
71
+
72
+ export type PreviewFlowOpenCommand = z.output<
73
+ typeof previewFlowOpenCommandSchema
74
+ >;
75
+ export type PreviewFlowOpenRequest = z.output<
76
+ typeof previewFlowOpenRequestSchema
77
+ >;
78
+ export type PreviewFlowOpenResult = z.output<
79
+ typeof previewFlowOpenResultSchema
80
+ >;