@realiizlabs/admin 0.15.9 → 0.17.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/dist/git/index.cjs +67 -5
- package/dist/git/index.cjs.map +1 -1
- package/dist/git/index.d.cts +31 -3
- package/dist/git/index.d.ts +31 -3
- package/dist/git/index.js +66 -6
- package/dist/git/index.js.map +1 -1
- package/dist/shell/index.cjs +22 -17
- package/dist/shell/index.cjs.map +1 -1
- package/dist/shell/index.d.cts +1 -1
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/index.js +22 -17
- package/dist/shell/index.js.map +1 -1
- package/dist/studio/index.cjs +78 -10
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.d.cts +14 -2
- package/dist/studio/index.d.ts +14 -2
- package/dist/studio/index.js +78 -10
- package/dist/studio/index.js.map +1 -1
- package/dist/studio-ui/index.cjs +34 -23
- package/dist/studio-ui/index.cjs.map +1 -1
- package/dist/studio-ui/index.d.cts +18 -4
- package/dist/studio-ui/index.d.ts +18 -4
- package/dist/studio-ui/index.js +35 -24
- package/dist/studio-ui/index.js.map +1 -1
- package/dist/{types-BP5G1myE.d.cts → types-Cy9UDz--.d.cts} +11 -4
- package/dist/{types-BP5G1myE.d.ts → types-Cy9UDz--.d.ts} +11 -4
- package/package.json +2 -2
package/dist/studio/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require('server-only');
|
|
4
4
|
var navigation = require('next/navigation');
|
|
5
5
|
var ssr = require('@supabase/ssr');
|
|
6
|
+
var crypto = require('crypto');
|
|
6
7
|
var matter = require('gray-matter');
|
|
7
8
|
var unified = require('unified');
|
|
8
9
|
var remarkParse = require('remark-parse');
|
|
@@ -183,15 +184,15 @@ var ChecksFailedError = class extends Error {
|
|
|
183
184
|
}
|
|
184
185
|
};
|
|
185
186
|
|
|
186
|
-
// src/git/
|
|
187
|
-
var
|
|
187
|
+
// src/git/http.ts
|
|
188
|
+
var GITHUB_API = "https://api.github.com";
|
|
188
189
|
var GITHUB_TIMEOUT_MS = 1e4;
|
|
189
|
-
async function
|
|
190
|
-
const res = await
|
|
190
|
+
async function githubRequest(method, path, authorization, body, fetchImpl = fetch) {
|
|
191
|
+
const res = await fetchImpl(GITHUB_API + path, {
|
|
191
192
|
method,
|
|
192
193
|
signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS),
|
|
193
194
|
headers: {
|
|
194
|
-
Authorization:
|
|
195
|
+
Authorization: authorization,
|
|
195
196
|
Accept: "application/vnd.github+json",
|
|
196
197
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
197
198
|
"User-Agent": "realiizlabs-admin",
|
|
@@ -210,6 +211,65 @@ async function ghFetch(ctx, method, path, body) {
|
|
|
210
211
|
}
|
|
211
212
|
return { ok: res.ok, status: res.status, json };
|
|
212
213
|
}
|
|
214
|
+
|
|
215
|
+
// src/git/app-auth.ts
|
|
216
|
+
var JWT_TTL_S = 9 * 60;
|
|
217
|
+
var REFRESH_BEFORE_MS = 5 * 6e4;
|
|
218
|
+
var cache = /* @__PURE__ */ new Map();
|
|
219
|
+
function b64url(input) {
|
|
220
|
+
return Buffer.from(input).toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
221
|
+
}
|
|
222
|
+
function appJwt(creds, now = Math.floor(Date.now() / 1e3)) {
|
|
223
|
+
const header = b64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
224
|
+
const payload = b64url(JSON.stringify({ iat: now - 60, exp: now + JWT_TTL_S, iss: creds.appId }));
|
|
225
|
+
const signer = crypto.createSign("RSA-SHA256");
|
|
226
|
+
signer.update(`${header}.${payload}`);
|
|
227
|
+
const signature = signer.sign(creds.privateKey.replace(/\\n/g, "\n"));
|
|
228
|
+
return `${header}.${payload}.${b64url(signature)}`;
|
|
229
|
+
}
|
|
230
|
+
function forgetInstallationToken(creds, owner, repo) {
|
|
231
|
+
cache.delete(`${creds.appId}:${owner}/${repo}`);
|
|
232
|
+
}
|
|
233
|
+
async function installationToken(creds, owner, repo, fetchImpl = fetch) {
|
|
234
|
+
const key = `${creds.appId}:${owner}/${repo}`;
|
|
235
|
+
const hit = cache.get(key);
|
|
236
|
+
if (hit && hit.expiresAt - Date.now() > REFRESH_BEFORE_MS) return hit.token;
|
|
237
|
+
const bearer = `Bearer ${appJwt(creds)}`;
|
|
238
|
+
const repoPath2 = `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`;
|
|
239
|
+
const found = await githubRequest("GET", `${repoPath2}/installation`, bearer, void 0, fetchImpl);
|
|
240
|
+
if (found.status === 404) {
|
|
241
|
+
throw new GitHubError(
|
|
242
|
+
`The Realiiz Studio GitHub App isn't installed on ${owner}/${repo}. The repository's owner installs it once \u2014 ask your web team for the link.`,
|
|
243
|
+
{ status: 404, path: `${repoPath2}/installation`, body: found.json }
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (!found.ok) throw new GitHubError(`GitHub ${found.status} looking up the app installation`, { status: found.status, path: `${repoPath2}/installation`, body: found.json });
|
|
247
|
+
const minted = await githubRequest(
|
|
248
|
+
"POST",
|
|
249
|
+
`/app/installations/${found.json.id}/access_tokens`,
|
|
250
|
+
bearer,
|
|
251
|
+
void 0,
|
|
252
|
+
fetchImpl
|
|
253
|
+
);
|
|
254
|
+
if (!minted.ok) throw new GitHubError(`GitHub ${minted.status} minting an installation token`, { status: minted.status, path: "/app/installations/\u2026/access_tokens", body: minted.json });
|
|
255
|
+
cache.set(key, { token: minted.json.token, expiresAt: Date.parse(minted.json.expires_at) });
|
|
256
|
+
return minted.json.token;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// src/git/client.ts
|
|
260
|
+
async function credentialFor(ctx) {
|
|
261
|
+
if (ctx.app) return installationToken(ctx.app, ctx.owner, ctx.repo);
|
|
262
|
+
if (ctx.token) return ctx.token;
|
|
263
|
+
throw new GitHubError(`No GitHub credential for ${ctx.owner}/${ctx.repo}: set GITHUB_APP_ID + GITHUB_APP_PRIVATE_KEY, or GITHUB_CONTENT_TOKEN.`, { status: 0, path: "", body: null });
|
|
264
|
+
}
|
|
265
|
+
async function ghFetch(ctx, method, path, body) {
|
|
266
|
+
const res = await githubRequest(method, path, `Bearer ${await credentialFor(ctx)}`, body);
|
|
267
|
+
if (res.status === 401 && ctx.app) {
|
|
268
|
+
forgetInstallationToken(ctx.app, ctx.owner, ctx.repo);
|
|
269
|
+
return githubRequest(method, path, `Bearer ${await credentialFor(ctx)}`, body);
|
|
270
|
+
}
|
|
271
|
+
return res;
|
|
272
|
+
}
|
|
213
273
|
async function ghFetchOrThrow(ctx, method, path, body) {
|
|
214
274
|
const res = await ghFetch(ctx, method, path, body);
|
|
215
275
|
if (!res.ok) throw toError(res, path);
|
|
@@ -416,6 +476,10 @@ function makeReaders(config, registry, pending) {
|
|
|
416
476
|
const entries = await listDirectory(repo(), e.folder);
|
|
417
477
|
return entries.find((x) => registry.slugOf(e, x.name) === slug)?.path ?? null;
|
|
418
478
|
};
|
|
479
|
+
const listSlugs = async (typeId) => {
|
|
480
|
+
const items = await listItems(typeId);
|
|
481
|
+
return items.filter((i) => !i.isNew).map((i) => i.slug).sort();
|
|
482
|
+
};
|
|
419
483
|
const listItems = async (typeId) => {
|
|
420
484
|
const e = need(typeId);
|
|
421
485
|
const ctx = repo();
|
|
@@ -491,7 +555,7 @@ function makeReaders(config, registry, pending) {
|
|
|
491
555
|
}
|
|
492
556
|
};
|
|
493
557
|
const prStatus = (number) => getPullRequestStatus(repo(), number);
|
|
494
|
-
return { pathOf, listItems, countItems, readItem, lastAuthor, getPullRequest: getPullRequest2, prStatus };
|
|
558
|
+
return { pathOf, listItems, listSlugs, countItems, readItem, lastAuthor, getPullRequest: getPullRequest2, prStatus };
|
|
495
559
|
}
|
|
496
560
|
|
|
497
561
|
// src/git/branch.ts
|
|
@@ -613,18 +677,22 @@ ${input.body.trim()}
|
|
|
613
677
|
if (!pictures.ok) return { ok: false, error: pictures.error };
|
|
614
678
|
const files = [{ path, content }, ...pictures.files];
|
|
615
679
|
const repo = config.env().repo;
|
|
680
|
+
const oldPath = input.replaces ? await readers.pathOf(entry.id, input.replaces).catch(() => null) : null;
|
|
681
|
+
const remove = oldPath && oldPath !== path ? [oldPath] : [];
|
|
682
|
+
const renamed = remove.length ? `
|
|
683
|
+
Renamed from \`${oldPath}\` to \`${path}\`` : "";
|
|
616
684
|
if (input.existing && await stillOpen(input.existing.number)) {
|
|
617
|
-
await writeFiles(repo, input.existing.branch, files, `Update: ${title}
|
|
685
|
+
await writeFiles(repo, input.existing.branch, files, `Update: ${title}`, { remove });
|
|
618
686
|
navigation.redirect(`/admin/pr/${input.existing.number}`);
|
|
619
687
|
}
|
|
620
688
|
const branch = `admin/${entry.id}/${fileName.replace(/\.mdx$/, "")}-${stamp()}`;
|
|
621
689
|
await createBranch(repo, branch);
|
|
622
|
-
await writeFiles(repo, branch, files, `Publish: ${title}
|
|
690
|
+
await writeFiles(repo, branch, files, `Publish: ${title}`, { remove });
|
|
623
691
|
const pr = await openPullRequest(repo, branch, {
|
|
624
692
|
title: `Publish: ${title}`,
|
|
625
693
|
body: `Published from the dashboard by ${user.email ?? user.id}.
|
|
626
694
|
|
|
627
|
-
File: \`${path}
|
|
695
|
+
File: \`${path}\`${renamed}`
|
|
628
696
|
});
|
|
629
697
|
navigation.redirect(`/admin/pr/${pr.number}`);
|
|
630
698
|
};
|
|
@@ -1115,7 +1183,7 @@ function makeHandlers(ctx) {
|
|
|
1115
1183
|
}
|
|
1116
1184
|
|
|
1117
1185
|
// src/version.ts
|
|
1118
|
-
var ADMIN_VERSION = "0.
|
|
1186
|
+
var ADMIN_VERSION = "0.17.0" ;
|
|
1119
1187
|
|
|
1120
1188
|
// src/studio/update.ts
|
|
1121
1189
|
var PACKAGE_NAME = "@realiizlabs/admin";
|