@particle-academy/fancy-connector-core 0.0.0 → 0.2.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/CHANGELOG.md +179 -103
- package/LICENSE +21 -21
- package/README.md +200 -175
- package/dist/index.cjs +95 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +143 -9
- package/dist/index.d.ts +143 -9
- package/dist/index.js +85 -10
- package/dist/index.js.map +1 -1
- package/package.json +71 -71
package/dist/index.d.cts
CHANGED
|
@@ -37,8 +37,22 @@
|
|
|
37
37
|
* one status id, Telegram needs a message id and a chat. A shape naming one
|
|
38
38
|
* provider's model would be wrong for the next one, so the chain carries
|
|
39
39
|
* whatever the poster returned and never reads inside it.
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
*
|
|
41
|
+
* **`object`, not `Record<string, string | number>`** — and the difference is
|
|
42
|
+
* not pedantry. An ordinary interface does not satisfy an index signature
|
|
43
|
+
* unless it declares one, so `interface PostRef { uri: string; cid: string }`
|
|
44
|
+
* did NOT satisfy the old constraint. The reference consumer worked around it
|
|
45
|
+
* with `postChain<T & ChainRef>` plus two `as unknown as` casts, and could not
|
|
46
|
+
* use `ChainOutcome<T>` in their own signatures at all — because the only other
|
|
47
|
+
* fix was to add an index signature to a type used across their codebase in
|
|
48
|
+
* order to satisfy a generic used in one place, which weakens the type
|
|
49
|
+
* everywhere to please one call site.
|
|
50
|
+
*
|
|
51
|
+
* A constraint everyone casts past is not enforcing anything; it is just making
|
|
52
|
+
* the casts. `object` still rejects the mistake worth rejecting — a primitive
|
|
53
|
+
* as a reference — and accepts every real one.
|
|
54
|
+
*/
|
|
55
|
+
type ChainRef = object;
|
|
42
56
|
type ChainLinks<Ref extends ChainRef> = {
|
|
43
57
|
/** The top of the conversation. Fixed for the whole chain. */
|
|
44
58
|
root: Ref;
|
|
@@ -496,10 +510,39 @@ declare const CONNECTOR_MODES: ConnectorMode[];
|
|
|
496
510
|
* - `base-url` — a different host entirely (PayPal's `api-m.sandbox.paypal.com`).
|
|
497
511
|
* - `separate-account` — a distinct tenant you must create, often with its own
|
|
498
512
|
* login host (Salesforce sandbox orgs on `test.salesforce.com`).
|
|
513
|
+
* - `restricted-reach` — there is no separate estate at all; what the provider
|
|
514
|
+
* offers instead is an **account-level restriction on who can see the
|
|
515
|
+
* result**. A Meta app in Development Mode; an unaudited TikTok app that can
|
|
516
|
+
* only post `SELF_ONLY`. Same credentials, same endpoints, same estate — only
|
|
517
|
+
* the audience changes, and nothing in a request selects it.
|
|
518
|
+
*
|
|
519
|
+
* **This is the dangerous one**, and it is why it is not folded into `none`.
|
|
520
|
+
* It is the shape most likely to be mistaken for a sandbox, because it looks
|
|
521
|
+
* exactly like a successful post that nobody can see: `ok: true`, a real id,
|
|
522
|
+
* no audience. `none` says "there is nothing"; this says "there is something,
|
|
523
|
+
* it is not selectable from here, and success does not mean reach".
|
|
499
524
|
* - `none` — the provider has no test estate. `sandbox` is then not offered at
|
|
500
|
-
* all, and the
|
|
501
|
-
|
|
502
|
-
|
|
525
|
+
* all, and the honest choices are `fake` and `live`.
|
|
526
|
+
* - `unverified` — **nobody has checked yet.** A real state, and the type has to
|
|
527
|
+
* carry it: this is the field where being wrong sends someone to a live
|
|
528
|
+
* estate believing it is a test one, so "researched but not verified" must not
|
|
529
|
+
* be forced to pick one of the other five. It belongs on a provider declared
|
|
530
|
+
* `implemented: false`; on one declared `implemented: true` it is a finding,
|
|
531
|
+
* and `providerProblems()` reports it.
|
|
532
|
+
*/
|
|
533
|
+
type SandboxKind = "credential" | "base-url" | "separate-account" | "restricted-reach" | "none" | "unverified";
|
|
534
|
+
/** Every value, as data, for a host validating input that crossed a JSON boundary. */
|
|
535
|
+
declare const SANDBOX_KINDS: readonly SandboxKind[];
|
|
536
|
+
declare function sandboxIsSelectable(kind: SandboxKind): boolean;
|
|
537
|
+
/**
|
|
538
|
+
* Why `mode: "sandbox"` cannot be honoured for this kind, in the words the
|
|
539
|
+
* person reading it needs.
|
|
540
|
+
*
|
|
541
|
+
* Three reasons, three messages. Collapsing them into "no sandbox available"
|
|
542
|
+
* would hide the one that matters: `restricted-reach` is not an absence, it is
|
|
543
|
+
* a different mechanism with a trap in it.
|
|
544
|
+
*/
|
|
545
|
+
declare function sandboxRefusal(service: string, kind: SandboxKind): string;
|
|
503
546
|
/** The host's view of where it is running. Kept tiny so it is trivial to fake. */
|
|
504
547
|
type HostEnvironment = {
|
|
505
548
|
/** True only in a real production deployment. Everything else is "local". */
|
|
@@ -1461,7 +1504,29 @@ type RenderedPayload = {
|
|
|
1461
1504
|
* ignores this; the point of the rule set is that most do not have to.
|
|
1462
1505
|
*/
|
|
1463
1506
|
type RenderRules = {
|
|
1464
|
-
/**
|
|
1507
|
+
/**
|
|
1508
|
+
* The provider's limit per message, or `null` where it imposes none.
|
|
1509
|
+
*
|
|
1510
|
+
* **`null` means UNCOUNTED, and it is a real answer** — distinct from "we do
|
|
1511
|
+
* not know", which is not a renderable state at all. A caller that does not
|
|
1512
|
+
* know the limit must find out before rendering, because every alternative
|
|
1513
|
+
* silently produces the wrong bytes.
|
|
1514
|
+
*
|
|
1515
|
+
* ## This must stay RESOLVABLE PER CONNECTION, and never become static
|
|
1516
|
+
*
|
|
1517
|
+
* A Mastodon instance's character limit comes from the server it is running:
|
|
1518
|
+
* one instance allows 500, another 5000, and the same connector talks to
|
|
1519
|
+
* both. Baking the limit into the connector breaks in the quietest way
|
|
1520
|
+
* available — rendering to 500 on an instance that allows 5000 wastes most of
|
|
1521
|
+
* a post, and rendering to 5000 on one that allows 500 produces a refusal the
|
|
1522
|
+
* author cannot see coming from the preview.
|
|
1523
|
+
*
|
|
1524
|
+
* So the limit is resolved by the CALLER, from the connection, and passed IN
|
|
1525
|
+
* — which is also what makes it part of what was approved rather than
|
|
1526
|
+
* something decided later behind the approver's back. `withResolvedLimit()`
|
|
1527
|
+
* is the supported way to do that, and a test pins that per-call rules beat
|
|
1528
|
+
* declared ones.
|
|
1529
|
+
*/
|
|
1465
1530
|
limit: number | null;
|
|
1466
1531
|
unit: TextUnit;
|
|
1467
1532
|
/**
|
|
@@ -1529,6 +1594,19 @@ declare function payloadHash(payload: RenderedPayload): Promise<string>;
|
|
|
1529
1594
|
* every one of those checks from being hollow.
|
|
1530
1595
|
*/
|
|
1531
1596
|
declare function isEmptyPayload(payload: RenderedPayload): boolean;
|
|
1597
|
+
/**
|
|
1598
|
+
* Apply a per-connection limit over a connector's declared rules.
|
|
1599
|
+
*
|
|
1600
|
+
* The one supported way to do the thing `RenderRules.limit` insists on: a
|
|
1601
|
+
* Mastodon instance publishes its own `max_toot_chars`, a Discord webhook does
|
|
1602
|
+
* not, and the same connector serves both. Resolving happens at the call site,
|
|
1603
|
+
* with the connection in hand, and the resolved value travels INTO `render` so
|
|
1604
|
+
* it is part of the payload the approver saw.
|
|
1605
|
+
*
|
|
1606
|
+
* `undefined` keeps whatever the connector declared — "I did not look" is not
|
|
1607
|
+
* the same as "there is no limit", and only the second is `null`.
|
|
1608
|
+
*/
|
|
1609
|
+
declare function withResolvedLimit(rules: RenderRules, limit: number | null | undefined): RenderRules;
|
|
1532
1610
|
|
|
1533
1611
|
/**
|
|
1534
1612
|
* The seam — two objects, deliberately separate.
|
|
@@ -1576,6 +1654,28 @@ declare function isEmptyPayload(payload: RenderedPayload): boolean;
|
|
|
1576
1654
|
* path — and the reference implementation very nearly stored it as
|
|
1577
1655
|
* configuration because it looked like a URL.
|
|
1578
1656
|
*/
|
|
1657
|
+
/**
|
|
1658
|
+
* Who a credential belongs to.
|
|
1659
|
+
*
|
|
1660
|
+
* Exported as a runtime constant as well as a type — see `CREDENTIAL_SCOPES`.
|
|
1661
|
+
*/
|
|
1662
|
+
type CredentialScope = "provider" | "account";
|
|
1663
|
+
/**
|
|
1664
|
+
* The scopes, as DATA.
|
|
1665
|
+
*
|
|
1666
|
+
* Because this union crosses a JSON boundary and the compiler cannot follow it
|
|
1667
|
+
* there. When these values were renamed from `app`/`brand`, a consumer that
|
|
1668
|
+
* re-declared the field shape on its client kept compiling — their
|
|
1669
|
+
* `f.scope === "brand"` silently became never-true, and every credential field
|
|
1670
|
+
* would have rendered as shared. `tsc` gives a host mirroring these types no
|
|
1671
|
+
* help at all, so the values ship as data a host can validate against at the
|
|
1672
|
+
* boundary where the compiler stops.
|
|
1673
|
+
*/
|
|
1674
|
+
declare const CREDENTIAL_SCOPES: readonly CredentialScope[];
|
|
1675
|
+
/** Severities, as data, for the same reason. */
|
|
1676
|
+
declare const PROBLEM_SEVERITIES: readonly ["block", "warn"];
|
|
1677
|
+
/** Canonical metric names, as data, for the same reason. */
|
|
1678
|
+
declare const CANONICAL_METRICS: readonly ["like", "share", "reply", "quote", "view"];
|
|
1579
1679
|
type CredentialField = {
|
|
1580
1680
|
/** Stable key. The host maps it to wherever it keeps values. */
|
|
1581
1681
|
key: string;
|
|
@@ -1589,7 +1689,7 @@ type CredentialField = {
|
|
|
1589
1689
|
* The distinction exists because getting it wrong means either asking for the
|
|
1590
1690
|
* same app secret five times or letting one account's token reach another's.
|
|
1591
1691
|
*/
|
|
1592
|
-
scope:
|
|
1692
|
+
scope: CredentialScope;
|
|
1593
1693
|
secret: boolean;
|
|
1594
1694
|
required: boolean;
|
|
1595
1695
|
/** A hint for an empty field. NEVER a real value. */
|
|
@@ -1642,8 +1742,26 @@ type ProviderAdapter = {
|
|
|
1642
1742
|
* that anything can be revoked. "No known expiry" is not "cannot stop working".
|
|
1643
1743
|
*/
|
|
1644
1744
|
credentialLifetimeDays?: number;
|
|
1645
|
-
/**
|
|
1745
|
+
/**
|
|
1746
|
+
* How the provider exposes a test estate.
|
|
1747
|
+
*
|
|
1748
|
+
* **`"unverified"` is a real answer and is the right one until somebody has
|
|
1749
|
+
* actually checked.** Being wrong here points a workflow at a live estate
|
|
1750
|
+
* while a person believes it is a test one, so the type carries "nobody
|
|
1751
|
+
* looked" rather than forcing a guess — a comment saying so is not a type, and
|
|
1752
|
+
* `providerProblems()` reports the combination `implemented: true` +
|
|
1753
|
+
* `unverified`.
|
|
1754
|
+
*/
|
|
1646
1755
|
sandbox: SandboxKind;
|
|
1756
|
+
/**
|
|
1757
|
+
* What `verify` proves, and what it does NOT.
|
|
1758
|
+
*
|
|
1759
|
+
* Required whenever `verify` exists, and checked by `providerProblems()`.
|
|
1760
|
+
* Telegram's `getMe` validates the token and says nothing about whether the
|
|
1761
|
+
* bot was added to the target chat — which is the step everyone actually gets
|
|
1762
|
+
* stuck on. A green tick that means more than it should is worse than no tick.
|
|
1763
|
+
*/
|
|
1764
|
+
proves?: string;
|
|
1647
1765
|
/**
|
|
1648
1766
|
* A read-only call proving the credential works AND reaches the right account.
|
|
1649
1767
|
*
|
|
@@ -1860,6 +1978,22 @@ declare function capabilityProblems(connector: Connector<never>): string[];
|
|
|
1860
1978
|
* `undefined` and non-numbers do not.
|
|
1861
1979
|
*/
|
|
1862
1980
|
declare function reported(values: Record<string, unknown>): Record<string, number>;
|
|
1981
|
+
/**
|
|
1982
|
+
* Every way a PROVIDER's declaration can outrun what anyone actually checked.
|
|
1983
|
+
*
|
|
1984
|
+
* The sibling of `capabilityProblems`, one level up. `capabilities.metrics: true`
|
|
1985
|
+
* with no shape turns an unimplemented feature into a reported zero; the
|
|
1986
|
+
* equivalent here turns *nobody looked* into a statement about a test estate —
|
|
1987
|
+
* and that field is the one where being wrong sends a person to a live estate
|
|
1988
|
+
* believing it is a test one.
|
|
1989
|
+
*
|
|
1990
|
+
* Strings rather than a throw, so a host reports all of them at once. A check
|
|
1991
|
+
* that stops at the first problem trains people to fix one thing and re-run,
|
|
1992
|
+
* which is how a list of six becomes six rounds.
|
|
1993
|
+
*/
|
|
1994
|
+
declare function providerProblems(provider: ProviderAdapter): string[];
|
|
1995
|
+
/** True when a provider's declared sandbox can actually be selected at run time. */
|
|
1996
|
+
declare function providerSandboxIsSelectable(provider: ProviderAdapter): boolean;
|
|
1863
1997
|
|
|
1864
1998
|
/**
|
|
1865
1999
|
* Dry-verify — proving the transport with a credential that cannot work.
|
|
@@ -2126,4 +2260,4 @@ declare function verifyDelivery(trigger: TriggerDescriptor, delivery: InboundDel
|
|
|
2126
2260
|
*/
|
|
2127
2261
|
declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
|
|
2128
2262
|
|
|
2129
|
-
export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type ByteRange, CONNECTOR_API_VERSION, CONNECTOR_MODES, 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, 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, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, 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, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SpecSource, 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, linkRanges, measure, payloadHash, postChain, probe, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac };
|
|
2263
|
+
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, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, 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 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, linkRanges, measure, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, withResolvedLimit };
|
package/dist/index.d.ts
CHANGED
|
@@ -37,8 +37,22 @@
|
|
|
37
37
|
* one status id, Telegram needs a message id and a chat. A shape naming one
|
|
38
38
|
* provider's model would be wrong for the next one, so the chain carries
|
|
39
39
|
* whatever the poster returned and never reads inside it.
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
*
|
|
41
|
+
* **`object`, not `Record<string, string | number>`** — and the difference is
|
|
42
|
+
* not pedantry. An ordinary interface does not satisfy an index signature
|
|
43
|
+
* unless it declares one, so `interface PostRef { uri: string; cid: string }`
|
|
44
|
+
* did NOT satisfy the old constraint. The reference consumer worked around it
|
|
45
|
+
* with `postChain<T & ChainRef>` plus two `as unknown as` casts, and could not
|
|
46
|
+
* use `ChainOutcome<T>` in their own signatures at all — because the only other
|
|
47
|
+
* fix was to add an index signature to a type used across their codebase in
|
|
48
|
+
* order to satisfy a generic used in one place, which weakens the type
|
|
49
|
+
* everywhere to please one call site.
|
|
50
|
+
*
|
|
51
|
+
* A constraint everyone casts past is not enforcing anything; it is just making
|
|
52
|
+
* the casts. `object` still rejects the mistake worth rejecting — a primitive
|
|
53
|
+
* as a reference — and accepts every real one.
|
|
54
|
+
*/
|
|
55
|
+
type ChainRef = object;
|
|
42
56
|
type ChainLinks<Ref extends ChainRef> = {
|
|
43
57
|
/** The top of the conversation. Fixed for the whole chain. */
|
|
44
58
|
root: Ref;
|
|
@@ -496,10 +510,39 @@ declare const CONNECTOR_MODES: ConnectorMode[];
|
|
|
496
510
|
* - `base-url` — a different host entirely (PayPal's `api-m.sandbox.paypal.com`).
|
|
497
511
|
* - `separate-account` — a distinct tenant you must create, often with its own
|
|
498
512
|
* login host (Salesforce sandbox orgs on `test.salesforce.com`).
|
|
513
|
+
* - `restricted-reach` — there is no separate estate at all; what the provider
|
|
514
|
+
* offers instead is an **account-level restriction on who can see the
|
|
515
|
+
* result**. A Meta app in Development Mode; an unaudited TikTok app that can
|
|
516
|
+
* only post `SELF_ONLY`. Same credentials, same endpoints, same estate — only
|
|
517
|
+
* the audience changes, and nothing in a request selects it.
|
|
518
|
+
*
|
|
519
|
+
* **This is the dangerous one**, and it is why it is not folded into `none`.
|
|
520
|
+
* It is the shape most likely to be mistaken for a sandbox, because it looks
|
|
521
|
+
* exactly like a successful post that nobody can see: `ok: true`, a real id,
|
|
522
|
+
* no audience. `none` says "there is nothing"; this says "there is something,
|
|
523
|
+
* it is not selectable from here, and success does not mean reach".
|
|
499
524
|
* - `none` — the provider has no test estate. `sandbox` is then not offered at
|
|
500
|
-
* all, and the
|
|
501
|
-
|
|
502
|
-
|
|
525
|
+
* all, and the honest choices are `fake` and `live`.
|
|
526
|
+
* - `unverified` — **nobody has checked yet.** A real state, and the type has to
|
|
527
|
+
* carry it: this is the field where being wrong sends someone to a live
|
|
528
|
+
* estate believing it is a test one, so "researched but not verified" must not
|
|
529
|
+
* be forced to pick one of the other five. It belongs on a provider declared
|
|
530
|
+
* `implemented: false`; on one declared `implemented: true` it is a finding,
|
|
531
|
+
* and `providerProblems()` reports it.
|
|
532
|
+
*/
|
|
533
|
+
type SandboxKind = "credential" | "base-url" | "separate-account" | "restricted-reach" | "none" | "unverified";
|
|
534
|
+
/** Every value, as data, for a host validating input that crossed a JSON boundary. */
|
|
535
|
+
declare const SANDBOX_KINDS: readonly SandboxKind[];
|
|
536
|
+
declare function sandboxIsSelectable(kind: SandboxKind): boolean;
|
|
537
|
+
/**
|
|
538
|
+
* Why `mode: "sandbox"` cannot be honoured for this kind, in the words the
|
|
539
|
+
* person reading it needs.
|
|
540
|
+
*
|
|
541
|
+
* Three reasons, three messages. Collapsing them into "no sandbox available"
|
|
542
|
+
* would hide the one that matters: `restricted-reach` is not an absence, it is
|
|
543
|
+
* a different mechanism with a trap in it.
|
|
544
|
+
*/
|
|
545
|
+
declare function sandboxRefusal(service: string, kind: SandboxKind): string;
|
|
503
546
|
/** The host's view of where it is running. Kept tiny so it is trivial to fake. */
|
|
504
547
|
type HostEnvironment = {
|
|
505
548
|
/** True only in a real production deployment. Everything else is "local". */
|
|
@@ -1461,7 +1504,29 @@ type RenderedPayload = {
|
|
|
1461
1504
|
* ignores this; the point of the rule set is that most do not have to.
|
|
1462
1505
|
*/
|
|
1463
1506
|
type RenderRules = {
|
|
1464
|
-
/**
|
|
1507
|
+
/**
|
|
1508
|
+
* The provider's limit per message, or `null` where it imposes none.
|
|
1509
|
+
*
|
|
1510
|
+
* **`null` means UNCOUNTED, and it is a real answer** — distinct from "we do
|
|
1511
|
+
* not know", which is not a renderable state at all. A caller that does not
|
|
1512
|
+
* know the limit must find out before rendering, because every alternative
|
|
1513
|
+
* silently produces the wrong bytes.
|
|
1514
|
+
*
|
|
1515
|
+
* ## This must stay RESOLVABLE PER CONNECTION, and never become static
|
|
1516
|
+
*
|
|
1517
|
+
* A Mastodon instance's character limit comes from the server it is running:
|
|
1518
|
+
* one instance allows 500, another 5000, and the same connector talks to
|
|
1519
|
+
* both. Baking the limit into the connector breaks in the quietest way
|
|
1520
|
+
* available — rendering to 500 on an instance that allows 5000 wastes most of
|
|
1521
|
+
* a post, and rendering to 5000 on one that allows 500 produces a refusal the
|
|
1522
|
+
* author cannot see coming from the preview.
|
|
1523
|
+
*
|
|
1524
|
+
* So the limit is resolved by the CALLER, from the connection, and passed IN
|
|
1525
|
+
* — which is also what makes it part of what was approved rather than
|
|
1526
|
+
* something decided later behind the approver's back. `withResolvedLimit()`
|
|
1527
|
+
* is the supported way to do that, and a test pins that per-call rules beat
|
|
1528
|
+
* declared ones.
|
|
1529
|
+
*/
|
|
1465
1530
|
limit: number | null;
|
|
1466
1531
|
unit: TextUnit;
|
|
1467
1532
|
/**
|
|
@@ -1529,6 +1594,19 @@ declare function payloadHash(payload: RenderedPayload): Promise<string>;
|
|
|
1529
1594
|
* every one of those checks from being hollow.
|
|
1530
1595
|
*/
|
|
1531
1596
|
declare function isEmptyPayload(payload: RenderedPayload): boolean;
|
|
1597
|
+
/**
|
|
1598
|
+
* Apply a per-connection limit over a connector's declared rules.
|
|
1599
|
+
*
|
|
1600
|
+
* The one supported way to do the thing `RenderRules.limit` insists on: a
|
|
1601
|
+
* Mastodon instance publishes its own `max_toot_chars`, a Discord webhook does
|
|
1602
|
+
* not, and the same connector serves both. Resolving happens at the call site,
|
|
1603
|
+
* with the connection in hand, and the resolved value travels INTO `render` so
|
|
1604
|
+
* it is part of the payload the approver saw.
|
|
1605
|
+
*
|
|
1606
|
+
* `undefined` keeps whatever the connector declared — "I did not look" is not
|
|
1607
|
+
* the same as "there is no limit", and only the second is `null`.
|
|
1608
|
+
*/
|
|
1609
|
+
declare function withResolvedLimit(rules: RenderRules, limit: number | null | undefined): RenderRules;
|
|
1532
1610
|
|
|
1533
1611
|
/**
|
|
1534
1612
|
* The seam — two objects, deliberately separate.
|
|
@@ -1576,6 +1654,28 @@ declare function isEmptyPayload(payload: RenderedPayload): boolean;
|
|
|
1576
1654
|
* path — and the reference implementation very nearly stored it as
|
|
1577
1655
|
* configuration because it looked like a URL.
|
|
1578
1656
|
*/
|
|
1657
|
+
/**
|
|
1658
|
+
* Who a credential belongs to.
|
|
1659
|
+
*
|
|
1660
|
+
* Exported as a runtime constant as well as a type — see `CREDENTIAL_SCOPES`.
|
|
1661
|
+
*/
|
|
1662
|
+
type CredentialScope = "provider" | "account";
|
|
1663
|
+
/**
|
|
1664
|
+
* The scopes, as DATA.
|
|
1665
|
+
*
|
|
1666
|
+
* Because this union crosses a JSON boundary and the compiler cannot follow it
|
|
1667
|
+
* there. When these values were renamed from `app`/`brand`, a consumer that
|
|
1668
|
+
* re-declared the field shape on its client kept compiling — their
|
|
1669
|
+
* `f.scope === "brand"` silently became never-true, and every credential field
|
|
1670
|
+
* would have rendered as shared. `tsc` gives a host mirroring these types no
|
|
1671
|
+
* help at all, so the values ship as data a host can validate against at the
|
|
1672
|
+
* boundary where the compiler stops.
|
|
1673
|
+
*/
|
|
1674
|
+
declare const CREDENTIAL_SCOPES: readonly CredentialScope[];
|
|
1675
|
+
/** Severities, as data, for the same reason. */
|
|
1676
|
+
declare const PROBLEM_SEVERITIES: readonly ["block", "warn"];
|
|
1677
|
+
/** Canonical metric names, as data, for the same reason. */
|
|
1678
|
+
declare const CANONICAL_METRICS: readonly ["like", "share", "reply", "quote", "view"];
|
|
1579
1679
|
type CredentialField = {
|
|
1580
1680
|
/** Stable key. The host maps it to wherever it keeps values. */
|
|
1581
1681
|
key: string;
|
|
@@ -1589,7 +1689,7 @@ type CredentialField = {
|
|
|
1589
1689
|
* The distinction exists because getting it wrong means either asking for the
|
|
1590
1690
|
* same app secret five times or letting one account's token reach another's.
|
|
1591
1691
|
*/
|
|
1592
|
-
scope:
|
|
1692
|
+
scope: CredentialScope;
|
|
1593
1693
|
secret: boolean;
|
|
1594
1694
|
required: boolean;
|
|
1595
1695
|
/** A hint for an empty field. NEVER a real value. */
|
|
@@ -1642,8 +1742,26 @@ type ProviderAdapter = {
|
|
|
1642
1742
|
* that anything can be revoked. "No known expiry" is not "cannot stop working".
|
|
1643
1743
|
*/
|
|
1644
1744
|
credentialLifetimeDays?: number;
|
|
1645
|
-
/**
|
|
1745
|
+
/**
|
|
1746
|
+
* How the provider exposes a test estate.
|
|
1747
|
+
*
|
|
1748
|
+
* **`"unverified"` is a real answer and is the right one until somebody has
|
|
1749
|
+
* actually checked.** Being wrong here points a workflow at a live estate
|
|
1750
|
+
* while a person believes it is a test one, so the type carries "nobody
|
|
1751
|
+
* looked" rather than forcing a guess — a comment saying so is not a type, and
|
|
1752
|
+
* `providerProblems()` reports the combination `implemented: true` +
|
|
1753
|
+
* `unverified`.
|
|
1754
|
+
*/
|
|
1646
1755
|
sandbox: SandboxKind;
|
|
1756
|
+
/**
|
|
1757
|
+
* What `verify` proves, and what it does NOT.
|
|
1758
|
+
*
|
|
1759
|
+
* Required whenever `verify` exists, and checked by `providerProblems()`.
|
|
1760
|
+
* Telegram's `getMe` validates the token and says nothing about whether the
|
|
1761
|
+
* bot was added to the target chat — which is the step everyone actually gets
|
|
1762
|
+
* stuck on. A green tick that means more than it should is worse than no tick.
|
|
1763
|
+
*/
|
|
1764
|
+
proves?: string;
|
|
1647
1765
|
/**
|
|
1648
1766
|
* A read-only call proving the credential works AND reaches the right account.
|
|
1649
1767
|
*
|
|
@@ -1860,6 +1978,22 @@ declare function capabilityProblems(connector: Connector<never>): string[];
|
|
|
1860
1978
|
* `undefined` and non-numbers do not.
|
|
1861
1979
|
*/
|
|
1862
1980
|
declare function reported(values: Record<string, unknown>): Record<string, number>;
|
|
1981
|
+
/**
|
|
1982
|
+
* Every way a PROVIDER's declaration can outrun what anyone actually checked.
|
|
1983
|
+
*
|
|
1984
|
+
* The sibling of `capabilityProblems`, one level up. `capabilities.metrics: true`
|
|
1985
|
+
* with no shape turns an unimplemented feature into a reported zero; the
|
|
1986
|
+
* equivalent here turns *nobody looked* into a statement about a test estate —
|
|
1987
|
+
* and that field is the one where being wrong sends a person to a live estate
|
|
1988
|
+
* believing it is a test one.
|
|
1989
|
+
*
|
|
1990
|
+
* Strings rather than a throw, so a host reports all of them at once. A check
|
|
1991
|
+
* that stops at the first problem trains people to fix one thing and re-run,
|
|
1992
|
+
* which is how a list of six becomes six rounds.
|
|
1993
|
+
*/
|
|
1994
|
+
declare function providerProblems(provider: ProviderAdapter): string[];
|
|
1995
|
+
/** True when a provider's declared sandbox can actually be selected at run time. */
|
|
1996
|
+
declare function providerSandboxIsSelectable(provider: ProviderAdapter): boolean;
|
|
1863
1997
|
|
|
1864
1998
|
/**
|
|
1865
1999
|
* Dry-verify — proving the transport with a credential that cannot work.
|
|
@@ -2126,4 +2260,4 @@ declare function verifyDelivery(trigger: TriggerDescriptor, delivery: InboundDel
|
|
|
2126
2260
|
*/
|
|
2127
2261
|
declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
|
|
2128
2262
|
|
|
2129
|
-
export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type ByteRange, CONNECTOR_API_VERSION, CONNECTOR_MODES, 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, 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, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, 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, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SpecSource, 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, linkRanges, measure, payloadHash, postChain, probe, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac };
|
|
2263
|
+
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, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, 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 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, linkRanges, measure, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, withResolvedLimit };
|
package/dist/index.js
CHANGED
|
@@ -67,6 +67,8 @@ var AMBIGUOUS_CODES = /* @__PURE__ */ new Set([
|
|
|
67
67
|
]);
|
|
68
68
|
var AMBIGUOUS_NAMES = /* @__PURE__ */ new Set(["AbortError", "TimeoutError"]);
|
|
69
69
|
function classifyError(error) {
|
|
70
|
+
const attached = error?.classified;
|
|
71
|
+
if (attached && typeof attached === "object" && typeof attached.kind === "string") return attached;
|
|
70
72
|
const detail = error instanceof Error ? error.message : String(error);
|
|
71
73
|
const code = error?.code ?? error?.cause?.code ?? "";
|
|
72
74
|
const name = error instanceof Error ? error.name : "";
|
|
@@ -304,19 +306,42 @@ function fakeRequest(service, operation, config, input) {
|
|
|
304
306
|
|
|
305
307
|
// src/mode.ts
|
|
306
308
|
var CONNECTOR_MODES = ["fake", "sandbox", "live"];
|
|
309
|
+
var SANDBOX_KINDS = [
|
|
310
|
+
"credential",
|
|
311
|
+
"base-url",
|
|
312
|
+
"separate-account",
|
|
313
|
+
"restricted-reach",
|
|
314
|
+
"none",
|
|
315
|
+
"unverified"
|
|
316
|
+
];
|
|
317
|
+
var SELECTABLE_SANDBOX = /* @__PURE__ */ new Set([
|
|
318
|
+
"credential",
|
|
319
|
+
"base-url",
|
|
320
|
+
"separate-account"
|
|
321
|
+
]);
|
|
322
|
+
function sandboxIsSelectable(kind) {
|
|
323
|
+
return SELECTABLE_SANDBOX.has(kind);
|
|
324
|
+
}
|
|
325
|
+
function sandboxRefusal(service, kind) {
|
|
326
|
+
if (kind === "restricted-reach") {
|
|
327
|
+
return service + ` has no separate test estate. What it has instead is an ACCOUNT-LEVEL reach restriction - an unreviewed app that posts only to its own developers, or only privately. Same credentials, same endpoints, same estate: only the audience changes, and nothing in a request selects it. That makes it the sandbox shape most likely to be mistaken for a real one, because a restricted call looks exactly like a successful one - ok, a real id, and no audience. Use "fake" to develop without touching the provider, or "live" and confirm reach on the provider's own surface, which is the only place it is visible.`;
|
|
328
|
+
}
|
|
329
|
+
if (kind === "unverified") {
|
|
330
|
+
return "Nobody has verified what test estate " + service + ' offers, so "sandbox" cannot be honoured - the resolver would be guessing, and the cost of guessing wrong here is a workflow pointed at a live estate while somebody believes it is a test one. Find out and declare it, or use "fake".';
|
|
331
|
+
}
|
|
332
|
+
return service + ' has no sandbox estate, so "sandbox" cannot be honoured. Use "fake" to develop without credentials, or "live" to talk to the provider.';
|
|
333
|
+
}
|
|
307
334
|
function resolveConnectorMode(inputs) {
|
|
308
335
|
const { requested, connectionMode, sandbox, hasSandboxCredentials, environment } = inputs;
|
|
309
336
|
if (requested && requested !== "auto") {
|
|
310
|
-
if (requested === "sandbox" && sandbox
|
|
311
|
-
throw new ConnectorModeError(
|
|
312
|
-
`This connector's provider has no sandbox estate, so "sandbox" cannot be honoured. Use "fake" to develop without credentials, or "live" to talk to the provider.`
|
|
313
|
-
);
|
|
337
|
+
if (requested === "sandbox" && !sandboxIsSelectable(sandbox)) {
|
|
338
|
+
throw new ConnectorModeError(sandboxRefusal("This connector's provider", sandbox));
|
|
314
339
|
}
|
|
315
340
|
return requested;
|
|
316
341
|
}
|
|
317
342
|
if (connectionMode) return connectionMode;
|
|
318
343
|
if (environment.production) return "live";
|
|
319
|
-
return sandbox
|
|
344
|
+
return sandboxIsSelectable(sandbox) && hasSandboxCredentials ? "sandbox" : "fake";
|
|
320
345
|
}
|
|
321
346
|
var ConnectorModeError = class extends Error {
|
|
322
347
|
constructor(message) {
|
|
@@ -347,10 +372,8 @@ function connectionsFor(service) {
|
|
|
347
372
|
function resolveConnection(options) {
|
|
348
373
|
const { service, operation, sandbox } = options;
|
|
349
374
|
const requestedMode = options.requested ?? "auto";
|
|
350
|
-
if (requestedMode === "sandbox" && sandbox
|
|
351
|
-
throw new ConnectorModeError(
|
|
352
|
-
`${service} has no sandbox estate, so "sandbox" cannot be honoured. Use "fake" to develop without credentials, or "live" to talk to the provider.`
|
|
353
|
-
);
|
|
375
|
+
if (requestedMode === "sandbox" && !sandboxIsSelectable(sandbox)) {
|
|
376
|
+
throw new ConnectorModeError(sandboxRefusal(service, sandbox));
|
|
354
377
|
}
|
|
355
378
|
const id = options.connectionId?.trim() || service;
|
|
356
379
|
if (options.credentials) {
|
|
@@ -877,6 +900,41 @@ function reported(values) {
|
|
|
877
900
|
}
|
|
878
901
|
return out;
|
|
879
902
|
}
|
|
903
|
+
function providerProblems(provider) {
|
|
904
|
+
const problems = [];
|
|
905
|
+
if (provider.implemented && provider.sandbox === "unverified") {
|
|
906
|
+
problems.push(
|
|
907
|
+
`${provider.id} says it is implemented while its sandbox shape is still "unverified". Something a person can run today must not be ambiguous about which estate it reaches \u2014 verify it, or set implemented: false.`
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
if (provider.implemented && provider.fields.length === 0) {
|
|
911
|
+
problems.push(`${provider.id} says it is implemented but declares no credential fields.`);
|
|
912
|
+
}
|
|
913
|
+
if (provider.implemented && provider.setup.length === 0) {
|
|
914
|
+
problems.push(
|
|
915
|
+
`${provider.id} says it is implemented and names no setup steps. The code is never the expensive part; the setup is, and a provider whose setup is undocumented is one nobody can stand up.`
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
for (const field of provider.fields) {
|
|
919
|
+
if (field.help.trim().length < 10) {
|
|
920
|
+
problems.push(`${provider.id}.${field.key} has no help text worth reading.`);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
if (provider.verify && !provider.proves) {
|
|
924
|
+
problems.push(
|
|
925
|
+
`${provider.id} ships a verify but does not say what it PROVES. A green tick that means more than it should is worse than no tick \u2014 name the step it does not cover.`
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
if (provider.sandbox === "restricted-reach" && !provider.summary.toLowerCase().includes("reach")) {
|
|
929
|
+
problems.push(
|
|
930
|
+
`${provider.id} is declared restricted-reach and its summary never mentions reach. That shape looks exactly like a successful post nobody can see, so the surface has to say so before anyone runs it.`
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
return problems;
|
|
934
|
+
}
|
|
935
|
+
function providerSandboxIsSelectable(provider) {
|
|
936
|
+
return sandboxIsSelectable(provider.sandbox);
|
|
937
|
+
}
|
|
880
938
|
|
|
881
939
|
// src/probe.ts
|
|
882
940
|
async function probe(spec) {
|
|
@@ -1078,6 +1136,14 @@ async function payloadHash(payload) {
|
|
|
1078
1136
|
function isEmptyPayload(payload) {
|
|
1079
1137
|
return payload.segments.every((segment) => segment.text.trim() === "");
|
|
1080
1138
|
}
|
|
1139
|
+
function withResolvedLimit(rules, limit) {
|
|
1140
|
+
return limit === void 0 ? rules : { ...rules, limit };
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
// src/seam.ts
|
|
1144
|
+
var CREDENTIAL_SCOPES = ["provider", "account"];
|
|
1145
|
+
var PROBLEM_SEVERITIES = ["block", "warn"];
|
|
1146
|
+
var CANONICAL_METRICS = ["like", "share", "reply", "quote", "view"];
|
|
1081
1147
|
|
|
1082
1148
|
// src/webhook.ts
|
|
1083
1149
|
async function verifyHmac(options) {
|
|
@@ -1179,8 +1245,10 @@ function hasDelivery(value) {
|
|
|
1179
1245
|
}
|
|
1180
1246
|
export {
|
|
1181
1247
|
AMBIGUOUS_REFUSAL,
|
|
1248
|
+
CANONICAL_METRICS,
|
|
1182
1249
|
CONNECTOR_API_VERSION,
|
|
1183
1250
|
CONNECTOR_MODES,
|
|
1251
|
+
CREDENTIAL_SCOPES,
|
|
1184
1252
|
ConnectorAmbiguous,
|
|
1185
1253
|
ConnectorApiMismatch,
|
|
1186
1254
|
ConnectorAuthError,
|
|
@@ -1197,8 +1265,10 @@ export {
|
|
|
1197
1265
|
FAKE_EPOCH,
|
|
1198
1266
|
MAX_IDEMPOTENCY_KEY_LENGTH,
|
|
1199
1267
|
NO_IDEMPOTENCY_KEY_WARNING,
|
|
1268
|
+
PROBLEM_SEVERITIES,
|
|
1200
1269
|
RENDERER_VERSION,
|
|
1201
1270
|
REVIEW_STALE_DAYS,
|
|
1271
|
+
SANDBOX_KINDS,
|
|
1202
1272
|
SUPPORTED_CONNECTOR_API,
|
|
1203
1273
|
assertConnectorApi,
|
|
1204
1274
|
byteRangeOf,
|
|
@@ -1230,6 +1300,8 @@ export {
|
|
|
1230
1300
|
payloadHash,
|
|
1231
1301
|
postChain,
|
|
1232
1302
|
probe,
|
|
1303
|
+
providerProblems,
|
|
1304
|
+
providerSandboxIsSelectable,
|
|
1233
1305
|
registerConnectionHost,
|
|
1234
1306
|
registerTransport,
|
|
1235
1307
|
render,
|
|
@@ -1241,6 +1313,8 @@ export {
|
|
|
1241
1313
|
runIdentityFrom,
|
|
1242
1314
|
runKeyFrom,
|
|
1243
1315
|
runProbes,
|
|
1316
|
+
sandboxIsSelectable,
|
|
1317
|
+
sandboxRefusal,
|
|
1244
1318
|
satisfiesMinimum,
|
|
1245
1319
|
seedFrom,
|
|
1246
1320
|
shapeOf,
|
|
@@ -1251,6 +1325,7 @@ export {
|
|
|
1251
1325
|
unchecked,
|
|
1252
1326
|
utf8Length,
|
|
1253
1327
|
verifyDelivery,
|
|
1254
|
-
verifyHmac
|
|
1328
|
+
verifyHmac,
|
|
1329
|
+
withResolvedLimit
|
|
1255
1330
|
};
|
|
1256
1331
|
//# sourceMappingURL=index.js.map
|