@alpacakit/integrations 0.1.0-beta.30 → 0.1.0-beta.35

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/README.md CHANGED
@@ -7,7 +7,13 @@ keyring support, and test fakes are isolated under subpath exports.
7
7
 
8
8
  Repository setup is split into two provider-owned contracts:
9
9
  `RepositoryScopeAdapter` applies provider-neutral repository updates to typed
10
- connection settings and projects them back to a repository reference, while
11
- the connection-level `RepositoryHost` finds or creates repositories.
10
+ connection settings and projects them back to one `RepositoryScope` containing
11
+ the repository reference and canonical provider base URL, while the
12
+ connection-level `RepositoryHost` finds or creates repositories.
12
13
  Repository-scoped issue, pull-request, and file operations remain on
13
14
  `Repository`.
15
+
16
+ Hosts that must end outstanding provider I/O explicitly can supply
17
+ `createAbortableHttpClient()` through the runtime's `ports.http` option and
18
+ call `close()` during shutdown. `parseRepositoryRef()` parses the shared
19
+ `owner/name` model, preserving nested owner paths such as GitLab groups.
@@ -0,0 +1,17 @@
1
+ import type { HttpClient } from "./ports.js";
2
+ export declare const ABORTABLE_HTTP_CLIENT_CLOSED_MESSAGE = "Integration HTTP client is closed.";
3
+ export interface AbortableHttpClient extends HttpClient {
4
+ /** Aborts every in-flight request and refuses new requests. */
5
+ close(): void;
6
+ readonly isClosed: boolean;
7
+ }
8
+ export type AbortableHttpClientOptions = {
9
+ readonly fetch?: HttpClient["fetch"];
10
+ readonly requestDeadlineMs?: number;
11
+ };
12
+ /**
13
+ * A host-owned HTTP client whose lifetime can end independently of the
14
+ * integration runtime using it.
15
+ */
16
+ export declare function createAbortableHttpClient(options?: AbortableHttpClientOptions): AbortableHttpClient;
17
+ //# sourceMappingURL=abortable-http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abortable-http-client.d.ts","sourceRoot":"","sources":["../src/abortable-http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,oCAAoC,uCACX,CAAC;AAEvC,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD,+DAA+D;IAC/D,KAAK,IAAI,IAAI,CAAC;IACd,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IACrC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,mBAAmB,CA6BrB"}
@@ -0,0 +1,32 @@
1
+ export const ABORTABLE_HTTP_CLIENT_CLOSED_MESSAGE = "Integration HTTP client is closed.";
2
+ /**
3
+ * A host-owned HTTP client whose lifetime can end independently of the
4
+ * integration runtime using it.
5
+ */
6
+ export function createAbortableHttpClient(options = {}) {
7
+ const send = options.fetch ?? globalThis.fetch;
8
+ const lifetime = new AbortController();
9
+ return {
10
+ get isClosed() {
11
+ return lifetime.signal.aborted;
12
+ },
13
+ fetch: async (url, init) => {
14
+ if (lifetime.signal.aborted) {
15
+ throw new Error(ABORTABLE_HTTP_CLIENT_CLOSED_MESSAGE);
16
+ }
17
+ const deadlineSignal = options.requestDeadlineMs === undefined
18
+ ? null
19
+ : AbortSignal.timeout(options.requestDeadlineMs);
20
+ const signals = [init?.signal, deadlineSignal, lifetime.signal].filter((signal) => signal !== null && signal !== undefined);
21
+ return await send(url, {
22
+ ...init,
23
+ signal: AbortSignal.any(signals),
24
+ });
25
+ },
26
+ close: () => {
27
+ if (lifetime.signal.aborted)
28
+ return;
29
+ lifetime.abort(new Error(ABORTABLE_HTTP_CLIENT_CLOSED_MESSAGE));
30
+ },
31
+ };
32
+ }
package/dist/auth.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import type { SecretRef, ValueOf } from "@alpacakit/core";
2
2
  import type { IntegrationAuthProfileId, IntegrationId } from "./ids.js";
3
3
  import type { SecretResolvers, SessionPorts } from "./ports.js";
4
- import type { INTEGRATION_AUTH_BINDING_KIND } from "./values.js";
5
- import { AUTHORIZATION_KIND, INTEGRATION_AUTH_MATERIAL_KIND } from "./values.js";
4
+ import { AUTHORIZATION_KIND, INTEGRATION_AUTH_BINDING_KIND, INTEGRATION_AUTH_MATERIAL_KIND } from "./values.js";
6
5
  export type { SecretRef } from "@alpacakit/core";
7
6
  export type IntegrationAuthMaterial = {
8
7
  readonly kind: typeof INTEGRATION_AUTH_MATERIAL_KIND.apiKey;
@@ -31,6 +30,7 @@ export type IntegrationAuthBinding = {
31
30
  } | {
32
31
  readonly kind: typeof INTEGRATION_AUTH_BINDING_KIND.anonymous;
33
32
  };
33
+ export declare function sameIntegrationAuthBinding(left: IntegrationAuthBinding, right: IntegrationAuthBinding): boolean;
34
34
  export type IntegrationAuthProfile = {
35
35
  readonly id: IntegrationAuthProfileId;
36
36
  readonly integrationId: IntegrationId;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/auth.js CHANGED
@@ -1,7 +1,15 @@
1
1
  import { AUTH_FAILURE_REASON, INTEGRATION_ERROR_CODE, IntegrationError, } from "./error.js";
2
- import { AUTHORIZATION_KIND, AUTHORIZATION_SCHEME, INTEGRATION_AUTH_MATERIAL_KIND, } from "./values.js";
2
+ import { AUTHORIZATION_KIND, AUTHORIZATION_SCHEME, INTEGRATION_AUTH_BINDING_KIND, INTEGRATION_AUTH_MATERIAL_KIND, } from "./values.js";
3
3
  const UTF8_ENCODING = "utf8";
4
4
  const BASE64_ENCODING = "base64";
5
+ export function sameIntegrationAuthBinding(left, right) {
6
+ if (left.kind !== right.kind)
7
+ return false;
8
+ return left.kind !== INTEGRATION_AUTH_BINDING_KIND.profile
9
+ ? true
10
+ : right.kind === INTEGRATION_AUTH_BINDING_KIND.profile &&
11
+ left.profileId === right.profileId;
12
+ }
5
13
  export async function requireSecret(resolvers, ref) {
6
14
  const resolver = resolvers[ref.resolver];
7
15
  if (resolver === undefined) {
package/dist/catalog.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { type JsonObject } from "@alpacakit/core";
2
- import type { IntegrationDefinition, IntegrationSettingsInput } from "./definition.js";
2
+ import type { IntegrationDefinition, IntegrationSettingsInput, RepositoryRemoteResolution, RepositoryScope } from "./definition.js";
3
3
  import type { IntegrationId } from "./ids.js";
4
- import type { RepositoryRef } from "./model.js";
5
4
  type AnyDefinition = IntegrationDefinition<IntegrationId, any, any>;
6
5
  export interface IntegrationDefinitionCatalog {
7
6
  resolveSettings(integration: IntegrationId, current: JsonObject | null, input: IntegrationSettingsInput): JsonObject;
8
- projectRepository(integration: IntegrationId, settings: JsonObject): RepositoryRef;
7
+ projectRepositoryScope(integration: IntegrationId, settings: JsonObject): RepositoryScope;
8
+ resolveRepositoryRemote(integration: IntegrationId, remoteUrl: string): RepositoryRemoteResolution;
9
9
  }
10
10
  export declare function createIntegrationDefinitionCatalog(definitions: readonly AnyDefinition[]): IntegrationDefinitionCatalog;
11
11
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,KAAK,EACV,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOhD,KAAK,aAAa,GAAG,qBAAqB,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEpE,MAAM,WAAW,4BAA4B;IAC3C,eAAe,CACb,WAAW,EAAE,aAAa,EAC1B,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,KAAK,EAAE,wBAAwB,GAC9B,UAAU,CAAC;IACd,iBAAiB,CACf,WAAW,EAAE,aAAa,EAC1B,QAAQ,EAAE,UAAU,GACnB,aAAa,CAAC;CAClB;AAED,wBAAgB,kCAAkC,CAChD,WAAW,EAAE,SAAS,aAAa,EAAE,GACpC,4BAA4B,CAE9B"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,KAAK,EACV,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,EAC1B,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQ9C,KAAK,aAAa,GAAG,qBAAqB,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEpE,MAAM,WAAW,4BAA4B;IAC3C,eAAe,CACb,WAAW,EAAE,aAAa,EAC1B,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,KAAK,EAAE,wBAAwB,GAC9B,UAAU,CAAC;IACd,sBAAsB,CACpB,WAAW,EAAE,aAAa,EAC1B,QAAQ,EAAE,UAAU,GACnB,eAAe,CAAC;IACnB,uBAAuB,CACrB,WAAW,EAAE,aAAa,EAC1B,SAAS,EAAE,MAAM,GAChB,0BAA0B,CAAC;CAC/B;AAED,wBAAgB,kCAAkC,CAChD,WAAW,EAAE,SAAS,aAAa,EAAE,GACpC,4BAA4B,CAE9B"}
package/dist/catalog.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CODEC_DECODE_RESULT_KIND } from "@alpacakit/core";
2
2
  import { INTEGRATION_ERROR_CODE, IntegrationError } from "./error.js";
3
- import { INTEGRATION_SETTINGS_INPUT_KIND, REPOSITORY_SETTINGS_UPDATE_KIND, } from "./values.js";
3
+ import { INTEGRATION_SETTINGS_INPUT_KIND, REPOSITORY_REMOTE_RESOLUTION_KIND, REPOSITORY_SETTINGS_UPDATE_KIND, } from "./values.js";
4
4
  export function createIntegrationDefinitionCatalog(definitions) {
5
5
  return new DefaultIntegrationDefinitionCatalog(definitions);
6
6
  }
@@ -39,13 +39,20 @@ class DefaultIntegrationDefinitionCatalog {
39
39
  this.decodeSettings(definition, settings);
40
40
  return settings;
41
41
  }
42
- projectRepository(id, settings) {
42
+ projectRepositoryScope(id, settings) {
43
43
  const definition = this.requireDefinition(id);
44
44
  const adapter = definition.repositoryScope;
45
45
  if (adapter === undefined) {
46
46
  throw unsupported(definition.id, "repository settings");
47
47
  }
48
- return adapter.projectRepository(this.decodeSettings(definition, settings));
48
+ return adapter.project(this.decodeSettings(definition, settings));
49
+ }
50
+ resolveRepositoryRemote(id, remoteUrl) {
51
+ const definition = this.requireDefinition(id);
52
+ const adapter = definition.repositoryScope;
53
+ return adapter === undefined
54
+ ? { kind: REPOSITORY_REMOTE_RESOLUTION_KIND.unmatched }
55
+ : adapter.resolveRemote(remoteUrl);
49
56
  }
50
57
  requireDefinition(id) {
51
58
  const definition = this.definitions.get(id);
@@ -1 +1 @@
1
- {"version":3,"file":"gitea.d.ts","sourceRoot":"","sources":["../../src/code-hosts/gitea.ts"],"names":[],"mappings":"AAiCA,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,aAAa,CAAC;AA2BrB,eAAO,MAAM,oBAAoB,2DAAyB,CAAC;AAO3D,eAAO,MAAM,oBAAoB,6DAGvB,CAAC;AACX,eAAO,MAAM,2BAA2B;;;CAGA,CAAC;AAEzC,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAwBF,wBAAgB,KAAK,gJAuDpB"}
1
+ {"version":3,"file":"gitea.d.ts","sourceRoot":"","sources":["../../src/code-hosts/gitea.ts"],"names":[],"mappings":"AAqCA,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,aAAa,CAAC;AAuBrB,eAAO,MAAM,oBAAoB,2DAAyB,CAAC;AAO3D,eAAO,MAAM,oBAAoB,6DAGvB,CAAC;AACX,eAAO,MAAM,2BAA2B;;;CAGA,CAAC;AAEzC,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAiIF,wBAAgB,KAAK,gJAqDpB"}
@@ -2,16 +2,16 @@
2
2
  import { createSchemaRuntimeCodec } from "@alpacakit/core";
3
3
  import { z } from "zod";
4
4
  import { bearerMaterialHandlers } from "../auth.js";
5
- import { defineIntegration } from "../definition.js";
5
+ import { defineIntegration, } from "../definition.js";
6
6
  import { INTEGRATION_ERROR_CODE, IntegrationError, isIntegrationError, } from "../error.js";
7
7
  import { integrationId } from "../ids.js";
8
8
  import { collectPaginated } from "../transport/collect.js";
9
9
  import { HttpTransport } from "../transport/http-transport.js";
10
10
  import { LinkHeaderPager } from "../transport/pager.js";
11
- import { AUTHORIZATION_SCHEME, GIT_PROTOCOL, HTTP_METHOD, MERGE_METHOD, OWNER_KIND, PULL_REQUEST_STATE, REPOSITORY_SETTINGS_UPDATE_KIND, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_STATE, } from "../values.js";
11
+ import { AUTHORIZATION_SCHEME, GIT_PROTOCOL, HTTP_METHOD, MERGE_METHOD, OWNER_KIND, PULL_REQUEST_STATE, REPOSITORY_REMOTE_RESOLUTION_KIND, REPOSITORY_SETTINGS_UPDATE_KIND, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_STATE, } from "../values.js";
12
12
  import { createCodeHostAccount, createCodeHostRepository, createCodeHostRepositoryHost, createCodeHostWorkItems, probeCodeHostDoctor, } from "./facets.js";
13
13
  import { projectGiteaPullRequestStatus, readGiteaPullRequest, readGiteaPullRequestReviews, readGiteaPullRequestSnapshot, } from "./gitea-pull-request-snapshot.js";
14
- import { ambientToken, matchesRemote, orgOrUserRepositoryRequest, } from "./helpers.js";
14
+ import { ambientToken, orgOrUserRepositoryRequest } from "./helpers.js";
15
15
  import { normalizeDependencyIssue } from "./normalize.js";
16
16
  import { rawGiteaDependencyListCodec, rawGiteaLabelCodec, rawGiteaLabelListCodec, } from "./schemas.js";
17
17
  import { CODE_HOST_CHANGE_FEED_KIND, refNumber } from "./strategy.js";
@@ -50,12 +50,92 @@ const settingsSchema = z
50
50
  baseUrl: settings.baseUrl.replace(/\/$/, ""),
51
51
  }));
52
52
  const cursorCodec = createTimestampChangeFeedCursorCodec(GITEA_INTEGRATION_ID);
53
+ function resolveGiteaRemote(remoteUrl) {
54
+ const parsed = parseCanonicalHttpUrl(remoteUrl);
55
+ if (parsed.kind === REPOSITORY_REMOTE_RESOLUTION_KIND.rejected)
56
+ return parsed;
57
+ if (parsed.segments.length < 2) {
58
+ return rejectedRemote("Gitea remote path must end with an owner and repository.");
59
+ }
60
+ const repositorySegment = parsed.segments.at(-1);
61
+ const repository = repositorySegment.endsWith(".git")
62
+ ? repositorySegment.slice(0, -4)
63
+ : repositorySegment;
64
+ const owner = parsed.segments.at(-2);
65
+ if (repository.length === 0) {
66
+ return rejectedRemote("Gitea remote repository must not be empty.");
67
+ }
68
+ const installationPath = parsed.segments.slice(0, -2);
69
+ return {
70
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.matched,
71
+ repository: { owner, name: repository },
72
+ baseUrl: canonicalHttpUrl(parsed.origin, installationPath),
73
+ };
74
+ }
75
+ function parseCanonicalHttpUrl(remoteUrl) {
76
+ let url;
77
+ try {
78
+ url = new URL(remoteUrl);
79
+ }
80
+ catch {
81
+ return rejectedRemote("Gitea remote must be an absolute HTTP(S) URL.");
82
+ }
83
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
84
+ return rejectedRemote("Gitea remote must use HTTP or HTTPS.");
85
+ }
86
+ if (url.username !== "" ||
87
+ url.password !== "" ||
88
+ url.search !== "" ||
89
+ url.hash !== "") {
90
+ return rejectedRemote("Gitea remote must not contain credentials, a query, or a fragment.");
91
+ }
92
+ const encodedSegments = url.pathname === "/" ? [] : url.pathname.split("/").slice(1);
93
+ if (encodedSegments.some((segment) => segment.length === 0)) {
94
+ return rejectedRemote("Gitea remote path contains an empty segment.");
95
+ }
96
+ const segments = [];
97
+ for (const encoded of encodedSegments) {
98
+ let segment;
99
+ try {
100
+ segment = decodeURIComponent(encoded);
101
+ }
102
+ catch {
103
+ return rejectedRemote("Gitea remote path contains invalid encoding.");
104
+ }
105
+ if (segment === "." ||
106
+ segment === ".." ||
107
+ segment.includes("/") ||
108
+ segment.includes("\\")) {
109
+ return rejectedRemote("Gitea remote path contains an unsafe segment.");
110
+ }
111
+ segments.push(segment);
112
+ }
113
+ return {
114
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.matched,
115
+ origin: url.origin,
116
+ segments,
117
+ };
118
+ }
119
+ function canonicalHttpUrl(origin, segments) {
120
+ return segments.length === 0
121
+ ? origin
122
+ : `${origin}/${segments.map((segment) => encodeURIComponent(segment)).join("/")}`;
123
+ }
124
+ function canonicalGiteaBaseUrl(baseUrl) {
125
+ const parsed = parseCanonicalHttpUrl(baseUrl);
126
+ return parsed.kind === REPOSITORY_REMOTE_RESOLUTION_KIND.rejected
127
+ ? null
128
+ : canonicalHttpUrl(parsed.origin, parsed.segments);
129
+ }
130
+ function rejectedRemote(detail) {
131
+ return { kind: REPOSITORY_REMOTE_RESOLUTION_KIND.rejected, detail };
132
+ }
53
133
  export function gitea() {
54
134
  return defineIntegration({
55
135
  id: GITEA_INTEGRATION_ID,
56
136
  settingsCodec: createSchemaRuntimeCodec(settingsSchema),
57
- remoteMatch: (remoteUrl, settings) => matchesRemote(remoteUrl, new URL(settings.baseUrl).hostname, `${settings.owner}/${settings.repository}`),
58
137
  repositoryScope: {
138
+ resolveRemote: resolveGiteaRemote,
59
139
  applySettings: (input) => {
60
140
  if (input.kind === REPOSITORY_SETTINGS_UPDATE_KIND.baseUrl) {
61
141
  return {
@@ -71,9 +151,12 @@ export function gitea() {
71
151
  ...(baseUrl === undefined ? {} : { baseUrl }),
72
152
  };
73
153
  },
74
- projectRepository: (settings) => ({
75
- owner: settings.owner,
76
- name: settings.repository,
154
+ project: (settings) => ({
155
+ repository: {
156
+ owner: settings.owner,
157
+ name: settings.repository,
158
+ },
159
+ baseUrl: canonicalGiteaBaseUrl(settings.baseUrl) ?? settings.baseUrl,
77
160
  }),
78
161
  },
79
162
  auth: {
@@ -1 +1 @@
1
- {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/code-hosts/github.ts"],"names":[],"mappings":"AAkCA,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,aAAa,CAAC;AAuBrB,eAAO,MAAM,qBAAqB,4DAA0B,CAAC;AA8B7D,eAAO,MAAM,qBAAqB,qCAAsC,CAAC;AACzE,eAAO,MAAM,4BAA4B;;;CAGD,CAAC;AAEzC,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AA0IF,wBAAgB,MAAM,kJAkErB"}
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/code-hosts/github.ts"],"names":[],"mappings":"AAsCA,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,aAAa,CAAC;AAuBrB,eAAO,MAAM,qBAAqB,4DAA0B,CAAC;AA8B7D,eAAO,MAAM,qBAAqB,qCAAsC,CAAC;AACzE,eAAO,MAAM,4BAA4B;;;CAGD,CAAC;AAEzC,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AA6LF,wBAAgB,MAAM,kJA4DrB"}
@@ -2,16 +2,16 @@
2
2
  import { createSchemaRuntimeCodec } from "@alpacakit/core";
3
3
  import { z } from "zod";
4
4
  import { bearerMaterialHandlers } from "../auth.js";
5
- import { defineIntegration } from "../definition.js";
5
+ import { defineIntegration, } from "../definition.js";
6
6
  import { INTEGRATION_ERROR_CODE, IntegrationError } from "../error.js";
7
7
  import { integrationId } from "../ids.js";
8
8
  import { collectPaginated } from "../transport/collect.js";
9
9
  import { HttpTransport } from "../transport/http-transport.js";
10
10
  import { LinkHeaderPager } from "../transport/pager.js";
11
- import { AUTHORIZATION_SCHEME, COMMENT_KIND, GIT_PROTOCOL, HTTP_METHOD, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_STATE, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_QUERY_STATE, WORK_ITEM_STATE, } from "../values.js";
11
+ import { AUTHORIZATION_SCHEME, COMMENT_KIND, GIT_PROTOCOL, HTTP_METHOD, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_STATE, REPOSITORY_REMOTE_RESOLUTION_KIND, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_QUERY_STATE, WORK_ITEM_STATE, } from "../values.js";
12
12
  import { createCodeHostAccount, createCodeHostRepository, createCodeHostRepositoryHost, createCodeHostWorkItems, probeCodeHostDoctor, } from "./facets.js";
13
13
  import { githubDeviceLogin } from "./github-login.js";
14
- import { ambientToken, matchesRemote, orgOrUserRepositoryRequest, } from "./helpers.js";
14
+ import { ambientToken, orgOrUserRepositoryRequest, parseGitRemote, } from "./helpers.js";
15
15
  import { normalizeDependencyIssue } from "./normalize.js";
16
16
  import { rawDependencyIssueListCodec, rawPullRequestCodec, rawReactionListCodec, rawWorkItemCodec, } from "./schemas.js";
17
17
  import { CODE_HOST_CHANGE_FEED_KIND, refNumber } from "./strategy.js";
@@ -65,7 +65,7 @@ const githubSettingsSchema = z
65
65
  .transform((settings) => ({
66
66
  owner: settings.owner,
67
67
  repository: settings.repository,
68
- baseUrl: settings.baseUrl ?? GITHUB_API_URL,
68
+ baseUrl: (settings.baseUrl ?? GITHUB_API_URL).replace(/\/$/, ""),
69
69
  }));
70
70
  const cursorCodec = createTimestampChangeFeedCursorCodec(GITHUB_INTEGRATION_ID);
71
71
  const githubPullRequestStatusCodec = createSchemaRuntimeCodec(z
@@ -165,18 +165,59 @@ const githubLinkedBranchMutationCodec = createSchemaRuntimeCodec(z
165
165
  .strip(),
166
166
  })
167
167
  .strip());
168
+ function resolveGitHubBaseUrls(input) {
169
+ if ("webOrigin" in input) {
170
+ return input.webOrigin === "https://github.com"
171
+ ? { webOrigin: input.webOrigin, apiBaseUrl: GITHUB_API_URL }
172
+ : {
173
+ webOrigin: input.webOrigin,
174
+ apiBaseUrl: `${input.webOrigin}/api/v3`,
175
+ };
176
+ }
177
+ const apiBaseUrl = new URL(input.apiBaseUrl).toString().replace(/\/$/u, "");
178
+ return apiBaseUrl === GITHUB_API_URL
179
+ ? { webOrigin: "https://github.com", apiBaseUrl }
180
+ : {
181
+ webOrigin: apiBaseUrl.replace(/\/api\/v3\/?$/u, ""),
182
+ apiBaseUrl,
183
+ };
184
+ }
185
+ function resolveGitHubRemote(remoteUrl) {
186
+ const parsed = parseGitRemote(remoteUrl);
187
+ if (parsed.kind === "rejected") {
188
+ return {
189
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.rejected,
190
+ detail: `GitHub remote ${parsed.detail}.`,
191
+ };
192
+ }
193
+ if (parsed.pathSegments.length !== 2) {
194
+ return {
195
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.rejected,
196
+ detail: "GitHub remote path must contain an owner and repository.",
197
+ };
198
+ }
199
+ const [owner, repositorySegment] = parsed.pathSegments;
200
+ const repository = repositorySegment.endsWith(".git")
201
+ ? repositorySegment.slice(0, -4)
202
+ : repositorySegment;
203
+ if (repository === "") {
204
+ return {
205
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.rejected,
206
+ detail: "GitHub remote repository must not be empty.",
207
+ };
208
+ }
209
+ return {
210
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.matched,
211
+ repository: { owner, name: repository },
212
+ baseUrl: resolveGitHubBaseUrls({ webOrigin: parsed.webOrigin }).apiBaseUrl,
213
+ };
214
+ }
168
215
  export function github() {
169
216
  return defineIntegration({
170
217
  id: GITHUB_INTEGRATION_ID,
171
218
  settingsCodec: createSchemaRuntimeCodec(githubSettingsSchema),
172
- remoteMatch: (remoteUrl, settings) => {
173
- const base = new URL(settings.baseUrl);
174
- const host = base.hostname === "api.github.com"
175
- ? "github.com"
176
- : base.hostname.replace(/^api\./, "");
177
- return matchesRemote(remoteUrl, host, `${settings.owner}/${settings.repository}`);
178
- },
179
219
  repositoryScope: {
220
+ resolveRemote: resolveGitHubRemote,
180
221
  applySettings: (input) => {
181
222
  if (input.kind === REPOSITORY_SETTINGS_UPDATE_KIND.baseUrl) {
182
223
  return {
@@ -185,16 +226,20 @@ export function github() {
185
226
  baseUrl: input.baseUrl,
186
227
  };
187
228
  }
188
- const baseUrl = input.baseUrl ?? input.current?.baseUrl;
229
+ const baseUrl = input.baseUrl ?? input.current?.baseUrl ?? GITHUB_API_URL;
189
230
  return {
190
231
  owner: input.repository.owner,
191
232
  repository: input.repository.name,
192
- ...(baseUrl === undefined ? {} : { baseUrl }),
233
+ baseUrl,
193
234
  };
194
235
  },
195
- projectRepository: (settings) => ({
196
- owner: settings.owner,
197
- name: settings.repository,
236
+ project: (settings) => ({
237
+ repository: {
238
+ owner: settings.owner,
239
+ name: settings.repository,
240
+ },
241
+ baseUrl: resolveGitHubBaseUrls({ apiBaseUrl: settings.baseUrl })
242
+ .apiBaseUrl,
198
243
  }),
199
244
  },
200
245
  auth: {
@@ -240,9 +285,7 @@ function createGitHubSession(settings, authorization, ports, connectionId) {
240
285
  // biome-ignore lint/complexity/noExcessiveLinesPerFunction: The provider request map stays together so endpoint behavior remains reviewable as one strategy.
241
286
  function githubStrategy(settings) {
242
287
  const repositoryPath = `/repos/${encodeURIComponent(settings.owner)}/${encodeURIComponent(settings.repository)}`;
243
- const webBaseUrl = settings.baseUrl === GITHUB_API_URL
244
- ? `https://github.com/${settings.owner}/${settings.repository}`
245
- : `${settings.baseUrl.replace(/\/api\/v3\/?$/, "")}/${settings.owner}/${settings.repository}`;
288
+ const webBaseUrl = `${resolveGitHubBaseUrls({ apiBaseUrl: settings.baseUrl }).webOrigin}/${settings.owner}/${settings.repository}`;
246
289
  const issueBody = (input) => ({
247
290
  ...(input.title === undefined ? {} : { title: input.title }),
248
291
  ...(input.body === undefined ? {} : { body: input.body }),
@@ -1 +1 @@
1
- {"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../src/code-hosts/gitlab.ts"],"names":[],"mappings":"AA4CA,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,aAAa,CAAC;AA4BrB,eAAO,MAAM,qBAAqB,4DAA0B,CAAC;AA8B7D,eAAO,MAAM,qBAAqB,sCAAuC,CAAC;AAC1E,eAAO,MAAM,4BAA4B;;;CAGD,CAAC;AAEzC,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AA2BF,wBAAgB,MAAM,kJAkErB"}
1
+ {"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../src/code-hosts/gitlab.ts"],"names":[],"mappings":"AAgDA,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,aAAa,CAAC;AA4BrB,eAAO,MAAM,qBAAqB,4DAA0B,CAAC;AA8B7D,eAAO,MAAM,qBAAqB,sCAAuC,CAAC;AAC1E,eAAO,MAAM,4BAA4B;;;CAGD,CAAC;AAEzC,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AA0EF,wBAAgB,MAAM,kJAiErB"}
@@ -2,18 +2,18 @@
2
2
  import { createSchemaRuntimeCodec } from "@alpacakit/core";
3
3
  import { z } from "zod";
4
4
  import { bearerMaterialHandlers } from "../auth.js";
5
- import { defineIntegration } from "../definition.js";
5
+ import { defineIntegration, } from "../definition.js";
6
6
  import { INTEGRATION_ERROR_CODE, IntegrationError, isIntegrationError, withIntegrationIdentity, } from "../error.js";
7
7
  import { integrationId, workItemRef, } from "../ids.js";
8
8
  import { collectPaginated } from "../transport/collect.js";
9
9
  import { createOpaqueCursorCodec } from "../transport/cursor.js";
10
10
  import { HttpTransport } from "../transport/http-transport.js";
11
11
  import { PageParamPager } from "../transport/pager.js";
12
- import { AUTHORIZATION_SCHEME, GIT_PROTOCOL, HTTP_METHOD, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_STATE, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_STATE, } from "../values.js";
12
+ import { AUTHORIZATION_SCHEME, GIT_PROTOCOL, HTTP_METHOD, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_STATE, REPOSITORY_REMOTE_RESOLUTION_KIND, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_STATE, } from "../values.js";
13
13
  import { createCodeHostAccount, createCodeHostRepository, createCodeHostRepositoryHost, createCodeHostWorkItems, probeCodeHostDoctor, } from "./facets.js";
14
14
  import { createGitLabIssueLabelChangeRequests, createGitLabLabelCreateRequest, } from "./gitlab-label-requests.js";
15
15
  import { gitLabDeviceLogin } from "./gitlab-login.js";
16
- import { ambientToken, matchesRemote } from "./helpers.js";
16
+ import { ambientToken, parseGitRemote } from "./helpers.js";
17
17
  import { rawGitLabApprovalsCodec, rawGitLabEventListCodec, rawGitLabIssueLinkListCodec, rawGitLabNamespaceCodec, rawGitLabUserListCodec, rawPullRequestCodec, rawReactionListCodec, rawRepositoryCodec, } from "./schemas.js";
18
18
  import { CODE_HOST_CHANGE_FEED_KIND, refNumber, } from "./strategy.js";
19
19
  import { CODE_HOST_LABEL_KIND, CODE_HOST_RESOURCE, GITLAB_REACTIONS, } from "./values.js";
@@ -62,7 +62,9 @@ const settingsSchema = z
62
62
  .strict()
63
63
  .transform((settings) => ({
64
64
  project: settings.project,
65
- baseUrl: (settings.baseUrl ?? GITLAB_DEFAULT_BASE_URL).replace(/\/$/, ""),
65
+ baseUrl: new URL(settings.baseUrl ?? GITLAB_DEFAULT_BASE_URL)
66
+ .toString()
67
+ .replace(/\/$/u, ""),
66
68
  }));
67
69
  const gitLabCursorCodec = createOpaqueCursorCodec({
68
70
  integration: GITLAB_INTEGRATION_ID,
@@ -71,12 +73,51 @@ const gitLabCursorCodec = createOpaqueCursorCodec({
71
73
  .object({ lastEventId: z.string(), observedAtMs: z.number().int() })
72
74
  .strict(),
73
75
  });
76
+ function splitGitLabProject(project) {
77
+ const parts = project.split("/");
78
+ return {
79
+ owner: parts.slice(0, -1).join("/"),
80
+ repository: parts.at(-1) ?? project,
81
+ };
82
+ }
83
+ function resolveGitLabRemote(remoteUrl) {
84
+ const parsed = parseGitRemote(remoteUrl);
85
+ if (parsed.kind === "rejected") {
86
+ return {
87
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.rejected,
88
+ detail: `GitLab remote ${parsed.detail}.`,
89
+ };
90
+ }
91
+ if (parsed.pathSegments.length < 2) {
92
+ return {
93
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.rejected,
94
+ detail: "GitLab remote path must contain a namespace and project.",
95
+ };
96
+ }
97
+ const projectSegment = parsed.pathSegments.at(-1);
98
+ const projectName = projectSegment.endsWith(".git")
99
+ ? projectSegment.slice(0, -4)
100
+ : projectSegment;
101
+ if (projectName === "") {
102
+ return {
103
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.rejected,
104
+ detail: "GitLab remote project must not be empty.",
105
+ };
106
+ }
107
+ const project = [...parsed.pathSegments.slice(0, -1), projectName].join("/");
108
+ const repository = splitGitLabProject(project);
109
+ return {
110
+ kind: REPOSITORY_REMOTE_RESOLUTION_KIND.matched,
111
+ repository: { owner: repository.owner, name: repository.repository },
112
+ baseUrl: parsed.webOrigin,
113
+ };
114
+ }
74
115
  export function gitlab() {
75
116
  return defineIntegration({
76
117
  id: GITLAB_INTEGRATION_ID,
77
118
  settingsCodec: createSchemaRuntimeCodec(settingsSchema),
78
- remoteMatch: (remoteUrl, settings) => matchesRemote(remoteUrl, new URL(settings.baseUrl).hostname, settings.project),
79
119
  repositoryScope: {
120
+ resolveRemote: resolveGitLabRemote,
80
121
  applySettings: (input) => {
81
122
  if (input.kind === REPOSITORY_SETTINGS_UPDATE_KIND.baseUrl) {
82
123
  return {
@@ -85,17 +126,20 @@ export function gitlab() {
85
126
  };
86
127
  }
87
128
  const project = `${input.repository.owner}/${input.repository.name}`;
88
- const baseUrl = input.baseUrl ?? input.current?.baseUrl;
129
+ const baseUrl = input.baseUrl ?? input.current?.baseUrl ?? GITLAB_DEFAULT_BASE_URL;
89
130
  return {
90
131
  project,
91
- ...(baseUrl === undefined ? {} : { baseUrl }),
132
+ baseUrl,
92
133
  };
93
134
  },
94
- projectRepository: (settings) => {
95
- const parts = settings.project.split("/");
135
+ project: (settings) => {
136
+ const project = splitGitLabProject(settings.project);
96
137
  return {
97
- owner: parts.slice(0, -1).join("/"),
98
- name: parts.at(-1) ?? settings.project,
138
+ repository: {
139
+ owner: project.owner,
140
+ name: project.repository,
141
+ },
142
+ baseUrl: settings.baseUrl,
99
143
  };
100
144
  },
101
145
  },
@@ -142,9 +186,7 @@ function createGitLabSession(settings, authorization, ports, connectionId) {
142
186
  function gitLabStrategy(settings) {
143
187
  const project = encodeURIComponent(settings.project);
144
188
  const projectPath = `/projects/${project}`;
145
- const parts = settings.project.split("/");
146
- const repository = parts.at(-1) ?? settings.project;
147
- const owner = parts.slice(0, -1).join("/") || settings.project;
189
+ const { owner, repository } = splitGitLabProject(settings.project);
148
190
  const webBaseUrl = `${settings.baseUrl}/${settings.project}`;
149
191
  const issueBody = (input, assigneeIds) => ({
150
192
  ...(input.title === undefined ? {} : { title: input.title }),
@@ -9,7 +9,15 @@ export declare function commentIdentity(ref: CommentRef): {
9
9
  readonly targetNumber: string;
10
10
  readonly comment: string;
11
11
  };
12
- export declare function matchesRemote(remoteUrl: string, expectedHost: string, expectedPath: string): boolean;
12
+ export type ParsedGitRemote = {
13
+ readonly kind: "parsed";
14
+ readonly webOrigin: string;
15
+ readonly pathSegments: readonly string[];
16
+ } | {
17
+ readonly kind: "rejected";
18
+ readonly detail: string;
19
+ };
20
+ export declare function parseGitRemote(remoteUrl: string): ParsedGitRemote;
13
21
  export declare function ambientToken(options: {
14
22
  readonly env: Record<string, string>;
15
23
  readonly envNames: readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/code-hosts/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKzD,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG;IAChD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAYA;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,GACnB,OAAO,CAeT;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA4BhC;AAED,wBAAsB,0BAA0B,CAC9C,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,WAAW,CAAC,CAsBtB;AAED,wBAAsB,OAAO,CAC3B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAef"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/code-hosts/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKzD,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG;IAChD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAYA;AAED,MAAM,MAAM,eAAe,GACvB;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAwCjE;AAuCD,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA4BhC;AAED,wBAAsB,0BAA0B,CAC9C,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,WAAW,CAAC,CAsBtB;AAED,wBAAsB,OAAO,CAC3B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAef"}
@@ -11,19 +11,75 @@ export function commentIdentity(ref) {
11
11
  comment: separator === -1 ? ref : ref.slice(separator + 2),
12
12
  };
13
13
  }
14
- export function matchesRemote(remoteUrl, expectedHost, expectedPath) {
15
- const normalizedPath = expectedPath.replace(/^\//, "").replace(/\.git$/, "");
14
+ export function parseGitRemote(remoteUrl) {
15
+ if (remoteUrl.trim() !== remoteUrl || /[\s?#]/u.test(remoteUrl)) {
16
+ return rejectedGitRemote("contains whitespace, a query, or a fragment");
17
+ }
16
18
  try {
17
19
  const url = new URL(remoteUrl);
18
- return (url.hostname.toLowerCase() === expectedHost.toLowerCase() &&
19
- url.pathname.replace(/^\//, "").replace(/\.git$/, "") === normalizedPath);
20
+ if (!["http:", "https:", "ssh:"].includes(url.protocol)) {
21
+ return rejectedGitRemote("must use HTTP(S) or SSH");
22
+ }
23
+ if (url.password !== "" ||
24
+ ((url.protocol === "http:" || url.protocol === "https:") &&
25
+ url.username !== "")) {
26
+ return rejectedGitRemote("must not contain credentials");
27
+ }
28
+ const path = parseRemotePath(url.pathname.replace(/^\//u, ""));
29
+ return path.kind === "rejected"
30
+ ? path
31
+ : {
32
+ kind: "parsed",
33
+ webOrigin: url.protocol === "ssh:" ? `https://${url.hostname}` : url.origin,
34
+ pathSegments: path.pathSegments,
35
+ };
20
36
  }
21
37
  catch {
22
- const match = remoteUrl.match(/^(?:[^@]+@)?([^:]+):(.+)$/);
23
- return (match?.[1]?.toLowerCase() === expectedHost.toLowerCase() &&
24
- match[2]?.replace(/\.git$/, "") === normalizedPath);
38
+ const match = remoteUrl.match(/^(?:[^@/:]+@)?([^@/:]+):(.+)$/u);
39
+ if (match?.[1] === undefined || match[2] === undefined) {
40
+ return rejectedGitRemote("is not a supported Git remote");
41
+ }
42
+ const path = parseRemotePath(match[2]);
43
+ if (path.kind === "rejected")
44
+ return path;
45
+ let webOrigin;
46
+ try {
47
+ webOrigin = new URL(`https://${match[1]}`).origin;
48
+ }
49
+ catch {
50
+ return rejectedGitRemote("contains an invalid host");
51
+ }
52
+ return { kind: "parsed", webOrigin, pathSegments: path.pathSegments };
25
53
  }
26
54
  }
55
+ function parseRemotePath(path) {
56
+ const encodedSegments = path.split("/");
57
+ if (encodedSegments.length === 0 ||
58
+ encodedSegments.some((segment) => segment.length === 0)) {
59
+ return rejectedGitRemote("contains an empty path segment");
60
+ }
61
+ const pathSegments = [];
62
+ for (const encoded of encodedSegments) {
63
+ let segment;
64
+ try {
65
+ segment = decodeURIComponent(encoded);
66
+ }
67
+ catch {
68
+ return rejectedGitRemote("contains invalid path encoding");
69
+ }
70
+ if (segment === "." ||
71
+ segment === ".." ||
72
+ segment.includes("/") ||
73
+ segment.includes("\\")) {
74
+ return rejectedGitRemote("contains an unsafe path segment");
75
+ }
76
+ pathSegments.push(segment);
77
+ }
78
+ return { kind: "parsed", pathSegments };
79
+ }
80
+ function rejectedGitRemote(detail) {
81
+ return { kind: "rejected", detail };
82
+ }
27
83
  export async function ambientToken(options) {
28
84
  for (const name of options.envNames) {
29
85
  const token = options.env[name];
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/code-hosts/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAEjB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EAEjB,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,YAAY,EACZ,cAAc,EAEf,MAAM,aAAa,CAAC;AAQrB,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,kBAAkB,EAClB,cAAc,EACd,OAAO,EACP,WAAW,EACZ,MAAM,cAAc,CAAC;AAOtB,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,UAAU,EAAE,aAAa,EACzB,UAAU,EAAE,uBAAuB,GAClC,cAAc,CAqBhB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAEzE;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,YAAY,GACvB,aAAa,CA8Bf;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,aAAa,EACzB,UAAU,EAAE,uBAAuB,GAClC,iBAAiB,CAkCnB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,iBAAiB,CASjE;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,kBAAkB,EACvB,UAAU,EAAE,aAAa,GACxB,kBAAkB,CAapB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAMnD;AAiDD,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAI3C"}
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/code-hosts/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAEjB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EAEjB,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,YAAY,EACZ,cAAc,EAEf,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,kBAAkB,EAClB,cAAc,EACd,OAAO,EACP,WAAW,EACZ,MAAM,cAAc,CAAC;AAOtB,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,UAAU,EAAE,aAAa,EACzB,UAAU,EAAE,uBAAuB,GAClC,cAAc,CAqBhB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAEzE;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,YAAY,GACvB,aAAa,CA8Bf;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,aAAa,EACzB,UAAU,EAAE,uBAAuB,GAClC,iBAAiB,CAkCnB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,iBAAiB,CASjE;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,kBAAkB,EACvB,UAAU,EAAE,aAAa,GACxB,kBAAkB,CAapB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAMnD;AA2CD,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAI3C"}
@@ -1,4 +1,5 @@
1
1
  import { commentRef, pullRequestRef, workItemRef, } from "../ids.js";
2
+ import { parseRepositoryRef } from "../repository-ref.js";
2
3
  import { COMMENT_KIND, COMMENT_SIDE, PULL_REQUEST_STATE, WORK_ITEM_KIND, WORK_ITEM_STATE, } from "../values.js";
3
4
  const REVIEW_TYPE_MARKER = "review";
4
5
  const DIFF_TYPE_MARKER = "diff";
@@ -147,13 +148,7 @@ function repositoryFromFullName(value) {
147
148
  return owner === undefined || name === undefined ? null : { owner, name };
148
149
  }
149
150
  function repositoryFromPath(value) {
150
- if (value === null) {
151
- return null;
152
- }
153
- const separator = value.lastIndexOf("/");
154
- return separator <= 0 || separator === value.length - 1
155
- ? null
156
- : { owner: value.slice(0, separator), name: value.slice(separator + 1) };
151
+ return value === null ? null : parseRepositoryRef(value);
157
152
  }
158
153
  export function isBot(raw) {
159
154
  return (raw.type?.toLowerCase() === BOT_TYPE || raw.login.endsWith(BOT_LOGIN_SUFFIX));
@@ -4,7 +4,7 @@ import type { IntegrationAuthProfileId, IntegrationConnectionId, IntegrationId }
4
4
  import type { DoctorCapability, IntegrationLoginCapability } from "./login.js";
5
5
  import type { Account, Repository, RepositoryHost, RepositoryRef, WorkItems } from "./model.js";
6
6
  import type { SessionPorts } from "./ports.js";
7
- import type { INTEGRATION_SETTINGS_INPUT_KIND, REPOSITORY_SETTINGS_UPDATE_KIND } from "./values.js";
7
+ import type { INTEGRATION_SETTINGS_INPUT_KIND, REPOSITORY_REMOTE_RESOLUTION_KIND, REPOSITORY_SETTINGS_UPDATE_KIND } from "./values.js";
8
8
  export type IntegrationConnectionRecord = {
9
9
  readonly id: IntegrationConnectionId;
10
10
  readonly integrationId: IntegrationId;
@@ -43,14 +43,29 @@ export type IntegrationSettingsInput = {
43
43
  readonly kind: typeof INTEGRATION_SETTINGS_INPUT_KIND.raw;
44
44
  readonly settings: JsonObject;
45
45
  };
46
+ export type RepositoryRemoteResolution = {
47
+ readonly kind: typeof REPOSITORY_REMOTE_RESOLUTION_KIND.matched;
48
+ readonly repository: RepositoryRef;
49
+ readonly baseUrl: string | null;
50
+ } | {
51
+ readonly kind: typeof REPOSITORY_REMOTE_RESOLUTION_KIND.unmatched;
52
+ } | {
53
+ readonly kind: typeof REPOSITORY_REMOTE_RESOLUTION_KIND.rejected;
54
+ readonly detail: string;
55
+ };
56
+ export type RepositoryScope = {
57
+ readonly repository: RepositoryRef;
58
+ readonly baseUrl: string;
59
+ };
60
+ export declare function sameRepositoryScope(left: RepositoryScope, right: RepositoryScope): boolean;
46
61
  export interface RepositoryScopeAdapter<TSettings> {
47
62
  applySettings(input: RepositorySettingsApplication<TSettings>): JsonObject;
48
- projectRepository(settings: TSettings): RepositoryRef;
63
+ project(settings: TSettings): RepositoryScope;
64
+ resolveRemote(remoteUrl: string): RepositoryRemoteResolution;
49
65
  }
50
66
  export interface IntegrationDefinition<Id extends IntegrationId = IntegrationId, TSettings = JsonObject, TSession = unknown> {
51
67
  readonly id: Id;
52
68
  readonly settingsCodec: RuntimeCodec<TSettings>;
53
- readonly remoteMatch?: (remoteUrl: string, settings: TSettings) => boolean;
54
69
  readonly repositoryScope?: RepositoryScopeAdapter<TSettings>;
55
70
  readonly auth?: IntegrationAuthCapability;
56
71
  readonly login?: IntegrationLoginCapability;
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,8 @@
1
+ export function sameRepositoryScope(left, right) {
2
+ return (left.baseUrl === right.baseUrl &&
3
+ left.repository.owner === right.repository.owner &&
4
+ left.repository.name === right.repository.name);
5
+ }
1
6
  export function defineIntegration(definition) {
2
7
  return definition;
3
8
  }
package/dist/index.d.ts CHANGED
@@ -1,22 +1,24 @@
1
1
  /** Provider-neutral development-management integration runtime. */
2
- export { type AmbientAuthResolver, type Authorization, authorizationHeader, bearerMaterialHandlers, envResolver, type IntegrationAuthBinding, type IntegrationAuthCapability, type IntegrationAuthMaterial, type IntegrationAuthMaterialKind, type IntegrationAuthProfile, type MaterialHandler, type MaterialHandlers, requireSecret, type SecretRef, } from "./auth.js";
2
+ export { ABORTABLE_HTTP_CLIENT_CLOSED_MESSAGE, type AbortableHttpClient, type AbortableHttpClientOptions, createAbortableHttpClient, } from "./abortable-http-client.js";
3
+ export { type AmbientAuthResolver, type Authorization, authorizationHeader, bearerMaterialHandlers, envResolver, type IntegrationAuthBinding, type IntegrationAuthCapability, type IntegrationAuthMaterial, type IntegrationAuthMaterialKind, type IntegrationAuthProfile, type MaterialHandler, type MaterialHandlers, requireSecret, type SecretRef, sameIntegrationAuthBinding, } from "./auth.js";
3
4
  export { createIntegrationDefinitionCatalog, type IntegrationDefinitionCatalog, } from "./catalog.js";
4
5
  export { BUILTIN_INTEGRATION_ID, type BuiltinIntegrationId, findGitCredentialScheme, gitCredentialScheme, templatePaths, } from "./code-hosts/builtin.js";
5
6
  export { GITEA_INTEGRATION_ID, type GiteaSettings, gitea, } from "./code-hosts/gitea.js";
6
7
  export { GITHUB_INTEGRATION_ID, type GitHubSettings, github, } from "./code-hosts/github.js";
7
8
  export { GITLAB_INTEGRATION_ID, type GitLabSettings, gitlab, } from "./code-hosts/gitlab.js";
8
- export type { ConnectContext, IntegrationConnectionRecord, IntegrationDefinition, IntegrationSettingsInput, RepositoryScopeAdapter, RepositorySettingsApplication, RepositorySettingsUpdate, } from "./definition.js";
9
- export { defineIntegration } from "./definition.js";
9
+ export type { ConnectContext, IntegrationConnectionRecord, IntegrationDefinition, IntegrationSettingsInput, RepositoryRemoteResolution, RepositoryScope, RepositoryScopeAdapter, RepositorySettingsApplication, RepositorySettingsUpdate, } from "./definition.js";
10
+ export { defineIntegration, sameRepositoryScope } from "./definition.js";
10
11
  export { AUTH_FAILURE_REASON, type AuthFailureReason, INTEGRATION_ERROR_CODE, IntegrationError, type IntegrationErrorCode, type IntegrationErrorData, type IntegrationErrorOptions, isIntegrationError, NOT_AVAILABLE_CAUSE, type NotAvailableCause, } from "./error.js";
11
12
  export type { ChangeFeedCursor, CommentReaction, CommentRef, IntegrationAuthProfileId, IntegrationConnectionId, IntegrationId, MilestoneRef, PullRequestRef, WorkItemRef, } from "./ids.js";
12
13
  export { changeFeedCursor, commentReaction, commentRef, integrationAuthProfileId, integrationConnectionId, integrationId, milestoneRef, pullRequestRef, workItemRef, } from "./ids.js";
13
14
  export type { DoctorCapability, DoctorCheck, DoctorCheckStatus, IntegrationLoginCapability, IntegrationLoginMethod, LoginContext, LoginEvent, LoginHandle, LoginHandler, LoginOutcome, LoginRequest, LoginRun, } from "./login.js";
14
15
  export * from "./model.js";
15
16
  export type { Clock, Exec, ExecChunk, ExecExit, ExecProcess, ExecSpawnOptions, HttpClient, HttpTelemetry, IntegrationPorts, Logger, SecretResolver, SecretResolvers, SessionPorts, TelemetrySink, } from "./ports.js";
16
- export { type ConnectionCheck, createIntegrationRuntime, type Integration, type IntegrationRuntime, type IntegrationRuntimeOptions, } from "./runtime.js";
17
+ export { parseRepositoryRef } from "./repository-ref.js";
18
+ export { type ConnectionCheck, createIntegrationRuntime, type Integration, type IntegrationRemoteResolution, type IntegrationRuntime, type IntegrationRuntimeOptions, } from "./runtime.js";
17
19
  export { createOpaqueCursorCodec } from "./transport/cursor.js";
18
20
  export { HttpTransport, type HttpTransportOptions, } from "./transport/http-transport.js";
19
21
  export { LinkHeaderPager, PageParamPager, type PageParamPagerOptions, } from "./transport/pager.js";
20
22
  export type { CursorCodec, HttpMethod, Pager, RequestSpec, } from "./transport/types.js";
21
- export { AUTHORIZATION_KIND, AUTHORIZATION_SCHEME, COMMENT_KIND, COMMENT_SIDE, CONNECTION_STATUS, DOCTOR_CHECK_STATUS, ENSURE_REPOSITORY_RESULT_KIND, EXEC_CHANNEL, FILE_CHANGE_STATUS, GIT_PROTOCOL, HTTP_MEDIA_TYPE, HTTP_METHOD, INTEGRATION_AUTH_BINDING_KIND, INTEGRATION_AUTH_MATERIAL_KIND, INTEGRATION_LOGIN_METHOD, INTEGRATION_SETTINGS_INPUT_KIND, LOG_LEVEL, LOGIN_EVENT_TYPE, MEMBERSHIP, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_FEEDBACK_KIND, PULL_REQUEST_REVIEW_CONTEXT_AVAILABILITY, PULL_REQUEST_REVIEW_STATE, PULL_REQUEST_STATE, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_SEARCH_FIELD, WORK_ITEM_STATE, } from "./values.js";
23
+ export { AUTHORIZATION_KIND, AUTHORIZATION_SCHEME, COMMENT_KIND, COMMENT_SIDE, CONNECTION_STATUS, DOCTOR_CHECK_STATUS, ENSURE_REPOSITORY_RESULT_KIND, EXEC_CHANNEL, FILE_CHANGE_STATUS, GIT_PROTOCOL, HTTP_MEDIA_TYPE, HTTP_METHOD, INTEGRATION_AUTH_BINDING_KIND, INTEGRATION_AUTH_MATERIAL_KIND, INTEGRATION_LOGIN_METHOD, INTEGRATION_REMOTE_RESOLUTION_KIND, INTEGRATION_SETTINGS_INPUT_KIND, LOG_LEVEL, LOGIN_EVENT_TYPE, MEMBERSHIP, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_FEEDBACK_KIND, PULL_REQUEST_REVIEW_CONTEXT_AVAILABILITY, PULL_REQUEST_REVIEW_STATE, PULL_REQUEST_STATE, REPOSITORY_REMOTE_RESOLUTION_KIND, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_SEARCH_FIELD, WORK_ITEM_STATE, } from "./values.js";
22
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,16 +1,18 @@
1
1
  /** Provider-neutral development-management integration runtime. */
2
- export { authorizationHeader, bearerMaterialHandlers, envResolver, requireSecret, } from "./auth.js";
2
+ export { ABORTABLE_HTTP_CLIENT_CLOSED_MESSAGE, createAbortableHttpClient, } from "./abortable-http-client.js";
3
+ export { authorizationHeader, bearerMaterialHandlers, envResolver, requireSecret, sameIntegrationAuthBinding, } from "./auth.js";
3
4
  export { createIntegrationDefinitionCatalog, } from "./catalog.js";
4
5
  export { BUILTIN_INTEGRATION_ID, findGitCredentialScheme, gitCredentialScheme, templatePaths, } from "./code-hosts/builtin.js";
5
6
  export { GITEA_INTEGRATION_ID, gitea, } from "./code-hosts/gitea.js";
6
7
  export { GITHUB_INTEGRATION_ID, github, } from "./code-hosts/github.js";
7
8
  export { GITLAB_INTEGRATION_ID, gitlab, } from "./code-hosts/gitlab.js";
8
- export { defineIntegration } from "./definition.js";
9
+ export { defineIntegration, sameRepositoryScope } from "./definition.js";
9
10
  export { AUTH_FAILURE_REASON, INTEGRATION_ERROR_CODE, IntegrationError, isIntegrationError, NOT_AVAILABLE_CAUSE, } from "./error.js";
10
11
  export { changeFeedCursor, commentReaction, commentRef, integrationAuthProfileId, integrationConnectionId, integrationId, milestoneRef, pullRequestRef, workItemRef, } from "./ids.js";
11
12
  export * from "./model.js";
13
+ export { parseRepositoryRef } from "./repository-ref.js";
12
14
  export { createIntegrationRuntime, } from "./runtime.js";
13
15
  export { createOpaqueCursorCodec } from "./transport/cursor.js";
14
16
  export { HttpTransport, } from "./transport/http-transport.js";
15
17
  export { LinkHeaderPager, PageParamPager, } from "./transport/pager.js";
16
- export { AUTHORIZATION_KIND, AUTHORIZATION_SCHEME, COMMENT_KIND, COMMENT_SIDE, CONNECTION_STATUS, DOCTOR_CHECK_STATUS, ENSURE_REPOSITORY_RESULT_KIND, EXEC_CHANNEL, FILE_CHANGE_STATUS, GIT_PROTOCOL, HTTP_MEDIA_TYPE, HTTP_METHOD, INTEGRATION_AUTH_BINDING_KIND, INTEGRATION_AUTH_MATERIAL_KIND, INTEGRATION_LOGIN_METHOD, INTEGRATION_SETTINGS_INPUT_KIND, LOG_LEVEL, LOGIN_EVENT_TYPE, MEMBERSHIP, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_FEEDBACK_KIND, PULL_REQUEST_REVIEW_CONTEXT_AVAILABILITY, PULL_REQUEST_REVIEW_STATE, PULL_REQUEST_STATE, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_SEARCH_FIELD, WORK_ITEM_STATE, } from "./values.js";
18
+ export { AUTHORIZATION_KIND, AUTHORIZATION_SCHEME, COMMENT_KIND, COMMENT_SIDE, CONNECTION_STATUS, DOCTOR_CHECK_STATUS, ENSURE_REPOSITORY_RESULT_KIND, EXEC_CHANNEL, FILE_CHANGE_STATUS, GIT_PROTOCOL, HTTP_MEDIA_TYPE, HTTP_METHOD, INTEGRATION_AUTH_BINDING_KIND, INTEGRATION_AUTH_MATERIAL_KIND, INTEGRATION_LOGIN_METHOD, INTEGRATION_REMOTE_RESOLUTION_KIND, INTEGRATION_SETTINGS_INPUT_KIND, LOG_LEVEL, LOGIN_EVENT_TYPE, MEMBERSHIP, MERGE_METHOD, MERGE_STATE_STATUS, MERGEABILITY, OWNER_KIND, PULL_REQUEST_FEEDBACK_KIND, PULL_REQUEST_REVIEW_CONTEXT_AVAILABILITY, PULL_REQUEST_REVIEW_STATE, PULL_REQUEST_STATE, REPOSITORY_REMOTE_RESOLUTION_KIND, REPOSITORY_SETTINGS_UPDATE_KIND, REVIEW_DECISION, WORK_ITEM_KIND, WORK_ITEM_QUERY_STATE, WORK_ITEM_SEARCH_FIELD, WORK_ITEM_STATE, } from "./values.js";
@@ -0,0 +1,4 @@
1
+ import type { RepositoryRef } from "./model.js";
2
+ /** Parses a provider-neutral `owner/name` path, including nested owners. */
3
+ export declare function parseRepositoryRef(input: string): RepositoryRef | null;
4
+ //# sourceMappingURL=repository-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository-ref.d.ts","sourceRoot":"","sources":["../src/repository-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAOtE"}
@@ -0,0 +1,9 @@
1
+ /** Parses a provider-neutral `owner/name` path, including nested owners. */
2
+ export function parseRepositoryRef(input) {
3
+ const separator = input.lastIndexOf("/");
4
+ return separator <= 0 ||
5
+ separator === input.length - 1 ||
6
+ input.includes("//")
7
+ ? null
8
+ : { owner: input.slice(0, separator), name: input.slice(separator + 1) };
9
+ }
package/dist/runtime.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { type IntegrationAuthProfile } from "./auth.js";
2
- import type { IntegrationConnectionRecord, IntegrationDefinition } from "./definition.js";
2
+ import { type IntegrationConnectionRecord, type IntegrationDefinition } from "./definition.js";
3
3
  import { type IntegrationConnectionId, type IntegrationId } from "./ids.js";
4
4
  import { type DoctorCheck, type LoginHandle, type LoginRequest } from "./login.js";
5
5
  import type { Account, Repository, RepositoryHost, UserRef, WorkItems } from "./model.js";
6
6
  import { type IntegrationPorts } from "./ports.js";
7
- import { CONNECTION_STATUS } from "./values.js";
7
+ import { CONNECTION_STATUS, INTEGRATION_REMOTE_RESOLUTION_KIND } from "./values.js";
8
8
  export interface Integration {
9
9
  readonly connectionId: IntegrationConnectionId;
10
10
  readonly integrationId: IntegrationId;
@@ -30,10 +30,19 @@ export type ConnectionCheck = {
30
30
  readonly viewer: null;
31
31
  readonly detail: string | null;
32
32
  };
33
+ export type IntegrationRemoteResolution = {
34
+ readonly kind: typeof INTEGRATION_REMOTE_RESOLUTION_KIND.matched;
35
+ readonly connectionId: IntegrationConnectionId;
36
+ } | {
37
+ readonly kind: typeof INTEGRATION_REMOTE_RESOLUTION_KIND.unmatched;
38
+ } | {
39
+ readonly kind: typeof INTEGRATION_REMOTE_RESOLUTION_KIND.ambiguous;
40
+ readonly connectionIds: readonly IntegrationConnectionId[];
41
+ };
33
42
  export interface IntegrationRuntime {
34
43
  connect(id: IntegrationConnectionId | string): Promise<Integration>;
35
44
  connections(): IntegrationConnectionId[];
36
- resolveRemote(remoteUrl: string): IntegrationConnectionId | null;
45
+ resolveRemote(remoteUrl: string): IntegrationRemoteResolution;
37
46
  login(integration: string, options: LoginRequest): LoginHandle;
38
47
  checkConnection(connection: IntegrationConnectionId | string): Promise<ConnectionCheck>;
39
48
  doctor(connection: IntegrationConnectionId | string): Promise<DoctorCheck[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,sBAAsB,EAE5B,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EACV,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAGnB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EAGlB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACV,OAAO,EACP,UAAU,EACV,cAAc,EACd,OAAO,EACP,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,iBAAiB,EAElB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC/C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,gBAAgB,IAAI,SAAS,CAAC;IAC9B,iBAAiB,IAAI,UAAU,CAAC;IAChC,qBAAqB,IAAI,cAAc,CAAC;IACxC,cAAc,IAAI,OAAO,CAAC;CAC3B;AAED,MAAM,MAAM,eAAe,GACvB;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;CACvB,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,iBAAiB,CAAC,OAAO,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,iBAAiB,CAAC,OAAO,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEN,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,EAAE,uBAAuB,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACpE,WAAW,IAAI,uBAAuB,EAAE,CAAC;IACzC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAAC;IAC/D,eAAe,CACb,UAAU,EAAE,uBAAuB,GAAG,MAAM,GAC3C,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5B,MAAM,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7E,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;CAClC;AAGD,KAAK,aAAa,GAAG,qBAAqB,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEpE,MAAM,MAAM,yBAAyB,CAAC,IAAI,SAAS,SAAS,aAAa,EAAE,IAAI;IAC7E,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS,2BAA2B,EAAE,CAAC;IAC7D,QAAQ,CAAC,QAAQ,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAkBF,wBAAgB,wBAAwB,CACtC,KAAK,CAAC,IAAI,SAAS,SAAS,aAAa,EAAE,EAC3C,OAAO,EAAE,yBAAyB,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAE9D"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,sBAAsB,EAE5B,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAE3B,MAAM,iBAAiB,CAAC;AAQzB,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAGnB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EAGlB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACV,OAAO,EACP,UAAU,EACV,cAAc,EACd,OAAO,EACP,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,iBAAiB,EAEjB,kCAAkC,EAEnC,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC/C,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,gBAAgB,IAAI,SAAS,CAAC;IAC9B,iBAAiB,IAAI,UAAU,CAAC;IAChC,qBAAqB,IAAI,cAAc,CAAC;IACxC,cAAc,IAAI,OAAO,CAAC;CAC3B;AAED,MAAM,MAAM,eAAe,GACvB;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;CACvB,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,iBAAiB,CAAC,OAAO,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,OAAO,iBAAiB,CAAC,OAAO,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEN,MAAM,MAAM,2BAA2B,GACnC;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,kCAAkC,CAAC,OAAO,CAAC;IACjE,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;CAChD,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,kCAAkC,CAAC,SAAS,CAAC;CACpE,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,kCAAkC,CAAC,SAAS,CAAC;IACnE,QAAQ,CAAC,aAAa,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC5D,CAAC;AAEN,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,EAAE,uBAAuB,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACpE,WAAW,IAAI,uBAAuB,EAAE,CAAC;IACzC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,2BAA2B,CAAC;IAC9D,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAAC;IAC/D,eAAe,CACb,UAAU,EAAE,uBAAuB,GAAG,MAAM,GAC3C,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5B,MAAM,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7E,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;CAClC;AAGD,KAAK,aAAa,GAAG,qBAAqB,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEpE,MAAM,MAAM,yBAAyB,CAAC,IAAI,SAAS,SAAS,aAAa,EAAE,IAAI;IAC7E,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,SAAS,2BAA2B,EAAE,CAAC;IAC7D,QAAQ,CAAC,QAAQ,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAkBF,wBAAgB,wBAAwB,CACtC,KAAK,CAAC,IAAI,SAAS,SAAS,aAAa,EAAE,EAC3C,OAAO,EAAE,yBAAyB,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAE9D"}
package/dist/runtime.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { CODEC_DECODE_RESULT_KIND } from "@alpacakit/core";
2
2
  import { envResolver, } from "./auth.js";
3
+ import { sameRepositoryScope, } from "./definition.js";
3
4
  import { AUTH_FAILURE_REASON, INTEGRATION_ERROR_CODE, IntegrationError, isIntegrationError, withIntegrationIdentity, } from "./error.js";
4
5
  import { integrationConnectionId, integrationId, } from "./ids.js";
5
6
  import { startLogin, } from "./login.js";
6
7
  import { fetchHttp, nodeExec, systemClock } from "./node-ports.js";
7
8
  import { noopLogger, noopTelemetry, } from "./ports.js";
8
- import { AUTHORIZATION_KIND, CONNECTION_STATUS, INTEGRATION_AUTH_BINDING_KIND, } from "./values.js";
9
+ import { AUTHORIZATION_KIND, CONNECTION_STATUS, INTEGRATION_AUTH_BINDING_KIND, INTEGRATION_REMOTE_RESOLUTION_KIND, REPOSITORY_REMOTE_RESOLUTION_KIND, } from "./values.js";
9
10
  function sessionPorts(ports) {
10
11
  return {
11
12
  http: ports.http,
@@ -63,6 +64,7 @@ class DefaultIntegrationRuntime {
63
64
  return this.connectionSnapshot.map((connection) => connection.id);
64
65
  }
65
66
  resolveRemote(remoteUrl) {
67
+ const connectionIds = [];
66
68
  for (const record of this.connectionSnapshot) {
67
69
  let resolved;
68
70
  try {
@@ -73,11 +75,30 @@ class DefaultIntegrationRuntime {
73
75
  // abort resolution of an otherwise-matching remote.
74
76
  continue;
75
77
  }
76
- if (resolved.definition.remoteMatch?.(remoteUrl, resolved.settings) === true) {
77
- return record.id;
78
+ const adapter = resolved.definition.repositoryScope;
79
+ if (adapter === undefined)
80
+ continue;
81
+ const remote = adapter.resolveRemote(remoteUrl);
82
+ const configured = adapter.project(resolved.settings);
83
+ if (remote.kind === REPOSITORY_REMOTE_RESOLUTION_KIND.matched &&
84
+ remote.baseUrl !== null &&
85
+ sameRepositoryScope({ baseUrl: remote.baseUrl, repository: remote.repository }, configured)) {
86
+ connectionIds.push(record.id);
78
87
  }
79
88
  }
80
- return null;
89
+ if (connectionIds.length === 0) {
90
+ return { kind: INTEGRATION_REMOTE_RESOLUTION_KIND.unmatched };
91
+ }
92
+ if (connectionIds.length === 1) {
93
+ return {
94
+ kind: INTEGRATION_REMOTE_RESOLUTION_KIND.matched,
95
+ connectionId: connectionIds[0],
96
+ };
97
+ }
98
+ return {
99
+ kind: INTEGRATION_REMOTE_RESOLUTION_KIND.ambiguous,
100
+ connectionIds,
101
+ };
81
102
  }
82
103
  login(rawIntegrationId, loginOptions) {
83
104
  const id = integrationId(rawIntegrationId);
package/dist/values.d.ts CHANGED
@@ -15,6 +15,16 @@ export declare const REPOSITORY_SETTINGS_UPDATE_KIND: {
15
15
  readonly repository: "repository";
16
16
  readonly baseUrl: "base_url";
17
17
  };
18
+ export declare const REPOSITORY_REMOTE_RESOLUTION_KIND: {
19
+ readonly matched: "matched";
20
+ readonly unmatched: "unmatched";
21
+ readonly rejected: "rejected";
22
+ };
23
+ export declare const INTEGRATION_REMOTE_RESOLUTION_KIND: {
24
+ readonly matched: "matched";
25
+ readonly unmatched: "unmatched";
26
+ readonly ambiguous: "ambiguous";
27
+ };
18
28
  export declare const ENSURE_REPOSITORY_RESULT_KIND: {
19
29
  readonly existing: "existing";
20
30
  readonly created: "created";
@@ -1 +1 @@
1
- {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../src/values.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B;;;;CAIhC,CAAC;AAEX,eAAO,MAAM,8BAA8B;;;CAGjC,CAAC;AAEX,eAAO,MAAM,+BAA+B;;;CAGlC,CAAC;AAEX,eAAO,MAAM,+BAA+B;;;CAGlC,CAAC;AAEX,eAAO,MAAM,6BAA6B;;;CAGhC,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAEX,eAAO,MAAM,oBAAoB;;;;CAIvB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,eAAO,MAAM,qBAAqB;;;;CAGxB,CAAC;AAEX,eAAO,MAAM,sBAAsB;;;CAGzB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AAEX,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX,eAAO,MAAM,wCAAwC;;;;CAI3C,CAAC;AAEX,eAAO,MAAM,0BAA0B;;;;CAI7B,CAAC;AAEX,eAAO,MAAM,yBAAyB;;;;;;CAM5B,CAAC;AAEX,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;;CAOrB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,eAAO,MAAM,UAAU;;;CAGb,CAAC;AAEX,eAAO,MAAM,UAAU;;;;CAIb,CAAC;AAEX,eAAO,MAAM,wBAAwB;;;CAG3B,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAEX,eAAO,MAAM,mBAAmB;;;;CAItB,CAAC;AAEX,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC;AAEX,eAAO,MAAM,WAAW;;;;;;CAMd,CAAC;AAEX,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC"}
1
+ {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../src/values.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B;;;;CAIhC,CAAC;AAEX,eAAO,MAAM,8BAA8B;;;CAGjC,CAAC;AAEX,eAAO,MAAM,+BAA+B;;;CAGlC,CAAC;AAEX,eAAO,MAAM,+BAA+B;;;CAGlC,CAAC;AAEX,eAAO,MAAM,iCAAiC;;;;CAIpC,CAAC;AAEX,eAAO,MAAM,kCAAkC;;;;CAIrC,CAAC;AAEX,eAAO,MAAM,6BAA6B;;;CAGhC,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAEX,eAAO,MAAM,oBAAoB;;;;CAIvB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,eAAO,MAAM,qBAAqB;;;;CAGxB,CAAC;AAEX,eAAO,MAAM,sBAAsB;;;CAGzB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AAEX,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX,eAAO,MAAM,wCAAwC;;;;CAI3C,CAAC;AAEX,eAAO,MAAM,0BAA0B;;;;CAI7B,CAAC;AAEX,eAAO,MAAM,yBAAyB;;;;;;CAM5B,CAAC;AAEX,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;;CAOrB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX,eAAO,MAAM,UAAU;;;CAGb,CAAC;AAEX,eAAO,MAAM,UAAU;;;;CAIb,CAAC;AAEX,eAAO,MAAM,wBAAwB;;;CAG3B,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAEX,eAAO,MAAM,mBAAmB;;;;CAItB,CAAC;AAEX,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC;AAEX,eAAO,MAAM,WAAW;;;;;;CAMd,CAAC;AAEX,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC"}
package/dist/values.js CHANGED
@@ -15,6 +15,16 @@ export const REPOSITORY_SETTINGS_UPDATE_KIND = {
15
15
  repository: "repository",
16
16
  baseUrl: "base_url",
17
17
  };
18
+ export const REPOSITORY_REMOTE_RESOLUTION_KIND = {
19
+ matched: "matched",
20
+ unmatched: "unmatched",
21
+ rejected: "rejected",
22
+ };
23
+ export const INTEGRATION_REMOTE_RESOLUTION_KIND = {
24
+ matched: "matched",
25
+ unmatched: "unmatched",
26
+ ambiguous: "ambiguous",
27
+ };
18
28
  export const ENSURE_REPOSITORY_RESULT_KIND = {
19
29
  existing: "existing",
20
30
  created: "created",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alpacakit/integrations",
3
- "version": "0.1.0-beta.30",
3
+ "version": "0.1.0-beta.35",
4
4
  "description": "Provider-neutral development-management integrations for issues, pull requests, and repositories.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "zod": "^4.3.6",
40
- "@alpacakit/core": "0.1.0-beta.30"
40
+ "@alpacakit/core": "0.1.0-beta.35"
41
41
  },
42
42
  "devDependencies": {
43
43
  "typescript": "^5.9.3",