okno 1.0.0-alpha.8 → 1.0.0-beta.6

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 (62) hide show
  1. package/dist/boot.d.ts +88 -0
  2. package/dist/boot.d.ts.map +1 -0
  3. package/dist/boot.js +84 -19
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +22 -0
  7. package/dist/codegen/generate.d.ts +10 -0
  8. package/dist/codegen/generate.d.ts.map +1 -0
  9. package/dist/codegen/scan-imports.d.ts +9 -0
  10. package/dist/codegen/scan-imports.d.ts.map +1 -0
  11. package/dist/content-encode-DoojdsVU.js +80 -0
  12. package/dist/core/content-encode.d.ts +44 -0
  13. package/dist/core/content-encode.d.ts.map +1 -0
  14. package/dist/core/order.d.ts +18 -0
  15. package/dist/core/order.d.ts.map +1 -0
  16. package/dist/core/parse.d.ts +16 -0
  17. package/dist/core/parse.d.ts.map +1 -0
  18. package/dist/editor/index.js +25499 -20740
  19. package/dist/{index-CyH92tZh.js → index-B1PShnsc.js} +1 -1
  20. package/dist/{index-_HDmM7wX.js → index-B2WzdTzI.js} +26 -26
  21. package/dist/{index-lOMQLdGq.js → index-ButdD9Pf.js} +5 -5
  22. package/dist/{index-CfLK4WZQ.js → index-DKF0siIz.js} +19 -19
  23. package/dist/{index-CoUiiRXQ.js → index-q-7MEoHz.js} +1 -1
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +1 -1
  27. package/dist/init.d.ts +39 -0
  28. package/dist/init.d.ts.map +1 -0
  29. package/dist/init.js +221 -0
  30. package/dist/mcp.d.ts +4 -0
  31. package/dist/mcp.d.ts.map +1 -0
  32. package/dist/mcp.js +140 -0
  33. package/dist/okno.css +1 -1
  34. package/dist/order-bAkdncZC.js +21 -0
  35. package/dist/plugin-Cuncen9r.js +1422 -0
  36. package/dist/runtime/wrap.d.ts +117 -0
  37. package/dist/runtime/wrap.d.ts.map +1 -0
  38. package/dist/runtime/wrap.js +393 -88
  39. package/dist/types/fields.d.ts +133 -0
  40. package/dist/types/fields.d.ts.map +1 -0
  41. package/dist/types/index.d.ts +4 -0
  42. package/dist/types/index.d.ts.map +1 -0
  43. package/dist/types/permissions.d.ts +22 -0
  44. package/dist/types/permissions.d.ts.map +1 -0
  45. package/dist/types/schema.d.ts +152 -0
  46. package/dist/types/schema.d.ts.map +1 -0
  47. package/dist/vite/dev-server.d.ts +16 -0
  48. package/dist/vite/dev-server.d.ts.map +1 -0
  49. package/dist/vite/editor-aliases.d.ts +23 -0
  50. package/dist/vite/editor-aliases.d.ts.map +1 -0
  51. package/dist/vite/index.d.ts +2 -0
  52. package/dist/vite/index.d.ts.map +1 -0
  53. package/dist/vite/index.js +1 -1
  54. package/dist/vite/local-engine.d.ts +34 -0
  55. package/dist/vite/local-engine.d.ts.map +1 -0
  56. package/dist/vite/plugin.d.ts +4 -0
  57. package/dist/vite/plugin.d.ts.map +1 -0
  58. package/package.json +14 -6
  59. package/skills/connect-okno/SKILL.md +405 -0
  60. package/src/runtime/wrap.test.ts +217 -0
  61. package/src/runtime/wrap.ts +747 -12
  62. package/dist/plugin-DfS9fJAq.js +0 -1067
package/dist/boot.d.ts ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * okno client boot — production editor delivery.
3
+ *
4
+ * In dev the okno Vite plugin injects the editor through dev-server middleware
5
+ * (`configureServer` in src/vite/plugin.ts). That middleware does not run in a
6
+ * production build, and on SSG frameworks (Astro et al.) the okno runtime is
7
+ * server-only — so a deployed page ships no editor at all. This module is the
8
+ * client-side entry that closes that gap: a page pulls it in (via a framework
9
+ * integration or a `<script>` in the layout) and it lazily boots the editor on
10
+ * demand.
11
+ *
12
+ * The ~1 MB editor bundle is loaded only when an editor signals intent —
13
+ * pressing `e`, or visiting with `?okno` / `#okno`. Public visitors download
14
+ * only this tiny gate. `import("okno/editor")` is a bare specifier the
15
+ * *consumer's* bundler resolves and code-splits at their build time (okno's own
16
+ * build keeps it external via rollup `external`), so the editor lands as its own
17
+ * chunk rather than inside this file.
18
+ *
19
+ * FUTURE (not now): this lazy import resolves to the consumer's OWN deployed
20
+ * chunk, pinned to the okno version they built with — so an editor update needs
21
+ * a consumer rebuild. An alternative is to load the editor from a hosted URL
22
+ * (`https://cdn.okno.build/editor@latest`) instead of `import("okno/editor")`:
23
+ * editors update everywhere with no consumer rebuild, at the cost of version
24
+ * pinning and a centralized editor↔backend version contract to keep in sync.
25
+ */
26
+ declare const __OKNO_IS_DEV__: boolean;
27
+ declare const GATE_KEY = "e";
28
+ declare const g: {
29
+ document?: Document;
30
+ location?: Location;
31
+ localStorage?: Storage;
32
+ __okno_loaded?: boolean;
33
+ __okno_gate_installed?: boolean;
34
+ __okno_autostart?: "key" | "url" | "session" | false;
35
+ __okno_ensure_vt?: () => void;
36
+ };
37
+ declare let loading: boolean;
38
+ declare const OPENED_KEY = "okno-win-opened";
39
+ declare const SHELL_ID = "okno-shadow-root";
40
+ declare const VT_STYLE_ID = "okno-vt-style";
41
+ declare const NAV_CLASS = "okno-nav-vt";
42
+ /** The window was last left open → the editor should ride along across navigation. */
43
+ declare function editorActive(): boolean;
44
+ /** Cross-document View Transitions: needs the VT API + the pageswap/pagereveal
45
+ * hooks (Chromium 126+, Safari 18.2+). Elsewhere we degrade to a plain reboot. */
46
+ declare function crossDocVTSupported(): boolean;
47
+ /** Does the HOST page already opt into cross-document View Transitions? Decides
48
+ * how we coexist without interfering (see ensureVTStyle). Read before injecting
49
+ * our own style; cross-origin sheets are skipped (their rules can't be read). */
50
+ declare function hostHasViewTransition(): boolean;
51
+ /** Inject (once) the rules that hold the editor in place across navigation. Two
52
+ * hard constraints: UNIVERSAL (no host-framework assumptions — pure CSS in the
53
+ * always-loaded gate) and NON-INTERFERING with the host's own transitions:
54
+ * • All `okno-shell` / `root` rules are scoped to `html.okno-nav-vt` — a class
55
+ * we set ONLY during a cross-document nav — so they never bleed into okno's
56
+ * own same-document structural View Transitions (which run constantly).
57
+ * • If the host ALREADY uses cross-document VT, we DON'T touch `root`: the page
58
+ * animates exactly as the host intends; we only lift the editor out + hold it.
59
+ * • If the host does NOT, we enable a minimal VT and HARD-CUT the page (suppress
60
+ * the default root crossfade), so a site that never wanted page transitions
61
+ * doesn't suddenly get one — only the editor is held.
62
+ * Public on `window.__okno_ensure_vt` so the editor can opt the current page in
63
+ * the instant it opens (boot ran here before the window was open). */
64
+ declare function ensureVTStyle(): void;
65
+ /** The editor host is normally a 0-size box (its UI is `position:fixed` inside
66
+ * the shadow root), which would snapshot empty and make the browser SKIP the
67
+ * transition. Give it a real viewport box + the group name for the capture —
68
+ * pointer-events:none so it never intercepts clicks. Inline + transient (only
69
+ * during the nav), so it never lingers to fight okno's structural `okno-editor`
70
+ * group. Mirrors the structural-edit code in wrap.ts. */
71
+ declare function pinHostForCapture(host: HTMLElement): void;
72
+ /** Outgoing page: flag the nav + lift the editor into its own snapshot group. */
73
+ declare function onPageSwap(e: Event): void;
74
+ /** Incoming page: flag the nav (so the scoped rules apply), then stand up a
75
+ * placeholder host with the box + name before first render so the new side has a
76
+ * matching `okno-shell` group. `initEditor` reuses it when the bundle loads. The
77
+ * flag is cleared once the transition settles. */
78
+ declare function onPageReveal(e: Event): void;
79
+ /** The editor sets `window.__okno_loaded` at the top of its entry module, so
80
+ * this flips true the moment the bundle starts evaluating. */
81
+ declare function editorPresent(): boolean;
82
+ /** Don't hijack `e` while the visitor is typing in the host page. Mirrors the
83
+ * editor's own focus check (modules/keys.svelte.ts), shadow DOM included. */
84
+ declare function isTyping(): boolean;
85
+ declare function bootEditor(reason: "key" | "url" | "session"): void;
86
+ declare function urlRequestsEditor(): boolean;
87
+ declare function install(): void;
88
+ //# sourceMappingURL=boot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../src/boot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,CAAC,MAAM,eAAe,EAAE,OAAO,CAAA;AAEtC,QAAA,MAAM,QAAQ,MAAM,CAAA;AAEpB,QAAA,MAAM,CAAC,EAA4B;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,gBAAgB,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,CAAA;IACpD,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;CAC7B,CAAA;AAED,QAAA,IAAI,OAAO,SAAQ,CAAA;AAenB,QAAA,MAAM,UAAU,oBAAoB,CAAA;AACpC,QAAA,MAAM,QAAQ,qBAAqB,CAAA;AACnC,QAAA,MAAM,WAAW,kBAAkB,CAAA;AACnC,QAAA,MAAM,SAAS,gBAAgB,CAAA;AAE/B,sFAAsF;AACtF,iBAAS,YAAY,IAAI,OAAO,CAM/B;AAED;mFACmF;AACnF,iBAAS,mBAAmB,IAAI,OAAO,CAOtC;AAED;;kFAEkF;AAClF,iBAAS,qBAAqB,IAAI,OAAO,CAgBxC;AAED;;;;;;;;;;;;uEAYuE;AACvE,iBAAS,aAAa,IAAI,IAAI,CA0B7B;AAED;;;;;0DAK0D;AAC1D,iBAAS,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAElD;AAED,iFAAiF;AACjF,iBAAS,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAKlC;AAED;;;mDAGmD;AACnD,iBAAS,YAAY,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAgBpC;AAED;+DAC+D;AAC/D,iBAAS,aAAa,IAAI,OAAO,CAEhC;AAED;8EAC8E;AAC9E,iBAAS,QAAQ,IAAI,OAAO,CAO3B;AAED,iBAAS,UAAU,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,IAAI,CAa3D;AAED,iBAAS,iBAAiB,IAAI,OAAO,CASpC;AAED,iBAAS,OAAO,IAAI,IAAI,CAgCvB"}
package/dist/boot.js CHANGED
@@ -1,23 +1,85 @@
1
- const n = globalThis;
2
- let o = !1;
3
- function s() {
4
- return !!n.__okno_loaded;
5
- }
1
+ const e = globalThis;
2
+ let r = !1;
3
+ const m = "okno-win-opened", l = "okno-shadow-root", c = "okno-vt-style", i = "okno-nav-vt";
6
4
  function u() {
7
- var r, i;
8
- let t = (r = n.document) == null ? void 0 : r.activeElement;
9
- for (; t && ((i = t.shadowRoot) != null && i.activeElement); )
5
+ try {
6
+ return e.localStorage?.getItem(m) === "true";
7
+ } catch {
8
+ return !1;
9
+ }
10
+ }
11
+ function h() {
12
+ return !!e.document && typeof e.document.startViewTransition == "function" && typeof window < "u" && "onpageswap" in window;
13
+ }
14
+ function _() {
15
+ if (!e.document) return !1;
16
+ for (const t of Array.from(e.document.styleSheets)) {
17
+ if (t.ownerNode?.id === c) continue;
18
+ let n;
19
+ try {
20
+ n = t.cssRules;
21
+ } catch {
22
+ continue;
23
+ }
24
+ for (const o of Array.from(n))
25
+ if (o.constructor?.name === "CSSViewTransitionRule" || typeof o.cssText == "string" && o.cssText.trimStart().startsWith("@view-transition")) return !0;
26
+ }
27
+ return !1;
28
+ }
29
+ function d() {
30
+ if (!e.document || e.document.getElementById(c) || !h()) return;
31
+ const t = _(), n = e.document.createElement("style");
32
+ n.id = c;
33
+ let o = `
34
+ html.${i}::view-transition-group(okno-shell) { animation-duration: 420ms; }
35
+ html.${i}::view-transition-old(okno-shell) { animation: okno-shell-hold 420ms both; }
36
+ html.${i}::view-transition-new(okno-shell) { animation: none; }
37
+ @keyframes okno-shell-hold { from { opacity: 1 } to { opacity: 1 } }
38
+ `;
39
+ t || (o += `
40
+ @view-transition { navigation: auto; }
41
+ html.${i}::view-transition-group(root),
42
+ html.${i}::view-transition-old(root),
43
+ html.${i}::view-transition-new(root) { animation: none; }
44
+ `), n.textContent = o, e.document.head.appendChild(n);
45
+ }
46
+ function w(t) {
47
+ t.style.cssText += ";position:fixed;inset:0;pointer-events:none;view-transition-name:okno-shell";
48
+ }
49
+ function v(t) {
50
+ if (!u() || !t.viewTransition) return;
51
+ e.document?.documentElement.classList.add(i);
52
+ const n = e.document?.getElementById(l);
53
+ n instanceof HTMLElement && w(n);
54
+ }
55
+ function y(t) {
56
+ const n = t.viewTransition;
57
+ if (!u() || !n || !e.document) return;
58
+ const o = e.document.documentElement;
59
+ o.classList.add(i), n.finished?.then?.(
60
+ () => o.classList.remove(i),
61
+ () => o.classList.remove(i)
62
+ );
63
+ let s = e.document.getElementById(l);
64
+ s || (s = e.document.createElement("div"), s.id = l, e.document.body.appendChild(s)), s instanceof HTMLElement && (s.style.cssText = "position:fixed;inset:0;pointer-events:none;view-transition-name:okno-shell");
65
+ }
66
+ function f() {
67
+ return !!e.__okno_loaded;
68
+ }
69
+ function E() {
70
+ let t = e.document?.activeElement;
71
+ for (; t && t.shadowRoot?.activeElement; )
10
72
  t = t.shadowRoot.activeElement;
11
- const e = t == null ? void 0 : t.tagName;
12
- return e === "INPUT" || e === "TEXTAREA" || (t == null ? void 0 : t.isContentEditable) === !0;
73
+ const n = t?.tagName;
74
+ return n === "INPUT" || n === "TEXTAREA" || t?.isContentEditable === !0;
13
75
  }
14
76
  function a(t) {
15
- o || s() || (o = !0, n.__okno_autostart = t, import("okno/editor").catch((e) => {
16
- o = !1, console.error("[okno] failed to load editor bundle", e);
77
+ r || f() || (r = !0, e.__okno_autostart = t, import("okno/editor").catch((n) => {
78
+ r = !1, console.error("[okno] failed to load editor bundle", n);
17
79
  }));
18
80
  }
19
- function l() {
20
- const t = n.location;
81
+ function p() {
82
+ const t = e.location;
21
83
  if (!t) return !1;
22
84
  try {
23
85
  if (new URLSearchParams(t.search).has("okno")) return !0;
@@ -25,9 +87,12 @@ function l() {
25
87
  }
26
88
  return typeof t.hash == "string" && /(?:^#|[#&])okno(?:$|[=&])/.test(t.hash);
27
89
  }
28
- function _() {
29
- !n.document || typeof __OKNO_IS_DEV__ < "u" && __OKNO_IS_DEV__ || n.__okno_gate_installed || (n.__okno_gate_installed = !0, n.document.addEventListener("keydown", (e) => {
30
- s() || e.key !== "e" || e.ctrlKey || e.metaKey || e.altKey || u() || a("key");
31
- }), l() && a("url"));
90
+ function g() {
91
+ if (!e.document || (typeof __OKNO_IS_DEV__ < "u" ? __OKNO_IS_DEV__ : !1) || e.__okno_gate_installed) return;
92
+ e.__okno_gate_installed = !0, e.document.addEventListener("keydown", (o) => {
93
+ f() || o.key !== "e" || o.ctrlKey || o.metaKey || o.altKey || E() || a("key");
94
+ }), e.__okno_ensure_vt = d;
95
+ const n = window;
96
+ n.addEventListener("pageswap", v), n.addEventListener("pagereveal", y), u() && (d(), a("session")), p() && a("url");
32
97
  }
33
- _();
98
+ g();
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA6BA,OAAO,EAAE,CAAA"}
package/dist/cli.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ const [n] = process.argv.slice(2);
3
+ switch (n) {
4
+ case "mcp": {
5
+ const { runMcp: o } = await import("./mcp.js");
6
+ await o();
7
+ break;
8
+ }
9
+ case "help":
10
+ case "--help":
11
+ case "-h": {
12
+ console.log(
13
+ ["", " npx okno Add okno to this project", " npx okno mcp Run the okno MCP server (for your AI client)", ""].join(`
14
+ `)
15
+ );
16
+ break;
17
+ }
18
+ default: {
19
+ const { runInit: o } = await import("./init.js");
20
+ await o();
21
+ }
22
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Read the schema, scan content directories, and generate:
3
+ * - modules.d.ts (type declarations for okno:* virtual modules)
4
+ *
5
+ * `root` is the project root (parent of the okno dir) — we scan it for
6
+ * `import { x } from "okno:<kind>"` so names referenced before scaffolding
7
+ * still get a (placeholder) type, mirroring the runtime virtual modules.
8
+ */
9
+ export declare function generateTypes(oknoDir: string, root: string): Promise<void>;
10
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/codegen/generate.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,iBA4HhE"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Walk the project root looking for `import { foo, bar } from "okno:<kind>"`
3
+ * statements and return the union of imported names. Used by both the runtime
4
+ * virtual modules and the type codegen to emit placeholder exports for content
5
+ * that doesn't exist yet, so a project can refer to `home.title` (and get types
6
+ * for it) before any schema is scaffolded.
7
+ */
8
+ export declare function scanImports(root: string, kind: "pages" | "collections" | "globals"): Promise<Set<string>>;
9
+ //# sourceMappingURL=scan-imports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-imports.d.ts","sourceRoot":"","sources":["../../src/codegen/scan-imports.ts"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,wBAAsB,WAAW,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,GACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CA0CtB"}
@@ -0,0 +1,80 @@
1
+ import { p as s } from "./acorn-CZBJD705.js";
2
+ function a(o) {
3
+ const e = o;
4
+ switch (e.type) {
5
+ case "Literal": {
6
+ if (e.regex) throw new Error("regex literals are not allowed");
7
+ return e.value;
8
+ }
9
+ case "TemplateLiteral": {
10
+ if (e.expressions.length > 0) throw new Error("template expressions are not allowed");
11
+ return e.quasis.map((r) => r.value.cooked).join("");
12
+ }
13
+ case "UnaryExpression": {
14
+ if ((e.operator === "-" || e.operator === "+") && e.argument?.type === "Literal" && typeof e.argument.value == "number")
15
+ return e.operator === "-" ? -e.argument.value : +e.argument.value;
16
+ throw new Error(`unary operator ${e.operator} is not allowed`);
17
+ }
18
+ case "Identifier": {
19
+ if (e.name === "undefined") return;
20
+ throw new Error(`identifier ${e.name} is not allowed`);
21
+ }
22
+ case "ArrayExpression":
23
+ return e.elements.map((r) => {
24
+ if (r === null) throw new Error("array holes are not allowed");
25
+ if (r.type === "SpreadElement") throw new Error("spread is not allowed");
26
+ return a(r);
27
+ });
28
+ case "ObjectExpression": {
29
+ const r = {};
30
+ for (const t of e.properties) {
31
+ if (t.type !== "Property") throw new Error("spread is not allowed");
32
+ if (t.computed) throw new Error("computed keys are not allowed");
33
+ if (t.kind !== "init") throw new Error("getters/setters are not allowed");
34
+ if (t.method) throw new Error("methods are not allowed");
35
+ let n;
36
+ if (t.key.type === "Identifier") n = t.key.name;
37
+ else if (t.key.type === "Literal") n = String(t.key.value);
38
+ else throw new Error("unsupported object key");
39
+ r[n] = a(t.value);
40
+ }
41
+ return r;
42
+ }
43
+ default:
44
+ throw new Error(`unsupported node: ${e.type}`);
45
+ }
46
+ }
47
+ function l(o) {
48
+ try {
49
+ let e = o.trim();
50
+ const r = e.match(/export\s+default\s+([\s\S]+)/);
51
+ if (!r)
52
+ return console.warn("Could not find export default"), {};
53
+ e = r[1].trim(), e.endsWith(";") && (e = e.slice(0, -1)), e = e.replace(/\s+satisfies\s+\w+\s*$/, ""), e = e.replace(/\s+as\s+\w+\s*$/, "");
54
+ const t = s(`(${e})`, 0, { ecmaVersion: "latest" });
55
+ return a(t);
56
+ } catch (e) {
57
+ return console.error("Failed to parse TypeScript export:", e), {};
58
+ }
59
+ }
60
+ function p(o, e) {
61
+ const r = { date: e.now, author: e.author }, t = { ...o, created: e.created ?? r, updated: r };
62
+ return `export default ${JSON.stringify(t, null, " ")}
63
+ `;
64
+ }
65
+ function u(o, e = `import type { Schema } from "okno"
66
+
67
+ `) {
68
+ return `${e}export default ${JSON.stringify(o, null, " ")} satisfies Schema
69
+ `;
70
+ }
71
+ function d(o) {
72
+ return `export default ${JSON.stringify(o, null, " ")}
73
+ `;
74
+ }
75
+ export {
76
+ u as a,
77
+ d as b,
78
+ p as e,
79
+ l as p
80
+ };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Canonical serializers: a content/schema object → its `.ts` source module.
3
+ *
4
+ * The byte format is a CONTRACT. The same logical content must encode
5
+ * identically on the live path (hosted backend → GitHub commit) and the dev
6
+ * path (local engine → disk write), or a publish round-trip shows phantom
7
+ * diffs. Keep this module dependency-free (pure string/JSON, no node/svelte) so
8
+ * either side can import it.
9
+ *
10
+ * SYNC: `backend/src/lib/encode.ts` is a byte-identical copy. The backend is a
11
+ * separate deployable and this monorepo has no cross-package source imports
12
+ * (same controlled-duplication pattern as this package's
13
+ * `editor/lib/parse-export-default.ts` ↔ the backend's `lib/parse.ts`). Any
14
+ * change here MUST be mirrored there, and vice versa.
15
+ */
16
+ export interface Stamp {
17
+ date: string;
18
+ author: string;
19
+ }
20
+ /**
21
+ * A content entry (page / collection item / global) → `export default {...}`.
22
+ * Stamps `updated` from `now`/`author`, and `created` from the same stamp unless
23
+ * a prior `created` is passed through (preserved across edits).
24
+ *
25
+ * Key order — content fields, then `created`, then `updated` — is part of the
26
+ * byte contract. Do not reorder.
27
+ */
28
+ export declare function encodeEntry(content: Record<string, unknown>, opts: {
29
+ now: string;
30
+ author: string;
31
+ created?: Stamp;
32
+ }): string;
33
+ /**
34
+ * The schema → `<header>export default {...} satisfies Schema`. `header`
35
+ * preserves the file's existing import/comment prelude (default: the canonical
36
+ * `import type { Schema } from "okno"`).
37
+ */
38
+ export declare function encodeSchema(schema: Record<string, unknown>, header?: string): string;
39
+ /**
40
+ * Bare `export default <json>` with no metadata — for scaffold seeds (a fresh
41
+ * page/global's default field values, or an empty `[]` collection).
42
+ */
43
+ export declare function encodeRaw(value: unknown): string;
44
+ //# sourceMappingURL=content-encode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-encode.d.ts","sourceRoot":"","sources":["../../src/core/content-encode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,CAAA;CAAE,GACpD,MAAM,CAIR;AAED;;;;GAIG;AAGH,wBAAgB,YAAY,CAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,SAA2C,GAC/C,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * okno's manual collection ordering — the single source of truth shared by the
3
+ * build plugin (`okno:collections` iteration order) and the editor (collection
4
+ * table + reference lists). okno owns ONLY this manual order; any date/field
5
+ * sort is the dev's own `.sort()` in their template, right before `.map()`.
6
+ */
7
+ /**
8
+ * Order `items` by an explicit slug list. Items whose slug appears in `order`
9
+ * come first, in that order; everything else keeps its original relative order
10
+ * after them (so items added outside the editor — not yet in `order` — still
11
+ * show up, just unsorted at the end). Pure and stable; never drops items.
12
+ */
13
+ export declare function orderBySlugs<T>(items: T[], getSlug: (item: T) => string | undefined, order?: string[]): T[];
14
+ /** Apply a create/delete to a slug-order list. Create prepends (newest-first);
15
+ * delete drops the slug. Returns a new array; both are no-ops when redundant. */
16
+ export declare function orderWithInsert(order: string[] | undefined, slug: string): string[];
17
+ export declare function orderWithout(order: string[] | undefined, slug: string): string[];
18
+ //# sourceMappingURL=order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"order.d.ts","sourceRoot":"","sources":["../../src/core/order.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC7B,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,EACxC,KAAK,CAAC,EAAE,MAAM,EAAE,GACd,CAAC,EAAE,CAaL;AAED;kFACkF;AAClF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnF;AACD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEhF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Parser for `export default { ... }` TypeScript content/schema files.
3
+ *
4
+ * We must NOT execute file content (`new Function` would be an RCE and corrupts
5
+ * any string containing `//`). Instead we parse the `export default` expression
6
+ * with acorn and walk the AST, accepting ONLY literal data; anything that would
7
+ * *evaluate* is rejected.
8
+ *
9
+ * PARITY / SYNC: byte-for-byte (parsing logic) with the editor's
10
+ * `editor/lib/parse-export-default.ts` and the backend's `lib/parse.ts` — THREE
11
+ * copies of the parser (local vs hosted), keep all in step. This copy lives under
12
+ * `src/` so the Vite plugin's local engine (which can't import across the editor
13
+ * `rootDir`) can read schema files. See docs/engine-parity.md.
14
+ */
15
+ export declare function parseExportDefault(raw: string): Record<string, unknown>;
16
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/core/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAqDH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyBvE"}