@micropage-sh/mcp 0.1.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/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/annotations.d.ts +20 -0
- package/dist/annotations.js +36 -0
- package/dist/annotations.js.map +1 -0
- package/dist/client/assets.d.ts +85 -0
- package/dist/client/assets.js +473 -0
- package/dist/client/assets.js.map +1 -0
- package/dist/client/auth-provider.d.ts +24 -0
- package/dist/client/auth-provider.js +10 -0
- package/dist/client/auth-provider.js.map +1 -0
- package/dist/client/builds.d.ts +82 -0
- package/dist/client/builds.js +166 -0
- package/dist/client/builds.js.map +1 -0
- package/dist/client/config.d.ts +18 -0
- package/dist/client/config.js +29 -0
- package/dist/client/config.js.map +1 -0
- package/dist/client/deploy-events.d.ts +98 -0
- package/dist/client/deploy-events.js +170 -0
- package/dist/client/deploy-events.js.map +1 -0
- package/dist/client/deploy-token.d.ts +48 -0
- package/dist/client/deploy-token.js +130 -0
- package/dist/client/deploy-token.js.map +1 -0
- package/dist/client/errors.d.ts +18 -0
- package/dist/client/errors.js +21 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/http.d.ts +68 -0
- package/dist/client/http.js +191 -0
- package/dist/client/http.js.map +1 -0
- package/dist/client/jwt.d.ts +13 -0
- package/dist/client/jwt.js +23 -0
- package/dist/client/jwt.js.map +1 -0
- package/dist/client/lock.d.ts +16 -0
- package/dist/client/lock.js +67 -0
- package/dist/client/lock.js.map +1 -0
- package/dist/client/pages.d.ts +47 -0
- package/dist/client/pages.js +131 -0
- package/dist/client/pages.js.map +1 -0
- package/dist/client/posts.d.ts +108 -0
- package/dist/client/posts.js +187 -0
- package/dist/client/posts.js.map +1 -0
- package/dist/client/project-ref.d.ts +68 -0
- package/dist/client/project-ref.js +118 -0
- package/dist/client/project-ref.js.map +1 -0
- package/dist/client/session-store.d.ts +81 -0
- package/dist/client/session-store.js +271 -0
- package/dist/client/session-store.js.map +1 -0
- package/dist/client/submissions.d.ts +59 -0
- package/dist/client/submissions.js +111 -0
- package/dist/client/submissions.js.map +1 -0
- package/dist/client/tier.d.ts +42 -0
- package/dist/client/tier.js +76 -0
- package/dist/client/tier.js.map +1 -0
- package/dist/content/index.d.ts +5 -0
- package/dist/content/index.js +28 -0
- package/dist/content/index.js.map +1 -0
- package/dist/context.d.ts +30 -0
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -0
- package/dist/guards.d.ts +55 -0
- package/dist/guards.js +168 -0
- package/dist/guards.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/progress.d.ts +7 -0
- package/dist/progress.js +25 -0
- package/dist/progress.js.map +1 -0
- package/dist/reference/prompts.d.ts +6 -0
- package/dist/reference/prompts.js +110 -0
- package/dist/reference/prompts.js.map +1 -0
- package/dist/reference/resources.d.ts +2 -0
- package/dist/reference/resources.js +41 -0
- package/dist/reference/resources.js.map +1 -0
- package/dist/reference/tool.d.ts +21 -0
- package/dist/reference/tool.js +50 -0
- package/dist/reference/tool.js.map +1 -0
- package/dist/reference/topics.d.ts +29 -0
- package/dist/reference/topics.js +91 -0
- package/dist/reference/topics.js.map +1 -0
- package/dist/reference.d.ts +9 -0
- package/dist/reference.js +20 -0
- package/dist/reference.js.map +1 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.js +75 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/account.d.ts +34 -0
- package/dist/tools/account.js +128 -0
- package/dist/tools/account.js.map +1 -0
- package/dist/tools/builds.d.ts +95 -0
- package/dist/tools/builds.js +403 -0
- package/dist/tools/builds.js.map +1 -0
- package/dist/tools/files.d.ts +71 -0
- package/dist/tools/files.js +205 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/forms.d.ts +59 -0
- package/dist/tools/forms.js +177 -0
- package/dist/tools/forms.js.map +1 -0
- package/dist/tools/posts.d.ts +191 -0
- package/dist/tools/posts.js +600 -0
- package/dist/tools/posts.js.map +1 -0
- package/dist/tools/projects.d.ts +201 -0
- package/dist/tools/projects.js +553 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/shared.d.ts +33 -0
- package/dist/tools/shared.js +41 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { IN_PROGRESS_STATUSES } from "./builds.js";
|
|
2
|
+
import { MicropageError } from "./errors.js";
|
|
3
|
+
import { eq, gt } from "./http.js";
|
|
4
|
+
/** Same set as the CLI's stream (cli/src/supabase.js). */
|
|
5
|
+
export const TERMINAL_DEPLOY_EVENTS = new Set([
|
|
6
|
+
"build.failed",
|
|
7
|
+
"deployment.completed",
|
|
8
|
+
"archive.completed",
|
|
9
|
+
"archive.failed",
|
|
10
|
+
]);
|
|
11
|
+
/**
|
|
12
|
+
* The events that end a publish. archive.* events belong to the zip export,
|
|
13
|
+
* which runs on the same build, so they must not end a publish wait.
|
|
14
|
+
*/
|
|
15
|
+
export const PUBLISH_TERMINAL_EVENTS = new Set(["build.failed", "deployment.completed"]);
|
|
16
|
+
function truncate(str, max = 200) {
|
|
17
|
+
const oneLine = String(str).replace(/\s+/g, " ").trim();
|
|
18
|
+
return oneLine.length > max ? `${oneLine.slice(0, max)}…` : oneLine;
|
|
19
|
+
}
|
|
20
|
+
/** Port of the CLI's formatDeployEventForConsole, so both read the same. */
|
|
21
|
+
export function formatDeployEvent(ev) {
|
|
22
|
+
const eventType = ev.event_type ?? "";
|
|
23
|
+
const payload = ev.payload && typeof ev.payload === "object" && !Array.isArray(ev.payload)
|
|
24
|
+
? ev.payload
|
|
25
|
+
: null;
|
|
26
|
+
if (eventType === "deployment.domain_wiring" && payload) {
|
|
27
|
+
const host = typeof payload.hostname === "string" ? payload.hostname : "";
|
|
28
|
+
const https = host ? `https://${host}` : "";
|
|
29
|
+
switch (payload.step) {
|
|
30
|
+
case "started":
|
|
31
|
+
return `${eventType}: preparing ${host || "platform hostname"}`;
|
|
32
|
+
case "dns_ok":
|
|
33
|
+
return `${eventType}: DNS CNAME ready (${host})`;
|
|
34
|
+
case "dns_resolve_ok":
|
|
35
|
+
return payload.skipped ? `${eventType}: skipped public DNS wait` : `${eventType}: hostname resolves (${host})`;
|
|
36
|
+
case "attach_ok":
|
|
37
|
+
return `${eventType}: registered on Cloudflare Pages (${host})`;
|
|
38
|
+
case "polling":
|
|
39
|
+
return `${eventType}: Pages status "${typeof payload.pages_status === "string" && payload.pages_status ? payload.pages_status : "…"}" (${host})`;
|
|
40
|
+
case "active":
|
|
41
|
+
return `${eventType}: live — ${https}`;
|
|
42
|
+
case "failed":
|
|
43
|
+
return `${eventType}: failed — ${truncate(payload.error ?? "unknown", 160)}`;
|
|
44
|
+
case "timeout":
|
|
45
|
+
return `${eventType}: still pending after wait (try ${https || "URL"} shortly)`;
|
|
46
|
+
default:
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const extra = ev.payload ? ` ${truncate(JSON.stringify(ev.payload))}` : "";
|
|
51
|
+
return `${eventType}${extra}`;
|
|
52
|
+
}
|
|
53
|
+
export function toDeployEvent(row) {
|
|
54
|
+
return { id: row.id, type: row.event_type ?? "", message: formatDeployEvent(row), created_at: row.created_at ?? null };
|
|
55
|
+
}
|
|
56
|
+
/** Highest build_deploy_events.id for the build, 0 when none: the cursor taken before publishing. */
|
|
57
|
+
export async function getMaxDeployEventId(http, buildId) {
|
|
58
|
+
const row = await http.selectOne("build_deploy_events", {
|
|
59
|
+
select: "id",
|
|
60
|
+
filters: { build_id: eq(buildId) },
|
|
61
|
+
order: "id.desc",
|
|
62
|
+
});
|
|
63
|
+
const n = Number(row?.id);
|
|
64
|
+
return Number.isFinite(n) ? n : 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Highest build_deploy_events.id across the project, 0 when none. Taken
|
|
68
|
+
* before a post change, when the build the server will rebuild is not known
|
|
69
|
+
* yet: event ids are global and polling filters by build, so any later event
|
|
70
|
+
* of whichever build gets rebuilt lands after it.
|
|
71
|
+
*/
|
|
72
|
+
export async function getMaxProjectDeployEventId(http, projectId) {
|
|
73
|
+
const row = await http.selectOne("build_deploy_events", {
|
|
74
|
+
select: "id",
|
|
75
|
+
filters: { project_id: eq(projectId) },
|
|
76
|
+
order: "id.desc",
|
|
77
|
+
});
|
|
78
|
+
const n = Number(row?.id);
|
|
79
|
+
return Number.isFinite(n) ? n : 0;
|
|
80
|
+
}
|
|
81
|
+
/** created_at of the build's newest deploy event, null when it has none. */
|
|
82
|
+
export async function getLatestDeployEventAt(http, buildId) {
|
|
83
|
+
const row = await http.selectOne("build_deploy_events", {
|
|
84
|
+
select: "created_at",
|
|
85
|
+
filters: { build_id: eq(buildId) },
|
|
86
|
+
order: "id.desc",
|
|
87
|
+
});
|
|
88
|
+
return row?.created_at ?? null;
|
|
89
|
+
}
|
|
90
|
+
export const EVENTS_PAGE = 100;
|
|
91
|
+
export async function fetchDeployEventsAfter(http, buildId, afterId) {
|
|
92
|
+
return http.select("build_deploy_events", {
|
|
93
|
+
select: "id,event_type,payload,created_at",
|
|
94
|
+
filters: { build_id: eq(buildId), id: gt(afterId) },
|
|
95
|
+
order: "id.asc",
|
|
96
|
+
limit: EVENTS_PAGE,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
export const realClock = {
|
|
100
|
+
now: () => Date.now(),
|
|
101
|
+
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
102
|
+
};
|
|
103
|
+
export const POLL_INTERVAL_MS = 2_000;
|
|
104
|
+
/**
|
|
105
|
+
* Polls builds.status and build_deploy_events (id > cursor) until the deploy
|
|
106
|
+
* ends (see PollOptions.trustEvents) or waitMs runs out. Always polls at
|
|
107
|
+
* least once, so waitMs 0 is a single snapshot. Never sleeps past the
|
|
108
|
+
* deadline and does not start a poll it would have to finish after it.
|
|
109
|
+
*/
|
|
110
|
+
export async function pollDeployStatus(options) {
|
|
111
|
+
const { http, projectId, buildId } = options;
|
|
112
|
+
const clock = options.clock ?? realClock;
|
|
113
|
+
const interval = options.intervalMs ?? POLL_INTERVAL_MS;
|
|
114
|
+
const cursorMode = options.trustEvents !== false;
|
|
115
|
+
const start = clock.now();
|
|
116
|
+
const deadline = start + Math.max(0, options.waitMs);
|
|
117
|
+
let cursor = options.afterId;
|
|
118
|
+
const events = [];
|
|
119
|
+
let terminal = null;
|
|
120
|
+
let sawInProgress = false;
|
|
121
|
+
for (;;) {
|
|
122
|
+
// Status before events: the publisher writes the status first, so the
|
|
123
|
+
// event that goes with a terminal status is normally already visible.
|
|
124
|
+
const build = await http.selectOne("builds", {
|
|
125
|
+
select: "id,number,status,failure_reason,updated_at",
|
|
126
|
+
filters: { id: eq(buildId), project_id: eq(projectId) },
|
|
127
|
+
});
|
|
128
|
+
if (!build) {
|
|
129
|
+
throw new MicropageError("BUILD_NOT_FOUND", `Build id ${buildId} is not in this project. Call list_builds to see its builds.`);
|
|
130
|
+
}
|
|
131
|
+
const rows = await fetchDeployEventsAfter(http, buildId, cursor);
|
|
132
|
+
const fresh = rows.map(toDeployEvent);
|
|
133
|
+
for (const ev of fresh)
|
|
134
|
+
cursor = Math.max(cursor, ev.id);
|
|
135
|
+
events.push(...fresh);
|
|
136
|
+
const inProgress = IN_PROGRESS_STATUSES.has(build.status ?? "");
|
|
137
|
+
if (cursorMode) {
|
|
138
|
+
terminal ??= fresh.find((e) => PUBLISH_TERMINAL_EVENTS.has(e.type)) ?? null;
|
|
139
|
+
}
|
|
140
|
+
const settledByStatus = !inProgress && (!cursorMode || sawInProgress);
|
|
141
|
+
if (inProgress)
|
|
142
|
+
sawInProgress = true;
|
|
143
|
+
const done = terminal !== null || settledByStatus;
|
|
144
|
+
if (options.onPoll) {
|
|
145
|
+
try {
|
|
146
|
+
await options.onPoll({ elapsedMs: clock.now() - start, status: build.status, newEvents: fresh });
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// progress is best effort
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const now = clock.now();
|
|
153
|
+
// A full page means more events are waiting: drain them while time allows.
|
|
154
|
+
const more = rows.length >= EVENTS_PAGE && now < deadline;
|
|
155
|
+
if (!more && (done || deadline - now <= interval)) {
|
|
156
|
+
return {
|
|
157
|
+
build,
|
|
158
|
+
events,
|
|
159
|
+
after_event_id: cursor,
|
|
160
|
+
done,
|
|
161
|
+
terminal_event: terminal,
|
|
162
|
+
timed_out: !done,
|
|
163
|
+
waiting_for_start: cursorMode && !done && !inProgress,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if (!more)
|
|
167
|
+
await clock.sleep(interval);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=deploy-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-events.js","sourceRoot":"","sources":["../../src/client/deploy-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { AuthProvider } from "./auth-provider.js";
|
|
2
|
+
import type { MicropageConfig } from "./config.js";
|
|
3
|
+
import type { FetchLike } from "./http.js";
|
|
4
|
+
/** TTL requested from exchange-deploy-token (the function clamps to 60-3600 s). */
|
|
5
|
+
export declare const DEPLOY_TOKEN_TTL_SECONDS = 1800;
|
|
6
|
+
export interface DeployTokenEnv {
|
|
7
|
+
token: string;
|
|
8
|
+
projectUuid: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* MICROPAGE_DEPLOY_TOKEN + MICROPAGE_DEPLOY_PROJECT, or null when neither is
|
|
12
|
+
* set. Exactly one set, or a project that is not a uuid, is a config mistake
|
|
13
|
+
* the user must fix, so it throws rather than silently falling back to the
|
|
14
|
+
* CLI session (which would act with broader access than they configured).
|
|
15
|
+
*/
|
|
16
|
+
export declare function readDeployTokenEnv(env?: NodeJS.ProcessEnv): DeployTokenEnv | null;
|
|
17
|
+
export interface DeployTokenAuthOptions extends DeployTokenEnv {
|
|
18
|
+
config: Pick<MicropageConfig, "supabaseUrl" | "supabaseAnonKey">;
|
|
19
|
+
fetch?: FetchLike;
|
|
20
|
+
now?: () => number;
|
|
21
|
+
ttlSeconds?: number;
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Exchanges a project deploy token for a short-lived owner JWT
|
|
26
|
+
* (supabase/functions/exchange-deploy-token), re-exchanging shortly before it
|
|
27
|
+
* expires. The JWT is a full owner token server-side; the pin to one project
|
|
28
|
+
* is enforced client-side (project-ref + guards).
|
|
29
|
+
*/
|
|
30
|
+
export declare class DeployTokenAuthProvider implements AuthProvider {
|
|
31
|
+
readonly mode: "deploy_token";
|
|
32
|
+
readonly pinnedProjectUuid: string;
|
|
33
|
+
/** Internal numeric id of the pinned project, known after the first exchange. */
|
|
34
|
+
projectId: number | undefined;
|
|
35
|
+
private readonly token;
|
|
36
|
+
private readonly config;
|
|
37
|
+
private readonly fetchImpl;
|
|
38
|
+
private readonly now;
|
|
39
|
+
private readonly ttlSeconds;
|
|
40
|
+
private readonly timeoutMs;
|
|
41
|
+
private cached;
|
|
42
|
+
private inflight;
|
|
43
|
+
constructor(options: DeployTokenAuthOptions);
|
|
44
|
+
getAccessToken(options?: {
|
|
45
|
+
forceRefresh?: boolean;
|
|
46
|
+
}): Promise<string>;
|
|
47
|
+
private exchange;
|
|
48
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { VERSION } from "../version.js";
|
|
2
|
+
import { MicropageError } from "./errors.js";
|
|
3
|
+
import { isProjectUuid } from "./project-ref.js";
|
|
4
|
+
/** TTL requested from exchange-deploy-token (the function clamps to 60-3600 s). */
|
|
5
|
+
export const DEPLOY_TOKEN_TTL_SECONDS = 1800;
|
|
6
|
+
/** Re-exchange this long before the minted JWT expires. */
|
|
7
|
+
const REEXCHANGE_SKEW_MS = 60_000;
|
|
8
|
+
/**
|
|
9
|
+
* MICROPAGE_DEPLOY_TOKEN + MICROPAGE_DEPLOY_PROJECT, or null when neither is
|
|
10
|
+
* set. Exactly one set, or a project that is not a uuid, is a config mistake
|
|
11
|
+
* the user must fix, so it throws rather than silently falling back to the
|
|
12
|
+
* CLI session (which would act with broader access than they configured).
|
|
13
|
+
*/
|
|
14
|
+
export function readDeployTokenEnv(env = process.env) {
|
|
15
|
+
const token = env.MICROPAGE_DEPLOY_TOKEN?.trim() ?? "";
|
|
16
|
+
const projectUuid = env.MICROPAGE_DEPLOY_PROJECT?.trim() ?? "";
|
|
17
|
+
if (!token && !projectUuid)
|
|
18
|
+
return null;
|
|
19
|
+
if (!token || !projectUuid) {
|
|
20
|
+
const missing = token ? "MICROPAGE_DEPLOY_PROJECT" : "MICROPAGE_DEPLOY_TOKEN";
|
|
21
|
+
const present = token ? "MICROPAGE_DEPLOY_TOKEN" : "MICROPAGE_DEPLOY_PROJECT";
|
|
22
|
+
throw new MicropageError("DEPLOY_TOKEN_CONFIG", `${present} is set but ${missing} is not. Set both (the deploy token and the project's uuid) ` +
|
|
23
|
+
`or neither (to use the \`micropage login\` session).`);
|
|
24
|
+
}
|
|
25
|
+
if (!isProjectUuid(projectUuid)) {
|
|
26
|
+
throw new MicropageError("DEPLOY_TOKEN_CONFIG", `MICROPAGE_DEPLOY_PROJECT must be the project's uuid (e.g. 1b4e28ba-2fa1-11d2-883f-0016d3cca427), got "${projectUuid}".`);
|
|
27
|
+
}
|
|
28
|
+
return { token, projectUuid: projectUuid.toLowerCase() };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Exchanges a project deploy token for a short-lived owner JWT
|
|
32
|
+
* (supabase/functions/exchange-deploy-token), re-exchanging shortly before it
|
|
33
|
+
* expires. The JWT is a full owner token server-side; the pin to one project
|
|
34
|
+
* is enforced client-side (project-ref + guards).
|
|
35
|
+
*/
|
|
36
|
+
export class DeployTokenAuthProvider {
|
|
37
|
+
mode = "deploy_token";
|
|
38
|
+
pinnedProjectUuid;
|
|
39
|
+
/** Internal numeric id of the pinned project, known after the first exchange. */
|
|
40
|
+
projectId;
|
|
41
|
+
token;
|
|
42
|
+
config;
|
|
43
|
+
fetchImpl;
|
|
44
|
+
now;
|
|
45
|
+
ttlSeconds;
|
|
46
|
+
timeoutMs;
|
|
47
|
+
cached = null;
|
|
48
|
+
inflight = null;
|
|
49
|
+
constructor(options) {
|
|
50
|
+
this.token = options.token;
|
|
51
|
+
this.pinnedProjectUuid = options.projectUuid.toLowerCase();
|
|
52
|
+
this.config = options.config;
|
|
53
|
+
this.fetchImpl = options.fetch ?? ((input, init) => fetch(input, init));
|
|
54
|
+
this.now = options.now ?? Date.now;
|
|
55
|
+
this.ttlSeconds = options.ttlSeconds ?? DEPLOY_TOKEN_TTL_SECONDS;
|
|
56
|
+
this.timeoutMs = options.timeoutMs ?? 20_000;
|
|
57
|
+
}
|
|
58
|
+
async getAccessToken(options = {}) {
|
|
59
|
+
const cached = this.cached;
|
|
60
|
+
if (!options.forceRefresh && cached && cached.expiresAtMs - REEXCHANGE_SKEW_MS > this.now()) {
|
|
61
|
+
return cached.accessToken;
|
|
62
|
+
}
|
|
63
|
+
this.inflight ??= this.exchange(options.forceRefresh ? cached?.accessToken : undefined).finally(() => {
|
|
64
|
+
this.inflight = null;
|
|
65
|
+
});
|
|
66
|
+
return this.inflight;
|
|
67
|
+
}
|
|
68
|
+
async exchange(rejected) {
|
|
69
|
+
let res;
|
|
70
|
+
try {
|
|
71
|
+
res = await this.fetchImpl(`${this.config.supabaseUrl}/functions/v1/exchange-deploy-token`, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers: {
|
|
74
|
+
apikey: this.config.supabaseAnonKey,
|
|
75
|
+
Authorization: `Bearer ${this.token}`,
|
|
76
|
+
"Content-Type": "application/json",
|
|
77
|
+
"User-Agent": `micropage-mcp/${VERSION}`,
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({ projectUuid: this.pinnedProjectUuid, expiresInSeconds: this.ttlSeconds }),
|
|
80
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
throw new MicropageError("NETWORK", `Exchanging the deploy token failed before a response arrived (${err instanceof Error ? err.message : String(err)}). Check the network and retry.`, { cause: err });
|
|
85
|
+
}
|
|
86
|
+
const text = await res.text().catch(() => "");
|
|
87
|
+
let data = null;
|
|
88
|
+
try {
|
|
89
|
+
data = text ? JSON.parse(text) : null;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
data = null;
|
|
93
|
+
}
|
|
94
|
+
const detail = (typeof data?.error === "string" && data.error) ||
|
|
95
|
+
(typeof data?.message === "string" && data.message) ||
|
|
96
|
+
`HTTP ${res.status}`;
|
|
97
|
+
if (res.status === 401 || res.status === 403) {
|
|
98
|
+
throw new MicropageError("DEPLOY_TOKEN_INVALID", `The deploy token was rejected (${detail}). Ask the user to check MICROPAGE_DEPLOY_TOKEN, or to create a new ` +
|
|
99
|
+
`token in the micropage editor under Settings > Deploy tokens.`, { status: res.status, data });
|
|
100
|
+
}
|
|
101
|
+
if (res.status === 404) {
|
|
102
|
+
throw new MicropageError("DEPLOY_TOKEN_INVALID", `No project with uuid ${this.pinnedProjectUuid} exists (${detail}). Ask the user to check MICROPAGE_DEPLOY_PROJECT.`, { status: 404, data });
|
|
103
|
+
}
|
|
104
|
+
if (!res.ok) {
|
|
105
|
+
throw new MicropageError("HTTP", `Exchanging the deploy token failed (HTTP ${res.status}): ${detail}`, {
|
|
106
|
+
status: res.status,
|
|
107
|
+
data,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (typeof data?.access_token !== "string" || !data.access_token) {
|
|
111
|
+
throw new MicropageError("HTTP", "exchange-deploy-token answered without an access_token.", { data });
|
|
112
|
+
}
|
|
113
|
+
if (rejected !== undefined && data.access_token === rejected) {
|
|
114
|
+
// Minted twice in the same second with identical claims: the server
|
|
115
|
+
// rejected a token it would mint again, so retrying cannot help.
|
|
116
|
+
throw new MicropageError("DEPLOY_TOKEN_INVALID", "micropage rejected a freshly exchanged deploy-token session. Ask the user to check the deploy token, then retry.");
|
|
117
|
+
}
|
|
118
|
+
const expiresAtMs = typeof data.expires_at === "number"
|
|
119
|
+
? data.expires_at * 1000
|
|
120
|
+
: this.now() + (typeof data.expires_in === "number" ? data.expires_in : this.ttlSeconds) * 1000;
|
|
121
|
+
if (typeof data.project_id === "number" || typeof data.project_id === "string") {
|
|
122
|
+
const id = Number(data.project_id);
|
|
123
|
+
if (Number.isFinite(id))
|
|
124
|
+
this.projectId = id;
|
|
125
|
+
}
|
|
126
|
+
this.cached = { accessToken: data.access_token, expiresAtMs };
|
|
127
|
+
return data.access_token;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=deploy-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-token.js","sourceRoot":"","sources":["../../src/client/deploy-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type MicropageErrorCode = "NOT_LOGGED_IN" | "SESSION_EXPIRED" | "HTTP" | "TIMEOUT" | "NETWORK" | "CONFIRM_REQUIRED" | "CONFIRM_INVALID" | "DISABLED" | "NOT_ALLOWED_IN_DEPLOY_TOKEN_MODE" | (string & {});
|
|
2
|
+
export interface MicropageErrorOptions {
|
|
3
|
+
status?: number;
|
|
4
|
+
data?: unknown;
|
|
5
|
+
cause?: unknown;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The one error type the client and guards throw. `message` is written for
|
|
9
|
+
* the model: it says what went wrong and names the call or argument that
|
|
10
|
+
* fixes it, because the model sees nothing else.
|
|
11
|
+
*/
|
|
12
|
+
export declare class MicropageError extends Error {
|
|
13
|
+
readonly code: MicropageErrorCode;
|
|
14
|
+
readonly status: number | undefined;
|
|
15
|
+
readonly data: unknown;
|
|
16
|
+
constructor(code: MicropageErrorCode, message: string, options?: MicropageErrorOptions);
|
|
17
|
+
}
|
|
18
|
+
export declare function isMicropageError(err: unknown): err is MicropageError;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one error type the client and guards throw. `message` is written for
|
|
3
|
+
* the model: it says what went wrong and names the call or argument that
|
|
4
|
+
* fixes it, because the model sees nothing else.
|
|
5
|
+
*/
|
|
6
|
+
export class MicropageError extends Error {
|
|
7
|
+
code;
|
|
8
|
+
status;
|
|
9
|
+
data;
|
|
10
|
+
constructor(code, message, options = {}) {
|
|
11
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
12
|
+
this.name = "MicropageError";
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.status = options.status;
|
|
15
|
+
this.data = options.data;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function isMicropageError(err) {
|
|
19
|
+
return err instanceof MicropageError;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/client/errors.ts"],"names":[],"mappings":"AAkBA;;;;GAIG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,IAAI,CAAqB;IACzB,MAAM,CAAqB;IAC3B,IAAI,CAAU;IAEvB,YAAY,IAAwB,EAAE,OAAe,EAAE,UAAiC,EAAE;QACxF,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,OAAO,GAAG,YAAY,cAAc,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { AuthProvider } from "./auth-provider.js";
|
|
2
|
+
import type { MicropageConfig } from "./config.js";
|
|
3
|
+
export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
4
|
+
export interface HttpOptions {
|
|
5
|
+
config: MicropageConfig;
|
|
6
|
+
auth: AuthProvider;
|
|
7
|
+
fetch?: FetchLike;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
userAgent?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RequestOptions {
|
|
12
|
+
/** JSON-serialised into the request body. */
|
|
13
|
+
body?: unknown;
|
|
14
|
+
/** Sent as-is (uploads). Takes precedence over `body`. */
|
|
15
|
+
rawBody?: NonNullable<RequestInit["body"]>;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* When false the anon key is sent as the bearer instead of a user token —
|
|
19
|
+
* for endpoints that run before the user is known (deploy-token exchange).
|
|
20
|
+
*/
|
|
21
|
+
auth?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** PostgREST filter expressions keyed by column, e.g. `{ id: eq(42) }`. */
|
|
24
|
+
export type Filters = Record<string, string>;
|
|
25
|
+
export declare const eq: (v: string | number | boolean) => string;
|
|
26
|
+
export declare const neq: (v: string | number | boolean) => string;
|
|
27
|
+
export declare const is: (v: "null" | "true" | "false") => string;
|
|
28
|
+
export declare const inList: (vs: ReadonlyArray<string | number>) => string;
|
|
29
|
+
export declare const gt: (v: string | number) => string;
|
|
30
|
+
export interface SelectOptions {
|
|
31
|
+
select?: string;
|
|
32
|
+
filters?: Filters;
|
|
33
|
+
order?: string;
|
|
34
|
+
limit?: number;
|
|
35
|
+
}
|
|
36
|
+
export declare const DEFAULT_TIMEOUT_MS = 20000;
|
|
37
|
+
/**
|
|
38
|
+
* fetch wrapper for Supabase (PostgREST + edge functions) and the build
|
|
39
|
+
* compiler. Mirrors the CLI's request() (cli/src/supabase.js): apikey header
|
|
40
|
+
* plus a user bearer, and one forced refresh + retry on 401 to cover tokens
|
|
41
|
+
* that expired server-side before the local expiry check caught them.
|
|
42
|
+
*/
|
|
43
|
+
export declare class Http {
|
|
44
|
+
readonly config: MicropageConfig;
|
|
45
|
+
readonly auth: AuthProvider;
|
|
46
|
+
private readonly fetchImpl;
|
|
47
|
+
private readonly timeoutMs;
|
|
48
|
+
private readonly userAgent;
|
|
49
|
+
constructor(options: HttpOptions);
|
|
50
|
+
request<T = unknown>(method: string, url: string, options?: RequestOptions): Promise<T>;
|
|
51
|
+
/** The response after auth and the one 401 retry; the caller reads (or cancels) the body. */
|
|
52
|
+
private exchange;
|
|
53
|
+
/**
|
|
54
|
+
* Exact row count from PostgREST's Content-Range (a HEAD with
|
|
55
|
+
* Prefer: count=exact). Selecting rows to count them would stop at the
|
|
56
|
+
* server's max_rows cap and undercount silently.
|
|
57
|
+
*/
|
|
58
|
+
count(table: string, filters?: Filters): Promise<number>;
|
|
59
|
+
select<T = unknown>(table: string, options?: SelectOptions): Promise<T[]>;
|
|
60
|
+
selectOne<T = unknown>(table: string, options?: SelectOptions): Promise<T | null>;
|
|
61
|
+
insert<T = unknown>(table: string, rows: object | object[]): Promise<T[]>;
|
|
62
|
+
patch<T = unknown>(table: string, filters: Filters, values: object): Promise<T[]>;
|
|
63
|
+
invoke<T = unknown>(name: string, body?: unknown): Promise<T>;
|
|
64
|
+
invokeGet<T = unknown>(name: string, params?: Record<string, string>): Promise<T>;
|
|
65
|
+
restUrl(table: string, params?: URLSearchParams): string;
|
|
66
|
+
functionUrl(name: string): string;
|
|
67
|
+
private send;
|
|
68
|
+
}
|