@zackbart/connecta 0.28.0 → 0.28.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 +173 -0
- package/README.md +8 -5
- package/dist/artifacts/connector.js +1 -1
- package/dist/auth/downstream-oauth.js +147 -28
- package/dist/auth/static-oauth.js +504 -0
- package/dist/connectors/api-connector.d.ts +168 -0
- package/dist/connectors/api-connector.js +127 -0
- package/dist/connectors/api.d.ts +8 -71
- package/dist/connectors/api.js +10 -99
- package/dist/connectors/guarded-fetch.js +37 -3
- package/dist/connectors/remote-mcp.js +7 -32
- package/dist/index.d.ts +1 -1
- package/dist/oauth-partition.js +17 -0
- package/dist/providers/basecamp.d.ts +65 -0
- package/dist/providers/basecamp.js +445 -0
- package/dist/providers/breeze.d.ts +34 -0
- package/dist/providers/breeze.js +1402 -0
- package/dist/providers/ccb.d.ts +103 -0
- package/dist/providers/ccb.js +1570 -0
- package/dist/providers/cloudflare.js +1 -1
- package/dist/providers/linear.js +1 -1
- package/dist/providers/mixpanel.js +1 -1
- package/dist/providers/notion.js +1 -1
- package/dist/providers/overflow.d.ts +60 -0
- package/dist/providers/overflow.js +1572 -0
- package/dist/providers/planning-center.d.ts +59 -0
- package/dist/providers/planning-center.js +2039 -0
- package/dist/providers/revenuecat.js +1 -1
- package/dist/providers/stripe.js +1 -1
- package/dist/providers/tithely.d.ts +49 -0
- package/dist/providers/tithely.js +1034 -0
- package/dist/providers/vercel.js +1 -1
- package/dist/routes/oauth.js +29 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/documentation/architecture.md +5 -3
- package/documentation/auth.md +120 -6
- package/ethos.md +3 -3
- package/package.json +25 -1
- package/templates/node/package.json +1 -1
package/dist/providers/vercel.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* those rows with Vercel's published OpenAPI document at
|
|
10
10
|
* https://openapi.vercel.sh/ without needing a credential.
|
|
11
11
|
*/
|
|
12
|
-
import { api, defined } from "../connectors/api.js";
|
|
12
|
+
import { apiConnector as api, defined } from "../connectors/api-connector.js";
|
|
13
13
|
import { remoteMcp } from "../connectors/remote-mcp.js";
|
|
14
14
|
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
15
15
|
import { guardedFetch, retryAfterMs, } from "../connectors/guarded-fetch.js";
|
package/dist/routes/oauth.js
CHANGED
|
@@ -102,6 +102,30 @@ export function routeOAuthCallback(context) {
|
|
|
102
102
|
return Effect.succeed(null);
|
|
103
103
|
return Effect.uninterruptible(Effect.promise(() => finishOAuthCallback(context)));
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* RFC 6749's error codes (sections 4.1.2.1 and 5.2) and RFC 8707's
|
|
107
|
+
* `invalid_target`. Only a code on this list is logged: the `code` an OAuth
|
|
108
|
+
* error carries is the provider's own text.
|
|
109
|
+
*/
|
|
110
|
+
const TOKEN_ERROR_CODES = new Set([
|
|
111
|
+
"invalid_request",
|
|
112
|
+
"invalid_client",
|
|
113
|
+
"invalid_grant",
|
|
114
|
+
"unauthorized_client",
|
|
115
|
+
"unsupported_grant_type",
|
|
116
|
+
"invalid_scope",
|
|
117
|
+
"invalid_target",
|
|
118
|
+
"access_denied",
|
|
119
|
+
"server_error",
|
|
120
|
+
"temporarily_unavailable",
|
|
121
|
+
]);
|
|
122
|
+
/** ` with OAuth error <code>` for a known code; nothing for anything else. */
|
|
123
|
+
function exchangeErrorCode(err) {
|
|
124
|
+
const code = err?.code;
|
|
125
|
+
return typeof code === "string" && TOKEN_ERROR_CODES.has(code)
|
|
126
|
+
? ` with OAuth error ${code}`
|
|
127
|
+
: "";
|
|
128
|
+
}
|
|
105
129
|
async function finishOAuthCallback(context) {
|
|
106
130
|
const { path, url, baseUrl, opts } = context;
|
|
107
131
|
const error = url.searchParams.get("error");
|
|
@@ -198,10 +222,12 @@ async function finishOAuthCallback(context) {
|
|
|
198
222
|
return html("connected", opts, connector);
|
|
199
223
|
}
|
|
200
224
|
catch (err) {
|
|
201
|
-
//
|
|
202
|
-
//
|
|
225
|
+
// Neither the page nor the log repeats what the exchange threw: the SDK
|
|
226
|
+
// quotes the token endpoint's error_description or raw body, and a
|
|
227
|
+
// provider echoing a client_secret_post request puts the secret there.
|
|
203
228
|
opts.logger.warn(`[connecta] OAuth callback for connector ${loggableValue(id)} failed ` +
|
|
204
|
-
`with 500: the authorization code exchange
|
|
229
|
+
`with 500: the authorization code exchange failed${exchangeErrorCode(err)}. ` +
|
|
230
|
+
"Check the connector's client configuration and re-run authorization.");
|
|
205
231
|
return html("exchange_failed", opts, connector);
|
|
206
232
|
}
|
|
207
233
|
}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -21,8 +21,10 @@ health, and the per-connector call limiters. It is built once and lives as long
|
|
|
21
21
|
as the isolate — on Workers a lazy module-scope singleton, which is why both
|
|
22
22
|
deployment shapes construct it outside the request handler.
|
|
23
23
|
|
|
24
|
-
An OAuth `remoteMcp()
|
|
25
|
-
|
|
24
|
+
An OAuth connector — `remoteMcp()`, or `api()` with a static grant
|
|
25
|
+
(`src/auth/static-oauth.ts`, the same provider with its discovery and client
|
|
26
|
+
answered from config) — also owns a runtime-local refresh completion gate
|
|
27
|
+
(`src/auth/downstream-oauth.ts`). It coordinates credential mutation across
|
|
26
28
|
concurrent request scopes while sharing no client, transport, or response, and
|
|
27
29
|
never lets a follower cancel the owner. The subtle part is that a valid token
|
|
28
30
|
response consumes the refresh token whether or not the owner survives to save it,
|
|
@@ -627,7 +629,7 @@ src/
|
|
|
627
629
|
skills.ts MCP instructions, the usage skill, connector guides
|
|
628
630
|
catalog-drift.ts vetted manifests and the counts a refresh produces
|
|
629
631
|
activity.ts optional history factory and best-effort recorder
|
|
630
|
-
auth/ bearer, Cloudflare Access, clerk (optional peer), downstream OAuth
|
|
632
|
+
auth/ bearer, Cloudflare Access, clerk (optional peer), downstream OAuth (remote and static)
|
|
631
633
|
executors/ the QuickJS pool and child (Node only)
|
|
632
634
|
node.ts listen() + fileStorage re-export (Node only)
|
|
633
635
|
```
|
package/documentation/auth.md
CHANGED
|
@@ -305,7 +305,9 @@ or epoch does not open. Anything that fails to open — a tampered value, a
|
|
|
305
305
|
rotated key — reads as absent: the connector reports `auth_required` and logs a
|
|
306
306
|
warning. The flow bookkeeping stays plaintext: `state`, the pending URL,
|
|
307
307
|
discovery metadata, and the generation. The callback route reads `state`
|
|
308
|
-
directly, and none of it authenticates anything by itself.
|
|
308
|
+
directly, and none of it authenticates anything by itself. An
|
|
309
|
+
[`api()` OAuth connector](#downstream-oauth-on-api) seals its tokens and
|
|
310
|
+
verifier the same way and stores no client at all.
|
|
309
311
|
|
|
310
312
|
Plaintext left by an older release is read, then sealed where it lies through
|
|
311
313
|
the same generation fence as any write, so an upgrade keeps the grant. Sealing
|
|
@@ -326,8 +328,8 @@ The operator's `POST /ui/oauth/<id>` takes a `mode` query parameter:
|
|
|
326
328
|
|
|
327
329
|
| Request | What it does |
|
|
328
330
|
| --- | --- |
|
|
329
|
-
| `POST /ui/oauth/<id>` or `?mode=restart` | `startAuth(ctx, { force: true })`: a new epoch, with tokens,
|
|
330
|
-
| `?mode=continue` | `startAuth(ctx, { force: false })`: hand back the pending authorization URL if it was written in the last ten minutes; otherwise start a flow in the current epoch, reusing the stored client registration. A disconnected connector still gets its new epoch first. |
|
|
331
|
+
| `POST /ui/oauth/<id>` or `?mode=restart` | `startAuth(ctx, { force: true })`: a new epoch, with tokens, discovery, and any pending flow wiped. A dynamically registered client may be carried into it ([below](#human-authentication-management)); one that is not carried is registered again. |
|
|
332
|
+
| `?mode=continue` | `startAuth(ctx, { force: false })`: hand back the pending authorization URL if it was written in the last ten minutes and still names the stored client; otherwise start a flow in the current epoch, reusing the stored client registration. A disconnected connector still gets its new epoch first. |
|
|
331
333
|
| `DELETE /ui/oauth/<id>` | Disconnect: a disconnected epoch that passive reads never turn back into a consent flow. |
|
|
332
334
|
|
|
333
335
|
Any other `mode`, or more than one, is a 400 before anything starts; the
|
|
@@ -592,9 +594,22 @@ the connector's URL, redirect URI, client metadata, auth scope, transport settin
|
|
|
592
594
|
and owner partition still match. It drops the grant and one-shot flow state,
|
|
593
595
|
selects the authorization server again, and re-seals the retained client under
|
|
594
596
|
the replacement epoch key. A different issuer registers a new client. Disconnect
|
|
595
|
-
and issuer-mismatch recovery discard it.
|
|
596
|
-
|
|
597
|
-
|
|
597
|
+
and issuer-mismatch recovery discard it. A URL-based client is never carried:
|
|
598
|
+
nothing was registered, and leaving it behind lets fresh metadata decide
|
|
599
|
+
whether the server still accepts one. Neither is a client whose secret has
|
|
600
|
+
expired.
|
|
601
|
+
|
|
602
|
+
A carried client has to earn its next carry. Building a consent URL sends the
|
|
603
|
+
provider nothing, so a restart cannot learn there that a provider has purged
|
|
604
|
+
the client, and RFC 6749 forbids the provider from redirecting an unknown
|
|
605
|
+
client back to the callback, so nothing arrives later either. Tokens in the
|
|
606
|
+
epoch are the only proof the provider still knows it. A restart that follows
|
|
607
|
+
a restart with no grant in between therefore registers again: a purged
|
|
608
|
+
registration costs one refused consent, not a Restart that can never recover.
|
|
609
|
+
A refusal connecta does hear is handled where it lands. A start whose refresh
|
|
610
|
+
draws `invalid_client` drops the client and registers in that same start; a
|
|
611
|
+
callback whose code exchange draws it drops the client, and Continue will not
|
|
612
|
+
hand back the URL that named it.
|
|
598
613
|
|
|
599
614
|
Credential and OAuth mutation require an admitted interactive human, connector
|
|
600
615
|
visibility, the appropriate shared or personal permission, and an exact
|
|
@@ -636,8 +651,107 @@ existing dynamic registration flow. State validation, PKCE, issuer binding,
|
|
|
636
651
|
encrypted token storage, refresh, and disconnect follow the same code paths.
|
|
637
652
|
The metadata URL and scopes participate in the saved-client configuration
|
|
638
653
|
binding, so restarting after either changes cannot reuse an old registration.
|
|
654
|
+
A restart never carries the URL-based client itself, so a server that stops
|
|
655
|
+
advertising support gets a registered client on the next restart.
|
|
639
656
|
|
|
640
657
|
`scope` supplies space-separated default OAuth scopes through client metadata.
|
|
641
658
|
A downstream challenge or protected-resource scope declaration takes precedence,
|
|
642
659
|
and the SDK adds `offline_access` when advertised for refresh-token grants.
|
|
643
660
|
Omitting both settings preserves the existing discovery and registration flow.
|
|
661
|
+
|
|
662
|
+
## Downstream OAuth on `api()`
|
|
663
|
+
|
|
664
|
+
Some APIs a deployment needs have no MCP server and take nothing but OAuth.
|
|
665
|
+
Church Community Builder's REST API accepts only a three-legged grant, issues
|
|
666
|
+
its clients by hand, and publishes no metadata to discover. `api()` takes a
|
|
667
|
+
static authorization-code configuration for that shape:
|
|
668
|
+
|
|
669
|
+
```ts
|
|
670
|
+
api("church", {
|
|
671
|
+
authScope: "personal",
|
|
672
|
+
oauth: {
|
|
673
|
+
authorizationEndpoint: "https://login.example.com/oauth/authorize",
|
|
674
|
+
tokenEndpoint: "https://api.example.com/oauth/token",
|
|
675
|
+
clientId: env.CHURCH_CLIENT_ID,
|
|
676
|
+
clientSecret: env.CHURCH_CLIENT_SECRET,
|
|
677
|
+
scope: "people:read",
|
|
678
|
+
apiOrigins: ["https://api.example.com"],
|
|
679
|
+
},
|
|
680
|
+
tools: [{
|
|
681
|
+
name: "get_person",
|
|
682
|
+
description: "Read one person",
|
|
683
|
+
annotations: { readOnlyHint: true },
|
|
684
|
+
inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
|
|
685
|
+
handler: async ({ id }, ctx) => {
|
|
686
|
+
const response = await ctx.oauth!.fetch(
|
|
687
|
+
`https://api.example.com/people/${encodeURIComponent(id)}`,
|
|
688
|
+
);
|
|
689
|
+
return response.json();
|
|
690
|
+
},
|
|
691
|
+
}],
|
|
692
|
+
});
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
Nothing is discovered, registered, or learned. Every URL is configuration, so
|
|
696
|
+
the rule for [URLs a downstream advertises](#urls-a-downstream-advertises)
|
|
697
|
+
has nothing to check, and the endpoints are checked once, at construction:
|
|
698
|
+
HTTPS (HTTP only on loopback), no credentials, no fragment. PKCE with S256 is
|
|
699
|
+
on unless `pkce: false`, which drops the challenge from the consent URL and
|
|
700
|
+
the verifier from the exchange, for a server that refuses them.
|
|
701
|
+
`authorizationParams` adds provider parameters but cannot restate the grant's
|
|
702
|
+
own, and `tokenRequestHeaders` adds headers to the code exchange and every
|
|
703
|
+
refresh — CCB's token endpoint wants its own `Accept` media type — but cannot
|
|
704
|
+
set `Authorization`, `Content-Type`, `Content-Length`, `Cookie`, or `Host`. `tokenEndpointAuthMethod` defaults to `client_secret_basic` with a secret
|
|
705
|
+
and `none` without; the mismatched pairings refuse to boot. A static server has
|
|
706
|
+
no advertised issuer, so no RFC 9207 `iss` is demanded and no RFC 8707
|
|
707
|
+
`resource` is sent. The grant is bound to the token endpoint instead:
|
|
708
|
+
repointing it fences the old tokens behind a new epoch rather than sending
|
|
709
|
+
them to the new server.
|
|
710
|
+
|
|
711
|
+
**The client lives in deployment configuration, not a vault slot.** It is the
|
|
712
|
+
deployment's identity at the provider — one per deployment, like Clerk's
|
|
713
|
+
`secretKey` — while a vault slot belongs to an owner: on a personal connector
|
|
714
|
+
every human would paste the deployment's secret into their own partition.
|
|
715
|
+
Configuration also keeps it out of storage altogether. It is never written,
|
|
716
|
+
sealed or otherwise, so a leaked store holds no client secret, Disconnect has
|
|
717
|
+
nothing of it to delete, and Restart has no registration to carry forward.
|
|
718
|
+
Read it from the environment or a Worker secret; an empty string, the usual
|
|
719
|
+
unset variable, refuses to boot without quoting it.
|
|
720
|
+
|
|
721
|
+
Handlers never see the grant. `ctx.oauth.fetch(url, init)` sends the calling
|
|
722
|
+
owner's access token as `Authorization: Bearer` and does four things a
|
|
723
|
+
hand-rolled header would not:
|
|
724
|
+
|
|
725
|
+
- **It sends the token to `apiOrigins` and nowhere else.** A request to any
|
|
726
|
+
other origin is refused before it leaves, so an untrusted URL in a response
|
|
727
|
+
— a pagination link, a webhook target — cannot carry the token off.
|
|
728
|
+
Redirects come back unfollowed, and a handler cannot set `Authorization`
|
|
729
|
+
itself.
|
|
730
|
+
- **A 401 earns exactly one recovery.** If another request has already
|
|
731
|
+
rotated a token in, that token is used; otherwise one refresh runs through
|
|
732
|
+
the same coordinator as `remoteMcp()`, coalesced across requests, with the
|
|
733
|
+
rotating refresh token persisted even if its owner is cancelled after the
|
|
734
|
+
answer arrives. The request is then replayed once, which is why a stream
|
|
735
|
+
body is refused.
|
|
736
|
+
- **Failures land in the existing classes.** No grant, a second 401, or a
|
|
737
|
+
[dead refresh](#refresh-failures), whose refused tokens are deleted on the
|
|
738
|
+
spot, is `auth_required` and routes the agent to `authorize_connector`. An
|
|
739
|
+
authorization-server outage is a retryable `unavailable` that keeps the
|
|
740
|
+
grant. A second 401 is latched for the rest of the request scope, so a
|
|
741
|
+
program's next fifty calls do not spend fifty refreshes on it.
|
|
742
|
+
- **It reads and writes nothing a handler can name.** Storage, sealing, and the
|
|
743
|
+
owner partition are the registry's, exactly as for `remoteMcp()`.
|
|
744
|
+
|
|
745
|
+
Everything else is the `remoteMcp()` grant, unchanged: the epoch fence and its
|
|
746
|
+
cleanup lineage, sealing under the vault key, shared and personal ownership,
|
|
747
|
+
the callback route and its state and principal checks, `authorize_connector`,
|
|
748
|
+
and the operator's Connect, Restart, and Disconnect. Status reports a stored
|
|
749
|
+
grant as healthy without asking the downstream — failing at use is enough —
|
|
750
|
+
and never starts authorization. One difference is deliberate: the first start
|
|
751
|
+
publishes a modern epoch at once. The legacy generation exists so a grant from
|
|
752
|
+
before epochs survives an upgrade, and an `api()` grant has no such past.
|
|
753
|
+
|
|
754
|
+
`oauth` and `credential` are exclusive on one connector, so `auth_required`
|
|
755
|
+
names one recovery. A provider that offers both a personal access token and
|
|
756
|
+
OAuth, as Planning Center does, lets the deployment choose which to pass;
|
|
757
|
+
handlers branch on whether `ctx.oauth` is present.
|
package/ethos.md
CHANGED
|
@@ -33,12 +33,13 @@ carries them.
|
|
|
33
33
|
| --- | --- | --- |
|
|
34
34
|
| OpenAPI / GraphQL ingestion | refused | the disease is a document-authored tool nobody chose; hand-written literals, even through a shared factory, are still authorship |
|
|
35
35
|
| Multi-tenancy / account model | refused | one deployment per tenant; inbound auth owns identity |
|
|
36
|
-
| Approvals and pauses | removed | hosts approve per call, so under always-allow the resume prompt was a rubber stamp that cost a round trip and a replay
|
|
36
|
+
| Approvals and pauses | removed | hosts approve per call, so under always-allow the resume prompt was a rubber stamp that cost a round trip and a replay ([#672](https://github.com/zackbart/connecta/issues/672), superseding [#565](https://github.com/zackbart/connecta/issues/565)) |
|
|
37
37
|
| Approval exemptions | accepted | config-only, program-only, never read-only elsewhere ([#566](https://github.com/zackbart/connecta/issues/566)) |
|
|
38
38
|
| Runtime connector registration | refused | config-as-code is the security model |
|
|
39
39
|
| Optional deployment modules | accepted | typed slots select UI, activity, vault, and inbound auth; core keeps discovery, execution, invocation, and enforcement |
|
|
40
40
|
| Artifacts module | accepted | a built-in connector for team-only sandboxed pages over stored JSON; immutable versions let writes skip approval. Supersedes [#287](https://github.com/zackbart/connecta/issues/287) |
|
|
41
41
|
| Plugin lifecycle, provider registry, or marketplace | refused | modules are deployment code, not runtime installs; prebuilt connections are imports, discovered in docs ([#297](https://github.com/zackbart/connecta/issues/297)) |
|
|
42
|
+
| OAuth on `api()` | accepted | OAuth-only APIs; static grants reuse `remoteMcp()` machinery, core's callback route |
|
|
42
43
|
| Connecta-issued access tokens | accepted | optional /auth/access-tokens preserves v0.23 secrets; config owns grants, interactive management needs explicit permission ([#619](https://github.com/zackbart/connecta/issues/619)) |
|
|
43
44
|
| Expanded Notion page create/update options | refused | different workflows, not missing fields; use `api()` ([#408](https://github.com/zackbart/connecta/issues/408)) |
|
|
44
45
|
| Resources, prompts, and downstream MCP Apps templates | refused | tools only; clients own presentation ([#266](https://github.com/zackbart/connecta/issues/266)) |
|
|
@@ -72,8 +73,7 @@ carries them.
|
|
|
72
73
|
|
|
73
74
|
## Invariants
|
|
74
75
|
|
|
75
|
-
Tests beside subsystem documentation enforce these
|
|
76
|
-
design decision.
|
|
76
|
+
Tests beside subsystem documentation enforce these.
|
|
77
77
|
|
|
78
78
|
- **Fail-closed read-only.** A missing, false, or contradictory annotation never gets the benefit of the doubt.
|
|
79
79
|
- **Generated code cannot mint capabilities.** Admission, credentials, and classification are enforced below the sandbox.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zackbart/connecta",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind a code-first surface of seven meta-tools.",
|
|
@@ -67,6 +67,14 @@
|
|
|
67
67
|
"types": "./dist/auth/cloudflare-access.d.ts",
|
|
68
68
|
"import": "./dist/auth/cloudflare-access.js"
|
|
69
69
|
},
|
|
70
|
+
"./providers/breeze": {
|
|
71
|
+
"types": "./dist/providers/breeze.d.ts",
|
|
72
|
+
"import": "./dist/providers/breeze.js"
|
|
73
|
+
},
|
|
74
|
+
"./providers/basecamp": {
|
|
75
|
+
"types": "./dist/providers/basecamp.d.ts",
|
|
76
|
+
"import": "./dist/providers/basecamp.js"
|
|
77
|
+
},
|
|
70
78
|
"./providers/cloudflare": {
|
|
71
79
|
"types": "./dist/providers/cloudflare.d.ts",
|
|
72
80
|
"import": "./dist/providers/cloudflare.js"
|
|
@@ -95,6 +103,22 @@
|
|
|
95
103
|
"types": "./dist/providers/vercel.d.ts",
|
|
96
104
|
"import": "./dist/providers/vercel.js"
|
|
97
105
|
},
|
|
106
|
+
"./providers/ccb": {
|
|
107
|
+
"types": "./dist/providers/ccb.d.ts",
|
|
108
|
+
"import": "./dist/providers/ccb.js"
|
|
109
|
+
},
|
|
110
|
+
"./providers/planning-center": {
|
|
111
|
+
"types": "./dist/providers/planning-center.d.ts",
|
|
112
|
+
"import": "./dist/providers/planning-center.js"
|
|
113
|
+
},
|
|
114
|
+
"./providers/overflow": {
|
|
115
|
+
"types": "./dist/providers/overflow.d.ts",
|
|
116
|
+
"import": "./dist/providers/overflow.js"
|
|
117
|
+
},
|
|
118
|
+
"./providers/tithely": {
|
|
119
|
+
"types": "./dist/providers/tithely.d.ts",
|
|
120
|
+
"import": "./dist/providers/tithely.js"
|
|
121
|
+
},
|
|
98
122
|
"./ui": {
|
|
99
123
|
"types": "./dist/ui.d.ts",
|
|
100
124
|
"import": "./dist/ui.js"
|