@webship.co/workspace-forge 0.0.0-stage → 1.0.0-alpha1
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 +17 -2
- package/css/forge.css +12 -0
- package/dist/src/index.d.ts +19 -0
- package/dist/src/index.js +212 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/provider.d.ts +74 -0
- package/dist/src/provider.js +12 -0
- package/dist/src/provider.js.map +1 -0
- package/package.json +29 -4
package/README.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @webship.co/workspace-forge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The forge family's shared base for [Webship Workspace](https://github.com/webship/workspace)
|
|
4
|
+
plugins. A forge plugin (`@webship.co/workspace-github`, `-gitlab`, `-bitbucket`) is one call plus its
|
|
5
|
+
provider:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { registerForge } from '@webship.co/workspace-forge';
|
|
9
|
+
export function register(api: PluginApi) { registerForge(api, provider(api)); }
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`registerForge` registers the credential the dashboard uses for the host (`api.addForge`, which
|
|
13
|
+
`gh`-based work such as the AI-items sync picks up), draws the row menu on every project whose git
|
|
14
|
+
remote is at the host (open the repository, the open issues and pull or merge requests in the modal,
|
|
15
|
+
open a request from the current branch in a terminal, copy the clone URL), the repository chip on
|
|
16
|
+
the card, and the "Clone a repository into this folder" option of New folder. The `ForgeProvider`
|
|
17
|
+
says what differs between forges: the host, the CLI, how a remote URL reads, where the pages are,
|
|
18
|
+
how the open issues and requests are listed, the command that opens a request, the clone URL.
|
package/css/forge.css
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* The forge family: the per-forge menu, the repository chip and the New-folder clone option.
|
|
2
|
+
Appended to the dashboard stylesheet after the components, so it may only ADD rules. */
|
|
3
|
+
.forge-menu-repo { text-transform: none; font-family: var(--font-code); }
|
|
4
|
+
.forge-menu-note { text-transform: none; font-weight: 400; opacity: .75; white-space: normal; }
|
|
5
|
+
.forge-menu-note code { white-space: normal; overflow-wrap: anywhere; }
|
|
6
|
+
.forge-unlinked { opacity: .75; }
|
|
7
|
+
.forge-unlinked:hover { opacity: 1; }
|
|
8
|
+
.pcard-meta .proj-forge-link { max-width: 13rem; }
|
|
9
|
+
.proj-forge-link { white-space: nowrap; }
|
|
10
|
+
.forge-items .uk-text-meta { margin-left: .4rem; }
|
|
11
|
+
.folder-new-form .folder-forge-repo { display: none; }
|
|
12
|
+
.folder-new-form .folder-forge:has(input[value="clone"]:checked) .folder-forge-repo { display: block; }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* registerForge(api, forge): the whole surface of a forge plugin, from a provider's facts.
|
|
3
|
+
*
|
|
4
|
+
* The credential the dashboard uses for the host (api.addForge), the row menu on every project
|
|
5
|
+
* whose git remote is at the host (repository, issues, pull requests, open one from the branch),
|
|
6
|
+
* the repository chip on the card, the issues and requests modals, and the "Clone from <forge>"
|
|
7
|
+
* option when a new folder is made. What differs between forges is in the provider.
|
|
8
|
+
*/
|
|
9
|
+
import type { PluginApi } from '@webship.co/workspace-plugin-api';
|
|
10
|
+
import type { ForgeProvider, ForgeRepo } from './provider';
|
|
11
|
+
export * from './provider';
|
|
12
|
+
/** The remotes of a repository folder: name -> url. */
|
|
13
|
+
export declare function gitRemotes(projectDir: string): Record<string, string>;
|
|
14
|
+
export declare function gitBranch(projectDir: string): string | null;
|
|
15
|
+
/** The repository of the folder on this forge: origin first, then any remote. */
|
|
16
|
+
export declare function repoOnForge(forge: ForgeProvider, projectDir: string): ForgeRepo | null;
|
|
17
|
+
/** 'owner/name' from a remote URL at `host`, in the ssh, https and ssh:// spellings; null otherwise. */
|
|
18
|
+
export declare function repoPathAt(host: string, url: string): string | null;
|
|
19
|
+
export declare function registerForge(api: PluginApi, f: ForgeProvider): void;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* registerForge(api, forge): the whole surface of a forge plugin, from a provider's facts.
|
|
4
|
+
*
|
|
5
|
+
* The credential the dashboard uses for the host (api.addForge), the row menu on every project
|
|
6
|
+
* whose git remote is at the host (repository, issues, pull requests, open one from the branch),
|
|
7
|
+
* the repository chip on the card, the issues and requests modals, and the "Clone from <forge>"
|
|
8
|
+
* option when a new folder is made. What differs between forges is in the provider.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
25
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.gitRemotes = gitRemotes;
|
|
29
|
+
exports.gitBranch = gitBranch;
|
|
30
|
+
exports.repoOnForge = repoOnForge;
|
|
31
|
+
exports.repoPathAt = repoPathAt;
|
|
32
|
+
exports.registerForge = registerForge;
|
|
33
|
+
const fs_1 = __importDefault(require("fs"));
|
|
34
|
+
const path_1 = __importDefault(require("path"));
|
|
35
|
+
__exportStar(require("./provider"), exports);
|
|
36
|
+
/** The remotes of a repository folder: name -> url. */
|
|
37
|
+
function gitRemotes(projectDir) {
|
|
38
|
+
let cfg;
|
|
39
|
+
try {
|
|
40
|
+
cfg = fs_1.default.readFileSync(path_1.default.join(projectDir, '.git', 'config'), 'utf8');
|
|
41
|
+
}
|
|
42
|
+
catch (_) {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
const out = {};
|
|
46
|
+
for (const m of cfg.matchAll(/\[remote "([^"]+)"\]([^[]*)/g)) {
|
|
47
|
+
const url = (m[2].match(/url\s*=\s*(\S+)/) || [])[1];
|
|
48
|
+
if (url)
|
|
49
|
+
out[m[1]] = url;
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
function gitBranch(projectDir) {
|
|
54
|
+
try {
|
|
55
|
+
const head = fs_1.default.readFileSync(path_1.default.join(projectDir, '.git', 'HEAD'), 'utf8').trim();
|
|
56
|
+
return (head.match(/^ref: refs\/heads\/(.+)$/) || [])[1] || null;
|
|
57
|
+
}
|
|
58
|
+
catch (_) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** The repository of the folder on this forge: origin first, then any remote. */
|
|
63
|
+
function repoOnForge(forge, projectDir) {
|
|
64
|
+
const remotes = gitRemotes(projectDir);
|
|
65
|
+
const names = ['origin', ...Object.keys(remotes).filter((n) => n !== 'origin')];
|
|
66
|
+
for (const name of names) {
|
|
67
|
+
if (!remotes[name])
|
|
68
|
+
continue;
|
|
69
|
+
const r = forge.repoOf(remotes[name], name);
|
|
70
|
+
if (r)
|
|
71
|
+
return r;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
/** 'owner/name' from a remote URL at `host`, in the ssh, https and ssh:// spellings; null otherwise. */
|
|
76
|
+
function repoPathAt(host, url) {
|
|
77
|
+
const h = host.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
78
|
+
const m = url.match(new RegExp(`^(?:https?://(?:[^@/]+@)?${h}/|(?:ssh://)?(?:git@)?${h}[:/])(.+?)(?:\\.git)?/?$`, 'i'));
|
|
79
|
+
return m ? m[1] : null;
|
|
80
|
+
}
|
|
81
|
+
function registerForge(api, f) {
|
|
82
|
+
const { esc, workspaceDir, listProjects, screenAction, iconHtml, NAME_RE } = api.lib;
|
|
83
|
+
const post = (name) => `/actions/p/${api.name}/${name}`;
|
|
84
|
+
const shq = (v) => `'${String(v).replace(/'/g, `'\\''`)}'`;
|
|
85
|
+
if (typeof api.addForge === 'function')
|
|
86
|
+
api.addForge(f.host(), { label: f.title, env: f.env, auth: f.auth });
|
|
87
|
+
if (typeof api.addCss === 'function')
|
|
88
|
+
api.addCss(path_1.default.join(__dirname, '..', '..', 'css', 'forge.css'));
|
|
89
|
+
// ---- The menu on a project row ---------------------------------------------------------------
|
|
90
|
+
api.addRowMenu(f.id, { label: f.label, row: 0 }, ({ key, project, dir, vals }) => {
|
|
91
|
+
const pdir = path_1.default.join(dir, project);
|
|
92
|
+
if (!fs_1.default.existsSync(path_1.default.join(pdir, '.git')))
|
|
93
|
+
return null;
|
|
94
|
+
const repo = repoOnForge(f, pdir);
|
|
95
|
+
if (!repo)
|
|
96
|
+
return null;
|
|
97
|
+
const branch = gitBranch(pdir);
|
|
98
|
+
const u = f.urls(repo);
|
|
99
|
+
const caption = repo.remote === 'origin' ? 'origin' : repo.remote;
|
|
100
|
+
const modal = (name) => `hx-post="${post(name)}" hx-vals='{"workspace":"${esc(key)}","projectName":"${esc(project)}"}' hx-target="#editor-modal-body" hx-swap="innerHTML"`;
|
|
101
|
+
return `<span class="act-with-status"><div class="uk-inline act-menu act-menu-${esc(f.id)} act-menu-forge">
|
|
102
|
+
<button class="uk-button uk-button-default uk-button-small" type="button" title="${esc(repo.path)} on ${esc(f.title)}"><span uk-icon="icon: git-fork; ratio: .7"></span> ${esc(f.label)} <span uk-icon="icon: chevron-down; ratio: .6"></span></button>
|
|
103
|
+
<div uk-dropdown="mode: click; pos: bottom-right"><ul class="uk-nav uk-dropdown-nav">
|
|
104
|
+
<li class="uk-nav-header forge-menu-repo" data-group="repository">${esc(repo.path)}${branch ? ` · ${esc(branch)}` : ''}</li>
|
|
105
|
+
<li><a href="${esc(repo.web)}" target="_blank" rel="noopener"><span uk-icon="icon: link-external; ratio: .7"></span> Open the repository</a></li>
|
|
106
|
+
<li><a href ${modal('issues')}><span uk-icon="icon: warning; ratio: .7"></span> Open issues</a></li>
|
|
107
|
+
<li><a href ${modal('pulls')}><span uk-icon="icon: git-branch; ratio: .7"></span> Open ${esc(f.pullsLabel.toLowerCase())}</a></li>
|
|
108
|
+
<li class="uk-nav-divider"></li>
|
|
109
|
+
${branch && f.newPullCommand
|
|
110
|
+
? `<li><a href hx-post="${post('new-pull')}" ${vals()}><span uk-icon="icon: push; ratio: .7"></span> Open a ${esc(f.pullsLabel.toLowerCase().replace(/s$/, ''))} from ${esc(branch)}…</a></li>`
|
|
111
|
+
: `<li><a href="${esc(u.newPull(branch || ''))}" target="_blank" rel="noopener"><span uk-icon="icon: push; ratio: .7"></span> New ${esc(f.pullsLabel.toLowerCase().replace(/s$/, ''))}${branch ? ` from ${esc(branch)}` : ''}</a></li>`}
|
|
112
|
+
<li><a href="${esc(u.newIssue)}" target="_blank" rel="noopener"><span uk-icon="icon: plus-circle; ratio: .7"></span> New issue</a></li>
|
|
113
|
+
<li><a href="#" class="copy-cmd" data-copy="${esc(f.cloneUrl(repo.path))}" title="Copy the clone URL"><span uk-icon="icon: copy; ratio: .7"></span> Copy the clone URL</a></li>
|
|
114
|
+
</ul></div>
|
|
115
|
+
</div><span class="act-status uk-text-meta">${esc(caption)}</span></span>`;
|
|
116
|
+
});
|
|
117
|
+
// ---- The repository chip on the card ---------------------------------------------------------
|
|
118
|
+
api.addProjectChip(({ project, dir }) => {
|
|
119
|
+
const repo = repoOnForge(f, path_1.default.join(dir, project));
|
|
120
|
+
if (!repo)
|
|
121
|
+
return null;
|
|
122
|
+
return `<a class="proj-alias proj-plugin-link proj-forge-link proj-${esc(f.id)}-link" href="${esc(repo.web)}" target="_blank" rel="noopener"
|
|
123
|
+
title="${esc(repo.path)} on ${esc(f.title)}">${iconHtml('tabler:git-fork', 0.7)}<span class="pcard-chip-text">${esc(repo.path)}</span></a>`;
|
|
124
|
+
});
|
|
125
|
+
// ---- Issues and requests, listed in the modal -------------------------------------------------
|
|
126
|
+
const guard = ({ form, send, workspace }) => {
|
|
127
|
+
const dir = workspaceDir(workspace);
|
|
128
|
+
const project = String(form.projectName || '');
|
|
129
|
+
if (!NAME_RE.test(project) || !listProjects(dir).includes(project)) {
|
|
130
|
+
send('<div class="msg error">Unknown project.</div>', 400);
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const repo = repoOnForge(f, path_1.default.join(dir, project));
|
|
134
|
+
if (!repo) {
|
|
135
|
+
send(`<div class="msg error">This project has no git remote on ${esc(f.title)}.</div>`, 409);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
return { dir, project, repo };
|
|
139
|
+
};
|
|
140
|
+
const itemsHtml = (items, empty) => (items.length
|
|
141
|
+
? `<ul class="uk-list uk-list-divider forge-items">${items.map((i) => `<li><a href="${esc(i.url)}" target="_blank" rel="noopener">#${esc(i.number)} ${esc(i.title)}</a>${i.author ? `<span class="uk-text-meta">${esc(i.author)}</span>` : ''}${i.updated ? `<span class="uk-text-meta">${esc(String(i.updated).slice(0, 10))}</span>` : ''}</li>`).join('')}</ul>`
|
|
142
|
+
: `<p class="uk-text-meta">${esc(empty)}</p>`);
|
|
143
|
+
for (const [name, title, list, pageOf] of [
|
|
144
|
+
['issues', 'Open issues', (r, env) => f.listIssues(r, api.lib, env), (r) => f.urls(r).issues],
|
|
145
|
+
['pulls', `Open ${f.pullsLabel.toLowerCase()}`, (r, env) => f.listPulls(r, api.lib, env), (r) => f.urls(r).pulls],
|
|
146
|
+
]) {
|
|
147
|
+
api.addAction(name, async (ctx) => {
|
|
148
|
+
const g = guard(ctx);
|
|
149
|
+
if (!g)
|
|
150
|
+
return;
|
|
151
|
+
const env = f.env() || process.env;
|
|
152
|
+
let items = [];
|
|
153
|
+
let problem = '';
|
|
154
|
+
try {
|
|
155
|
+
items = await list(g.repo, env);
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
problem = String(e.message || e);
|
|
159
|
+
}
|
|
160
|
+
return ctx.send(`
|
|
161
|
+
<div class="editor-card">
|
|
162
|
+
<h3 class="uk-margin-small-bottom">${esc(title)} — ${esc(g.repo.path)}</h3>
|
|
163
|
+
<p class="uk-text-meta">On ${esc(f.title)}. <a href="${esc(pageOf(g.repo))}" target="_blank" rel="noopener">All of them</a>${!f.env() ? ` · no credential (${esc(f.tokenHint)}): a private repository answers nothing` : ''}</p>
|
|
164
|
+
${problem ? `<div class="msg error"><pre>${esc(problem)}</pre></div>` : itemsHtml(items, `No ${title.toLowerCase()}.`)}
|
|
165
|
+
</div>`);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// ---- A pull request from the current branch, in a terminal -------------------------------------
|
|
169
|
+
if (f.newPullCommand) {
|
|
170
|
+
const cmd = f.newPullCommand;
|
|
171
|
+
api.addAction('new-pull', (ctx) => {
|
|
172
|
+
const g = guard(ctx);
|
|
173
|
+
if (!g)
|
|
174
|
+
return;
|
|
175
|
+
const branch = gitBranch(path_1.default.join(g.dir, g.project));
|
|
176
|
+
if (!branch)
|
|
177
|
+
return ctx.send('<div class="msg error">The project is on a detached HEAD: check out a branch first.</div>', 409);
|
|
178
|
+
return screenAction(ctx.send, { workspace: ctx.workspace, project: g.project, projectDir: path_1.default.join(g.dir, g.project),
|
|
179
|
+
ownerDir: path_1.default.join(g.dir, g.project), verb: `${f.id}-pull-${branch.replace(/[^a-zA-Z0-9_-]+/g, '-')}`,
|
|
180
|
+
cmdLine: cmd(g.repo, branch), label: `${f.id}: ${f.pullsLabel.toLowerCase().replace(/s$/, '')} from ${branch}` });
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
// ---- New folder: clone from the forge ---------------------------------------------------------
|
|
184
|
+
api.addFolderSetup({
|
|
185
|
+
html: (ws) => `<div class="uk-margin-small-top folder-forge folder-${esc(f.id)}">
|
|
186
|
+
<span class="uk-text-meta">${esc(f.title)}:</span>
|
|
187
|
+
<label class="uk-margin-small-right"><input class="uk-radio" type="radio" name="${esc(f.id)}" value="none" checked> Not now</label>
|
|
188
|
+
<label><input class="uk-radio" type="radio" name="${esc(f.id)}" value="clone"> Clone a repository into this folder</label>
|
|
189
|
+
<div class="folder-forge-repo uk-margin-small-top">
|
|
190
|
+
<label class="uk-form-label" for="folder-${esc(f.id)}-repo">Repository (owner/name, or its URL)</label>
|
|
191
|
+
<input class="uk-input uk-form-small uk-form-width-large" id="folder-${esc(f.id)}-repo" name="${esc(f.id)}_repo" placeholder="${esc(f.clone.placeholder)}">
|
|
192
|
+
<span class="uk-text-meta">${esc(ws)} gets a clone; the folder must be new.</span>
|
|
193
|
+
</div>
|
|
194
|
+
</div>`,
|
|
195
|
+
steps: (_ws, name, form) => {
|
|
196
|
+
if (form[f.id] !== 'clone')
|
|
197
|
+
return [];
|
|
198
|
+
const spec = String(form[`${f.id}_repo`] || '').trim();
|
|
199
|
+
const env = f.cloneEnv ? `${f.cloneEnv()} ` : '';
|
|
200
|
+
// git clones into an existing EMPTY folder, which is what the setup made.
|
|
201
|
+
return [`${env}git clone ${shq(f.cloneUrl(spec))} ${shq(name)}`];
|
|
202
|
+
},
|
|
203
|
+
prompt: () => [],
|
|
204
|
+
problem: (_ws, form) => {
|
|
205
|
+
if (form[f.id] !== 'clone')
|
|
206
|
+
return '';
|
|
207
|
+
const spec = String(form[`${f.id}_repo`] || '').trim();
|
|
208
|
+
return f.clone.pattern.test(spec) ? '' : f.clone.help;
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;;;AAWH,gCASC;AAED,8BAKC;AAGD,kCASC;AAGD,gCAIC;AAED,sCAuHC;AArKD,4CAAoB;AACpB,gDAAwB;AAKxB,6CAA2B;AAE3B,uDAAuD;AACvD,SAAgB,UAAU,CAAC,UAAkB;IAC3C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QAAC,GAAG,GAAG,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;IACxG,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,8BAA8B,CAAC,EAAE,CAAC;QAC7D,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,GAAG;YAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAC3B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAgB,SAAS,CAAC,UAAkB;IAC1C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACnF,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACnE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC9B,CAAC;AAED,iFAAiF;AACjF,SAAgB,WAAW,CAAC,KAAoB,EAAE,UAAkB;IAClE,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;IAChF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wGAAwG;AACxG,SAAgB,UAAU,CAAC,IAAY,EAAE,GAAW;IAClD,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,4BAA4B,CAAC,yBAAyB,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC,CAAC;IACxH,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC;AAED,SAAgB,aAAa,CAAC,GAAc,EAAE,CAAgB;IAC5D,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC;IACrF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,cAAc,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;IAChE,MAAM,GAAG,GAAG,CAAC,CAAU,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;IAEpE,IAAI,OAAQ,GAAW,CAAC,QAAQ,KAAK,UAAU;QAAG,GAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/H,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU;QAAE,GAAG,CAAC,MAAM,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;IAEvG,iGAAiG;IAEjG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAc,EAAE,EAAE;QAC3F,MAAM,IAAI,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACzD,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAClE,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,4BAA4B,GAAG,CAAC,GAAG,CAAC,oBAAoB,GAAG,CAAC,OAAO,CAAC,wDAAwD,CAAC;QACnL,OAAO,yEAAyE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;2FACF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,uDAAuD,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;;8EAEjH,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;yBACvG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;wBACd,KAAK,CAAC,QAAQ,CAAC;wBACf,KAAK,CAAC,OAAO,CAAC,6DAA6D,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;;YAEtH,MAAM,IAAI,CAAC,CAAC,cAAc;YAClC,CAAC,CAAC,wBAAwB,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,yDAAyD,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,YAAY;YAC/L,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,sFAAsF,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW;yBAClN,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;wDACgB,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;oDAE9B,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,iGAAiG;IAEjG,GAAG,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;QACtC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,EAAE,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO,8DAA8D,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;eAChG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,iCAAiC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IAChJ,CAAC,CAAC,CAAC;IAEH,kGAAkG;IAElG,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAiB,EAAE,EAAE;QACzD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,+CAA+C,EAAE,GAAG,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QAChJ,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,EAAE,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,IAAI,CAAC,4DAA4D,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QACzH,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAChC,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,KAAkB,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM;QACpE,CAAC,CAAC,mDAAmD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,qCAAqC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,8BAA8B,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO;QACnW,CAAC,CAAC,2BAA2B,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAEjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI;QACxC,CAAC,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAY,EAAE,GAAsB,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACtI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAY,EAAE,GAAsB,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;KAClJ,EAAE,CAAC;QACX,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,GAAkB,EAAE,EAAE;YAC/C,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YAAC,IAAI,CAAC,CAAC;gBAAE,OAAO;YACrC,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC;YACnC,IAAI,KAAK,GAAgB,EAAE,CAAC;YAAC,IAAI,OAAO,GAAG,EAAE,CAAC;YAC9C,IAAI,CAAC;gBAAC,KAAK,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAAC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBAAC,OAAO,GAAG,MAAM,CAAE,CAAW,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;YAAC,CAAC;YACnG,OAAO,GAAG,CAAC,IAAI,CAAC;;+CAEyB,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;uCACxC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,mDAAmD,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC,CAAC,EAAE;YACzN,OAAO,CAAC,CAAC,CAAC,+BAA+B,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC;eACjH,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAED,mGAAmG;IAEnG,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,CAAC,CAAC,cAAc,CAAC;QAC7B,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,GAAkB,EAAE,EAAE;YAC/C,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YAAC,IAAI,CAAC,CAAC;gBAAE,OAAO;YACrC,MAAM,MAAM,GAAG,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACtD,IAAI,CAAC,MAAM;gBAAE,OAAO,GAAG,CAAC,IAAI,CAAC,2FAA2F,EAAE,GAAG,CAAC,CAAC;YAC/H,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,cAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC;gBACnH,QAAQ,EAAE,cAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,SAAS,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,EAAE;gBACtG,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,MAAM,EAAE,EAAE,CAAC,CAAC;QACtH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,kGAAkG;IAElG,GAAG,CAAC,cAAc,CAAC;QACjB,IAAI,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,uDAAuD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;qCACrD,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;0FACyC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;4DACvC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;;qDAEhB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;iFACmB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,uBAAuB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;uCAC3H,GAAG,CAAC,EAAE,CAAC;;aAEjC;QACT,KAAK,EAAE,CAAC,GAAW,EAAE,IAAY,EAAE,IAAU,EAAE,EAAE;YAC/C,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO;gBAAE,OAAO,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACvD,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,0EAA0E;YAC1E,OAAO,CAAC,GAAG,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE;QAChB,OAAO,EAAE,CAAC,GAAW,EAAE,IAAU,EAAE,EAAE;YACnC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO;gBAAE,OAAO,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACvD,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QACxD,CAAC;KACK,CAAC,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a git forge is, to the dashboard.
|
|
3
|
+
*
|
|
4
|
+
* A forge hosts repositories, issues and pull (or merge) requests at one host, and the dashboard
|
|
5
|
+
* authenticates there with a credential a person put in the forge plugin's settings. A provider
|
|
6
|
+
* knows the host, how to read a remote URL, where the pages are, how to list the open issues and
|
|
7
|
+
* requests, and which command opens a request from a branch. The row menu, the modals, the chip,
|
|
8
|
+
* the clone option and the credential hook are the family's (registerForge).
|
|
9
|
+
*/
|
|
10
|
+
import type { PluginLib } from '@webship.co/workspace-plugin-api';
|
|
11
|
+
/** A repository on the forge, as read from a git remote. */
|
|
12
|
+
export interface ForgeRepo {
|
|
13
|
+
/** 'owner/name' (or a deeper GitLab path). */
|
|
14
|
+
path: string;
|
|
15
|
+
/** The repository's web page. */
|
|
16
|
+
web: string;
|
|
17
|
+
/** The remote this was read from ('origin'). */
|
|
18
|
+
remote: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ForgeItem {
|
|
21
|
+
number: number | string;
|
|
22
|
+
title: string;
|
|
23
|
+
url: string;
|
|
24
|
+
author?: string;
|
|
25
|
+
updated?: string;
|
|
26
|
+
state?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ForgeProvider {
|
|
29
|
+
/** The slot, the settings key and the route namespace: 'github'. */
|
|
30
|
+
id: string;
|
|
31
|
+
/** The button's text: 'GITHUB'. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** The product's name in sentences: 'GitHub'. */
|
|
34
|
+
title: string;
|
|
35
|
+
/** The host this forge answers for, from the plugin's settings when it is configurable. */
|
|
36
|
+
host: () => string;
|
|
37
|
+
/** The CLI used when present (gh, glab); none for Bitbucket. */
|
|
38
|
+
cli?: string;
|
|
39
|
+
/** What the pull requests are called here: 'Pull requests' or 'Merge requests'. */
|
|
40
|
+
pullsLabel: string;
|
|
41
|
+
/** The environment a child process needs to authenticate at the host, or null when there is no credential. */
|
|
42
|
+
env: () => NodeJS.ProcessEnv | null;
|
|
43
|
+
/** Who the credential belongs to, for the settings page; never the token. */
|
|
44
|
+
auth: () => {
|
|
45
|
+
username?: string;
|
|
46
|
+
email?: string;
|
|
47
|
+
how: string;
|
|
48
|
+
};
|
|
49
|
+
/** The repository a remote URL names, if it is on this host. */
|
|
50
|
+
repoOf: (remoteUrl: string, remote: string) => ForgeRepo | null;
|
|
51
|
+
/** The clone URL of 'owner/name' (or a full URL given as is). */
|
|
52
|
+
cloneUrl: (spec: string) => string;
|
|
53
|
+
/** The pages of a repository. */
|
|
54
|
+
urls: (repo: ForgeRepo) => {
|
|
55
|
+
issues: string;
|
|
56
|
+
pulls: string;
|
|
57
|
+
newIssue: string;
|
|
58
|
+
newPull: (branch: string) => string;
|
|
59
|
+
};
|
|
60
|
+
listIssues: (repo: ForgeRepo, lib: PluginLib, env: NodeJS.ProcessEnv) => Promise<ForgeItem[]>;
|
|
61
|
+
listPulls: (repo: ForgeRepo, lib: PluginLib, env: NodeJS.ProcessEnv) => Promise<ForgeItem[]>;
|
|
62
|
+
/** The command that opens a pull request from the branch, run in a terminal in the project; null when there is no CLI (the New-pull page is linked instead). */
|
|
63
|
+
newPullCommand?: (repo: ForgeRepo, branch: string) => string;
|
|
64
|
+
/** The environment a `git clone` of a private repository needs (a credential helper); merged into the clone step. */
|
|
65
|
+
cloneEnv?: () => string;
|
|
66
|
+
/** The pattern a clone spec must match, and its help. */
|
|
67
|
+
clone: {
|
|
68
|
+
pattern: RegExp;
|
|
69
|
+
placeholder: string;
|
|
70
|
+
help: string;
|
|
71
|
+
};
|
|
72
|
+
/** Where the token comes from, for the message when there is none. */
|
|
73
|
+
tokenHint: string;
|
|
74
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What a git forge is, to the dashboard.
|
|
4
|
+
*
|
|
5
|
+
* A forge hosts repositories, issues and pull (or merge) requests at one host, and the dashboard
|
|
6
|
+
* authenticates there with a credential a person put in the forge plugin's settings. A provider
|
|
7
|
+
* knows the host, how to read a remote URL, where the pages are, how to list the open issues and
|
|
8
|
+
* requests, and which command opens a request from a branch. The row menu, the modals, the chip,
|
|
9
|
+
* the clone option and the credential hook are the family's (registerForge).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webship.co/workspace-forge",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0-alpha1",
|
|
4
|
+
"description": "The forge family's shared base for Webship Workspace plugins: the ForgeProvider contract, and the row menu (repository, issues, pull requests, open a pull request), the repo chip, the clone option in New folder and the credential the dashboard uses for the host, registered through registerForge(api, forge).",
|
|
5
|
+
"main": "dist/src/index.js",
|
|
6
|
+
"types": "dist/src/index.d.ts",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/webship/workspace-forge.git"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/src",
|
|
14
|
+
"css",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"prepare": "npm run build",
|
|
20
|
+
"test": "npm run build && node --test dist/tests/*.test.js",
|
|
21
|
+
"lint": "tsc -p tsconfig.json --noEmit"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^24.0.0",
|
|
25
|
+
"@webship.co/workspace-plugin-api": "^1.0.0-alpha1",
|
|
26
|
+
"typescript": "^5.9.0"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
}
|
|
31
|
+
}
|