@seedprotocol/query 0.6.7 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.node.js +1 -1
- package/dist/parseEasRelationPropertyName.d.ts +2 -0
- package/dist/parseEasRelationPropertyName.d.ts.map +1 -1
- package/dist/{src-BoSE9m_G.js → src-D2LHcfAN.js} +2 -2
- package/dist/src-D2LHcfAN.js.map +1 -0
- package/package.json +3 -3
- package/dist/src-BoSE9m_G.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { a as e, i as t, o as n, r, t as i } from "./types-DHRoT30t.js";
|
|
2
|
-
import { A as a, B as o, C as s, D as c, E as l, F as u, G as d, H as f, I as p, J as m, K as h, L as g, M as _, N as v, O as y, P as b, R as x, S, T as C, U as w, V as T, W as E, X as D, Y as O, Z as k, _ as A, a as j, b as M, c as N, d as P, f as F, g as I, i as L, j as R, k as z, l as B, m as V, n as H, o as U, p as W, q as G, r as K, s as q, t as J, u as Y, v as X, w as Z, x as Q, y as $, z as ee } from "./src-
|
|
2
|
+
import { A as a, B as o, C as s, D as c, E as l, F as u, G as d, H as f, I as p, J as m, K as h, L as g, M as _, N as v, O as y, P as b, R as x, S, T as C, U as w, V as T, W as E, X as D, Y as O, Z as k, _ as A, a as j, b as M, c as N, d as P, f as F, g as I, i as L, j as R, k as z, l as B, m as V, n as H, o as U, p as W, q as G, r as K, s as q, t as J, u as Y, v as X, w as Z, x as Q, y as $, z as ee } from "./src-D2LHcfAN.js";
|
|
3
3
|
export { V as CacheManager, r as DEFAULT_ARWEAVE_HOST, _ as FEED_RICH_BODY_STORAGE_SCHEMAS, v as RICH_BODY_STORAGE_SCHEMAS, A as applyChangelogFilters, I as assembleSeedChangelog, s as assembleSeeds, i as buildAssembleOptionsKey, X as buildFlatSnapshotFromProperties, $ as changelogValuesEqual, U as clearLocalQuerySource, Y as createQueryCacheManager, Z as createRemoteQueryDataSource, M as decodePropertyAttestation, Q as diffPropertyAttestations, S as diffVersionSnapshots, h as enrichImageSeedClone, G as enrichImageSeedCloneForFeed, b as feedRichBodyModelPriority, k as getArweaveUrlForTransaction, u as getFeedFieldStorageModels, p as getFeedListElementStorageModels, g as getFieldStorageModels, x as getListElementStorageModels, P as getQueryCacheManager, q as getRegisteredLocalQuerySource, C as getRemoteQueryDataSource, J as getSeed, N as hasLocalQuerySource, z as hydrateArweaveRichTextInFeedItems, a as hydrateArweaveRichTextInItems, t as initializeQueryPlatform, R as isArweaveTransactionGatewayUrl, ee as isFeedRichBodyStorageSchema, e as isQueryPlatformInitialized, o as isRichBodyStorageSchema, W as loadQueryCacheConfig, L as normalizeSourceMode, c as parseEasPropertyMetadata, y as parseEasPropertyMetadataForFeed, l as parseEasRelationPropertyName, m as publicListRelationPropertyKey, H as queryBySchema, K as queryBySchemaForMonth, B as registerLocalQuerySource, F as resetQueryCacheManager, j as resolveQuerySource, T as richBodyModelPriority, f as setFeedFieldStorageModel, w as setFeedListElementStorageModels, E as setFieldStorageModel, d as setListElementStorageModels, O as stripListRelationStorageAliasesForPublicKey, n as teardownQueryPlatform, D as tryCoerceJsonStringArray };
|
package/dist/index.node.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as e, i as t, o as n, r as ee, t as r } from "./types-DHRoT30t.js";
|
|
2
|
-
import { A as i, B as a, C as o, D as s, E as c, F as l, G as u, H as d, I as f, J as p, K as m, L as h, M as g, N as _, O as v, P as y, R as b, S as x, T as S, U as C, V as w, W as T, X as te, Y as E, Z as D, _ as O, a as k, b as A, c as j, d as M, f as N, g as P, h as F, i as I, j as L, k as R, l as z, m as B, n as V, o as H, p as U, q as W, r as G, s as K, t as q, u as J, v as Y, w as X, x as Z, y as Q, z as ne } from "./src-
|
|
2
|
+
import { A as i, B as a, C as o, D as s, E as c, F as l, G as u, H as d, I as f, J as p, K as m, L as h, M as g, N as _, O as v, P as y, R as b, S as x, T as S, U as C, V as w, W as T, X as te, Y as E, Z as D, _ as O, a as k, b as A, c as j, d as M, f as N, g as P, h as F, i as I, j as L, k as R, l as z, m as B, n as V, o as H, p as U, q as W, r as G, s as K, t as q, u as J, v as Y, w as X, x as Z, y as Q, z as ne } from "./src-D2LHcfAN.js";
|
|
3
3
|
import { t as $ } from "./FileCache-BZ2cHsU3.js";
|
|
4
4
|
//#region src/index.node.ts
|
|
5
5
|
F((e) => new $(e));
|
|
@@ -5,6 +5,8 @@ export type ParsedEasRelationPropertyName = {
|
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
7
7
|
* Parse EAS relation property naming: `{singular}_{model}_id` or `{singular}_{model}_ids`.
|
|
8
|
+
* Lists map back to the plural schema key the same way publicListRelationPropertyKey does
|
|
9
|
+
* (`author_identity_ids` → `authors`, `staff_identity_ids` → `staff`); single relations keep the singular.
|
|
8
10
|
* Returns null when the name does not match the expected shape.
|
|
9
11
|
*/
|
|
10
12
|
export declare function parseEasRelationPropertyName(easPropertyName: string): ParsedEasRelationPropertyName | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseEasRelationPropertyName.d.ts","sourceRoot":"","sources":["../src/parseEasRelationPropertyName.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parseEasRelationPropertyName.d.ts","sourceRoot":"","sources":["../src/parseEasRelationPropertyName.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,eAAe,EAAE,MAAM,GACtB,6BAA6B,GAAG,IAAI,CAUtC"}
|
|
@@ -195,7 +195,7 @@ function N(e) {
|
|
|
195
195
|
if (!t || !n) return null;
|
|
196
196
|
let i = r === "ids";
|
|
197
197
|
return {
|
|
198
|
-
propertyName: t.endsWith("s") ? t : t
|
|
198
|
+
propertyName: i ? t.endsWith("s") ? t : f(t) : t,
|
|
199
199
|
modelName: n,
|
|
200
200
|
isList: i
|
|
201
201
|
};
|
|
@@ -982,4 +982,4 @@ async function Je(n, r, i, a) {
|
|
|
982
982
|
//#endregion
|
|
983
983
|
export { j as A, T as B, H as C, M as D, N as E, ae as F, A as G, se as H, oe as I, _ as J, b as K, D as L, ne as M, x as N, ge as O, ie as P, O as R, Ee as S, I as T, ce as U, E as V, k as W, y as X, v as Y, g as Z, Oe as _, X as a, W as b, He as c, J as d, Le as f, ke as g, Fe as h, Z as i, de as j, he as k, ze as l, G as m, Ke as n, Be as o, K as p, te as q, Je as r, Ve as s, qe as t, Re as u, Te as v, P as w, De as x, U as y, re as z };
|
|
984
984
|
|
|
985
|
-
//# sourceMappingURL=src-
|
|
985
|
+
//# sourceMappingURL=src-D2LHcfAN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-D2LHcfAN.js","names":[],"sources":["../src/arweaveUrl.ts","../src/listRelationKey.ts","../src/imageRelationEnrichment.ts","../src/fieldStorageModel.ts","../src/hydrateArweaveRichText.ts","../src/parseEasPropertyMetadata.ts","../src/parseEasRelationPropertyName.ts","../src/source/remote.ts","../src/assembleSeeds.ts","../src/changelog.ts","../src/assembleChangelog.ts","../src/cache/etag.ts","../src/cache/MemoryCache.ts","../src/cache/CacheManager.ts","../src/cache/config.ts","../src/cache/index.ts","../src/source/registry.ts","../src/source/resolve.ts","../src/api.ts"],"sourcesContent":["import { BaseArweaveClient } from '@seedprotocol/arweave'\n\n/**\n * Builds an Arweave gateway URL for a transaction ID (no `/raw` segment).\n */\nexport function getArweaveUrlForTransaction(transactionId: string): string {\n return `https://${BaseArweaveClient.getHost()}/${transactionId}`\n}\n","import pluralize from 'pluralize'\n\n/** Matches SDK list storage: singular(schemaKey) + PascalCase(ref) + \"Ids\", e.g. authorIdentityIds → authors */\nconst CAMEL_LIST_RELATION_IDS = /^(.+?)([A-Z][a-zA-Z]+)Ids$/\n\n/**\n * Maps list-relation storage / wire names to schema-facing plural keys (e.g. `authorIdentityIds` → `authors`).\n * Non-matching keys are returned unchanged.\n */\nexport function publicListRelationPropertyKey(propertyKey: string): string {\n const camel = CAMEL_LIST_RELATION_IDS.exec(propertyKey)\n if (camel) {\n const singularPart = camel[1]\n if (singularPart) return pluralize(singularPart)\n }\n if (propertyKey.endsWith('_ids')) {\n const base = propertyKey.slice(0, -4)\n const segments = base.split('_').filter(Boolean)\n if (segments.length >= 2) {\n const singularProperty = segments[0]!\n return singularProperty.endsWith('s') ? singularProperty : pluralize(singularProperty)\n }\n return pluralize(base)\n }\n return propertyKey\n}\n\n/**\n * Removes keys that are storage aliases for the same list relation as `publicKey`\n * (e.g. delete `authorIdentityIds` when `authors` is the canonical field).\n */\nexport function stripListRelationStorageAliasesForPublicKey(\n item: Record<string, unknown>,\n publicKey: string,\n): void {\n for (const k of Object.keys(item)) {\n if (k === publicKey) continue\n if (publicListRelationPropertyKey(k) === publicKey) {\n delete item[k]\n }\n }\n}\n\n/** If value is a JSON array string from legacy assembly, parse to string[]. */\nexport function tryCoerceJsonStringArray(value: unknown): unknown {\n if (Array.isArray(value)) return value\n if (typeof value !== 'string') return value\n const s = value.trim()\n if (!s.startsWith('[')) return value\n try {\n const parsed = JSON.parse(s) as unknown\n if (Array.isArray(parsed)) return parsed\n } catch {\n // keep original\n }\n return value\n}\n","import { getArweaveUrlForTransaction } from './arweaveUrl.js'\n\n/**\n * Adds `arweaveUrl` to an assembled Image seed clone when `storageTransactionId`\n * (or snake_case) is present.\n */\nexport function enrichImageSeedClone(clone: Record<string, unknown>): void {\n const txId = (clone.storageTransactionId ?? clone.storage_transaction_id) as\n | string\n | undefined\n if (txId && typeof txId === 'string' && txId.trim()) {\n try {\n clone.arweaveUrl = getArweaveUrlForTransaction(txId.trim())\n } catch {\n // keep clone without arweaveUrl\n }\n }\n}\n\n/** @deprecated Use {@link enrichImageSeedClone} */\nexport const enrichImageSeedCloneForFeed = enrichImageSeedClone\n","/** Related Seed schema names (lowercased) used as primary rich-body sources. */\nexport const RICH_BODY_STORAGE_SCHEMAS = new Set(['html', 'file', 'json'])\n\n/** @deprecated Alias for {@link RICH_BODY_STORAGE_SCHEMAS} (feed key compatibility). */\nexport const FEED_RICH_BODY_STORAGE_SCHEMAS = RICH_BODY_STORAGE_SCHEMAS\n\n/** Kept as `_feedFieldStorageModels` for feed/RSS pickers in Phase 1. */\nconst FIELD_MODELS_KEY = '_feedFieldStorageModels' as const\nconst LIST_MODELS_KEY = '_feedListElementStorageModels' as const\n\nexport type FieldStorageModels = Record<string, string>\nexport type ListElementStorageModels = Record<string, string[]>\n\n/** @deprecated Use {@link FieldStorageModels} */\nexport type FeedFieldStorageModels = FieldStorageModels\n/** @deprecated Use {@link ListElementStorageModels} */\nexport type FeedListElementStorageModels = ListElementStorageModels\n\nfunction normalizeModelName(schemaName: string): string {\n return schemaName.trim().toLowerCase()\n}\n\nexport function isRichBodyStorageSchema(schemaName: string): boolean {\n return RICH_BODY_STORAGE_SCHEMAS.has(normalizeModelName(schemaName))\n}\n\n/** @deprecated Use {@link isRichBodyStorageSchema} */\nexport const isFeedRichBodyStorageSchema = isRichBodyStorageSchema\n\n/** html < file < json for tie-breaking among rich body fields. */\nexport function richBodyModelPriority(schemaName: string): number {\n const m = normalizeModelName(schemaName)\n if (m === 'html') return 0\n if (m === 'file') return 1\n if (m === 'json') return 2\n return 99\n}\n\n/** @deprecated Use {@link richBodyModelPriority} */\nexport const feedRichBodyModelPriority = richBodyModelPriority\n\nexport function getFieldStorageModels(\n item: Record<string, unknown>,\n): FieldStorageModels | undefined {\n const raw = item[FIELD_MODELS_KEY]\n if (raw !== null && typeof raw === 'object' && !Array.isArray(raw)) {\n return raw as FieldStorageModels\n }\n return undefined\n}\n\n/** @deprecated Use {@link getFieldStorageModels} */\nexport const getFeedFieldStorageModels = getFieldStorageModels\n\nexport function getListElementStorageModels(\n item: Record<string, unknown>,\n): ListElementStorageModels | undefined {\n const raw = item[LIST_MODELS_KEY]\n if (raw !== null && typeof raw === 'object' && !Array.isArray(raw)) {\n return raw as ListElementStorageModels\n }\n return undefined\n}\n\n/** @deprecated Use {@link getListElementStorageModels} */\nexport const getFeedListElementStorageModels = getListElementStorageModels\n\nexport function setFieldStorageModel(\n item: Record<string, unknown>,\n fieldKey: string,\n schemaName: string,\n): void {\n const normalized = normalizeModelName(schemaName)\n let map = getFieldStorageModels(item)\n if (!map) {\n map = {}\n item[FIELD_MODELS_KEY] = map\n }\n map[fieldKey] = normalized\n}\n\n/** @deprecated Use {@link setFieldStorageModel} */\nexport const setFeedFieldStorageModel = setFieldStorageModel\n\nexport function setListElementStorageModels(\n item: Record<string, unknown>,\n outputKey: string,\n models: string[],\n): void {\n let map = getListElementStorageModels(item)\n if (!map) {\n map = {}\n item[LIST_MODELS_KEY] = map\n }\n map[outputKey] = models.map(normalizeModelName)\n}\n\n/** @deprecated Use {@link setListElementStorageModels} */\nexport const setFeedListElementStorageModels = setListElementStorageModels\n","import { BaseArweaveClient, isKnownArweaveGatewayHostname } from '@seedprotocol/arweave'\nimport {\n getFieldStorageModels,\n getListElementStorageModels,\n isRichBodyStorageSchema,\n} from './fieldStorageModel.js'\n\n/** Same logical fields as legacy rich-text primary keys — inline HTML/body for consumers. */\nconst RICH_TEXT_KEYS = ['html', 'Html', 'body', 'Body', 'content', 'Content'] as const\n\n/** Max UTF-8 bytes for a single rich-body fetch. */\nconst MAX_BODY_BYTES = 8_000_000\n\nexport type HydrateStorageOptions = {\n /** Prefer local file body when available; fall back to Arweave gateway fetch. */\n readStorageBody?: (ref: {\n propertyName: string\n value: unknown\n localPathHint?: string\n }) => Promise<string | null>\n}\n\n/**\n * True for a single-path gateway URL whose path looks like an Arweave transaction id.\n */\nexport function isArweaveTransactionGatewayUrl(raw: string): boolean {\n const s = raw.trim()\n if (!s.startsWith('http://') && !s.startsWith('https://')) return false\n try {\n const u = new URL(s)\n const host = u.hostname.toLowerCase()\n const expected = BaseArweaveClient.getHost().toLowerCase()\n if (host !== expected && !isKnownArweaveGatewayHostname(host)) return false\n const segments = u.pathname.replace(/^\\//, '').split('/').filter(Boolean)\n if (segments.length !== 1) return false\n const id = segments[0]!\n return /^[A-Za-z0-9_-]{43}$/.test(id)\n } catch {\n return false\n }\n}\n\nasync function fetchGatewayPayloadAsUtf8(url: string): Promise<string | null> {\n try {\n const res = await fetch(url, {\n headers: { Accept: 'text/html, text/plain, text/markdown, application/json, */*' },\n signal: AbortSignal.timeout(15_000),\n })\n if (!res.ok) return null\n const ct = res.headers.get('content-type') ?? ''\n if (/^(image|video|audio)\\//i.test(ct)) return null\n const buf = await res.arrayBuffer()\n if (buf.byteLength > MAX_BODY_BYTES) return null\n const text = new TextDecoder('utf-8', { fatal: false }).decode(buf)\n if (text.length === 0 || text.includes('\\0')) return null\n return text\n } catch {\n return null\n }\n}\n\nasync function resolveHydratedBody(\n propertyName: string,\n value: string,\n readStorageBody?: HydrateStorageOptions['readStorageBody'],\n): Promise<string | null> {\n if (readStorageBody) {\n try {\n const local = await readStorageBody({ propertyName, value })\n if (local != null && local.length > 0) return local\n } catch {\n // fall through to gateway\n }\n }\n if (!isArweaveTransactionGatewayUrl(value)) return null\n return fetchGatewayPayloadAsUtf8(value)\n}\n\nasync function hydrateStringField(\n item: Record<string, unknown>,\n key: string,\n readStorageBody?: HydrateStorageOptions['readStorageBody'],\n): Promise<void> {\n const v = item[key]\n if (typeof v !== 'string' || v.trim() === '') return\n const text = await resolveHydratedBody(key, v, readStorageBody)\n if (text === null) return\n item[key] = text\n}\n\n/**\n * After relation URL resolution, Html/File fields may be gateway URLs (or local paths).\n * Replace those with the UTF-8 body when `hydrateStorage` is enabled.\n */\nexport async function hydrateArweaveRichTextInItems(\n items: Record<string, unknown>[],\n options?: HydrateStorageOptions,\n): Promise<void> {\n const readStorageBody = options?.readStorageBody\n for (const item of items) {\n const keysToHydrate = new Set<string>([...RICH_TEXT_KEYS])\n const fieldModels = getFieldStorageModels(item)\n if (fieldModels) {\n for (const [k, m] of Object.entries(fieldModels)) {\n if (isRichBodyStorageSchema(m)) keysToHydrate.add(k)\n }\n }\n for (const key of keysToHydrate) {\n await hydrateStringField(item, key, readStorageBody)\n }\n\n const listModels = getListElementStorageModels(item)\n if (listModels) {\n for (const [listKey, models] of Object.entries(listModels)) {\n const arr = item[listKey]\n if (!Array.isArray(arr)) continue\n const n = Math.min(models.length, arr.length)\n for (let i = 0; i < n; i++) {\n if (!isRichBodyStorageSchema(models[i]!)) continue\n const el = arr[i]\n if (typeof el !== 'string') continue\n const text = await resolveHydratedBody(listKey, el, readStorageBody)\n if (text === null) continue\n arr[i] = text\n }\n }\n }\n }\n}\n\n/** @deprecated Use {@link hydrateArweaveRichTextInItems} */\nexport const hydrateArweaveRichTextInFeedItems = hydrateArweaveRichTextInItems\n","export type EasPropertyMetadata = {\n name: string\n value: string | string[]\n type?: string\n}\n\nexport type ParseEasPropertyMetadataResult =\n | { ok: true; metadata: EasPropertyMetadata }\n | { ok: false; reason: 'empty' }\n | { ok: false; reason: 'shape' }\n | { ok: false; reason: 'parse'; error: unknown }\n\n/**\n * Parse EAS property `decodedDataJson`.\n * Matches SDK guards in syncDbWithEas / saveDataToDb (empty trim, parse, array + [0].value).\n */\nexport function parseEasPropertyMetadata(\n decodedDataJson: string | undefined | null,\n): ParseEasPropertyMetadataResult {\n const raw = typeof decodedDataJson === 'string' ? decodedDataJson.trim() : ''\n if (!raw) {\n return { ok: false, reason: 'empty' }\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (e) {\n return { ok: false, reason: 'parse', error: e }\n }\n\n if (!Array.isArray(parsed) || parsed.length === 0 || !parsed[0]?.value) {\n return { ok: false, reason: 'shape' }\n }\n\n const metadata = parsed[0].value as EasPropertyMetadata\n return { ok: true, metadata }\n}\n\n/** @deprecated Use {@link parseEasPropertyMetadata} */\nexport const parseEasPropertyMetadataForFeed = parseEasPropertyMetadata\n/** @deprecated Use {@link EasPropertyMetadata} */\nexport type EasPropertyMetadataForFeed = EasPropertyMetadata\n/** @deprecated Use {@link ParseEasPropertyMetadataResult} */\nexport type ParseEasPropertyMetadataForFeedResult = ParseEasPropertyMetadataResult\n","import pluralize from 'pluralize'\n\nexport type ParsedEasRelationPropertyName = {\n propertyName: string\n modelName: string\n isList: boolean\n}\n\n/**\n * Parse EAS relation property naming: `{singular}_{model}_id` or `{singular}_{model}_ids`.\n * Lists map back to the plural schema key the same way publicListRelationPropertyKey does\n * (`author_identity_ids` → `authors`, `staff_identity_ids` → `staff`); single relations keep the singular.\n * Returns null when the name does not match the expected shape.\n */\nexport function parseEasRelationPropertyName(\n easPropertyName: string,\n): ParsedEasRelationPropertyName | null {\n const [singularProperty, modelName, idSegment] = easPropertyName.split('_')\n if (!singularProperty || !modelName) return null\n const isList = idSegment === 'ids'\n const propertyName = !isList\n ? singularProperty\n : singularProperty.endsWith('s')\n ? singularProperty\n : pluralize(singularProperty)\n return { propertyName, modelName, isList }\n}\n","import {\n getSeedsBySchemaName,\n getItemVersionsFromEas,\n getItemPropertiesFromEas,\n EasClient,\n withExcludeRevokedFilter,\n GET_SEEDS,\n} from '@seedprotocol/eas'\nimport type { AttestationLike } from '../types.js'\nimport type { QueryDataSource } from './types.js'\n\nfunction monthBoundsUnix(year: number, month: number): { startTs: number; endTs: number } {\n const startDate = new Date(year, month - 1, 1)\n const endDate = new Date(year, month, 0, 23, 59, 59)\n const startTs = Math.floor(startDate.getTime() / 1000)\n const endTs = Math.floor(endDate.getTime() / 1000) + 1\n return { startTs, endTs }\n}\n\n/**\n * Default remote data source: EAS GraphQL (+ callers hydrate via Arweave).\n */\nexport function createRemoteQueryDataSource(): QueryDataSource {\n return {\n kind: 'remote',\n\n async getSeedByUid(seedUid: string): Promise<AttestationLike | null> {\n const easClient = EasClient.getEasClient()\n const { itemSeeds } = await easClient.request(GET_SEEDS, {\n where: withExcludeRevokedFilter({\n id: { equals: seedUid },\n }),\n take: 1,\n skip: 0,\n })\n return ((itemSeeds ?? [])[0] as AttestationLike | undefined) ?? null\n },\n\n async listSeedsBySchemaName(\n schemaName: string,\n opts: { limit: number; skip: number },\n ): Promise<AttestationLike[]> {\n return (await getSeedsBySchemaName(\n schemaName,\n opts.limit,\n opts.skip,\n )) as AttestationLike[]\n },\n\n async listSeedsBySchemaNameForMonth(\n schemaName: string,\n year: number,\n month: number,\n ): Promise<AttestationLike[]> {\n const { startTs, endTs } = monthBoundsUnix(year, month)\n const where = withExcludeRevokedFilter({\n AND: [\n {\n schema: {\n is: {\n schemaNames: {\n some: {\n name: { equals: schemaName },\n },\n },\n },\n },\n },\n {\n timeCreated: { gte: startTs, lt: endTs },\n },\n ],\n })\n\n const easClient = EasClient.getEasClient()\n const { itemSeeds } = await easClient.request(GET_SEEDS, {\n where,\n take: 1000,\n skip: 0,\n })\n return (itemSeeds ?? []) as AttestationLike[]\n },\n\n async getVersionsForSeed(seedUid: string): Promise<AttestationLike[]> {\n return (await getItemVersionsFromEas({\n seedUids: [seedUid],\n })) as AttestationLike[]\n },\n\n async getVersionsForSeeds(seedUids: string[]): Promise<AttestationLike[]> {\n if (seedUids.length === 0) return []\n return (await getItemVersionsFromEas({ seedUids })) as AttestationLike[]\n },\n\n async getPropertiesForVersionUids(\n versionUids: string[],\n ): Promise<AttestationLike[]> {\n if (versionUids.length === 0) return []\n return (await getItemPropertiesFromEas({\n versionUids,\n })) as AttestationLike[]\n },\n\n async getSeedsByUids(uids: string[]): Promise<AttestationLike[]> {\n if (uids.length === 0) return []\n const easClient = EasClient.getEasClient()\n const { itemSeeds } = await easClient.request(GET_SEEDS, {\n where: withExcludeRevokedFilter({\n id: { in: uids },\n }),\n take: uids.length || 1,\n skip: 0,\n })\n return (itemSeeds ?? []) as AttestationLike[]\n },\n }\n}\n\nlet remoteSingleton: QueryDataSource | null = null\n\nexport function getRemoteQueryDataSource(): QueryDataSource {\n if (!remoteSingleton) {\n remoteSingleton = createRemoteQueryDataSource()\n }\n return remoteSingleton\n}\n\n/** Tests only. */\nexport function resetRemoteQueryDataSource(): void {\n remoteSingleton = null\n}\n","import {\n setSchemaUidForSchemaDefinition,\n pickLatestPropertyAttestationsByRefAndSchema,\n} from '@seedprotocol/eas'\nimport { getArweaveUrlForTransaction } from './arweaveUrl.js'\nimport {\n publicListRelationPropertyKey,\n stripListRelationStorageAliasesForPublicKey,\n tryCoerceJsonStringArray,\n} from './listRelationKey.js'\nimport { enrichImageSeedClone } from './imageRelationEnrichment.js'\nimport { hydrateArweaveRichTextInItems } from './hydrateArweaveRichText.js'\nimport { parseEasPropertyMetadata } from './parseEasPropertyMetadata.js'\nimport { parseEasRelationPropertyName } from './parseEasRelationPropertyName.js'\nimport {\n setFieldStorageModel,\n setListElementStorageModels,\n} from './fieldStorageModel.js'\nimport { getRemoteQueryDataSource } from './source/remote.js'\nimport type { QueryDataSource } from './source/types.js'\nimport type { AssembleOptions, AttestationLike, SeedRecord } from './types.js'\n\nconst IMAGE_SCHEMA = 'image'\n\nconst relationValuesToExclude = [\n '0x0000000000000000000000000000000000000000000000000000000000000020',\n]\n\nconst RESERVED_KEYS = new Set([\n 'seedUid',\n 'SeedUid',\n 'timeCreated',\n 'attester',\n 'Attester',\n 'storage_transaction_id',\n 'storage_provider_transaction_id',\n 'storageTransactionId',\n 'storageProviderTransactionId',\n 'versionUid',\n])\n\nconst toCamelCase = (str: string): string => {\n return str.replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())\n}\n\ntype AssembleContext = {\n seedUidToModelType: Map<string, string>\n relatedSeedUids: Set<string>\n versionUidToSeedUid: Map<string, string>\n assembledItems: Map<string, Record<string, unknown>>\n versionsBySeedUid: Map<string, AttestationLike[]>\n latestVersionUidsBySeedUid: Map<string, string>\n}\n\nfunction createAssembleContext(): AssembleContext {\n return {\n seedUidToModelType: new Map(),\n relatedSeedUids: new Set(),\n versionUidToSeedUid: new Map(),\n assembledItems: new Map(),\n versionsBySeedUid: new Map(),\n latestVersionUidsBySeedUid: new Map(),\n }\n}\n\nfunction ensureSeedIdentity(clone: Record<string, unknown>, seedUid: string): void {\n if (!clone.seedUid && !clone.SeedUid) {\n clone.seedUid = seedUid\n clone.SeedUid = seedUid\n } else if (clone.seedUid && !clone.SeedUid) {\n clone.SeedUid = clone.seedUid\n } else if (clone.SeedUid && !clone.seedUid) {\n clone.seedUid = clone.SeedUid\n }\n if (clone.attester && !clone.Attester) {\n clone.Attester = clone.attester\n } else if (clone.Attester && !clone.attester) {\n clone.attester = clone.Attester\n }\n}\n\nasync function processItemProperty(\n ctx: AssembleContext,\n property: AttestationLike,\n): Promise<void> {\n const parsed = parseEasPropertyMetadata(property.decodedDataJson)\n if (!parsed.ok) {\n const { id, refUID, schemaId } = property\n if (parsed.reason === 'empty') {\n console.warn(\n '[query] [processItemProperty] empty decodedDataJson for property:',\n id,\n refUID,\n schemaId,\n )\n } else if (parsed.reason === 'parse') {\n console.warn(\n '[query] [processItemProperty] failed to parse decodedDataJson for property:',\n id,\n refUID,\n schemaId,\n parsed.error,\n )\n } else {\n console.warn(\n '[query] [processItemProperty] invalid decodedDataJson structure for property:',\n id,\n refUID,\n schemaId,\n )\n }\n return\n }\n\n const metadata = parsed.metadata\n\n let propertyNameSnake = metadata.name\n if (!propertyNameSnake) {\n return\n }\n\n const schemaUid = property.schemaId\n setSchemaUidForSchemaDefinition({\n text: propertyNameSnake,\n schemaUid,\n })\n\n let isRelation = false\n let isList = false\n const easType = metadata.type\n const isBytes32Relation =\n (easType === 'bytes32' || easType === 'bytes32[]') &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n const isNamingConventionRelation =\n !isBytes32Relation &&\n (propertyNameSnake.endsWith('_id') || propertyNameSnake.endsWith('_ids')) &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n\n if (isBytes32Relation || isNamingConventionRelation) {\n isRelation = true\n if (Array.isArray(metadata.value)) {\n isList = true\n if (isNamingConventionRelation) {\n const result = parseEasRelationPropertyName(propertyNameSnake)\n if (result) {\n propertyNameSnake = result.propertyName\n }\n }\n metadata.value.forEach((value: string) => {\n if (!relationValuesToExclude.includes(value)) ctx.relatedSeedUids.add(value)\n })\n } else if (!relationValuesToExclude.includes(metadata.value as string)) {\n ctx.relatedSeedUids.add(metadata.value as string)\n }\n }\n\n let propertyValue: string | string[] = metadata.value as string | string[]\n if (isRelation && isList && Array.isArray(propertyValue)) {\n propertyValue = propertyValue.map((v) => String(v))\n } else if (typeof propertyValue !== 'string') {\n propertyValue = JSON.stringify(propertyValue)\n }\n\n const seedUidForProperty = ctx.versionUidToSeedUid.get(property.refUID)\n if (!seedUidForProperty) {\n return\n }\n\n const existingItem = ctx.assembledItems.get(seedUidForProperty) || {}\n existingItem[propertyNameSnake] = propertyValue\n const propertyNameCamel = toCamelCase(propertyNameSnake)\n if (propertyNameCamel !== propertyNameSnake) {\n existingItem[propertyNameCamel] = propertyValue\n }\n ctx.assembledItems.set(seedUidForProperty, existingItem)\n}\n\nasync function processSeeds(\n ctx: AssembleContext,\n seeds: AttestationLike[],\n dataSource: QueryDataSource,\n): Promise<void> {\n const seedUids: string[] = []\n\n for (let i = 0; i < seeds.length; i++) {\n const seed = seeds[i]\n if (!seed) continue\n seedUids.push(seed.id)\n const modelType = seed.schema?.schemaNames?.[0]?.name ?? 'unknown'\n ctx.seedUidToModelType.set(seed.id, modelType)\n\n if (!ctx.assembledItems.has(seed.id)) {\n ctx.assembledItems.set(seed.id, {\n seedUid: seed.id,\n timeCreated: seed.timeCreated,\n attester: seed.attester,\n })\n }\n }\n\n if (seedUids.length === 0) return\n\n const itemVersions = await dataSource.getVersionsForSeeds(seedUids)\n\n for (let i = 0; i < itemVersions.length; i++) {\n const itemVersion = itemVersions[i] as AttestationLike\n const seedUid = itemVersion.refUID\n ctx.versionUidToSeedUid.set(itemVersion.id, seedUid)\n const existingVersions = ctx.versionsBySeedUid.get(seedUid) || []\n ctx.versionsBySeedUid.set(seedUid, [...existingVersions, itemVersion])\n }\n\n const latestVersionUids: string[] = []\n for (const [seedUid, versions] of ctx.versionsBySeedUid.entries()) {\n if (ctx.latestVersionUidsBySeedUid.has(seedUid)) continue\n const sortedVersions = [...versions].sort((a, b) => b.timeCreated - a.timeCreated)\n const latestVersion = sortedVersions[0]\n if (latestVersion) {\n latestVersionUids.push(latestVersion.id)\n ctx.latestVersionUidsBySeedUid.set(seedUid, latestVersion.id)\n }\n }\n\n if (latestVersionUids.length === 0) return\n\n const rawProperties =\n await dataSource.getPropertiesForVersionUids(latestVersionUids)\n const itemProperties = pickLatestPropertyAttestationsByRefAndSchema(rawProperties)\n\n for (let i = 0; i < itemProperties.length; i++) {\n await processItemProperty(ctx, itemProperties[i] as AttestationLike)\n }\n}\n\nfunction resolveRelationPropertiesToUrls(ctx: AssembleContext, schemaName: string): void {\n const itemsToProcess = Array.from(ctx.assembledItems.entries()).filter(\n ([seedUid]) => ctx.seedUidToModelType.get(seedUid) === schemaName,\n )\n\n for (const [, item] of itemsToProcess) {\n const keysToProcess = Object.keys(item).filter(\n (k) => !k.startsWith('_') && !RESERVED_KEYS.has(k),\n )\n\n for (const key of keysToProcess) {\n let value = item[key]\n const coerced = tryCoerceJsonStringArray(value)\n if (coerced !== value && Array.isArray(coerced)) {\n item[key] = coerced\n value = coerced\n }\n const isList = Array.isArray(value)\n\n if (isList) {\n const uids = value as unknown[]\n const hasRelationUid = uids.some(\n (v) =>\n typeof v === 'string' &&\n !relationValuesToExclude.includes(v) &&\n ctx.assembledItems.has(v),\n )\n if (!hasRelationUid) continue\n\n const urls: string[] = []\n const models: string[] = []\n let resolved = false\n for (const uid of uids) {\n if (typeof uid !== 'string' || relationValuesToExclude.includes(uid)) {\n urls.push(String(uid))\n models.push('unknown')\n continue\n }\n const modelForUid = ctx.seedUidToModelType.get(uid) ?? 'unknown'\n if (modelForUid === IMAGE_SCHEMA) {\n urls.push(uid)\n models.push(IMAGE_SCHEMA)\n continue\n }\n const related = ctx.assembledItems.get(uid)\n const txId = (related?.storageTransactionId ??\n related?.storage_transaction_id) as string | undefined\n if (txId && typeof txId === 'string' && txId.trim()) {\n try {\n urls.push(getArweaveUrlForTransaction(txId))\n models.push(modelForUid)\n resolved = true\n } catch {\n urls.push(uid)\n models.push(modelForUid)\n }\n } else {\n urls.push(uid)\n models.push(modelForUid)\n }\n }\n if (resolved) {\n const outputKey = publicListRelationPropertyKey(key)\n item[outputKey] = urls\n setListElementStorageModels(item, outputKey, models)\n stripListRelationStorageAliasesForPublicKey(item, outputKey)\n if (outputKey !== key) {\n delete item[key]\n const camelKey = toCamelCase(key)\n if (camelKey !== key) delete item[camelKey]\n }\n }\n } else if (typeof value === 'string') {\n if (relationValuesToExclude.includes(value)) continue\n if (!ctx.assembledItems.has(value)) continue\n\n const related = ctx.assembledItems.get(value)\n if (ctx.seedUidToModelType.get(value) === IMAGE_SCHEMA) {\n continue\n }\n const txId = (related?.storageTransactionId ?? related?.storage_transaction_id) as\n | string\n | undefined\n if (txId && typeof txId === 'string' && txId.trim()) {\n try {\n const outputKey = key.endsWith('_id') ? key.replace(/_id$/, '') : key\n item[outputKey] = getArweaveUrlForTransaction(txId)\n const relatedModel = ctx.seedUidToModelType.get(value) ?? 'unknown'\n setFieldStorageModel(item, outputKey, relatedModel)\n const camelOut = toCamelCase(outputKey)\n if (camelOut !== outputKey) {\n setFieldStorageModel(item, camelOut, relatedModel)\n }\n if (outputKey !== key) {\n delete item[key]\n const camelKey = toCamelCase(key)\n if (camelKey !== key) delete item[camelKey]\n }\n } catch {\n // keep original on error\n }\n }\n }\n }\n }\n}\n\nfunction expandRelationProperties(\n ctx: AssembleContext,\n schemaName: string,\n expandRelations: boolean,\n): void {\n if (!expandRelations) return\n\n const itemsToProcess = Array.from(ctx.assembledItems.entries()).filter(\n ([seedUid]) => ctx.seedUidToModelType.get(seedUid) === schemaName,\n )\n\n for (const [, item] of itemsToProcess) {\n const keysToProcess = Object.keys(item).filter(\n (k) => !k.startsWith('_') && !RESERVED_KEYS.has(k),\n )\n\n for (const key of keysToProcess) {\n let value = item[key]\n const coerced = tryCoerceJsonStringArray(value)\n if (coerced !== value && Array.isArray(coerced)) {\n item[key] = coerced\n value = coerced\n }\n const isList = Array.isArray(value)\n const uids = isList ? (value as unknown[]) : [value]\n\n const expanded: unknown[] = []\n let didExpand = false\n\n for (const uid of uids) {\n if (typeof uid !== 'string' || relationValuesToExclude.includes(uid)) {\n expanded.push(uid)\n continue\n }\n const related = ctx.assembledItems.get(uid)\n if (!related) {\n expanded.push(uid)\n continue\n }\n const txId = (related?.storageTransactionId ?? related?.storage_transaction_id) as\n | string\n | undefined\n const isImage = ctx.seedUidToModelType.get(uid) === IMAGE_SCHEMA\n\n if (isImage) {\n const clone = { ...related } as Record<string, unknown>\n ensureSeedIdentity(clone, uid)\n clone.schemaName = IMAGE_SCHEMA\n enrichImageSeedClone(clone)\n expanded.push(clone)\n didExpand = true\n continue\n }\n\n if (txId && typeof txId === 'string' && txId.trim()) {\n expanded.push(uid)\n continue\n }\n const clone = { ...related } as Record<string, unknown>\n ensureSeedIdentity(clone, uid)\n expanded.push(clone)\n didExpand = true\n }\n\n if (didExpand) {\n const outputKey = isList\n ? publicListRelationPropertyKey(key)\n : key.endsWith('_id')\n ? key.replace(/_id$/, '')\n : key\n item[outputKey] = isList ? expanded : expanded[0]\n stripListRelationStorageAliasesForPublicKey(item, outputKey)\n if (outputKey !== key) {\n delete item[key]\n const camelKey = toCamelCase(key)\n if (camelKey !== key) delete item[camelKey]\n }\n }\n }\n }\n}\n\nfunction toSeedRecords(\n ctx: AssembleContext,\n schemaName: string,\n): SeedRecord[] {\n return Array.from(ctx.assembledItems.entries())\n .filter(([seedUid]) => ctx.seedUidToModelType.get(seedUid) === schemaName)\n .map(([seedUid, item]) => {\n const versionUid = ctx.latestVersionUidsBySeedUid.get(seedUid) ?? ''\n if (versionUid) {\n item.versionUid = versionUid\n }\n ensureSeedIdentity(item, seedUid)\n const timeCreated =\n typeof item.timeCreated === 'number' ? item.timeCreated : 0\n const attester =\n typeof item.attester === 'string'\n ? item.attester\n : typeof item.Attester === 'string'\n ? item.Attester\n : undefined\n return {\n seedUid,\n schemaName,\n attester,\n timeCreated,\n versionUid,\n data: item,\n }\n })\n}\n\n/**\n * Assemble canonical SeedRecords from Seed attestations (latest Version + canonical properties).\n * Uses per-call state (safe for concurrent requests).\n */\nexport async function assembleSeeds(\n schemaName: string,\n seeds: AttestationLike[],\n options?: AssembleOptions,\n dataSource: QueryDataSource = getRemoteQueryDataSource(),\n): Promise<SeedRecord[]> {\n const expandRelations = options?.expandRelations !== false\n const hydrateStorage = options?.hydrateStorage !== false\n\n const ctx = createAssembleContext()\n\n await processSeeds(ctx, seeds, dataSource)\n\n const relatedSeedUidsArray = Array.from(ctx.relatedSeedUids).filter(\n (uid) => !ctx.assembledItems.has(uid),\n )\n if (relatedSeedUidsArray.length > 0) {\n const relatedSeeds = await dataSource.getSeedsByUids(relatedSeedUidsArray)\n await processSeeds(ctx, relatedSeeds, dataSource)\n }\n\n resolveRelationPropertiesToUrls(ctx, schemaName)\n expandRelationProperties(ctx, schemaName, expandRelations)\n\n const records = toSeedRecords(ctx, schemaName)\n\n if (hydrateStorage) {\n await hydrateArweaveRichTextInItems(\n records.map((r) => r.data),\n dataSource.readStorageBody\n ? { readStorageBody: dataSource.readStorageBody.bind(dataSource) }\n : undefined,\n )\n }\n\n return records\n}\n","import { parseEasPropertyMetadata } from './parseEasPropertyMetadata.js'\nimport { parseEasRelationPropertyName } from './parseEasRelationPropertyName.js'\nimport type {\n AttestationLike,\n ChangelogEntry,\n ChangelogOptions,\n PropertyChangelogEntry,\n VersionChangelogEntry,\n} from './types.js'\n\nconst toCamelCase = (str: string): string => {\n return str.replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())\n}\n\n/**\n * Stable-ish deep equality for changelog value comparison.\n */\nexport function changelogValuesEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (a === undefined || b === undefined) return false\n if (a === null || b === null) return a === b\n if (typeof a !== typeof b) return false\n if (typeof a !== 'object') return false\n try {\n return JSON.stringify(a) === JSON.stringify(b)\n } catch {\n return false\n }\n}\n\nexport type DecodedProperty = {\n propertyName: string\n value: string | string[]\n camelName?: string\n}\n\n/**\n * Decode a single property attestation into name + value (no relation expand).\n * Returns null when metadata cannot be parsed.\n */\nexport function decodePropertyAttestation(\n property: AttestationLike,\n): DecodedProperty | null {\n const parsed = parseEasPropertyMetadata(property.decodedDataJson)\n if (!parsed.ok) return null\n\n const metadata = parsed.metadata\n let propertyNameSnake = metadata.name\n if (!propertyNameSnake) return null\n\n const easType = metadata.type\n const isBytes32Relation =\n (easType === 'bytes32' || easType === 'bytes32[]') &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n const isNamingConventionRelation =\n !isBytes32Relation &&\n (propertyNameSnake.endsWith('_id') || propertyNameSnake.endsWith('_ids')) &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n\n let isRelation = false\n let isList = false\n if (isBytes32Relation || isNamingConventionRelation) {\n isRelation = true\n if (Array.isArray(metadata.value)) {\n isList = true\n if (isNamingConventionRelation) {\n const result = parseEasRelationPropertyName(propertyNameSnake)\n if (result?.isList) {\n propertyNameSnake = result.propertyName\n }\n }\n }\n }\n\n let propertyValue: string | string[] = metadata.value as string | string[]\n if (isRelation && isList && Array.isArray(propertyValue)) {\n propertyValue = propertyValue.map((v) => String(v))\n } else if (typeof propertyValue !== 'string') {\n propertyValue = JSON.stringify(propertyValue)\n }\n\n const camelName = toCamelCase(propertyNameSnake)\n return {\n propertyName: propertyNameSnake,\n value: propertyValue,\n camelName: camelName !== propertyNameSnake ? camelName : undefined,\n }\n}\n\n/**\n * Build a flat property map from canonical property attestations for one Version.\n */\nexport function buildFlatSnapshotFromProperties(\n properties: AttestationLike[],\n): Record<string, unknown> {\n const snapshot: Record<string, unknown> = {}\n for (const property of properties) {\n const decoded = decodePropertyAttestation(property)\n if (!decoded) continue\n snapshot[decoded.propertyName] = decoded.value\n if (decoded.camelName) {\n snapshot[decoded.camelName] = decoded.value\n }\n }\n return snapshot\n}\n\nexport type VersionSnapshot = {\n versionUid: string\n at: number\n data: Record<string, unknown>\n}\n\n/**\n * Diff consecutive version snapshots (ascending by `at`).\n * First version: `before = {}`, all keys in `after` are changed.\n */\nexport function diffVersionSnapshots(\n sortedSnapshots: VersionSnapshot[],\n): VersionChangelogEntry[] {\n const entries: VersionChangelogEntry[] = []\n let before: Record<string, unknown> = {}\n\n for (const snap of sortedSnapshots) {\n const after = snap.data\n const keySet = new Set([...Object.keys(before), ...Object.keys(after)])\n const changedKeys: string[] = []\n for (const key of keySet) {\n if (!changelogValuesEqual(before[key], after[key])) {\n changedKeys.push(key)\n }\n }\n changedKeys.sort()\n entries.push({\n type: 'version',\n at: snap.at,\n versionUid: snap.versionUid,\n before: { ...before },\n after: { ...after },\n changedKeys,\n })\n before = after\n }\n\n return entries\n}\n\n/**\n * Per-attestation property diffs across all versions (ordered by timeCreated asc).\n */\nexport function diffPropertyAttestations(\n properties: AttestationLike[],\n): PropertyChangelogEntry[] {\n const sorted = [...properties].sort((a, b) => {\n if (a.timeCreated !== b.timeCreated) return a.timeCreated - b.timeCreated\n return a.id.localeCompare(b.id)\n })\n\n const previousByProperty = new Map<string, unknown>()\n const entries: PropertyChangelogEntry[] = []\n\n for (const property of sorted) {\n const decoded = decodePropertyAttestation(property)\n if (!decoded) continue\n\n const names = [decoded.propertyName]\n if (decoded.camelName) names.push(decoded.camelName)\n\n // Emit one entry per logical property (snake); camel is alias only.\n const previousValue = previousByProperty.has(decoded.propertyName)\n ? previousByProperty.get(decoded.propertyName)\n : undefined\n const nextValue = decoded.value\n\n if (!changelogValuesEqual(previousValue, nextValue)) {\n entries.push({\n type: 'property',\n at: property.timeCreated,\n versionUid: property.refUID,\n property: decoded.propertyName,\n attestationUid: property.id,\n previousValue,\n nextValue,\n })\n }\n\n previousByProperty.set(decoded.propertyName, nextValue)\n if (decoded.camelName) {\n previousByProperty.set(decoded.camelName, nextValue)\n }\n }\n\n return entries\n}\n\n/**\n * Filter by `since` (inclusive), then keep the newest `limit` entries (newest-first).\n * Returned array is newest-first when limit is applied; otherwise chronological (asc).\n */\nexport function applyChangelogFilters(\n entries: ChangelogEntry[],\n options?: ChangelogOptions,\n): ChangelogEntry[] {\n let filtered = entries\n if (typeof options?.since === 'number') {\n const since = options.since\n filtered = filtered.filter((e) => e.at >= since)\n }\n\n if (typeof options?.limit === 'number' && options.limit >= 0) {\n // Newest-first slice, then reverse back to chronological for callers.\n const newestFirst = [...filtered].sort((a, b) => {\n if (b.at !== a.at) return b.at - a.at\n return 0\n })\n filtered = newestFirst.slice(0, options.limit).reverse()\n }\n\n return filtered\n}\n","import { pickLatestPropertyAttestationsByRefAndSchema } from '@seedprotocol/eas'\nimport {\n applyChangelogFilters,\n buildFlatSnapshotFromProperties,\n diffPropertyAttestations,\n diffVersionSnapshots,\n type VersionSnapshot,\n} from './changelog.js'\nimport { getRemoteQueryDataSource } from './source/remote.js'\nimport type { QueryDataSource } from './source/types.js'\nimport type {\n AttestationLike,\n ChangelogEntry,\n ChangelogOptions,\n GetSeedOptions,\n} from './types.js'\n\nexport type AssembleSeedChangelogResult = {\n latestVersionUid: string\n changelog: ChangelogEntry[]\n}\n\n/**\n * Build a changelog for one seed from all Versions + property attestations.\n * Snapshots are flat (no relation expand / hydrate).\n */\nexport async function assembleSeedChangelog(\n seedUid: string,\n options?: Pick<GetSeedOptions, 'changelog'>,\n dataSource: QueryDataSource = getRemoteQueryDataSource(),\n): Promise<AssembleSeedChangelogResult> {\n const changelogOpts: ChangelogOptions = options?.changelog ?? {}\n const granularity = changelogOpts.granularity ?? 'version'\n\n const itemVersions = await dataSource.getVersionsForSeed(seedUid)\n\n const sortedVersions = [...itemVersions].sort(\n (a, b) => a.timeCreated - b.timeCreated,\n )\n\n if (sortedVersions.length === 0) {\n return { latestVersionUid: '', changelog: [] }\n }\n\n const latestVersionUid = sortedVersions[sortedVersions.length - 1]!.id\n const versionUids = sortedVersions.map((v) => v.id)\n\n const rawProperties =\n await dataSource.getPropertiesForVersionUids(versionUids)\n\n let changelog: ChangelogEntry[]\n\n if (granularity === 'property') {\n changelog = diffPropertyAttestations(rawProperties)\n } else {\n const byVersion = new Map<string, AttestationLike[]>()\n for (const prop of rawProperties) {\n const list = byVersion.get(prop.refUID) ?? []\n list.push(prop)\n byVersion.set(prop.refUID, list)\n }\n\n const snapshots: VersionSnapshot[] = []\n for (const version of sortedVersions) {\n const propsForVersion = byVersion.get(version.id) ?? []\n const canonical = pickLatestPropertyAttestationsByRefAndSchema(\n propsForVersion,\n ) as AttestationLike[]\n snapshots.push({\n versionUid: version.id,\n at: version.timeCreated,\n data: buildFlatSnapshotFromProperties(canonical),\n })\n }\n changelog = diffVersionSnapshots(snapshots)\n }\n\n return {\n latestVersionUid,\n changelog: applyChangelogFilters(changelog, changelogOpts),\n }\n}\n","import { sha256 } from '@noble/hashes/sha256'\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils'\n\n/**\n * Generate an ETag from a string value (SHA-256, first 16 hex chars, quoted).\n */\nexport function generateETag(value: string): string {\n const hash = bytesToHex(sha256(utf8ToBytes(value)))\n return `\"${hash.substring(0, 16)}\"`\n}\n\n/**\n * Generate an ETag for a collection working set.\n */\nexport function generateCollectionETag(\n schemaName: string,\n lastProcessedTimestamp: number,\n itemCount: number,\n): string {\n return generateETag(\n `${schemaName}-data-${lastProcessedTimestamp}-${itemCount}`,\n )\n}\n\n/**\n * Generate an ETag for a single SeedRecord.\n */\nexport function generateItemETag(\n seedUid: string,\n versionUid: string,\n timeCreated: number,\n optionsKey: string,\n): string {\n return generateETag(\n `${seedUid}-${versionUid}-${timeCreated}-${optionsKey}`,\n )\n}\n","import type { GetSeedResult, SeedRecord } from '../types.js'\nimport { generateCollectionETag, generateItemETag } from './etag.js'\nimport type {\n CachedCollectionData,\n CachedItemData,\n QueryCacheConfig,\n} from './types.js'\n\n/**\n * In-memory collection + item cache with TTL and refresh locks.\n */\nexport class MemoryCache {\n private collectionCache: Map<string, CachedCollectionData> = new Map()\n private itemCache: Map<string, CachedItemData> = new Map()\n private config: QueryCacheConfig\n private refreshLocks: Map<string, Promise<unknown>> = new Map()\n\n constructor(config: QueryCacheConfig) {\n this.config = config\n }\n\n private itemKey(seedUid: string, optionsKey: string): string {\n return `${seedUid}:${optionsKey}`\n }\n\n getCollection(schemaName: string): CachedCollectionData | null {\n const cached = this.collectionCache.get(schemaName)\n if (!cached) return null\n\n const now = Math.floor(Date.now() / 1000)\n if (now - cached.lastUpdated > this.config.ttl) {\n this.collectionCache.delete(schemaName)\n return null\n }\n return cached\n }\n\n setCollection(schemaName: string, items: SeedRecord[]): CachedCollectionData {\n const now = Math.floor(Date.now() / 1000)\n let lastProcessedTimestamp = 0\n let lastProcessedItemId = ''\n\n for (const item of items) {\n if (item.timeCreated && item.timeCreated > lastProcessedTimestamp) {\n lastProcessedTimestamp = item.timeCreated\n lastProcessedItemId = item.seedUid\n }\n }\n if (lastProcessedTimestamp === 0) {\n lastProcessedTimestamp = now\n }\n\n const etag = generateCollectionETag(\n schemaName,\n lastProcessedTimestamp,\n items.length,\n )\n\n const cached: CachedCollectionData = {\n items: items.map((r) => ({ ...r, data: { ...r.data } })),\n lastProcessedTimestamp,\n lastProcessedItemId,\n lastUpdated: now,\n etag,\n }\n this.collectionCache.set(schemaName, cached)\n return cached\n }\n\n getItem(seedUid: string, optionsKey: string): CachedItemData | null {\n const cached = this.itemCache.get(this.itemKey(seedUid, optionsKey))\n if (!cached) return null\n\n const now = Math.floor(Date.now() / 1000)\n if (now - cached.lastUpdated > this.config.ttl) {\n this.itemCache.delete(this.itemKey(seedUid, optionsKey))\n return null\n }\n return cached\n }\n\n setItem(\n record: GetSeedResult,\n optionsKey: string,\n ): CachedItemData {\n const now = Math.floor(Date.now() / 1000)\n const etag = generateItemETag(\n record.seedUid,\n record.versionUid,\n record.timeCreated,\n optionsKey,\n )\n const cachedRecord: GetSeedResult = {\n ...record,\n data: { ...record.data },\n }\n if (record.changelog) {\n cachedRecord.changelog = [...record.changelog]\n }\n const cached: CachedItemData = {\n record: cachedRecord,\n lastUpdated: now,\n etag,\n optionsKey,\n }\n this.itemCache.set(this.itemKey(record.seedUid, optionsKey), cached)\n return cached\n }\n\n clearCollection(schemaName: string): void {\n this.collectionCache.delete(schemaName)\n }\n\n clearItem(seedUid: string, optionsKey?: string): void {\n if (optionsKey) {\n this.itemCache.delete(this.itemKey(seedUid, optionsKey))\n return\n }\n for (const key of this.itemCache.keys()) {\n if (key.startsWith(`${seedUid}:`)) {\n this.itemCache.delete(key)\n }\n }\n }\n\n clearAll(): void {\n this.collectionCache.clear()\n this.itemCache.clear()\n }\n\n /**\n * Single-flight: concurrent callers for the same schema share one in-flight promise.\n */\n async withRefreshLock<T>(\n schemaName: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n const existingLock = this.refreshLocks.get(schemaName)\n if (existingLock) {\n return existingLock as Promise<T>\n }\n\n const lockPromise = (async () => {\n try {\n return await fn()\n } finally {\n this.refreshLocks.delete(schemaName)\n }\n })()\n\n this.refreshLocks.set(schemaName, lockPromise)\n return lockPromise\n }\n\n updateConfig(config: Partial<QueryCacheConfig>): void {\n this.config = { ...this.config, ...config }\n }\n\n getStats(): {\n collectionCount: number\n itemCount: number\n activeLocks: number\n } {\n return {\n collectionCount: this.collectionCache.size,\n itemCount: this.itemCache.size,\n activeLocks: this.refreshLocks.size,\n }\n }\n}\n","import type { GetSeedResult, SeedRecord } from '../types.js'\nimport { MemoryCache } from './MemoryCache.js'\nimport type {\n CachedCollectionData,\n CachedItemData,\n PersistentCache,\n QueryCacheConfig,\n QueryCacheStats,\n} from './types.js'\n\ntype PersistentCacheFactory = (config: QueryCacheConfig) => PersistentCache | null\n\nlet persistentCacheFactory: PersistentCacheFactory = () => null\n\n/**\n * Node entry (`index.node.ts`) registers FileCache here so the browser\n * graph never statically imports `fs` / `path`.\n */\nexport function configurePersistentCacheFactory(\n factory: PersistentCacheFactory,\n): void {\n persistentCacheFactory = factory\n}\n\n/**\n * Unified query cache: memory, with optional persistent (disk) layer.\n */\nexport class CacheManager {\n private memoryCache: MemoryCache\n private persistent: PersistentCache | null\n private config: QueryCacheConfig\n private stats: QueryCacheStats = {\n hits: 0,\n misses: 0,\n refreshes: 0,\n errors: 0,\n }\n\n constructor(config: QueryCacheConfig, persistent?: PersistentCache | null) {\n this.config = config\n this.memoryCache = new MemoryCache(config)\n if (persistent === undefined) {\n this.persistent = persistentCacheFactory(config)\n } else {\n this.persistent = persistent\n }\n }\n\n get enabled(): boolean {\n return this.config.enabled\n }\n\n getConfig(): QueryCacheConfig {\n return { ...this.config }\n }\n\n async getCollection(\n schemaName: string,\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n let cached = this.memoryCache.getCollection(schemaName)\n if (cached) {\n this.stats.hits++\n return cached\n }\n\n cached = (await this.persistent?.getCollection(schemaName)) ?? null\n if (cached) {\n this.memoryCache.setCollection(schemaName, cached.items)\n this.stats.hits++\n return cached\n }\n\n this.stats.misses++\n return null\n } catch (error) {\n console.error(\n `Error getting query collection cache for ${schemaName}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async setCollection(\n schemaName: string,\n items: SeedRecord[],\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n const cached = this.memoryCache.setCollection(schemaName, items)\n await this.persistent?.setCollection(schemaName, cached)\n return cached\n } catch (error) {\n console.error(\n `Error setting query collection cache for ${schemaName}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async getItem(\n seedUid: string,\n optionsKey: string,\n ): Promise<CachedItemData | null> {\n if (!this.config.enabled) return null\n\n try {\n let cached = this.memoryCache.getItem(seedUid, optionsKey)\n if (cached) {\n this.stats.hits++\n return cached\n }\n\n cached = (await this.persistent?.getItem(seedUid, optionsKey)) ?? null\n if (cached) {\n this.memoryCache.setItem(cached.record, optionsKey)\n this.stats.hits++\n return cached\n }\n\n this.stats.misses++\n return null\n } catch (error) {\n console.error(`Error getting query item cache for ${seedUid}:`, error)\n this.stats.errors++\n return null\n }\n }\n\n async setItem(\n record: GetSeedResult,\n optionsKey: string,\n ): Promise<CachedItemData | null> {\n if (!this.config.enabled) return null\n\n try {\n const cached = this.memoryCache.setItem(record, optionsKey)\n await this.persistent?.setItem(cached)\n return cached\n } catch (error) {\n console.error(\n `Error setting query item cache for ${record.seedUid}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async writeThroughItems(\n items: SeedRecord[],\n optionsKey: string,\n ): Promise<void> {\n if (!this.config.enabled) return\n for (const item of items) {\n await this.setItem(item, optionsKey)\n }\n }\n\n async clearCollection(schemaName: string): Promise<void> {\n this.memoryCache.clearCollection(schemaName)\n await this.persistent?.clearCollection(schemaName)\n }\n\n async clearAll(): Promise<void> {\n this.memoryCache.clearAll()\n await this.persistent?.clearAll()\n }\n\n async withRefreshLock<T>(\n schemaName: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n return this.memoryCache.withRefreshLock(schemaName, fn)\n }\n\n /**\n * Merge records by seedUid; new wins. Sort by timeCreated descending.\n */\n mergeRecords(\n cachedItems: SeedRecord[],\n newItems: SeedRecord[],\n ): SeedRecord[] {\n const itemMap = new Map<string, SeedRecord>()\n\n for (const item of cachedItems) {\n if (item.seedUid) itemMap.set(item.seedUid, item)\n }\n for (const item of newItems) {\n if (item.seedUid) {\n itemMap.set(item.seedUid, item)\n } else {\n itemMap.set(`temp-${Date.now()}-${Math.random()}`, item)\n }\n }\n\n const merged = Array.from(itemMap.values())\n merged.sort((a, b) => (b.timeCreated || 0) - (a.timeCreated || 0))\n return merged\n }\n\n /**\n * Keep only records newer than lastProcessedTimestamp.\n */\n filterNewRecords(\n items: SeedRecord[],\n lastProcessedTimestamp: number,\n ): SeedRecord[] {\n return items.filter(\n (item) => item.timeCreated && item.timeCreated > lastProcessedTimestamp,\n )\n }\n\n updateConfig(config: Partial<QueryCacheConfig>): void {\n this.config = { ...this.config, ...config }\n this.memoryCache.updateConfig(this.config)\n }\n\n getStats(): QueryCacheStats & {\n memoryStats: ReturnType<MemoryCache['getStats']>\n } {\n return {\n ...this.stats,\n memoryStats: this.memoryCache.getStats(),\n }\n }\n\n resetStats(): void {\n this.stats = {\n hits: 0,\n misses: 0,\n refreshes: 0,\n errors: 0,\n }\n }\n}\n","import type { QueryCacheConfig } from './types.js'\n\nfunction env(): Record<string, string | undefined> {\n const processEnv = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process?.env\n return processEnv ?? {}\n}\n\n/**\n * Load query cache configuration from environment variables.\n *\n * Uses the same CACHE_* vars as feed for ops compatibility:\n * - CACHE_ENABLED\n * - CACHE_TTL (default 3600)\n * - CACHE_DIR (default ./cache)\n * - CACHE_BACKGROUND_REFRESH / CACHE_REFRESH_INTERVAL (unused stubs)\n *\n * In development (NODE_ENV=development), cache is disabled unless\n * CACHE_ENABLED is explicitly true.\n */\nexport function loadQueryCacheConfig(): QueryCacheConfig {\n const e = env()\n const ttl = parseInt(e.CACHE_TTL || '3600', 10)\n const cacheDir = e.CACHE_DIR || './cache'\n\n const cacheDisabledByEnvVar =\n e.CACHE_ENABLED === 'false' ||\n e.CACHE_ENABLED === '0' ||\n e.CACHE_ENABLED === 'no' ||\n e.CACHE_ENABLED === 'off'\n const cacheEnabledByEnvVar =\n e.CACHE_ENABLED === 'true' ||\n e.CACHE_ENABLED === '1' ||\n e.CACHE_ENABLED === 'yes'\n const isDev = e.NODE_ENV === 'development'\n\n let enabled: boolean\n if (cacheDisabledByEnvVar) {\n enabled = false\n } else if (cacheEnabledByEnvVar) {\n enabled = true\n } else if (isDev) {\n enabled = false\n } else {\n enabled = true\n }\n\n const backgroundRefresh = e.CACHE_BACKGROUND_REFRESH === 'true'\n const refreshInterval = parseInt(e.CACHE_REFRESH_INTERVAL || '300', 10)\n\n return {\n ttl,\n cacheDir,\n enabled,\n backgroundRefresh,\n refreshInterval,\n }\n}\n","import { CacheManager } from './CacheManager.js'\nimport { loadQueryCacheConfig } from './config.js'\nimport type { PersistentCache, QueryCacheConfig } from './types.js'\n\nexport { CacheManager, configurePersistentCacheFactory } from './CacheManager.js'\nexport { MemoryCache } from './MemoryCache.js'\nexport { loadQueryCacheConfig } from './config.js'\nexport {\n generateETag,\n generateCollectionETag,\n generateItemETag,\n} from './etag.js'\nexport {\n buildAssembleOptionsKey,\n sanitizeSeedUidForPath,\n} from './types.js'\nexport type {\n CachedCollectionData,\n CachedItemData,\n PersistentCache,\n QueryCacheConfig,\n QueryCacheStats,\n} from './types.js'\n\nlet cacheManager: CacheManager | null = null\n\n/**\n * Get the singleton query CacheManager (lazy-init from env).\n * Browser graphs are memory-only. Node `index.node` registers FileCache.\n */\nexport function getQueryCacheManager(): CacheManager {\n if (!cacheManager) {\n cacheManager = new CacheManager(loadQueryCacheConfig())\n }\n return cacheManager\n}\n\n/**\n * Reset singleton (tests / config reload).\n */\nexport function resetQueryCacheManager(): void {\n cacheManager = null\n}\n\n/**\n * Create a CacheManager with an explicit config (tests).\n * Pass a PersistentCache (e.g. FileCache) to enable the disk layer.\n */\nexport function createQueryCacheManager(\n config?: Partial<QueryCacheConfig>,\n persistent?: PersistentCache | null,\n): CacheManager {\n return new CacheManager(\n {\n ...loadQueryCacheConfig(),\n ...config,\n },\n persistent,\n )\n}\n","import type { QueryDataSource } from './types.js'\n\nlet localSource: QueryDataSource | null = null\n\n/**\n * Register the SDK (or test) local SQLite/files adapter.\n * Replaces any previously registered local source.\n */\nexport function registerLocalQuerySource(source: QueryDataSource): void {\n if (source.kind !== 'local') {\n throw new Error(\n '[query] registerLocalQuerySource expects a source with kind: \"local\"',\n )\n }\n localSource = source\n}\n\n/** Clear the registered local source (tests / teardown). */\nexport function clearLocalQuerySource(): void {\n localSource = null\n}\n\nexport function getRegisteredLocalQuerySource(): QueryDataSource | null {\n return localSource\n}\n\nexport function hasLocalQuerySource(): boolean {\n return localSource != null\n}\n","import type { QuerySourceMode } from '../types.js'\nimport { getRegisteredLocalQuerySource } from './registry.js'\nimport { getRemoteQueryDataSource } from './remote.js'\nimport type { QueryDataSource } from './types.js'\n\nexport type ResolvedQuerySource = {\n mode: QuerySourceMode\n dataSource: QueryDataSource\n /** True when CacheManager may be used for this call. */\n useQueryCache: boolean\n}\n\n/**\n * Resolve which data source to use for a call.\n * - remote (default): EAS\n * - local: registered adapter or throw\n * - auto: prefer local when registered; else remote (caller may still fall back per-seed)\n */\nexport function resolveQuerySource(\n mode: QuerySourceMode = 'remote',\n): ResolvedQuerySource {\n if (mode === 'remote') {\n return {\n mode: 'remote',\n dataSource: getRemoteQueryDataSource(),\n useQueryCache: true,\n }\n }\n\n const local = getRegisteredLocalQuerySource()\n\n if (mode === 'local') {\n if (!local) {\n throw new Error(\n '[query] source: \"local\" requires registerLocalQuerySource(...) (e.g. SDK DB ready)',\n )\n }\n return {\n mode: 'local',\n dataSource: local,\n useQueryCache: false,\n }\n }\n\n // auto\n if (local) {\n return {\n mode: 'auto',\n dataSource: local,\n useQueryCache: false,\n }\n }\n return {\n mode: 'auto',\n dataSource: getRemoteQueryDataSource(),\n useQueryCache: true,\n }\n}\n\nexport function normalizeSourceMode(\n source?: QuerySourceMode,\n): QuerySourceMode {\n return source ?? 'remote'\n}\n","import { initializeQueryPlatform } from './bootstrap.js'\nimport { assembleSeeds } from './assembleSeeds.js'\nimport { assembleSeedChangelog } from './assembleChangelog.js'\nimport {\n buildAssembleOptionsKey,\n getQueryCacheManager,\n} from './cache/index.js'\nimport {\n normalizeSourceMode,\n resolveQuerySource,\n getRemoteQueryDataSource,\n} from './source/index.js'\nimport type { QueryDataSource } from './source/types.js'\nimport type {\n AssembleOptions,\n GetSeedOptions,\n GetSeedResult,\n QueryBySchemaOptions,\n QueryBySchemaResult,\n SeedRecord,\n} from './types.js'\n\nfunction shouldUseCache(\n options: AssembleOptions | undefined,\n allowCache: boolean,\n): boolean {\n if (!allowCache) return false\n if (options?.cache === false) return false\n return getQueryCacheManager().enabled\n}\n\nfunction wantsChangelog(include: GetSeedOptions['include']): boolean {\n return include === 'data+changelog' || include === 'changelog'\n}\n\nfunction wantsData(include: GetSeedOptions['include']): boolean {\n return include !== 'changelog'\n}\n\nasync function fetchAndAssemble(\n schemaName: string,\n limit: number,\n skip: number,\n options: AssembleOptions | undefined,\n dataSource: QueryDataSource,\n): Promise<SeedRecord[]> {\n const seeds = await dataSource.listSeedsBySchemaName(schemaName, {\n limit,\n skip,\n })\n return assembleSeeds(schemaName, seeds, options, dataSource)\n}\n\n/**\n * For `source: 'auto'`: try local first; if empty/miss, fall back to remote.\n */\nasync function withAutoFallbackForCollection(\n mode: ReturnType<typeof normalizeSourceMode>,\n dataSource: QueryDataSource,\n run: (ds: QueryDataSource) => Promise<SeedRecord[]>,\n): Promise<{ items: SeedRecord[]; dataSource: QueryDataSource; useQueryCache: boolean }> {\n const items = await run(dataSource)\n if (mode !== 'auto' || dataSource.kind !== 'local') {\n return {\n items,\n dataSource,\n useQueryCache: dataSource.kind === 'remote',\n }\n }\n if (items.length > 0) {\n return { items, dataSource, useQueryCache: false }\n }\n const remote = getRemoteQueryDataSource()\n const remoteItems = await run(remote)\n return { items: remoteItems, dataSource: remote, useQueryCache: true }\n}\n\nexport async function queryBySchema(\n schemaName: string,\n options?: QueryBySchemaOptions,\n): Promise<QueryBySchemaResult> {\n await initializeQueryPlatform()\n const limit = options?.limit ?? 100\n const skip = options?.skip ?? 0\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n const optionsKey = buildAssembleOptionsKey(options)\n\n const runAssemble = (ds: QueryDataSource) =>\n fetchAndAssemble(schemaName, limit, skip, options, ds)\n\n // Collection cache only for remote + skip=0 working set\n if (\n shouldUseCache(options, resolved.useQueryCache) &&\n skip === 0 &&\n resolved.dataSource.kind === 'remote'\n ) {\n const cache = getQueryCacheManager()\n return cache.withRefreshLock(schemaName, async () => {\n const cachedData = await cache.getCollection(schemaName)\n let items: SeedRecord[]\n let etag: string | undefined\n\n if (cachedData) {\n const pageItems = await fetchAndAssemble(\n schemaName,\n limit,\n 0,\n options,\n resolved.dataSource,\n )\n const newItems = cache.filterNewRecords(\n pageItems,\n cachedData.lastProcessedTimestamp,\n )\n\n if (newItems.length > 0) {\n items = cache\n .mergeRecords(cachedData.items, newItems)\n .slice(0, limit)\n } else {\n items = cachedData.items.slice(0, limit)\n }\n } else {\n items = await fetchAndAssemble(\n schemaName,\n limit,\n 0,\n options,\n resolved.dataSource,\n )\n }\n\n const stored = await cache.setCollection(schemaName, items)\n etag = stored?.etag\n await cache.writeThroughItems(items, optionsKey)\n\n return { items, limit, skip, etag }\n })\n }\n\n const {\n items,\n dataSource: used,\n useQueryCache,\n } = await withAutoFallbackForCollection(mode, resolved.dataSource, (ds) =>\n runAssemble(ds),\n )\n\n if (shouldUseCache(options, useQueryCache) && used.kind === 'remote') {\n await getQueryCacheManager().writeThroughItems(items, optionsKey)\n }\n return { items, limit, skip }\n}\n\nexport async function getSeed(\n seedUid: string,\n options?: GetSeedOptions,\n): Promise<GetSeedResult | null> {\n await initializeQueryPlatform()\n if (!seedUid || typeof seedUid !== 'string' || seedUid.trim() === '') {\n return null\n }\n\n const trimmed = seedUid.trim()\n const include = options?.include ?? 'data'\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n const optionsKey = buildAssembleOptionsKey(options)\n\n let dataSource = resolved.dataSource\n let allowCache = resolved.useQueryCache\n\n if (shouldUseCache(options, allowCache) && dataSource.kind === 'remote') {\n const cached = await getQueryCacheManager().getItem(trimmed, optionsKey)\n if (cached) {\n return cached.record\n }\n }\n\n let seed = await dataSource.getSeedByUid(trimmed)\n\n // auto: local miss → remote\n if (!seed && mode === 'auto' && dataSource.kind === 'local') {\n dataSource = getRemoteQueryDataSource()\n allowCache = true\n seed = await dataSource.getSeedByUid(trimmed)\n if (shouldUseCache(options, allowCache)) {\n const cached = await getQueryCacheManager().getItem(trimmed, optionsKey)\n if (cached) {\n return cached.record\n }\n }\n }\n\n if (!seed) return null\n\n const schemaName = seed.schema?.schemaNames?.[0]?.name\n if (!schemaName) return null\n\n let result: GetSeedResult | null = null\n\n if (!wantsChangelog(include)) {\n const records = await assembleSeeds(schemaName, [seed], options, dataSource)\n result = records[0] ?? null\n } else {\n const { latestVersionUid, changelog } = await assembleSeedChangelog(\n trimmed,\n options,\n dataSource,\n )\n\n if (wantsData(include)) {\n const records = await assembleSeeds(\n schemaName,\n [seed],\n options,\n dataSource,\n )\n const record = records[0]\n if (!record) {\n result = null\n } else {\n result = { ...record, changelog }\n }\n } else {\n result = {\n seedUid: trimmed,\n schemaName,\n attester: seed.attester,\n timeCreated: seed.timeCreated,\n versionUid: latestVersionUid,\n data: {},\n changelog,\n }\n }\n }\n\n if (\n result &&\n shouldUseCache(options, allowCache) &&\n dataSource.kind === 'remote'\n ) {\n await getQueryCacheManager().setItem(result, optionsKey)\n }\n\n return result\n}\n\n/**\n * Query seeds of a schema created within a calendar month (local timezone bounds).\n * No collection cache; may write-through to item cache when remote.\n */\nexport async function queryBySchemaForMonth(\n schemaName: string,\n year: number,\n month: number,\n options?: AssembleOptions,\n): Promise<SeedRecord[]> {\n await initializeQueryPlatform()\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n\n const run = async (ds: QueryDataSource) => {\n const seeds = await ds.listSeedsBySchemaNameForMonth(\n schemaName,\n year,\n month,\n )\n return assembleSeeds(schemaName, seeds, options, ds)\n }\n\n const { items, dataSource: used, useQueryCache } =\n await withAutoFallbackForCollection(mode, resolved.dataSource, run)\n\n if (shouldUseCache(options, useQueryCache) && used.kind === 'remote') {\n const optionsKey = buildAssembleOptionsKey(options)\n await getQueryCacheManager().writeThroughItems(items, optionsKey)\n }\n\n return items\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seedprotocol/query",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.8",
|
|
4
4
|
"description": "Canonical Seed JSON query (remote EAS + local SQLite adapters) for Seed Protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@noble/hashes": "^1.8.0",
|
|
44
|
-
"@seedprotocol/arweave": "0.6.
|
|
45
|
-
"@seedprotocol/eas": "0.6.
|
|
44
|
+
"@seedprotocol/arweave": "0.6.8",
|
|
45
|
+
"@seedprotocol/eas": "0.6.8",
|
|
46
46
|
"graphql-request": "^7.3.5",
|
|
47
47
|
"pluralize": "^8.0.0"
|
|
48
48
|
},
|
package/dist/src-BoSE9m_G.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"src-BoSE9m_G.js","names":[],"sources":["../src/arweaveUrl.ts","../src/listRelationKey.ts","../src/imageRelationEnrichment.ts","../src/fieldStorageModel.ts","../src/hydrateArweaveRichText.ts","../src/parseEasPropertyMetadata.ts","../src/parseEasRelationPropertyName.ts","../src/source/remote.ts","../src/assembleSeeds.ts","../src/changelog.ts","../src/assembleChangelog.ts","../src/cache/etag.ts","../src/cache/MemoryCache.ts","../src/cache/CacheManager.ts","../src/cache/config.ts","../src/cache/index.ts","../src/source/registry.ts","../src/source/resolve.ts","../src/api.ts"],"sourcesContent":["import { BaseArweaveClient } from '@seedprotocol/arweave'\n\n/**\n * Builds an Arweave gateway URL for a transaction ID (no `/raw` segment).\n */\nexport function getArweaveUrlForTransaction(transactionId: string): string {\n return `https://${BaseArweaveClient.getHost()}/${transactionId}`\n}\n","import pluralize from 'pluralize'\n\n/** Matches SDK list storage: singular(schemaKey) + PascalCase(ref) + \"Ids\", e.g. authorIdentityIds → authors */\nconst CAMEL_LIST_RELATION_IDS = /^(.+?)([A-Z][a-zA-Z]+)Ids$/\n\n/**\n * Maps list-relation storage / wire names to schema-facing plural keys (e.g. `authorIdentityIds` → `authors`).\n * Non-matching keys are returned unchanged.\n */\nexport function publicListRelationPropertyKey(propertyKey: string): string {\n const camel = CAMEL_LIST_RELATION_IDS.exec(propertyKey)\n if (camel) {\n const singularPart = camel[1]\n if (singularPart) return pluralize(singularPart)\n }\n if (propertyKey.endsWith('_ids')) {\n const base = propertyKey.slice(0, -4)\n const segments = base.split('_').filter(Boolean)\n if (segments.length >= 2) {\n const singularProperty = segments[0]!\n return singularProperty.endsWith('s') ? singularProperty : pluralize(singularProperty)\n }\n return pluralize(base)\n }\n return propertyKey\n}\n\n/**\n * Removes keys that are storage aliases for the same list relation as `publicKey`\n * (e.g. delete `authorIdentityIds` when `authors` is the canonical field).\n */\nexport function stripListRelationStorageAliasesForPublicKey(\n item: Record<string, unknown>,\n publicKey: string,\n): void {\n for (const k of Object.keys(item)) {\n if (k === publicKey) continue\n if (publicListRelationPropertyKey(k) === publicKey) {\n delete item[k]\n }\n }\n}\n\n/** If value is a JSON array string from legacy assembly, parse to string[]. */\nexport function tryCoerceJsonStringArray(value: unknown): unknown {\n if (Array.isArray(value)) return value\n if (typeof value !== 'string') return value\n const s = value.trim()\n if (!s.startsWith('[')) return value\n try {\n const parsed = JSON.parse(s) as unknown\n if (Array.isArray(parsed)) return parsed\n } catch {\n // keep original\n }\n return value\n}\n","import { getArweaveUrlForTransaction } from './arweaveUrl.js'\n\n/**\n * Adds `arweaveUrl` to an assembled Image seed clone when `storageTransactionId`\n * (or snake_case) is present.\n */\nexport function enrichImageSeedClone(clone: Record<string, unknown>): void {\n const txId = (clone.storageTransactionId ?? clone.storage_transaction_id) as\n | string\n | undefined\n if (txId && typeof txId === 'string' && txId.trim()) {\n try {\n clone.arweaveUrl = getArweaveUrlForTransaction(txId.trim())\n } catch {\n // keep clone without arweaveUrl\n }\n }\n}\n\n/** @deprecated Use {@link enrichImageSeedClone} */\nexport const enrichImageSeedCloneForFeed = enrichImageSeedClone\n","/** Related Seed schema names (lowercased) used as primary rich-body sources. */\nexport const RICH_BODY_STORAGE_SCHEMAS = new Set(['html', 'file', 'json'])\n\n/** @deprecated Alias for {@link RICH_BODY_STORAGE_SCHEMAS} (feed key compatibility). */\nexport const FEED_RICH_BODY_STORAGE_SCHEMAS = RICH_BODY_STORAGE_SCHEMAS\n\n/** Kept as `_feedFieldStorageModels` for feed/RSS pickers in Phase 1. */\nconst FIELD_MODELS_KEY = '_feedFieldStorageModels' as const\nconst LIST_MODELS_KEY = '_feedListElementStorageModels' as const\n\nexport type FieldStorageModels = Record<string, string>\nexport type ListElementStorageModels = Record<string, string[]>\n\n/** @deprecated Use {@link FieldStorageModels} */\nexport type FeedFieldStorageModels = FieldStorageModels\n/** @deprecated Use {@link ListElementStorageModels} */\nexport type FeedListElementStorageModels = ListElementStorageModels\n\nfunction normalizeModelName(schemaName: string): string {\n return schemaName.trim().toLowerCase()\n}\n\nexport function isRichBodyStorageSchema(schemaName: string): boolean {\n return RICH_BODY_STORAGE_SCHEMAS.has(normalizeModelName(schemaName))\n}\n\n/** @deprecated Use {@link isRichBodyStorageSchema} */\nexport const isFeedRichBodyStorageSchema = isRichBodyStorageSchema\n\n/** html < file < json for tie-breaking among rich body fields. */\nexport function richBodyModelPriority(schemaName: string): number {\n const m = normalizeModelName(schemaName)\n if (m === 'html') return 0\n if (m === 'file') return 1\n if (m === 'json') return 2\n return 99\n}\n\n/** @deprecated Use {@link richBodyModelPriority} */\nexport const feedRichBodyModelPriority = richBodyModelPriority\n\nexport function getFieldStorageModels(\n item: Record<string, unknown>,\n): FieldStorageModels | undefined {\n const raw = item[FIELD_MODELS_KEY]\n if (raw !== null && typeof raw === 'object' && !Array.isArray(raw)) {\n return raw as FieldStorageModels\n }\n return undefined\n}\n\n/** @deprecated Use {@link getFieldStorageModels} */\nexport const getFeedFieldStorageModels = getFieldStorageModels\n\nexport function getListElementStorageModels(\n item: Record<string, unknown>,\n): ListElementStorageModels | undefined {\n const raw = item[LIST_MODELS_KEY]\n if (raw !== null && typeof raw === 'object' && !Array.isArray(raw)) {\n return raw as ListElementStorageModels\n }\n return undefined\n}\n\n/** @deprecated Use {@link getListElementStorageModels} */\nexport const getFeedListElementStorageModels = getListElementStorageModels\n\nexport function setFieldStorageModel(\n item: Record<string, unknown>,\n fieldKey: string,\n schemaName: string,\n): void {\n const normalized = normalizeModelName(schemaName)\n let map = getFieldStorageModels(item)\n if (!map) {\n map = {}\n item[FIELD_MODELS_KEY] = map\n }\n map[fieldKey] = normalized\n}\n\n/** @deprecated Use {@link setFieldStorageModel} */\nexport const setFeedFieldStorageModel = setFieldStorageModel\n\nexport function setListElementStorageModels(\n item: Record<string, unknown>,\n outputKey: string,\n models: string[],\n): void {\n let map = getListElementStorageModels(item)\n if (!map) {\n map = {}\n item[LIST_MODELS_KEY] = map\n }\n map[outputKey] = models.map(normalizeModelName)\n}\n\n/** @deprecated Use {@link setListElementStorageModels} */\nexport const setFeedListElementStorageModels = setListElementStorageModels\n","import { BaseArweaveClient, isKnownArweaveGatewayHostname } from '@seedprotocol/arweave'\nimport {\n getFieldStorageModels,\n getListElementStorageModels,\n isRichBodyStorageSchema,\n} from './fieldStorageModel.js'\n\n/** Same logical fields as legacy rich-text primary keys — inline HTML/body for consumers. */\nconst RICH_TEXT_KEYS = ['html', 'Html', 'body', 'Body', 'content', 'Content'] as const\n\n/** Max UTF-8 bytes for a single rich-body fetch. */\nconst MAX_BODY_BYTES = 8_000_000\n\nexport type HydrateStorageOptions = {\n /** Prefer local file body when available; fall back to Arweave gateway fetch. */\n readStorageBody?: (ref: {\n propertyName: string\n value: unknown\n localPathHint?: string\n }) => Promise<string | null>\n}\n\n/**\n * True for a single-path gateway URL whose path looks like an Arweave transaction id.\n */\nexport function isArweaveTransactionGatewayUrl(raw: string): boolean {\n const s = raw.trim()\n if (!s.startsWith('http://') && !s.startsWith('https://')) return false\n try {\n const u = new URL(s)\n const host = u.hostname.toLowerCase()\n const expected = BaseArweaveClient.getHost().toLowerCase()\n if (host !== expected && !isKnownArweaveGatewayHostname(host)) return false\n const segments = u.pathname.replace(/^\\//, '').split('/').filter(Boolean)\n if (segments.length !== 1) return false\n const id = segments[0]!\n return /^[A-Za-z0-9_-]{43}$/.test(id)\n } catch {\n return false\n }\n}\n\nasync function fetchGatewayPayloadAsUtf8(url: string): Promise<string | null> {\n try {\n const res = await fetch(url, {\n headers: { Accept: 'text/html, text/plain, text/markdown, application/json, */*' },\n signal: AbortSignal.timeout(15_000),\n })\n if (!res.ok) return null\n const ct = res.headers.get('content-type') ?? ''\n if (/^(image|video|audio)\\//i.test(ct)) return null\n const buf = await res.arrayBuffer()\n if (buf.byteLength > MAX_BODY_BYTES) return null\n const text = new TextDecoder('utf-8', { fatal: false }).decode(buf)\n if (text.length === 0 || text.includes('\\0')) return null\n return text\n } catch {\n return null\n }\n}\n\nasync function resolveHydratedBody(\n propertyName: string,\n value: string,\n readStorageBody?: HydrateStorageOptions['readStorageBody'],\n): Promise<string | null> {\n if (readStorageBody) {\n try {\n const local = await readStorageBody({ propertyName, value })\n if (local != null && local.length > 0) return local\n } catch {\n // fall through to gateway\n }\n }\n if (!isArweaveTransactionGatewayUrl(value)) return null\n return fetchGatewayPayloadAsUtf8(value)\n}\n\nasync function hydrateStringField(\n item: Record<string, unknown>,\n key: string,\n readStorageBody?: HydrateStorageOptions['readStorageBody'],\n): Promise<void> {\n const v = item[key]\n if (typeof v !== 'string' || v.trim() === '') return\n const text = await resolveHydratedBody(key, v, readStorageBody)\n if (text === null) return\n item[key] = text\n}\n\n/**\n * After relation URL resolution, Html/File fields may be gateway URLs (or local paths).\n * Replace those with the UTF-8 body when `hydrateStorage` is enabled.\n */\nexport async function hydrateArweaveRichTextInItems(\n items: Record<string, unknown>[],\n options?: HydrateStorageOptions,\n): Promise<void> {\n const readStorageBody = options?.readStorageBody\n for (const item of items) {\n const keysToHydrate = new Set<string>([...RICH_TEXT_KEYS])\n const fieldModels = getFieldStorageModels(item)\n if (fieldModels) {\n for (const [k, m] of Object.entries(fieldModels)) {\n if (isRichBodyStorageSchema(m)) keysToHydrate.add(k)\n }\n }\n for (const key of keysToHydrate) {\n await hydrateStringField(item, key, readStorageBody)\n }\n\n const listModels = getListElementStorageModels(item)\n if (listModels) {\n for (const [listKey, models] of Object.entries(listModels)) {\n const arr = item[listKey]\n if (!Array.isArray(arr)) continue\n const n = Math.min(models.length, arr.length)\n for (let i = 0; i < n; i++) {\n if (!isRichBodyStorageSchema(models[i]!)) continue\n const el = arr[i]\n if (typeof el !== 'string') continue\n const text = await resolveHydratedBody(listKey, el, readStorageBody)\n if (text === null) continue\n arr[i] = text\n }\n }\n }\n }\n}\n\n/** @deprecated Use {@link hydrateArweaveRichTextInItems} */\nexport const hydrateArweaveRichTextInFeedItems = hydrateArweaveRichTextInItems\n","export type EasPropertyMetadata = {\n name: string\n value: string | string[]\n type?: string\n}\n\nexport type ParseEasPropertyMetadataResult =\n | { ok: true; metadata: EasPropertyMetadata }\n | { ok: false; reason: 'empty' }\n | { ok: false; reason: 'shape' }\n | { ok: false; reason: 'parse'; error: unknown }\n\n/**\n * Parse EAS property `decodedDataJson`.\n * Matches SDK guards in syncDbWithEas / saveDataToDb (empty trim, parse, array + [0].value).\n */\nexport function parseEasPropertyMetadata(\n decodedDataJson: string | undefined | null,\n): ParseEasPropertyMetadataResult {\n const raw = typeof decodedDataJson === 'string' ? decodedDataJson.trim() : ''\n if (!raw) {\n return { ok: false, reason: 'empty' }\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (e) {\n return { ok: false, reason: 'parse', error: e }\n }\n\n if (!Array.isArray(parsed) || parsed.length === 0 || !parsed[0]?.value) {\n return { ok: false, reason: 'shape' }\n }\n\n const metadata = parsed[0].value as EasPropertyMetadata\n return { ok: true, metadata }\n}\n\n/** @deprecated Use {@link parseEasPropertyMetadata} */\nexport const parseEasPropertyMetadataForFeed = parseEasPropertyMetadata\n/** @deprecated Use {@link EasPropertyMetadata} */\nexport type EasPropertyMetadataForFeed = EasPropertyMetadata\n/** @deprecated Use {@link ParseEasPropertyMetadataResult} */\nexport type ParseEasPropertyMetadataForFeedResult = ParseEasPropertyMetadataResult\n","export type ParsedEasRelationPropertyName = {\n propertyName: string\n modelName: string\n isList: boolean\n}\n\n/**\n * Parse EAS relation property naming: `{singular}_{model}_id` or `{singular}_{model}_ids`.\n * Returns null when the name does not match the expected shape.\n */\nexport function parseEasRelationPropertyName(\n easPropertyName: string,\n): ParsedEasRelationPropertyName | null {\n const [singularProperty, modelName, idSegment] = easPropertyName.split('_')\n if (!singularProperty || !modelName) return null\n const isList = idSegment === 'ids'\n const propertyName = singularProperty.endsWith('s')\n ? singularProperty\n : singularProperty + 's'\n return { propertyName, modelName, isList }\n}\n","import {\n getSeedsBySchemaName,\n getItemVersionsFromEas,\n getItemPropertiesFromEas,\n EasClient,\n withExcludeRevokedFilter,\n GET_SEEDS,\n} from '@seedprotocol/eas'\nimport type { AttestationLike } from '../types.js'\nimport type { QueryDataSource } from './types.js'\n\nfunction monthBoundsUnix(year: number, month: number): { startTs: number; endTs: number } {\n const startDate = new Date(year, month - 1, 1)\n const endDate = new Date(year, month, 0, 23, 59, 59)\n const startTs = Math.floor(startDate.getTime() / 1000)\n const endTs = Math.floor(endDate.getTime() / 1000) + 1\n return { startTs, endTs }\n}\n\n/**\n * Default remote data source: EAS GraphQL (+ callers hydrate via Arweave).\n */\nexport function createRemoteQueryDataSource(): QueryDataSource {\n return {\n kind: 'remote',\n\n async getSeedByUid(seedUid: string): Promise<AttestationLike | null> {\n const easClient = EasClient.getEasClient()\n const { itemSeeds } = await easClient.request(GET_SEEDS, {\n where: withExcludeRevokedFilter({\n id: { equals: seedUid },\n }),\n take: 1,\n skip: 0,\n })\n return ((itemSeeds ?? [])[0] as AttestationLike | undefined) ?? null\n },\n\n async listSeedsBySchemaName(\n schemaName: string,\n opts: { limit: number; skip: number },\n ): Promise<AttestationLike[]> {\n return (await getSeedsBySchemaName(\n schemaName,\n opts.limit,\n opts.skip,\n )) as AttestationLike[]\n },\n\n async listSeedsBySchemaNameForMonth(\n schemaName: string,\n year: number,\n month: number,\n ): Promise<AttestationLike[]> {\n const { startTs, endTs } = monthBoundsUnix(year, month)\n const where = withExcludeRevokedFilter({\n AND: [\n {\n schema: {\n is: {\n schemaNames: {\n some: {\n name: { equals: schemaName },\n },\n },\n },\n },\n },\n {\n timeCreated: { gte: startTs, lt: endTs },\n },\n ],\n })\n\n const easClient = EasClient.getEasClient()\n const { itemSeeds } = await easClient.request(GET_SEEDS, {\n where,\n take: 1000,\n skip: 0,\n })\n return (itemSeeds ?? []) as AttestationLike[]\n },\n\n async getVersionsForSeed(seedUid: string): Promise<AttestationLike[]> {\n return (await getItemVersionsFromEas({\n seedUids: [seedUid],\n })) as AttestationLike[]\n },\n\n async getVersionsForSeeds(seedUids: string[]): Promise<AttestationLike[]> {\n if (seedUids.length === 0) return []\n return (await getItemVersionsFromEas({ seedUids })) as AttestationLike[]\n },\n\n async getPropertiesForVersionUids(\n versionUids: string[],\n ): Promise<AttestationLike[]> {\n if (versionUids.length === 0) return []\n return (await getItemPropertiesFromEas({\n versionUids,\n })) as AttestationLike[]\n },\n\n async getSeedsByUids(uids: string[]): Promise<AttestationLike[]> {\n if (uids.length === 0) return []\n const easClient = EasClient.getEasClient()\n const { itemSeeds } = await easClient.request(GET_SEEDS, {\n where: withExcludeRevokedFilter({\n id: { in: uids },\n }),\n take: uids.length || 1,\n skip: 0,\n })\n return (itemSeeds ?? []) as AttestationLike[]\n },\n }\n}\n\nlet remoteSingleton: QueryDataSource | null = null\n\nexport function getRemoteQueryDataSource(): QueryDataSource {\n if (!remoteSingleton) {\n remoteSingleton = createRemoteQueryDataSource()\n }\n return remoteSingleton\n}\n\n/** Tests only. */\nexport function resetRemoteQueryDataSource(): void {\n remoteSingleton = null\n}\n","import {\n setSchemaUidForSchemaDefinition,\n pickLatestPropertyAttestationsByRefAndSchema,\n} from '@seedprotocol/eas'\nimport { getArweaveUrlForTransaction } from './arweaveUrl.js'\nimport {\n publicListRelationPropertyKey,\n stripListRelationStorageAliasesForPublicKey,\n tryCoerceJsonStringArray,\n} from './listRelationKey.js'\nimport { enrichImageSeedClone } from './imageRelationEnrichment.js'\nimport { hydrateArweaveRichTextInItems } from './hydrateArweaveRichText.js'\nimport { parseEasPropertyMetadata } from './parseEasPropertyMetadata.js'\nimport { parseEasRelationPropertyName } from './parseEasRelationPropertyName.js'\nimport {\n setFieldStorageModel,\n setListElementStorageModels,\n} from './fieldStorageModel.js'\nimport { getRemoteQueryDataSource } from './source/remote.js'\nimport type { QueryDataSource } from './source/types.js'\nimport type { AssembleOptions, AttestationLike, SeedRecord } from './types.js'\n\nconst IMAGE_SCHEMA = 'image'\n\nconst relationValuesToExclude = [\n '0x0000000000000000000000000000000000000000000000000000000000000020',\n]\n\nconst RESERVED_KEYS = new Set([\n 'seedUid',\n 'SeedUid',\n 'timeCreated',\n 'attester',\n 'Attester',\n 'storage_transaction_id',\n 'storage_provider_transaction_id',\n 'storageTransactionId',\n 'storageProviderTransactionId',\n 'versionUid',\n])\n\nconst toCamelCase = (str: string): string => {\n return str.replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())\n}\n\ntype AssembleContext = {\n seedUidToModelType: Map<string, string>\n relatedSeedUids: Set<string>\n versionUidToSeedUid: Map<string, string>\n assembledItems: Map<string, Record<string, unknown>>\n versionsBySeedUid: Map<string, AttestationLike[]>\n latestVersionUidsBySeedUid: Map<string, string>\n}\n\nfunction createAssembleContext(): AssembleContext {\n return {\n seedUidToModelType: new Map(),\n relatedSeedUids: new Set(),\n versionUidToSeedUid: new Map(),\n assembledItems: new Map(),\n versionsBySeedUid: new Map(),\n latestVersionUidsBySeedUid: new Map(),\n }\n}\n\nfunction ensureSeedIdentity(clone: Record<string, unknown>, seedUid: string): void {\n if (!clone.seedUid && !clone.SeedUid) {\n clone.seedUid = seedUid\n clone.SeedUid = seedUid\n } else if (clone.seedUid && !clone.SeedUid) {\n clone.SeedUid = clone.seedUid\n } else if (clone.SeedUid && !clone.seedUid) {\n clone.seedUid = clone.SeedUid\n }\n if (clone.attester && !clone.Attester) {\n clone.Attester = clone.attester\n } else if (clone.Attester && !clone.attester) {\n clone.attester = clone.Attester\n }\n}\n\nasync function processItemProperty(\n ctx: AssembleContext,\n property: AttestationLike,\n): Promise<void> {\n const parsed = parseEasPropertyMetadata(property.decodedDataJson)\n if (!parsed.ok) {\n const { id, refUID, schemaId } = property\n if (parsed.reason === 'empty') {\n console.warn(\n '[query] [processItemProperty] empty decodedDataJson for property:',\n id,\n refUID,\n schemaId,\n )\n } else if (parsed.reason === 'parse') {\n console.warn(\n '[query] [processItemProperty] failed to parse decodedDataJson for property:',\n id,\n refUID,\n schemaId,\n parsed.error,\n )\n } else {\n console.warn(\n '[query] [processItemProperty] invalid decodedDataJson structure for property:',\n id,\n refUID,\n schemaId,\n )\n }\n return\n }\n\n const metadata = parsed.metadata\n\n let propertyNameSnake = metadata.name\n if (!propertyNameSnake) {\n return\n }\n\n const schemaUid = property.schemaId\n setSchemaUidForSchemaDefinition({\n text: propertyNameSnake,\n schemaUid,\n })\n\n let isRelation = false\n let isList = false\n const easType = metadata.type\n const isBytes32Relation =\n (easType === 'bytes32' || easType === 'bytes32[]') &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n const isNamingConventionRelation =\n !isBytes32Relation &&\n (propertyNameSnake.endsWith('_id') || propertyNameSnake.endsWith('_ids')) &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n\n if (isBytes32Relation || isNamingConventionRelation) {\n isRelation = true\n if (Array.isArray(metadata.value)) {\n isList = true\n if (isNamingConventionRelation) {\n const result = parseEasRelationPropertyName(propertyNameSnake)\n if (result) {\n propertyNameSnake = result.propertyName\n }\n }\n metadata.value.forEach((value: string) => {\n if (!relationValuesToExclude.includes(value)) ctx.relatedSeedUids.add(value)\n })\n } else if (!relationValuesToExclude.includes(metadata.value as string)) {\n ctx.relatedSeedUids.add(metadata.value as string)\n }\n }\n\n let propertyValue: string | string[] = metadata.value as string | string[]\n if (isRelation && isList && Array.isArray(propertyValue)) {\n propertyValue = propertyValue.map((v) => String(v))\n } else if (typeof propertyValue !== 'string') {\n propertyValue = JSON.stringify(propertyValue)\n }\n\n const seedUidForProperty = ctx.versionUidToSeedUid.get(property.refUID)\n if (!seedUidForProperty) {\n return\n }\n\n const existingItem = ctx.assembledItems.get(seedUidForProperty) || {}\n existingItem[propertyNameSnake] = propertyValue\n const propertyNameCamel = toCamelCase(propertyNameSnake)\n if (propertyNameCamel !== propertyNameSnake) {\n existingItem[propertyNameCamel] = propertyValue\n }\n ctx.assembledItems.set(seedUidForProperty, existingItem)\n}\n\nasync function processSeeds(\n ctx: AssembleContext,\n seeds: AttestationLike[],\n dataSource: QueryDataSource,\n): Promise<void> {\n const seedUids: string[] = []\n\n for (let i = 0; i < seeds.length; i++) {\n const seed = seeds[i]\n if (!seed) continue\n seedUids.push(seed.id)\n const modelType = seed.schema?.schemaNames?.[0]?.name ?? 'unknown'\n ctx.seedUidToModelType.set(seed.id, modelType)\n\n if (!ctx.assembledItems.has(seed.id)) {\n ctx.assembledItems.set(seed.id, {\n seedUid: seed.id,\n timeCreated: seed.timeCreated,\n attester: seed.attester,\n })\n }\n }\n\n if (seedUids.length === 0) return\n\n const itemVersions = await dataSource.getVersionsForSeeds(seedUids)\n\n for (let i = 0; i < itemVersions.length; i++) {\n const itemVersion = itemVersions[i] as AttestationLike\n const seedUid = itemVersion.refUID\n ctx.versionUidToSeedUid.set(itemVersion.id, seedUid)\n const existingVersions = ctx.versionsBySeedUid.get(seedUid) || []\n ctx.versionsBySeedUid.set(seedUid, [...existingVersions, itemVersion])\n }\n\n const latestVersionUids: string[] = []\n for (const [seedUid, versions] of ctx.versionsBySeedUid.entries()) {\n if (ctx.latestVersionUidsBySeedUid.has(seedUid)) continue\n const sortedVersions = [...versions].sort((a, b) => b.timeCreated - a.timeCreated)\n const latestVersion = sortedVersions[0]\n if (latestVersion) {\n latestVersionUids.push(latestVersion.id)\n ctx.latestVersionUidsBySeedUid.set(seedUid, latestVersion.id)\n }\n }\n\n if (latestVersionUids.length === 0) return\n\n const rawProperties =\n await dataSource.getPropertiesForVersionUids(latestVersionUids)\n const itemProperties = pickLatestPropertyAttestationsByRefAndSchema(rawProperties)\n\n for (let i = 0; i < itemProperties.length; i++) {\n await processItemProperty(ctx, itemProperties[i] as AttestationLike)\n }\n}\n\nfunction resolveRelationPropertiesToUrls(ctx: AssembleContext, schemaName: string): void {\n const itemsToProcess = Array.from(ctx.assembledItems.entries()).filter(\n ([seedUid]) => ctx.seedUidToModelType.get(seedUid) === schemaName,\n )\n\n for (const [, item] of itemsToProcess) {\n const keysToProcess = Object.keys(item).filter(\n (k) => !k.startsWith('_') && !RESERVED_KEYS.has(k),\n )\n\n for (const key of keysToProcess) {\n let value = item[key]\n const coerced = tryCoerceJsonStringArray(value)\n if (coerced !== value && Array.isArray(coerced)) {\n item[key] = coerced\n value = coerced\n }\n const isList = Array.isArray(value)\n\n if (isList) {\n const uids = value as unknown[]\n const hasRelationUid = uids.some(\n (v) =>\n typeof v === 'string' &&\n !relationValuesToExclude.includes(v) &&\n ctx.assembledItems.has(v),\n )\n if (!hasRelationUid) continue\n\n const urls: string[] = []\n const models: string[] = []\n let resolved = false\n for (const uid of uids) {\n if (typeof uid !== 'string' || relationValuesToExclude.includes(uid)) {\n urls.push(String(uid))\n models.push('unknown')\n continue\n }\n const modelForUid = ctx.seedUidToModelType.get(uid) ?? 'unknown'\n if (modelForUid === IMAGE_SCHEMA) {\n urls.push(uid)\n models.push(IMAGE_SCHEMA)\n continue\n }\n const related = ctx.assembledItems.get(uid)\n const txId = (related?.storageTransactionId ??\n related?.storage_transaction_id) as string | undefined\n if (txId && typeof txId === 'string' && txId.trim()) {\n try {\n urls.push(getArweaveUrlForTransaction(txId))\n models.push(modelForUid)\n resolved = true\n } catch {\n urls.push(uid)\n models.push(modelForUid)\n }\n } else {\n urls.push(uid)\n models.push(modelForUid)\n }\n }\n if (resolved) {\n const outputKey = publicListRelationPropertyKey(key)\n item[outputKey] = urls\n setListElementStorageModels(item, outputKey, models)\n stripListRelationStorageAliasesForPublicKey(item, outputKey)\n if (outputKey !== key) {\n delete item[key]\n const camelKey = toCamelCase(key)\n if (camelKey !== key) delete item[camelKey]\n }\n }\n } else if (typeof value === 'string') {\n if (relationValuesToExclude.includes(value)) continue\n if (!ctx.assembledItems.has(value)) continue\n\n const related = ctx.assembledItems.get(value)\n if (ctx.seedUidToModelType.get(value) === IMAGE_SCHEMA) {\n continue\n }\n const txId = (related?.storageTransactionId ?? related?.storage_transaction_id) as\n | string\n | undefined\n if (txId && typeof txId === 'string' && txId.trim()) {\n try {\n const outputKey = key.endsWith('_id') ? key.replace(/_id$/, '') : key\n item[outputKey] = getArweaveUrlForTransaction(txId)\n const relatedModel = ctx.seedUidToModelType.get(value) ?? 'unknown'\n setFieldStorageModel(item, outputKey, relatedModel)\n const camelOut = toCamelCase(outputKey)\n if (camelOut !== outputKey) {\n setFieldStorageModel(item, camelOut, relatedModel)\n }\n if (outputKey !== key) {\n delete item[key]\n const camelKey = toCamelCase(key)\n if (camelKey !== key) delete item[camelKey]\n }\n } catch {\n // keep original on error\n }\n }\n }\n }\n }\n}\n\nfunction expandRelationProperties(\n ctx: AssembleContext,\n schemaName: string,\n expandRelations: boolean,\n): void {\n if (!expandRelations) return\n\n const itemsToProcess = Array.from(ctx.assembledItems.entries()).filter(\n ([seedUid]) => ctx.seedUidToModelType.get(seedUid) === schemaName,\n )\n\n for (const [, item] of itemsToProcess) {\n const keysToProcess = Object.keys(item).filter(\n (k) => !k.startsWith('_') && !RESERVED_KEYS.has(k),\n )\n\n for (const key of keysToProcess) {\n let value = item[key]\n const coerced = tryCoerceJsonStringArray(value)\n if (coerced !== value && Array.isArray(coerced)) {\n item[key] = coerced\n value = coerced\n }\n const isList = Array.isArray(value)\n const uids = isList ? (value as unknown[]) : [value]\n\n const expanded: unknown[] = []\n let didExpand = false\n\n for (const uid of uids) {\n if (typeof uid !== 'string' || relationValuesToExclude.includes(uid)) {\n expanded.push(uid)\n continue\n }\n const related = ctx.assembledItems.get(uid)\n if (!related) {\n expanded.push(uid)\n continue\n }\n const txId = (related?.storageTransactionId ?? related?.storage_transaction_id) as\n | string\n | undefined\n const isImage = ctx.seedUidToModelType.get(uid) === IMAGE_SCHEMA\n\n if (isImage) {\n const clone = { ...related } as Record<string, unknown>\n ensureSeedIdentity(clone, uid)\n clone.schemaName = IMAGE_SCHEMA\n enrichImageSeedClone(clone)\n expanded.push(clone)\n didExpand = true\n continue\n }\n\n if (txId && typeof txId === 'string' && txId.trim()) {\n expanded.push(uid)\n continue\n }\n const clone = { ...related } as Record<string, unknown>\n ensureSeedIdentity(clone, uid)\n expanded.push(clone)\n didExpand = true\n }\n\n if (didExpand) {\n const outputKey = isList\n ? publicListRelationPropertyKey(key)\n : key.endsWith('_id')\n ? key.replace(/_id$/, '')\n : key\n item[outputKey] = isList ? expanded : expanded[0]\n stripListRelationStorageAliasesForPublicKey(item, outputKey)\n if (outputKey !== key) {\n delete item[key]\n const camelKey = toCamelCase(key)\n if (camelKey !== key) delete item[camelKey]\n }\n }\n }\n }\n}\n\nfunction toSeedRecords(\n ctx: AssembleContext,\n schemaName: string,\n): SeedRecord[] {\n return Array.from(ctx.assembledItems.entries())\n .filter(([seedUid]) => ctx.seedUidToModelType.get(seedUid) === schemaName)\n .map(([seedUid, item]) => {\n const versionUid = ctx.latestVersionUidsBySeedUid.get(seedUid) ?? ''\n if (versionUid) {\n item.versionUid = versionUid\n }\n ensureSeedIdentity(item, seedUid)\n const timeCreated =\n typeof item.timeCreated === 'number' ? item.timeCreated : 0\n const attester =\n typeof item.attester === 'string'\n ? item.attester\n : typeof item.Attester === 'string'\n ? item.Attester\n : undefined\n return {\n seedUid,\n schemaName,\n attester,\n timeCreated,\n versionUid,\n data: item,\n }\n })\n}\n\n/**\n * Assemble canonical SeedRecords from Seed attestations (latest Version + canonical properties).\n * Uses per-call state (safe for concurrent requests).\n */\nexport async function assembleSeeds(\n schemaName: string,\n seeds: AttestationLike[],\n options?: AssembleOptions,\n dataSource: QueryDataSource = getRemoteQueryDataSource(),\n): Promise<SeedRecord[]> {\n const expandRelations = options?.expandRelations !== false\n const hydrateStorage = options?.hydrateStorage !== false\n\n const ctx = createAssembleContext()\n\n await processSeeds(ctx, seeds, dataSource)\n\n const relatedSeedUidsArray = Array.from(ctx.relatedSeedUids).filter(\n (uid) => !ctx.assembledItems.has(uid),\n )\n if (relatedSeedUidsArray.length > 0) {\n const relatedSeeds = await dataSource.getSeedsByUids(relatedSeedUidsArray)\n await processSeeds(ctx, relatedSeeds, dataSource)\n }\n\n resolveRelationPropertiesToUrls(ctx, schemaName)\n expandRelationProperties(ctx, schemaName, expandRelations)\n\n const records = toSeedRecords(ctx, schemaName)\n\n if (hydrateStorage) {\n await hydrateArweaveRichTextInItems(\n records.map((r) => r.data),\n dataSource.readStorageBody\n ? { readStorageBody: dataSource.readStorageBody.bind(dataSource) }\n : undefined,\n )\n }\n\n return records\n}\n","import { parseEasPropertyMetadata } from './parseEasPropertyMetadata.js'\nimport { parseEasRelationPropertyName } from './parseEasRelationPropertyName.js'\nimport type {\n AttestationLike,\n ChangelogEntry,\n ChangelogOptions,\n PropertyChangelogEntry,\n VersionChangelogEntry,\n} from './types.js'\n\nconst toCamelCase = (str: string): string => {\n return str.replace(/_([a-z])/g, (_, letter: string) => letter.toUpperCase())\n}\n\n/**\n * Stable-ish deep equality for changelog value comparison.\n */\nexport function changelogValuesEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (a === undefined || b === undefined) return false\n if (a === null || b === null) return a === b\n if (typeof a !== typeof b) return false\n if (typeof a !== 'object') return false\n try {\n return JSON.stringify(a) === JSON.stringify(b)\n } catch {\n return false\n }\n}\n\nexport type DecodedProperty = {\n propertyName: string\n value: string | string[]\n camelName?: string\n}\n\n/**\n * Decode a single property attestation into name + value (no relation expand).\n * Returns null when metadata cannot be parsed.\n */\nexport function decodePropertyAttestation(\n property: AttestationLike,\n): DecodedProperty | null {\n const parsed = parseEasPropertyMetadata(property.decodedDataJson)\n if (!parsed.ok) return null\n\n const metadata = parsed.metadata\n let propertyNameSnake = metadata.name\n if (!propertyNameSnake) return null\n\n const easType = metadata.type\n const isBytes32Relation =\n (easType === 'bytes32' || easType === 'bytes32[]') &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n const isNamingConventionRelation =\n !isBytes32Relation &&\n (propertyNameSnake.endsWith('_id') || propertyNameSnake.endsWith('_ids')) &&\n propertyNameSnake !== 'storage_transaction_id' &&\n propertyNameSnake !== 'storage_provider_transaction_id'\n\n let isRelation = false\n let isList = false\n if (isBytes32Relation || isNamingConventionRelation) {\n isRelation = true\n if (Array.isArray(metadata.value)) {\n isList = true\n if (isNamingConventionRelation) {\n const result = parseEasRelationPropertyName(propertyNameSnake)\n if (result?.isList) {\n propertyNameSnake = result.propertyName\n }\n }\n }\n }\n\n let propertyValue: string | string[] = metadata.value as string | string[]\n if (isRelation && isList && Array.isArray(propertyValue)) {\n propertyValue = propertyValue.map((v) => String(v))\n } else if (typeof propertyValue !== 'string') {\n propertyValue = JSON.stringify(propertyValue)\n }\n\n const camelName = toCamelCase(propertyNameSnake)\n return {\n propertyName: propertyNameSnake,\n value: propertyValue,\n camelName: camelName !== propertyNameSnake ? camelName : undefined,\n }\n}\n\n/**\n * Build a flat property map from canonical property attestations for one Version.\n */\nexport function buildFlatSnapshotFromProperties(\n properties: AttestationLike[],\n): Record<string, unknown> {\n const snapshot: Record<string, unknown> = {}\n for (const property of properties) {\n const decoded = decodePropertyAttestation(property)\n if (!decoded) continue\n snapshot[decoded.propertyName] = decoded.value\n if (decoded.camelName) {\n snapshot[decoded.camelName] = decoded.value\n }\n }\n return snapshot\n}\n\nexport type VersionSnapshot = {\n versionUid: string\n at: number\n data: Record<string, unknown>\n}\n\n/**\n * Diff consecutive version snapshots (ascending by `at`).\n * First version: `before = {}`, all keys in `after` are changed.\n */\nexport function diffVersionSnapshots(\n sortedSnapshots: VersionSnapshot[],\n): VersionChangelogEntry[] {\n const entries: VersionChangelogEntry[] = []\n let before: Record<string, unknown> = {}\n\n for (const snap of sortedSnapshots) {\n const after = snap.data\n const keySet = new Set([...Object.keys(before), ...Object.keys(after)])\n const changedKeys: string[] = []\n for (const key of keySet) {\n if (!changelogValuesEqual(before[key], after[key])) {\n changedKeys.push(key)\n }\n }\n changedKeys.sort()\n entries.push({\n type: 'version',\n at: snap.at,\n versionUid: snap.versionUid,\n before: { ...before },\n after: { ...after },\n changedKeys,\n })\n before = after\n }\n\n return entries\n}\n\n/**\n * Per-attestation property diffs across all versions (ordered by timeCreated asc).\n */\nexport function diffPropertyAttestations(\n properties: AttestationLike[],\n): PropertyChangelogEntry[] {\n const sorted = [...properties].sort((a, b) => {\n if (a.timeCreated !== b.timeCreated) return a.timeCreated - b.timeCreated\n return a.id.localeCompare(b.id)\n })\n\n const previousByProperty = new Map<string, unknown>()\n const entries: PropertyChangelogEntry[] = []\n\n for (const property of sorted) {\n const decoded = decodePropertyAttestation(property)\n if (!decoded) continue\n\n const names = [decoded.propertyName]\n if (decoded.camelName) names.push(decoded.camelName)\n\n // Emit one entry per logical property (snake); camel is alias only.\n const previousValue = previousByProperty.has(decoded.propertyName)\n ? previousByProperty.get(decoded.propertyName)\n : undefined\n const nextValue = decoded.value\n\n if (!changelogValuesEqual(previousValue, nextValue)) {\n entries.push({\n type: 'property',\n at: property.timeCreated,\n versionUid: property.refUID,\n property: decoded.propertyName,\n attestationUid: property.id,\n previousValue,\n nextValue,\n })\n }\n\n previousByProperty.set(decoded.propertyName, nextValue)\n if (decoded.camelName) {\n previousByProperty.set(decoded.camelName, nextValue)\n }\n }\n\n return entries\n}\n\n/**\n * Filter by `since` (inclusive), then keep the newest `limit` entries (newest-first).\n * Returned array is newest-first when limit is applied; otherwise chronological (asc).\n */\nexport function applyChangelogFilters(\n entries: ChangelogEntry[],\n options?: ChangelogOptions,\n): ChangelogEntry[] {\n let filtered = entries\n if (typeof options?.since === 'number') {\n const since = options.since\n filtered = filtered.filter((e) => e.at >= since)\n }\n\n if (typeof options?.limit === 'number' && options.limit >= 0) {\n // Newest-first slice, then reverse back to chronological for callers.\n const newestFirst = [...filtered].sort((a, b) => {\n if (b.at !== a.at) return b.at - a.at\n return 0\n })\n filtered = newestFirst.slice(0, options.limit).reverse()\n }\n\n return filtered\n}\n","import { pickLatestPropertyAttestationsByRefAndSchema } from '@seedprotocol/eas'\nimport {\n applyChangelogFilters,\n buildFlatSnapshotFromProperties,\n diffPropertyAttestations,\n diffVersionSnapshots,\n type VersionSnapshot,\n} from './changelog.js'\nimport { getRemoteQueryDataSource } from './source/remote.js'\nimport type { QueryDataSource } from './source/types.js'\nimport type {\n AttestationLike,\n ChangelogEntry,\n ChangelogOptions,\n GetSeedOptions,\n} from './types.js'\n\nexport type AssembleSeedChangelogResult = {\n latestVersionUid: string\n changelog: ChangelogEntry[]\n}\n\n/**\n * Build a changelog for one seed from all Versions + property attestations.\n * Snapshots are flat (no relation expand / hydrate).\n */\nexport async function assembleSeedChangelog(\n seedUid: string,\n options?: Pick<GetSeedOptions, 'changelog'>,\n dataSource: QueryDataSource = getRemoteQueryDataSource(),\n): Promise<AssembleSeedChangelogResult> {\n const changelogOpts: ChangelogOptions = options?.changelog ?? {}\n const granularity = changelogOpts.granularity ?? 'version'\n\n const itemVersions = await dataSource.getVersionsForSeed(seedUid)\n\n const sortedVersions = [...itemVersions].sort(\n (a, b) => a.timeCreated - b.timeCreated,\n )\n\n if (sortedVersions.length === 0) {\n return { latestVersionUid: '', changelog: [] }\n }\n\n const latestVersionUid = sortedVersions[sortedVersions.length - 1]!.id\n const versionUids = sortedVersions.map((v) => v.id)\n\n const rawProperties =\n await dataSource.getPropertiesForVersionUids(versionUids)\n\n let changelog: ChangelogEntry[]\n\n if (granularity === 'property') {\n changelog = diffPropertyAttestations(rawProperties)\n } else {\n const byVersion = new Map<string, AttestationLike[]>()\n for (const prop of rawProperties) {\n const list = byVersion.get(prop.refUID) ?? []\n list.push(prop)\n byVersion.set(prop.refUID, list)\n }\n\n const snapshots: VersionSnapshot[] = []\n for (const version of sortedVersions) {\n const propsForVersion = byVersion.get(version.id) ?? []\n const canonical = pickLatestPropertyAttestationsByRefAndSchema(\n propsForVersion,\n ) as AttestationLike[]\n snapshots.push({\n versionUid: version.id,\n at: version.timeCreated,\n data: buildFlatSnapshotFromProperties(canonical),\n })\n }\n changelog = diffVersionSnapshots(snapshots)\n }\n\n return {\n latestVersionUid,\n changelog: applyChangelogFilters(changelog, changelogOpts),\n }\n}\n","import { sha256 } from '@noble/hashes/sha256'\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils'\n\n/**\n * Generate an ETag from a string value (SHA-256, first 16 hex chars, quoted).\n */\nexport function generateETag(value: string): string {\n const hash = bytesToHex(sha256(utf8ToBytes(value)))\n return `\"${hash.substring(0, 16)}\"`\n}\n\n/**\n * Generate an ETag for a collection working set.\n */\nexport function generateCollectionETag(\n schemaName: string,\n lastProcessedTimestamp: number,\n itemCount: number,\n): string {\n return generateETag(\n `${schemaName}-data-${lastProcessedTimestamp}-${itemCount}`,\n )\n}\n\n/**\n * Generate an ETag for a single SeedRecord.\n */\nexport function generateItemETag(\n seedUid: string,\n versionUid: string,\n timeCreated: number,\n optionsKey: string,\n): string {\n return generateETag(\n `${seedUid}-${versionUid}-${timeCreated}-${optionsKey}`,\n )\n}\n","import type { GetSeedResult, SeedRecord } from '../types.js'\nimport { generateCollectionETag, generateItemETag } from './etag.js'\nimport type {\n CachedCollectionData,\n CachedItemData,\n QueryCacheConfig,\n} from './types.js'\n\n/**\n * In-memory collection + item cache with TTL and refresh locks.\n */\nexport class MemoryCache {\n private collectionCache: Map<string, CachedCollectionData> = new Map()\n private itemCache: Map<string, CachedItemData> = new Map()\n private config: QueryCacheConfig\n private refreshLocks: Map<string, Promise<unknown>> = new Map()\n\n constructor(config: QueryCacheConfig) {\n this.config = config\n }\n\n private itemKey(seedUid: string, optionsKey: string): string {\n return `${seedUid}:${optionsKey}`\n }\n\n getCollection(schemaName: string): CachedCollectionData | null {\n const cached = this.collectionCache.get(schemaName)\n if (!cached) return null\n\n const now = Math.floor(Date.now() / 1000)\n if (now - cached.lastUpdated > this.config.ttl) {\n this.collectionCache.delete(schemaName)\n return null\n }\n return cached\n }\n\n setCollection(schemaName: string, items: SeedRecord[]): CachedCollectionData {\n const now = Math.floor(Date.now() / 1000)\n let lastProcessedTimestamp = 0\n let lastProcessedItemId = ''\n\n for (const item of items) {\n if (item.timeCreated && item.timeCreated > lastProcessedTimestamp) {\n lastProcessedTimestamp = item.timeCreated\n lastProcessedItemId = item.seedUid\n }\n }\n if (lastProcessedTimestamp === 0) {\n lastProcessedTimestamp = now\n }\n\n const etag = generateCollectionETag(\n schemaName,\n lastProcessedTimestamp,\n items.length,\n )\n\n const cached: CachedCollectionData = {\n items: items.map((r) => ({ ...r, data: { ...r.data } })),\n lastProcessedTimestamp,\n lastProcessedItemId,\n lastUpdated: now,\n etag,\n }\n this.collectionCache.set(schemaName, cached)\n return cached\n }\n\n getItem(seedUid: string, optionsKey: string): CachedItemData | null {\n const cached = this.itemCache.get(this.itemKey(seedUid, optionsKey))\n if (!cached) return null\n\n const now = Math.floor(Date.now() / 1000)\n if (now - cached.lastUpdated > this.config.ttl) {\n this.itemCache.delete(this.itemKey(seedUid, optionsKey))\n return null\n }\n return cached\n }\n\n setItem(\n record: GetSeedResult,\n optionsKey: string,\n ): CachedItemData {\n const now = Math.floor(Date.now() / 1000)\n const etag = generateItemETag(\n record.seedUid,\n record.versionUid,\n record.timeCreated,\n optionsKey,\n )\n const cachedRecord: GetSeedResult = {\n ...record,\n data: { ...record.data },\n }\n if (record.changelog) {\n cachedRecord.changelog = [...record.changelog]\n }\n const cached: CachedItemData = {\n record: cachedRecord,\n lastUpdated: now,\n etag,\n optionsKey,\n }\n this.itemCache.set(this.itemKey(record.seedUid, optionsKey), cached)\n return cached\n }\n\n clearCollection(schemaName: string): void {\n this.collectionCache.delete(schemaName)\n }\n\n clearItem(seedUid: string, optionsKey?: string): void {\n if (optionsKey) {\n this.itemCache.delete(this.itemKey(seedUid, optionsKey))\n return\n }\n for (const key of this.itemCache.keys()) {\n if (key.startsWith(`${seedUid}:`)) {\n this.itemCache.delete(key)\n }\n }\n }\n\n clearAll(): void {\n this.collectionCache.clear()\n this.itemCache.clear()\n }\n\n /**\n * Single-flight: concurrent callers for the same schema share one in-flight promise.\n */\n async withRefreshLock<T>(\n schemaName: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n const existingLock = this.refreshLocks.get(schemaName)\n if (existingLock) {\n return existingLock as Promise<T>\n }\n\n const lockPromise = (async () => {\n try {\n return await fn()\n } finally {\n this.refreshLocks.delete(schemaName)\n }\n })()\n\n this.refreshLocks.set(schemaName, lockPromise)\n return lockPromise\n }\n\n updateConfig(config: Partial<QueryCacheConfig>): void {\n this.config = { ...this.config, ...config }\n }\n\n getStats(): {\n collectionCount: number\n itemCount: number\n activeLocks: number\n } {\n return {\n collectionCount: this.collectionCache.size,\n itemCount: this.itemCache.size,\n activeLocks: this.refreshLocks.size,\n }\n }\n}\n","import type { GetSeedResult, SeedRecord } from '../types.js'\nimport { MemoryCache } from './MemoryCache.js'\nimport type {\n CachedCollectionData,\n CachedItemData,\n PersistentCache,\n QueryCacheConfig,\n QueryCacheStats,\n} from './types.js'\n\ntype PersistentCacheFactory = (config: QueryCacheConfig) => PersistentCache | null\n\nlet persistentCacheFactory: PersistentCacheFactory = () => null\n\n/**\n * Node entry (`index.node.ts`) registers FileCache here so the browser\n * graph never statically imports `fs` / `path`.\n */\nexport function configurePersistentCacheFactory(\n factory: PersistentCacheFactory,\n): void {\n persistentCacheFactory = factory\n}\n\n/**\n * Unified query cache: memory, with optional persistent (disk) layer.\n */\nexport class CacheManager {\n private memoryCache: MemoryCache\n private persistent: PersistentCache | null\n private config: QueryCacheConfig\n private stats: QueryCacheStats = {\n hits: 0,\n misses: 0,\n refreshes: 0,\n errors: 0,\n }\n\n constructor(config: QueryCacheConfig, persistent?: PersistentCache | null) {\n this.config = config\n this.memoryCache = new MemoryCache(config)\n if (persistent === undefined) {\n this.persistent = persistentCacheFactory(config)\n } else {\n this.persistent = persistent\n }\n }\n\n get enabled(): boolean {\n return this.config.enabled\n }\n\n getConfig(): QueryCacheConfig {\n return { ...this.config }\n }\n\n async getCollection(\n schemaName: string,\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n let cached = this.memoryCache.getCollection(schemaName)\n if (cached) {\n this.stats.hits++\n return cached\n }\n\n cached = (await this.persistent?.getCollection(schemaName)) ?? null\n if (cached) {\n this.memoryCache.setCollection(schemaName, cached.items)\n this.stats.hits++\n return cached\n }\n\n this.stats.misses++\n return null\n } catch (error) {\n console.error(\n `Error getting query collection cache for ${schemaName}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async setCollection(\n schemaName: string,\n items: SeedRecord[],\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n const cached = this.memoryCache.setCollection(schemaName, items)\n await this.persistent?.setCollection(schemaName, cached)\n return cached\n } catch (error) {\n console.error(\n `Error setting query collection cache for ${schemaName}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async getItem(\n seedUid: string,\n optionsKey: string,\n ): Promise<CachedItemData | null> {\n if (!this.config.enabled) return null\n\n try {\n let cached = this.memoryCache.getItem(seedUid, optionsKey)\n if (cached) {\n this.stats.hits++\n return cached\n }\n\n cached = (await this.persistent?.getItem(seedUid, optionsKey)) ?? null\n if (cached) {\n this.memoryCache.setItem(cached.record, optionsKey)\n this.stats.hits++\n return cached\n }\n\n this.stats.misses++\n return null\n } catch (error) {\n console.error(`Error getting query item cache for ${seedUid}:`, error)\n this.stats.errors++\n return null\n }\n }\n\n async setItem(\n record: GetSeedResult,\n optionsKey: string,\n ): Promise<CachedItemData | null> {\n if (!this.config.enabled) return null\n\n try {\n const cached = this.memoryCache.setItem(record, optionsKey)\n await this.persistent?.setItem(cached)\n return cached\n } catch (error) {\n console.error(\n `Error setting query item cache for ${record.seedUid}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async writeThroughItems(\n items: SeedRecord[],\n optionsKey: string,\n ): Promise<void> {\n if (!this.config.enabled) return\n for (const item of items) {\n await this.setItem(item, optionsKey)\n }\n }\n\n async clearCollection(schemaName: string): Promise<void> {\n this.memoryCache.clearCollection(schemaName)\n await this.persistent?.clearCollection(schemaName)\n }\n\n async clearAll(): Promise<void> {\n this.memoryCache.clearAll()\n await this.persistent?.clearAll()\n }\n\n async withRefreshLock<T>(\n schemaName: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n return this.memoryCache.withRefreshLock(schemaName, fn)\n }\n\n /**\n * Merge records by seedUid; new wins. Sort by timeCreated descending.\n */\n mergeRecords(\n cachedItems: SeedRecord[],\n newItems: SeedRecord[],\n ): SeedRecord[] {\n const itemMap = new Map<string, SeedRecord>()\n\n for (const item of cachedItems) {\n if (item.seedUid) itemMap.set(item.seedUid, item)\n }\n for (const item of newItems) {\n if (item.seedUid) {\n itemMap.set(item.seedUid, item)\n } else {\n itemMap.set(`temp-${Date.now()}-${Math.random()}`, item)\n }\n }\n\n const merged = Array.from(itemMap.values())\n merged.sort((a, b) => (b.timeCreated || 0) - (a.timeCreated || 0))\n return merged\n }\n\n /**\n * Keep only records newer than lastProcessedTimestamp.\n */\n filterNewRecords(\n items: SeedRecord[],\n lastProcessedTimestamp: number,\n ): SeedRecord[] {\n return items.filter(\n (item) => item.timeCreated && item.timeCreated > lastProcessedTimestamp,\n )\n }\n\n updateConfig(config: Partial<QueryCacheConfig>): void {\n this.config = { ...this.config, ...config }\n this.memoryCache.updateConfig(this.config)\n }\n\n getStats(): QueryCacheStats & {\n memoryStats: ReturnType<MemoryCache['getStats']>\n } {\n return {\n ...this.stats,\n memoryStats: this.memoryCache.getStats(),\n }\n }\n\n resetStats(): void {\n this.stats = {\n hits: 0,\n misses: 0,\n refreshes: 0,\n errors: 0,\n }\n }\n}\n","import type { QueryCacheConfig } from './types.js'\n\nfunction env(): Record<string, string | undefined> {\n const processEnv = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process?.env\n return processEnv ?? {}\n}\n\n/**\n * Load query cache configuration from environment variables.\n *\n * Uses the same CACHE_* vars as feed for ops compatibility:\n * - CACHE_ENABLED\n * - CACHE_TTL (default 3600)\n * - CACHE_DIR (default ./cache)\n * - CACHE_BACKGROUND_REFRESH / CACHE_REFRESH_INTERVAL (unused stubs)\n *\n * In development (NODE_ENV=development), cache is disabled unless\n * CACHE_ENABLED is explicitly true.\n */\nexport function loadQueryCacheConfig(): QueryCacheConfig {\n const e = env()\n const ttl = parseInt(e.CACHE_TTL || '3600', 10)\n const cacheDir = e.CACHE_DIR || './cache'\n\n const cacheDisabledByEnvVar =\n e.CACHE_ENABLED === 'false' ||\n e.CACHE_ENABLED === '0' ||\n e.CACHE_ENABLED === 'no' ||\n e.CACHE_ENABLED === 'off'\n const cacheEnabledByEnvVar =\n e.CACHE_ENABLED === 'true' ||\n e.CACHE_ENABLED === '1' ||\n e.CACHE_ENABLED === 'yes'\n const isDev = e.NODE_ENV === 'development'\n\n let enabled: boolean\n if (cacheDisabledByEnvVar) {\n enabled = false\n } else if (cacheEnabledByEnvVar) {\n enabled = true\n } else if (isDev) {\n enabled = false\n } else {\n enabled = true\n }\n\n const backgroundRefresh = e.CACHE_BACKGROUND_REFRESH === 'true'\n const refreshInterval = parseInt(e.CACHE_REFRESH_INTERVAL || '300', 10)\n\n return {\n ttl,\n cacheDir,\n enabled,\n backgroundRefresh,\n refreshInterval,\n }\n}\n","import { CacheManager } from './CacheManager.js'\nimport { loadQueryCacheConfig } from './config.js'\nimport type { PersistentCache, QueryCacheConfig } from './types.js'\n\nexport { CacheManager, configurePersistentCacheFactory } from './CacheManager.js'\nexport { MemoryCache } from './MemoryCache.js'\nexport { loadQueryCacheConfig } from './config.js'\nexport {\n generateETag,\n generateCollectionETag,\n generateItemETag,\n} from './etag.js'\nexport {\n buildAssembleOptionsKey,\n sanitizeSeedUidForPath,\n} from './types.js'\nexport type {\n CachedCollectionData,\n CachedItemData,\n PersistentCache,\n QueryCacheConfig,\n QueryCacheStats,\n} from './types.js'\n\nlet cacheManager: CacheManager | null = null\n\n/**\n * Get the singleton query CacheManager (lazy-init from env).\n * Browser graphs are memory-only. Node `index.node` registers FileCache.\n */\nexport function getQueryCacheManager(): CacheManager {\n if (!cacheManager) {\n cacheManager = new CacheManager(loadQueryCacheConfig())\n }\n return cacheManager\n}\n\n/**\n * Reset singleton (tests / config reload).\n */\nexport function resetQueryCacheManager(): void {\n cacheManager = null\n}\n\n/**\n * Create a CacheManager with an explicit config (tests).\n * Pass a PersistentCache (e.g. FileCache) to enable the disk layer.\n */\nexport function createQueryCacheManager(\n config?: Partial<QueryCacheConfig>,\n persistent?: PersistentCache | null,\n): CacheManager {\n return new CacheManager(\n {\n ...loadQueryCacheConfig(),\n ...config,\n },\n persistent,\n )\n}\n","import type { QueryDataSource } from './types.js'\n\nlet localSource: QueryDataSource | null = null\n\n/**\n * Register the SDK (or test) local SQLite/files adapter.\n * Replaces any previously registered local source.\n */\nexport function registerLocalQuerySource(source: QueryDataSource): void {\n if (source.kind !== 'local') {\n throw new Error(\n '[query] registerLocalQuerySource expects a source with kind: \"local\"',\n )\n }\n localSource = source\n}\n\n/** Clear the registered local source (tests / teardown). */\nexport function clearLocalQuerySource(): void {\n localSource = null\n}\n\nexport function getRegisteredLocalQuerySource(): QueryDataSource | null {\n return localSource\n}\n\nexport function hasLocalQuerySource(): boolean {\n return localSource != null\n}\n","import type { QuerySourceMode } from '../types.js'\nimport { getRegisteredLocalQuerySource } from './registry.js'\nimport { getRemoteQueryDataSource } from './remote.js'\nimport type { QueryDataSource } from './types.js'\n\nexport type ResolvedQuerySource = {\n mode: QuerySourceMode\n dataSource: QueryDataSource\n /** True when CacheManager may be used for this call. */\n useQueryCache: boolean\n}\n\n/**\n * Resolve which data source to use for a call.\n * - remote (default): EAS\n * - local: registered adapter or throw\n * - auto: prefer local when registered; else remote (caller may still fall back per-seed)\n */\nexport function resolveQuerySource(\n mode: QuerySourceMode = 'remote',\n): ResolvedQuerySource {\n if (mode === 'remote') {\n return {\n mode: 'remote',\n dataSource: getRemoteQueryDataSource(),\n useQueryCache: true,\n }\n }\n\n const local = getRegisteredLocalQuerySource()\n\n if (mode === 'local') {\n if (!local) {\n throw new Error(\n '[query] source: \"local\" requires registerLocalQuerySource(...) (e.g. SDK DB ready)',\n )\n }\n return {\n mode: 'local',\n dataSource: local,\n useQueryCache: false,\n }\n }\n\n // auto\n if (local) {\n return {\n mode: 'auto',\n dataSource: local,\n useQueryCache: false,\n }\n }\n return {\n mode: 'auto',\n dataSource: getRemoteQueryDataSource(),\n useQueryCache: true,\n }\n}\n\nexport function normalizeSourceMode(\n source?: QuerySourceMode,\n): QuerySourceMode {\n return source ?? 'remote'\n}\n","import { initializeQueryPlatform } from './bootstrap.js'\nimport { assembleSeeds } from './assembleSeeds.js'\nimport { assembleSeedChangelog } from './assembleChangelog.js'\nimport {\n buildAssembleOptionsKey,\n getQueryCacheManager,\n} from './cache/index.js'\nimport {\n normalizeSourceMode,\n resolveQuerySource,\n getRemoteQueryDataSource,\n} from './source/index.js'\nimport type { QueryDataSource } from './source/types.js'\nimport type {\n AssembleOptions,\n GetSeedOptions,\n GetSeedResult,\n QueryBySchemaOptions,\n QueryBySchemaResult,\n SeedRecord,\n} from './types.js'\n\nfunction shouldUseCache(\n options: AssembleOptions | undefined,\n allowCache: boolean,\n): boolean {\n if (!allowCache) return false\n if (options?.cache === false) return false\n return getQueryCacheManager().enabled\n}\n\nfunction wantsChangelog(include: GetSeedOptions['include']): boolean {\n return include === 'data+changelog' || include === 'changelog'\n}\n\nfunction wantsData(include: GetSeedOptions['include']): boolean {\n return include !== 'changelog'\n}\n\nasync function fetchAndAssemble(\n schemaName: string,\n limit: number,\n skip: number,\n options: AssembleOptions | undefined,\n dataSource: QueryDataSource,\n): Promise<SeedRecord[]> {\n const seeds = await dataSource.listSeedsBySchemaName(schemaName, {\n limit,\n skip,\n })\n return assembleSeeds(schemaName, seeds, options, dataSource)\n}\n\n/**\n * For `source: 'auto'`: try local first; if empty/miss, fall back to remote.\n */\nasync function withAutoFallbackForCollection(\n mode: ReturnType<typeof normalizeSourceMode>,\n dataSource: QueryDataSource,\n run: (ds: QueryDataSource) => Promise<SeedRecord[]>,\n): Promise<{ items: SeedRecord[]; dataSource: QueryDataSource; useQueryCache: boolean }> {\n const items = await run(dataSource)\n if (mode !== 'auto' || dataSource.kind !== 'local') {\n return {\n items,\n dataSource,\n useQueryCache: dataSource.kind === 'remote',\n }\n }\n if (items.length > 0) {\n return { items, dataSource, useQueryCache: false }\n }\n const remote = getRemoteQueryDataSource()\n const remoteItems = await run(remote)\n return { items: remoteItems, dataSource: remote, useQueryCache: true }\n}\n\nexport async function queryBySchema(\n schemaName: string,\n options?: QueryBySchemaOptions,\n): Promise<QueryBySchemaResult> {\n await initializeQueryPlatform()\n const limit = options?.limit ?? 100\n const skip = options?.skip ?? 0\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n const optionsKey = buildAssembleOptionsKey(options)\n\n const runAssemble = (ds: QueryDataSource) =>\n fetchAndAssemble(schemaName, limit, skip, options, ds)\n\n // Collection cache only for remote + skip=0 working set\n if (\n shouldUseCache(options, resolved.useQueryCache) &&\n skip === 0 &&\n resolved.dataSource.kind === 'remote'\n ) {\n const cache = getQueryCacheManager()\n return cache.withRefreshLock(schemaName, async () => {\n const cachedData = await cache.getCollection(schemaName)\n let items: SeedRecord[]\n let etag: string | undefined\n\n if (cachedData) {\n const pageItems = await fetchAndAssemble(\n schemaName,\n limit,\n 0,\n options,\n resolved.dataSource,\n )\n const newItems = cache.filterNewRecords(\n pageItems,\n cachedData.lastProcessedTimestamp,\n )\n\n if (newItems.length > 0) {\n items = cache\n .mergeRecords(cachedData.items, newItems)\n .slice(0, limit)\n } else {\n items = cachedData.items.slice(0, limit)\n }\n } else {\n items = await fetchAndAssemble(\n schemaName,\n limit,\n 0,\n options,\n resolved.dataSource,\n )\n }\n\n const stored = await cache.setCollection(schemaName, items)\n etag = stored?.etag\n await cache.writeThroughItems(items, optionsKey)\n\n return { items, limit, skip, etag }\n })\n }\n\n const {\n items,\n dataSource: used,\n useQueryCache,\n } = await withAutoFallbackForCollection(mode, resolved.dataSource, (ds) =>\n runAssemble(ds),\n )\n\n if (shouldUseCache(options, useQueryCache) && used.kind === 'remote') {\n await getQueryCacheManager().writeThroughItems(items, optionsKey)\n }\n return { items, limit, skip }\n}\n\nexport async function getSeed(\n seedUid: string,\n options?: GetSeedOptions,\n): Promise<GetSeedResult | null> {\n await initializeQueryPlatform()\n if (!seedUid || typeof seedUid !== 'string' || seedUid.trim() === '') {\n return null\n }\n\n const trimmed = seedUid.trim()\n const include = options?.include ?? 'data'\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n const optionsKey = buildAssembleOptionsKey(options)\n\n let dataSource = resolved.dataSource\n let allowCache = resolved.useQueryCache\n\n if (shouldUseCache(options, allowCache) && dataSource.kind === 'remote') {\n const cached = await getQueryCacheManager().getItem(trimmed, optionsKey)\n if (cached) {\n return cached.record\n }\n }\n\n let seed = await dataSource.getSeedByUid(trimmed)\n\n // auto: local miss → remote\n if (!seed && mode === 'auto' && dataSource.kind === 'local') {\n dataSource = getRemoteQueryDataSource()\n allowCache = true\n seed = await dataSource.getSeedByUid(trimmed)\n if (shouldUseCache(options, allowCache)) {\n const cached = await getQueryCacheManager().getItem(trimmed, optionsKey)\n if (cached) {\n return cached.record\n }\n }\n }\n\n if (!seed) return null\n\n const schemaName = seed.schema?.schemaNames?.[0]?.name\n if (!schemaName) return null\n\n let result: GetSeedResult | null = null\n\n if (!wantsChangelog(include)) {\n const records = await assembleSeeds(schemaName, [seed], options, dataSource)\n result = records[0] ?? null\n } else {\n const { latestVersionUid, changelog } = await assembleSeedChangelog(\n trimmed,\n options,\n dataSource,\n )\n\n if (wantsData(include)) {\n const records = await assembleSeeds(\n schemaName,\n [seed],\n options,\n dataSource,\n )\n const record = records[0]\n if (!record) {\n result = null\n } else {\n result = { ...record, changelog }\n }\n } else {\n result = {\n seedUid: trimmed,\n schemaName,\n attester: seed.attester,\n timeCreated: seed.timeCreated,\n versionUid: latestVersionUid,\n data: {},\n changelog,\n }\n }\n }\n\n if (\n result &&\n shouldUseCache(options, allowCache) &&\n dataSource.kind === 'remote'\n ) {\n await getQueryCacheManager().setItem(result, optionsKey)\n }\n\n return result\n}\n\n/**\n * Query seeds of a schema created within a calendar month (local timezone bounds).\n * No collection cache; may write-through to item cache when remote.\n */\nexport async function queryBySchemaForMonth(\n schemaName: string,\n year: number,\n month: number,\n options?: AssembleOptions,\n): Promise<SeedRecord[]> {\n await initializeQueryPlatform()\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n\n const run = async (ds: QueryDataSource) => {\n const seeds = await ds.listSeedsBySchemaNameForMonth(\n schemaName,\n year,\n month,\n )\n return assembleSeeds(schemaName, seeds, options, ds)\n }\n\n const { items, dataSource: used, useQueryCache } =\n await withAutoFallbackForCollection(mode, resolved.dataSource, run)\n\n if (shouldUseCache(options, useQueryCache) && used.kind === 'remote') {\n const optionsKey = buildAssembleOptionsKey(options)\n await getQueryCacheManager().writeThroughItems(items, optionsKey)\n }\n\n return items\n}\n"],"mappings":"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"}
|