okno 1.0.0-alpha.2 → 1.0.0-alpha.21

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 (58) hide show
  1. package/dist/acorn-CZBJD705.js +3143 -0
  2. package/dist/boot.d.ts +88 -0
  3. package/dist/boot.d.ts.map +1 -0
  4. package/dist/boot.js +98 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +22 -0
  8. package/dist/codegen/generate.d.ts +5 -1
  9. package/dist/codegen/generate.d.ts.map +1 -1
  10. package/dist/codegen/scan-imports.d.ts +9 -0
  11. package/dist/codegen/scan-imports.d.ts.map +1 -0
  12. package/dist/content-encode-DoojdsVU.js +80 -0
  13. package/dist/core/content-encode.d.ts +44 -0
  14. package/dist/core/content-encode.d.ts.map +1 -0
  15. package/dist/core/order.d.ts +18 -0
  16. package/dist/core/order.d.ts.map +1 -0
  17. package/dist/core/parse.d.ts +15 -0
  18. package/dist/core/parse.d.ts.map +1 -0
  19. package/dist/editor/index.js +29645 -15293
  20. package/dist/index-B1PShnsc.js +132 -0
  21. package/dist/index-B2WzdTzI.js +14263 -0
  22. package/dist/index-ButdD9Pf.js +1825 -0
  23. package/dist/index-DKF0siIz.js +5497 -0
  24. package/dist/index-q-7MEoHz.js +47 -0
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/init.d.ts +39 -0
  29. package/dist/init.d.ts.map +1 -0
  30. package/dist/init.js +221 -0
  31. package/dist/mcp.d.ts +4 -0
  32. package/dist/mcp.d.ts.map +1 -0
  33. package/dist/mcp.js +140 -0
  34. package/dist/okno.css +1 -0
  35. package/dist/order-bAkdncZC.js +21 -0
  36. package/dist/plugin-Cy62173B.js +1080 -0
  37. package/dist/runtime/wrap.d.ts +48 -1
  38. package/dist/runtime/wrap.d.ts.map +1 -1
  39. package/dist/runtime/wrap.js +274 -0
  40. package/dist/types/fields.d.ts +54 -6
  41. package/dist/types/fields.d.ts.map +1 -1
  42. package/dist/types/index.d.ts +3 -2
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/dist/types/permissions.d.ts +22 -0
  45. package/dist/types/permissions.d.ts.map +1 -0
  46. package/dist/types/schema.d.ts +41 -6
  47. package/dist/types/schema.d.ts.map +1 -1
  48. package/dist/vite/dev-server.d.ts +8 -0
  49. package/dist/vite/dev-server.d.ts.map +1 -1
  50. package/dist/vite/index.js +1 -1
  51. package/dist/vite/local-engine.d.ts +34 -0
  52. package/dist/vite/local-engine.d.ts.map +1 -0
  53. package/dist/vite/plugin.d.ts.map +1 -1
  54. package/package.json +42 -11
  55. package/skills/connect-okno/SKILL.md +367 -0
  56. package/src/runtime/wrap.test.ts +82 -0
  57. package/src/runtime/wrap.ts +684 -0
  58. package/dist/plugin-Cwwh6E1P.js +0 -440
@@ -0,0 +1,1080 @@
1
+ import { join as y, dirname as M, sep as F, relative as I, extname as Tt, resolve as v } from "node:path";
2
+ import { existsSync as w, readFileSync as j, mkdirSync as W, writeFileSync as x, unlinkSync as V, renameSync as Pt, realpathSync as jt, readdirSync as ot, statSync as Rt, cpSync as xt } from "node:fs";
3
+ import { execSync as nt } from "node:child_process";
4
+ import { readdir as J, readFile as Nt, writeFile as At } from "node:fs/promises";
5
+ import { fileURLToPath as Et } from "node:url";
6
+ import { e as Mt, b as $t, p as st, a as Wt } from "./content-encode-DoojdsVU.js";
7
+ import { o as Ct } from "./order-bAkdncZC.js";
8
+ import { simpleGit as Z } from "simple-git";
9
+ const It = /* @__PURE__ */ new Set([".astro", ".svelte", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]), Ft = /* @__PURE__ */ new Set([
10
+ "node_modules",
11
+ ".astro",
12
+ ".svelte-kit",
13
+ ".next",
14
+ ".nuxt",
15
+ ".vite",
16
+ "dist",
17
+ "build",
18
+ ".git",
19
+ ".turbo"
20
+ ]);
21
+ async function C(n, s) {
22
+ const e = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']okno:${s}["']`, "g"), t = /* @__PURE__ */ new Set();
23
+ async function d(a) {
24
+ let r;
25
+ try {
26
+ r = await J(a, { withFileTypes: !0 });
27
+ } catch {
28
+ return;
29
+ }
30
+ for (const o of r) {
31
+ if (o.name.startsWith(".") && o.name !== "." || Ft.has(o.name)) continue;
32
+ const i = y(a, o.name);
33
+ if (o.isDirectory()) {
34
+ await d(i);
35
+ continue;
36
+ }
37
+ const p = o.name.lastIndexOf(".");
38
+ if (p === -1) continue;
39
+ const f = o.name.slice(p);
40
+ if (!It.has(f)) continue;
41
+ let c;
42
+ try {
43
+ c = await Nt(i, "utf-8");
44
+ } catch {
45
+ continue;
46
+ }
47
+ if (c.includes(`okno:${s}`))
48
+ for (const l of c.matchAll(e)) {
49
+ const u = l[1] ?? "";
50
+ for (const h of u.split(",")) {
51
+ const g = h.trim().split(/\s+as\s+/)[0]?.trim();
52
+ g && /^[A-Za-z_$][\w$]*$/.test(g) && t.add(g);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ return await d(n), t;
58
+ }
59
+ async function ut(n, s) {
60
+ const e = await Gt(n), t = new Map(e.map((f) => [f.name, f.first])), d = Ht(n), a = [
61
+ "// Auto-generated by okno. Do not edit.",
62
+ "",
63
+ "/** A wrapped content value that can be spread onto elements and rendered as text. */",
64
+ "type OknoValue<T = unknown> = {",
65
+ ' readonly "data-okno": string',
66
+ " toString(): string",
67
+ " [Symbol.toPrimitive](hint: string): string",
68
+ " on(callback: (value: T) => void): () => void",
69
+ " /** Re-root reads at a locale; no-op when unset or on the default locale. */",
70
+ " locale(code?: string | null): this",
71
+ "}",
72
+ "",
73
+ "/** Array-membership boundary — ONLY on array items (so it never appears on a",
74
+ " * scalar `{...field}` spread and can't collide with HTML attributes). Spread it",
75
+ ' * onto the item\'s wrapper: `<article {...item.slot}>` → data-okno-item="<list>.<i>"',
76
+ " * (the list + index, distinct from data-okno content identity). `slot` is a",
77
+ " * reserved field key in the editor so a content field can never shadow it. */",
78
+ 'type OknoSlot = { readonly slot: { readonly "data-okno-item": string } }',
79
+ "",
80
+ "/** Recursively wraps content types so values are spreadable/renderable. Media",
81
+ " * (`{src}`) and link (`{url,text}`) objects keep RAW attribute values so",
82
+ " * `<img {...media}>` / `<a {...link}>` type-check against element attributes;",
83
+ " * other objects expose wrapped fields + the data-okno hook. Array items also",
84
+ " * carry `.slot` (the boundary). */",
85
+ "type OknoWrapped<T> =",
86
+ " T extends string | number | boolean",
87
+ " ? OknoValue<T>",
88
+ " : T extends ReadonlyArray<infer U>",
89
+ " ? (OknoWrapped<U> & OknoSlot)[]",
90
+ " : T extends { src: string }",
91
+ " ? T & OknoValue<T>",
92
+ " : T extends { url: string; text: string }",
93
+ " ? { href: string; target?: string; rel?: string } & OknoValue<T>",
94
+ " : T extends Record<string, unknown>",
95
+ " ? { [K in keyof T]: OknoWrapped<T[K]> } & OknoValue<T>",
96
+ " : OknoValue<T>",
97
+ "",
98
+ "/** Content referenced in code but not yet scaffolded — the shape is unknown,",
99
+ " * so every field is a flat leaf. This makes nested access (e.g.",
100
+ " * `home.hero.title`) a type error on purpose: Okno fields are flat. Dividers",
101
+ " * organize the editor; they do NOT nest data. Use a Block for nested shapes. */",
102
+ "type OknoUnscaffolded = OknoWrapped<Record<string, unknown>>",
103
+ "",
104
+ "/** Authorship + timestamp metadata Okno writes on every entry (page,",
105
+ " * collection item, global). Read-only — you never edit or spread these;",
106
+ " * they're the data your own `.sort()` uses. Each is wrapped like any value,",
107
+ " * so render with `{a.updated.date}` and compare with `String(a.updated.date)`. */",
108
+ "type OknoStamp = { readonly date: string; readonly author: string }",
109
+ "type OknoMeta = {",
110
+ " readonly created: OknoWrapped<OknoStamp>",
111
+ " readonly updated: OknoWrapped<OknoStamp>",
112
+ "}",
113
+ ""
114
+ ], r = (f, c, l) => {
115
+ const u = `typeof import("${l}").default`, h = d?.[f]?.[c]?.fields, g = h ? Object.entries(h).filter(
116
+ ([, b]) => b?.type === "reference" && typeof b.collection == "string" && t.has(b.collection)
117
+ ) : [], _ = '"created" | "updated"';
118
+ if (g.length === 0) return `OknoWrapped<Omit<${u}, ${_}>> & OknoMeta`;
119
+ const k = `${g.map(([b]) => `"${b}"`).join(" | ")} | ${_}`, S = g.map(([b, T]) => {
120
+ const $ = `typeof import("./collections/${T.collection}/${t.get(T.collection)}").default`;
121
+ return `${b}: ${T.multiple ? `${$}[]` : $}`;
122
+ }).join("; ");
123
+ return `OknoWrapped<Omit<${u}, ${k}> & { ${S} }> & OknoMeta`;
124
+ }, [o, i, p] = await Promise.all([
125
+ C(s, "pages"),
126
+ C(s, "globals"),
127
+ C(s, "collections")
128
+ ]);
129
+ a.push(
130
+ ...ft("okno:pages", "pages", await q(y(n, "pages")), o, r)
131
+ ), a.push(...Bt(e, p, r)), a.push(
132
+ ...ft("okno:globals", "globals", await q(y(n, "globals")), i, r)
133
+ ), await At(y(n, "modules.d.ts"), a.join(`
134
+ `));
135
+ }
136
+ function ft(n, s, e, t, d) {
137
+ const a = /* @__PURE__ */ new Set(), r = [];
138
+ for (const o of e)
139
+ r.push(` export const ${o}: ${d(s, o, `./${s}/${o}`)}`), a.add(o);
140
+ for (const o of t)
141
+ a.has(o) || r.push(` export const ${o}: OknoUnscaffolded`);
142
+ return [`declare module "${n}" {`, ...r, "}", ""];
143
+ }
144
+ function Bt(n, s, e) {
145
+ const t = /* @__PURE__ */ new Set(), d = [];
146
+ for (const a of n) {
147
+ const r = e("collections", a.name, `./collections/${a.name}/${a.first}`);
148
+ d.push(` export const ${a.name}: (${r})[]`), t.add(a.name);
149
+ }
150
+ for (const a of s)
151
+ t.has(a) || d.push(` export const ${a}: OknoUnscaffolded[]`);
152
+ return ['declare module "okno:collections" {', ...d, "}", ""];
153
+ }
154
+ function Ht(n) {
155
+ const s = y(n, "schema.ts");
156
+ if (!w(s)) return null;
157
+ try {
158
+ let e = j(s, "utf8");
159
+ const t = e.indexOf("export default");
160
+ return t === -1 ? null : (e = e.slice(t + 14).replace(/\bas const\b/g, "").replace(/\bsatisfies\s+[A-Za-z0-9_.]+/g, "").trim(), e.endsWith(";") && (e = e.slice(0, -1).trim()), JSON.parse(e));
161
+ } catch {
162
+ return null;
163
+ }
164
+ }
165
+ async function Gt(n) {
166
+ const s = y(n, "collections");
167
+ if (!w(s)) return [];
168
+ const e = (await J(s, { withFileTypes: !0 })).filter((d) => d.isDirectory()), t = [];
169
+ for (const d of e) {
170
+ const a = await q(y(s, d.name));
171
+ a.length > 0 && t.push({ name: d.name, first: a[0] });
172
+ }
173
+ return t;
174
+ }
175
+ async function q(n) {
176
+ return w(n) ? (await J(n)).filter((e) => e.endsWith(".ts") && e !== "index.ts" && e !== "modules.d.ts").map((e) => e.replace(".ts", "")) : [];
177
+ }
178
+ const bt = ["pages", "collections", "globals"], St = /* @__PURE__ */ new Map();
179
+ function L(n) {
180
+ St.set(n, Date.now());
181
+ }
182
+ function dt(n) {
183
+ const s = St.get(n);
184
+ return s !== void 0 && Date.now() - s < 3e3;
185
+ }
186
+ function z(n, s) {
187
+ if (!s || s.includes("..") || s.includes("\0") || s.startsWith("/") || !s.endsWith(".ts")) return null;
188
+ const e = y(n, s);
189
+ return e !== n && !e.startsWith(n + F) ? null : e;
190
+ }
191
+ function Jt(n) {
192
+ const s = {}, e = (t) => {
193
+ if (w(t))
194
+ for (const d of ot(t, { withFileTypes: !0 })) {
195
+ const a = y(t, d.name);
196
+ if (d.isDirectory()) e(a);
197
+ else if (d.name.endsWith(".ts") && d.name !== "index.ts") {
198
+ const r = I(n, a).split(F).join("/");
199
+ s[r] = j(a, "utf-8");
200
+ }
201
+ }
202
+ };
203
+ for (const t of bt) e(y(n, t));
204
+ return s;
205
+ }
206
+ function kt(n) {
207
+ const s = y(n, "schema.ts"), e = y(n, "users.json");
208
+ return {
209
+ schema: w(s) ? j(s, "utf-8") : null,
210
+ users: w(e) ? j(e, "utf-8") : null,
211
+ content: Jt(n),
212
+ // File listing for the demo Files browser. The media itself is served
213
+ // separately: dev = the /okno/files/* middleware; prod = the okno() plugin
214
+ // copies okno/files/ into public/okno/files/ at build.
215
+ files: Ot(n)
216
+ };
217
+ }
218
+ function U(n, s) {
219
+ if (!s || s.includes("..") || s.includes("\0") || s.startsWith("/")) return null;
220
+ const e = y(n, s);
221
+ return e !== n && !e.startsWith(n + F) ? null : e;
222
+ }
223
+ const pt = (n) => n.replace(/[^a-zA-Z0-9._-]/g, "-"), mt = (n) => n.split("/").map((s) => s.replace(/[^a-zA-Z0-9._-]/g, "-")).filter((s) => s && s !== "-" && s !== "..").join("/");
224
+ function Ot(n) {
225
+ const s = y(n, "files"), e = [], t = (d) => {
226
+ if (w(d))
227
+ for (const a of ot(d, { withFileTypes: !0 })) {
228
+ const r = y(d, a.name);
229
+ if (a.isDirectory()) t(r);
230
+ else if (a.name !== ".okno-tree.json") {
231
+ const o = I(s, r).split(F).join("/");
232
+ e.push({ path: `files/${o}`, filename: a.name, size: Rt(r).size });
233
+ }
234
+ }
235
+ };
236
+ return t(s), e;
237
+ }
238
+ function zt(n) {
239
+ return new Promise((s, e) => {
240
+ const t = [];
241
+ n.on("data", (d) => t.push(d)), n.on("end", () => s(Buffer.concat(t))), n.on("error", e);
242
+ });
243
+ }
244
+ let Q;
245
+ function tt(n) {
246
+ return Q || (Q = nt("git rev-parse --show-toplevel", { cwd: n, encoding: "utf-8" }).trim()), Q;
247
+ }
248
+ function ht(n) {
249
+ return I(tt(n), jt(n)).split(F).join("/");
250
+ }
251
+ let K;
252
+ function Ut(n) {
253
+ if (K !== void 0) return K;
254
+ try {
255
+ K = nt("git config user.name", { cwd: n, encoding: "utf-8" }).trim() || "local";
256
+ } catch {
257
+ K = "local";
258
+ }
259
+ return K;
260
+ }
261
+ function O(n) {
262
+ return new Promise((s) => {
263
+ let e = "";
264
+ n.on("data", (t) => e += t), n.on("end", () => {
265
+ try {
266
+ s(e ? JSON.parse(e) : {});
267
+ } catch {
268
+ s({});
269
+ }
270
+ }), n.on("error", () => s({}));
271
+ });
272
+ }
273
+ function m(n, s, e) {
274
+ n.statusCode = s, n.setHeader("Content-Type", "application/json"), n.setHeader("Cache-Control", "no-store"), n.end(JSON.stringify(e));
275
+ }
276
+ function G(n, s, e) {
277
+ const t = s.split("/")[0];
278
+ if (t !== "pages" && t !== "collections" && t !== "globals") return;
279
+ const d = n.moduleGraph.getModuleById("\0okno:" + t);
280
+ d && n.moduleGraph.invalidateModule(d), n.moduleGraph.getModulesByFile(e)?.forEach((a) => n.moduleGraph.invalidateModule(a));
281
+ }
282
+ const Lt = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/, Vt = (n) => n.charAt(0).toUpperCase() + n.slice(1);
283
+ function N(n) {
284
+ const s = y(n, "schema.ts");
285
+ let e = `import type { Schema } from "okno"
286
+
287
+ `, t = {};
288
+ if (w(s)) {
289
+ const d = j(s, "utf-8"), a = d.indexOf("export default");
290
+ a > 0 && (e = d.slice(0, a));
291
+ try {
292
+ t = st(d) ?? {};
293
+ } catch {
294
+ t = {};
295
+ }
296
+ }
297
+ return { schema: t, header: e };
298
+ }
299
+ function A(n, s, e, t) {
300
+ x(y(s, "schema.ts"), Wt(e, t));
301
+ for (const d of bt) {
302
+ const a = n.moduleGraph.getModuleById("\0okno:" + d);
303
+ a && n.moduleGraph.invalidateModule(a);
304
+ }
305
+ }
306
+ function Kt(n) {
307
+ switch (n) {
308
+ case "number":
309
+ return 0;
310
+ case "boolean":
311
+ return !1;
312
+ case "media":
313
+ return null;
314
+ default:
315
+ return "";
316
+ }
317
+ }
318
+ function Xt(n) {
319
+ const s = {};
320
+ for (const e of n) {
321
+ const t = e.path.split(".");
322
+ let d = s;
323
+ for (let r = 0; r < t.length - 1; r++) {
324
+ const o = t[r];
325
+ (!d[o] || d[o].type !== "group") && (d[o] = { type: "group", fields: {} }), d = d[o].fields;
326
+ }
327
+ const a = t[t.length - 1];
328
+ if (!d[a]) {
329
+ const r = {};
330
+ for (const [o, i] of Object.entries(e)) o !== "path" && o !== "value" && (r[o] = i);
331
+ d[a] = { ...r, type: e.type };
332
+ }
333
+ }
334
+ return s;
335
+ }
336
+ function Zt(n) {
337
+ const s = {};
338
+ for (const e of n) {
339
+ const t = e.path.split(".");
340
+ let d = s;
341
+ for (let r = 0; r < t.length - 1; r++) {
342
+ const o = t[r];
343
+ (!d[o] || typeof d[o] != "object") && (d[o] = {}), d = d[o];
344
+ }
345
+ const a = t[t.length - 1];
346
+ d[a] = e.value !== void 0 && e.value !== null ? e.value : Kt(e.type);
347
+ }
348
+ return s;
349
+ }
350
+ function gt(n, s, e) {
351
+ const t = {};
352
+ let d = !1;
353
+ for (const [a, r] of Object.entries(n)) {
354
+ if (e.has(a)) {
355
+ d = !0;
356
+ continue;
357
+ }
358
+ const o = a in s && !(s[a] in n) ? s[a] : a;
359
+ o !== a && (d = !0), t[o] = r;
360
+ }
361
+ return { out: t, changed: d };
362
+ }
363
+ function Yt(n, s, e, t, d, a) {
364
+ const r = y(s, e), o = new Set(a);
365
+ if (!w(r) || Object.keys(d).length === 0 && o.size === 0) return;
366
+ const i = [], p = (f) => {
367
+ for (const c of ot(f, { withFileTypes: !0 })) {
368
+ const l = y(f, c.name);
369
+ c.isDirectory() ? p(l) : c.name === `${t}.ts` && i.push(l);
370
+ }
371
+ };
372
+ p(r);
373
+ for (const f of i) {
374
+ let c;
375
+ try {
376
+ c = st(j(f, "utf-8"));
377
+ } catch {
378
+ continue;
379
+ }
380
+ let l, u = !1;
381
+ if (Array.isArray(c))
382
+ l = c.map((g) => {
383
+ if (g && typeof g == "object" && !Array.isArray(g)) {
384
+ const _ = gt(g, d, o);
385
+ return _.changed && (u = !0), _.out;
386
+ }
387
+ return g;
388
+ });
389
+ else if (c && typeof c == "object") {
390
+ const g = gt(c, d, o);
391
+ l = g.out, u = g.changed;
392
+ } else
393
+ continue;
394
+ if (!u) continue;
395
+ L(f), x(f, $t(l));
396
+ const h = I(s, f).split(F).join("/");
397
+ G(n, h, f), console.log(`[okno] field-change migrated content: ${h}`, { renames: d, deletes: a });
398
+ }
399
+ }
400
+ function Qt(n, s) {
401
+ n.middlewares.use(async (e, t, d) => {
402
+ if (!e.url?.startsWith("/__okno/api/")) return d();
403
+ const a = e.url.slice(12).split("?")[0];
404
+ try {
405
+ if (e.method === "GET" && a === "content")
406
+ return m(t, 200, kt(s));
407
+ if (e.method === "POST" && a === "content/save") {
408
+ const r = await O(e), { path: o, content: i, created: p, author: f } = r;
409
+ if (!o || !i) return m(t, 400, { error: "Missing path or content" });
410
+ const c = z(s, o);
411
+ if (!c) return m(t, 400, { error: "Invalid path" });
412
+ const l = Mt(i, {
413
+ now: (/* @__PURE__ */ new Date()).toISOString(),
414
+ author: f || Ut(s),
415
+ created: p
416
+ });
417
+ return W(M(c), { recursive: !0 }), L(c), x(c, l), G(n, o, c), m(t, 200, { ok: !0, commit: { fileSha: "" } });
418
+ }
419
+ if (e.method === "POST" && a === "content/delete") {
420
+ const o = (await O(e))?.path;
421
+ if (!o) return m(t, 400, { error: "Missing path" });
422
+ const i = z(s, o);
423
+ return i ? (w(i) && (V(i), G(n, o, i)), m(t, 200, { ok: !0 })) : m(t, 400, { error: "Invalid path" });
424
+ }
425
+ if (e.method === "GET" && a === "publish-state")
426
+ try {
427
+ const o = await Z(tt(s)).status(), i = ht(s), p = o.files.some((f) => f.path.startsWith(i + "/"));
428
+ return m(t, 200, { pendingPublish: p || o.ahead > 0 });
429
+ } catch {
430
+ return m(t, 200, { pendingPublish: !1 });
431
+ }
432
+ if (e.method === "POST" && a === "publish") {
433
+ const r = Z(tt(s)), o = ht(s);
434
+ await r.raw(["add", "-A", "--", o]);
435
+ const i = await r.status(), p = i.staged.length > 0;
436
+ let f = !1;
437
+ p && (await r.commit("okno: publish content"), f = !0);
438
+ let c = !1, l = null;
439
+ try {
440
+ (f || i.ahead > 0) && (await r.push(), c = !0);
441
+ } catch (u) {
442
+ l = u instanceof Error ? u.message.split(`
443
+ `)[0] : String(u);
444
+ }
445
+ return m(t, 200, {
446
+ ok: !0,
447
+ alreadyUpToDate: !f && i.ahead === 0,
448
+ committed: f,
449
+ pushed: c,
450
+ pushError: l
451
+ });
452
+ }
453
+ if (e.method === "POST" && a === "schema/save-fields") {
454
+ const r = await O(e), { kind: o, name: i, fields: p, renames: f, deletes: c } = r;
455
+ if (!o || !i || !p) return m(t, 400, { error: "Missing kind, name or fields" });
456
+ const { schema: l, header: u } = N(s), h = l[o] ??= {};
457
+ if (!h[i]) return m(t, 404, { error: `${o}/${i} does not exist in schema` });
458
+ h[i].fields = p, A(n, s, l, u);
459
+ const g = f && typeof f == "object" ? f : {}, _ = Array.isArray(c) ? c : [];
460
+ return (Object.keys(g).length > 0 || _.length > 0) && Yt(n, s, o, i, g, _), m(t, 200, { ok: !0, commit: { fileSha: "" }, schema: l });
461
+ }
462
+ if (e.method === "POST" && a === "schema/set-locales") {
463
+ const o = (await O(e))?.locales, { schema: i, header: p } = N(s);
464
+ return o && Array.isArray(o.supported) && o.supported.length > 0 ? i.locales = o : delete i.locales, A(n, s, i, p), m(t, 200, { ok: !0, commit: { fileSha: "" } });
465
+ }
466
+ if (e.method === "POST" && a === "schema/set-name") {
467
+ const r = await O(e), { kind: o, slug: i, name: p } = r;
468
+ if (!o || !i || !p) return m(t, 400, { error: "Missing kind, slug or name" });
469
+ const { schema: f, header: c } = N(s), l = f[o] ??= {}, u = l[i];
470
+ if (!u) return m(t, 404, { error: `${o}/${i} does not exist in schema` });
471
+ const h = { ...u, name: p };
472
+ return delete h.label, l[i] = h, A(n, s, f, c), m(t, 200, { ok: !0, commit: { fileSha: "" } });
473
+ }
474
+ if (e.method === "POST" && a === "schema/set-url") {
475
+ const r = await O(e), { kind: o, slug: i, url: p } = r;
476
+ if (!o || !i) return m(t, 400, { error: "Missing kind or slug" });
477
+ const { schema: f, header: c } = N(s), l = f[o] ??= {}, u = l[i];
478
+ if (!u) return m(t, 404, { error: `${o}/${i} does not exist in schema` });
479
+ const h = { ...u };
480
+ return typeof p == "string" && p.trim() ? h.url = p.trim() : delete h.url, l[i] = h, A(n, s, f, c), m(t, 200, { ok: !0, commit: { fileSha: "" } });
481
+ }
482
+ if (e.method === "POST" && a === "schema/rename-slug") {
483
+ const r = await O(e), { kind: o, from: i, to: p } = r;
484
+ if (!o || !i || !p) return m(t, 400, { error: "Missing kind, from or to" });
485
+ if (!Lt.test(p)) return m(t, 400, { error: "Invalid target slug" });
486
+ if (i === p) return m(t, 200, { ok: !0, unchanged: !0 });
487
+ const { schema: f, header: c } = N(s), l = f[o] ??= {};
488
+ if (!l[i]) return m(t, 404, { error: `${o}/${i} does not exist in schema` });
489
+ if (l[p]) return m(t, 409, { error: `${o}/${p} already exists` });
490
+ const u = {};
491
+ for (const S of Object.keys(l)) u[S === i ? p : S] = l[S];
492
+ f[o] = u, A(n, s, f, c);
493
+ const h = `${o}/${i}.ts`, g = `${o}/${p}.ts`, _ = z(s, h), k = z(s, g);
494
+ return _ && k && w(_) && (W(M(k), { recursive: !0 }), L(_), L(k), x(k, j(_)), V(_), G(n, h, _), G(n, g, k)), m(t, 200, { ok: !0, commit: { fileSha: "" }, schema: f, from: i, to: p, kind: o });
495
+ }
496
+ if (e.method === "POST" && a === "schema/reorder") {
497
+ const r = await O(e), { kind: o, order: i } = r;
498
+ if (!o || !Array.isArray(i)) return m(t, 400, { error: "Missing kind or order" });
499
+ const { schema: p, header: f } = N(s), c = p[o];
500
+ if (!c) return m(t, 404, { error: `${o} not in schema` });
501
+ const l = {};
502
+ for (const u of i) c[u] && (l[u] = c[u]);
503
+ for (const u of Object.keys(c)) u in l || (l[u] = c[u]);
504
+ return p[o] = l, A(n, s, p, f), m(t, 200, { ok: !0, commit: { fileSha: "" }, schema: p });
505
+ }
506
+ if (e.method === "POST" && a === "collections/set-order") {
507
+ const r = await O(e), { name: o, order: i } = r;
508
+ if (!o || !Array.isArray(i)) return m(t, 400, { error: "Missing name or order" });
509
+ const { schema: p, header: f } = N(s), l = (p.collections ??= {})[o];
510
+ return l ? (l.order = i.filter((u) => typeof u == "string"), A(n, s, p, f), m(t, 200, { ok: !0, commit: { fileSha: "" }, schema: p })) : m(t, 404, { error: `collections/${o} not in schema` });
511
+ }
512
+ if (e.method === "POST" && a === "collections/set-drafts") {
513
+ const r = await O(e), { name: o, drafts: i } = r;
514
+ if (!o || typeof i != "boolean") return m(t, 400, { error: "Missing name or drafts" });
515
+ const { schema: p, header: f } = N(s), l = (p.collections ??= {})[o];
516
+ return l ? (i ? l.drafts = !0 : delete l.drafts, A(n, s, p, f), m(t, 200, { ok: !0, commit: { fileSha: "" }, schema: p })) : m(t, 404, { error: `collections/${o} not in schema` });
517
+ }
518
+ if (e.method === "POST" && a === "schema/delete-entry") {
519
+ const r = await O(e), { kind: o, name: i } = r;
520
+ if (!o || !i) return m(t, 400, { error: "Missing kind or name" });
521
+ const { schema: p, header: f } = N(s), c = p[o];
522
+ if (!c || !c[i]) return m(t, 404, { error: `${o}/${i} does not exist in schema` });
523
+ delete c[i], A(n, s, p, f);
524
+ const l = `${o}/${i}.ts`, u = z(s, l);
525
+ return u && w(u) && (L(u), V(u), G(n, l, u)), m(t, 200, { ok: !0, commit: { fileSha: "" }, schema: p });
526
+ }
527
+ if (e.method === "POST" && a === "setup/scaffold-page") {
528
+ const r = await O(e), { name: o, kind: i, fields: p, label: f } = r;
529
+ if (!o || !i) return m(t, 400, { error: "Missing name or kind" });
530
+ const c = p ?? [], { schema: l, header: u } = N(s);
531
+ if (l[i] || (l[i] = {}), l[i][o] = { name: f?.trim() || Vt(o), fields: Xt(c) }, A(n, s, l, u), i !== "blocks") {
532
+ const h = `${i}/${o}.ts`, g = z(s, h);
533
+ if (g) {
534
+ const _ = i === "collections" ? `export default []
535
+ ` : $t(Zt(c));
536
+ W(M(g), { recursive: !0 }), L(g), x(g, _), G(n, h, g);
537
+ }
538
+ }
539
+ return m(t, 200, { ok: !0 });
540
+ }
541
+ if (e.method === "GET" && a === "files") {
542
+ const r = y(s, "files", ".okno-tree.json");
543
+ return m(t, 200, {
544
+ files: Ot(s),
545
+ manifest: w(r) ? j(r, "utf-8") : null
546
+ });
547
+ }
548
+ if (e.method === "POST" && a === "files/blob") {
549
+ const r = pt(decodeURIComponent(e.headers["x-okno-filename"] || "")), o = e.headers["x-okno-dir"] ? decodeURIComponent(e.headers["x-okno-dir"]) : "";
550
+ if (!r || r === "-") return m(t, 400, { error: "Invalid filename" });
551
+ const i = mt(o), p = i ? `${i}/${r}` : r, f = U(s, `files/${p}`);
552
+ if (!f) return m(t, 400, { error: "Invalid path" });
553
+ const c = await zt(e);
554
+ return c.length === 0 ? m(t, 400, { error: "Empty body" }) : (W(M(f), { recursive: !0 }), x(f, c), m(t, 200, { ok: !0, blobSha: "", path: `files/${p}`, filename: r }));
555
+ }
556
+ if (e.method === "POST" && a === "files/commit")
557
+ return m(t, 200, { ok: !0 });
558
+ if (e.method === "POST" && a === "files/upload") {
559
+ const r = await O(e), { filename: o, content: i, dir: p } = r;
560
+ if (!o || i == null) return m(t, 400, { error: "Missing filename or content" });
561
+ const f = pt(o);
562
+ if (!f || f === "-") return m(t, 400, { error: "Invalid filename" });
563
+ const c = mt(p ?? ""), l = c ? `${c}/${f}` : f, u = U(s, `files/${l}`);
564
+ return u ? (W(M(u), { recursive: !0 }), x(u, Buffer.from(i, "base64")), m(t, 200, { ok: !0, path: `files/${l}`, filename: f, commit: { fileSha: "" } })) : m(t, 400, { error: "Invalid path" });
565
+ }
566
+ if (e.method === "POST" && a === "files/delete") {
567
+ const o = (await O(e))?.path;
568
+ if (!o) return m(t, 400, { error: "Missing path" });
569
+ const i = U(s, o);
570
+ return i ? (w(i) && V(i), m(t, 200, { ok: !0 })) : m(t, 400, { error: "Invalid path" });
571
+ }
572
+ if (e.method === "POST" && a === "files/delete-many") {
573
+ const o = (await O(e))?.paths;
574
+ if (!Array.isArray(o)) return m(t, 400, { error: "Missing paths" });
575
+ for (const i of o) {
576
+ const p = U(s, String(i));
577
+ p && w(p) && V(p);
578
+ }
579
+ return m(t, 200, { ok: !0 });
580
+ }
581
+ if (e.method === "POST" && a === "files/rename") {
582
+ const r = await O(e), { from: o, to: i } = r;
583
+ if (!o || !i) return m(t, 400, { error: "Missing from or to" });
584
+ const p = U(s, o), f = U(s, i);
585
+ return !p || !f ? m(t, 400, { error: "Invalid path" }) : w(p) ? (W(M(f), { recursive: !0 }), Pt(p, f), m(t, 200, { ok: !0, commit: { fileSha: "" } })) : m(t, 404, { error: "Source not found" });
586
+ }
587
+ if (e.method === "POST" && a === "users/save") {
588
+ const o = (await O(e))?.users;
589
+ return Array.isArray(o) ? (x(y(s, "users.json"), JSON.stringify(o, null, " ") + `
590
+ `), m(t, 200, { ok: !0, commit: { fileSha: "" } })) : m(t, 400, { error: "Missing users" });
591
+ }
592
+ return d();
593
+ } catch (r) {
594
+ m(t, 500, { error: r instanceof Error ? r.message : String(r) });
595
+ }
596
+ });
597
+ }
598
+ function Dt(n, s) {
599
+ let e;
600
+ try {
601
+ e = decodeURIComponent(s);
602
+ } catch {
603
+ return null;
604
+ }
605
+ if (!e || e.includes("\0")) return null;
606
+ const t = v(n, "files"), d = v(t, e);
607
+ return d === t || !d.startsWith(t + F) ? null : d;
608
+ }
609
+ const D = "okno", qt = {
610
+ ".webp": "image/webp",
611
+ ".png": "image/png",
612
+ ".jpg": "image/jpeg",
613
+ ".jpeg": "image/jpeg",
614
+ ".gif": "image/gif",
615
+ ".svg": "image/svg+xml",
616
+ ".avif": "image/avif",
617
+ ".ico": "image/x-icon",
618
+ ".mp4": "video/mp4",
619
+ ".webm": "video/webm",
620
+ ".ogg": "video/ogg",
621
+ ".mp3": "audio/mpeg",
622
+ ".wav": "audio/wav",
623
+ ".flac": "audio/flac",
624
+ ".pdf": "application/pdf",
625
+ ".woff2": "font/woff2",
626
+ ".woff": "font/woff",
627
+ ".ttf": "font/ttf",
628
+ ".otf": "font/otf"
629
+ };
630
+ function te(n, s) {
631
+ Qt(n, s), n.middlewares.use((e, t, d) => {
632
+ if (e.method !== "GET" || !e.url?.startsWith("/okno/files/")) return d();
633
+ const a = e.url.slice(12).split("?")[0];
634
+ if (!a) return d();
635
+ const r = Dt(s, a);
636
+ if (!r)
637
+ return t.statusCode = 403, t.end("Forbidden");
638
+ if (!w(r))
639
+ return t.statusCode = 404, t.end("Not found");
640
+ const o = Tt(r).toLowerCase();
641
+ t.setHeader("Content-Type", qt[o] || "application/octet-stream"), t.setHeader("Cache-Control", "public, max-age=3600"), t.end(j(r));
642
+ }), n.middlewares.use(async (e, t, d) => {
643
+ if (!e.url?.startsWith("/__okno/")) return d();
644
+ const a = e.url.slice(8);
645
+ t.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate"), t.setHeader("Pragma", "no-cache"), t.setHeader("Expires", "0");
646
+ try {
647
+ if (e.method === "GET" && a === "repo") {
648
+ t.setHeader("Content-Type", "application/json");
649
+ try {
650
+ const r = Z(n.config.root), o = (await r.remote(["get-url", "origin"]))?.toString().trim(), i = (await r.revparse(["--abbrev-ref", "HEAD"])).trim(), { owner: p, repo: f } = ee(o);
651
+ return t.end(
652
+ JSON.stringify({ ok: !0, owner: p, repo: f, branch: i || null, remote: o || null })
653
+ );
654
+ } catch (r) {
655
+ return t.end(JSON.stringify({ ok: !1, error: String(r) }));
656
+ }
657
+ }
658
+ if (e.method === "POST" && a.startsWith("mirror")) {
659
+ const o = new URL(e.url, "http://localhost").searchParams.get("path");
660
+ if (!o || o.includes("..") || !o.startsWith("files/"))
661
+ return t.statusCode = 400, t.setHeader("Content-Type", "application/json"), t.end(JSON.stringify({ error: "Invalid path" }));
662
+ const i = y(s, o);
663
+ if (w(i))
664
+ return t.setHeader("Content-Type", "application/json"), t.end(JSON.stringify({ ok: !0, skipped: !0 }));
665
+ const p = await oe(e);
666
+ return W(M(i), { recursive: !0 }), x(i, p), t.setHeader("Content-Type", "application/json"), t.end(JSON.stringify({ ok: !0, written: o, bytes: p.length }));
667
+ }
668
+ if (e.method === "POST" && a === "sync") {
669
+ const o = (await ne(e))?.path;
670
+ if (o) {
671
+ if (o.includes("..") || o.includes("\0"))
672
+ return t.statusCode = 400, t.setHeader("Content-Type", "application/json"), t.end(JSON.stringify({ error: "Invalid path" }));
673
+ const c = y(s, o);
674
+ try {
675
+ const l = Z(s);
676
+ await l.fetch("origin", D);
677
+ const u = (await l.revparse(["--show-toplevel"])).trim(), h = I(u, c).split(F).join("/"), g = await l.show([`origin/${D}:${h}`]);
678
+ W(M(c), { recursive: !0 }), x(c, g);
679
+ } catch (l) {
680
+ const u = l instanceof Error ? l.message : String(l);
681
+ console.warn(
682
+ `[okno] sync: could not materialize ${o} from origin/${D} — ${u.split(`
683
+ `)[0]}`
684
+ );
685
+ }
686
+ return yt(n, o, c), t.setHeader("Content-Type", "application/json"), t.end(JSON.stringify({ ok: !0, invalidated: o }));
687
+ }
688
+ const i = Z(s), p = await i.revparse(["--show-toplevel"]), f = I(p.trim(), s);
689
+ try {
690
+ const c = await i.pull();
691
+ for (const l of c.files)
692
+ if (l.startsWith(`${f}/`)) {
693
+ const u = l.slice(`${f}/`.length), h = y(s, u);
694
+ yt(n, u, h);
695
+ }
696
+ return t.setHeader("Content-Type", "application/json"), t.end(JSON.stringify({ ok: !0, files: c.files }));
697
+ } catch (c) {
698
+ const l = c instanceof Error ? c.message : String(c);
699
+ return console.warn(`[okno] sync: git pull skipped — ${l.split(`
700
+ `)[0]}`), t.setHeader("Content-Type", "application/json"), t.end(JSON.stringify({ ok: !0, pullSkipped: !0, reason: l }));
701
+ }
702
+ }
703
+ d();
704
+ } catch (r) {
705
+ t.statusCode = 500, t.end(JSON.stringify({ error: String(r) }));
706
+ }
707
+ });
708
+ }
709
+ function ee(n) {
710
+ if (!n) return { owner: null, repo: null };
711
+ const s = n.match(/github\.com[:/]([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
712
+ return s ? { owner: s[1], repo: s[2] } : { owner: null, repo: null };
713
+ }
714
+ function oe(n) {
715
+ return new Promise((s, e) => {
716
+ const t = [];
717
+ n.on("data", (d) => t.push(d)), n.on("end", () => s(Buffer.concat(t))), n.on("error", e);
718
+ });
719
+ }
720
+ function ne(n) {
721
+ return new Promise((s) => {
722
+ let e = "";
723
+ n.on("data", (t) => {
724
+ e += t;
725
+ }), n.on("end", () => {
726
+ try {
727
+ s(e ? JSON.parse(e) : null);
728
+ } catch {
729
+ s(null);
730
+ }
731
+ }), n.on("error", () => s(null));
732
+ });
733
+ }
734
+ function yt(n, s, e) {
735
+ const t = "\0okno:";
736
+ let d;
737
+ if (s.startsWith("pages/") ? d = t + "pages" : s.startsWith("collections/") ? d = t + "collections" : s.startsWith("globals/") && (d = t + "globals"), d) {
738
+ const a = n.moduleGraph.getModuleById(d);
739
+ a && n.moduleGraph.invalidateModule(a);
740
+ const r = n.moduleGraph.getModulesByFile(e);
741
+ r && r.forEach((o) => {
742
+ n.moduleGraph.invalidateModule(o);
743
+ });
744
+ }
745
+ }
746
+ const se = "okno:", X = "\0okno:", rt = M(Et(import.meta.url)), re = JSON.parse(j(v(rt, "../package.json"), "utf-8")).version, _t = v(rt, "./runtime/wrap.js"), wt = w(_t) ? j(_t, "utf-8") : null, R = v(rt, "../editor"), et = v(R, "index.ts"), ie = w(et), ae = {
747
+ "@modules": v(R, "modules"),
748
+ "@lib": v(R, "lib"),
749
+ "@logger": v(R, "lib/logger.svelte.ts"),
750
+ "@utils": v(R, "lib/utils.ts"),
751
+ "@/types": v(R, "lib/types.ts"),
752
+ "@styles": v(R, "styles"),
753
+ "@components": v(R, "components"),
754
+ "@assets": v(R, "assets"),
755
+ "@pages": v(R, "pages"),
756
+ "@controllers": v(R, "controllers")
757
+ };
758
+ function ce() {
759
+ try {
760
+ const n = (d) => nt(d, { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }).trim(), e = n("git remote get-url origin").match(/github\.com[:/]([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
761
+ if (!e) return null;
762
+ const t = n("git rev-parse --abbrev-ref HEAD") || "main";
763
+ return `${e[1]}/${e[2]}@${t}`;
764
+ } catch {
765
+ return null;
766
+ }
767
+ }
768
+ function be(n = {}) {
769
+ const s = n.dir ?? "okno";
770
+ let e, t, d = !1, a = !1;
771
+ return n.isEditor, {
772
+ name: "okno",
773
+ enforce: "pre",
774
+ config(r, o) {
775
+ const i = o.command === "serve";
776
+ return a = o.command === "build", d = i && ie, {
777
+ define: {
778
+ __OKNO_API_URL__: JSON.stringify(n.apiUrl ?? "https://api.okno.build"),
779
+ __OKNO_VERSION__: JSON.stringify(re),
780
+ // True when the consumer is running `vite dev` / `astro dev` /
781
+ // `sveltekit dev` — anything that serves locally. Replaced at
782
+ // consumer build time so the prebuilt editor bundle can honor
783
+ // the consumer's actual environment.
784
+ __OKNO_IS_DEV__: JSON.stringify(i),
785
+ // Public demo build: editor boots login-less, reads a static
786
+ // `okno-demo.json` snapshot, no-ops writes. See docs/demo-mode.md.
787
+ __OKNO_DEMO__: JSON.stringify(n.demo ?? !1),
788
+ // Repo identity (`owner/repo@branch`) baked from the app's git
789
+ // origin at the consumer's build time, so the deployed editor
790
+ // auto-targets its repo with no picker. null outside a git
791
+ // checkout → editor falls back to the picker. Dev ignores it
792
+ // (runtime /__okno/repo derivation is more current).
793
+ __OKNO_REPO__: JSON.stringify(ce())
794
+ },
795
+ // Source mode (monorepo dev only): expose the editor's internal
796
+ // @-aliases to the consumer's Vite and skip prebundling so saves
797
+ // to `package/editor/**` propagate via HMR instead of needing
798
+ // `bun run build:pkg`.
799
+ ...d && {
800
+ resolve: { alias: ae },
801
+ optimizeDeps: { exclude: ["okno", "okno/editor"] }
802
+ },
803
+ server: {
804
+ watch: {
805
+ // Only ignore binary assets and editor-only metadata. Page/
806
+ // collection/global .ts files SHOULD trigger Vite HMR — that's
807
+ // how users see updates when they `git pull` content from the
808
+ // drafts branch into their working tree. (Previously this list
809
+ // also blocked pages/collections/globals because in DEV_MODE
810
+ // the backend mirrored saves to disk, causing spurious full
811
+ // reloads. In production-mode the backend never touches local
812
+ // FS so blocking those is pure harm — pulls go unseen.)
813
+ ignored: [`**/${s}/files/**`, `**/${s}/.okno-tree.json`]
814
+ },
815
+ // Source mode: the editor loads via a dynamic `import("okno/editor")`
816
+ // from a separate package over `@fs`, so Vite's startup dep scan
817
+ // never crawls it — its transitive deps (bits-ui, tiptap, runed…)
818
+ // are discovered lazily on first import, triggering a mid-session
819
+ // re-optimize that 404s the now-stale prebundled chunks. Warming the
820
+ // editor entry forces that crawl at startup, so those deps land in
821
+ // the first optimize pass and never re-bundle under the user.
822
+ ...d && {
823
+ warmup: { clientFiles: [et] }
824
+ }
825
+ }
826
+ };
827
+ },
828
+ configResolved(r) {
829
+ e = r.root, t = v(e, s);
830
+ },
831
+ async buildStart() {
832
+ if (w(t) && (await ut(t, e), n.demo)) {
833
+ const r = y(e, "public");
834
+ w(r) || W(r, { recursive: !0 }), x(
835
+ y(r, "okno-demo.json"),
836
+ JSON.stringify(kt(t))
837
+ );
838
+ const o = y(t, "files");
839
+ w(o) && xt(o, y(r, "okno", "files"), {
840
+ recursive: !0,
841
+ filter: (i) => !i.endsWith(".okno-tree.json")
842
+ });
843
+ }
844
+ },
845
+ configureServer(r) {
846
+ te(r, t);
847
+ const o = (p) => {
848
+ const f = I(t, p);
849
+ if (f.startsWith("..") || !f.endsWith(".ts")) return;
850
+ const c = f.split(/[\\/]/)[0];
851
+ if (c !== "pages" && c !== "collections" && c !== "globals") return;
852
+ const l = r.moduleGraph.getModuleById(X + c);
853
+ l && r.moduleGraph.invalidateModule(l), r.moduleGraph.getModulesByFile(p)?.forEach((u) => r.moduleGraph.invalidateModule(u)), !dt(p) && r.ws.send({ type: "full-reload" });
854
+ };
855
+ r.watcher.on("add", o), r.watcher.on("unlink", o), r.middlewares.use("/__okno/imports", async (p, f, c) => {
856
+ if (p.method !== "GET") return c();
857
+ try {
858
+ const [l, u, h] = await Promise.all([
859
+ C(e, "pages"),
860
+ C(e, "globals"),
861
+ C(e, "collections")
862
+ ]);
863
+ f.setHeader("Content-Type", "application/json"), f.setHeader("Cache-Control", "no-store"), f.end(JSON.stringify({
864
+ pages: Array.from(l),
865
+ globals: Array.from(u),
866
+ collections: Array.from(h)
867
+ }));
868
+ } catch (l) {
869
+ c(l);
870
+ }
871
+ });
872
+ const i = "/__okno_bootstrap.js";
873
+ r.middlewares.use(i, async (p, f, c) => {
874
+ try {
875
+ const l = await r.transformRequest("\0okno:bootstrap");
876
+ if (!l) {
877
+ f.statusCode = 500, f.end("okno bootstrap transform failed");
878
+ return;
879
+ }
880
+ f.setHeader("content-type", "text/javascript"), f.end(l.code);
881
+ } catch (l) {
882
+ c(l);
883
+ }
884
+ }), r.middlewares.use((p, f, c) => {
885
+ const u = `${n.demo ? "<script>window.__oknoDemo=true<\/script>" : ""}<script type="module" src="${i}"><\/script>`, h = [];
886
+ let g = null;
887
+ const _ = f.write.bind(f), k = f.end.bind(f), S = f.setHeader.bind(f), b = () => {
888
+ const $ = f.getHeader("content-type");
889
+ return typeof $ == "string" && $.includes("text/html");
890
+ }, T = ($, P) => Buffer.isBuffer($) ? $ : $ instanceof Uint8Array ? Buffer.from($.buffer, $.byteOffset, $.byteLength) : typeof $ == "string" ? Buffer.from($, P || "utf-8") : Buffer.from(String($));
891
+ f.write = ($, P, ...B) => (g === null && (g = b()), g ? ($ && h.push(T($, typeof P == "string" ? P : void 0)), !0) : _($, P, ...B)), f.end = ($, P, ...B) => {
892
+ if (g === null && (g = b()), !g) return k($, P, ...B);
893
+ $ && h.push(T($, typeof P == "string" ? P : void 0));
894
+ let E = Buffer.concat(h).toString("utf-8");
895
+ E.includes(u) || (E = E.includes("</body>") ? E.replace("</body>", `${u}</body>`) : E + u);
896
+ const H = Buffer.from(E, "utf-8");
897
+ if (!f.headersSent)
898
+ try {
899
+ S("content-length", String(H.length));
900
+ } catch {
901
+ }
902
+ return k(H, ...B);
903
+ }, c();
904
+ });
905
+ },
906
+ async handleHotUpdate(r) {
907
+ const o = y(t, "schema.ts"), i = y(t, "users.json"), p = y(t, "permissions.ts"), f = y(t, "modules.d.ts");
908
+ if (r.file === o) {
909
+ await ut(t, e);
910
+ for (const l of ["pages", "collections", "globals"]) {
911
+ const u = r.server.moduleGraph.getModuleById(X + l);
912
+ u && r.server.moduleGraph.invalidateModule(u);
913
+ }
914
+ return [];
915
+ }
916
+ if (r.file === i || r.file === p || r.file === f)
917
+ return [];
918
+ const c = I(t, r.file);
919
+ if (!c.startsWith("..") && c.endsWith(".ts")) {
920
+ const l = c.split(/[\\/]/)[0];
921
+ if ((l === "pages" || l === "collections" || l === "globals") && dt(r.file)) {
922
+ const u = r.server.moduleGraph.getModuleById(X + l);
923
+ return u && r.server.moduleGraph.invalidateModule(u), [];
924
+ }
925
+ }
926
+ },
927
+ resolveId(r) {
928
+ if (r.startsWith(se))
929
+ return "\0" + r;
930
+ if (d && r === "okno/editor")
931
+ return et;
932
+ },
933
+ async load(r) {
934
+ if (!r.startsWith(X)) return;
935
+ const o = r.slice(X.length);
936
+ if (o === "runtime") {
937
+ if (!wt)
938
+ throw new Error("okno: runtime/wrap.js missing — run `bun run build:pkg`");
939
+ return wt;
940
+ }
941
+ if (o === "bootstrap")
942
+ return 'import("okno/editor")';
943
+ if (o === "pages") {
944
+ const i = await C(e, "pages");
945
+ return await ue(t, i);
946
+ }
947
+ if (o === "collections") {
948
+ const i = await C(e, "collections");
949
+ return await fe(t, i, a);
950
+ }
951
+ if (o === "globals") {
952
+ const i = await C(e, "globals");
953
+ return await de(t, i);
954
+ }
955
+ }
956
+ };
957
+ }
958
+ async function it(n) {
959
+ return w(n) ? (await J(n)).filter((e) => e.endsWith(".ts") && e !== "index.ts") : [];
960
+ }
961
+ function le(n) {
962
+ const s = y(n, "schema.ts"), e = {}, t = /* @__PURE__ */ new Set();
963
+ if (!w(s)) return { orders: e, drafts: t };
964
+ try {
965
+ const a = st(j(s, "utf-8"))?.collections ?? {};
966
+ for (const [r, o] of Object.entries(a))
967
+ Array.isArray(o?.order) && (e[r] = o.order.filter((i) => typeof i == "string")), o?.drafts === !0 && t.add(r);
968
+ } catch {
969
+ }
970
+ return { orders: e, drafts: t };
971
+ }
972
+ const at = /^[a-z]{2}(-[a-z]{2})?$/;
973
+ function ct(n) {
974
+ return n.replace(".ts", "").replace(/-/g, "_");
975
+ }
976
+ function vt(n) {
977
+ return n.replace(".ts", "").replace(/-/g, "_");
978
+ }
979
+ function Y(n) {
980
+ return n.replace(".ts", "");
981
+ }
982
+ async function ue(n, s = /* @__PURE__ */ new Set()) {
983
+ const e = y(n, "pages"), t = y(n, "schema.ts"), d = w(t), a = [
984
+ 'import { __oknoWrap, __oknoLocalize, __oknoResolveRefs } from "okno:runtime"'
985
+ ];
986
+ d && (a.push('import * as __collections from "okno:collections"'), a.push(`import __schema from "${t}"`));
987
+ const r = (i, p) => d ? `__oknoResolveRefs(_${i}, __schema?.pages?.["${p}"]?.fields, __collections)` : `_${i}`, o = /* @__PURE__ */ new Set();
988
+ if (w(e)) {
989
+ const p = (await J(e, { withFileTypes: !0 })).filter((c) => c.isDirectory() && at.test(c.name)).map((c) => c.name), f = await it(e);
990
+ for (const c of f) {
991
+ const l = ct(c), u = vt(c), h = Y(c), g = y(e, c);
992
+ if (p.length === 0) {
993
+ a.push(`import _${l} from "${g}"`), a.push(`export const ${u} = __oknoWrap(${r(l, h)}, "${h}")`), o.add(u);
994
+ continue;
995
+ }
996
+ const _ = [`import _${l}_default from "${g}"`], k = [];
997
+ for (const S of p) {
998
+ const b = y(e, S, c);
999
+ w(b) && (_.push(`import _${l}_${S} from "${b}"`), k.push(`${S}: _${l}_${S}`));
1000
+ }
1001
+ a.push(..._), a.push(`const _${l} = __oknoLocalize(_${l}_default, { ${k.join(", ")} })`), a.push(`export const ${u} = __oknoWrap(${r(l, h)}, "${h}")`), o.add(u);
1002
+ }
1003
+ }
1004
+ for (const i of s)
1005
+ o.has(i) || a.push(`export const ${i} = __oknoWrap(null, "${i}")`);
1006
+ return a.join(`
1007
+ `);
1008
+ }
1009
+ async function fe(n, s = /* @__PURE__ */ new Set(), e = !1) {
1010
+ const t = y(n, "collections");
1011
+ if (!w(t)) {
1012
+ const u = [];
1013
+ for (const h of s) {
1014
+ const g = h.replace(/-/g, "_");
1015
+ u.push(`export const ${g} = []`);
1016
+ }
1017
+ return u.join(`
1018
+ `) || "export {}";
1019
+ }
1020
+ const d = await J(t, { withFileTypes: !0 }), a = d.filter((u) => u.isDirectory() && at.test(u.name)).map((u) => u.name), r = d.filter((u) => u.isDirectory() && !a.includes(u.name)).map((u) => u.name), { orders: o, drafts: i } = le(n), p = y(n, "schema.ts"), f = w(p), c = [
1021
+ 'import { __oknoWrap, __oknoLocalize, __oknoResolveRefs } from "okno:runtime"'
1022
+ ];
1023
+ f && c.push(`import __schema from "${p}"`);
1024
+ const l = [];
1025
+ for (const u of r) {
1026
+ const h = y(t, u), g = Ct(await it(h), Y, o[u]), _ = u.replace(/-/g, "_"), k = e && i.has(u), S = [];
1027
+ for (const b of g) {
1028
+ const T = `_${_}_${ct(b)}`, $ = Y(b), P = y(h, b);
1029
+ if (a.length === 0)
1030
+ c.push(`import ${T} from "${P}"`);
1031
+ else {
1032
+ const B = [`import ${T}_default from "${P}"`], E = [];
1033
+ for (const H of a) {
1034
+ const lt = y(t, H, u, b);
1035
+ w(lt) && (B.push(`import ${T}_${H} from "${lt}"`), E.push(`${H}: ${T}_${H}`));
1036
+ }
1037
+ c.push(...B), c.push(`const ${T} = __oknoLocalize(${T}_default, { ${E.join(", ")} })`);
1038
+ }
1039
+ S.push({ varName: T, itemName: $ });
1040
+ }
1041
+ c.push(`const __oknoRaw_${_} = [${S.map((b) => b.varName).join(", ")}]`), l.push({ name: u, safe: _, draftsOn: k, items: S });
1042
+ }
1043
+ f && c.push(`const __oknoNs = { ${l.map((u) => `${u.safe}: __oknoRaw_${u.safe}`).join(", ")} }`);
1044
+ for (const u of l) {
1045
+ const h = (_) => `__oknoWrap(${f ? `__oknoResolveRefs(${_.varName}, __schema?.collections?.["${u.name}"]?.fields, __oknoNs)` : _.varName}, "${u.name}.${_.itemName}")`, g = u.draftsOn ? `[${u.items.map((_) => `[${_.varName}, ${h(_)}]`).join(", ")}].filter((e) => e[0]?.status !== "draft").map((e) => e[1])` : `[${u.items.map(h).join(", ")}]`;
1046
+ c.push(`export const ${u.safe} = ${g}`);
1047
+ }
1048
+ return c.join(`
1049
+ `);
1050
+ }
1051
+ async function de(n, s = /* @__PURE__ */ new Set()) {
1052
+ const e = y(n, "globals"), t = y(n, "schema.ts"), d = w(t), a = [
1053
+ 'import { __oknoWrap, __oknoLocalize, __oknoResolveRefs } from "okno:runtime"'
1054
+ ];
1055
+ d && (a.push('import * as __collections from "okno:collections"'), a.push(`import __schema from "${t}"`));
1056
+ const r = (i, p) => d ? `__oknoResolveRefs(_${i}, __schema?.globals?.["${p}"]?.fields, __collections)` : `_${i}`, o = /* @__PURE__ */ new Set();
1057
+ if (w(e)) {
1058
+ const p = (await J(e, { withFileTypes: !0 })).filter((c) => c.isDirectory() && at.test(c.name)).map((c) => c.name), f = await it(e);
1059
+ for (const c of f) {
1060
+ const l = ct(c), u = vt(c), h = Y(c), g = y(e, c);
1061
+ if (p.length === 0) {
1062
+ a.push(`import _${l} from "${g}"`), a.push(`export const ${u} = __oknoWrap(${r(l, h)}, "${h}")`), o.add(u);
1063
+ continue;
1064
+ }
1065
+ const _ = [`import _${l}_default from "${g}"`], k = [];
1066
+ for (const S of p) {
1067
+ const b = y(e, S, c);
1068
+ w(b) && (_.push(`import _${l}_${S} from "${b}"`), k.push(`${S}: _${l}_${S}`));
1069
+ }
1070
+ a.push(..._), a.push(`const _${l} = __oknoLocalize(_${l}_default, { ${k.join(", ")} })`), a.push(`export const ${u} = __oknoWrap(${r(l, h)}, "${h}")`), o.add(u);
1071
+ }
1072
+ }
1073
+ for (const i of s)
1074
+ o.has(i) || a.push(`export const ${i} = __oknoWrap(null, "${i}")`);
1075
+ return a.join(`
1076
+ `);
1077
+ }
1078
+ export {
1079
+ be as o
1080
+ };