@cat-factory/local-server 0.6.0 → 0.7.2
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 -21
- package/package.json +13 -8
- package/dist/LocalDockerRunnerTransport.d.ts +0 -95
- package/dist/LocalDockerRunnerTransport.d.ts.map +0 -1
- package/dist/LocalDockerRunnerTransport.js +0 -342
- package/dist/LocalDockerRunnerTransport.js.map +0 -1
- package/dist/config.d.ts +0 -9
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -42
- package/dist/config.js.map +0 -1
- package/dist/container.d.ts +0 -4
- package/dist/container.d.ts.map +0 -1
- package/dist/container.js +0 -84
- package/dist/container.js.map +0 -1
- package/dist/github.d.ts +0 -36
- package/dist/github.d.ts.map +0 -1
- package/dist/github.js +0 -174
- package/dist/github.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -21
- package/dist/index.js.map +0 -1
- package/dist/installations.d.ts +0 -31
- package/dist/installations.d.ts.map +0 -1
- package/dist/installations.js +0 -76
- package/dist/installations.js.map +0 -1
- package/dist/link-repo.d.ts +0 -2
- package/dist/link-repo.d.ts.map +0 -1
- package/dist/link-repo.js +0 -21
- package/dist/link-repo.js.map +0 -1
- package/dist/linkRepo.d.ts +0 -31
- package/dist/linkRepo.d.ts.map +0 -1
- package/dist/linkRepo.js +0 -113
- package/dist/linkRepo.js.map +0 -1
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -10
- package/dist/main.js.map +0 -1
- package/dist/server.d.ts +0 -5
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -50
- package/dist/server.js.map +0 -1
package/dist/container.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { DrizzleGitHubInstallationRepository, buildNodeContainer, loadNodeConfig, } from '@cat-factory/node-server';
|
|
2
|
-
import { applyLocalDefaults } from './config.js';
|
|
3
|
-
import { createLocalGitHubClient, fetchPatAccount, githubPatCreationUrl } from './github.js';
|
|
4
|
-
import { AutoProvisioningInstallationRepository } from './installations.js';
|
|
5
|
-
import { createLocalDockerTransportFromEnv, } from './LocalDockerRunnerTransport.js';
|
|
6
|
-
// The local-mode composition root. It is intentionally thin: the ENTIRE Drizzle/
|
|
7
|
-
// Postgres persistence, pg-boss durable execution, gateways and model provisioning
|
|
8
|
-
// come from `buildNodeContainer` unchanged. Local mode only swaps the two
|
|
9
|
-
// differentiators behind the seams `buildNodeContainer` exposes:
|
|
10
|
-
// - the runner backend → a per-job local Docker container (LocalDockerRunnerTransport)
|
|
11
|
-
// instead of a self-hosted runner pool;
|
|
12
|
-
// - the push/clone token → a static GitHub PAT (`GITHUB_PAT`) instead of a GitHub
|
|
13
|
-
// App installation token.
|
|
14
|
-
// Repo resolution is unchanged: the executor still resolves a block's repo from the
|
|
15
|
-
// `github_repos` / `github_installations` projection (seed those rows for a target
|
|
16
|
-
// repo with the link helper). So a developer can run coder/mocker/playwright/
|
|
17
|
-
// blueprints/ci-fixer/merger jobs entirely locally, pushing real branches and opening
|
|
18
|
-
// real PRs on github.com via the PAT.
|
|
19
|
-
export function buildLocalContainer(options) {
|
|
20
|
-
const env = applyLocalDefaults(options.env ?? process.env);
|
|
21
|
-
const pat = env.GITHUB_PAT?.trim();
|
|
22
|
-
const base = options.config ?? loadNodeConfig(env);
|
|
23
|
-
// Tag the config as local mode and, when no PAT is set, carry the (scopes-preselected)
|
|
24
|
-
// creation URL so the SPA can surface it as a dismissible banner — the server-side warn
|
|
25
|
-
// log alone is easy to miss in a dev terminal. With a PAT, force the GitHub integration
|
|
26
|
-
// ON: the Node loader only enables it for a configured GitHub App, but local mode reaches
|
|
27
|
-
// GitHub through the PAT-backed client, so the read/link endpoints (connection, available
|
|
28
|
-
// repos, "add from existing repo") should be served the same way.
|
|
29
|
-
const config = {
|
|
30
|
-
...base,
|
|
31
|
-
...(pat ? { github: { ...base.github, enabled: true } } : {}),
|
|
32
|
-
localMode: {
|
|
33
|
-
enabled: true,
|
|
34
|
-
...(pat ? {} : { githubPatSetupUrl: githubPatCreationUrl() }),
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
// Local mode has no GitHub-App connect flow, so a workspace's installation is conjured
|
|
38
|
-
// from the PAT on first read (see AutoProvisioningInstallationRepository): the synthetic
|
|
39
|
-
// row makes `getConnection` report connected and gives the sync service an installation
|
|
40
|
-
// id to list/link repos under. The PAT account is fetched once and shared across
|
|
41
|
-
// workspaces (a single developer's token).
|
|
42
|
-
let accountPromise;
|
|
43
|
-
const resolveAccount = () => (accountPromise ??= fetchPatAccount(env));
|
|
44
|
-
const githubInstallationRepository = pat && options.db
|
|
45
|
-
? new AutoProvisioningInstallationRepository(new DrizzleGitHubInstallationRepository(options.db), resolveAccount)
|
|
46
|
-
: undefined;
|
|
47
|
-
// The Docker transport is constructed LAZILY on first container-job dispatch, so the
|
|
48
|
-
// service still boots to serve the board (and inline kinds) when LOCAL_HARNESS_IMAGE
|
|
49
|
-
// is unset — only repo-operating kinds then fail, loudly and with a clear message,
|
|
50
|
-
// mirroring how the Node facade treats a missing runner backend.
|
|
51
|
-
let transport;
|
|
52
|
-
const resolveTransport = () => {
|
|
53
|
-
transport ??= createLocalDockerTransportFromEnv(env);
|
|
54
|
-
return Promise.resolve(transport);
|
|
55
|
-
};
|
|
56
|
-
return buildNodeContainer({
|
|
57
|
-
...options,
|
|
58
|
-
env,
|
|
59
|
-
config,
|
|
60
|
-
// Always dispatch container jobs to the local Docker transport (a constant
|
|
61
|
-
// resolver, ignoring workspace — local mode has no per-workspace runner pools).
|
|
62
|
-
resolveTransport,
|
|
63
|
-
// Authenticate git with the developer's PAT when present. Absent → the executor
|
|
64
|
-
// falls back to the GitHub App path (and is null without it), so container kinds
|
|
65
|
-
// fail loudly rather than silently mis-running.
|
|
66
|
-
...(pat ? { mintInstallationToken: async () => pat } : {}),
|
|
67
|
-
// The PAT-backed GitHub client wires the CI gate + merge / mergeability providers,
|
|
68
|
-
// so a local pipeline gates on real GitHub Actions CI and merges the PR for real, AND
|
|
69
|
-
// serves the read/link endpoints (it lists repos via /user/repos, the PAT analogue of
|
|
70
|
-
// the App-only /installation/repositories).
|
|
71
|
-
...(pat ? { githubClient: createLocalGitHubClient(env) } : {}),
|
|
72
|
-
// Auto-provision the synthetic per-workspace installation so the integration reports
|
|
73
|
-
// connected with no manual connect step.
|
|
74
|
-
...(githubInstallationRepository ? { githubInstallationRepository } : {}),
|
|
75
|
-
overrides: {
|
|
76
|
-
...options.overrides,
|
|
77
|
-
// The local PAT carries `workflow` scope (the creation URL pre-selects it), so the
|
|
78
|
-
// connection isn't missing workflows: write — report it granted to suppress the
|
|
79
|
-
// advisory banner. (The App-permissions probe this normally uses needs an app JWT.)
|
|
80
|
-
...(pat ? { workflowsGranted: async () => true } : {}),
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
//# sourceMappingURL=container.js.map
|
package/dist/container.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
|
package/dist/github.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { GitHubClient } from '@cat-factory/kernel';
|
|
2
|
-
import { type AppTokenSource } from '@cat-factory/server';
|
|
3
|
-
import type { PatAccount } from './installations.js';
|
|
4
|
-
/**
|
|
5
|
-
* A GitHub "new personal access token (classic)" URL with the scopes local mode needs
|
|
6
|
-
* pre-selected, so a developer without a PAT can click straight through to create one.
|
|
7
|
-
* Classic tokens are used (not fine-grained) because only the classic form accepts the
|
|
8
|
-
* `scopes` query param for pre-selection.
|
|
9
|
-
*/
|
|
10
|
-
export declare function githubPatCreationUrl(): string;
|
|
11
|
-
/** An {@link AppTokenSource} that returns a fixed PAT for every installation call. */
|
|
12
|
-
export declare class StaticTokenAppRegistry implements AppTokenSource {
|
|
13
|
-
private readonly token;
|
|
14
|
-
readonly defaultAppId = "";
|
|
15
|
-
constructor(token: string);
|
|
16
|
-
apps(): readonly {
|
|
17
|
-
appId: string;
|
|
18
|
-
}[];
|
|
19
|
-
authForApp(): {
|
|
20
|
-
appJwt(): Promise<string>;
|
|
21
|
-
};
|
|
22
|
-
installationToken(): Promise<string>;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Read the PAT's own account (`GET /user`) so a synthetic installation can be attributed
|
|
26
|
-
* to it in the connect UI. Best-effort: a failed/forbidden call falls back to an empty
|
|
27
|
-
* login (the link flow only needs the installation row to exist, not its account label).
|
|
28
|
-
*/
|
|
29
|
-
export declare function fetchPatAccount(env: NodeJS.ProcessEnv): Promise<PatAccount>;
|
|
30
|
-
/**
|
|
31
|
-
* Build a {@link GitHubClient} that authenticates with the PAT, for the CI / merge /
|
|
32
|
-
* mergeability gates AND the repo-link / board "add from repo" flows. Returns undefined
|
|
33
|
-
* when no PAT is configured (the gates then pass through, like the Node default).
|
|
34
|
-
*/
|
|
35
|
-
export declare function createLocalGitHubClient(env: NodeJS.ProcessEnv): GitHubClient | undefined;
|
|
36
|
-
//# sourceMappingURL=github.d.ts.map
|
package/dist/github.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,YAAY,EAMb,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,qBAAqB,CAAA;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAgBpD;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C;AAED,sFAAsF;AACtF,qBAAa,sBAAuB,YAAW,cAAc;IAE/C,OAAO,CAAC,QAAQ,CAAC,KAAK;IADlC,QAAQ,CAAC,YAAY,MAAK;IAC1B,YAA6B,KAAK,EAAE,MAAM,EAAI;IAE9C,IAAI,IAAI,SAAS;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAEnC;IAED,UAAU,IAAI;QAAE,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,CAK1C;IAED,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEnC;CACF;AAoGD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBjF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,YAAY,GAAG,SAAS,CAgBxF"}
|
package/dist/github.js
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { FetchGitHubClient } from '@cat-factory/server';
|
|
3
|
-
// PAT-backed GitHub access for local mode. The shared FetchGitHubClient normally mints
|
|
4
|
-
// per-installation tokens via the GitHub App registry; here we feed it a static-token
|
|
5
|
-
// source returning the developer's PAT, so the CI gate + merge / mergeability
|
|
6
|
-
// providers (wired in container.ts from this client) hit real GitHub with the PAT.
|
|
7
|
-
//
|
|
8
|
-
// The app-JWT paths (installation discovery / listing) are never reached in local
|
|
9
|
-
// mode — those are the GitHub-App connect flow, which local mode replaces with the
|
|
10
|
-
// linkRepo helper — so they throw rather than pretend to work.
|
|
11
|
-
// The scopes a local-mode PAT needs. Agent containers clone/push branches and open PRs
|
|
12
|
-
// (`repo`, which also covers reading the PR head's Actions check runs for the CI gate and
|
|
13
|
-
// merging the PR), and the coder/ci-fixer may touch `.github/workflows/*` files (`workflow`).
|
|
14
|
-
const LOCAL_PAT_SCOPES = ['repo', 'workflow'];
|
|
15
|
-
/**
|
|
16
|
-
* A GitHub "new personal access token (classic)" URL with the scopes local mode needs
|
|
17
|
-
* pre-selected, so a developer without a PAT can click straight through to create one.
|
|
18
|
-
* Classic tokens are used (not fine-grained) because only the classic form accepts the
|
|
19
|
-
* `scopes` query param for pre-selection.
|
|
20
|
-
*/
|
|
21
|
-
export function githubPatCreationUrl() {
|
|
22
|
-
const params = new URLSearchParams({
|
|
23
|
-
description: 'cat-factory local mode',
|
|
24
|
-
scopes: LOCAL_PAT_SCOPES.join(','),
|
|
25
|
-
});
|
|
26
|
-
return `https://github.com/settings/tokens/new?${params.toString()}`;
|
|
27
|
-
}
|
|
28
|
-
/** An {@link AppTokenSource} that returns a fixed PAT for every installation call. */
|
|
29
|
-
export class StaticTokenAppRegistry {
|
|
30
|
-
token;
|
|
31
|
-
defaultAppId = '';
|
|
32
|
-
constructor(token) {
|
|
33
|
-
this.token = token;
|
|
34
|
-
}
|
|
35
|
-
apps() {
|
|
36
|
-
return [{ appId: '' }];
|
|
37
|
-
}
|
|
38
|
-
authForApp() {
|
|
39
|
-
return {
|
|
40
|
-
appJwt: () => Promise.reject(new Error('GitHub App JWT is not available in local (PAT) mode')),
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
installationToken() {
|
|
44
|
-
return Promise.resolve(this.token);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/** Rate-limit accounting is best-effort telemetry the local facade simply drops. */
|
|
48
|
-
class NoopRateLimitRepository {
|
|
49
|
-
record(_snapshot) {
|
|
50
|
-
return Promise.resolve();
|
|
51
|
-
}
|
|
52
|
-
deleteOlderThan(_epochMs) {
|
|
53
|
-
return Promise.resolve(0);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const localIdGenerator = {
|
|
57
|
-
next: (prefix) => (prefix ? `${prefix}_${randomUUID()}` : randomUUID()),
|
|
58
|
-
};
|
|
59
|
-
const localClock = { now: () => Date.now() };
|
|
60
|
-
const PER_PAGE = 100;
|
|
61
|
-
const MAX_PAGES = 20;
|
|
62
|
-
/** Parse the `rel="next"` URL out of a GitHub `Link` response header, if present. */
|
|
63
|
-
function nextLink(header) {
|
|
64
|
-
if (!header)
|
|
65
|
-
return null;
|
|
66
|
-
for (const part of header.split(',')) {
|
|
67
|
-
const m = part.match(/<([^>]+)>\s*;\s*rel="next"/);
|
|
68
|
-
if (m)
|
|
69
|
-
return m[1] ?? null;
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
function toRepoProjection(p, installationId, syncedAt) {
|
|
74
|
-
return {
|
|
75
|
-
githubId: p.id,
|
|
76
|
-
installationId,
|
|
77
|
-
owner: p.owner?.login ?? '',
|
|
78
|
-
name: p.name,
|
|
79
|
-
defaultBranch: p.default_branch ?? null,
|
|
80
|
-
private: p.private ?? false,
|
|
81
|
-
blockId: null,
|
|
82
|
-
syncedAt,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
function patHeaders(pat) {
|
|
86
|
-
return {
|
|
87
|
-
authorization: `Bearer ${pat}`,
|
|
88
|
-
accept: 'application/vnd.github+json',
|
|
89
|
-
'x-github-api-version': '2022-11-28',
|
|
90
|
-
'user-agent': 'cat-factory',
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* A {@link FetchGitHubClient} that lists repos a PAT can access via `/user/repos`, the
|
|
95
|
-
* personal-token analogue of the App-only `/installation/repositories` the base client
|
|
96
|
-
* uses (which 403s for a PAT). The board's "Add from existing repo" picker, the
|
|
97
|
-
* link-a-repo flow and the monorepo browser all enumerate repos through
|
|
98
|
-
* `listInstallationRepos`, so overriding this one method makes them work under a PAT.
|
|
99
|
-
* Every other call (repo/branch/PR/issue reads, merges) already works with the PAT via
|
|
100
|
-
* the installation-token paths, so they fall through to the base implementation.
|
|
101
|
-
*/
|
|
102
|
-
class PatGitHubClient extends FetchGitHubClient {
|
|
103
|
-
pat;
|
|
104
|
-
apiBase;
|
|
105
|
-
clock;
|
|
106
|
-
constructor(deps, pat, apiBase, clock) {
|
|
107
|
-
super(deps);
|
|
108
|
-
this.pat = pat;
|
|
109
|
-
this.apiBase = apiBase;
|
|
110
|
-
this.clock = clock;
|
|
111
|
-
}
|
|
112
|
-
async listInstallationRepos(installationId) {
|
|
113
|
-
const syncedAt = this.clock.now();
|
|
114
|
-
const items = [];
|
|
115
|
-
let url = `${this.apiBase}/user/repos?per_page=${PER_PAGE}&sort=full_name&affiliation=owner,collaborator,organization_member`;
|
|
116
|
-
for (let page = 0; url && page < MAX_PAGES; page++) {
|
|
117
|
-
const res = await fetch(url, { headers: patHeaders(this.pat) });
|
|
118
|
-
if (!res.ok) {
|
|
119
|
-
const text = await res.text().catch(() => '');
|
|
120
|
-
throw new Error(`GitHub /user/repos failed (HTTP ${res.status}): ${text.slice(0, 200)}`);
|
|
121
|
-
}
|
|
122
|
-
const payload = (await res.json());
|
|
123
|
-
for (const repo of payload)
|
|
124
|
-
items.push(toRepoProjection(repo, installationId, syncedAt));
|
|
125
|
-
url = nextLink(res.headers.get('link'));
|
|
126
|
-
}
|
|
127
|
-
return { items };
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Read the PAT's own account (`GET /user`) so a synthetic installation can be attributed
|
|
132
|
-
* to it in the connect UI. Best-effort: a failed/forbidden call falls back to an empty
|
|
133
|
-
* login (the link flow only needs the installation row to exist, not its account label).
|
|
134
|
-
*/
|
|
135
|
-
export async function fetchPatAccount(env) {
|
|
136
|
-
const fallback = { accountId: null, accountLogin: '', targetType: 'User' };
|
|
137
|
-
const pat = env.GITHUB_PAT?.trim();
|
|
138
|
-
if (!pat)
|
|
139
|
-
return fallback;
|
|
140
|
-
const apiBase = (env.GITHUB_API_BASE?.trim() || 'https://api.github.com').replace(/\/+$/, '');
|
|
141
|
-
try {
|
|
142
|
-
const res = await fetch(`${apiBase}/user`, { headers: patHeaders(pat) });
|
|
143
|
-
if (!res.ok)
|
|
144
|
-
return fallback;
|
|
145
|
-
const user = (await res.json());
|
|
146
|
-
return {
|
|
147
|
-
accountId: user.id != null ? String(user.id) : null,
|
|
148
|
-
accountLogin: user.login ?? '',
|
|
149
|
-
targetType: user.type === 'Organization' ? 'Organization' : 'User',
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
catch {
|
|
153
|
-
return fallback;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Build a {@link GitHubClient} that authenticates with the PAT, for the CI / merge /
|
|
158
|
-
* mergeability gates AND the repo-link / board "add from repo" flows. Returns undefined
|
|
159
|
-
* when no PAT is configured (the gates then pass through, like the Node default).
|
|
160
|
-
*/
|
|
161
|
-
export function createLocalGitHubClient(env) {
|
|
162
|
-
const pat = env.GITHUB_PAT?.trim();
|
|
163
|
-
if (!pat)
|
|
164
|
-
return undefined;
|
|
165
|
-
const apiBase = env.GITHUB_API_BASE?.trim() || 'https://api.github.com';
|
|
166
|
-
return new PatGitHubClient({
|
|
167
|
-
registry: new StaticTokenAppRegistry(pat),
|
|
168
|
-
rateLimitRepository: new NoopRateLimitRepository(),
|
|
169
|
-
idGenerator: localIdGenerator,
|
|
170
|
-
clock: localClock,
|
|
171
|
-
apiBase,
|
|
172
|
-
}, pat, apiBase, localClock);
|
|
173
|
-
}
|
|
174
|
-
//# sourceMappingURL=github.js.map
|
package/dist/github.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { startLocal } from './server.js';
|
|
2
|
-
export { buildLocalContainer } from './container.js';
|
|
3
|
-
export { loadLocalConfig, applyLocalDefaults } from './config.js';
|
|
4
|
-
export { LocalDockerRunnerTransport, createLocalDockerTransportFromEnv, type LocalDockerRunnerTransportOptions, type DockerExec, } from './LocalDockerRunnerTransport.js';
|
|
5
|
-
export { linkRepo, type LinkRepoOptions, type LinkedRepo } from './linkRepo.js';
|
|
6
|
-
export { createLocalGitHubClient, StaticTokenAppRegistry } from './github.js';
|
|
7
|
-
export { registerAgentKind, registerAgentKinds, clearRegisteredAgentKinds, type AgentKindDefinition, } from '@cat-factory/agents';
|
|
8
|
-
export { registerPipeline, registerPipelines, clearRegisteredPipelines } from '@cat-factory/kernel';
|
|
9
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,EACjC,KAAK,iCAAiC,EACtC,KAAK,UAAU,GAChB,MAAM,iCAAiC,CAAA;AAIxC,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAE/E,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAI7E,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA"}
|
package/dist/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// @cat-factory/local-server — the local-mode runtime facade. It is the Node.js
|
|
2
|
-
// facade (@cat-factory/node-server: shared Hono app + Drizzle/Postgres + pg-boss)
|
|
3
|
-
// with two differentiators so a developer can run the whole product on their own
|
|
4
|
-
// machine: agent jobs run as per-job local Docker/Podman containers, and GitHub is
|
|
5
|
-
// reached via a personal access token (no GitHub App). `startLocal()` boots the
|
|
6
|
-
// service; `buildLocalContainer()` is the composition root.
|
|
7
|
-
export { startLocal } from './server.js';
|
|
8
|
-
export { buildLocalContainer } from './container.js';
|
|
9
|
-
export { loadLocalConfig, applyLocalDefaults } from './config.js';
|
|
10
|
-
export { LocalDockerRunnerTransport, createLocalDockerTransportFromEnv, } from './LocalDockerRunnerTransport.js';
|
|
11
|
-
// Seed the github_installations/github_repos projection so container agent steps can
|
|
12
|
-
// resolve a target repo in local mode (no GitHub App connect flow). Also a CLI:
|
|
13
|
-
// `node dist/link-repo.js <workspaceId> <frameBlockId> <owner/repo>`.
|
|
14
|
-
export { linkRepo } from './linkRepo.js';
|
|
15
|
-
// PAT-backed GitHub access for the CI gate + merge / mergeability providers.
|
|
16
|
-
export { createLocalGitHubClient, StaticTokenAppRegistry } from './github.js';
|
|
17
|
-
// Installation-level extension points, re-exported for parity with the Node facade so
|
|
18
|
-
// a local deployment can register custom agent kinds / pipelines before `startLocal()`.
|
|
19
|
-
export { registerAgentKind, registerAgentKinds, clearRegisteredAgentKinds, } from '@cat-factory/agents';
|
|
20
|
-
export { registerPipeline, registerPipelines, clearRegisteredPipelines } from '@cat-factory/kernel';
|
|
21
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,kFAAkF;AAClF,iFAAiF;AACjF,mFAAmF;AACnF,gFAAgF;AAChF,4DAA4D;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,GAGlC,MAAM,iCAAiC,CAAA;AACxC,qFAAqF;AACrF,gFAAgF;AAChF,sEAAsE;AACtE,OAAO,EAAE,QAAQ,EAAyC,MAAM,eAAe,CAAA;AAC/E,6EAA6E;AAC7E,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAE7E,sFAAsF;AACtF,wFAAwF;AACxF,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAE1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA"}
|
package/dist/installations.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { GitHubInstallation, GitHubInstallationRepository } from '@cat-factory/kernel';
|
|
2
|
-
/** A stable, positive, safe-integer installation id derived from the workspace id. */
|
|
3
|
-
export declare function syntheticInstallationId(workspaceId: string): number;
|
|
4
|
-
/** The PAT account a synthetic installation is attributed to (shown in the connect UI). */
|
|
5
|
-
export interface PatAccount {
|
|
6
|
-
accountId: string | null;
|
|
7
|
-
accountLogin: string;
|
|
8
|
-
targetType: 'Organization' | 'User';
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Wraps a real {@link GitHubInstallationRepository} so that, in local PAT mode, a
|
|
12
|
-
* workspace's installation is conjured on first read instead of requiring a connect flow.
|
|
13
|
-
* Every method delegates to the inner repository; only {@link getByWorkspace} adds the
|
|
14
|
-
* lazy provision (and only when no live row exists — a CLI-seeded or already-provisioned
|
|
15
|
-
* row is returned untouched). The provisioned row carries the synthetic id, so a repo
|
|
16
|
-
* later linked via the CLI lands under the same installation.
|
|
17
|
-
*/
|
|
18
|
-
export declare class AutoProvisioningInstallationRepository implements GitHubInstallationRepository {
|
|
19
|
-
private readonly inner;
|
|
20
|
-
private readonly resolveAccount;
|
|
21
|
-
private readonly now;
|
|
22
|
-
constructor(inner: GitHubInstallationRepository, resolveAccount: () => Promise<PatAccount>, now?: () => number);
|
|
23
|
-
getByWorkspace(workspaceId: string): Promise<GitHubInstallation | null>;
|
|
24
|
-
getByInstallationId(installationId: number): Promise<GitHubInstallation | null>;
|
|
25
|
-
listWorkspacesForInstallation(installationId: number): Promise<string[]>;
|
|
26
|
-
listActive(): Promise<GitHubInstallation[]>;
|
|
27
|
-
upsert(installation: GitHubInstallation): Promise<void>;
|
|
28
|
-
updateCachedToken(installationId: number, token: string, expiresAt: number): Promise<void>;
|
|
29
|
-
softDelete(installationId: number, at: number): Promise<void>;
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=installations.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"installations.d.ts","sourceRoot":"","sources":["../src/installations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAA;AAa3F,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMnE;AAED,2FAA2F;AAC3F,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,cAAc,GAAG,MAAM,CAAA;CACpC;AAED;;;;;;;GAOG;AACH,qBAAa,sCAAuC,YAAW,4BAA4B;IAEvF,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHtB,YACmB,KAAK,EAAE,4BAA4B,EACnC,cAAc,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,EACzC,GAAG,GAAE,MAAM,MAAyB,EACnD;IAEE,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAkB5E;IAED,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAE9E;IAED,6BAA6B,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAEvE;IAED,UAAU,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAE1C;IAED,MAAM,CAAC,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtD;IAED,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF;IAED,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;CACF"}
|
package/dist/installations.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
// Local mode has no GitHub-App connect flow: a single developer runs the whole product
|
|
3
|
-
// against one PAT. So instead of binding a real App installation, every workspace is
|
|
4
|
-
// implicitly "connected" to the PAT. This module supplies the two pieces that makes the
|
|
5
|
-
// shared GitHub integration work that way:
|
|
6
|
-
// - `syntheticInstallationId`: a stable per-workspace id (the projection rows the CLI
|
|
7
|
-
// `linkRepo` helper and the in-UI link flow both write key off it, so they agree);
|
|
8
|
-
// - `AutoProvisioningInstallationRepository`: a decorator that lazily materialises that
|
|
9
|
-
// synthetic `github_installations` row the first time a workspace's installation is
|
|
10
|
-
// read, so `getConnection` reports connected and the sync service has an
|
|
11
|
-
// installation id to list/link repos under — no manual connect step.
|
|
12
|
-
/** A stable, positive, safe-integer installation id derived from the workspace id. */
|
|
13
|
-
export function syntheticInstallationId(workspaceId) {
|
|
14
|
-
// 48 bits keeps it well inside Number.MAX_SAFE_INTEGER and the bigint column; the value
|
|
15
|
-
// is per-workspace (the table's workspace_id is unique) so two workspaces never collide,
|
|
16
|
-
// and re-provisioning a workspace reuses the same id (upsert, not a new row).
|
|
17
|
-
const hex = createHash('sha1').update(workspaceId).digest('hex').slice(0, 12);
|
|
18
|
-
return Number.parseInt(hex, 16);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Wraps a real {@link GitHubInstallationRepository} so that, in local PAT mode, a
|
|
22
|
-
* workspace's installation is conjured on first read instead of requiring a connect flow.
|
|
23
|
-
* Every method delegates to the inner repository; only {@link getByWorkspace} adds the
|
|
24
|
-
* lazy provision (and only when no live row exists — a CLI-seeded or already-provisioned
|
|
25
|
-
* row is returned untouched). The provisioned row carries the synthetic id, so a repo
|
|
26
|
-
* later linked via the CLI lands under the same installation.
|
|
27
|
-
*/
|
|
28
|
-
export class AutoProvisioningInstallationRepository {
|
|
29
|
-
inner;
|
|
30
|
-
resolveAccount;
|
|
31
|
-
now;
|
|
32
|
-
constructor(inner, resolveAccount, now = () => Date.now()) {
|
|
33
|
-
this.inner = inner;
|
|
34
|
-
this.resolveAccount = resolveAccount;
|
|
35
|
-
this.now = now;
|
|
36
|
-
}
|
|
37
|
-
async getByWorkspace(workspaceId) {
|
|
38
|
-
const existing = await this.inner.getByWorkspace(workspaceId);
|
|
39
|
-
if (existing && !existing.deletedAt)
|
|
40
|
-
return existing;
|
|
41
|
-
const account = await this.resolveAccount();
|
|
42
|
-
const installation = {
|
|
43
|
-
installationId: syntheticInstallationId(workspaceId),
|
|
44
|
-
workspaceId,
|
|
45
|
-
accountId: account.accountId,
|
|
46
|
-
accountLogin: account.accountLogin,
|
|
47
|
-
targetType: account.targetType,
|
|
48
|
-
appId: null,
|
|
49
|
-
cachedToken: null,
|
|
50
|
-
tokenExpiresAt: null,
|
|
51
|
-
createdAt: this.now(),
|
|
52
|
-
deletedAt: null,
|
|
53
|
-
};
|
|
54
|
-
await this.inner.upsert(installation);
|
|
55
|
-
return installation;
|
|
56
|
-
}
|
|
57
|
-
getByInstallationId(installationId) {
|
|
58
|
-
return this.inner.getByInstallationId(installationId);
|
|
59
|
-
}
|
|
60
|
-
listWorkspacesForInstallation(installationId) {
|
|
61
|
-
return this.inner.listWorkspacesForInstallation(installationId);
|
|
62
|
-
}
|
|
63
|
-
listActive() {
|
|
64
|
-
return this.inner.listActive();
|
|
65
|
-
}
|
|
66
|
-
upsert(installation) {
|
|
67
|
-
return this.inner.upsert(installation);
|
|
68
|
-
}
|
|
69
|
-
updateCachedToken(installationId, token, expiresAt) {
|
|
70
|
-
return this.inner.updateCachedToken(installationId, token, expiresAt);
|
|
71
|
-
}
|
|
72
|
-
softDelete(installationId, at) {
|
|
73
|
-
return this.inner.softDelete(installationId, at);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=installations.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"installations.js","sourceRoot":"","sources":["../src/installations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,uFAAuF;AACvF,qFAAqF;AACrF,wFAAwF;AACxF,2CAA2C;AAC3C,wFAAwF;AACxF,uFAAuF;AACvF,0FAA0F;AAC1F,wFAAwF;AACxF,6EAA6E;AAC7E,yEAAyE;AAEzE,sFAAsF;AACtF,MAAM,UAAU,uBAAuB,CAAC,WAAmB;IACzD,wFAAwF;IACxF,yFAAyF;IACzF,8EAA8E;IAC9E,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC7E,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AACjC,CAAC;AASD;;;;;;;GAOG;AACH,MAAM,OAAO,sCAAsC;IAE9B,KAAK;IACL,cAAc;IACd,GAAG;IAHtB,YACmB,KAAmC,EACnC,cAAyC,EACzC,GAAG,GAAiB,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;qBAFpC,KAAK;8BACL,cAAc;mBACd,GAAG;IACnB,CAAC;IAEJ,KAAK,CAAC,cAAc,CAAC,WAAmB;QACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;QAC7D,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,SAAS;YAAE,OAAO,QAAQ,CAAA;QACpD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;QAC3C,MAAM,YAAY,GAAuB;YACvC,cAAc,EAAE,uBAAuB,CAAC,WAAW,CAAC;YACpD,WAAW;YACX,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,IAAI;YACjB,cAAc,EAAE,IAAI;YACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI;SAChB,CAAA;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;QACrC,OAAO,YAAY,CAAA;IACrB,CAAC;IAED,mBAAmB,CAAC,cAAsB;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAA;IACvD,CAAC;IAED,6BAA6B,CAAC,cAAsB;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,cAAc,CAAC,CAAA;IACjE,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA;IAChC,CAAC;IAED,MAAM,CAAC,YAAgC;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACxC,CAAC;IAED,iBAAiB,CAAC,cAAsB,EAAE,KAAa,EAAE,SAAiB;QACxE,OAAO,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;IACvE,CAAC;IAED,UAAU,CAAC,cAAsB,EAAE,EAAU;QAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,CAAA;IAClD,CAAC;CACF"}
|
package/dist/link-repo.d.ts
DELETED
package/dist/link-repo.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link-repo.d.ts","sourceRoot":"","sources":["../src/link-repo.ts"],"names":[],"mappings":""}
|
package/dist/link-repo.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { linkRepo } from './linkRepo.js';
|
|
2
|
-
// Small CLI to link a real GitHub repo to a board service frame in local mode:
|
|
3
|
-
// node dist/link-repo.js <workspaceId> <frameBlockId> <owner/repo>
|
|
4
|
-
// Reads GITHUB_PAT + DATABASE_URL from the environment (load a .env via Node's
|
|
5
|
-
// `--env-file-if-exists`). Seeds the github_installations + github_repos rows the
|
|
6
|
-
// container executor resolves a run's target repo from.
|
|
7
|
-
const [workspaceId, frameBlockId, repo] = process.argv.slice(2);
|
|
8
|
-
if (!workspaceId || !frameBlockId || !repo) {
|
|
9
|
-
console.error('usage: link-repo <workspaceId> <frameBlockId> <owner/repo>');
|
|
10
|
-
process.exit(2);
|
|
11
|
-
}
|
|
12
|
-
linkRepo({ workspaceId, frameBlockId, repo })
|
|
13
|
-
.then((r) => {
|
|
14
|
-
console.log(`linked ${r.owner}/${r.name} (#${r.githubId}) → frame ${frameBlockId} ` +
|
|
15
|
-
`[default branch: ${r.defaultBranch}, installation ${r.installationId}]`);
|
|
16
|
-
})
|
|
17
|
-
.catch((err) => {
|
|
18
|
-
console.error('link failed:', err instanceof Error ? err.message : String(err));
|
|
19
|
-
process.exit(1);
|
|
20
|
-
});
|
|
21
|
-
//# sourceMappingURL=link-repo.js.map
|
package/dist/link-repo.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link-repo.js","sourceRoot":"","sources":["../src/link-repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,+EAA+E;AAC/E,qEAAqE;AACrE,+EAA+E;AAC/E,kFAAkF;AAClF,wDAAwD;AACxD,MAAM,CAAC,WAAW,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAE/D,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3C,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAA;IAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,QAAQ,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;KAC1C,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;IACV,OAAO,CAAC,GAAG,CACT,UAAU,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,QAAQ,aAAa,YAAY,GAAG;QACrE,oBAAoB,CAAC,CAAC,aAAa,kBAAkB,CAAC,CAAC,cAAc,GAAG,CAC3E,CAAA;AACH,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
package/dist/linkRepo.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { type DrizzleDb } from '@cat-factory/node-server';
|
|
2
|
-
export interface LinkRepoOptions {
|
|
3
|
-
/** The board workspace id. */
|
|
4
|
-
workspaceId: string;
|
|
5
|
-
/** The service-frame block id tasks will sit under (the repo links to this). */
|
|
6
|
-
frameBlockId: string;
|
|
7
|
-
/** The repository, as `owner/name`. */
|
|
8
|
-
repo: string;
|
|
9
|
-
/** Pre-built Drizzle client; else one is opened from {@link databaseUrl}. */
|
|
10
|
-
db?: DrizzleDb;
|
|
11
|
-
/** `DATABASE_URL`; required when {@link db} is not supplied. */
|
|
12
|
-
databaseUrl?: string;
|
|
13
|
-
/** The PAT; defaults to `env.GITHUB_PAT`. */
|
|
14
|
-
pat?: string;
|
|
15
|
-
/** GitHub API base; defaults to `env.GITHUB_API_BASE` or api.github.com. */
|
|
16
|
-
apiBase?: string;
|
|
17
|
-
/** Environment source for the PAT / API base defaults. */
|
|
18
|
-
env?: NodeJS.ProcessEnv;
|
|
19
|
-
/** Injectable fetch (tests). */
|
|
20
|
-
fetchImpl?: typeof fetch;
|
|
21
|
-
}
|
|
22
|
-
export interface LinkedRepo {
|
|
23
|
-
owner: string;
|
|
24
|
-
name: string;
|
|
25
|
-
githubId: number;
|
|
26
|
-
installationId: number;
|
|
27
|
-
defaultBranch: string;
|
|
28
|
-
private: boolean;
|
|
29
|
-
}
|
|
30
|
-
export declare function linkRepo(options: LinkRepoOptions): Promise<LinkedRepo>;
|
|
31
|
-
//# sourceMappingURL=linkRepo.d.ts.map
|
package/dist/linkRepo.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"linkRepo.d.ts","sourceRoot":"","sources":["../src/linkRepo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAA0B,MAAM,0BAA0B,CAAA;AAkBjF,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,EAAE,CAAC,EAAE,SAAS,CAAA;IACd,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,gCAAgC;IAChC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAgH5E"}
|