@particle-academy/fancy-connector-core 0.13.0 → 0.15.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/dist/index.d.cts CHANGED
@@ -916,6 +916,72 @@ type ConnectorResult<T = unknown> = {
916
916
  declare function registerTransport(next: Transport | null): void;
917
917
  declare function callConnector<T = unknown>(service: ServiceDescriptor, options: CallOptions): Promise<ConnectorResult<T>>;
918
918
 
919
+ /**
920
+ * A read that resumes from a HOST-HELD cursor, and pages.
921
+ *
922
+ * Gmail's push and Drive's channel notifications carry no changes: they say
923
+ * "something moved", and the follow-up read fetches what did, starting from
924
+ * the position the HOST stored last time (Gmail's `startHistoryId`, Drive's
925
+ * `pageToken`). Reading from the delivery's own position instead misses the
926
+ * very change that caused it. The package holds no state: the host stores the
927
+ * cursor, passes it in, and persists `cursor.next` when the run succeeds.
928
+ *
929
+ * The PHP twin is `CursorRead::read`; both read `fixtures/cursor-read/`.
930
+ *
931
+ * The decisions, each pinned by a case:
932
+ *
933
+ * - **`next` comes ONLY from the LAST page.** Gmail's `historyId` is the
934
+ * mailbox's CURRENT one on every page, and Google says to store it only "if
935
+ * you receive no nextPageToken". Taking it after page one would skip every
936
+ * page not yet read, silently.
937
+ * - **Too many pages is refused** (`cursor-overflow`), never a partial read
938
+ * with a cursor that skips the rest. The host's answer is a bounded resync.
939
+ * - **The provider's own "cursor out of range"** (`expiredStatus`, Gmail's
940
+ * 404) is `cursor-expired`; every OTHER failure is rethrown unchanged, so a
941
+ * 500 is never mistaken for a lapse.
942
+ * - **No stored cursor is `cursor-missing`**, and the provider is not called:
943
+ * a read with no starting point is a read from the beginning of time.
944
+ * - `collect` absent is `[]` (Gmail omits `history` when nothing changed); not
945
+ * a list is `bad-page`. The cursor and `next` are strings: history ids are
946
+ * uint64.
947
+ */
948
+ declare const CURSOR_READ_REASONS: readonly ["cursor-missing", "cursor-expired", "cursor-overflow", "bad-page"];
949
+ type CursorReadReason = (typeof CURSOR_READ_REASONS)[number];
950
+ type CursorReadSpec = {
951
+ /** The read's parameter the stored cursor fills (Gmail: `startHistoryId`). */
952
+ param: string;
953
+ /** Where the NEXT cursor is read in the last page's data (Gmail: `historyId`). */
954
+ advanceFrom: string;
955
+ /** Paging, when the read pages (Gmail: `pageToken` / `nextPageToken`, `history`). */
956
+ page?: {
957
+ param: string;
958
+ from: string;
959
+ collect: string;
960
+ maxPages: number;
961
+ };
962
+ /** The status the provider answers for a cursor out of range (Gmail: 404). */
963
+ expiredStatus?: number;
964
+ };
965
+ type CursorReadResult = {
966
+ data: unknown;
967
+ cursor: {
968
+ used: string;
969
+ next: string | null;
970
+ };
971
+ };
972
+ /** Refused BY NAME; `reason` is the same string PHP's exception carries. */
973
+ declare class CursorReadError extends Error {
974
+ readonly reason: CursorReadReason;
975
+ /** The host's bounded resync, when the caller declared one (Gmail: `newer_than:7d`). */
976
+ readonly resyncQuery?: string | undefined;
977
+ constructor(reason: CursorReadReason, message: string,
978
+ /** The host's bounded resync, when the caller declared one (Gmail: `newer_than:7d`). */
979
+ resyncQuery?: string | undefined);
980
+ }
981
+ declare function readWithCursor(spec: CursorReadSpec, cursor: unknown, call: (params: Record<string, string>) => Promise<unknown>, options?: {
982
+ resyncQuery?: string;
983
+ }): Promise<CursorReadResult>;
984
+
919
985
  /**
920
986
  * API drift — being told the provider changed, rather than discovering it.
921
987
  *
@@ -1982,11 +2048,27 @@ type CredentialField = {
1982
2048
  /** A hint for an empty field. NEVER a real value. */
1983
2049
  placeholder?: string;
1984
2050
  };
2051
+ /** Who performs a setup step. Ships as data: a host mirrors it across JSON. */
2052
+ declare const SETUP_ACTORS: readonly ["person", "agent"];
2053
+ type SetupActor = (typeof SETUP_ACTORS)[number];
1985
2054
  type SetupStep = {
1986
2055
  title: string;
1987
2056
  /** The step, and the trap in it. A step with no trap named is usually wrong. */
1988
2057
  detail: string;
1989
2058
  url?: string;
2059
+ /** Who does it. Absent means `person` (0.15.0). */
2060
+ actor?: SetupActor;
2061
+ /** What an agent is asked to do. Required when `actor` is `agent`. */
2062
+ prompt?: string;
2063
+ /** Values the person pastes somewhere, e.g. the callback URL. */
2064
+ copy?: {
2065
+ label: string;
2066
+ value: string;
2067
+ }[];
2068
+ /** The credential keys this step yields. */
2069
+ fields?: string[];
2070
+ /** How the person knows the step is done. */
2071
+ done?: string;
1990
2072
  };
1991
2073
  /**
1992
2074
  * The result of a read-only credential check.
@@ -2784,6 +2866,40 @@ type PubSubPushMessage = {
2784
2866
  };
2785
2867
  declare function decodePubSubPush(raw: Uint8Array | string): PubSubPushMessage;
2786
2868
 
2869
+ /**
2870
+ * A connector's setup steps, rendered for ONE app.
2871
+ *
2872
+ * A definition is written once for every host, so the values that differ per
2873
+ * host — where its webhooks live, what it calls itself, which connector this
2874
+ * is — are tokens: `{{appUrl}}`, `{{appName}}`, `{{connector}}`, and only
2875
+ * those. Held to `fixtures/setup-render/cases.json`, mirrored in
2876
+ * `php/src/Setup.php`.
2877
+ *
2878
+ * Two refusals, both BY NAME, because each would otherwise reach a person as a
2879
+ * broken instruction that looks deliberate:
2880
+ *
2881
+ * - `unknown-token`: anything else shaped like `{{...}}` — a typo, a spaced
2882
+ * `{{ appUrl }}`, a token a definition invented. Left in, a person pastes a
2883
+ * literal brace into a provider console.
2884
+ * - `missing-context`: a token the host gave no (or an empty) value for. Left
2885
+ * empty, a callback URL becomes `/hooks/twilio` and points nowhere.
2886
+ *
2887
+ * `appUrl` loses ONE trailing slash first, so `{{appUrl}}/hooks` never doubles
2888
+ * it. A context value is inserted once and never expanded again.
2889
+ */
2890
+
2891
+ declare const SETUP_TOKENS: readonly ["appUrl", "appName", "connector"];
2892
+ type SetupToken = (typeof SETUP_TOKENS)[number];
2893
+ declare const SETUP_RENDER_REASONS: readonly ["unknown-token", "missing-context"];
2894
+ type SetupRenderReason = (typeof SETUP_RENDER_REASONS)[number];
2895
+ type SetupContext = Partial<Record<SetupToken, string>>;
2896
+ declare class SetupRenderError extends Error {
2897
+ readonly reason: SetupRenderReason;
2898
+ constructor(reason: SetupRenderReason, message: string);
2899
+ }
2900
+ /** Render every step for one app: tokens filled, `actor` and `fields` defaulted. */
2901
+ declare function renderSetup(steps: readonly SetupStep[], context: SetupContext): SetupStep[];
2902
+
2787
2903
  /**
2788
2904
  * How a connector trigger learns that something happened.
2789
2905
  *
@@ -2946,4 +3062,4 @@ oidc?: OidcExpectation): Promise<WebhookVerification>;
2946
3062
  */
2947
3063
  declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
2948
3064
 
2949
- export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DeliveryRoute, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, JWT_ALGORITHMS, type JoinTarget, type JoinTargetKind, type Jwk, type JwtVerification, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, OIDC_JWT_SCHEME_KIND, type OidcExpectation, type OidcJwtScheme, type OidcJwtVerificationSpec, PROBLEM_SEVERITIES, PUBSUB_PUSH_REASONS, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, PubSubPushError, type PubSubPushMessage, type PubSubPushReason, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SIGNED_URI_RULES, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SignedRequestLine, type SignedUriRule, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyJwtOptions, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, decodePubSubPush, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isOidcJwtScheme, isOidcJwtSpec, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, normaliseSignedUri, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifyJwt, verifyOidcDelivery, verifySharedToken, withResolvedLimit };
3065
+ export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, CURSOR_READ_REASONS, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, CursorReadError, type CursorReadReason, type CursorReadResult, type CursorReadSpec, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DeliveryRoute, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, JWT_ALGORITHMS, type JoinTarget, type JoinTargetKind, type Jwk, type JwtVerification, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, OIDC_JWT_SCHEME_KIND, type OidcExpectation, type OidcJwtScheme, type OidcJwtVerificationSpec, PROBLEM_SEVERITIES, PUBSUB_PUSH_REASONS, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, PubSubPushError, type PubSubPushMessage, type PubSubPushReason, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SETUP_ACTORS, SETUP_RENDER_REASONS, SETUP_TOKENS, SIGNED_URI_RULES, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupActor, type SetupContext, SetupRenderError, type SetupRenderReason, type SetupStep, type SetupToken, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SignedRequestLine, type SignedUriRule, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyJwtOptions, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, decodePubSubPush, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isOidcJwtScheme, isOidcJwtSpec, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, normaliseSignedUri, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, readWithCursor, registerConnectionHost, registerTransport, render, renderSetup, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifyJwt, verifyOidcDelivery, verifySharedToken, withResolvedLimit };
package/dist/index.d.ts CHANGED
@@ -916,6 +916,72 @@ type ConnectorResult<T = unknown> = {
916
916
  declare function registerTransport(next: Transport | null): void;
917
917
  declare function callConnector<T = unknown>(service: ServiceDescriptor, options: CallOptions): Promise<ConnectorResult<T>>;
918
918
 
919
+ /**
920
+ * A read that resumes from a HOST-HELD cursor, and pages.
921
+ *
922
+ * Gmail's push and Drive's channel notifications carry no changes: they say
923
+ * "something moved", and the follow-up read fetches what did, starting from
924
+ * the position the HOST stored last time (Gmail's `startHistoryId`, Drive's
925
+ * `pageToken`). Reading from the delivery's own position instead misses the
926
+ * very change that caused it. The package holds no state: the host stores the
927
+ * cursor, passes it in, and persists `cursor.next` when the run succeeds.
928
+ *
929
+ * The PHP twin is `CursorRead::read`; both read `fixtures/cursor-read/`.
930
+ *
931
+ * The decisions, each pinned by a case:
932
+ *
933
+ * - **`next` comes ONLY from the LAST page.** Gmail's `historyId` is the
934
+ * mailbox's CURRENT one on every page, and Google says to store it only "if
935
+ * you receive no nextPageToken". Taking it after page one would skip every
936
+ * page not yet read, silently.
937
+ * - **Too many pages is refused** (`cursor-overflow`), never a partial read
938
+ * with a cursor that skips the rest. The host's answer is a bounded resync.
939
+ * - **The provider's own "cursor out of range"** (`expiredStatus`, Gmail's
940
+ * 404) is `cursor-expired`; every OTHER failure is rethrown unchanged, so a
941
+ * 500 is never mistaken for a lapse.
942
+ * - **No stored cursor is `cursor-missing`**, and the provider is not called:
943
+ * a read with no starting point is a read from the beginning of time.
944
+ * - `collect` absent is `[]` (Gmail omits `history` when nothing changed); not
945
+ * a list is `bad-page`. The cursor and `next` are strings: history ids are
946
+ * uint64.
947
+ */
948
+ declare const CURSOR_READ_REASONS: readonly ["cursor-missing", "cursor-expired", "cursor-overflow", "bad-page"];
949
+ type CursorReadReason = (typeof CURSOR_READ_REASONS)[number];
950
+ type CursorReadSpec = {
951
+ /** The read's parameter the stored cursor fills (Gmail: `startHistoryId`). */
952
+ param: string;
953
+ /** Where the NEXT cursor is read in the last page's data (Gmail: `historyId`). */
954
+ advanceFrom: string;
955
+ /** Paging, when the read pages (Gmail: `pageToken` / `nextPageToken`, `history`). */
956
+ page?: {
957
+ param: string;
958
+ from: string;
959
+ collect: string;
960
+ maxPages: number;
961
+ };
962
+ /** The status the provider answers for a cursor out of range (Gmail: 404). */
963
+ expiredStatus?: number;
964
+ };
965
+ type CursorReadResult = {
966
+ data: unknown;
967
+ cursor: {
968
+ used: string;
969
+ next: string | null;
970
+ };
971
+ };
972
+ /** Refused BY NAME; `reason` is the same string PHP's exception carries. */
973
+ declare class CursorReadError extends Error {
974
+ readonly reason: CursorReadReason;
975
+ /** The host's bounded resync, when the caller declared one (Gmail: `newer_than:7d`). */
976
+ readonly resyncQuery?: string | undefined;
977
+ constructor(reason: CursorReadReason, message: string,
978
+ /** The host's bounded resync, when the caller declared one (Gmail: `newer_than:7d`). */
979
+ resyncQuery?: string | undefined);
980
+ }
981
+ declare function readWithCursor(spec: CursorReadSpec, cursor: unknown, call: (params: Record<string, string>) => Promise<unknown>, options?: {
982
+ resyncQuery?: string;
983
+ }): Promise<CursorReadResult>;
984
+
919
985
  /**
920
986
  * API drift — being told the provider changed, rather than discovering it.
921
987
  *
@@ -1982,11 +2048,27 @@ type CredentialField = {
1982
2048
  /** A hint for an empty field. NEVER a real value. */
1983
2049
  placeholder?: string;
1984
2050
  };
2051
+ /** Who performs a setup step. Ships as data: a host mirrors it across JSON. */
2052
+ declare const SETUP_ACTORS: readonly ["person", "agent"];
2053
+ type SetupActor = (typeof SETUP_ACTORS)[number];
1985
2054
  type SetupStep = {
1986
2055
  title: string;
1987
2056
  /** The step, and the trap in it. A step with no trap named is usually wrong. */
1988
2057
  detail: string;
1989
2058
  url?: string;
2059
+ /** Who does it. Absent means `person` (0.15.0). */
2060
+ actor?: SetupActor;
2061
+ /** What an agent is asked to do. Required when `actor` is `agent`. */
2062
+ prompt?: string;
2063
+ /** Values the person pastes somewhere, e.g. the callback URL. */
2064
+ copy?: {
2065
+ label: string;
2066
+ value: string;
2067
+ }[];
2068
+ /** The credential keys this step yields. */
2069
+ fields?: string[];
2070
+ /** How the person knows the step is done. */
2071
+ done?: string;
1990
2072
  };
1991
2073
  /**
1992
2074
  * The result of a read-only credential check.
@@ -2784,6 +2866,40 @@ type PubSubPushMessage = {
2784
2866
  };
2785
2867
  declare function decodePubSubPush(raw: Uint8Array | string): PubSubPushMessage;
2786
2868
 
2869
+ /**
2870
+ * A connector's setup steps, rendered for ONE app.
2871
+ *
2872
+ * A definition is written once for every host, so the values that differ per
2873
+ * host — where its webhooks live, what it calls itself, which connector this
2874
+ * is — are tokens: `{{appUrl}}`, `{{appName}}`, `{{connector}}`, and only
2875
+ * those. Held to `fixtures/setup-render/cases.json`, mirrored in
2876
+ * `php/src/Setup.php`.
2877
+ *
2878
+ * Two refusals, both BY NAME, because each would otherwise reach a person as a
2879
+ * broken instruction that looks deliberate:
2880
+ *
2881
+ * - `unknown-token`: anything else shaped like `{{...}}` — a typo, a spaced
2882
+ * `{{ appUrl }}`, a token a definition invented. Left in, a person pastes a
2883
+ * literal brace into a provider console.
2884
+ * - `missing-context`: a token the host gave no (or an empty) value for. Left
2885
+ * empty, a callback URL becomes `/hooks/twilio` and points nowhere.
2886
+ *
2887
+ * `appUrl` loses ONE trailing slash first, so `{{appUrl}}/hooks` never doubles
2888
+ * it. A context value is inserted once and never expanded again.
2889
+ */
2890
+
2891
+ declare const SETUP_TOKENS: readonly ["appUrl", "appName", "connector"];
2892
+ type SetupToken = (typeof SETUP_TOKENS)[number];
2893
+ declare const SETUP_RENDER_REASONS: readonly ["unknown-token", "missing-context"];
2894
+ type SetupRenderReason = (typeof SETUP_RENDER_REASONS)[number];
2895
+ type SetupContext = Partial<Record<SetupToken, string>>;
2896
+ declare class SetupRenderError extends Error {
2897
+ readonly reason: SetupRenderReason;
2898
+ constructor(reason: SetupRenderReason, message: string);
2899
+ }
2900
+ /** Render every step for one app: tokens filled, `actor` and `fields` defaulted. */
2901
+ declare function renderSetup(steps: readonly SetupStep[], context: SetupContext): SetupStep[];
2902
+
2787
2903
  /**
2788
2904
  * How a connector trigger learns that something happened.
2789
2905
  *
@@ -2946,4 +3062,4 @@ oidc?: OidcExpectation): Promise<WebhookVerification>;
2946
3062
  */
2947
3063
  declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
2948
3064
 
2949
- export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DeliveryRoute, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, JWT_ALGORITHMS, type JoinTarget, type JoinTargetKind, type Jwk, type JwtVerification, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, OIDC_JWT_SCHEME_KIND, type OidcExpectation, type OidcJwtScheme, type OidcJwtVerificationSpec, PROBLEM_SEVERITIES, PUBSUB_PUSH_REASONS, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, PubSubPushError, type PubSubPushMessage, type PubSubPushReason, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SIGNED_URI_RULES, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SignedRequestLine, type SignedUriRule, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyJwtOptions, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, decodePubSubPush, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isOidcJwtScheme, isOidcJwtSpec, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, normaliseSignedUri, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifyJwt, verifyOidcDelivery, verifySharedToken, withResolvedLimit };
3065
+ export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, CURSOR_READ_REASONS, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, CursorReadError, type CursorReadReason, type CursorReadResult, type CursorReadSpec, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DeliveryRoute, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, JWT_ALGORITHMS, type JoinTarget, type JoinTargetKind, type Jwk, type JwtVerification, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, OIDC_JWT_SCHEME_KIND, type OidcExpectation, type OidcJwtScheme, type OidcJwtVerificationSpec, PROBLEM_SEVERITIES, PUBSUB_PUSH_REASONS, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, PubSubPushError, type PubSubPushMessage, type PubSubPushReason, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SETUP_ACTORS, SETUP_RENDER_REASONS, SETUP_TOKENS, SIGNED_URI_RULES, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupActor, type SetupContext, SetupRenderError, type SetupRenderReason, type SetupStep, type SetupToken, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SignedRequestLine, type SignedUriRule, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyJwtOptions, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, decodePubSubPush, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isOidcJwtScheme, isOidcJwtSpec, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, normaliseSignedUri, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, readWithCursor, registerConnectionHost, registerTransport, render, renderSetup, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifyJwt, verifyOidcDelivery, verifySharedToken, withResolvedLimit };
package/dist/index.js CHANGED
@@ -163,10 +163,10 @@ var lastCallAt = /* @__PURE__ */ new Map();
163
163
  async function respectRate(channel, minIntervalMs, now = () => Date.now(), sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
164
164
  if (minIntervalMs <= 0) return { waitedMs: 0 };
165
165
  const previous = lastCallAt.get(channel);
166
- const at = now();
167
- const waitedMs = previous === void 0 ? 0 : Math.max(0, previous + minIntervalMs - at);
166
+ const at2 = now();
167
+ const waitedMs = previous === void 0 ? 0 : Math.max(0, previous + minIntervalMs - at2);
168
168
  if (waitedMs > 0) await sleep(waitedMs);
169
- lastCallAt.set(channel, at + waitedMs);
169
+ lastCallAt.set(channel, at2 + waitedMs);
170
170
  return { waitedMs };
171
171
  }
172
172
  function resetRateState() {
@@ -664,6 +664,71 @@ function readString(config, key) {
664
664
  return typeof value === "string" && value.trim() !== "" ? value.trim() : null;
665
665
  }
666
666
 
667
+ // src/cursor-read.ts
668
+ var CURSOR_READ_REASONS = ["cursor-missing", "cursor-expired", "cursor-overflow", "bad-page"];
669
+ var CursorReadError = class extends Error {
670
+ constructor(reason, message, resyncQuery) {
671
+ super(message);
672
+ this.reason = reason;
673
+ this.resyncQuery = resyncQuery;
674
+ this.name = "CursorReadError";
675
+ }
676
+ reason;
677
+ resyncQuery;
678
+ };
679
+ async function readWithCursor(spec, cursor, call, options = {}) {
680
+ const refuse = (reason, message) => new CursorReadError(reason, message, options.resyncQuery);
681
+ const used = asCursor(cursor);
682
+ if (used === null) throw refuse("cursor-missing", `no stored ${spec.param}: the host seeds one before the first read`);
683
+ const collected = [];
684
+ let last;
685
+ let token = null;
686
+ let pages = 0;
687
+ for (; ; ) {
688
+ if (spec.page && pages === spec.page.maxPages) {
689
+ throw refuse("cursor-overflow", `more than ${spec.page.maxPages} pages since ${spec.param} ${used}`);
690
+ }
691
+ const params = { [spec.param]: used };
692
+ if (spec.page && token !== null) params[spec.page.param] = token;
693
+ try {
694
+ last = await call(params);
695
+ } catch (error) {
696
+ const status = error?.status;
697
+ if (spec.expiredStatus !== void 0 && status === spec.expiredStatus) {
698
+ throw refuse("cursor-expired", `${spec.param} ${used} is out of the provider's range (${status})`);
699
+ }
700
+ throw error;
701
+ }
702
+ pages++;
703
+ if (!spec.page) break;
704
+ const items = at(last, spec.page.collect);
705
+ if (items !== void 0 && !Array.isArray(items)) {
706
+ throw refuse("bad-page", `${spec.page.collect} is not a list`);
707
+ }
708
+ if (items) collected.push(...items);
709
+ token = asCursor(at(last, spec.page.from));
710
+ if (token === null) break;
711
+ }
712
+ const data = spec.page ? withList(last, spec.page.collect, collected) : last;
713
+ return { data, cursor: { used, next: asCursor(at(last, spec.advanceFrom)) } };
714
+ }
715
+ function asCursor(value) {
716
+ if (typeof value === "string") return value === "" ? null : value;
717
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
718
+ return null;
719
+ }
720
+ function at(value, path) {
721
+ return path.split(".").reduce(
722
+ (v, key) => v !== null && typeof v === "object" && !Array.isArray(v) ? v[key] : void 0,
723
+ value
724
+ );
725
+ }
726
+ function withList(data, path, list) {
727
+ const [head, ...rest] = path.split(".");
728
+ const base = data !== null && typeof data === "object" && !Array.isArray(data) ? data : {};
729
+ return { ...base, [head]: rest.length ? withList(base[head], rest.join("."), list) : list };
730
+ }
731
+
667
732
  // src/drift.ts
668
733
  function resolveRef(document, node, depth = 0) {
669
734
  if (depth > 8 || node === null || typeof node !== "object") return node;
@@ -1318,32 +1383,32 @@ function base64urlBytes(segment) {
1318
1383
  var EXPIRES_AT_UNITS = ["rfc3339", "epoch-ms"];
1319
1384
  var INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
1320
1385
  var DEFAULT_CONTEXT = { service: "", operation: "subscription" };
1321
- function instantMs(value, field, at) {
1386
+ function instantMs(value, field, at2) {
1322
1387
  if (typeof value !== "string" || !INSTANT.test(value)) {
1323
1388
  throw new ConnectorConfigError(
1324
1389
  `${field} must be an RFC 3339 instant such as "2026-09-22T00:00:00Z", got ${JSON.stringify(value)}. A provider's own shape \u2014 Google's epoch milliseconds, say \u2014 is converted by the connector, never guessed at here.`,
1325
- at
1390
+ at2
1326
1391
  );
1327
1392
  }
1328
1393
  const ms = Date.parse(value.replace(/(\.\d{3})\d+/, "$1"));
1329
1394
  if (Number.isNaN(ms)) {
1330
- throw new ConnectorConfigError(`${field} is not a real instant: ${JSON.stringify(value)}`, at);
1395
+ throw new ConnectorConfigError(`${field} is not a real instant: ${JSON.stringify(value)}`, at2);
1331
1396
  }
1332
1397
  return ms;
1333
1398
  }
1334
- function leaseFromResponse(declaration, response, at = DEFAULT_CONTEXT) {
1399
+ function leaseFromResponse(declaration, response, at2 = DEFAULT_CONTEXT) {
1335
1400
  const { expiresAtFrom: path, expiresAtUnit: unit } = declaration;
1336
1401
  if (!EXPIRES_AT_UNITS.includes(unit)) {
1337
1402
  throw new ConnectorConfigError(
1338
1403
  `expiresAtUnit must be one of ${EXPIRES_AT_UNITS.join(" | ")}, got ${JSON.stringify(unit)}.`,
1339
- at
1404
+ at2
1340
1405
  );
1341
1406
  }
1342
1407
  const value = readPath(response, path);
1343
1408
  if (value === void 0 || value === null) {
1344
1409
  throw new ConnectorConfigError(
1345
1410
  `${path} is not present in the response, so no lease can be built \u2014 a subscription with no known expiry is one nobody renews.`,
1346
- at
1411
+ at2
1347
1412
  );
1348
1413
  }
1349
1414
  let expiresAt;
@@ -1352,7 +1417,7 @@ function leaseFromResponse(declaration, response, at = DEFAULT_CONTEXT) {
1352
1417
  if (!Number.isSafeInteger(ms)) {
1353
1418
  throw new ConnectorConfigError(
1354
1419
  `${path} must be epoch milliseconds as digits under "epoch-ms", got ${JSON.stringify(value)}.`,
1355
- at
1420
+ at2
1356
1421
  );
1357
1422
  }
1358
1423
  expiresAt = new Date(ms).toISOString();
@@ -1360,14 +1425,14 @@ function leaseFromResponse(declaration, response, at = DEFAULT_CONTEXT) {
1360
1425
  if (typeof value !== "string" || !INSTANT.test(value)) {
1361
1426
  throw new ConnectorConfigError(
1362
1427
  `${path} must be an RFC 3339 instant under "rfc3339", got ${JSON.stringify(value)}.`,
1363
- at
1428
+ at2
1364
1429
  );
1365
1430
  }
1366
- expiresAt = new Date(instantMs(value, path, at)).toISOString();
1431
+ expiresAt = new Date(instantMs(value, path, at2)).toISOString();
1367
1432
  }
1368
1433
  return subscriptionLease(
1369
1434
  { expiresAt, renewBeforeSeconds: declaration.renewBeforeSeconds, renewOperation: declaration.renewOperation },
1370
- at
1435
+ at2
1371
1436
  );
1372
1437
  }
1373
1438
  function readPath(value, path) {
@@ -1378,18 +1443,18 @@ function readPath(value, path) {
1378
1443
  }
1379
1444
  return current;
1380
1445
  }
1381
- function subscriptionLease(input, at = DEFAULT_CONTEXT) {
1382
- instantMs(input.expiresAt, "expiresAt", at);
1446
+ function subscriptionLease(input, at2 = DEFAULT_CONTEXT) {
1447
+ instantMs(input.expiresAt, "expiresAt", at2);
1383
1448
  if (!Number.isInteger(input.renewBeforeSeconds) || input.renewBeforeSeconds <= 0) {
1384
1449
  throw new ConnectorConfigError(
1385
1450
  `renewBeforeSeconds must be a positive whole number of seconds, got ${JSON.stringify(input.renewBeforeSeconds)}. Zero would make the lease due only at the instant it expires, which is a lease nobody renews.`,
1386
- at
1451
+ at2
1387
1452
  );
1388
1453
  }
1389
1454
  if (typeof input.renewOperation !== "string" || input.renewOperation.trim() === "") {
1390
1455
  throw new ConnectorConfigError(
1391
1456
  "renewOperation must name the operation the host calls when the lease is due; a due lease with nothing to call is one nobody renews.",
1392
- at
1457
+ at2
1393
1458
  );
1394
1459
  }
1395
1460
  return { expiresAt: input.expiresAt, renewBeforeSeconds: input.renewBeforeSeconds, renewOperation: input.renewOperation };
@@ -1398,10 +1463,10 @@ function leaseRenewAt(lease) {
1398
1463
  return new Date(instantMs(lease.expiresAt, "expiresAt", DEFAULT_CONTEXT) - lease.renewBeforeSeconds * 1e3).toISOString();
1399
1464
  }
1400
1465
  function leaseState(lease, now) {
1401
- const at = now instanceof Date ? now.getTime() : instantMs(now, "now", DEFAULT_CONTEXT);
1466
+ const at2 = now instanceof Date ? now.getTime() : instantMs(now, "now", DEFAULT_CONTEXT);
1402
1467
  const expires = instantMs(lease.expiresAt, "expiresAt", DEFAULT_CONTEXT);
1403
- if (at >= expires) return "expired";
1404
- if (at >= expires - lease.renewBeforeSeconds * 1e3) return "due";
1468
+ if (at2 >= expires) return "expired";
1469
+ if (at2 >= expires - lease.renewBeforeSeconds * 1e3) return "due";
1405
1470
  return "active";
1406
1471
  }
1407
1472
  function leaseAction(lease, now) {
@@ -1721,8 +1786,8 @@ function splitMultipart(body, boundary) {
1721
1786
  if (partStart >= 0 && partStart <= body.length) children.push(body.subarray(partStart));
1722
1787
  return children;
1723
1788
  }
1724
- function startsWith(haystack, at, needle) {
1725
- for (let k = 0; k < needle.length; k++) if (haystack[at + k] !== needle[k]) return false;
1789
+ function startsWith(haystack, at2, needle) {
1790
+ for (let k = 0; k < needle.length; k++) if (haystack[at2 + k] !== needle[k]) return false;
1726
1791
  return true;
1727
1792
  }
1728
1793
  function parseMime(raw) {
@@ -2289,6 +2354,53 @@ function withResolvedLimit(rules, limit) {
2289
2354
  var CREDENTIAL_SCOPES = ["provider", "account"];
2290
2355
  var PROBLEM_SEVERITIES = ["block", "warn"];
2291
2356
  var CANONICAL_METRICS = ["like", "share", "reply", "quote", "view"];
2357
+ var SETUP_ACTORS = ["person", "agent"];
2358
+
2359
+ // src/setup.ts
2360
+ var SETUP_TOKENS = ["appUrl", "appName", "connector"];
2361
+ var SETUP_RENDER_REASONS = ["unknown-token", "missing-context"];
2362
+ var SetupRenderError = class extends Error {
2363
+ constructor(reason, message) {
2364
+ super(message);
2365
+ this.reason = reason;
2366
+ this.name = "SetupRenderError";
2367
+ }
2368
+ reason;
2369
+ };
2370
+ var TOKEN = /\{\{([^{}]*)\}\}/g;
2371
+ function fill(text, context) {
2372
+ return text.replace(TOKEN, (whole, name) => {
2373
+ if (!SETUP_TOKENS.includes(name)) {
2374
+ throw new SetupRenderError(
2375
+ "unknown-token",
2376
+ `setup step text uses ${whole}, which is not one of ${SETUP_TOKENS.map((t) => `{{${t}}}`).join(", ")}`
2377
+ );
2378
+ }
2379
+ let value = context[name];
2380
+ if (value === void 0 || value === null || value === "") {
2381
+ throw new SetupRenderError("missing-context", `setup step text uses ${whole} and the host gave no value for ${name}`);
2382
+ }
2383
+ if (name === "appUrl" && value.endsWith("/")) value = value.slice(0, -1);
2384
+ return value;
2385
+ });
2386
+ }
2387
+ function renderSetup(steps, context) {
2388
+ return steps.map((step) => {
2389
+ const out = {
2390
+ title: fill(step.title, context),
2391
+ detail: fill(step.detail, context),
2392
+ actor: step.actor ?? "person",
2393
+ fields: [...step.fields ?? []]
2394
+ };
2395
+ if (step.url !== void 0) out.url = fill(step.url, context);
2396
+ if (step.prompt !== void 0) out.prompt = fill(step.prompt, context);
2397
+ if (step.done !== void 0) out.done = fill(step.done, context);
2398
+ if (step.copy !== void 0) {
2399
+ out.copy = step.copy.map((c) => ({ label: fill(c.label, context), value: fill(c.value, context) }));
2400
+ }
2401
+ return out;
2402
+ });
2403
+ }
2292
2404
 
2293
2405
  // src/trigger.ts
2294
2406
  function isOidcJwtSpec(spec) {
@@ -2363,6 +2475,7 @@ export {
2363
2475
  CONNECTOR_API_VERSION,
2364
2476
  CONNECTOR_MODES,
2365
2477
  CREDENTIAL_SCOPES,
2478
+ CURSOR_READ_REASONS,
2366
2479
  ConnectorAmbiguous,
2367
2480
  ConnectorApiMismatch,
2368
2481
  ConnectorAuthError,
@@ -2374,6 +2487,7 @@ export {
2374
2487
  ConnectorRequestError,
2375
2488
  ConnectorTransient,
2376
2489
  ConnectorUnreachable,
2490
+ CursorReadError,
2377
2491
  DEFAULT_IDEMPOTENCY_WINDOW_SECONDS,
2378
2492
  DEFAULT_RETRY,
2379
2493
  DELIVERY_DECODE_KINDS,
@@ -2391,8 +2505,12 @@ export {
2391
2505
  RENDERER_VERSION,
2392
2506
  REVIEW_STALE_DAYS,
2393
2507
  SANDBOX_KINDS,
2508
+ SETUP_ACTORS,
2509
+ SETUP_RENDER_REASONS,
2510
+ SETUP_TOKENS,
2394
2511
  SIGNED_URI_RULES,
2395
2512
  SUPPORTED_CONNECTOR_API,
2513
+ SetupRenderError,
2396
2514
  assertConnectorApi,
2397
2515
  byteRangeOf,
2398
2516
  callConnector,
@@ -2442,9 +2560,11 @@ export {
2442
2560
  probe,
2443
2561
  providerProblems,
2444
2562
  providerSandboxIsSelectable,
2563
+ readWithCursor,
2445
2564
  registerConnectionHost,
2446
2565
  registerTransport,
2447
2566
  render,
2567
+ renderSetup,
2448
2568
  reported,
2449
2569
  resetRateState,
2450
2570
  resolveConnection,