ghagga-forge 3.1.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 -0
- package/dist/adapters/github/github-app-credential-provider.d.ts +102 -0
- package/dist/adapters/github/github-app-credential-provider.d.ts.map +1 -0
- package/dist/adapters/github/github-app-credential-provider.js +166 -0
- package/dist/adapters/github/github-app-credential-provider.js.map +1 -0
- package/dist/adapters/github/github-client-port.d.ts +92 -0
- package/dist/adapters/github/github-client-port.d.ts.map +1 -0
- package/dist/adapters/github/github-client-port.js +24 -0
- package/dist/adapters/github/github-client-port.js.map +1 -0
- package/dist/adapters/github/github-forge-adapter.d.ts +105 -0
- package/dist/adapters/github/github-forge-adapter.d.ts.map +1 -0
- package/dist/adapters/github/github-forge-adapter.js +225 -0
- package/dist/adapters/github/github-forge-adapter.js.map +1 -0
- package/dist/adapters/github/static-token-provider.d.ts +30 -0
- package/dist/adapters/github/static-token-provider.d.ts.map +1 -0
- package/dist/adapters/github/static-token-provider.js +35 -0
- package/dist/adapters/github/static-token-provider.js.map +1 -0
- package/dist/adapters/gitlab/gitlab-client-port.d.ts +82 -0
- package/dist/adapters/gitlab/gitlab-client-port.d.ts.map +1 -0
- package/dist/adapters/gitlab/gitlab-client-port.js +27 -0
- package/dist/adapters/gitlab/gitlab-client-port.js.map +1 -0
- package/dist/adapters/gitlab/gitlab-forge-adapter.d.ts +118 -0
- package/dist/adapters/gitlab/gitlab-forge-adapter.d.ts.map +1 -0
- package/dist/adapters/gitlab/gitlab-forge-adapter.js +238 -0
- package/dist/adapters/gitlab/gitlab-forge-adapter.js.map +1 -0
- package/dist/comment-id.d.ts +45 -0
- package/dist/comment-id.d.ts.map +1 -0
- package/dist/comment-id.js +48 -0
- package/dist/comment-id.js.map +1 -0
- package/dist/errors.d.ts +48 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +67 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/lint-boundary.d.ts +36 -0
- package/dist/lint-boundary.d.ts.map +1 -0
- package/dist/lint-boundary.impl.d.mts +41 -0
- package/dist/lint-boundary.impl.mjs +400 -0
- package/dist/lint-boundary.js +35 -0
- package/dist/lint-boundary.js.map +1 -0
- package/dist/ports/ci-runner.d.ts +48 -0
- package/dist/ports/ci-runner.d.ts.map +1 -0
- package/dist/ports/ci-runner.js +10 -0
- package/dist/ports/ci-runner.js.map +1 -0
- package/dist/ports/credential-provider.d.ts +32 -0
- package/dist/ports/credential-provider.d.ts.map +1 -0
- package/dist/ports/credential-provider.js +10 -0
- package/dist/ports/credential-provider.js.map +1 -0
- package/dist/ports/forge-adapter.d.ts +174 -0
- package/dist/ports/forge-adapter.d.ts.map +1 -0
- package/dist/ports/forge-adapter.js +34 -0
- package/dist/ports/forge-adapter.js.map +1 -0
- package/dist/ports/webhook-codec.d.ts +41 -0
- package/dist/ports/webhook-codec.d.ts.map +1 -0
- package/dist/ports/webhook-codec.js +18 -0
- package/dist/ports/webhook-codec.js.map +1 -0
- package/dist/project.d.ts +32 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +41 -0
- package/dist/project.js.map +1 -0
- package/dist/ref.d.ts +20 -0
- package/dist/ref.d.ts.map +1 -0
- package/dist/ref.js +21 -0
- package/dist/ref.js.map +1 -0
- package/dist/registry.d.ts +69 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +68 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +310 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The forge adapter port.
|
|
3
|
+
*
|
|
4
|
+
* A {@link ForgeAdapter} is what the core review engine talks to instead of any
|
|
5
|
+
* concrete forge SDK. {@link ForgeAdapterBase} is the mandatory surface every
|
|
6
|
+
* adapter MUST implement; optional capabilities are factored into discrete
|
|
7
|
+
* sub-interfaces composed onto the base via `Partial<>`.
|
|
8
|
+
*
|
|
9
|
+
* R-CAPABILITY (the load-bearing rule of this file):
|
|
10
|
+
* - Optional methods are guarded at runtime by METHOD PRESENCE
|
|
11
|
+
* (`'fetchGraph' in adapter`), NEVER by the {@link ForgeCapabilities} flags.
|
|
12
|
+
* - The `capabilities` field is a HINT for planning/UI only. A misconfigured
|
|
13
|
+
* flag must never cause a missing method to be invoked (TypeError) nor a
|
|
14
|
+
* present method to be skipped.
|
|
15
|
+
* - Sub-interfaces exist so that, once you DO narrow via `'m' in adapter`, TS
|
|
16
|
+
* gives you the full co-present method set of that capability (e.g. narrowing
|
|
17
|
+
* on `fetchGraph` co-presence is expressed by the {@link GraphReadCapable}
|
|
18
|
+
* interface owning BOTH graph methods).
|
|
19
|
+
* - Co-presence of the TWO graph methods is enforced AT THE TYPE LEVEL by the
|
|
20
|
+
* union `GraphReadCapable | { fetchGraph?: never; fetchGraphMetadata?: never }`
|
|
21
|
+
* in {@link ForgeAdapter}: an object may have BOTH graph methods or NEITHER,
|
|
22
|
+
* but never exactly one. (`Partial<GraphReadCapable>` would NOT enforce this —
|
|
23
|
+
* it would permit `fetchGraph` without `fetchGraphMetadata`.) Single-method
|
|
24
|
+
* capabilities stay `Partial<>` because co-presence is trivial for one method.
|
|
25
|
+
*/
|
|
26
|
+
import type { DependencyGraph, GraphMetadata } from 'ghagga-core';
|
|
27
|
+
import type { ChangedFile, ChangeRequest, ChangeRequestRef, CommentId, CommentMarker, Commit, ForgeCapabilities, PublishReport, RepoRef, UnifiedDiff, UpsertSummaryResult } from '../types.js';
|
|
28
|
+
/** Kinds of reactions an adapter may support. */
|
|
29
|
+
export declare const REACTION_KIND: {
|
|
30
|
+
readonly THUMBS_UP: "+1";
|
|
31
|
+
readonly THUMBS_DOWN: "-1";
|
|
32
|
+
readonly EYES: "eyes";
|
|
33
|
+
readonly ROCKET: "rocket";
|
|
34
|
+
readonly CONFUSED: "confused";
|
|
35
|
+
};
|
|
36
|
+
export type ReactionKind = (typeof REACTION_KIND)[keyof typeof REACTION_KIND];
|
|
37
|
+
/**
|
|
38
|
+
* A single line-anchored inline comment to publish.
|
|
39
|
+
*
|
|
40
|
+
* PUBLIC API (R-LEAK-PUBLISH). This shape is intentionally ANCHORABLE so the
|
|
41
|
+
* GitLab discussion API (and a future GitHub inline-review impl) can be satisfied
|
|
42
|
+
* WITHOUT a breaking change:
|
|
43
|
+
* - `path` + `line` + `side` cover the common single-revision anchor (GitHub maps
|
|
44
|
+
* `side` → LEFT/RIGHT; GitLab maps `side` → old_line/new_line).
|
|
45
|
+
* - `position` carries the GitLab diff-thread anchor (base/head/start SHAs +
|
|
46
|
+
* old/new line). When present, the GitLab v1 adapter USES it toward the
|
|
47
|
+
* discussions API for a true diff-thread; when absent it degrades to a
|
|
48
|
+
* `path:line` body-prefixed plain note.
|
|
49
|
+
* - `oldPath`/`newPath` make RENAMES representable (GitLab requires BOTH
|
|
50
|
+
* `position[old_path]` and `position[new_path]` for text diff notes). When
|
|
51
|
+
* unset the adapter falls back to `path` for both — correct for non-renamed
|
|
52
|
+
* files.
|
|
53
|
+
*/
|
|
54
|
+
export interface InlineComment {
|
|
55
|
+
/** File the comment anchors to (the post-change path for a renamed file). */
|
|
56
|
+
path: string;
|
|
57
|
+
/** Line number (in the diff's head/new revision unless `side` says otherwise). */
|
|
58
|
+
line: number;
|
|
59
|
+
/**
|
|
60
|
+
* Which side of the diff the line is on. `'new'` (default) → added/context
|
|
61
|
+
* line on the head revision; `'old'` → a line on the base revision.
|
|
62
|
+
*/
|
|
63
|
+
side?: 'old' | 'new';
|
|
64
|
+
/**
|
|
65
|
+
* Pre-change path, for a RENAMED file. GitLab text diff notes require both the
|
|
66
|
+
* old and new path; when set, the adapter sends `position[old_path]`. Defaults
|
|
67
|
+
* to `path` when unset.
|
|
68
|
+
*/
|
|
69
|
+
oldPath?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Post-change path, for a RENAMED file. Defaults to `path` when unset. Carried
|
|
72
|
+
* so a future impl never needs an API change to support renames.
|
|
73
|
+
*/
|
|
74
|
+
newPath?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Full GitLab-style diff-thread anchor. When present, the GitLab v1 adapter
|
|
77
|
+
* uses it toward the discussions API (`position[position_type]=text`, the three
|
|
78
|
+
* SHAs, plus `old_line`/`new_line`). When absent, the adapter degrades to a
|
|
79
|
+
* plain note carrying the `path:line` prefix in the body.
|
|
80
|
+
*/
|
|
81
|
+
position?: {
|
|
82
|
+
/** Merge-base / comparison base SHA (GitLab `position[base_sha]`). */
|
|
83
|
+
baseSha: string;
|
|
84
|
+
/** Head SHA of the change request (GitLab `position[head_sha]`). */
|
|
85
|
+
headSha: string;
|
|
86
|
+
/** Start SHA (GitLab `position[start_sha]`). */
|
|
87
|
+
startSha: string;
|
|
88
|
+
/** Line on the base revision (GitLab `position[old_line]`). */
|
|
89
|
+
oldLine?: number;
|
|
90
|
+
/** Line on the head revision (GitLab `position[new_line]`). */
|
|
91
|
+
newLine?: number;
|
|
92
|
+
};
|
|
93
|
+
/** Comment body (markdown). */
|
|
94
|
+
body: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Mandatory surface every forge adapter MUST implement.
|
|
98
|
+
*
|
|
99
|
+
* The methods here are the irreducible operations the review pipeline needs:
|
|
100
|
+
* read the diff, read change-request metadata, read the file list, read commits,
|
|
101
|
+
* and idempotently upsert the single summary comment.
|
|
102
|
+
*/
|
|
103
|
+
export interface ForgeAdapterBase {
|
|
104
|
+
/**
|
|
105
|
+
* Declarative capability hints. READONLY and HINT-ONLY — never use these as
|
|
106
|
+
* the runtime guard for an optional method (R-CAPABILITY).
|
|
107
|
+
*/
|
|
108
|
+
readonly capabilities: ForgeCapabilities;
|
|
109
|
+
/** Fetch the unified diff for a change request. */
|
|
110
|
+
fetchDiff(ref: ChangeRequestRef): Promise<UnifiedDiff>;
|
|
111
|
+
/** Fetch change-request metadata (head SHA, base branch, author). */
|
|
112
|
+
fetchChangeRequest(ref: ChangeRequestRef): Promise<ChangeRequest>;
|
|
113
|
+
/** Fetch the list of changed files. */
|
|
114
|
+
fetchFileList(ref: ChangeRequestRef): Promise<ChangedFile[]>;
|
|
115
|
+
/** Fetch the commits in the change request. */
|
|
116
|
+
fetchCommits(ref: ChangeRequestRef): Promise<Commit[]>;
|
|
117
|
+
/**
|
|
118
|
+
* Idempotently upsert the single GHAGGA summary comment.
|
|
119
|
+
*
|
|
120
|
+
* The `marker` identifies prior GHAGGA summary comments so they can be cleaned
|
|
121
|
+
* up; the result reports the surviving comment and any deleted stale ones.
|
|
122
|
+
*/
|
|
123
|
+
upsertSummaryComment(ref: ChangeRequestRef, body: string, marker: CommentMarker): Promise<UpsertSummaryResult>;
|
|
124
|
+
}
|
|
125
|
+
/** Optional: adapter can add reactions to comments. */
|
|
126
|
+
export interface ReactionCapable {
|
|
127
|
+
/** Add a reaction to a comment. */
|
|
128
|
+
addReaction(commentId: CommentId, reaction: ReactionKind): Promise<void>;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Optional: adapter can READ a dependency graph for a repo.
|
|
132
|
+
*
|
|
133
|
+
* R-GRAPH: this is the typed graph-READ seam. The two methods are co-present:
|
|
134
|
+
* {@link ForgeAdapter} composes this interface as an all-or-nothing union, so an
|
|
135
|
+
* adapter has BOTH methods or NEITHER — never exactly one. Graph WRITE is
|
|
136
|
+
* GitHub-only and
|
|
137
|
+
* is deliberately NOT part of the adapter surface (deferred to P5). Returns of
|
|
138
|
+
* `null` mean "no graph available" — distinct from "graph read unsupported"
|
|
139
|
+
* (which is method absence).
|
|
140
|
+
*/
|
|
141
|
+
export interface GraphReadCapable {
|
|
142
|
+
/** Read the full dependency graph, or null if none is available. */
|
|
143
|
+
fetchGraph(repo: RepoRef): Promise<DependencyGraph | null>;
|
|
144
|
+
/** Read graph metadata (freshness, size, …), or null if none is available. */
|
|
145
|
+
fetchGraphMetadata(repo: RepoRef): Promise<GraphMetadata | null>;
|
|
146
|
+
}
|
|
147
|
+
/** Optional: adapter can publish line-anchored inline comments. */
|
|
148
|
+
export interface InlineCapable {
|
|
149
|
+
/** Publish a batch of inline comments; partial success is reported. */
|
|
150
|
+
publishInline(ref: ChangeRequestRef, comments: InlineComment[]): Promise<PublishReport>;
|
|
151
|
+
}
|
|
152
|
+
/** Optional: adapter can extract a marker payload from a comment body. */
|
|
153
|
+
export interface MarkerExtractable {
|
|
154
|
+
/**
|
|
155
|
+
* Extract the payload embedded behind `marker` in `body`, or null if the
|
|
156
|
+
* marker is not present.
|
|
157
|
+
*/
|
|
158
|
+
extractMarker(body: string, marker: CommentMarker): string | null;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The full adapter type the engine consumes.
|
|
162
|
+
*
|
|
163
|
+
* Base is mandatory; single-method capabilities are `Partial<>`-composed so an
|
|
164
|
+
* adapter can implement any subset. The graph capability is composed as an
|
|
165
|
+
* all-or-nothing union so an adapter cannot have exactly one of the two graph
|
|
166
|
+
* methods (type-level co-presence; see R-GRAPH and the header note). Consumers
|
|
167
|
+
* MUST narrow optional capabilities via method-presence (`'fetchGraph' in
|
|
168
|
+
* adapter`) before calling — see R-CAPABILITY at the top of this file.
|
|
169
|
+
*/
|
|
170
|
+
export type ForgeAdapter = ForgeAdapterBase & Partial<ReactionCapable> & (GraphReadCapable | {
|
|
171
|
+
fetchGraph?: never;
|
|
172
|
+
fetchGraphMetadata?: never;
|
|
173
|
+
}) & Partial<InlineCapable> & Partial<MarkerExtractable>;
|
|
174
|
+
//# sourceMappingURL=forge-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forge-adapter.d.ts","sourceRoot":"","sources":["../../src/ports/forge-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The forge adapter port.
|
|
3
|
+
*
|
|
4
|
+
* A {@link ForgeAdapter} is what the core review engine talks to instead of any
|
|
5
|
+
* concrete forge SDK. {@link ForgeAdapterBase} is the mandatory surface every
|
|
6
|
+
* adapter MUST implement; optional capabilities are factored into discrete
|
|
7
|
+
* sub-interfaces composed onto the base via `Partial<>`.
|
|
8
|
+
*
|
|
9
|
+
* R-CAPABILITY (the load-bearing rule of this file):
|
|
10
|
+
* - Optional methods are guarded at runtime by METHOD PRESENCE
|
|
11
|
+
* (`'fetchGraph' in adapter`), NEVER by the {@link ForgeCapabilities} flags.
|
|
12
|
+
* - The `capabilities` field is a HINT for planning/UI only. A misconfigured
|
|
13
|
+
* flag must never cause a missing method to be invoked (TypeError) nor a
|
|
14
|
+
* present method to be skipped.
|
|
15
|
+
* - Sub-interfaces exist so that, once you DO narrow via `'m' in adapter`, TS
|
|
16
|
+
* gives you the full co-present method set of that capability (e.g. narrowing
|
|
17
|
+
* on `fetchGraph` co-presence is expressed by the {@link GraphReadCapable}
|
|
18
|
+
* interface owning BOTH graph methods).
|
|
19
|
+
* - Co-presence of the TWO graph methods is enforced AT THE TYPE LEVEL by the
|
|
20
|
+
* union `GraphReadCapable | { fetchGraph?: never; fetchGraphMetadata?: never }`
|
|
21
|
+
* in {@link ForgeAdapter}: an object may have BOTH graph methods or NEITHER,
|
|
22
|
+
* but never exactly one. (`Partial<GraphReadCapable>` would NOT enforce this —
|
|
23
|
+
* it would permit `fetchGraph` without `fetchGraphMetadata`.) Single-method
|
|
24
|
+
* capabilities stay `Partial<>` because co-presence is trivial for one method.
|
|
25
|
+
*/
|
|
26
|
+
/** Kinds of reactions an adapter may support. */
|
|
27
|
+
export const REACTION_KIND = {
|
|
28
|
+
THUMBS_UP: '+1',
|
|
29
|
+
THUMBS_DOWN: '-1',
|
|
30
|
+
EYES: 'eyes',
|
|
31
|
+
ROCKET: 'rocket',
|
|
32
|
+
CONFUSED: 'confused',
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=forge-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forge-adapter.js","sourceRoot":"","sources":["../../src/ports/forge-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAqBH,iDAAiD;AACjD,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;CACZ,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The forge webhook codec port (task 0.5) — INTERFACE SHAPE ONLY.
|
|
3
|
+
*
|
|
4
|
+
* Two-phase design:
|
|
5
|
+
* 1. identify(headers, raw) → cheap, pre-verification tenant routing. Returns
|
|
6
|
+
* a {@link TenantHint} (or null) so the host can pick the right secret /
|
|
7
|
+
* credentials before trusting anything.
|
|
8
|
+
* 2. verify(payload, headers, secret) → authenticate the payload signature.
|
|
9
|
+
* 3. parse(payload, headers) → normalize into a forge-agnostic {@link ForgeEvent}.
|
|
10
|
+
*
|
|
11
|
+
* NEEDS GUARD (P5): the verify-before-parse ordering guarantee is INTENTIONALLY
|
|
12
|
+
* DEFERRED to P5. This interface only declares the shape — it does NOT yet
|
|
13
|
+
* enforce, at the type level or runtime, that `verify` was called (and returned
|
|
14
|
+
* true) before `parse`. P5 will add that guard. Do NOT assume parse is safe to
|
|
15
|
+
* call on unverified input in the meantime.
|
|
16
|
+
*/
|
|
17
|
+
import type { ForgeEvent, TenantHint } from '../types.js';
|
|
18
|
+
/** Decodes and authenticates incoming forge webhooks. */
|
|
19
|
+
export interface ForgeWebhookCodec {
|
|
20
|
+
/**
|
|
21
|
+
* Phase 1: extract a tenant-routing hint WITHOUT trusting the payload.
|
|
22
|
+
*
|
|
23
|
+
* Runs before signature verification so the host can select the correct
|
|
24
|
+
* secret/credentials. Returns null when the webhook cannot be routed.
|
|
25
|
+
*/
|
|
26
|
+
identify(headers: Record<string, string>, raw: string): TenantHint | null;
|
|
27
|
+
/**
|
|
28
|
+
* Phase 2: verify the payload signature against `secret`.
|
|
29
|
+
*
|
|
30
|
+
* @returns true iff the payload is authentic.
|
|
31
|
+
*/
|
|
32
|
+
verify(payload: unknown, headers: Record<string, string>, secret: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Phase 3: normalize a (verified) payload into a forge-agnostic event.
|
|
35
|
+
*
|
|
36
|
+
* NEEDS GUARD (P5): nothing here yet enforces that {@link verify} succeeded
|
|
37
|
+
* first — that guard lands in P5.
|
|
38
|
+
*/
|
|
39
|
+
parse(payload: unknown, headers: Record<string, string>): ForgeEvent;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=webhook-codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-codec.d.ts","sourceRoot":"","sources":["../../src/ports/webhook-codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IAE1E;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAEnF;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC;CACtE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The forge webhook codec port (task 0.5) — INTERFACE SHAPE ONLY.
|
|
3
|
+
*
|
|
4
|
+
* Two-phase design:
|
|
5
|
+
* 1. identify(headers, raw) → cheap, pre-verification tenant routing. Returns
|
|
6
|
+
* a {@link TenantHint} (or null) so the host can pick the right secret /
|
|
7
|
+
* credentials before trusting anything.
|
|
8
|
+
* 2. verify(payload, headers, secret) → authenticate the payload signature.
|
|
9
|
+
* 3. parse(payload, headers) → normalize into a forge-agnostic {@link ForgeEvent}.
|
|
10
|
+
*
|
|
11
|
+
* NEEDS GUARD (P5): the verify-before-parse ordering guarantee is INTENTIONALLY
|
|
12
|
+
* DEFERRED to P5. This interface only declares the shape — it does NOT yet
|
|
13
|
+
* enforce, at the type level or runtime, that `verify` was called (and returned
|
|
14
|
+
* true) before `parse`. P5 will add that guard. Do NOT assume parse is safe to
|
|
15
|
+
* call on unverified input in the meantime.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=webhook-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-codec.js","sourceRoot":"","sources":["../../src/ports/webhook-codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanctioned projection helpers (task 0.6).
|
|
3
|
+
*
|
|
4
|
+
* These three functions are the ONLY blessed way to project forge-agnostic
|
|
5
|
+
* domain objects into the shapes the core review engine consumes. Centralizing
|
|
6
|
+
* the projections keeps the wrong-field bug class (R-PROJECTION) in exactly one
|
|
7
|
+
* auditable place.
|
|
8
|
+
*
|
|
9
|
+
* R-PROJECTION (load-bearing): {@link toCommitMessages} MUST map each commit's
|
|
10
|
+
* `.message`, NEVER its `.sha`. A `.sha` projection type-checks perfectly
|
|
11
|
+
* (both are `string`) yet silently feeds 40-char hashes to the LLM instead of
|
|
12
|
+
* commit messages — a correctness bug invisible to the type system. The unit
|
|
13
|
+
* test in `project.test.ts` pins `.message !== .sha` to catch any regression.
|
|
14
|
+
*/
|
|
15
|
+
import type { ReviewContext } from 'ghagga-core';
|
|
16
|
+
import type { ChangedFile, Commit } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Project commits into the commit-message strings the engine reviews.
|
|
19
|
+
*
|
|
20
|
+
* R-PROJECTION: maps `.message` (NOT `.sha`).
|
|
21
|
+
*/
|
|
22
|
+
export declare function toCommitMessages(commits: Commit[]): string[];
|
|
23
|
+
/** Project changed files into the flat path list the engine consumes. */
|
|
24
|
+
export declare function toFileList(files: ChangedFile[]): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Assemble the core {@link ReviewContext} from forge-agnostic inputs.
|
|
27
|
+
*
|
|
28
|
+
* Uses {@link toCommitMessages} and {@link toFileList} internally so the
|
|
29
|
+
* projection rules are applied consistently.
|
|
30
|
+
*/
|
|
31
|
+
export declare function toReviewContext(repoFullName: string, prNumber: number, commits: Commit[], files: ChangedFile[]): ReviewContext;
|
|
32
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE5D;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EAAE,EACjB,KAAK,EAAE,WAAW,EAAE,GACnB,aAAa,CAOf"}
|
package/dist/project.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanctioned projection helpers (task 0.6).
|
|
3
|
+
*
|
|
4
|
+
* These three functions are the ONLY blessed way to project forge-agnostic
|
|
5
|
+
* domain objects into the shapes the core review engine consumes. Centralizing
|
|
6
|
+
* the projections keeps the wrong-field bug class (R-PROJECTION) in exactly one
|
|
7
|
+
* auditable place.
|
|
8
|
+
*
|
|
9
|
+
* R-PROJECTION (load-bearing): {@link toCommitMessages} MUST map each commit's
|
|
10
|
+
* `.message`, NEVER its `.sha`. A `.sha` projection type-checks perfectly
|
|
11
|
+
* (both are `string`) yet silently feeds 40-char hashes to the LLM instead of
|
|
12
|
+
* commit messages — a correctness bug invisible to the type system. The unit
|
|
13
|
+
* test in `project.test.ts` pins `.message !== .sha` to catch any regression.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Project commits into the commit-message strings the engine reviews.
|
|
17
|
+
*
|
|
18
|
+
* R-PROJECTION: maps `.message` (NOT `.sha`).
|
|
19
|
+
*/
|
|
20
|
+
export function toCommitMessages(commits) {
|
|
21
|
+
return commits.map((commit) => commit.message);
|
|
22
|
+
}
|
|
23
|
+
/** Project changed files into the flat path list the engine consumes. */
|
|
24
|
+
export function toFileList(files) {
|
|
25
|
+
return files.map((file) => file.path);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Assemble the core {@link ReviewContext} from forge-agnostic inputs.
|
|
29
|
+
*
|
|
30
|
+
* Uses {@link toCommitMessages} and {@link toFileList} internally so the
|
|
31
|
+
* projection rules are applied consistently.
|
|
32
|
+
*/
|
|
33
|
+
export function toReviewContext(repoFullName, prNumber, commits, files) {
|
|
34
|
+
return {
|
|
35
|
+
repoFullName,
|
|
36
|
+
prNumber,
|
|
37
|
+
commitMessages: toCommitMessages(commits),
|
|
38
|
+
fileList: toFileList(files),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAiB;IAChD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,YAAoB,EACpB,QAAgB,EAChB,OAAiB,EACjB,KAAoB;IAEpB,OAAO;QACL,YAAY;QACZ,QAAQ;QACR,cAAc,EAAE,gBAAgB,CAAC,OAAO,CAAC;QACzC,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC;KAC5B,CAAC;AACJ,CAAC"}
|
package/dist/ref.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RepoRef identity helpers.
|
|
3
|
+
*
|
|
4
|
+
* R-COMMENTID family / IDENTITY RULE: two repositories are the same iff their
|
|
5
|
+
* `kind` AND `nativeId` match. `path` is a mutable human-friendly label (repos
|
|
6
|
+
* get renamed/transferred) and MUST NOT participate in identity comparison.
|
|
7
|
+
*/
|
|
8
|
+
import type { RepoRef } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Structural identity for {@link RepoRef}.
|
|
11
|
+
*
|
|
12
|
+
* Keys on `kind` + `nativeId` and DELIBERATELY ignores `path` (mutable label).
|
|
13
|
+
* This is the contract every consumer (registry, dedup, caching) relies on.
|
|
14
|
+
*
|
|
15
|
+
* @param a first repo reference.
|
|
16
|
+
* @param b second repo reference.
|
|
17
|
+
* @returns true iff `a` and `b` denote the same repository.
|
|
18
|
+
*/
|
|
19
|
+
export declare function repoRefEquals(a: RepoRef, b: RepoRef): boolean;
|
|
20
|
+
//# sourceMappingURL=ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../src/ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAE7D"}
|
package/dist/ref.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RepoRef identity helpers.
|
|
3
|
+
*
|
|
4
|
+
* R-COMMENTID family / IDENTITY RULE: two repositories are the same iff their
|
|
5
|
+
* `kind` AND `nativeId` match. `path` is a mutable human-friendly label (repos
|
|
6
|
+
* get renamed/transferred) and MUST NOT participate in identity comparison.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Structural identity for {@link RepoRef}.
|
|
10
|
+
*
|
|
11
|
+
* Keys on `kind` + `nativeId` and DELIBERATELY ignores `path` (mutable label).
|
|
12
|
+
* This is the contract every consumer (registry, dedup, caching) relies on.
|
|
13
|
+
*
|
|
14
|
+
* @param a first repo reference.
|
|
15
|
+
* @param b second repo reference.
|
|
16
|
+
* @returns true iff `a` and `b` denote the same repository.
|
|
17
|
+
*/
|
|
18
|
+
export function repoRefEquals(a, b) {
|
|
19
|
+
return a.kind === b.kind && a.nativeId === b.nativeId;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ref.js.map
|
package/dist/ref.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.js","sourceRoot":"","sources":["../src/ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,CAAU,EAAE,CAAU;IAClD,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The adapter registry (task 0.7).
|
|
3
|
+
*
|
|
4
|
+
* Resolves a {@link ForgeAdapter} from a {@link RepoRef} by its `kind`. A lookup
|
|
5
|
+
* miss is a TYPED failure (R-RESOLVE): {@link ForgeRegistry.resolve} throws
|
|
6
|
+
* {@link UnknownForgeError} rather than returning `undefined` and letting a
|
|
7
|
+
* caller blow up later on `undefined.fetchDiff(...)`.
|
|
8
|
+
*/
|
|
9
|
+
import type { ForgeAdapter } from './ports/forge-adapter.js';
|
|
10
|
+
import type { ForgeKind, RepoRef } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Optional diagnostic context attached to an {@link UnknownForgeError}.
|
|
13
|
+
*
|
|
14
|
+
* Purely additive — the error remains constructible with just a `kind`. When the
|
|
15
|
+
* registry raises it, it fills in the kinds it DOES know about (and the repo, if
|
|
16
|
+
* available) so the failure message is self-diagnosing instead of just naming
|
|
17
|
+
* the missing kind.
|
|
18
|
+
*/
|
|
19
|
+
export interface UnknownForgeErrorContext {
|
|
20
|
+
/** Forge kinds that DO have a registered adapter at throw time. */
|
|
21
|
+
registeredKinds?: readonly ForgeKind[];
|
|
22
|
+
/** The repo whose resolution failed, when available. */
|
|
23
|
+
repo?: RepoRef;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Thrown when the registry has no adapter registered for a repo's forge kind.
|
|
27
|
+
*
|
|
28
|
+
* R-RESOLVE: a typed, named error — callers can `instanceof`-narrow it instead
|
|
29
|
+
* of guessing why an adapter was `undefined`.
|
|
30
|
+
*/
|
|
31
|
+
export declare class UnknownForgeError extends Error {
|
|
32
|
+
/** The forge kind that had no registered adapter. */
|
|
33
|
+
readonly kind: ForgeKind;
|
|
34
|
+
/** Forge kinds that DID have a registered adapter at throw time, if known. */
|
|
35
|
+
readonly registeredKinds?: readonly ForgeKind[];
|
|
36
|
+
/** The repo whose resolution failed, if available. */
|
|
37
|
+
readonly repo?: RepoRef;
|
|
38
|
+
constructor(kind: ForgeKind, context?: UnknownForgeErrorContext);
|
|
39
|
+
}
|
|
40
|
+
/** Looks up forge adapters by forge kind. */
|
|
41
|
+
export interface ForgeRegistry {
|
|
42
|
+
/**
|
|
43
|
+
* Register an adapter for a forge kind. A later registration for the same kind
|
|
44
|
+
* overrides the earlier one.
|
|
45
|
+
*/
|
|
46
|
+
register(kind: ForgeKind, adapter: ForgeAdapter): void;
|
|
47
|
+
/** Whether an adapter is registered for `kind`. */
|
|
48
|
+
has(kind: ForgeKind): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the adapter for `repo.kind`.
|
|
51
|
+
*
|
|
52
|
+
* @throws {UnknownForgeError} when no adapter is registered for the kind.
|
|
53
|
+
*/
|
|
54
|
+
resolve(repo: RepoRef): ForgeAdapter;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* In-memory {@link ForgeRegistry}.
|
|
58
|
+
*
|
|
59
|
+
* The default registry implementation: a simple `Map` keyed by forge kind.
|
|
60
|
+
* `resolve` is where R-RESOLVE lives — a miss throws {@link UnknownForgeError},
|
|
61
|
+
* never returns `undefined`.
|
|
62
|
+
*/
|
|
63
|
+
export declare class MapForgeRegistry implements ForgeRegistry {
|
|
64
|
+
private readonly adapters;
|
|
65
|
+
register(kind: ForgeKind, adapter: ForgeAdapter): void;
|
|
66
|
+
has(kind: ForgeKind): boolean;
|
|
67
|
+
resolve(repo: RepoRef): ForgeAdapter;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,eAAe,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,wDAAwD;IACxD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,qDAAqD;IACrD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAChD,sDAAsD;IACtD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;gBAEZ,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,wBAAwB;CAoBhE;AAED,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAEvD,mDAAmD;IACnD,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAE9B;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,CAAC;CACtC;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAE/D,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAItD,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO;IAI7B,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY;CAUrC"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The adapter registry (task 0.7).
|
|
3
|
+
*
|
|
4
|
+
* Resolves a {@link ForgeAdapter} from a {@link RepoRef} by its `kind`. A lookup
|
|
5
|
+
* miss is a TYPED failure (R-RESOLVE): {@link ForgeRegistry.resolve} throws
|
|
6
|
+
* {@link UnknownForgeError} rather than returning `undefined` and letting a
|
|
7
|
+
* caller blow up later on `undefined.fetchDiff(...)`.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Thrown when the registry has no adapter registered for a repo's forge kind.
|
|
11
|
+
*
|
|
12
|
+
* R-RESOLVE: a typed, named error — callers can `instanceof`-narrow it instead
|
|
13
|
+
* of guessing why an adapter was `undefined`.
|
|
14
|
+
*/
|
|
15
|
+
export class UnknownForgeError extends Error {
|
|
16
|
+
/** The forge kind that had no registered adapter. */
|
|
17
|
+
kind;
|
|
18
|
+
/** Forge kinds that DID have a registered adapter at throw time, if known. */
|
|
19
|
+
registeredKinds;
|
|
20
|
+
/** The repo whose resolution failed, if available. */
|
|
21
|
+
repo;
|
|
22
|
+
constructor(kind, context) {
|
|
23
|
+
const known = context?.registeredKinds;
|
|
24
|
+
const knownSuffix = known === undefined
|
|
25
|
+
? ''
|
|
26
|
+
: known.length === 0
|
|
27
|
+
? ' (no adapters are registered)'
|
|
28
|
+
: ` (registered: ${known.map((k) => `"${k}"`).join(', ')})`;
|
|
29
|
+
super(`No forge adapter registered for kind "${kind}"${knownSuffix}`);
|
|
30
|
+
this.name = 'UnknownForgeError';
|
|
31
|
+
this.kind = kind;
|
|
32
|
+
if (context?.registeredKinds !== undefined) {
|
|
33
|
+
this.registeredKinds = context.registeredKinds;
|
|
34
|
+
}
|
|
35
|
+
if (context?.repo !== undefined) {
|
|
36
|
+
this.repo = context.repo;
|
|
37
|
+
}
|
|
38
|
+
// Preserve prototype chain across down-level transpilation targets.
|
|
39
|
+
Object.setPrototypeOf(this, UnknownForgeError.prototype);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* In-memory {@link ForgeRegistry}.
|
|
44
|
+
*
|
|
45
|
+
* The default registry implementation: a simple `Map` keyed by forge kind.
|
|
46
|
+
* `resolve` is where R-RESOLVE lives — a miss throws {@link UnknownForgeError},
|
|
47
|
+
* never returns `undefined`.
|
|
48
|
+
*/
|
|
49
|
+
export class MapForgeRegistry {
|
|
50
|
+
adapters = new Map();
|
|
51
|
+
register(kind, adapter) {
|
|
52
|
+
this.adapters.set(kind, adapter);
|
|
53
|
+
}
|
|
54
|
+
has(kind) {
|
|
55
|
+
return this.adapters.has(kind);
|
|
56
|
+
}
|
|
57
|
+
resolve(repo) {
|
|
58
|
+
const adapter = this.adapters.get(repo.kind);
|
|
59
|
+
if (adapter === undefined) {
|
|
60
|
+
throw new UnknownForgeError(repo.kind, {
|
|
61
|
+
registeredKinds: [...this.adapters.keys()],
|
|
62
|
+
repo,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return adapter;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoBH;;;;;GAKG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,qDAAqD;IAC5C,IAAI,CAAY;IACzB,8EAA8E;IACrE,eAAe,CAAwB;IAChD,sDAAsD;IAC7C,IAAI,CAAW;IAExB,YAAY,IAAe,EAAE,OAAkC;QAC7D,MAAM,KAAK,GAAG,OAAO,EAAE,eAAe,CAAC;QACvC,MAAM,WAAW,GACf,KAAK,KAAK,SAAS;YACjB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;gBAClB,CAAC,CAAC,+BAA+B;gBACjC,CAAC,CAAC,iBAAiB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAClE,KAAK,CAAC,yCAAyC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,EAAE,eAAe,KAAK,SAAS,EAAE,CAAC;YAC3C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;QACjD,CAAC;QACD,IAAI,OAAO,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3B,CAAC;QACD,oEAAoE;QACpE,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC3D,CAAC;CACF;AAqBD;;;;;;GAMG;AACH,MAAM,OAAO,gBAAgB;IACV,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAE/D,QAAQ,CAAC,IAAe,EAAE,OAAqB;QAC7C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAAC,IAAe;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,CAAC,IAAa;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE;gBACrC,eAAe,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC1C,IAAI;aACL,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|