pipe-kan 0.30.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/pipe-kan.js +79 -5
- package/dist/ui/assets/index-yGNyVuOj.js +56 -0
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/index-CyO_1G_D.js +0 -56
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ bunx pipe-kan --plane --projects APH,PULSE,PKAN,PUI,DEC
|
|
|
57
57
|
| `PLANE_API_KEY` | (required in Plane mode) | personal access token (`X-API-Key`) |
|
|
58
58
|
| `PLANE_HOST` | `https://plane.tail48fe8.ts.net` | Plane origin; API is `{host}/api/v1` |
|
|
59
59
|
|
|
60
|
-
Same `--projects` style as Jira: comma-separated, trimmed, uppercased. The header **Scope flags** field accepts the same string, then **Refresh**.
|
|
60
|
+
Same `--projects` style as Jira: comma-separated, trimmed, uppercased. The header **Scope flags** field accepts the same string, then **Refresh**. In Plane mode a header **Workspace** pill (beside the project-identifier chip) types a slug, writes `--workspace` into Scope flags, and Refresh-confirms all Epics. Jira omits the pill. Next launch still uses argv `--workspace`, else `PLANE_WORKSPACE`, else `personal`.
|
|
61
61
|
|
|
62
62
|
On Refresh:
|
|
63
63
|
|
package/dist/pipe-kan.js
CHANGED
|
@@ -1504,6 +1504,12 @@ function createApp(opts) {
|
|
|
1504
1504
|
error: err instanceof Error ? err.message : "jira issue view failed"
|
|
1505
1505
|
};
|
|
1506
1506
|
}
|
|
1507
|
+
},
|
|
1508
|
+
async listWorkspaces() {
|
|
1509
|
+
return cli.listWorkspaces?.() ?? [];
|
|
1510
|
+
},
|
|
1511
|
+
async listProjectIdentifiers(workspace) {
|
|
1512
|
+
return cli.listProjectIdentifiers?.(workspace) ?? [];
|
|
1507
1513
|
}
|
|
1508
1514
|
};
|
|
1509
1515
|
return app;
|
|
@@ -1877,6 +1883,19 @@ function createPlaneCli(opts) {
|
|
|
1877
1883
|
return;
|
|
1878
1884
|
return { id, identifier, name: asString(row?.name) ?? identifier };
|
|
1879
1885
|
}
|
|
1886
|
+
function parseWorkspace(raw) {
|
|
1887
|
+
const row = asRecord(raw);
|
|
1888
|
+
const slug = asString(row?.slug);
|
|
1889
|
+
if (!slug)
|
|
1890
|
+
return;
|
|
1891
|
+
return { id: asString(row?.id) ?? slug, name: asString(row?.name) ?? slug, slug };
|
|
1892
|
+
}
|
|
1893
|
+
function parseWorkspaceList(raw) {
|
|
1894
|
+
const rows = Array.isArray(raw) ? raw : asRecord(raw)?.results;
|
|
1895
|
+
if (!Array.isArray(rows))
|
|
1896
|
+
return;
|
|
1897
|
+
return rows.map(parseWorkspace).filter((row) => !!row);
|
|
1898
|
+
}
|
|
1880
1899
|
function parseState(raw) {
|
|
1881
1900
|
const row = asRecord(raw);
|
|
1882
1901
|
const id = asString(row?.id);
|
|
@@ -2092,6 +2111,25 @@ function createPlaneCli(opts) {
|
|
|
2092
2111
|
const loaded = await loadCatalog(flags || defaultFlags);
|
|
2093
2112
|
return loaded.columns;
|
|
2094
2113
|
},
|
|
2114
|
+
async listWorkspaces() {
|
|
2115
|
+
for (const path of ["/users/me/workspaces/", "/workspaces/"]) {
|
|
2116
|
+
try {
|
|
2117
|
+
return parseWorkspaceList(await requestJson(path)) ?? [];
|
|
2118
|
+
} catch (err) {
|
|
2119
|
+
const status = err.status;
|
|
2120
|
+
if (status === 404 && path === "/users/me/workspaces/")
|
|
2121
|
+
continue;
|
|
2122
|
+
return [];
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
return [];
|
|
2126
|
+
},
|
|
2127
|
+
async listProjectIdentifiers(workspace) {
|
|
2128
|
+
const slug = workspace.trim();
|
|
2129
|
+
if (!slug)
|
|
2130
|
+
return [];
|
|
2131
|
+
return (await paginate(`/workspaces/${slug}/projects/`)).map(parseProject).filter((row) => !!row).map((row) => row.identifier);
|
|
2132
|
+
},
|
|
2095
2133
|
async move(key, status) {
|
|
2096
2134
|
try {
|
|
2097
2135
|
const module = (await loadCatalog(lastFlags)).modules.get(key);
|
|
@@ -2259,11 +2297,46 @@ function reply(req, res, work) {
|
|
|
2259
2297
|
json(res, 500, { error: message });
|
|
2260
2298
|
});
|
|
2261
2299
|
}
|
|
2262
|
-
function
|
|
2300
|
+
async function boardEnvelope(body, kind, flags, env, app) {
|
|
2301
|
+
if (kind !== "plane")
|
|
2302
|
+
return { ...body, kind };
|
|
2303
|
+
const envelope = { ...body, kind, workspace: planeWorkspace(flags, env) };
|
|
2304
|
+
try {
|
|
2305
|
+
const workspaces = await app.listWorkspaces?.();
|
|
2306
|
+
if (workspaces && workspaces.length)
|
|
2307
|
+
return { ...envelope, workspaces };
|
|
2308
|
+
} catch {}
|
|
2309
|
+
return envelope;
|
|
2310
|
+
}
|
|
2311
|
+
function handleAppApi(req, res, app, opts = {}) {
|
|
2312
|
+
const kind = opts.kind ?? "store";
|
|
2313
|
+
const env = opts.env ?? process.env;
|
|
2263
2314
|
const url = pathOf(req);
|
|
2264
2315
|
const method = (req.method ?? "GET").toUpperCase();
|
|
2265
2316
|
if (url.pathname === "/api/board" && method === "GET") {
|
|
2266
|
-
|
|
2317
|
+
reply(req, res, async () => {
|
|
2318
|
+
json(res, 200, await boardEnvelope({ ...app.board(), flags: app.flags }, kind, app.flags, env, app));
|
|
2319
|
+
});
|
|
2320
|
+
return true;
|
|
2321
|
+
}
|
|
2322
|
+
if (url.pathname === "/api/projects" && method === "GET") {
|
|
2323
|
+
reply(req, res, async () => {
|
|
2324
|
+
if (kind !== "plane") {
|
|
2325
|
+
json(res, 404, { error: "not plane" });
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
const workspace = (url.searchParams.get("workspace") ?? "").trim();
|
|
2329
|
+
if (!workspace) {
|
|
2330
|
+
json(res, 400, { error: "workspace required" });
|
|
2331
|
+
return;
|
|
2332
|
+
}
|
|
2333
|
+
try {
|
|
2334
|
+
json(res, 200, { projects: await app.listProjectIdentifiers?.(workspace) ?? [] });
|
|
2335
|
+
} catch (err) {
|
|
2336
|
+
const message = err instanceof Error ? err.message : "catalog failed";
|
|
2337
|
+
json(res, 409, { error: message });
|
|
2338
|
+
}
|
|
2339
|
+
});
|
|
2267
2340
|
return true;
|
|
2268
2341
|
}
|
|
2269
2342
|
if (url.pathname === "/api/refresh" && method === "POST") {
|
|
@@ -2275,10 +2348,10 @@ function handleAppApi(req, res, app) {
|
|
|
2275
2348
|
json(res, 400, { error: "selected Refresh requires epicKeys" });
|
|
2276
2349
|
return;
|
|
2277
2350
|
}
|
|
2278
|
-
json(res, 200, await app.refresh(undefined, { scope: "selected", epicKeys }));
|
|
2351
|
+
json(res, 200, await boardEnvelope(await app.refresh(undefined, { scope: "selected", epicKeys }), kind, app.flags, env, app));
|
|
2279
2352
|
return;
|
|
2280
2353
|
}
|
|
2281
|
-
json(res, 200, await app.refresh(body.flags));
|
|
2354
|
+
json(res, 200, await boardEnvelope(await app.refresh(body.flags), kind, app.flags, env, app));
|
|
2282
2355
|
});
|
|
2283
2356
|
return true;
|
|
2284
2357
|
}
|
|
@@ -13307,8 +13380,9 @@ function handleFakeJira(req, res, store) {
|
|
|
13307
13380
|
|
|
13308
13381
|
// src/http.ts
|
|
13309
13382
|
function handleRequest(req, res, ctx) {
|
|
13310
|
-
if (handleAppApi(req, res, ctx.app) || handleAgentApi(req, res, ctx.app))
|
|
13383
|
+
if (handleAppApi(req, res, ctx.app, { kind: ctx.kind }) || handleAgentApi(req, res, ctx.app)) {
|
|
13311
13384
|
return true;
|
|
13385
|
+
}
|
|
13312
13386
|
if (ctx.kind === "plane")
|
|
13313
13387
|
return false;
|
|
13314
13388
|
return handleFakeJira(req, res, ctx.store);
|