@braidhq/server 0.2.0 → 0.3.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/LICENSE +21 -0
- package/README.md +3 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +32 -6
- package/dist/app.js.map +1 -1
- package/dist/composeApp.d.ts +9 -4
- package/dist/composeApp.d.ts.map +1 -1
- package/dist/composeApp.js +13 -6
- package/dist/composeApp.js.map +1 -1
- package/dist/composeFsApp.d.ts +49 -3
- package/dist/composeFsApp.d.ts.map +1 -1
- package/dist/composeFsApp.js +156 -61
- package/dist/composeFsApp.js.map +1 -1
- package/dist/defaultOntologyPlugins.d.ts +9 -0
- package/dist/defaultOntologyPlugins.d.ts.map +1 -0
- package/dist/defaultOntologyPlugins.js +11 -0
- package/dist/defaultOntologyPlugins.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/auth/AccessPolicy.d.ts +1 -1
- package/dist/infrastructure/auth/SessionStore.d.ts.map +1 -1
- package/dist/infrastructure/auth/SessionStore.js +5 -2
- package/dist/infrastructure/auth/SessionStore.js.map +1 -1
- package/dist/infrastructure/batch/FsBatchPlanRepository.d.ts +2 -67
- package/dist/infrastructure/batch/FsBatchPlanRepository.d.ts.map +1 -1
- package/dist/infrastructure/batch/FsBatchPlanRepository.js +8 -6
- package/dist/infrastructure/batch/FsBatchPlanRepository.js.map +1 -1
- package/dist/infrastructure/hitl/FsClarificationRepository.d.ts +1 -1
- package/dist/infrastructure/hitl/FsClarificationRepository.d.ts.map +1 -1
- package/dist/infrastructure/hitl/FsClarificationRepository.js +8 -7
- package/dist/infrastructure/hitl/FsClarificationRepository.js.map +1 -1
- package/dist/infrastructure/hitl/FsProposalRepository.d.ts.map +1 -1
- package/dist/infrastructure/hitl/FsProposalRepository.js +2 -1
- package/dist/infrastructure/hitl/FsProposalRepository.js.map +1 -1
- package/dist/infrastructure/model/FsModelSerializer.d.ts +2 -4
- package/dist/infrastructure/model/FsModelSerializer.d.ts.map +1 -1
- package/dist/infrastructure/oauth/GitHubOAuth.d.ts +45 -0
- package/dist/infrastructure/oauth/GitHubOAuth.d.ts.map +1 -0
- package/dist/infrastructure/oauth/GitHubOAuth.js +85 -0
- package/dist/infrastructure/oauth/GitHubOAuth.js.map +1 -0
- package/dist/infrastructure/oauth/providers.d.ts +19 -0
- package/dist/infrastructure/oauth/providers.d.ts.map +1 -0
- package/dist/infrastructure/oauth/providers.js +22 -0
- package/dist/infrastructure/oauth/providers.js.map +1 -0
- package/dist/infrastructure/skill/FsSkillRegistry.d.ts +6 -0
- package/dist/infrastructure/skill/FsSkillRegistry.d.ts.map +1 -1
- package/dist/infrastructure/skill/FsSkillRegistry.js +7 -1
- package/dist/infrastructure/skill/FsSkillRegistry.js.map +1 -1
- package/dist/infrastructure/skill/SubprocessSkillRunner.d.ts +26 -5
- package/dist/infrastructure/skill/SubprocessSkillRunner.d.ts.map +1 -1
- package/dist/infrastructure/skill/SubprocessSkillRunner.js +125 -13
- package/dist/infrastructure/skill/SubprocessSkillRunner.js.map +1 -1
- package/dist/infrastructure/source/unitScan.d.ts +11 -0
- package/dist/infrastructure/source/unitScan.d.ts.map +1 -0
- package/dist/infrastructure/source/{intentScan.js → unitScan.js} +19 -12
- package/dist/infrastructure/source/unitScan.js.map +1 -0
- package/dist/infrastructure/users/UserDirectoryFromRegistry.d.ts.map +1 -1
- package/dist/infrastructure/users/UserDirectoryFromRegistry.js +1 -0
- package/dist/infrastructure/users/UserDirectoryFromRegistry.js.map +1 -1
- package/dist/infrastructure/workspace/productManifestWriter.d.ts +5 -1
- package/dist/infrastructure/workspace/productManifestWriter.d.ts.map +1 -1
- package/dist/infrastructure/workspace/productManifestWriter.js +5 -2
- package/dist/infrastructure/workspace/productManifestWriter.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +18 -1
- package/dist/middleware/auth.js.map +1 -1
- package/dist/routes/clarifications.d.ts.map +1 -1
- package/dist/routes/clarifications.js +25 -22
- package/dist/routes/clarifications.js.map +1 -1
- package/dist/routes/oauth.d.ts +51 -10
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/oauth.js +174 -62
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/ontologies.d.ts +7 -0
- package/dist/routes/ontologies.d.ts.map +1 -0
- package/dist/routes/ontologies.js +29 -0
- package/dist/routes/ontologies.js.map +1 -0
- package/dist/routes/ontology.d.ts.map +1 -1
- package/dist/routes/ontology.js +2 -1
- package/dist/routes/ontology.js.map +1 -1
- package/dist/routes/proposals.d.ts.map +1 -1
- package/dist/routes/proposals.js +5 -2
- package/dist/routes/proposals.js.map +1 -1
- package/dist/routes/skillInputOptions.js +16 -14
- package/dist/routes/skillInputOptions.js.map +1 -1
- package/dist/routes/skills.d.ts.map +1 -1
- package/dist/routes/skills.js +7 -5
- package/dist/routes/skills.js.map +1 -1
- package/dist/routes/sourceConnection.d.ts +30 -0
- package/dist/routes/sourceConnection.d.ts.map +1 -0
- package/dist/routes/sourceConnection.js +51 -0
- package/dist/routes/sourceConnection.js.map +1 -0
- package/dist/routes/sourceUnitObservations.d.ts +3 -3
- package/dist/routes/sourceUnitObservations.d.ts.map +1 -1
- package/dist/routes/sourceUnitObservations.js +3 -3
- package/dist/routes/sourceUnitObservations.js.map +1 -1
- package/dist/routes/workspaces.d.ts +6 -0
- package/dist/routes/workspaces.d.ts.map +1 -1
- package/dist/routes/workspaces.js +12 -7
- package/dist/routes/workspaces.js.map +1 -1
- package/dist/serviceAccounts.d.ts +13 -0
- package/dist/serviceAccounts.d.ts.map +1 -0
- package/dist/serviceAccounts.js +26 -0
- package/dist/serviceAccounts.js.map +1 -0
- package/package.json +34 -39
- package/dist/infrastructure/source/intentScan.d.ts +0 -13
- package/dist/infrastructure/source/intentScan.d.ts.map +0 -1
- package/dist/infrastructure/source/intentScan.js.map +0 -1
|
@@ -7,7 +7,7 @@ import { getWorkspaceId } from '../middleware/workspaceId.js';
|
|
|
7
7
|
import { NotFoundResponse, ValidationFailureResponse, WorkspaceIdParam } from './_shared.js';
|
|
8
8
|
import { assertEntityInWorkspace } from './helpers.js';
|
|
9
9
|
const ListQuery = z.object({
|
|
10
|
-
status: z.union([ClarificationStatus, z.array(ClarificationStatus)]).optional().openapi({ description: 'Filter by
|
|
10
|
+
status: z.union([ClarificationStatus, z.array(ClarificationStatus)]).optional().openapi({ description: 'Filter by clarification status. Pass one or many.' }),
|
|
11
11
|
limit: z.coerce.number().int().positive().optional(),
|
|
12
12
|
offset: z.coerce.number().int().nonnegative().optional(),
|
|
13
13
|
showAll: z.coerce.boolean().optional().openapi({ description: 'Owner-only: bypass the personal-pending filter so every member\'s open questions are visible.' }),
|
|
@@ -15,7 +15,7 @@ const ListQuery = z.object({
|
|
|
15
15
|
// Reviewer-facing answer body.
|
|
16
16
|
// The selection is either an existing `candidateId`,
|
|
17
17
|
// or a freshly authored `customCandidate` (description only).
|
|
18
|
-
// The server appends it to the
|
|
18
|
+
// The server appends it to the clarification and answers in one transaction.
|
|
19
19
|
// `note` is a free-text rationale saved on the answer commit.
|
|
20
20
|
// `userId` is accepted for backwards compat,
|
|
21
21
|
// the authoritative value is the request context set by middleware.
|
|
@@ -36,7 +36,7 @@ const SkipBody = z.object({
|
|
|
36
36
|
// The only legal transition the skill drives is `answered` to `applied`.
|
|
37
37
|
// The proposalId is optional, present when a Proposal was produced,
|
|
38
38
|
// absent when the chosen candidate had no graph impact.
|
|
39
|
-
// The skill then records the
|
|
39
|
+
// The skill then records the clarification as applied without a linking proposal.
|
|
40
40
|
const ApplyBody = z.object({
|
|
41
41
|
status: z.literal('applied'),
|
|
42
42
|
proposalId: ProposalId.optional(),
|
|
@@ -98,7 +98,7 @@ const getClarificationRoute = createRoute({
|
|
|
98
98
|
request: { params: ClarificationIdParam },
|
|
99
99
|
responses: {
|
|
100
100
|
200: {
|
|
101
|
-
description: 'The requested
|
|
101
|
+
description: 'The requested clarification.',
|
|
102
102
|
content: { 'application/json': { schema: Clarification } },
|
|
103
103
|
},
|
|
104
104
|
404: NotFoundResponse,
|
|
@@ -116,7 +116,7 @@ const answerClarificationRoute = createRoute({
|
|
|
116
116
|
},
|
|
117
117
|
responses: {
|
|
118
118
|
200: {
|
|
119
|
-
description: 'The updated
|
|
119
|
+
description: 'The updated clarification.',
|
|
120
120
|
content: { 'application/json': { schema: Clarification } },
|
|
121
121
|
},
|
|
122
122
|
404: NotFoundResponse,
|
|
@@ -135,7 +135,7 @@ const applyClarificationRoute = createRoute({
|
|
|
135
135
|
},
|
|
136
136
|
responses: {
|
|
137
137
|
200: {
|
|
138
|
-
description: 'The updated
|
|
138
|
+
description: 'The updated clarification.',
|
|
139
139
|
content: { 'application/json': { schema: Clarification } },
|
|
140
140
|
},
|
|
141
141
|
404: NotFoundResponse,
|
|
@@ -153,7 +153,7 @@ const skipClarificationRoute = createRoute({
|
|
|
153
153
|
},
|
|
154
154
|
responses: {
|
|
155
155
|
200: {
|
|
156
|
-
description: 'The updated
|
|
156
|
+
description: 'The updated clarification.',
|
|
157
157
|
content: { 'application/json': { schema: Clarification } },
|
|
158
158
|
},
|
|
159
159
|
404: NotFoundResponse,
|
|
@@ -175,38 +175,41 @@ export function createClarificationRouter(deps) {
|
|
|
175
175
|
...c,
|
|
176
176
|
id: c.id ?? newClarificationCandidateId(),
|
|
177
177
|
}));
|
|
178
|
-
const
|
|
179
|
-
return context.json(
|
|
178
|
+
const clarification = await deps.hitlService.submitClarification({ ...body, workspaceId, candidates, submitterId });
|
|
179
|
+
return context.json(clarification.toData(), 201);
|
|
180
180
|
});
|
|
181
181
|
router.openapi(listClarificationRoute, async (context) => {
|
|
182
182
|
const workspaceId = getWorkspaceId(context);
|
|
183
183
|
const { status, limit, offset, showAll } = context.req.valid('query');
|
|
184
184
|
const statuses = status === undefined ? undefined : Array.isArray(status) ? status : [status];
|
|
185
185
|
const viewer = getViewerContext(context);
|
|
186
|
-
const
|
|
187
|
-
|
|
186
|
+
const isOwner = viewer?.effectiveRole === 'owner';
|
|
187
|
+
// No viewer is an open composition (in-memory), which applies no personal filter.
|
|
188
|
+
const viewerId = (!viewer || (showAll && isOwner)) ? undefined : getUserId(context);
|
|
189
|
+
// Owners also see service-owned (autonomous) pending, since only they can act on it.
|
|
190
|
+
const clarifications = await deps.clarificationRepository.list({
|
|
188
191
|
workspaceId,
|
|
189
192
|
statuses,
|
|
190
193
|
limit,
|
|
191
194
|
offset,
|
|
192
|
-
...(viewerId ? { viewerId } : {}),
|
|
195
|
+
...(viewerId ? { viewerId, includeServiceOwned: isOwner } : {}),
|
|
193
196
|
});
|
|
194
|
-
return context.json({ items:
|
|
197
|
+
return context.json({ items: clarifications.map(clarification => clarification.toData()) }, 200);
|
|
195
198
|
});
|
|
196
199
|
router.openapi(getClarificationRoute, async (context) => {
|
|
197
200
|
const workspaceId = getWorkspaceId(context);
|
|
198
201
|
const { clarificationId } = context.req.valid('param');
|
|
199
|
-
const
|
|
200
|
-
assertEntityInWorkspace(workspaceId,
|
|
201
|
-
return context.json(
|
|
202
|
+
const clarification = await deps.clarificationRepository.load(clarificationId);
|
|
203
|
+
assertEntityInWorkspace(workspaceId, clarification.workspaceId, 'Clarification', clarificationId);
|
|
204
|
+
return context.json(clarification.toData(), 200);
|
|
202
205
|
});
|
|
203
206
|
router.openapi(answerClarificationRoute, async (context) => {
|
|
204
207
|
const workspaceId = getWorkspaceId(context);
|
|
205
208
|
const { clarificationId } = context.req.valid('param');
|
|
206
209
|
const body = context.req.valid('json');
|
|
207
210
|
const userId = body.userId ?? getUserId(context);
|
|
208
|
-
const
|
|
209
|
-
assertEntityInWorkspace(workspaceId,
|
|
211
|
+
const clarification = await deps.clarificationRepository.load(clarificationId);
|
|
212
|
+
assertEntityInWorkspace(workspaceId, clarification.workspaceId, 'Clarification', clarificationId);
|
|
210
213
|
const selection = body.candidateId
|
|
211
214
|
? { kind: 'existing', candidateId: body.candidateId }
|
|
212
215
|
: { kind: 'custom', description: body.customCandidate.description };
|
|
@@ -223,8 +226,8 @@ export function createClarificationRouter(deps) {
|
|
|
223
226
|
const { clarificationId } = context.req.valid('param');
|
|
224
227
|
const { proposalId, userId: bodyUserId } = context.req.valid('json');
|
|
225
228
|
const userId = bodyUserId ?? getUserId(context);
|
|
226
|
-
const
|
|
227
|
-
assertEntityInWorkspace(workspaceId,
|
|
229
|
+
const clarification = await deps.clarificationRepository.load(clarificationId);
|
|
230
|
+
assertEntityInWorkspace(workspaceId, clarification.workspaceId, 'Clarification', clarificationId);
|
|
228
231
|
const applied = await deps.hitlService.markClarificationApplied(clarificationId, userId, proposalId);
|
|
229
232
|
return context.json(applied.toData(), 200);
|
|
230
233
|
});
|
|
@@ -233,8 +236,8 @@ export function createClarificationRouter(deps) {
|
|
|
233
236
|
const { clarificationId } = context.req.valid('param');
|
|
234
237
|
const { reason, userId: bodyUserId } = context.req.valid('json');
|
|
235
238
|
const userId = bodyUserId ?? getUserId(context);
|
|
236
|
-
const
|
|
237
|
-
assertEntityInWorkspace(workspaceId,
|
|
239
|
+
const clarification = await deps.clarificationRepository.load(clarificationId);
|
|
240
|
+
assertEntityInWorkspace(workspaceId, clarification.workspaceId, 'Clarification', clarificationId);
|
|
238
241
|
const skipped = await deps.hitlService.skipClarification(clarificationId, reason, userId);
|
|
239
242
|
return context.json(skipped.toData(), 200);
|
|
240
243
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clarifications.js","sourceRoot":"","sources":["../../src/routes/clarifications.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,eAAe,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC5J,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC5F,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAEtD,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"clarifications.js","sourceRoot":"","sources":["../../src/routes/clarifications.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/oauth.d.ts
CHANGED
|
@@ -1,19 +1,60 @@
|
|
|
1
|
+
import type { WorkspaceService } from '@braidhq/core';
|
|
2
|
+
import type { Hono as HonoType } from 'hono';
|
|
3
|
+
import type { GitHubOAuth } from '../infrastructure/oauth/GitHubOAuth.js';
|
|
1
4
|
import type { GoogleOAuth } from '../infrastructure/oauth/GoogleOAuth.js';
|
|
2
5
|
import type { SecretStore } from '../infrastructure/secrets/SecretStore.js';
|
|
3
|
-
import {
|
|
6
|
+
import type { UserRegistryFile } from '../infrastructure/users/UserRegistryFile.js';
|
|
7
|
+
import type { WorkspaceRegistryFile } from '../infrastructure/workspace/WorkspaceRegistryFile.js';
|
|
8
|
+
/** The workspace member who authorised a source connection. */
|
|
9
|
+
export interface ConnectedBy {
|
|
10
|
+
readonly userId: string;
|
|
11
|
+
readonly displayName: string;
|
|
12
|
+
}
|
|
13
|
+
interface PendingFlow {
|
|
14
|
+
readonly workspaceId: string;
|
|
15
|
+
readonly sourceId: string;
|
|
16
|
+
readonly connectedBy?: ConnectedBy;
|
|
17
|
+
readonly codeVerifier?: string;
|
|
18
|
+
readonly createdAt: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* In-process store of pending OAuth flows, keyed by the state token.
|
|
22
|
+
* The start and callback routers mount at different prefixes,
|
|
23
|
+
* so they share one instance,
|
|
24
|
+
* and a flow opened by `start` is resolved by `callback`.
|
|
25
|
+
* A flow is short-lived, one browser round-trip, and a restart cancels it.
|
|
26
|
+
* SaaS deployments should swap this for a shared store.
|
|
27
|
+
*/
|
|
28
|
+
export declare class OAuthFlowStore {
|
|
29
|
+
private readonly pending;
|
|
30
|
+
put(state: string, flow: PendingFlow): void;
|
|
31
|
+
take(state: string): PendingFlow | undefined;
|
|
32
|
+
private sweep;
|
|
33
|
+
}
|
|
4
34
|
export interface OAuthRouterDeps {
|
|
5
35
|
readonly secretStore: SecretStore;
|
|
36
|
+
readonly flowStore: OAuthFlowStore;
|
|
6
37
|
readonly google?: GoogleOAuth;
|
|
38
|
+
readonly github?: GitHubOAuth;
|
|
39
|
+
readonly userRegistry?: UserRegistryFile;
|
|
40
|
+
readonly workspaceService?: WorkspaceService;
|
|
41
|
+
readonly workspaceRegistry?: WorkspaceRegistryFile;
|
|
7
42
|
}
|
|
8
43
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
44
|
+
* Source-connection start routes. `workspace.write` is owner-only,
|
|
45
|
+
* so only an owner connects or reconnects a source on an existing workspace,
|
|
46
|
+
* and the authorising member is recorded as `connectedBy`.
|
|
47
|
+
* A not-yet-scaffolded workspace is allowed,
|
|
48
|
+
* since the Wizard connects a source before it creates the workspace,
|
|
49
|
+
* and the caller becomes its owner.
|
|
50
|
+
*/
|
|
51
|
+
export declare function createOAuthStartRouter(deps: OAuthRouterDeps): HonoType;
|
|
52
|
+
/**
|
|
53
|
+
* OAuth callback routes, mounted at `/oauth`,
|
|
54
|
+
* so the redirect URI stays one fixed path per provider,
|
|
55
|
+
* which is what the OAuth app registers.
|
|
56
|
+
* The state token carries the flow back to its workspace and source.
|
|
17
57
|
*/
|
|
18
|
-
export declare function
|
|
58
|
+
export declare function createOAuthCallbackRouter(deps: OAuthRouterDeps): HonoType;
|
|
59
|
+
export {};
|
|
19
60
|
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/routes/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/routes/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhE,OAAO,KAAK,EAAW,IAAI,IAAI,QAAQ,EAAE,MAAM,MAAM,CAAA;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAA;AACnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sDAAsD,CAAA;AAkBjG,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAA;IAElC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAmBD;;;;;;;GAOG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IAEzD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI;IAK3C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAM5C,OAAO,CAAC,KAAK;CAOd;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAG7B,QAAQ,CAAC,YAAY,CAAC,EAAE,gBAAgB,CAAA;IACxC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAC5C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,qBAAqB,CAAA;CACnD;AAwCD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,eAAe,GAAG,QAAQ,CAetE;AAmCD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,eAAe,GAAG,QAAQ,CAuBzE"}
|
package/dist/routes/oauth.js
CHANGED
|
@@ -1,86 +1,198 @@
|
|
|
1
|
+
import { ForbiddenError, NotFoundError } from '@braidhq/core';
|
|
2
|
+
import { WorkspaceId } from '@braidhq/schema';
|
|
1
3
|
import { zValidator } from '@hono/zod-validator';
|
|
2
4
|
import { Hono } from 'hono';
|
|
3
5
|
import { z } from 'zod';
|
|
4
6
|
import { createOAuthState, createPkceVerifier } from '../infrastructure/oauth/GoogleOAuth.js';
|
|
7
|
+
import { oauthProvider } from '../infrastructure/oauth/providers.js';
|
|
8
|
+
import { getUserId } from '../middleware/auth.js';
|
|
9
|
+
import { defaultPermissionRegistry, resolveViewer } from '../policy/index.js';
|
|
5
10
|
const DRIVE_READONLY_SCOPE = 'https://www.googleapis.com/auth/drive.readonly';
|
|
6
11
|
const StartBodySchema = z.object({
|
|
7
12
|
workspaceId: z.string().min(1),
|
|
8
13
|
sourceId: z.string().min(1),
|
|
9
14
|
});
|
|
10
15
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* acceptable for a local desktop or single-user install.
|
|
18
|
-
* SaaS deployments should swap `pending` for a shared store.
|
|
16
|
+
* In-process store of pending OAuth flows, keyed by the state token.
|
|
17
|
+
* The start and callback routers mount at different prefixes,
|
|
18
|
+
* so they share one instance,
|
|
19
|
+
* and a flow opened by `start` is resolved by `callback`.
|
|
20
|
+
* A flow is short-lived, one browser round-trip, and a restart cancels it.
|
|
21
|
+
* SaaS deployments should swap this for a shared store.
|
|
19
22
|
*/
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
export class OAuthFlowStore {
|
|
24
|
+
pending = new Map();
|
|
25
|
+
put(state, flow) {
|
|
26
|
+
this.pending.set(state, flow);
|
|
27
|
+
this.sweep();
|
|
28
|
+
}
|
|
29
|
+
take(state) {
|
|
30
|
+
const flow = this.pending.get(state);
|
|
31
|
+
this.pending.delete(state);
|
|
32
|
+
return flow;
|
|
33
|
+
}
|
|
34
|
+
sweep() {
|
|
35
|
+
const cutoff = Date.now() - 10 * 60 * 1000;
|
|
36
|
+
for (const [state, flow] of this.pending) {
|
|
37
|
+
if (flow.createdAt < cutoff)
|
|
38
|
+
this.pending.delete(state);
|
|
28
39
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function providersOf(deps) {
|
|
43
|
+
const google = oauthProvider('google');
|
|
44
|
+
const github = oauthProvider('github');
|
|
45
|
+
return [
|
|
46
|
+
{
|
|
47
|
+
id: google.id,
|
|
48
|
+
label: google.label,
|
|
49
|
+
namespace: google.namespace,
|
|
50
|
+
notConfigured: 'Google OAuth is not configured on this server. Set BRAID_GOOGLE_CLIENT_ID + BRAID_GOOGLE_CLIENT_SECRET (and BRAID_GOOGLE_REDIRECT_URI if not the default) and restart.',
|
|
51
|
+
...(deps.google
|
|
52
|
+
? {
|
|
53
|
+
begin: (state) => {
|
|
54
|
+
const codeVerifier = createPkceVerifier();
|
|
55
|
+
return { authorizationUrl: deps.google.buildAuthorizationUrl({ scopes: [DRIVE_READONLY_SCOPE], state, codeVerifier }), codeVerifier };
|
|
56
|
+
},
|
|
57
|
+
complete: (flow, code) => {
|
|
58
|
+
if (!flow.codeVerifier)
|
|
59
|
+
throw new Error('Google flow is missing its PKCE verifier.');
|
|
60
|
+
return deps.google.exchangeCode({ code, codeVerifier: flow.codeVerifier });
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
: {}),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: github.id,
|
|
67
|
+
label: github.label,
|
|
68
|
+
namespace: github.namespace,
|
|
69
|
+
notConfigured: 'GitHub OAuth is not configured on this server. Set BRAID_GITHUB_CLIENT_ID + BRAID_GITHUB_CLIENT_SECRET (and BRAID_GITHUB_REDIRECT_URI if not the default) and restart.',
|
|
70
|
+
...(deps.github
|
|
71
|
+
? {
|
|
72
|
+
begin: (state) => ({ authorizationUrl: deps.github.buildAuthorizationUrl({ state }) }),
|
|
73
|
+
complete: (_flow, code) => deps.github.exchangeCode({ code }),
|
|
74
|
+
}
|
|
75
|
+
: {}),
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Source-connection start routes. `workspace.write` is owner-only,
|
|
81
|
+
* so only an owner connects or reconnects a source on an existing workspace,
|
|
82
|
+
* and the authorising member is recorded as `connectedBy`.
|
|
83
|
+
* A not-yet-scaffolded workspace is allowed,
|
|
84
|
+
* since the Wizard connects a source before it creates the workspace,
|
|
85
|
+
* and the caller becomes its owner.
|
|
86
|
+
*/
|
|
87
|
+
export function createOAuthStartRouter(deps) {
|
|
88
|
+
const router = new Hono();
|
|
89
|
+
for (const provider of providersOf(deps)) {
|
|
90
|
+
router.post(`/${provider.id}/start`, zValidator('json', StartBodySchema), async (context) => {
|
|
91
|
+
if (!provider.begin)
|
|
92
|
+
return context.json({ error: provider.notConfigured }, 503);
|
|
93
|
+
const { workspaceId, sourceId } = context.req.valid('json');
|
|
94
|
+
const connectedBy = await authoriseConnect(deps, workspaceId, getUserId(context));
|
|
95
|
+
const state = createOAuthState();
|
|
96
|
+
const started = provider.begin(state);
|
|
97
|
+
deps.flowStore.put(state, pendingFlow(workspaceId, sourceId, connectedBy, started.codeVerifier));
|
|
98
|
+
return context.json({ authorizationUrl: started.authorizationUrl });
|
|
38
99
|
});
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
router.get('/google/callback', async (context) => {
|
|
42
|
-
const state = context.req.query('state');
|
|
43
|
-
const code = context.req.query('code');
|
|
44
|
-
const error = context.req.query('error');
|
|
45
|
-
if (error)
|
|
46
|
-
return context.html(renderCallbackPage({ ok: false, message: `Google returned: ${error}` }), 400);
|
|
47
|
-
if (!state || !code)
|
|
48
|
-
return context.html(renderCallbackPage({ ok: false, message: 'Missing state or code query parameter.' }), 400);
|
|
49
|
-
if (!deps.google)
|
|
50
|
-
return context.html(renderCallbackPage({ ok: false, message: 'OAuth not configured.' }), 503);
|
|
51
|
-
const flow = pending.get(state);
|
|
52
|
-
pending.delete(state);
|
|
53
|
-
if (!flow)
|
|
54
|
-
return context.html(renderCallbackPage({ ok: false, message: 'State token not recognised (probably expired or already used).' }), 400);
|
|
55
|
-
try {
|
|
56
|
-
const tokens = await deps.google.exchangeCode({ code, codeVerifier: flow.codeVerifier });
|
|
57
|
-
await persistTokens(deps.secretStore, flow.workspaceId, flow.sourceId, tokens);
|
|
58
|
-
return context.html(renderCallbackPage({ ok: true, message: 'Connected. You can close this window.' }));
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
return context.html(renderCallbackPage({
|
|
62
|
-
ok: false,
|
|
63
|
-
message: err instanceof Error ? err.message : String(err),
|
|
64
|
-
}), 500);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
100
|
+
}
|
|
67
101
|
return router;
|
|
68
102
|
}
|
|
69
|
-
|
|
70
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Gate a connect on `workspace.write` when the workspace exists,
|
|
105
|
+
* allow it before scaffold, and return who is connecting.
|
|
106
|
+
* Returns undefined in the in-memory composition,
|
|
107
|
+
* which wires no user or workspace registry and stays open,
|
|
108
|
+
* matching how the other workspace routes behave there.
|
|
109
|
+
*/
|
|
110
|
+
async function authoriseConnect(deps, workspaceId, userId) {
|
|
111
|
+
if (!deps.userRegistry || !deps.workspaceService || !deps.workspaceRegistry)
|
|
112
|
+
return undefined;
|
|
113
|
+
const user = await deps.userRegistry.get(userId);
|
|
114
|
+
if (!user)
|
|
115
|
+
throw new ForbiddenError(`Unknown user "${userId}".`);
|
|
116
|
+
const workspace = await findWorkspaceOrUndefined(deps.workspaceService, workspaceId);
|
|
117
|
+
if (workspace) {
|
|
118
|
+
const member = await deps.workspaceRegistry.getMember(workspace.rootPath, userId);
|
|
119
|
+
if (!defaultPermissionRegistry.can('workspace.write', resolveViewer(user, member)))
|
|
120
|
+
throw new ForbiddenError(`Only an owner can connect a source on workspace "${workspaceId}".`);
|
|
121
|
+
}
|
|
122
|
+
return { userId: user.id, displayName: user.displayName };
|
|
71
123
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
124
|
+
async function findWorkspaceOrUndefined(service, workspaceId) {
|
|
125
|
+
try {
|
|
126
|
+
return await service.findById(WorkspaceId.parse(workspaceId));
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (error instanceof NotFoundError)
|
|
130
|
+
return undefined;
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* OAuth callback routes, mounted at `/oauth`,
|
|
136
|
+
* so the redirect URI stays one fixed path per provider,
|
|
137
|
+
* which is what the OAuth app registers.
|
|
138
|
+
* The state token carries the flow back to its workspace and source.
|
|
139
|
+
*/
|
|
140
|
+
export function createOAuthCallbackRouter(deps) {
|
|
141
|
+
const router = new Hono();
|
|
142
|
+
for (const provider of providersOf(deps)) {
|
|
143
|
+
router.get(`/${provider.id}/callback`, async (context) => {
|
|
144
|
+
const parsed = parseCallback(context, provider);
|
|
145
|
+
if (!parsed.ok)
|
|
146
|
+
return parsed.response;
|
|
147
|
+
if (!provider.complete)
|
|
148
|
+
return context.html(renderCallbackPage({ ok: false, provider, message: 'OAuth not configured.' }), 503);
|
|
149
|
+
const flow = deps.flowStore.take(parsed.state);
|
|
150
|
+
if (!flow)
|
|
151
|
+
return context.html(renderCallbackPage({ ok: false, provider, message: 'State token not recognised (probably expired or already used).' }), 400);
|
|
152
|
+
try {
|
|
153
|
+
const tokens = await provider.complete(flow, parsed.code);
|
|
154
|
+
await persistTokens(deps.secretStore, provider, flow, tokens);
|
|
155
|
+
return context.html(renderCallbackPage({ ok: true, provider, message: 'Connected. You can close this window.' }));
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
return context.html(renderCallbackPage({ ok: false, provider, message: err instanceof Error ? err.message : String(err) }), 500);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
77
161
|
}
|
|
162
|
+
return router;
|
|
163
|
+
}
|
|
164
|
+
function pendingFlow(workspaceId, sourceId, connectedBy, codeVerifier) {
|
|
165
|
+
return {
|
|
166
|
+
workspaceId,
|
|
167
|
+
sourceId,
|
|
168
|
+
createdAt: Date.now(),
|
|
169
|
+
...(connectedBy ? { connectedBy } : {}),
|
|
170
|
+
...(codeVerifier ? { codeVerifier } : {}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function parseCallback(context, provider) {
|
|
174
|
+
const error = context.req.query('error');
|
|
175
|
+
if (error)
|
|
176
|
+
return { ok: false, response: context.html(renderCallbackPage({ ok: false, provider, message: `${provider.label} returned: ${error}` }), 400) };
|
|
177
|
+
const state = context.req.query('state');
|
|
178
|
+
const code = context.req.query('code');
|
|
179
|
+
if (!state || !code)
|
|
180
|
+
return { ok: false, response: context.html(renderCallbackPage({ ok: false, provider, message: 'Missing state or code query parameter.' }), 400) };
|
|
181
|
+
return { ok: true, state, code };
|
|
182
|
+
}
|
|
183
|
+
async function persistTokens(store, provider, flow, tokens) {
|
|
184
|
+
await store.write(provider.namespace, `${flow.workspaceId}--${flow.sourceId}`, {
|
|
185
|
+
...tokens,
|
|
186
|
+
connectedAt: new Date().toISOString(),
|
|
187
|
+
...(flow.connectedBy ? { connectedBy: flow.connectedBy } : {}),
|
|
188
|
+
});
|
|
78
189
|
}
|
|
79
190
|
function renderCallbackPage(input) {
|
|
80
191
|
// Tiny self-contained HTML. Tells the popup opener and closes itself.
|
|
81
192
|
// Inline style so the page works without any asset pipeline.
|
|
82
193
|
const colour = input.ok ? '#16a34a' : '#dc2626';
|
|
83
194
|
const status = input.ok ? 'success' : 'error';
|
|
195
|
+
const heading = input.ok ? `Connected to ${input.provider.label}` : 'Authorization failed';
|
|
84
196
|
return `<!doctype html>
|
|
85
197
|
<html><head><meta charset="utf-8"><title>Braid OAuth</title>
|
|
86
198
|
<style>
|
|
@@ -91,11 +203,11 @@ function renderCallbackPage(input) {
|
|
|
91
203
|
</style>
|
|
92
204
|
</head><body>
|
|
93
205
|
<div class="card">
|
|
94
|
-
<h1>${
|
|
206
|
+
<h1>${heading}</h1>
|
|
95
207
|
<p>${escapeHtml(input.message)}</p>
|
|
96
208
|
</div>
|
|
97
209
|
<script>
|
|
98
|
-
try { window.opener?.postMessage({ source: 'braid-oauth', provider:
|
|
210
|
+
try { window.opener?.postMessage({ source: 'braid-oauth', provider: ${JSON.stringify(input.provider.id)}, status: ${JSON.stringify(status)} }, '*'); } catch (_e) {}
|
|
99
211
|
setTimeout(() => { try { window.close(); } catch (_e) {} }, 1500);
|
|
100
212
|
</script>
|
|
101
213
|
</body></html>`;
|
package/dist/routes/oauth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/routes/oauth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/routes/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PluginRegistry } from '@braidhq/core';
|
|
2
|
+
import { OpenAPIHono } from '@hono/zod-openapi';
|
|
3
|
+
export interface OntologiesRouterDeps {
|
|
4
|
+
pluginRegistry: PluginRegistry;
|
|
5
|
+
}
|
|
6
|
+
export declare function createOntologiesRouter(deps: OntologiesRouterDeps): OpenAPIHono;
|
|
7
|
+
//# sourceMappingURL=ontologies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ontologies.d.ts","sourceRoot":"","sources":["../../src/routes/ontologies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEnD,OAAO,EAAe,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE5D,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,cAAc,CAAA;CAC/B;AAgBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,WAAW,CAc9E"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { OntologyListResponse } from '@braidhq/schema';
|
|
2
|
+
import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
|
|
3
|
+
const listRoute = createRoute({
|
|
4
|
+
method: 'get',
|
|
5
|
+
path: '/',
|
|
6
|
+
operationId: 'listOntologies',
|
|
7
|
+
summary: 'List every registered ontology (node types, edge types, source roles).',
|
|
8
|
+
tags: ['ontology'],
|
|
9
|
+
responses: {
|
|
10
|
+
200: {
|
|
11
|
+
description: 'The registered ontologies.',
|
|
12
|
+
content: { 'application/json': { schema: OntologyListResponse } },
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
export function createOntologiesRouter(deps) {
|
|
17
|
+
const router = new OpenAPIHono();
|
|
18
|
+
router.openapi(listRoute, (context) => {
|
|
19
|
+
const ontologies = deps.pluginRegistry.ontologies().map(ontology => ({
|
|
20
|
+
ontologyId: ontology.ontologyId,
|
|
21
|
+
nodeTypes: ontology.nodeTypes,
|
|
22
|
+
edgeTypes: ontology.edgeTypes,
|
|
23
|
+
sourceRoles: ontology.sourceRoles,
|
|
24
|
+
}));
|
|
25
|
+
return context.json(OntologyListResponse.parse({ ontologies }), 200);
|
|
26
|
+
});
|
|
27
|
+
return router;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=ontologies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ontologies.js","sourceRoot":"","sources":["../../src/routes/ontologies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAM5D,MAAM,SAAS,GAAG,WAAW,CAAC;IAC5B,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,GAAG;IACT,WAAW,EAAE,gBAAgB;IAC7B,OAAO,EAAE,wEAAwE;IACjF,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,SAAS,EAAE;QACT,GAAG,EAAE;YACH,WAAW,EAAE,4BAA4B;YACzC,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,oBAAoB,EAAE,EAAE;SAClE;KACF;CACF,CAAC,CAAA;AAEF,MAAM,UAAU,sBAAsB,CAAC,IAA0B;IAC/D,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAA;IAEhC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACnE,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;SAClC,CAAC,CAAC,CAAA;QACH,OAAO,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,GAAG,CAAC,CAAA;IACtE,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ontology.d.ts","sourceRoot":"","sources":["../../src/routes/ontology.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAGxE,OAAO,EAAe,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAI5D,MAAM,WAAW,kBAAkB;IACjC,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,cAAc,EAAE,cAAc,CAAA;CAC/B;AAkBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"ontology.d.ts","sourceRoot":"","sources":["../../src/routes/ontology.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAGxE,OAAO,EAAe,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAI5D,MAAM,WAAW,kBAAkB;IACjC,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,cAAc,EAAE,cAAc,CAAA;CAC/B;AAkBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW,CAmB1E"}
|