@realiizlabs/admin 0.16.0 → 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/studio/index.cjs +66 -6
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.d.cts +7 -2
- package/dist/studio/index.d.ts +7 -2
- package/dist/studio/index.js +66 -6
- package/dist/studio/index.js.map +1 -1
- package/dist/studio-ui/index.cjs +1 -1
- package/dist/studio-ui/index.d.cts +1 -1
- package/dist/studio-ui/index.d.ts +1 -1
- package/dist/studio-ui/index.js +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.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { c as ImagePayload } from '../validate-C84Ll1cD.cjs';
|
|
2
2
|
export { I as IMAGE_ERRORS, a as IMAGE_LIMITS, b as ImageLimits, V as ValidatedImages, d as decodedSize, v as validateImages } from '../validate-C84Ll1cD.cjs';
|
|
3
3
|
import { a as IdentityUser, f as SiteRole, C as CookieStore, d as SiteMember, I as IdentityClient, c as SiteBranding } from '../members-nhbRSYyr.cjs';
|
|
4
|
-
import { a as PullRequestStatus } from '../types-
|
|
4
|
+
import { a as PullRequestStatus } from '../types-Cy9UDz--.cjs';
|
|
5
5
|
import { C as ContentTypeEntry } from '../types-DeHdasdP.cjs';
|
|
6
6
|
import * as zod from 'zod';
|
|
7
7
|
import * as zod_v4_core from 'zod/v4/core';
|
|
@@ -15,10 +15,15 @@ import '@supabase/supabase-js';
|
|
|
15
15
|
* arrives here, lazily, so `next build` with no env set still succeeds.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
/** The site's repo and how Studio reaches it — the GitHub App (preferred) or a personal access token. */
|
|
18
19
|
interface RepoConfig {
|
|
19
20
|
owner: string;
|
|
20
21
|
repo: string;
|
|
21
|
-
|
|
22
|
+
app?: {
|
|
23
|
+
appId: string;
|
|
24
|
+
privateKey: string;
|
|
25
|
+
} | null;
|
|
26
|
+
token?: string | null;
|
|
22
27
|
}
|
|
23
28
|
interface IdentityConfig {
|
|
24
29
|
url: string;
|
package/dist/studio/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { c as ImagePayload } from '../validate-C84Ll1cD.js';
|
|
2
2
|
export { I as IMAGE_ERRORS, a as IMAGE_LIMITS, b as ImageLimits, V as ValidatedImages, d as decodedSize, v as validateImages } from '../validate-C84Ll1cD.js';
|
|
3
3
|
import { a as IdentityUser, f as SiteRole, C as CookieStore, d as SiteMember, I as IdentityClient, c as SiteBranding } from '../members-nhbRSYyr.js';
|
|
4
|
-
import { a as PullRequestStatus } from '../types-
|
|
4
|
+
import { a as PullRequestStatus } from '../types-Cy9UDz--.js';
|
|
5
5
|
import { C as ContentTypeEntry } from '../types-DeHdasdP.js';
|
|
6
6
|
import * as zod from 'zod';
|
|
7
7
|
import * as zod_v4_core from 'zod/v4/core';
|
|
@@ -15,10 +15,15 @@ import '@supabase/supabase-js';
|
|
|
15
15
|
* arrives here, lazily, so `next build` with no env set still succeeds.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
/** The site's repo and how Studio reaches it — the GitHub App (preferred) or a personal access token. */
|
|
18
19
|
interface RepoConfig {
|
|
19
20
|
owner: string;
|
|
20
21
|
repo: string;
|
|
21
|
-
|
|
22
|
+
app?: {
|
|
23
|
+
appId: string;
|
|
24
|
+
privateKey: string;
|
|
25
|
+
} | null;
|
|
26
|
+
token?: string | null;
|
|
22
27
|
}
|
|
23
28
|
interface IdentityConfig {
|
|
24
29
|
url: string;
|
package/dist/studio/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import 'server-only';
|
|
2
2
|
import { redirect } from 'next/navigation';
|
|
3
3
|
import { createServerClient } from '@supabase/ssr';
|
|
4
|
+
import { createSign } from 'crypto';
|
|
4
5
|
import matter from 'gray-matter';
|
|
5
6
|
import { unified } from 'unified';
|
|
6
7
|
import remarkParse from 'remark-parse';
|
|
@@ -171,15 +172,15 @@ var ChecksFailedError = class extends Error {
|
|
|
171
172
|
}
|
|
172
173
|
};
|
|
173
174
|
|
|
174
|
-
// src/git/
|
|
175
|
-
var
|
|
175
|
+
// src/git/http.ts
|
|
176
|
+
var GITHUB_API = "https://api.github.com";
|
|
176
177
|
var GITHUB_TIMEOUT_MS = 1e4;
|
|
177
|
-
async function
|
|
178
|
-
const res = await
|
|
178
|
+
async function githubRequest(method, path, authorization, body, fetchImpl = fetch) {
|
|
179
|
+
const res = await fetchImpl(GITHUB_API + path, {
|
|
179
180
|
method,
|
|
180
181
|
signal: AbortSignal.timeout(GITHUB_TIMEOUT_MS),
|
|
181
182
|
headers: {
|
|
182
|
-
Authorization:
|
|
183
|
+
Authorization: authorization,
|
|
183
184
|
Accept: "application/vnd.github+json",
|
|
184
185
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
185
186
|
"User-Agent": "realiizlabs-admin",
|
|
@@ -198,6 +199,65 @@ async function ghFetch(ctx, method, path, body) {
|
|
|
198
199
|
}
|
|
199
200
|
return { ok: res.ok, status: res.status, json };
|
|
200
201
|
}
|
|
202
|
+
|
|
203
|
+
// src/git/app-auth.ts
|
|
204
|
+
var JWT_TTL_S = 9 * 60;
|
|
205
|
+
var REFRESH_BEFORE_MS = 5 * 6e4;
|
|
206
|
+
var cache = /* @__PURE__ */ new Map();
|
|
207
|
+
function b64url(input) {
|
|
208
|
+
return Buffer.from(input).toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
209
|
+
}
|
|
210
|
+
function appJwt(creds, now = Math.floor(Date.now() / 1e3)) {
|
|
211
|
+
const header = b64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
212
|
+
const payload = b64url(JSON.stringify({ iat: now - 60, exp: now + JWT_TTL_S, iss: creds.appId }));
|
|
213
|
+
const signer = createSign("RSA-SHA256");
|
|
214
|
+
signer.update(`${header}.${payload}`);
|
|
215
|
+
const signature = signer.sign(creds.privateKey.replace(/\\n/g, "\n"));
|
|
216
|
+
return `${header}.${payload}.${b64url(signature)}`;
|
|
217
|
+
}
|
|
218
|
+
function forgetInstallationToken(creds, owner, repo) {
|
|
219
|
+
cache.delete(`${creds.appId}:${owner}/${repo}`);
|
|
220
|
+
}
|
|
221
|
+
async function installationToken(creds, owner, repo, fetchImpl = fetch) {
|
|
222
|
+
const key = `${creds.appId}:${owner}/${repo}`;
|
|
223
|
+
const hit = cache.get(key);
|
|
224
|
+
if (hit && hit.expiresAt - Date.now() > REFRESH_BEFORE_MS) return hit.token;
|
|
225
|
+
const bearer = `Bearer ${appJwt(creds)}`;
|
|
226
|
+
const repoPath2 = `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`;
|
|
227
|
+
const found = await githubRequest("GET", `${repoPath2}/installation`, bearer, void 0, fetchImpl);
|
|
228
|
+
if (found.status === 404) {
|
|
229
|
+
throw new GitHubError(
|
|
230
|
+
`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.`,
|
|
231
|
+
{ status: 404, path: `${repoPath2}/installation`, body: found.json }
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
if (!found.ok) throw new GitHubError(`GitHub ${found.status} looking up the app installation`, { status: found.status, path: `${repoPath2}/installation`, body: found.json });
|
|
235
|
+
const minted = await githubRequest(
|
|
236
|
+
"POST",
|
|
237
|
+
`/app/installations/${found.json.id}/access_tokens`,
|
|
238
|
+
bearer,
|
|
239
|
+
void 0,
|
|
240
|
+
fetchImpl
|
|
241
|
+
);
|
|
242
|
+
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 });
|
|
243
|
+
cache.set(key, { token: minted.json.token, expiresAt: Date.parse(minted.json.expires_at) });
|
|
244
|
+
return minted.json.token;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/git/client.ts
|
|
248
|
+
async function credentialFor(ctx) {
|
|
249
|
+
if (ctx.app) return installationToken(ctx.app, ctx.owner, ctx.repo);
|
|
250
|
+
if (ctx.token) return ctx.token;
|
|
251
|
+
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 });
|
|
252
|
+
}
|
|
253
|
+
async function ghFetch(ctx, method, path, body) {
|
|
254
|
+
const res = await githubRequest(method, path, `Bearer ${await credentialFor(ctx)}`, body);
|
|
255
|
+
if (res.status === 401 && ctx.app) {
|
|
256
|
+
forgetInstallationToken(ctx.app, ctx.owner, ctx.repo);
|
|
257
|
+
return githubRequest(method, path, `Bearer ${await credentialFor(ctx)}`, body);
|
|
258
|
+
}
|
|
259
|
+
return res;
|
|
260
|
+
}
|
|
201
261
|
async function ghFetchOrThrow(ctx, method, path, body) {
|
|
202
262
|
const res = await ghFetch(ctx, method, path, body);
|
|
203
263
|
if (!res.ok) throw toError(res, path);
|
|
@@ -1111,7 +1171,7 @@ function makeHandlers(ctx) {
|
|
|
1111
1171
|
}
|
|
1112
1172
|
|
|
1113
1173
|
// src/version.ts
|
|
1114
|
-
var ADMIN_VERSION = "0.
|
|
1174
|
+
var ADMIN_VERSION = "0.17.0" ;
|
|
1115
1175
|
|
|
1116
1176
|
// src/studio/update.ts
|
|
1117
1177
|
var PACKAGE_NAME = "@realiizlabs/admin";
|