@omgbase/astro 0.3.0 → 0.3.1

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.
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Hash-first sync support: the pieces that let `syncEntries` decide, from a
3
+ * lean OQX hit alone, whether a document needs to be fetched or re-rendered.
4
+ *
5
+ * - {@link withContentHash} projects `$content_hash` onto the user's query so
6
+ * every hit carries the server's whole-file hash (frontmatter included).
7
+ * - {@link encodeEntryDigest} / {@link parseEntryDigest} store everything the
8
+ * next sync needs to skip a doc — hash, path, slug, href, projection and link
9
+ * fingerprints — inside the Astro data-store `digest` string, so no extra
10
+ * state lives outside Astro's own persistence.
11
+ * - {@link linksFingerprint} pins a doc's rewritten body to the hrefs of the
12
+ * docs it links to, so a new/removed/moved doc only invalidates its linkers.
13
+ */
14
+ import type { HrefIndex, OutEdge } from "./links.js";
15
+ export interface EntryDigest {
16
+ /** Server `$content_hash`, or `body:<len>` when the server has none. */
17
+ hash: string;
18
+ path: string;
19
+ slug: string;
20
+ /** Site href used for link rewriting; `""` when rewriting is disabled. */
21
+ href: string;
22
+ /** Fingerprint of the hit's extra OQX projections (they land in `data`). */
23
+ hitsFp: string;
24
+ /** Fingerprint of the hrefs of this doc's in-collection link targets. */
25
+ linksFp: string;
26
+ /** Only meaningful when `hash` is a `body:` fallback (no server hash). */
27
+ fmFp?: string;
28
+ rev?: string | null;
29
+ }
30
+ export declare function encodeEntryDigest(d: EntryDigest): string;
31
+ /** Parse a stored digest; `null` for legacy/foreign digests (forces a re-hydrate). */
32
+ export declare function parseEntryDigest(digest: string | number | undefined | null): EntryDigest | null;
33
+ export declare const CONTENT_HASH_FIELD = "$content_hash";
34
+ /**
35
+ * Add `$content_hash` to the top-level projection of an OQX query.
36
+ *
37
+ * OQX fixes clause order (`select … from … where …`) and only `select` may drop
38
+ * its keyword, so the projection is always at the very start of the string:
39
+ *
40
+ * - `select a, b from docs …` → `select $content_hash, a, b from docs …`
41
+ * - `a, b from docs …` → `$content_hash, a, b from docs …`
42
+ * - `from docs …` → `select $content_hash from docs …`
43
+ *
44
+ * Queries that already mention `$content_hash`, or scalar `$repo.` forms, are
45
+ * returned unchanged. Returns `{ query, injected }` so the caller can strip the
46
+ * field from hit projections again (it must not leak into entry `data`).
47
+ */
48
+ export declare function withContentHash(query: string): {
49
+ query: string;
50
+ injected: boolean;
51
+ };
52
+ /** Read the projected hash off a hit; `null` when absent or malformed. */
53
+ export declare function hitContentHash(hit: Record<string, unknown>): string | null;
54
+ /**
55
+ * Fingerprint of a hit's extra projections (everything but `id`/`path` and an
56
+ * injected `$content_hash`). These merge into entry `data`, so a change in e.g.
57
+ * `outs: doc.out collect { … }` must re-map the entry even when content didn't move.
58
+ */
59
+ export declare function hitProjectionsFingerprint(hit: Record<string, unknown>, stripContentHash: boolean): string;
60
+ /**
61
+ * Fingerprint of the hrefs this doc's body may be rewritten to: its live
62
+ * out-edges into the collection. A doc with no such edges falls back to path
63
+ * resolution against the whole index (see `syncEntries`), so it is pinned to
64
+ * the whole-index fingerprint instead.
65
+ */
66
+ export declare function linksFingerprint(srcDocId: string, edges: OutEdge[], index: HrefIndex, wholeIndexFp: string): string;
67
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAKrD,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAYxD;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,GACzC,WAAW,GAAG,IAAI,CAsBpB;AAED,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAoBnF;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAG1E;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,gBAAgB,EAAE,OAAO,GACxB,MAAM,CAQR;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EAAE,EAChB,KAAK,EAAE,SAAS,EAChB,YAAY,EAAE,MAAM,GACnB,MAAM,CAcR"}
package/dist/digest.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Hash-first sync support: the pieces that let `syncEntries` decide, from a
3
+ * lean OQX hit alone, whether a document needs to be fetched or re-rendered.
4
+ *
5
+ * - {@link withContentHash} projects `$content_hash` onto the user's query so
6
+ * every hit carries the server's whole-file hash (frontmatter included).
7
+ * - {@link encodeEntryDigest} / {@link parseEntryDigest} store everything the
8
+ * next sync needs to skip a doc — hash, path, slug, href, projection and link
9
+ * fingerprints — inside the Astro data-store `digest` string, so no extra
10
+ * state lives outside Astro's own persistence.
11
+ * - {@link linksFingerprint} pins a doc's rewritten body to the hrefs of the
12
+ * docs it links to, so a new/removed/moved doc only invalidates its linkers.
13
+ */
14
+ import { digestFingerprint } from "./map.js";
15
+ /** Version tag; bump when the digest shape changes so old stores re-hydrate once. */
16
+ const DIGEST_PREFIX = "omg2:";
17
+ export function encodeEntryDigest(d) {
18
+ const ordered = {
19
+ h: d.hash,
20
+ p: d.path,
21
+ s: d.slug,
22
+ u: d.href,
23
+ q: d.hitsFp,
24
+ l: d.linksFp,
25
+ };
26
+ if (d.fmFp !== undefined)
27
+ ordered.fm = d.fmFp;
28
+ if (d.rev !== undefined && d.rev !== null)
29
+ ordered.r = d.rev;
30
+ return `${DIGEST_PREFIX}${JSON.stringify(ordered)}`;
31
+ }
32
+ /** Parse a stored digest; `null` for legacy/foreign digests (forces a re-hydrate). */
33
+ export function parseEntryDigest(digest) {
34
+ if (typeof digest !== "string" || !digest.startsWith(DIGEST_PREFIX))
35
+ return null;
36
+ try {
37
+ const raw = JSON.parse(digest.slice(DIGEST_PREFIX.length));
38
+ const str = (k) => (typeof raw[k] === "string" ? raw[k] : null);
39
+ const hash = str("h");
40
+ const path = str("p");
41
+ const slug = str("s");
42
+ if (hash === null || path === null || slug === null)
43
+ return null;
44
+ return {
45
+ hash,
46
+ path,
47
+ slug,
48
+ href: str("u") ?? "",
49
+ hitsFp: str("q") ?? "",
50
+ linksFp: str("l") ?? "",
51
+ ...(str("fm") !== null ? { fmFp: str("fm") } : {}),
52
+ ...(str("r") !== null ? { rev: str("r") } : {}),
53
+ };
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ export const CONTENT_HASH_FIELD = "$content_hash";
60
+ /**
61
+ * Add `$content_hash` to the top-level projection of an OQX query.
62
+ *
63
+ * OQX fixes clause order (`select … from … where …`) and only `select` may drop
64
+ * its keyword, so the projection is always at the very start of the string:
65
+ *
66
+ * - `select a, b from docs …` → `select $content_hash, a, b from docs …`
67
+ * - `a, b from docs …` → `$content_hash, a, b from docs …`
68
+ * - `from docs …` → `select $content_hash from docs …`
69
+ *
70
+ * Queries that already mention `$content_hash`, or scalar `$repo.` forms, are
71
+ * returned unchanged. Returns `{ query, injected }` so the caller can strip the
72
+ * field from hit projections again (it must not leak into entry `data`).
73
+ */
74
+ export function withContentHash(query) {
75
+ const trimmed = query.trimStart();
76
+ const lead = query.slice(0, query.length - trimmed.length);
77
+ if (/\$content_hash\b/.test(trimmed))
78
+ return { query, injected: false };
79
+ if (/^\$repo\./.test(trimmed))
80
+ return { query, injected: false };
81
+ if (/^select\s/i.test(trimmed)) {
82
+ return {
83
+ query: `${lead}select ${CONTENT_HASH_FIELD}, ${trimmed.slice("select".length).trimStart()}`,
84
+ injected: true,
85
+ };
86
+ }
87
+ if (/^from\s/i.test(trimmed)) {
88
+ return { query: `${lead}select ${CONTENT_HASH_FIELD} ${trimmed}`, injected: true };
89
+ }
90
+ // Bare projection list (`$path, title from docs …`).
91
+ if (/\sfrom\s/i.test(trimmed)) {
92
+ return { query: `${lead}${CONTENT_HASH_FIELD}, ${trimmed}`, injected: true };
93
+ }
94
+ return { query, injected: false };
95
+ }
96
+ /** Read the projected hash off a hit; `null` when absent or malformed. */
97
+ export function hitContentHash(hit) {
98
+ const v = hit[CONTENT_HASH_FIELD];
99
+ return typeof v === "string" && v.length > 0 ? v : null;
100
+ }
101
+ /**
102
+ * Fingerprint of a hit's extra projections (everything but `id`/`path` and an
103
+ * injected `$content_hash`). These merge into entry `data`, so a change in e.g.
104
+ * `outs: doc.out collect { … }` must re-map the entry even when content didn't move.
105
+ */
106
+ export function hitProjectionsFingerprint(hit, stripContentHash) {
107
+ const extras = {};
108
+ for (const [k, v] of Object.entries(hit)) {
109
+ if (k === "id" || k === "path")
110
+ continue;
111
+ if (stripContentHash && k === CONTENT_HASH_FIELD)
112
+ continue;
113
+ extras[k] = v;
114
+ }
115
+ return digestFingerprint(extras);
116
+ }
117
+ /**
118
+ * Fingerprint of the hrefs this doc's body may be rewritten to: its live
119
+ * out-edges into the collection. A doc with no such edges falls back to path
120
+ * resolution against the whole index (see `syncEntries`), so it is pinned to
121
+ * the whole-index fingerprint instead.
122
+ */
123
+ export function linksFingerprint(srcDocId, edges, index, wholeIndexFp) {
124
+ const parts = [];
125
+ let hasAnyDocEdge = false;
126
+ for (const e of edges) {
127
+ if (e.src !== srcDocId)
128
+ continue;
129
+ if (!e.dst || e.dst.startsWith("phantom:") || e.dst.startsWith("x_"))
130
+ continue;
131
+ hasAnyDocEdge = true;
132
+ const href = index.byDocId.get(e.dst);
133
+ if (href !== undefined)
134
+ parts.push(`${e.dst}=${href}`);
135
+ }
136
+ if (parts.length > 0)
137
+ return parts.sort().join("|");
138
+ // Edges exist but none land in this collection, or no edges at all: the
139
+ // rewrite is gated by path resolution over the full index.
140
+ return hasAnyDocEdge ? `idx:${wholeIndexFp}` : "";
141
+ }
142
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  export { omgLoader } from "./loader.js";
2
- export type { OmgLoaderOptions, OmgLoaderBaseOptions, OmgLoaderLocalOptions, OmgLoaderRemoteOptions, } from "./loader.js";
2
+ export type { OmgLoaderOptions, OmgLoaderBaseOptions, OmgLoaderLocalOptions, OmgLoaderRemoteOptions, TransportOptions, } from "./loader.js";
3
+ export { omgLiveLoader, OmgLiveError } from "./live.js";
4
+ export type { OmgLiveLoaderOptions, OmgLiveCollectionFilter, OmgLiveEntryFilter, OmgLiveEntryData, OmgLiveErrorCode, OmgLiveLoader, } from "./live.js";
5
+ export { outEdgesQuery } from "./transport.js";
3
6
  export type { Transport, QueryHit, HydratedDoc, QueryOptions, HydrateOptions, DocOutEdge } from "./transport.js";
4
7
  export { createLocalTransport, LocalTransport } from "./local.js";
5
8
  export type { LocalTransportOptions } from "./local.js";
6
9
  export { createRemoteTransport, RemoteTransport, parseHeaderLine, resolveHeaders, } from "./remote.js";
7
- export type { RemoteTransportOptions } from "./remote.js";
8
- export type { WatchOption } from "./watch.js";
10
+ export type { RemoteTransportOptions, ToolClient } from "./remote.js";
11
+ export type { WatchOption, SyncResult } from "./watch.js";
12
+ export { withContentHash, encodeEntryDigest, parseEntryDigest } from "./digest.js";
13
+ export type { EntryDigest } from "./digest.js";
9
14
  export { defaultSlug, stripFrontmatter, mapDoc, mergeHitProjections, contentHashOf } from "./map.js";
10
15
  export type { SlugContext, MappedEntry } from "./map.js";
11
16
  export type { OmgEntryIntrinsics } from "./schema.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjH,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACrG,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EACL,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE7E,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,oBAAoB,EACpB,aAAa,EACb,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EACV,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,GACd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjH,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEtE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACrG,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EACL,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE7E,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,oBAAoB,EACpB,aAAa,EACb,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  export { omgLoader } from "./loader.js";
2
+ export { omgLiveLoader, OmgLiveError } from "./live.js";
3
+ export { outEdgesQuery } from "./transport.js";
2
4
  export { createLocalTransport, LocalTransport } from "./local.js";
3
5
  export { createRemoteTransport, RemoteTransport, parseHeaderLine, resolveHeaders, } from "./remote.js";
6
+ export { withContentHash, encodeEntryDigest, parseEntryDigest } from "./digest.js";
4
7
  export { defaultSlug, stripFrontmatter, mapDoc, mergeHitProjections, contentHashOf } from "./map.js";
5
8
  export { defaultHref, buildHrefIndex, rewriteMarkdownLinks, resolveLinkHref, canonicalLinkPath, splitDestination, docDirOf, } from "./links.js";
6
9
  export { createMcpHttpServer, createPublicationServer, } from "./server.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AASxC,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIrG,OAAO,EACL,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GACT,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AASxC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAUxD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGnF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIrG,OAAO,EACL,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GACT,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC"}
package/dist/live.d.ts ADDED
@@ -0,0 +1,97 @@
1
+ import type { LiveLoader } from "astro/loaders";
2
+ import type { AstroMarkdownOptions } from "@astrojs/markdown-remark";
3
+ import type { Transport } from "./transport.js";
4
+ import { type SlugContext } from "./map.js";
5
+ import { type HrefContext } from "./links.js";
6
+ export interface OmgLiveLoaderOptions {
7
+ /** Streamable HTTP MCP endpoint (same as `omg … --server <url>`). Selects the remote transport. */
8
+ url?: string;
9
+ /** Convenience bearer token → `Authorization: Bearer …` if unset. */
10
+ token?: string;
11
+ /** Extra headers on every MCP request (CLI `-H` as a map). */
12
+ headers?: Record<string, string>;
13
+ /** Extra headers as CLI `-H` strings: `["X-Foo: bar"]`. */
14
+ headerLines?: string[];
15
+ /** Path to the omgbase workspace root (directory containing `.omgbase/`). Selects the local transport. */
16
+ workspace?: string;
17
+ /** Local only: skip the freshness sweep before reads (default false). */
18
+ stale?: boolean;
19
+ /** Repo slug (local workspace or remote multi-repo server). */
20
+ repo?: string;
21
+ /** Inject a pre-built transport (tests, or sharing one connection between loaders). */
22
+ transport?: Transport;
23
+ /** Default OQX for `loadCollection`. Hits must be documents. */
24
+ query: string;
25
+ /** Default result limit for `loadCollection`. */
26
+ limit?: number;
27
+ /** Override slug generation. Default: path with `.md` stripped. */
28
+ slug?: (ctx: SlugContext) => string;
29
+ /**
30
+ * Site href for a doc; used to rewrite markdown links in hydrated bodies.
31
+ * `false` disables rewriting. Default: `/${slug}`.
32
+ */
33
+ href?: false | ((ctx: HrefContext) => string);
34
+ /** Inverse of the default slug, for `loadEntry({ slug })`. Default: `(slug) => `${slug}.md``. */
35
+ pathForSlug?: (slug: string) => string;
36
+ /** Hydrate bodies for collection entries too (default false: collection entries are lean). */
37
+ hydrate?: boolean;
38
+ /** Options for `@astrojs/markdown-remark`'s `createMarkdownProcessor` (e.g. `shikiConfig`). */
39
+ markdown?: AstroMarkdownOptions;
40
+ /** Replace the markdown renderer entirely. */
41
+ render?: (markdown: string, ctx: {
42
+ docId: string;
43
+ path: string;
44
+ }) => Promise<{
45
+ html: string;
46
+ }>;
47
+ }
48
+ /** `getLiveCollection(name, filter)` shape. Each field falls back to the loader option. */
49
+ export type OmgLiveCollectionFilter = {
50
+ query?: string;
51
+ limit?: number;
52
+ hydrate?: boolean;
53
+ };
54
+ /** `getLiveEntry(name, filter)` shape. Exactly one key must be set. */
55
+ export type OmgLiveEntryFilter = {
56
+ id?: string;
57
+ path?: string;
58
+ slug?: string;
59
+ };
60
+ export type OmgLiveErrorCode = "not_found" | "invalid_filter" | "query_failed" | "hydrate_failed" | "render_failed";
61
+ export declare class OmgLiveError extends Error {
62
+ readonly code: OmgLiveErrorCode;
63
+ constructor(code: OmgLiveErrorCode, message: string, options?: {
64
+ cause?: unknown;
65
+ });
66
+ }
67
+ /**
68
+ * Entry `data` for live collections. Lean entries carry the hit projections
69
+ * plus intrinsics; hydrated entries add frontmatter, `contentHash` and `body`.
70
+ */
71
+ export interface OmgLiveEntryData {
72
+ path: string;
73
+ docId: string;
74
+ slug: string;
75
+ /** Alias of the `$updated_at` projection when the query selects it. */
76
+ updatedAt?: unknown;
77
+ /** Frontmatter `title`, else `$title` (computed or projected). */
78
+ title?: unknown;
79
+ /** Hydrated only: markdown after frontmatter, with inter-doc links rewritten. */
80
+ body?: string;
81
+ contentHash?: string | null;
82
+ [key: string]: unknown;
83
+ }
84
+ export type OmgLiveLoader = LiveLoader<OmgLiveEntryData, OmgLiveEntryFilter, OmgLiveCollectionFilter, OmgLiveError>;
85
+ /**
86
+ * Astro live collection loader backed by omgbase (SSR, request time).
87
+ *
88
+ * `loadCollection` runs an OQX query and returns one lean entry per hit (id,
89
+ * path, slug and the query's projections). `loadEntry` hydrates a single doc by
90
+ * id, path or slug, rewrites its markdown links to the site hrefs of the docs
91
+ * omg says it links to, and renders it to HTML. Pass `hydrate: true` (option or
92
+ * filter) to get the same hydrated shape for every collection entry.
93
+ *
94
+ * One transport is connected lazily per loader and reused across requests.
95
+ */
96
+ export declare function omgLiveLoader(opts: OmgLiveLoaderOptions): OmgLiveLoader;
97
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}
package/dist/live.js ADDED
@@ -0,0 +1,254 @@
1
+ import { resolveTransport } from "./loader.js";
2
+ import { defaultSlug, mapDoc, mergeHitProjections } from "./map.js";
3
+ import { buildHrefIndex, defaultHref, rewriteMarkdownLinks, } from "./links.js";
4
+ export class OmgLiveError extends Error {
5
+ code;
6
+ constructor(code, message, options) {
7
+ super(message, options);
8
+ this.name = "OmgLiveError";
9
+ this.code = code;
10
+ }
11
+ }
12
+ const defaultPathForSlug = (slug) => `${slug}.md`;
13
+ function message(err) {
14
+ return err instanceof Error ? err.message : String(err);
15
+ }
16
+ /** `$updated_at` as a `Date`, when the value is a parseable string or number. */
17
+ function asDate(value) {
18
+ if (typeof value !== "string" && typeof value !== "number")
19
+ return undefined;
20
+ const d = new Date(value);
21
+ return Number.isNaN(d.getTime()) ? undefined : d;
22
+ }
23
+ function lastModifiedOf(values) {
24
+ let max;
25
+ for (const v of values) {
26
+ const d = asDate(v);
27
+ if (d && (!max || d > max))
28
+ max = d;
29
+ }
30
+ return max;
31
+ }
32
+ /** Lazily create the `@astrojs/markdown-remark` processor once per loader. */
33
+ function defaultRenderer(markdown) {
34
+ let processor = null;
35
+ return async (body) => {
36
+ if (!processor) {
37
+ processor = import("@astrojs/markdown-remark").then((m) => m.createMarkdownProcessor(markdown ?? {}));
38
+ processor.catch(() => {
39
+ processor = null; // let the next request retry instead of caching the failure
40
+ });
41
+ }
42
+ const result = await (await processor).render(body);
43
+ return { html: result.code };
44
+ };
45
+ }
46
+ /**
47
+ * Astro live collection loader backed by omgbase (SSR, request time).
48
+ *
49
+ * `loadCollection` runs an OQX query and returns one lean entry per hit (id,
50
+ * path, slug and the query's projections). `loadEntry` hydrates a single doc by
51
+ * id, path or slug, rewrites its markdown links to the site hrefs of the docs
52
+ * omg says it links to, and renders it to HTML. Pass `hydrate: true` (option or
53
+ * filter) to get the same hydrated shape for every collection entry.
54
+ *
55
+ * One transport is connected lazily per loader and reused across requests.
56
+ */
57
+ export function omgLiveLoader(opts) {
58
+ const slugFn = opts.slug ?? defaultSlug;
59
+ const hrefFn = opts.href === false ? false : (opts.href ?? defaultHref);
60
+ const pathForSlug = opts.pathForSlug ?? defaultPathForSlug;
61
+ const render = opts.render ?? defaultRenderer(opts.markdown);
62
+ const repoArg = opts.repo !== undefined ? { repo: opts.repo } : {};
63
+ let transport = null;
64
+ const getTransport = () => {
65
+ transport ??= resolveTransport(opts, "omgLiveLoader");
66
+ return transport;
67
+ };
68
+ const leanSlug = (hit) => slugFn({ path: hit.path, docId: hit.id, properties: {} });
69
+ const leanEntry = (hit) => {
70
+ const slug = leanSlug(hit);
71
+ const merged = mergeHitProjections({ path: hit.path, docId: hit.id, slug }, hit);
72
+ const data = { ...merged, path: hit.path, docId: hit.id, slug };
73
+ const lastModified = asDate(hit.$updated_at);
74
+ return {
75
+ id: hit.id,
76
+ data,
77
+ ...(lastModified ? { cacheHint: { lastModified } } : {}),
78
+ };
79
+ };
80
+ /** Out-edges to documents for `ids`; unavailable edges degrade to "no rewrite". */
81
+ const edgesFor = async (ids) => {
82
+ if (hrefFn === false)
83
+ return [];
84
+ const t = getTransport();
85
+ if (!t.outEdges)
86
+ return [];
87
+ try {
88
+ return await t.outEdges({ ids, ...repoArg });
89
+ }
90
+ catch {
91
+ return [];
92
+ }
93
+ };
94
+ /** Href index over the destinations of `edges`, keyed by omg identity. */
95
+ const hrefIndexFor = (edges) => {
96
+ const entries = [];
97
+ const seen = new Set();
98
+ if (hrefFn !== false) {
99
+ for (const e of edges) {
100
+ if (!e.dstPath || seen.has(e.dst))
101
+ continue;
102
+ seen.add(e.dst);
103
+ const ctx = { path: e.dstPath, docId: e.dst, properties: {} };
104
+ entries.push({
105
+ docId: e.dst,
106
+ path: e.dstPath,
107
+ href: hrefFn({ ...ctx, slug: slugFn(ctx) }),
108
+ });
109
+ }
110
+ }
111
+ return buildHrefIndex(entries);
112
+ };
113
+ const hydratedEntry = async (doc, hit, edges) => {
114
+ const mapped = mapDoc(doc, slugFn);
115
+ const merged = hit ? mergeHitProjections(mapped.data, hit) : mapped.data;
116
+ let body = mapped.body;
117
+ if (hrefFn !== false) {
118
+ const own = edges.filter((e) => e.src === doc.id);
119
+ body = rewriteMarkdownLinks(body, {
120
+ srcPath: doc.path,
121
+ hrefIndex: hrefIndexFor(own),
122
+ allowedDstIds: new Set(own.map((e) => e.dst)),
123
+ });
124
+ }
125
+ let html;
126
+ try {
127
+ ({ html } = await render(body, { docId: doc.id, path: doc.path }));
128
+ }
129
+ catch (err) {
130
+ return {
131
+ error: new OmgLiveError("render_failed", `omgbase: rendering ${doc.path} (${doc.id}) failed: ${message(err)}`, { cause: err }),
132
+ };
133
+ }
134
+ const data = {
135
+ ...merged,
136
+ path: doc.path,
137
+ docId: doc.id,
138
+ slug: String(mapped.data.slug),
139
+ body,
140
+ };
141
+ const lastModified = asDate(hit?.$updated_at ?? doc.properties.computed?.$updated_at);
142
+ return {
143
+ id: doc.id,
144
+ data,
145
+ rendered: { html },
146
+ ...(lastModified ? { cacheHint: { lastModified } } : {}),
147
+ };
148
+ };
149
+ const hydrate = async (ids) => {
150
+ try {
151
+ return await getTransport().hydrate({ ids, ...repoArg });
152
+ }
153
+ catch (err) {
154
+ return {
155
+ error: new OmgLiveError("hydrate_failed", `omgbase: docs_get_many failed: ${message(err)}`, {
156
+ cause: err,
157
+ }),
158
+ };
159
+ }
160
+ };
161
+ const query = async (q, limit) => {
162
+ try {
163
+ return await getTransport().query({
164
+ query: q,
165
+ ...(limit !== undefined ? { limit } : {}),
166
+ ...repoArg,
167
+ });
168
+ }
169
+ catch (err) {
170
+ return {
171
+ error: new OmgLiveError("query_failed", `omgbase: query failed: ${message(err)}`, {
172
+ cause: err,
173
+ }),
174
+ };
175
+ }
176
+ };
177
+ return {
178
+ name: "@omgbase/astro",
179
+ async loadCollection({ filter }) {
180
+ const q = filter?.query ?? opts.query;
181
+ const limit = filter?.limit ?? opts.limit;
182
+ const wantBodies = filter?.hydrate ?? opts.hydrate ?? false;
183
+ const queried = await query(q, limit);
184
+ if ("error" in queried)
185
+ return queried;
186
+ // One entry per doc even if the query yields a doc twice.
187
+ const hits = [];
188
+ const seen = new Set();
189
+ for (const hit of queried) {
190
+ if (seen.has(hit.id))
191
+ continue;
192
+ seen.add(hit.id);
193
+ hits.push(hit);
194
+ }
195
+ const cacheHint = (() => {
196
+ const lastModified = lastModifiedOf(hits.map((h) => h.$updated_at));
197
+ return lastModified ? { cacheHint: { lastModified } } : {};
198
+ })();
199
+ if (!wantBodies) {
200
+ return { entries: hits.map(leanEntry), ...cacheHint };
201
+ }
202
+ const ids = hits.map((h) => h.id);
203
+ const docs = await hydrate(ids);
204
+ if ("error" in docs)
205
+ return docs;
206
+ const byId = new Map(docs.map((d) => [d.id, d]));
207
+ const edges = await edgesFor(ids);
208
+ const entries = [];
209
+ for (const hit of hits) {
210
+ const doc = byId.get(hit.id);
211
+ if (!doc)
212
+ continue; // deleted between query and hydrate
213
+ const entry = await hydratedEntry(doc, hit, edges);
214
+ if ("error" in entry)
215
+ return entry;
216
+ entries.push(entry);
217
+ }
218
+ return { entries, ...cacheHint };
219
+ },
220
+ async loadEntry({ filter }) {
221
+ const given = ["id", "path", "slug"].filter((k) => filter?.[k] !== undefined);
222
+ const key = given[0];
223
+ const value = key ? filter[key] : undefined;
224
+ if (given.length !== 1 || !key || typeof value !== "string" || value.length === 0) {
225
+ return {
226
+ error: new OmgLiveError("invalid_filter", "omgbase: loadEntry filter must set exactly one of `id`, `path` or `slug`"),
227
+ };
228
+ }
229
+ let id;
230
+ let hit;
231
+ if (key === "id") {
232
+ id = value;
233
+ }
234
+ else {
235
+ const path = (key === "path" ? value : pathForSlug(value)).replace(/^\//, "");
236
+ const hits = await query(`select $path, $title, $updated_at from docs where $path == ${JSON.stringify(path)}`, 1);
237
+ if ("error" in hits)
238
+ return hits;
239
+ hit = hits[0];
240
+ if (!hit)
241
+ return undefined;
242
+ id = hit.id;
243
+ }
244
+ const docs = await hydrate([id]);
245
+ if ("error" in docs)
246
+ return docs;
247
+ const doc = docs[0];
248
+ if (!doc)
249
+ return undefined;
250
+ return hydratedEntry(doc, hit, await edgesFor([doc.id]));
251
+ },
252
+ };
253
+ }
254
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}