@possibl/rcrt-sdk 0.1.2 → 0.5.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 +99 -62
- package/LICENSE +21 -0
- package/README.md +35 -21
- package/dist/auth.d.ts +45 -0
- package/dist/auth.d.ts.map +1 -0
- package/{src/auth.ts → dist/auth.js} +9 -24
- package/dist/auth.js.map +1 -0
- package/dist/authn.d.ts +114 -0
- package/dist/authn.d.ts.map +1 -0
- package/dist/authn.js +107 -0
- package/dist/authn.js.map +1 -0
- package/dist/breadcrumbs.d.ts +43 -0
- package/dist/breadcrumbs.d.ts.map +1 -0
- package/dist/breadcrumbs.js +122 -0
- package/dist/breadcrumbs.js.map +1 -0
- package/dist/cards.d.ts +28 -0
- package/dist/cards.d.ts.map +1 -0
- package/dist/cards.js +105 -0
- package/dist/cards.js.map +1 -0
- package/dist/chat.d.ts +103 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +105 -0
- package/dist/chat.js.map +1 -0
- package/dist/client.d.ts +85 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +133 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +76 -0
- package/dist/errors.js.map +1 -0
- package/dist/files.d.ts +41 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +64 -0
- package/dist/files.js.map +1 -0
- package/dist/generated/conformance.d.ts +48 -0
- package/dist/generated/conformance.d.ts.map +1 -0
- package/dist/generated/conformance.js +24 -0
- package/dist/generated/conformance.js.map +1 -0
- package/dist/generated/index.d.ts +34 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/index.js +34 -0
- package/dist/generated/index.js.map +1 -0
- package/dist/generated/openapi.d.ts +3900 -0
- package/dist/generated/openapi.d.ts.map +1 -0
- package/dist/generated/openapi.js +6 -0
- package/dist/generated/openapi.js.map +1 -0
- package/dist/grants.d.ts +41 -0
- package/dist/grants.d.ts.map +1 -0
- package/dist/grants.js +50 -0
- package/dist/grants.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/fetch.d.ts +47 -0
- package/dist/internal/fetch.d.ts.map +1 -0
- package/dist/internal/fetch.js +108 -0
- package/dist/internal/fetch.js.map +1 -0
- package/dist/internal/sse.d.ts +82 -0
- package/dist/internal/sse.d.ts.map +1 -0
- package/dist/internal/sse.js +161 -0
- package/dist/internal/sse.js.map +1 -0
- package/dist/marketplace.d.ts +98 -0
- package/dist/marketplace.d.ts.map +1 -0
- package/dist/marketplace.js +74 -0
- package/dist/marketplace.js.map +1 -0
- package/dist/members.d.ts +60 -0
- package/dist/members.d.ts.map +1 -0
- package/dist/members.js +74 -0
- package/dist/members.js.map +1 -0
- package/dist/org.d.ts +85 -0
- package/dist/org.d.ts.map +1 -0
- package/dist/org.js +70 -0
- package/dist/org.js.map +1 -0
- package/dist/types/breadcrumb.d.ts +70 -0
- package/dist/types/breadcrumb.d.ts.map +1 -0
- package/dist/types/breadcrumb.js +8 -0
- package/dist/types/breadcrumb.js.map +1 -0
- package/dist/types/card.d.ts +251 -0
- package/dist/types/card.d.ts.map +1 -0
- package/dist/types/card.js +10 -0
- package/dist/types/card.js.map +1 -0
- package/dist/types/engine.d.ts +69 -0
- package/dist/types/engine.d.ts.map +1 -0
- package/dist/types/engine.js +53 -0
- package/dist/types/engine.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +35 -6
- package/src/authn.ts +0 -159
- package/src/breadcrumbs.ts +0 -111
- package/src/capabilities.ts +0 -93
- package/src/cards.ts +0 -109
- package/src/chat.ts +0 -83
- package/src/client.ts +0 -97
- package/src/errors.ts +0 -101
- package/src/files.ts +0 -135
- package/src/grants.ts +0 -99
- package/src/index.ts +0 -103
- package/src/internal/fetch.ts +0 -133
- package/src/internal/sse.ts +0 -236
- package/src/sessions.ts +0 -110
- package/src/types/breadcrumb.ts +0 -77
- package/src/types/card.ts +0 -298
- package/src/types/index.ts +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,82 +1,119 @@
|
|
|
1
|
-
# Changelog
|
|
1
|
+
# @possibl/rcrt-sdk — Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes
|
|
4
|
-
format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
|
|
5
|
-
this package follows [SemVer](https://semver.org/spec/v2.0.0.html) once
|
|
6
|
-
published.
|
|
3
|
+
All notable changes are documented here. Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) + [semver](https://semver.org/).
|
|
7
4
|
|
|
8
|
-
##
|
|
5
|
+
## 0.5.0 — 2026-06-22
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
shouldn't have been published — content of the package itself is
|
|
12
|
-
unchanged from 0.1.1.
|
|
7
|
+
Workspace membership + invitation management, plus self-serve signup and open-enrollment join. Additive only — no breaking changes.
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
### Added
|
|
15
10
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
`
|
|
20
|
-
|
|
11
|
+
- **`client.members`** — `MembersModule`: workspace member + invitation
|
|
12
|
+
lifecycle against `/v1/tenants/{id}/members` and `/v1/tenants/{id}/invitations`.
|
|
13
|
+
Methods: `list`, `add`, `updateRole`, `remove`, `listInvitations`, `invite`,
|
|
14
|
+
`cancelInvitation`. Creating an invitation also sends the invite email
|
|
15
|
+
server-side (no separate resend endpoint — re-create to resend).
|
|
16
|
+
- **`TenantMember`**, **`TenantInvitation`** types, exported from the package root.
|
|
17
|
+
- **`auth.signup()`** — self-serve first-workspace provisioning
|
|
18
|
+
(`POST /v1/auth/signup`). Idempotent: returns the existing personal workspace
|
|
19
|
+
(200) when one already exists, 201 on creation. Call when `listTenants()` is
|
|
20
|
+
empty after first sign-in.
|
|
21
|
+
- **`auth.joinTenant(tenantId)`** — open-enrollment self-join
|
|
22
|
+
(`POST /v1/tenants/{id}/join`). Any authenticated user may join a tenant that
|
|
23
|
+
has opted into `tenants.auto_enroll_role`; idempotent. No `X-Tenant-ID` header.
|
|
24
|
+
- **`TenantMembership`** type, exported from the package root.
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
## 0.4.0 — 2026-06-18
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
`noUnusedLocals: true` no longer fail the type-check on the SDK's
|
|
26
|
-
source.
|
|
28
|
+
Chat file attachments (route-agnostic multimodal).
|
|
27
29
|
|
|
28
|
-
###
|
|
30
|
+
### Added
|
|
29
31
|
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
- **`SendChatRequest.attachments`** — optional `ChatAttachmentRef[]`
|
|
33
|
+
(`{ file_breadcrumb_id, mime_type? }`). Upload via `client.files.upload(...)`
|
|
34
|
+
first, then pass the returned `FileRecord.id` as `file_breadcrumb_id`. The
|
|
35
|
+
server resolves the `gs://` URI + mime type and delivers the file to a
|
|
36
|
+
file-capable agent. Omitting it leaves the text-only body unchanged.
|
|
37
|
+
- **`ChatAttachmentRef`** type, exported from the package root.
|
|
33
38
|
|
|
34
|
-
##
|
|
39
|
+
## 0.3.0 — 2026-06-17
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
The unified LLM model addressing release. LLM selection is now a single
|
|
42
|
+
canonical `route/provider/model` address stored in the agent breadcrumb's
|
|
43
|
+
`engine_config.model` (see `docs/design/LLM_PROVIDER_MODEL_RESOLUTION.md`).
|
|
44
|
+
There is no runtime tier indirection, no org override layer, and no fallbacks.
|
|
39
45
|
|
|
40
|
-
###
|
|
46
|
+
### Removed (breaking)
|
|
41
47
|
|
|
42
|
-
- **`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- **`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
- **`
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
- **`org.getLLMTiers` / `org.upsertLLMTier` / `org.deleteLLMTier`** and the
|
|
49
|
+
`OrgLLMTier` type — the `/v1/orgs/{org}/llm-tiers` endpoints and the
|
|
50
|
+
`org_intelligence_tier_overrides` layer are gone. Tiers are authoring sugar
|
|
51
|
+
expanded to a concrete address at publish time; there is no org tier override.
|
|
52
|
+
- **`OrgLLMProvider.fallback_for_id`** — `org_llm_providers` is now purely a
|
|
53
|
+
credential store keyed by route. `is_default` is retained only as a
|
|
54
|
+
convenience flag for credential listing and does NOT influence resolution.
|
|
55
|
+
There is no `fallback` role and no fallback behaviour (fail loudly instead).
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **`EngineConfig` / `ModelAddress`** types plus `parseModelAddress`,
|
|
60
|
+
`formatModelAddress`, `isTierAddress`, and `ROUTE_TIER` — the typed mirror of
|
|
61
|
+
the Go `pkg/rcrt/types.go` `EngineConfig` and `internal/llm/address.go`
|
|
62
|
+
`ModelAddress`.
|
|
63
|
+
- **`breadcrumbs.updateAgentEngineConfig(id, modelAddress, version)`** — typed
|
|
64
|
+
convenience that PATCHes an agent breadcrumb's `engine_config.model` to a
|
|
65
|
+
canonical address while preserving the rest of `content`.
|
|
66
|
+
|
|
67
|
+
### Migration
|
|
68
|
+
|
|
69
|
+
- `org.listLLMProviders` is unchanged (credential listing).
|
|
70
|
+
- Replace any tier reads/writes with the per-agent breadcrumb address via
|
|
71
|
+
`breadcrumbs.updateAgentEngineConfig`.
|
|
72
|
+
|
|
73
|
+
## 0.2.0 — 2026-06-12
|
|
74
|
+
|
|
75
|
+
The convergence release: everything the MSP console reached past the SDK for is now typed surface. `@possibl/rcrt-api` consumers should migrate to this package — the legacy package is being deprecated.
|
|
76
|
+
|
|
77
|
+
### Added
|
|
78
|
+
|
|
79
|
+
- **`client.request(path, options)`** — public, typed escape hatch with the client's auth + tenant headers, 401/409/429 retry handling and error envelope. Apps are never blocked on an SDK release for a new gateway endpoint. `options.body` takes a plain object (SDK serialises); `options.rawBody` takes FormData/binary; `options.query` appends search params.
|
|
80
|
+
- **`client.forTenant(tenantId)`** — cached, permanently-bound per-tenant client instances for parallel fleet fan-out. Replaces the mutate-one-client `setTenantId` pattern for multi-workspace reads (no shared-client races, no request serialisation).
|
|
81
|
+
- **`client.marketplace`** — bundle catalogue + install lifecycle: `listBundles`, `getBundle`, `bundleStatus`, `listInstalledBundles`, `installBundle`, `updateBundle`, `repairBundle`, `pruneBundle`, `uninstallBundle`. Typed `BundleStatus` / `BundleItemResult` wire shapes matching the gateway's `/v1/marketplace/*` routes.
|
|
82
|
+
- **`client.org`** — org admin surface: `get`, `listMembers`, `listTenants`, `createTenant`, `createCustomerOrg`, plus intelligence-tier overrides (`getLLMTiers`, `upsertLLMTier`, `deleteLLMTier`, `listLLMProviders`).
|
|
83
|
+
- **`client.files`** — multipart `upload` (isomorphic `FormData`, no deps), `list`, `get`, `downloadUrl`, `getText`, `delete`.
|
|
84
|
+
- **`client.chat`** — session utilities: `sessionBreadcrumbs`, `sessionParticipants`, `addSessionParticipant`, `removeSessionParticipant`; and `listAgents()` agent discovery (`interpret:promptable` + `interface:chat` filtering).
|
|
85
|
+
- Internal fetch: `rawBody` request option for non-JSON payloads.
|
|
59
86
|
|
|
60
87
|
### Notes
|
|
61
88
|
|
|
62
|
-
- `
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
89
|
+
- `chat.send` already supported `extra_tags` + `target_agent` — no change needed for App Control grounding tags.
|
|
90
|
+
- No breaking changes; 0.1.x consumers upgrade cleanly.
|
|
91
|
+
|
|
92
|
+
## 0.1.0-alpha.1 — 2026-04-23
|
|
93
|
+
|
|
94
|
+
First publish. Breaking changes are expected during the `alpha` line — pin exact versions. Do not use in production until `0.1.0` stable.
|
|
95
|
+
|
|
96
|
+
### Included
|
|
97
|
+
|
|
98
|
+
- `RcrtClient` with auth, chat (send + stream), breadcrumbs (CRUD + tag query + semantic search), service grants, cards, identity modules.
|
|
99
|
+
- Pluggable `TokenProvider` interface — SDK never touches Firebase / Auth0 / Clerk directly.
|
|
100
|
+
- Pluggable `EventSource` — React Native consumers inject `react-native-sse`; browser + Node 18+ use native.
|
|
101
|
+
- Typed error envelope via `ApiError.detail.code` / `KnownErrorCode`. Accepts both the canonical `{error: {code, message, details}}` and legacy `{error: "string"}` shapes during the migration window.
|
|
102
|
+
- Domain types (`Card`, `Breadcrumb`, `Row`, `ChartSpec`, ...) under the main export.
|
|
103
|
+
- OpenAPI-generated types (`paths`, `operations`, `components`) under `@possibl/rcrt-sdk/generated` for raw fetch-level type safety.
|
|
70
104
|
|
|
71
|
-
###
|
|
105
|
+
### Known gaps
|
|
72
106
|
|
|
73
|
-
- No
|
|
74
|
-
|
|
107
|
+
- No integration test suite against a live backend yet. Smoke tests (9/9) cover the mock surface. Integration harness is queued.
|
|
108
|
+
- The backend's error-envelope migration is in progress (tracked in `packages/docs/guides/07-error-handling.md`). Any handler still returning `{error: "string"}` is normalised by the SDK's `parseErrorBody`.
|
|
109
|
+
- React hooks / a card renderer are deliberately out of scope. See `packages/docs/recipes/react.md` for copy-pasteable patterns.
|
|
75
110
|
|
|
76
|
-
###
|
|
111
|
+
### Support matrix
|
|
77
112
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
| Runtime | Supported |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| Browser (Chrome 103+, Firefox 102+, Safari 16+) | Yes |
|
|
116
|
+
| Node 18+ | Yes |
|
|
117
|
+
| React Native + `react-native-sse` polyfill | Yes |
|
|
118
|
+
| Deno 1.40+ | Untested, should work |
|
|
119
|
+
| Bun 1.0+ | Untested, should work |
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Possibl AI Ltd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -87,33 +87,47 @@ const stream = rcrt.chat.sessionStream(sessionId, handlers, {
|
|
|
87
87
|
});
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
## Fleet fan-out (multi-workspace apps)
|
|
91
|
+
|
|
92
|
+
A console that reads dozens of workspaces in parallel should never
|
|
93
|
+
mutate one client's tenant. Get a cheap, cached, permanently-bound
|
|
94
|
+
client per workspace instead:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const reports = await Promise.all(
|
|
98
|
+
workspaces.map(async (ws) => {
|
|
99
|
+
const c = rcrt.forTenant(ws.tenantId);
|
|
100
|
+
return c.marketplace.listInstalledBundles();
|
|
101
|
+
}),
|
|
102
|
+
);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Escape hatch
|
|
106
|
+
|
|
107
|
+
Any gateway endpoint the SDK hasn't wrapped yet is one call away —
|
|
108
|
+
with the same auth, tenant header, retries and error envelope:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
const res = await rcrt.request<{ items: unknown[] }>('/v1/some/new/endpoint', {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
body: { plain: 'object' }, // SDK serialises JSON
|
|
114
|
+
query: { limit: 50 },
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
90
118
|
## What's exported
|
|
91
119
|
|
|
92
120
|
| Symbol | Purpose |
|
|
93
121
|
| --- | --- |
|
|
94
|
-
| `RcrtClient` | The client. One instance per workspace session. |
|
|
122
|
+
| `RcrtClient` | The client. One instance per workspace session; `forTenant()` for fan-out. |
|
|
95
123
|
| `TokenProvider` | Interface — wire any IdP. |
|
|
96
124
|
| `staticTokenProvider` | Static-token convenience (tests, `tk_*` workspace keys). |
|
|
97
125
|
| `ApiError`, `SdkError` | Error classes. Typed + discriminable by `.status` and `.detail.code`. |
|
|
126
|
+
| `MarketplaceModule`, `OrgModule`, `FilesModule` | Bundle lifecycle, org admin + LLM tiers, file upload. |
|
|
98
127
|
| `Breadcrumb`, `Card`, `Row`, `ChartSpec`, ... | Every public type from the RCRT contract. Re-exportable as your UI types. |
|
|
99
128
|
|
|
100
129
|
Browse `src/index.ts` for the full re-export list.
|
|
101
130
|
|
|
102
|
-
### Module surface on `RcrtClient`
|
|
103
|
-
|
|
104
|
-
```ts
|
|
105
|
-
const rcrt = new RcrtClient({ apiUrl, tokenProvider });
|
|
106
|
-
|
|
107
|
-
rcrt.auth // identity, tenants, invitations, user profile
|
|
108
|
-
rcrt.breadcrumbs // CRUD + tag query + semantic search
|
|
109
|
-
rcrt.chat // send + sessionStream (per-session SSE) + globalStream (/v1/events)
|
|
110
|
-
rcrt.cards // JIT-UI card resolve + helpers
|
|
111
|
-
rcrt.grants // OAuth grants + initiate + resolveService
|
|
112
|
-
rcrt.files // upload / list / get / signed download / text extract / delete
|
|
113
|
-
rcrt.sessions // constellation + participants
|
|
114
|
-
rcrt.capabilities // tools / agents / services / knowledge discovery
|
|
115
|
-
```
|
|
116
|
-
|
|
117
131
|
## Design notes
|
|
118
132
|
|
|
119
133
|
- **Isomorphic**: zero DOM or Node-only APIs in the core. The only
|
|
@@ -142,11 +156,11 @@ Full narrative + concepts + operations playbook in
|
|
|
142
156
|
|
|
143
157
|
## Status
|
|
144
158
|
|
|
145
|
-
**0.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
159
|
+
**0.2.0** — the convergence release: marketplace/org/files modules,
|
|
160
|
+
`forTenant()` fan-out and the `request()` escape hatch cover the full
|
|
161
|
+
surface the production MSP console uses. `@possibl/rcrt-api` is
|
|
162
|
+
deprecated in favour of this package. Shape is stable for the
|
|
163
|
+
documented surface; minor adjustments possible before 1.0.
|
|
150
164
|
|
|
151
165
|
## Licence
|
|
152
166
|
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TokenProvider — the seam between RCRT and your identity source.
|
|
3
|
+
*
|
|
4
|
+
* The SDK never talks to Firebase / Auth0 / Clerk directly. You wire
|
|
5
|
+
* up whichever IdP you use by implementing this interface once. On
|
|
6
|
+
* every request the SDK calls `getIdToken()` to get a fresh bearer.
|
|
7
|
+
*
|
|
8
|
+
* The provider owns refresh. If your IdP supports it (Firebase does),
|
|
9
|
+
* it should return a token that's valid for at least the next ~60s;
|
|
10
|
+
* the SDK doesn't track expiry itself.
|
|
11
|
+
*
|
|
12
|
+
* Example Firebase (web):
|
|
13
|
+
*
|
|
14
|
+
* import { getAuth } from 'firebase/auth';
|
|
15
|
+
* const auth = getAuth();
|
|
16
|
+
* const tokenProvider: TokenProvider = {
|
|
17
|
+
* async getIdToken() {
|
|
18
|
+
* const u = auth.currentUser;
|
|
19
|
+
* if (!u) throw new SdkError('NOT_SIGNED_IN', 'Sign in first');
|
|
20
|
+
* return u.getIdToken(false);
|
|
21
|
+
* },
|
|
22
|
+
* };
|
|
23
|
+
*
|
|
24
|
+
* Example test stub:
|
|
25
|
+
*
|
|
26
|
+
* const tokenProvider: TokenProvider = {
|
|
27
|
+
* async getIdToken() { return 'tk_test_workspace_api_key'; },
|
|
28
|
+
* };
|
|
29
|
+
*/
|
|
30
|
+
export interface TokenProvider {
|
|
31
|
+
/**
|
|
32
|
+
* Return a bearer token for the next request. Throws or rejects if
|
|
33
|
+
* the user isn't signed in / the key is missing.
|
|
34
|
+
*
|
|
35
|
+
* Implementations SHOULD refresh transparently if they know the
|
|
36
|
+
* token is close to expiry. The SDK calls this per-request and
|
|
37
|
+
* doesn't cache.
|
|
38
|
+
*/
|
|
39
|
+
getIdToken(): Promise<string>;
|
|
40
|
+
/** Optional hook: called on 401. Implementations can force a refresh. */
|
|
41
|
+
onUnauthorized?(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** Convenience: a provider that returns a static string. For workspace API keys or tests. */
|
|
44
|
+
export declare function staticTokenProvider(token: string): TokenProvider;
|
|
45
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE9B,yEAAyE;IACzE,cAAc,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAOhE"}
|
|
@@ -27,30 +27,15 @@
|
|
|
27
27
|
* async getIdToken() { return 'tk_test_workspace_api_key'; },
|
|
28
28
|
* };
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
import { SdkError } from './errors.js';
|
|
32
|
-
|
|
33
|
-
export interface TokenProvider {
|
|
34
|
-
/**
|
|
35
|
-
* Return a bearer token for the next request. Throws or rejects if
|
|
36
|
-
* the user isn't signed in / the key is missing.
|
|
37
|
-
*
|
|
38
|
-
* Implementations SHOULD refresh transparently if they know the
|
|
39
|
-
* token is close to expiry. The SDK calls this per-request and
|
|
40
|
-
* doesn't cache.
|
|
41
|
-
*/
|
|
42
|
-
getIdToken(): Promise<string>;
|
|
43
|
-
|
|
44
|
-
/** Optional hook: called on 401. Implementations can force a refresh. */
|
|
45
|
-
onUnauthorized?(): Promise<void>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
31
|
/** Convenience: a provider that returns a static string. For workspace API keys or tests. */
|
|
49
|
-
export function staticTokenProvider(token
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
32
|
+
export function staticTokenProvider(token) {
|
|
33
|
+
if (!token)
|
|
34
|
+
throw new SdkError('EMPTY_TOKEN', 'staticTokenProvider called with empty token');
|
|
35
|
+
return {
|
|
36
|
+
async getIdToken() {
|
|
37
|
+
return token;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
56
40
|
}
|
|
41
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiBvC,6FAA6F;AAC7F,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,QAAQ,CAAC,aAAa,EAAE,6CAA6C,CAAC,CAAC;IAC7F,OAAO;QACL,KAAK,CAAC,UAAU;YACd,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/authn.d.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity module — `/v1/auth/*` endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Distinct from the TokenProvider abstraction: this is the server-side
|
|
5
|
+
* identity surface that runs _after_ you've presented a bearer token.
|
|
6
|
+
* See `packages/docs/guides/02-auth.md`.
|
|
7
|
+
*/
|
|
8
|
+
import type { FetchContext } from './internal/fetch.js';
|
|
9
|
+
export interface MeResponse {
|
|
10
|
+
user: {
|
|
11
|
+
id: string;
|
|
12
|
+
email: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
picture?: string;
|
|
15
|
+
};
|
|
16
|
+
is_platform_admin: boolean;
|
|
17
|
+
organizations: Array<{
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
role: string;
|
|
21
|
+
}>;
|
|
22
|
+
tenants: Array<{
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
role: string;
|
|
26
|
+
}>;
|
|
27
|
+
active_tenant?: {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
role: string;
|
|
31
|
+
};
|
|
32
|
+
permissions?: string[];
|
|
33
|
+
grants?: unknown[];
|
|
34
|
+
}
|
|
35
|
+
export interface Tenant {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
org_id?: string;
|
|
39
|
+
role?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface TenantMembership {
|
|
42
|
+
user_id: string;
|
|
43
|
+
tenant_id: string;
|
|
44
|
+
role: string;
|
|
45
|
+
}
|
|
46
|
+
export interface PendingInvitation {
|
|
47
|
+
id: string;
|
|
48
|
+
org_id?: string | null;
|
|
49
|
+
tenant_id?: string | null;
|
|
50
|
+
email: string;
|
|
51
|
+
role: string;
|
|
52
|
+
status: 'pending' | 'accepted' | 'declined' | 'expired' | 'cancelled';
|
|
53
|
+
expires_at: string;
|
|
54
|
+
invited_by?: {
|
|
55
|
+
id: string;
|
|
56
|
+
name?: string;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export declare class IdentityModule {
|
|
60
|
+
private readonly ctx;
|
|
61
|
+
constructor(ctx: FetchContext);
|
|
62
|
+
/**
|
|
63
|
+
* `GET /v1/auth/me` — returns identity + all accessible workspaces.
|
|
64
|
+
*
|
|
65
|
+
* Creates the user row on first sign-in. Call this before any other
|
|
66
|
+
* RCRT endpoint for brand-new Firebase users.
|
|
67
|
+
*/
|
|
68
|
+
me(): Promise<MeResponse>;
|
|
69
|
+
/** List workspaces the current user is a member of. */
|
|
70
|
+
listTenants(): Promise<Tenant[]>;
|
|
71
|
+
/**
|
|
72
|
+
* `POST /v1/auth/signup` — self-serve first-workspace provisioning.
|
|
73
|
+
*
|
|
74
|
+
* Creates a personal organisation + "Personal" workspace for an
|
|
75
|
+
* authenticated user with zero org memberships. Idempotent: returns
|
|
76
|
+
* the existing personal workspace (200) when one already exists,
|
|
77
|
+
* 201 on creation. Call when `listTenants()` comes back empty after
|
|
78
|
+
* first sign-in.
|
|
79
|
+
*/
|
|
80
|
+
signup(): Promise<{
|
|
81
|
+
org_id: string;
|
|
82
|
+
tenant_id: string;
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* `POST /v1/tenants/{id}/join` — self-enroll into a tenant that has
|
|
86
|
+
* opted into open enrollment via `tenants.auto_enroll_role`.
|
|
87
|
+
*
|
|
88
|
+
* Unlike member management this needs NO existing membership: any
|
|
89
|
+
* authenticated user may join, and the gateway enrolls them with the
|
|
90
|
+
* tenant's configured read-only role. Idempotent — calling it again
|
|
91
|
+
* (or when already a member) is a no-op that returns the current
|
|
92
|
+
* role. The tenant id is in the URL, so no X-Tenant-ID header is
|
|
93
|
+
* sent.
|
|
94
|
+
*/
|
|
95
|
+
joinTenant(tenantId: string): Promise<TenantMembership>;
|
|
96
|
+
/** Confirm workspace membership. Client code is still responsible for setting X-Tenant-ID. */
|
|
97
|
+
selectTenant(tenantId: string): Promise<void>;
|
|
98
|
+
/** `POST /v1/auth/logout` — server-side no-op; included for symmetry + audit. */
|
|
99
|
+
logout(): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* `POST /v1/auth/delete-account` — cascading account deletion.
|
|
102
|
+
*
|
|
103
|
+
* **NOT YET ON `development`** at publish time — pending a follow-up
|
|
104
|
+
* PR. The SDK method exists so consumer code can compile against the
|
|
105
|
+
* intended shape; invoking it against a gateway that lacks the
|
|
106
|
+
* handler returns 404.
|
|
107
|
+
*/
|
|
108
|
+
deleteAccount(): Promise<void>;
|
|
109
|
+
/** Pending invitations keyed by the caller's email. */
|
|
110
|
+
listPendingInvitations(): Promise<PendingInvitation[]>;
|
|
111
|
+
acceptInvitation(token: string): Promise<void>;
|
|
112
|
+
declineInvitation(invitationId: string): Promise<void>;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=authn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authn.d.ts","sourceRoot":"","sources":["../src/authn.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,aAAa,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,CAAC;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,YAAY;IAE9C;;;;;OAKG;IACG,EAAE,IAAI,OAAO,CAAC,UAAU,CAAC;IAI/B,uDAAuD;IACjD,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAOtC;;;;;;;;OAQG;IACG,MAAM,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAO9D;;;;;;;;;;OAUG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAO7D,8FAA8F;IACxF,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD,iFAAiF;IAC3E,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAO7B;;;;;;;OAOG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC,uDAAuD;IACjD,sBAAsB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAOtD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAK7D"}
|
package/dist/authn.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity module — `/v1/auth/*` endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Distinct from the TokenProvider abstraction: this is the server-side
|
|
5
|
+
* identity surface that runs _after_ you've presented a bearer token.
|
|
6
|
+
* See `packages/docs/guides/02-auth.md`.
|
|
7
|
+
*/
|
|
8
|
+
import { request } from './internal/fetch.js';
|
|
9
|
+
export class IdentityModule {
|
|
10
|
+
ctx;
|
|
11
|
+
constructor(ctx) {
|
|
12
|
+
this.ctx = ctx;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* `GET /v1/auth/me` — returns identity + all accessible workspaces.
|
|
16
|
+
*
|
|
17
|
+
* Creates the user row on first sign-in. Call this before any other
|
|
18
|
+
* RCRT endpoint for brand-new Firebase users.
|
|
19
|
+
*/
|
|
20
|
+
async me() {
|
|
21
|
+
return request(this.ctx, '/v1/auth/me', { skipTenant: true });
|
|
22
|
+
}
|
|
23
|
+
/** List workspaces the current user is a member of. */
|
|
24
|
+
async listTenants() {
|
|
25
|
+
const res = await request(this.ctx, '/v1/auth/tenants', {
|
|
26
|
+
skipTenant: true,
|
|
27
|
+
});
|
|
28
|
+
return Array.isArray(res) ? res : (res.tenants ?? []);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* `POST /v1/auth/signup` — self-serve first-workspace provisioning.
|
|
32
|
+
*
|
|
33
|
+
* Creates a personal organisation + "Personal" workspace for an
|
|
34
|
+
* authenticated user with zero org memberships. Idempotent: returns
|
|
35
|
+
* the existing personal workspace (200) when one already exists,
|
|
36
|
+
* 201 on creation. Call when `listTenants()` comes back empty after
|
|
37
|
+
* first sign-in.
|
|
38
|
+
*/
|
|
39
|
+
async signup() {
|
|
40
|
+
return request(this.ctx, '/v1/auth/signup', {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
skipTenant: true,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `POST /v1/tenants/{id}/join` — self-enroll into a tenant that has
|
|
47
|
+
* opted into open enrollment via `tenants.auto_enroll_role`.
|
|
48
|
+
*
|
|
49
|
+
* Unlike member management this needs NO existing membership: any
|
|
50
|
+
* authenticated user may join, and the gateway enrolls them with the
|
|
51
|
+
* tenant's configured read-only role. Idempotent — calling it again
|
|
52
|
+
* (or when already a member) is a no-op that returns the current
|
|
53
|
+
* role. The tenant id is in the URL, so no X-Tenant-ID header is
|
|
54
|
+
* sent.
|
|
55
|
+
*/
|
|
56
|
+
async joinTenant(tenantId) {
|
|
57
|
+
return request(this.ctx, `/v1/tenants/${tenantId}/join`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
skipTenant: true,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Confirm workspace membership. Client code is still responsible for setting X-Tenant-ID. */
|
|
63
|
+
async selectTenant(tenantId) {
|
|
64
|
+
await request(this.ctx, `/v1/auth/tenants/${tenantId}/select`, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
skipTenant: true,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** `POST /v1/auth/logout` — server-side no-op; included for symmetry + audit. */
|
|
70
|
+
async logout() {
|
|
71
|
+
await request(this.ctx, '/v1/auth/logout', {
|
|
72
|
+
method: 'POST',
|
|
73
|
+
skipTenant: true,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* `POST /v1/auth/delete-account` — cascading account deletion.
|
|
78
|
+
*
|
|
79
|
+
* **NOT YET ON `development`** at publish time — pending a follow-up
|
|
80
|
+
* PR. The SDK method exists so consumer code can compile against the
|
|
81
|
+
* intended shape; invoking it against a gateway that lacks the
|
|
82
|
+
* handler returns 404.
|
|
83
|
+
*/
|
|
84
|
+
async deleteAccount() {
|
|
85
|
+
await request(this.ctx, '/v1/auth/delete-account', {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
skipTenant: true,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** Pending invitations keyed by the caller's email. */
|
|
91
|
+
async listPendingInvitations() {
|
|
92
|
+
const res = await request(this.ctx, '/v1/invitations/pending');
|
|
93
|
+
return Array.isArray(res) ? res : (res.invitations ?? []);
|
|
94
|
+
}
|
|
95
|
+
async acceptInvitation(token) {
|
|
96
|
+
await request(this.ctx, '/v1/invitations/accept', {
|
|
97
|
+
method: 'POST',
|
|
98
|
+
body: { token },
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async declineInvitation(invitationId) {
|
|
102
|
+
await request(this.ctx, `/v1/invitations/${invitationId}/decline`, {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=authn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authn.js","sourceRoot":"","sources":["../src/authn.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAyC9C,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,GAAiB;QAAjB,QAAG,GAAH,GAAG,CAAc;IAAG,CAAC;IAElD;;;;;OAKG;IACH,KAAK,CAAC,EAAE;QACN,OAAO,OAAO,CAAa,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,WAAW;QACf,MAAM,GAAG,GAAG,MAAM,OAAO,CAAmC,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE;YACxF,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,MAAM;QACV,OAAO,OAAO,CAAwC,IAAI,CAAC,GAAG,EAAE,iBAAiB,EAAE;YACjF,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,UAAU,CAAC,QAAgB;QAC/B,OAAO,OAAO,CAAmB,IAAI,CAAC,GAAG,EAAE,eAAe,QAAQ,OAAO,EAAE;YACzE,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,oBAAoB,QAAQ,SAAS,EAAE;YACnE,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,MAAM;QACV,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,iBAAiB,EAAE;YAC/C,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,yBAAyB,EAAE;YACvD,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,sBAAsB;QAC1B,MAAM,GAAG,GAAG,MAAM,OAAO,CAEvB,IAAI,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;QACvC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAAa;QAClC,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,wBAAwB,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,KAAK,EAAE;SAChB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,YAAoB;QAC1C,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,mBAAmB,YAAY,UAAU,EAAE;YACvE,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;IACL,CAAC;CACF"}
|