@particle-academy/fancy-connector-core 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/dist/index.cjs +120 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -3
- package/dist/index.d.ts +122 -3
- package/dist/index.js +114 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.cts
CHANGED
|
@@ -1420,7 +1420,8 @@ declare const NO_IDEMPOTENCY_KEY_WARNING: string;
|
|
|
1420
1420
|
* the host must re-list (sync token or full) AND re-subscribe.
|
|
1421
1421
|
*
|
|
1422
1422
|
* The boundaries are DECIDED, not measured, and they are pinned in
|
|
1423
|
-
* `
|
|
1423
|
+
* fancy-conformance's `shared/subscription-lease` suite, which drives the PHP
|
|
1424
|
+
* twin too (`tests/subscription-lease.test.ts` and its Pest mirror).
|
|
1424
1425
|
*/
|
|
1425
1426
|
|
|
1426
1427
|
type SubscriptionLease = {
|
|
@@ -1433,6 +1434,42 @@ type SubscriptionLease = {
|
|
|
1433
1434
|
};
|
|
1434
1435
|
type LeaseState = "active" | "due" | "expired";
|
|
1435
1436
|
type LeaseAction = "none" | "renew" | "resync";
|
|
1437
|
+
/**
|
|
1438
|
+
* How a provider spells its expiry. Two, because two providers: Google
|
|
1439
|
+
* Calendar's channel `expiration` is epoch MILLISECONDS (as a JSON string, and
|
|
1440
|
+
* a number is accepted too); Microsoft Graph's `expirationDateTime` is ISO
|
|
1441
|
+
* 8601 with a seven-digit fraction. A unit no shipped provider spells is not
|
|
1442
|
+
* here — a vocabulary with no provider is a claim that outruns the code.
|
|
1443
|
+
*
|
|
1444
|
+
* Data as well as a type: a host validates a definition at the JSON boundary,
|
|
1445
|
+
* where `tsc` cannot see.
|
|
1446
|
+
*/
|
|
1447
|
+
declare const EXPIRES_AT_UNITS: readonly ["rfc3339", "epoch-ms"];
|
|
1448
|
+
type ExpiresAtUnit = (typeof EXPIRES_AT_UNITS)[number];
|
|
1449
|
+
/**
|
|
1450
|
+
* What a subscription trigger DECLARES about its lease, so a host can build
|
|
1451
|
+
* the value from the provider's create (or renew) response without knowing
|
|
1452
|
+
* the provider.
|
|
1453
|
+
*/
|
|
1454
|
+
type LeaseDeclaration = {
|
|
1455
|
+
/** Dotted path to the expiry in the create/renew response, e.g. `expiration` or `channel.expiration`. */
|
|
1456
|
+
expiresAtFrom: string;
|
|
1457
|
+
expiresAtUnit: ExpiresAtUnit;
|
|
1458
|
+
/** How early the host renews, in seconds. Positive. */
|
|
1459
|
+
renewBeforeSeconds: number;
|
|
1460
|
+
/** The operation the host calls when the lease is due. */
|
|
1461
|
+
renewOperation: string;
|
|
1462
|
+
};
|
|
1463
|
+
/**
|
|
1464
|
+
* Build the lease from the provider's create (or renew) response, by
|
|
1465
|
+
* declaration. The declared unit is never guessed around: digits under
|
|
1466
|
+
* `rfc3339`, or an instant under `epoch-ms`, are refused — a lease built from
|
|
1467
|
+
* a misread expiry is one that expires unannounced.
|
|
1468
|
+
*
|
|
1469
|
+
* The expiry is stored as an RFC 3339 instant in UTC at millisecond
|
|
1470
|
+
* precision; the lease's own refusals (margin, operation) still apply.
|
|
1471
|
+
*/
|
|
1472
|
+
declare function leaseFromResponse(declaration: LeaseDeclaration, response: unknown, at?: ConnectorErrorContext): SubscriptionLease;
|
|
1436
1473
|
/**
|
|
1437
1474
|
* Validate a declaration and return the lease — a plain value a host stores
|
|
1438
1475
|
* beside the trigger and hands back to `leaseState` / `leaseAction` later.
|
|
@@ -2296,6 +2333,15 @@ type WebhookVerification = {
|
|
|
2296
2333
|
reason: string;
|
|
2297
2334
|
};
|
|
2298
2335
|
type HmacScheme = {
|
|
2336
|
+
/**
|
|
2337
|
+
* Optional and always `"hmac"`: every scheme written before 0.8.0 omits it
|
|
2338
|
+
* and still means HMAC. It exists so `verifyDelivery` dispatches on a NAMED
|
|
2339
|
+
* kind — `"shared-token"`, `"hmac"` or absent — and refuses any other value
|
|
2340
|
+
* by name, rather than treating "has no kind" as HMAC forever. (Fancy's
|
|
2341
|
+
* alignment review of 0.8.0: a third scheme that forgot its kind would
|
|
2342
|
+
* otherwise be verified as HMAC, silently.)
|
|
2343
|
+
*/
|
|
2344
|
+
kind?: "hmac";
|
|
2299
2345
|
/** Hash to use. */
|
|
2300
2346
|
algorithm: "SHA-256" | "SHA-1" | "SHA-512";
|
|
2301
2347
|
/**
|
|
@@ -2335,6 +2381,58 @@ declare function hmac(secret: string, payload: string, algorithm: HmacScheme["al
|
|
|
2335
2381
|
* attacker nothing they could not compute.
|
|
2336
2382
|
*/
|
|
2337
2383
|
declare function constantTimeEquals(a: string, b: string): boolean;
|
|
2384
|
+
/**
|
|
2385
|
+
* A delivery verified by a token the provider ECHOES rather than a signature
|
|
2386
|
+
* it computes.
|
|
2387
|
+
*
|
|
2388
|
+
* Google Calendar sends the channel's `token` back in `X-Goog-Channel-Token`
|
|
2389
|
+
* on every notification — with an EMPTY body, so there is nothing to sign.
|
|
2390
|
+
* Microsoft Graph sends `clientState` inside every item of the notification's
|
|
2391
|
+
* `value` array. Same refusal-by-default as HMAC, same result shape, and a
|
|
2392
|
+
* constant-time comparison: a token is a secret, and `===` leaks which prefix
|
|
2393
|
+
* was right.
|
|
2394
|
+
*
|
|
2395
|
+
* A body `path` is dotted; a segment ending in `[]` means EVERY element of that
|
|
2396
|
+
* array, all of which must match — one wrong item refuses the whole delivery.
|
|
2397
|
+
*/
|
|
2398
|
+
type SharedTokenScheme = {
|
|
2399
|
+
kind: "shared-token";
|
|
2400
|
+
in: "header";
|
|
2401
|
+
name: string;
|
|
2402
|
+
} | {
|
|
2403
|
+
kind: "shared-token";
|
|
2404
|
+
in: "body";
|
|
2405
|
+
path: string;
|
|
2406
|
+
};
|
|
2407
|
+
declare function isSharedTokenScheme(scheme: HmacScheme | SharedTokenScheme): scheme is SharedTokenScheme;
|
|
2408
|
+
declare function verifySharedToken(options: {
|
|
2409
|
+
raw: string;
|
|
2410
|
+
headers: Record<string, string | string[] | undefined>;
|
|
2411
|
+
secret: string | undefined;
|
|
2412
|
+
scheme: SharedTokenScheme;
|
|
2413
|
+
}): WebhookVerification;
|
|
2414
|
+
/**
|
|
2415
|
+
* A challenge the provider makes BEFORE it will deliver anything, answered by
|
|
2416
|
+
* echoing a query parameter as plain text. Microsoft Graph POSTs
|
|
2417
|
+
* `?validationToken=…` to the notification URL when a subscription is created
|
|
2418
|
+
* and refuses to create it unless the token comes back, decoded, as
|
|
2419
|
+
* `text/plain` within ten seconds.
|
|
2420
|
+
*
|
|
2421
|
+
* Declared as data on the trigger so a host can answer it in its own routing
|
|
2422
|
+
* layer; `handshakeResponse` is the pure half — what to send, or `undefined`
|
|
2423
|
+
* when the request is not a challenge at all.
|
|
2424
|
+
*/
|
|
2425
|
+
type ChallengeHandshake = {
|
|
2426
|
+
kind: "echo-query";
|
|
2427
|
+
/** The query parameter carrying the challenge. */
|
|
2428
|
+
param: string;
|
|
2429
|
+
contentType?: "text/plain";
|
|
2430
|
+
};
|
|
2431
|
+
declare function handshakeResponse(handshake: ChallengeHandshake | undefined, query: Record<string, string | string[] | undefined>): {
|
|
2432
|
+
status: 200;
|
|
2433
|
+
contentType: string;
|
|
2434
|
+
body: string;
|
|
2435
|
+
} | undefined;
|
|
2338
2436
|
/**
|
|
2339
2437
|
* Pull one header case-insensitively.
|
|
2340
2438
|
*
|
|
@@ -2385,6 +2483,13 @@ type TriggerDescriptor = {
|
|
|
2385
2483
|
setup: string;
|
|
2386
2484
|
/** For `subscription`: how long the provider keeps it alive, in seconds. */
|
|
2387
2485
|
subscriptionTtl?: number;
|
|
2486
|
+
/**
|
|
2487
|
+
* For `subscription`: where the provider's expiry sits in the create/renew
|
|
2488
|
+
* response and how it is spelled, so a host builds the `SubscriptionLease`
|
|
2489
|
+
* with `leaseFromResponse` and runs ONE renewal scheduler for every
|
|
2490
|
+
* expiring trigger.
|
|
2491
|
+
*/
|
|
2492
|
+
lease?: LeaseDeclaration;
|
|
2388
2493
|
/** For `webhook` / `subscription`: how a delivery is authenticated. */
|
|
2389
2494
|
verification?: WebhookVerificationSpec;
|
|
2390
2495
|
/** For `poll`: the provider's smallest sane interval, in seconds. */
|
|
@@ -2392,7 +2497,8 @@ type TriggerDescriptor = {
|
|
|
2392
2497
|
/** A faked sample event, so the node is runnable before any of the above. */
|
|
2393
2498
|
faker: ConnectorFaker;
|
|
2394
2499
|
};
|
|
2395
|
-
|
|
2500
|
+
/** The provider SIGNS each delivery. */
|
|
2501
|
+
type HmacVerificationSpec = {
|
|
2396
2502
|
/** Header carrying the signature. */
|
|
2397
2503
|
signatureHeader: string;
|
|
2398
2504
|
/** Header carrying the timestamp, when the scheme signs one. */
|
|
@@ -2406,7 +2512,20 @@ type WebhookVerificationSpec = {
|
|
|
2406
2512
|
signature?: string;
|
|
2407
2513
|
timestamp?: string;
|
|
2408
2514
|
};
|
|
2515
|
+
/** A challenge the provider makes before it will deliver anything. */
|
|
2516
|
+
handshake?: ChallengeHandshake;
|
|
2517
|
+
};
|
|
2518
|
+
/**
|
|
2519
|
+
* The provider ECHOES a token the subscriber chose. Google Calendar's channel
|
|
2520
|
+
* token, Graph's `clientState`. See `SharedTokenScheme`.
|
|
2521
|
+
*/
|
|
2522
|
+
type SharedTokenVerificationSpec = {
|
|
2523
|
+
scheme: SharedTokenScheme;
|
|
2524
|
+
/** A challenge the provider makes before it will deliver anything. */
|
|
2525
|
+
handshake?: ChallengeHandshake;
|
|
2409
2526
|
};
|
|
2527
|
+
type WebhookVerificationSpec = HmacVerificationSpec | SharedTokenVerificationSpec;
|
|
2528
|
+
declare function isSharedTokenSpec(spec: WebhookVerificationSpec): spec is SharedTokenVerificationSpec;
|
|
2410
2529
|
type InboundDelivery = {
|
|
2411
2530
|
/** The body EXACTLY as received. Not re-serialised. See `webhook.ts`. */
|
|
2412
2531
|
raw: string;
|
|
@@ -2436,4 +2555,4 @@ declare function verifyDelivery(trigger: TriggerDescriptor, delivery: InboundDel
|
|
|
2436
2555
|
*/
|
|
2437
2556
|
declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
|
|
2438
2557
|
|
|
2439
|
-
export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, 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 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, type DeliveryDeclaration, type DeliveryMechanism, type DeliveryOutcome, type DriftFinding, type DriftReport, FAKE_EPOCH, type FailureKind, type FakeRequest, type FakeValues, type HmacScheme, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type LeaseAction, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isUnconditionallyRetryable, leaseAction, leaseRenewAt, leaseState, linkRanges, measure, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, withResolvedLimit };
|
|
2558
|
+
export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, 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, type DeliveryDeclaration, type DeliveryMechanism, type DeliveryOutcome, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, type FailureKind, type FakeRequest, type FakeValues, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, 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, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifySharedToken, withResolvedLimit };
|
package/dist/index.d.ts
CHANGED
|
@@ -1420,7 +1420,8 @@ declare const NO_IDEMPOTENCY_KEY_WARNING: string;
|
|
|
1420
1420
|
* the host must re-list (sync token or full) AND re-subscribe.
|
|
1421
1421
|
*
|
|
1422
1422
|
* The boundaries are DECIDED, not measured, and they are pinned in
|
|
1423
|
-
* `
|
|
1423
|
+
* fancy-conformance's `shared/subscription-lease` suite, which drives the PHP
|
|
1424
|
+
* twin too (`tests/subscription-lease.test.ts` and its Pest mirror).
|
|
1424
1425
|
*/
|
|
1425
1426
|
|
|
1426
1427
|
type SubscriptionLease = {
|
|
@@ -1433,6 +1434,42 @@ type SubscriptionLease = {
|
|
|
1433
1434
|
};
|
|
1434
1435
|
type LeaseState = "active" | "due" | "expired";
|
|
1435
1436
|
type LeaseAction = "none" | "renew" | "resync";
|
|
1437
|
+
/**
|
|
1438
|
+
* How a provider spells its expiry. Two, because two providers: Google
|
|
1439
|
+
* Calendar's channel `expiration` is epoch MILLISECONDS (as a JSON string, and
|
|
1440
|
+
* a number is accepted too); Microsoft Graph's `expirationDateTime` is ISO
|
|
1441
|
+
* 8601 with a seven-digit fraction. A unit no shipped provider spells is not
|
|
1442
|
+
* here — a vocabulary with no provider is a claim that outruns the code.
|
|
1443
|
+
*
|
|
1444
|
+
* Data as well as a type: a host validates a definition at the JSON boundary,
|
|
1445
|
+
* where `tsc` cannot see.
|
|
1446
|
+
*/
|
|
1447
|
+
declare const EXPIRES_AT_UNITS: readonly ["rfc3339", "epoch-ms"];
|
|
1448
|
+
type ExpiresAtUnit = (typeof EXPIRES_AT_UNITS)[number];
|
|
1449
|
+
/**
|
|
1450
|
+
* What a subscription trigger DECLARES about its lease, so a host can build
|
|
1451
|
+
* the value from the provider's create (or renew) response without knowing
|
|
1452
|
+
* the provider.
|
|
1453
|
+
*/
|
|
1454
|
+
type LeaseDeclaration = {
|
|
1455
|
+
/** Dotted path to the expiry in the create/renew response, e.g. `expiration` or `channel.expiration`. */
|
|
1456
|
+
expiresAtFrom: string;
|
|
1457
|
+
expiresAtUnit: ExpiresAtUnit;
|
|
1458
|
+
/** How early the host renews, in seconds. Positive. */
|
|
1459
|
+
renewBeforeSeconds: number;
|
|
1460
|
+
/** The operation the host calls when the lease is due. */
|
|
1461
|
+
renewOperation: string;
|
|
1462
|
+
};
|
|
1463
|
+
/**
|
|
1464
|
+
* Build the lease from the provider's create (or renew) response, by
|
|
1465
|
+
* declaration. The declared unit is never guessed around: digits under
|
|
1466
|
+
* `rfc3339`, or an instant under `epoch-ms`, are refused — a lease built from
|
|
1467
|
+
* a misread expiry is one that expires unannounced.
|
|
1468
|
+
*
|
|
1469
|
+
* The expiry is stored as an RFC 3339 instant in UTC at millisecond
|
|
1470
|
+
* precision; the lease's own refusals (margin, operation) still apply.
|
|
1471
|
+
*/
|
|
1472
|
+
declare function leaseFromResponse(declaration: LeaseDeclaration, response: unknown, at?: ConnectorErrorContext): SubscriptionLease;
|
|
1436
1473
|
/**
|
|
1437
1474
|
* Validate a declaration and return the lease — a plain value a host stores
|
|
1438
1475
|
* beside the trigger and hands back to `leaseState` / `leaseAction` later.
|
|
@@ -2296,6 +2333,15 @@ type WebhookVerification = {
|
|
|
2296
2333
|
reason: string;
|
|
2297
2334
|
};
|
|
2298
2335
|
type HmacScheme = {
|
|
2336
|
+
/**
|
|
2337
|
+
* Optional and always `"hmac"`: every scheme written before 0.8.0 omits it
|
|
2338
|
+
* and still means HMAC. It exists so `verifyDelivery` dispatches on a NAMED
|
|
2339
|
+
* kind — `"shared-token"`, `"hmac"` or absent — and refuses any other value
|
|
2340
|
+
* by name, rather than treating "has no kind" as HMAC forever. (Fancy's
|
|
2341
|
+
* alignment review of 0.8.0: a third scheme that forgot its kind would
|
|
2342
|
+
* otherwise be verified as HMAC, silently.)
|
|
2343
|
+
*/
|
|
2344
|
+
kind?: "hmac";
|
|
2299
2345
|
/** Hash to use. */
|
|
2300
2346
|
algorithm: "SHA-256" | "SHA-1" | "SHA-512";
|
|
2301
2347
|
/**
|
|
@@ -2335,6 +2381,58 @@ declare function hmac(secret: string, payload: string, algorithm: HmacScheme["al
|
|
|
2335
2381
|
* attacker nothing they could not compute.
|
|
2336
2382
|
*/
|
|
2337
2383
|
declare function constantTimeEquals(a: string, b: string): boolean;
|
|
2384
|
+
/**
|
|
2385
|
+
* A delivery verified by a token the provider ECHOES rather than a signature
|
|
2386
|
+
* it computes.
|
|
2387
|
+
*
|
|
2388
|
+
* Google Calendar sends the channel's `token` back in `X-Goog-Channel-Token`
|
|
2389
|
+
* on every notification — with an EMPTY body, so there is nothing to sign.
|
|
2390
|
+
* Microsoft Graph sends `clientState` inside every item of the notification's
|
|
2391
|
+
* `value` array. Same refusal-by-default as HMAC, same result shape, and a
|
|
2392
|
+
* constant-time comparison: a token is a secret, and `===` leaks which prefix
|
|
2393
|
+
* was right.
|
|
2394
|
+
*
|
|
2395
|
+
* A body `path` is dotted; a segment ending in `[]` means EVERY element of that
|
|
2396
|
+
* array, all of which must match — one wrong item refuses the whole delivery.
|
|
2397
|
+
*/
|
|
2398
|
+
type SharedTokenScheme = {
|
|
2399
|
+
kind: "shared-token";
|
|
2400
|
+
in: "header";
|
|
2401
|
+
name: string;
|
|
2402
|
+
} | {
|
|
2403
|
+
kind: "shared-token";
|
|
2404
|
+
in: "body";
|
|
2405
|
+
path: string;
|
|
2406
|
+
};
|
|
2407
|
+
declare function isSharedTokenScheme(scheme: HmacScheme | SharedTokenScheme): scheme is SharedTokenScheme;
|
|
2408
|
+
declare function verifySharedToken(options: {
|
|
2409
|
+
raw: string;
|
|
2410
|
+
headers: Record<string, string | string[] | undefined>;
|
|
2411
|
+
secret: string | undefined;
|
|
2412
|
+
scheme: SharedTokenScheme;
|
|
2413
|
+
}): WebhookVerification;
|
|
2414
|
+
/**
|
|
2415
|
+
* A challenge the provider makes BEFORE it will deliver anything, answered by
|
|
2416
|
+
* echoing a query parameter as plain text. Microsoft Graph POSTs
|
|
2417
|
+
* `?validationToken=…` to the notification URL when a subscription is created
|
|
2418
|
+
* and refuses to create it unless the token comes back, decoded, as
|
|
2419
|
+
* `text/plain` within ten seconds.
|
|
2420
|
+
*
|
|
2421
|
+
* Declared as data on the trigger so a host can answer it in its own routing
|
|
2422
|
+
* layer; `handshakeResponse` is the pure half — what to send, or `undefined`
|
|
2423
|
+
* when the request is not a challenge at all.
|
|
2424
|
+
*/
|
|
2425
|
+
type ChallengeHandshake = {
|
|
2426
|
+
kind: "echo-query";
|
|
2427
|
+
/** The query parameter carrying the challenge. */
|
|
2428
|
+
param: string;
|
|
2429
|
+
contentType?: "text/plain";
|
|
2430
|
+
};
|
|
2431
|
+
declare function handshakeResponse(handshake: ChallengeHandshake | undefined, query: Record<string, string | string[] | undefined>): {
|
|
2432
|
+
status: 200;
|
|
2433
|
+
contentType: string;
|
|
2434
|
+
body: string;
|
|
2435
|
+
} | undefined;
|
|
2338
2436
|
/**
|
|
2339
2437
|
* Pull one header case-insensitively.
|
|
2340
2438
|
*
|
|
@@ -2385,6 +2483,13 @@ type TriggerDescriptor = {
|
|
|
2385
2483
|
setup: string;
|
|
2386
2484
|
/** For `subscription`: how long the provider keeps it alive, in seconds. */
|
|
2387
2485
|
subscriptionTtl?: number;
|
|
2486
|
+
/**
|
|
2487
|
+
* For `subscription`: where the provider's expiry sits in the create/renew
|
|
2488
|
+
* response and how it is spelled, so a host builds the `SubscriptionLease`
|
|
2489
|
+
* with `leaseFromResponse` and runs ONE renewal scheduler for every
|
|
2490
|
+
* expiring trigger.
|
|
2491
|
+
*/
|
|
2492
|
+
lease?: LeaseDeclaration;
|
|
2388
2493
|
/** For `webhook` / `subscription`: how a delivery is authenticated. */
|
|
2389
2494
|
verification?: WebhookVerificationSpec;
|
|
2390
2495
|
/** For `poll`: the provider's smallest sane interval, in seconds. */
|
|
@@ -2392,7 +2497,8 @@ type TriggerDescriptor = {
|
|
|
2392
2497
|
/** A faked sample event, so the node is runnable before any of the above. */
|
|
2393
2498
|
faker: ConnectorFaker;
|
|
2394
2499
|
};
|
|
2395
|
-
|
|
2500
|
+
/** The provider SIGNS each delivery. */
|
|
2501
|
+
type HmacVerificationSpec = {
|
|
2396
2502
|
/** Header carrying the signature. */
|
|
2397
2503
|
signatureHeader: string;
|
|
2398
2504
|
/** Header carrying the timestamp, when the scheme signs one. */
|
|
@@ -2406,7 +2512,20 @@ type WebhookVerificationSpec = {
|
|
|
2406
2512
|
signature?: string;
|
|
2407
2513
|
timestamp?: string;
|
|
2408
2514
|
};
|
|
2515
|
+
/** A challenge the provider makes before it will deliver anything. */
|
|
2516
|
+
handshake?: ChallengeHandshake;
|
|
2517
|
+
};
|
|
2518
|
+
/**
|
|
2519
|
+
* The provider ECHOES a token the subscriber chose. Google Calendar's channel
|
|
2520
|
+
* token, Graph's `clientState`. See `SharedTokenScheme`.
|
|
2521
|
+
*/
|
|
2522
|
+
type SharedTokenVerificationSpec = {
|
|
2523
|
+
scheme: SharedTokenScheme;
|
|
2524
|
+
/** A challenge the provider makes before it will deliver anything. */
|
|
2525
|
+
handshake?: ChallengeHandshake;
|
|
2409
2526
|
};
|
|
2527
|
+
type WebhookVerificationSpec = HmacVerificationSpec | SharedTokenVerificationSpec;
|
|
2528
|
+
declare function isSharedTokenSpec(spec: WebhookVerificationSpec): spec is SharedTokenVerificationSpec;
|
|
2410
2529
|
type InboundDelivery = {
|
|
2411
2530
|
/** The body EXACTLY as received. Not re-serialised. See `webhook.ts`. */
|
|
2412
2531
|
raw: string;
|
|
@@ -2436,4 +2555,4 @@ declare function verifyDelivery(trigger: TriggerDescriptor, delivery: InboundDel
|
|
|
2436
2555
|
*/
|
|
2437
2556
|
declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
|
|
2438
2557
|
|
|
2439
|
-
export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, 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 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, type DeliveryDeclaration, type DeliveryMechanism, type DeliveryOutcome, type DriftFinding, type DriftReport, FAKE_EPOCH, type FailureKind, type FakeRequest, type FakeValues, type HmacScheme, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type LeaseAction, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isUnconditionallyRetryable, leaseAction, leaseRenewAt, leaseState, linkRanges, measure, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, withResolvedLimit };
|
|
2558
|
+
export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, 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, type DeliveryDeclaration, type DeliveryMechanism, type DeliveryOutcome, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, type FailureKind, type FakeRequest, type FakeValues, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, 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, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifySharedToken, withResolvedLimit };
|
package/dist/index.js
CHANGED
|
@@ -914,6 +914,7 @@ function fnv1a(value) {
|
|
|
914
914
|
}
|
|
915
915
|
|
|
916
916
|
// src/lease.ts
|
|
917
|
+
var EXPIRES_AT_UNITS = ["rfc3339", "epoch-ms"];
|
|
917
918
|
var INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
918
919
|
var DEFAULT_CONTEXT = { service: "", operation: "subscription" };
|
|
919
920
|
function instantMs(value, field, at) {
|
|
@@ -923,12 +924,59 @@ function instantMs(value, field, at) {
|
|
|
923
924
|
at
|
|
924
925
|
);
|
|
925
926
|
}
|
|
926
|
-
const ms = Date.parse(value);
|
|
927
|
+
const ms = Date.parse(value.replace(/(\.\d{3})\d+/, "$1"));
|
|
927
928
|
if (Number.isNaN(ms)) {
|
|
928
929
|
throw new ConnectorConfigError(`${field} is not a real instant: ${JSON.stringify(value)}`, at);
|
|
929
930
|
}
|
|
930
931
|
return ms;
|
|
931
932
|
}
|
|
933
|
+
function leaseFromResponse(declaration, response, at = DEFAULT_CONTEXT) {
|
|
934
|
+
const { expiresAtFrom: path, expiresAtUnit: unit } = declaration;
|
|
935
|
+
if (!EXPIRES_AT_UNITS.includes(unit)) {
|
|
936
|
+
throw new ConnectorConfigError(
|
|
937
|
+
`expiresAtUnit must be one of ${EXPIRES_AT_UNITS.join(" | ")}, got ${JSON.stringify(unit)}.`,
|
|
938
|
+
at
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
const value = readPath(response, path);
|
|
942
|
+
if (value === void 0 || value === null) {
|
|
943
|
+
throw new ConnectorConfigError(
|
|
944
|
+
`${path} is not present in the response, so no lease can be built \u2014 a subscription with no known expiry is one nobody renews.`,
|
|
945
|
+
at
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
let expiresAt;
|
|
949
|
+
if (unit === "epoch-ms") {
|
|
950
|
+
const ms = typeof value === "number" ? value : typeof value === "string" && /^\d+$/.test(value) ? Number(value) : Number.NaN;
|
|
951
|
+
if (!Number.isSafeInteger(ms)) {
|
|
952
|
+
throw new ConnectorConfigError(
|
|
953
|
+
`${path} must be epoch milliseconds as digits under "epoch-ms", got ${JSON.stringify(value)}.`,
|
|
954
|
+
at
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
expiresAt = new Date(ms).toISOString();
|
|
958
|
+
} else {
|
|
959
|
+
if (typeof value !== "string" || !INSTANT.test(value)) {
|
|
960
|
+
throw new ConnectorConfigError(
|
|
961
|
+
`${path} must be an RFC 3339 instant under "rfc3339", got ${JSON.stringify(value)}.`,
|
|
962
|
+
at
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
expiresAt = new Date(instantMs(value, path, at)).toISOString();
|
|
966
|
+
}
|
|
967
|
+
return subscriptionLease(
|
|
968
|
+
{ expiresAt, renewBeforeSeconds: declaration.renewBeforeSeconds, renewOperation: declaration.renewOperation },
|
|
969
|
+
at
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
function readPath(value, path) {
|
|
973
|
+
let current = value;
|
|
974
|
+
for (const segment of path.split(".")) {
|
|
975
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
976
|
+
current = current[segment];
|
|
977
|
+
}
|
|
978
|
+
return current;
|
|
979
|
+
}
|
|
932
980
|
function subscriptionLease(input, at = DEFAULT_CONTEXT) {
|
|
933
981
|
instantMs(input.expiresAt, "expiresAt", at);
|
|
934
982
|
if (!Number.isInteger(input.renewBeforeSeconds) || input.renewBeforeSeconds <= 0) {
|
|
@@ -1558,6 +1606,52 @@ function constantTimeEquals(a, b) {
|
|
|
1558
1606
|
for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
1559
1607
|
return diff === 0;
|
|
1560
1608
|
}
|
|
1609
|
+
function isSharedTokenScheme(scheme) {
|
|
1610
|
+
return "kind" in scheme && scheme.kind === "shared-token";
|
|
1611
|
+
}
|
|
1612
|
+
function verifySharedToken(options) {
|
|
1613
|
+
const { raw, headers, secret, scheme } = options;
|
|
1614
|
+
if (!secret) {
|
|
1615
|
+
return { ok: false, reason: "no shared token configured for this trigger" };
|
|
1616
|
+
}
|
|
1617
|
+
let tokens;
|
|
1618
|
+
if (scheme.in === "header") {
|
|
1619
|
+
tokens = [header2(headers, scheme.name)];
|
|
1620
|
+
} else {
|
|
1621
|
+
let parsed;
|
|
1622
|
+
try {
|
|
1623
|
+
parsed = JSON.parse(raw);
|
|
1624
|
+
} catch {
|
|
1625
|
+
return { ok: false, reason: "delivery body is not JSON" };
|
|
1626
|
+
}
|
|
1627
|
+
tokens = readTokens(parsed, scheme.path.split("."));
|
|
1628
|
+
}
|
|
1629
|
+
const present = tokens.filter((t) => t !== void 0 && t !== null && t !== "");
|
|
1630
|
+
if (present.length === 0) return { ok: false, reason: "delivery carried no token" };
|
|
1631
|
+
let matched = present.length === tokens.length;
|
|
1632
|
+
for (const token of present) {
|
|
1633
|
+
matched = typeof token === "string" && constantTimeEquals(secret, token) && matched;
|
|
1634
|
+
}
|
|
1635
|
+
return matched ? { ok: true } : { ok: false, reason: "token did not match" };
|
|
1636
|
+
}
|
|
1637
|
+
function readTokens(value, segments) {
|
|
1638
|
+
if (segments.length === 0) return [value];
|
|
1639
|
+
const [head, ...rest] = segments;
|
|
1640
|
+
const eachElement = head.endsWith("[]");
|
|
1641
|
+
const key = eachElement ? head.slice(0, -2) : head;
|
|
1642
|
+
if (value === null || typeof value !== "object") return [void 0];
|
|
1643
|
+
const next = value[key];
|
|
1644
|
+
if (!eachElement) return readTokens(next, rest);
|
|
1645
|
+
if (!Array.isArray(next)) return [void 0];
|
|
1646
|
+
return next.flatMap((element) => readTokens(element, rest));
|
|
1647
|
+
}
|
|
1648
|
+
function handshakeResponse(handshake, query) {
|
|
1649
|
+
if (!handshake) return void 0;
|
|
1650
|
+
const raw = query[handshake.param];
|
|
1651
|
+
const token = Array.isArray(raw) ? raw[0] : raw;
|
|
1652
|
+
if (!token) return void 0;
|
|
1653
|
+
return { status: 200, contentType: handshake.contentType ?? "text/plain", body: token };
|
|
1654
|
+
}
|
|
1561
1655
|
function header2(headers, name) {
|
|
1562
1656
|
const wanted = name.toLowerCase();
|
|
1563
1657
|
for (const [key, value] of Object.entries(headers)) {
|
|
@@ -1568,6 +1662,9 @@ function header2(headers, name) {
|
|
|
1568
1662
|
}
|
|
1569
1663
|
|
|
1570
1664
|
// src/trigger.ts
|
|
1665
|
+
function isSharedTokenSpec(spec) {
|
|
1666
|
+
return isSharedTokenScheme(spec.scheme);
|
|
1667
|
+
}
|
|
1571
1668
|
async function verifyDelivery(trigger, delivery, secret, now) {
|
|
1572
1669
|
const spec = trigger.verification;
|
|
1573
1670
|
if (!spec) {
|
|
@@ -1576,6 +1673,16 @@ async function verifyDelivery(trigger, delivery, secret, now) {
|
|
|
1576
1673
|
reason: `${trigger.service}.${trigger.operation} declares no signature scheme, so a delivery cannot be trusted.`
|
|
1577
1674
|
};
|
|
1578
1675
|
}
|
|
1676
|
+
if (isSharedTokenSpec(spec)) {
|
|
1677
|
+
return verifySharedToken({ raw: delivery.raw, headers: delivery.headers, secret, scheme: spec.scheme });
|
|
1678
|
+
}
|
|
1679
|
+
const kind = spec.scheme.kind ?? "hmac";
|
|
1680
|
+
if (kind !== "hmac") {
|
|
1681
|
+
return {
|
|
1682
|
+
ok: false,
|
|
1683
|
+
reason: `${trigger.service}.${trigger.operation} declares a verification scheme "${kind}" this runtime does not know \u2014 refusing rather than guessing.`
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1579
1686
|
const rawHeader = header2(delivery.headers, spec.signatureHeader);
|
|
1580
1687
|
const parsed = spec.parse && rawHeader ? spec.parse(rawHeader) : { signature: rawHeader };
|
|
1581
1688
|
const timestamp = parsed.timestamp ?? (spec.timestampHeader ? header2(delivery.headers, spec.timestampHeader) : void 0);
|
|
@@ -1625,6 +1732,7 @@ export {
|
|
|
1625
1732
|
ConnectorUnreachable,
|
|
1626
1733
|
DEFAULT_IDEMPOTENCY_WINDOW_SECONDS,
|
|
1627
1734
|
DEFAULT_RETRY,
|
|
1735
|
+
EXPIRES_AT_UNITS,
|
|
1628
1736
|
FAKE_EPOCH,
|
|
1629
1737
|
MAX_IDEMPOTENCY_KEY_LENGTH,
|
|
1630
1738
|
NO_IDEMPOTENCY_KEY_WARNING,
|
|
@@ -1651,14 +1759,18 @@ export {
|
|
|
1651
1759
|
fakeValues,
|
|
1652
1760
|
getConnectionHost,
|
|
1653
1761
|
graphemes,
|
|
1762
|
+
handshakeResponse,
|
|
1654
1763
|
header2 as header,
|
|
1655
1764
|
hmac,
|
|
1656
1765
|
httpFailure,
|
|
1657
1766
|
idempotencyKeyFor,
|
|
1658
1767
|
isEmptyPayload,
|
|
1659
1768
|
isRemote,
|
|
1769
|
+
isSharedTokenScheme,
|
|
1770
|
+
isSharedTokenSpec,
|
|
1660
1771
|
isUnconditionallyRetryable,
|
|
1661
1772
|
leaseAction,
|
|
1773
|
+
leaseFromResponse,
|
|
1662
1774
|
leaseRenewAt,
|
|
1663
1775
|
leaseState,
|
|
1664
1776
|
linkRanges,
|
|
@@ -1694,6 +1806,7 @@ export {
|
|
|
1694
1806
|
utf8Length,
|
|
1695
1807
|
verifyDelivery,
|
|
1696
1808
|
verifyHmac,
|
|
1809
|
+
verifySharedToken,
|
|
1697
1810
|
withResolvedLimit
|
|
1698
1811
|
};
|
|
1699
1812
|
//# sourceMappingURL=index.js.map
|