@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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/dist/annotations.d.ts +20 -0
  4. package/dist/annotations.js +36 -0
  5. package/dist/annotations.js.map +1 -0
  6. package/dist/client/assets.d.ts +85 -0
  7. package/dist/client/assets.js +473 -0
  8. package/dist/client/assets.js.map +1 -0
  9. package/dist/client/auth-provider.d.ts +24 -0
  10. package/dist/client/auth-provider.js +10 -0
  11. package/dist/client/auth-provider.js.map +1 -0
  12. package/dist/client/builds.d.ts +82 -0
  13. package/dist/client/builds.js +166 -0
  14. package/dist/client/builds.js.map +1 -0
  15. package/dist/client/config.d.ts +18 -0
  16. package/dist/client/config.js +29 -0
  17. package/dist/client/config.js.map +1 -0
  18. package/dist/client/deploy-events.d.ts +98 -0
  19. package/dist/client/deploy-events.js +170 -0
  20. package/dist/client/deploy-events.js.map +1 -0
  21. package/dist/client/deploy-token.d.ts +48 -0
  22. package/dist/client/deploy-token.js +130 -0
  23. package/dist/client/deploy-token.js.map +1 -0
  24. package/dist/client/errors.d.ts +18 -0
  25. package/dist/client/errors.js +21 -0
  26. package/dist/client/errors.js.map +1 -0
  27. package/dist/client/http.d.ts +68 -0
  28. package/dist/client/http.js +191 -0
  29. package/dist/client/http.js.map +1 -0
  30. package/dist/client/jwt.d.ts +13 -0
  31. package/dist/client/jwt.js +23 -0
  32. package/dist/client/jwt.js.map +1 -0
  33. package/dist/client/lock.d.ts +16 -0
  34. package/dist/client/lock.js +67 -0
  35. package/dist/client/lock.js.map +1 -0
  36. package/dist/client/pages.d.ts +47 -0
  37. package/dist/client/pages.js +131 -0
  38. package/dist/client/pages.js.map +1 -0
  39. package/dist/client/posts.d.ts +108 -0
  40. package/dist/client/posts.js +187 -0
  41. package/dist/client/posts.js.map +1 -0
  42. package/dist/client/project-ref.d.ts +68 -0
  43. package/dist/client/project-ref.js +118 -0
  44. package/dist/client/project-ref.js.map +1 -0
  45. package/dist/client/session-store.d.ts +81 -0
  46. package/dist/client/session-store.js +271 -0
  47. package/dist/client/session-store.js.map +1 -0
  48. package/dist/client/submissions.d.ts +59 -0
  49. package/dist/client/submissions.js +111 -0
  50. package/dist/client/submissions.js.map +1 -0
  51. package/dist/client/tier.d.ts +42 -0
  52. package/dist/client/tier.js +76 -0
  53. package/dist/client/tier.js.map +1 -0
  54. package/dist/content/index.d.ts +5 -0
  55. package/dist/content/index.js +28 -0
  56. package/dist/content/index.js.map +1 -0
  57. package/dist/context.d.ts +30 -0
  58. package/dist/context.js +2 -0
  59. package/dist/context.js.map +1 -0
  60. package/dist/guards.d.ts +55 -0
  61. package/dist/guards.js +168 -0
  62. package/dist/guards.js.map +1 -0
  63. package/dist/index.d.ts +2 -0
  64. package/dist/index.js +16 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/progress.d.ts +7 -0
  67. package/dist/progress.js +25 -0
  68. package/dist/progress.js.map +1 -0
  69. package/dist/reference/prompts.d.ts +6 -0
  70. package/dist/reference/prompts.js +110 -0
  71. package/dist/reference/prompts.js.map +1 -0
  72. package/dist/reference/resources.d.ts +2 -0
  73. package/dist/reference/resources.js +41 -0
  74. package/dist/reference/resources.js.map +1 -0
  75. package/dist/reference/tool.d.ts +21 -0
  76. package/dist/reference/tool.js +50 -0
  77. package/dist/reference/tool.js.map +1 -0
  78. package/dist/reference/topics.d.ts +29 -0
  79. package/dist/reference/topics.js +91 -0
  80. package/dist/reference/topics.js.map +1 -0
  81. package/dist/reference.d.ts +9 -0
  82. package/dist/reference.js +20 -0
  83. package/dist/reference.js.map +1 -0
  84. package/dist/server.d.ts +29 -0
  85. package/dist/server.js +75 -0
  86. package/dist/server.js.map +1 -0
  87. package/dist/tools/account.d.ts +34 -0
  88. package/dist/tools/account.js +128 -0
  89. package/dist/tools/account.js.map +1 -0
  90. package/dist/tools/builds.d.ts +95 -0
  91. package/dist/tools/builds.js +403 -0
  92. package/dist/tools/builds.js.map +1 -0
  93. package/dist/tools/files.d.ts +71 -0
  94. package/dist/tools/files.js +205 -0
  95. package/dist/tools/files.js.map +1 -0
  96. package/dist/tools/forms.d.ts +59 -0
  97. package/dist/tools/forms.js +177 -0
  98. package/dist/tools/forms.js.map +1 -0
  99. package/dist/tools/posts.d.ts +191 -0
  100. package/dist/tools/posts.js +600 -0
  101. package/dist/tools/posts.js.map +1 -0
  102. package/dist/tools/projects.d.ts +201 -0
  103. package/dist/tools/projects.js +553 -0
  104. package/dist/tools/projects.js.map +1 -0
  105. package/dist/tools/shared.d.ts +33 -0
  106. package/dist/tools/shared.js +41 -0
  107. package/dist/tools/shared.js.map +1 -0
  108. package/dist/version.d.ts +2 -0
  109. package/dist/version.js +8 -0
  110. package/dist/version.js.map +1 -0
  111. package/package.json +67 -0
@@ -0,0 +1,191 @@
1
+ import { VERSION } from "../version.js";
2
+ import { MicropageError } from "./errors.js";
3
+ export const eq = (v) => `eq.${v}`;
4
+ export const neq = (v) => `neq.${v}`;
5
+ export const is = (v) => `is.${v}`;
6
+ export const inList = (vs) => `in.(${vs.join(",")})`;
7
+ export const gt = (v) => `gt.${v}`;
8
+ export const DEFAULT_TIMEOUT_MS = 20_000;
9
+ /**
10
+ * fetch wrapper for Supabase (PostgREST + edge functions) and the build
11
+ * compiler. Mirrors the CLI's request() (cli/src/supabase.js): apikey header
12
+ * plus a user bearer, and one forced refresh + retry on 401 to cover tokens
13
+ * that expired server-side before the local expiry check caught them.
14
+ */
15
+ export class Http {
16
+ config;
17
+ auth;
18
+ fetchImpl;
19
+ timeoutMs;
20
+ userAgent;
21
+ constructor(options) {
22
+ this.config = options.config;
23
+ this.auth = options.auth;
24
+ this.fetchImpl = options.fetch ?? ((input, init) => fetch(input, init));
25
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
26
+ this.userAgent = options.userAgent ?? `micropage-mcp/${VERSION}`;
27
+ }
28
+ async request(method, url, options = {}) {
29
+ const res = await this.exchange(method, url, options);
30
+ const data = await readBody(res);
31
+ if (!res.ok)
32
+ throw httpError(method, url, res, data);
33
+ return data;
34
+ }
35
+ /** The response after auth and the one 401 retry; the caller reads (or cancels) the body. */
36
+ async exchange(method, url, options) {
37
+ const useAuth = options.auth !== false;
38
+ let token = useAuth ? await this.auth.getAccessToken() : this.config.supabaseAnonKey;
39
+ let res = await this.send(method, url, token, options);
40
+ if (res.status === 401 && useAuth) {
41
+ const refreshed = await this.auth.getAccessToken({ forceRefresh: true });
42
+ if (refreshed !== token) {
43
+ await res.body?.cancel().catch(() => undefined);
44
+ token = refreshed;
45
+ res = await this.send(method, url, token, options);
46
+ }
47
+ }
48
+ return res;
49
+ }
50
+ /**
51
+ * Exact row count from PostgREST's Content-Range (a HEAD with
52
+ * Prefer: count=exact). Selecting rows to count them would stop at the
53
+ * server's max_rows cap and undercount silently.
54
+ */
55
+ async count(table, filters = {}) {
56
+ const params = new URLSearchParams();
57
+ params.set("select", "*");
58
+ appendFilters(params, filters);
59
+ const url = this.restUrl(table, params);
60
+ const res = await this.exchange("HEAD", url, { headers: { Prefer: "count=exact" } });
61
+ const data = await readBody(res);
62
+ if (!res.ok)
63
+ throw httpError("HEAD", url, res, data);
64
+ const total = /\/(\d+)\s*$/.exec(res.headers.get("content-range") ?? "")?.[1];
65
+ if (total === undefined) {
66
+ throw new MicropageError("HTTP", `HEAD ${new URL(url).pathname} returned no row count (Content-Range). Retry shortly.`, {
67
+ status: res.status,
68
+ });
69
+ }
70
+ return Number(total);
71
+ }
72
+ async select(table, options = {}) {
73
+ const params = new URLSearchParams();
74
+ params.set("select", options.select ?? "*");
75
+ appendFilters(params, options.filters);
76
+ if (options.order)
77
+ params.set("order", options.order);
78
+ if (options.limit !== undefined)
79
+ params.set("limit", String(options.limit));
80
+ const rows = await this.request("GET", this.restUrl(table, params));
81
+ return rows ?? [];
82
+ }
83
+ async selectOne(table, options = {}) {
84
+ const rows = await this.select(table, { ...options, limit: 1 });
85
+ return rows[0] ?? null;
86
+ }
87
+ async insert(table, rows) {
88
+ const out = await this.request("POST", this.restUrl(table), {
89
+ body: rows,
90
+ headers: { Prefer: "return=representation" },
91
+ });
92
+ return out ?? [];
93
+ }
94
+ async patch(table, filters, values) {
95
+ if (Object.keys(filters).length === 0) {
96
+ // An unfiltered PATCH updates every row RLS lets the user see.
97
+ throw new MicropageError("HTTP", `Refusing to PATCH ${table} without a filter.`);
98
+ }
99
+ const params = new URLSearchParams();
100
+ appendFilters(params, filters);
101
+ const out = await this.request("PATCH", this.restUrl(table, params), {
102
+ body: values,
103
+ headers: { Prefer: "return=representation" },
104
+ });
105
+ return out ?? [];
106
+ }
107
+ async invoke(name, body) {
108
+ return this.request("POST", this.functionUrl(name), body === undefined ? {} : { body });
109
+ }
110
+ async invokeGet(name, params = {}) {
111
+ const qs = new URLSearchParams(params).toString();
112
+ return this.request("GET", `${this.functionUrl(name)}${qs ? `?${qs}` : ""}`);
113
+ }
114
+ restUrl(table, params) {
115
+ const qs = params?.toString();
116
+ return `${this.config.supabaseUrl}/rest/v1/${table}${qs ? `?${qs}` : ""}`;
117
+ }
118
+ functionUrl(name) {
119
+ return `${this.config.supabaseUrl}/functions/v1/${name}`;
120
+ }
121
+ async send(method, url, token, options) {
122
+ const headers = {
123
+ apikey: this.config.supabaseAnonKey,
124
+ Authorization: `Bearer ${token}`,
125
+ "User-Agent": this.userAgent,
126
+ ...options.headers,
127
+ };
128
+ const init = { method, headers, signal: AbortSignal.timeout(this.timeoutMs) };
129
+ if (options.rawBody !== undefined) {
130
+ init.body = options.rawBody;
131
+ }
132
+ else if (options.body !== undefined) {
133
+ headers["Content-Type"] ??= "application/json";
134
+ init.body = JSON.stringify(options.body);
135
+ }
136
+ try {
137
+ return await this.fetchImpl(url, init);
138
+ }
139
+ catch (err) {
140
+ const where = describe(method, url);
141
+ if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
142
+ throw new MicropageError("TIMEOUT", `${where} timed out after ${Math.round(this.timeoutMs / 1000)}s. micropage may be slow right now; retry shortly.`, { cause: err });
143
+ }
144
+ throw new MicropageError("NETWORK", `${where} failed before a response arrived (${err instanceof Error ? err.message : String(err)}). Check the network and retry.`, { cause: err });
145
+ }
146
+ }
147
+ }
148
+ function appendFilters(params, filters) {
149
+ for (const [column, expr] of Object.entries(filters ?? {}))
150
+ params.append(column, expr);
151
+ }
152
+ async function readBody(res) {
153
+ const text = await res.text();
154
+ if (!text)
155
+ return null;
156
+ try {
157
+ return JSON.parse(text);
158
+ }
159
+ catch {
160
+ return text;
161
+ }
162
+ }
163
+ function describe(method, url) {
164
+ // Path only: query strings can carry filter values that read as noise to the model.
165
+ let path = url;
166
+ try {
167
+ path = new URL(url).pathname;
168
+ }
169
+ catch {
170
+ // keep the raw url
171
+ }
172
+ return `${method} ${path}`;
173
+ }
174
+ function httpError(method, url, res, data) {
175
+ if (res.status === 401) {
176
+ return new MicropageError("SESSION_EXPIRED", "The micropage session is no longer valid. Ask the user to run `micropage login` in a terminal, then retry.", { status: 401, data });
177
+ }
178
+ const detail = (data && typeof data === "object" && (pick(data, "message") ?? pick(data, "error"))) ||
179
+ (typeof data === "string" && data.length < 500 ? data : null) ||
180
+ res.statusText ||
181
+ `HTTP ${res.status}`;
182
+ return new MicropageError("HTTP", `${describe(method, url)} failed (HTTP ${res.status}): ${detail}`, {
183
+ status: res.status,
184
+ data,
185
+ });
186
+ }
187
+ function pick(obj, key) {
188
+ const v = obj[key];
189
+ return typeof v === "string" && v ? v : undefined;
190
+ }
191
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /** Unverified JWT claims. Only used to read `exp`, `sub` and `email` of tokens we already trust. */
2
+ export interface JwtClaims {
3
+ exp?: number;
4
+ sub?: string;
5
+ email?: string;
6
+ [claim: string]: unknown;
7
+ }
8
+ export declare function decodeJwtClaims(token: string): JwtClaims | null;
9
+ /**
10
+ * True when the token expires within `skewSeconds` (default 60, as the CLI).
11
+ * An unreadable token counts as expired so it gets refreshed rather than sent.
12
+ */
13
+ export declare function isJwtExpiring(token: string, nowMs: number, skewSeconds?: number): boolean;
@@ -0,0 +1,23 @@
1
+ export function decodeJwtClaims(token) {
2
+ const part = token.split(".")[1];
3
+ if (!part)
4
+ return null;
5
+ try {
6
+ const claims = JSON.parse(Buffer.from(part, "base64url").toString("utf8"));
7
+ return claims && typeof claims === "object" ? claims : null;
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ /**
14
+ * True when the token expires within `skewSeconds` (default 60, as the CLI).
15
+ * An unreadable token counts as expired so it gets refreshed rather than sent.
16
+ */
17
+ export function isJwtExpiring(token, nowMs, skewSeconds = 60) {
18
+ const exp = decodeJwtClaims(token)?.exp;
19
+ if (typeof exp !== "number" || !Number.isFinite(exp))
20
+ return true;
21
+ return exp < Math.floor(nowMs / 1000) + skewSeconds;
22
+ }
23
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/client/jwt.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACpF,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAE,MAAoB,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,KAAa,EAAE,WAAW,GAAG,EAAE;IAC1E,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC;IACxC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC;AACtD,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface LockOptions {
2
+ /** A lock older than this is assumed abandoned (its holder crashed) and is broken. */
3
+ staleMs?: number;
4
+ /** Poll interval while another process holds the lock. */
5
+ retryMs?: number;
6
+ /** Give up waiting after this long. */
7
+ timeoutMs?: number;
8
+ }
9
+ export declare const DEFAULT_LOCK_STALE_MS = 30000;
10
+ /**
11
+ * Cross-process mutex on a lockfile created with O_EXCL. Serialises token
12
+ * refreshes between MCP server processes sharing one CLI session file, since
13
+ * Supabase rotates the refresh token and a second use of the old one fails.
14
+ */
15
+ export declare function withFileLock<T>(lockPath: string, fn: () => Promise<T>, options?: LockOptions): Promise<T>;
16
+ export declare function acquireFileLock(lockPath: string, options?: LockOptions): Promise<() => Promise<void>>;
@@ -0,0 +1,67 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { open, readFile, stat, unlink } from "node:fs/promises";
3
+ import { MicropageError } from "./errors.js";
4
+ export const DEFAULT_LOCK_STALE_MS = 30_000;
5
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
+ /**
7
+ * Cross-process mutex on a lockfile created with O_EXCL. Serialises token
8
+ * refreshes between MCP server processes sharing one CLI session file, since
9
+ * Supabase rotates the refresh token and a second use of the old one fails.
10
+ */
11
+ export async function withFileLock(lockPath, fn, options = {}) {
12
+ const release = await acquireFileLock(lockPath, options);
13
+ try {
14
+ return await fn();
15
+ }
16
+ finally {
17
+ await release();
18
+ }
19
+ }
20
+ export async function acquireFileLock(lockPath, options = {}) {
21
+ const staleMs = options.staleMs ?? DEFAULT_LOCK_STALE_MS;
22
+ const retryMs = options.retryMs ?? 50;
23
+ const timeoutMs = options.timeoutMs ?? staleMs + 5_000;
24
+ const nonce = `${process.pid}.${randomBytes(8).toString("hex")}`;
25
+ const deadline = Date.now() + timeoutMs;
26
+ for (;;) {
27
+ try {
28
+ const handle = await open(lockPath, "wx", 0o600);
29
+ try {
30
+ await handle.writeFile(nonce, "utf8");
31
+ }
32
+ finally {
33
+ await handle.close();
34
+ }
35
+ return async () => {
36
+ // Only remove our own lock: if we overran staleMs, someone else may hold it now.
37
+ if ((await readFile(lockPath, "utf8").catch(() => null)) === nonce) {
38
+ await unlink(lockPath).catch(() => undefined);
39
+ }
40
+ };
41
+ }
42
+ catch (err) {
43
+ if (err.code !== "EEXIST")
44
+ throw err;
45
+ }
46
+ await breakIfStale(lockPath, staleMs);
47
+ if (Date.now() >= deadline) {
48
+ throw new MicropageError("SESSION_LOCKED", `Timed out waiting for another micropage process to finish refreshing the login session (${lockPath}). Retry shortly.`);
49
+ }
50
+ await sleep(retryMs);
51
+ }
52
+ }
53
+ async function breakIfStale(lockPath, staleMs) {
54
+ const info = await stat(lockPath).catch(() => null);
55
+ if (!info || Date.now() - info.mtimeMs < staleMs)
56
+ return;
57
+ // Re-check the holder right before unlinking so two waiters breaking the
58
+ // same stale lock are unlikely to delete a fresh lock the other just took.
59
+ const holder = await readFile(lockPath, "utf8").catch(() => null);
60
+ const again = await stat(lockPath).catch(() => null);
61
+ if (!again || again.mtimeMs !== info.mtimeMs)
62
+ return;
63
+ if ((await readFile(lockPath, "utf8").catch(() => null)) !== holder)
64
+ return;
65
+ await unlink(lockPath).catch(() => undefined);
66
+ }
67
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/client/lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { MicropageConfig } from "./config.js";
2
+ import type { Http } from "./http.js";
3
+ /** The CLI's primary file: always merged first. */
4
+ export declare const PRIMARY_PAGE = "landing.page";
5
+ /** Total merged source cap. Real sites are a few KB; this only stops runaway input. */
6
+ export declare const MAX_SOURCE_BYTES = 1000000;
7
+ /** llms.txt cap; the CLI has none, but it is read from disk rather than a tool argument. */
8
+ export declare const MAX_LLMS_TXT_BYTES = 200000;
9
+ export interface PageFile {
10
+ name: string;
11
+ content: string;
12
+ }
13
+ /**
14
+ * Merges inline page files exactly like the CLI's readPageFilesFromDir
15
+ * (cli/src/parser.js): landing.page first (trimmed, kept even when empty),
16
+ * then every other file sorted by name, trimmed, empty ones skipped, joined
17
+ * by one blank line. Validates names and size before anything is sent.
18
+ */
19
+ export declare function concatPages(pages: readonly PageFile[]): string;
20
+ /** llms.txt as the CLI stores it: verbatim minus one trailing newline; blank means none. */
21
+ export declare function normalizeLlmsTxt(value: string): string | null;
22
+ export type BuildJson = Record<string, unknown> & {
23
+ site?: Record<string, unknown>;
24
+ pages?: unknown[];
25
+ };
26
+ export interface ParseRequest {
27
+ text: string;
28
+ projectId: number;
29
+ /** The build the result will be stored on, when known (it is stamped into each page). */
30
+ buildId: number | null;
31
+ }
32
+ /**
33
+ * POST {buildCompilerUrl}/parse with the user's bearer, same body as the CLI.
34
+ * Not read-only: the compiler registers the source's forms on the project.
35
+ */
36
+ export declare function parsePageSource(http: Http, config: Pick<MicropageConfig, "buildCompilerUrl">, req: ParseRequest): Promise<BuildJson>;
37
+ /** Same placement as the CLI's push: json_content.site.llms_txt. */
38
+ export declare function injectLlmsTxt(json: BuildJson, llmsTxt: string | null): BuildJson;
39
+ export declare const MAX_PARSE_ISSUES = 50;
40
+ /**
41
+ * The compiler has no separate warnings list: an element it could not
42
+ * resolve (a missing file, a failed image search) carries an `error` string
43
+ * in place. Collects those, plus a site with no pages, so the model can fix
44
+ * them before publishing.
45
+ */
46
+ export declare function collectParseIssues(json: BuildJson): string[];
47
+ export declare function countPages(json: BuildJson): number;
@@ -0,0 +1,131 @@
1
+ import { MicropageError } from "./errors.js";
2
+ /** The CLI's primary file: always merged first. */
3
+ export const PRIMARY_PAGE = "landing.page";
4
+ /** Total merged source cap. Real sites are a few KB; this only stops runaway input. */
5
+ export const MAX_SOURCE_BYTES = 1_000_000;
6
+ /** llms.txt cap; the CLI has none, but it is read from disk rather than a tool argument. */
7
+ export const MAX_LLMS_TXT_BYTES = 200_000;
8
+ const PAGE_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*\.page$/;
9
+ /**
10
+ * Merges inline page files exactly like the CLI's readPageFilesFromDir
11
+ * (cli/src/parser.js): landing.page first (trimmed, kept even when empty),
12
+ * then every other file sorted by name, trimmed, empty ones skipped, joined
13
+ * by one blank line. Validates names and size before anything is sent.
14
+ */
15
+ export function concatPages(pages) {
16
+ if (pages.length === 0) {
17
+ throw new MicropageError("INVALID_PAGES", "Pass at least one page, e.g. pages: [{ name: \"landing.page\", content: \"...\" }].");
18
+ }
19
+ const seen = new Set();
20
+ for (const p of pages) {
21
+ if (!PAGE_NAME_RE.test(p.name)) {
22
+ throw new MicropageError("INVALID_PAGES", `Page name "${p.name}" is not valid. Use a plain file name ending in .page (letters, digits, ".", "_", "-"), ` +
23
+ `e.g. "landing.page" or "about.page". Nothing was saved.`);
24
+ }
25
+ if (seen.has(p.name)) {
26
+ throw new MicropageError("INVALID_PAGES", `Page name "${p.name}" appears twice. Each name must be unique. Nothing was saved.`);
27
+ }
28
+ seen.add(p.name);
29
+ }
30
+ const primary = pages.find((p) => p.name === PRIMARY_PAGE);
31
+ const others = pages
32
+ .filter((p) => p.name !== PRIMARY_PAGE)
33
+ .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
34
+ const parts = [];
35
+ if (primary)
36
+ parts.push(primary.content.trim());
37
+ for (const p of others) {
38
+ const content = p.content.trim();
39
+ if (content)
40
+ parts.push(content);
41
+ }
42
+ const text = parts.join("\n\n");
43
+ if (!text.trim()) {
44
+ throw new MicropageError("INVALID_PAGES", "Every page is empty. Write the .page markup into `content`. Nothing was saved.");
45
+ }
46
+ const bytes = Buffer.byteLength(text, "utf8");
47
+ if (bytes > MAX_SOURCE_BYTES) {
48
+ throw new MicropageError("INVALID_PAGES", `The merged source is ${bytes} bytes; the limit is ${MAX_SOURCE_BYTES}. Shorten the pages. Nothing was saved.`);
49
+ }
50
+ return text;
51
+ }
52
+ /** llms.txt as the CLI stores it: verbatim minus one trailing newline; blank means none. */
53
+ export function normalizeLlmsTxt(value) {
54
+ if (!value.trim())
55
+ return null;
56
+ const out = value.replace(/\n$/, "");
57
+ const bytes = Buffer.byteLength(out, "utf8");
58
+ if (bytes > MAX_LLMS_TXT_BYTES) {
59
+ throw new MicropageError("INVALID_PAGES", `llms_txt is ${bytes} bytes; the limit is ${MAX_LLMS_TXT_BYTES}. Shorten it. Nothing was saved.`);
60
+ }
61
+ return out;
62
+ }
63
+ /**
64
+ * POST {buildCompilerUrl}/parse with the user's bearer, same body as the CLI.
65
+ * Not read-only: the compiler registers the source's forms on the project.
66
+ */
67
+ export async function parsePageSource(http, config, req) {
68
+ const url = `${config.buildCompilerUrl.replace(/\/+$/, "")}/parse`;
69
+ let json;
70
+ try {
71
+ json = await http.request("POST", url, {
72
+ body: { text: req.text, project_id: req.projectId, build_id: req.buildId, version: "2" },
73
+ });
74
+ }
75
+ catch (err) {
76
+ if (err instanceof MicropageError && err.code === "HTTP") {
77
+ if (err.status === 403) {
78
+ throw new MicropageError("PARSE_FORBIDDEN", "The build compiler refused this project for the signed-in account (it does not own it). Nothing was saved.", { status: 403, data: err.data, cause: err });
79
+ }
80
+ throw new MicropageError("PARSE_FAILED", `The build compiler could not parse the source: ${err.message}. Check the markup against get_markup_reference. Nothing was saved.`, { ...(err.status === undefined ? {} : { status: err.status }), data: err.data, cause: err });
81
+ }
82
+ throw err;
83
+ }
84
+ if (!json || typeof json !== "object" || Array.isArray(json)) {
85
+ throw new MicropageError("PARSE_FAILED", "The build compiler returned an unexpected response. Retry shortly. Nothing was saved.");
86
+ }
87
+ return json;
88
+ }
89
+ /** Same placement as the CLI's push: json_content.site.llms_txt. */
90
+ export function injectLlmsTxt(json, llmsTxt) {
91
+ if (llmsTxt === null)
92
+ return json;
93
+ const site = json.site && typeof json.site === "object" ? json.site : {};
94
+ return { ...json, site: { ...site, llms_txt: llmsTxt } };
95
+ }
96
+ export const MAX_PARSE_ISSUES = 50;
97
+ /**
98
+ * The compiler has no separate warnings list: an element it could not
99
+ * resolve (a missing file, a failed image search) carries an `error` string
100
+ * in place. Collects those, plus a site with no pages, so the model can fix
101
+ * them before publishing.
102
+ */
103
+ export function collectParseIssues(json) {
104
+ const issues = [];
105
+ const pages = Array.isArray(json.pages) ? json.pages : [];
106
+ if (pages.length === 0) {
107
+ issues.push("No pages were produced. Add a page block such as `[Home -> /]` followed by `/// hero` or `/// section`.");
108
+ }
109
+ const walk = (node, depth) => {
110
+ if (issues.length >= MAX_PARSE_ISSUES || depth > 40 || !node || typeof node !== "object")
111
+ return;
112
+ if (Array.isArray(node)) {
113
+ for (const child of node)
114
+ walk(child, depth + 1);
115
+ return;
116
+ }
117
+ const obj = node;
118
+ if (typeof obj.error === "string" && obj.error)
119
+ issues.push(obj.error);
120
+ for (const [key, value] of Object.entries(obj)) {
121
+ if (key !== "error")
122
+ walk(value, depth + 1);
123
+ }
124
+ };
125
+ walk(json, 0);
126
+ return [...new Set(issues)].slice(0, MAX_PARSE_ISSUES);
127
+ }
128
+ export function countPages(json) {
129
+ return Array.isArray(json.pages) ? json.pages.length : 0;
130
+ }
131
+ //# sourceMappingURL=pages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/client/pages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ import { MicropageError } from "./errors.js";
2
+ import { type Http } from "./http.js";
3
+ /** Same rule as supabase/functions/_shared/slug.ts and the CLI's slugify. */
4
+ export declare function slugify(s: string): string;
5
+ export type WebVisibility = "listed" | "unlisted" | "none";
6
+ /** Columns for the list view (cli posts list, plus form_id to name the list). */
7
+ export declare const POST_LIST_COLUMNS = "id,slug,title,web_visibility,email_enabled,form_id,status,published_at,created_at,recipient_count";
8
+ /** Everything posts pull reads, plus the email fields upsert_post writes. */
9
+ export declare const POST_FULL_COLUMNS: string;
10
+ export interface PostListRow {
11
+ id: string;
12
+ slug: string | null;
13
+ title: string | null;
14
+ web_visibility: WebVisibility | null;
15
+ email_enabled: boolean | null;
16
+ form_id: string | null;
17
+ status: string | null;
18
+ published_at: string | null;
19
+ created_at: string | null;
20
+ recipient_count: number | null;
21
+ }
22
+ export interface PostRow extends PostListRow {
23
+ description: string | null;
24
+ body_markdown: string | null;
25
+ hero_image: string | null;
26
+ subject: string | null;
27
+ preheader: string | null;
28
+ sent_count: number | null;
29
+ }
30
+ export declare function listPosts(http: Http, projectId: number): Promise<PostListRow[]>;
31
+ export declare function getPostBySlug(http: Http, projectId: number, slug: string): Promise<PostRow | null>;
32
+ export declare function postNotFound(slug: string): MicropageError;
33
+ /** publish-post's condition for sending (supabase/functions/publish-post/index.ts). */
34
+ export declare function postWillEmail(post: Pick<PostRow, "email_enabled" | "form_id">): boolean;
35
+ export interface FormNameRow {
36
+ id: string;
37
+ form_name: string | null;
38
+ }
39
+ /**
40
+ * `list: <form name>` -> form_id, as cli/src/commands/posts.js resolveFormId:
41
+ * case-insensitive exact name among the project's newsletter forms.
42
+ */
43
+ export declare function resolveListFormId(http: Http, projectId: number, listName: string): Promise<string>;
44
+ export declare function formNamesById(http: Http, ids: ReadonlyArray<string>): Promise<Map<string, string | null>>;
45
+ /**
46
+ * Active subscribers on a list, with the filter publish-post sends to
47
+ * (form_id, unsubscribed_at is null). The owner can read the table under RLS
48
+ * ("Users can select newsletter_subscribers for own projects").
49
+ */
50
+ export declare function countActiveSubscribers(http: Http, formId: string): Promise<number>;
51
+ export declare function isAbsoluteUrl(s: string): boolean;
52
+ /**
53
+ * The hero as cli/src/posts-assets.js resolveHeroImage resolves it, minus the
54
+ * local-file upload branch: an absolute URL passes through, anything else must
55
+ * be the filename of an asset already uploaded to the project.
56
+ */
57
+ export declare function resolveHeroUrl(http: Http, projectId: number, hero: string | undefined): Promise<string | null>;
58
+ /** Body image refs that are not hosted URLs; they would 404 on the live page. */
59
+ export declare function unhostedBodyImages(markdown: string): string[];
60
+ /**
61
+ * posts has no updated_at, so a preview is bound to a hash of every field a
62
+ * save can change. Fixed field order keeps it stable without key sorting.
63
+ */
64
+ export declare function postContentFingerprint(post: PostRow): string;
65
+ /** Body of upsert-post, field for field what `micropage posts push` sends. */
66
+ export interface UpsertPostPayload {
67
+ project_id: number;
68
+ title: string;
69
+ slug: string;
70
+ body_markdown: string;
71
+ description: string | null;
72
+ web_visibility: "listed" | "unlisted";
73
+ hero_image: string | null;
74
+ form_id: string | null;
75
+ subject: string | null;
76
+ preheader: string | null;
77
+ }
78
+ /**
79
+ * The build a post change queued a site rebuild of: the live build, never a
80
+ * page draft. null when nothing was rebuilt. Absent from servers older than
81
+ * the live-build rebuild, which redeployed projects.active_build_id instead.
82
+ */
83
+ export interface RebuildField {
84
+ rebuild_build_id?: number | null;
85
+ }
86
+ export interface UpsertPostResponse extends RebuildField {
87
+ post_id: string;
88
+ action: "created" | "updated";
89
+ published: boolean;
90
+ }
91
+ export declare function upsertPost(http: Http, payload: UpsertPostPayload): Promise<UpsertPostResponse>;
92
+ export interface PublishPostResponse extends RebuildField {
93
+ post_id: string;
94
+ published_at: string;
95
+ emailed: boolean;
96
+ recipient_count: number;
97
+ }
98
+ export declare function publishPost(http: Http, projectId: number, slug: string): Promise<PublishPostResponse>;
99
+ export interface UnpublishPostResponse extends RebuildField {
100
+ post_id: string;
101
+ unpublished: boolean;
102
+ }
103
+ export declare function unpublishPost(http: Http, projectId: number, slug: string): Promise<UnpublishPostResponse>;
104
+ export interface DeletePostResponse extends RebuildField {
105
+ deleted: boolean;
106
+ slug: string | null;
107
+ }
108
+ export declare function deletePost(http: Http, projectId: number, slug: string): Promise<DeletePostResponse>;