@seedprotocol/query 0.7.6 → 0.7.7-next.988.g7046e66
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/src-D20xeLMs.js.map +1 -1
- package/package.json +3 -3
package/dist/src-D20xeLMs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src-D20xeLMs.js","names":["toCamelCase","initializeQueryPlatform","pluralize","getArweaveUrlForTransaction","BaseArweaveClient","transactionId","CAMEL_LIST_RELATION_IDS","publicListRelationPropertyKey","camel","propertyKey","singularPart","base","segments","singularProperty","stripListRelationStorageAliasesForPublicKey","k","item","publicKey","tryCoerceJsonStringArray","value","s","parsed","enrichImageSeedClone","txId","clone","enrichImageSeedCloneForFeed","RICH_BODY_STORAGE_SCHEMAS","FEED_RICH_BODY_STORAGE_SCHEMAS","FIELD_MODELS_KEY","LIST_MODELS_KEY","normalizeModelName","schemaName","isRichBodyStorageSchema","isFeedRichBodyStorageSchema","richBodyModelPriority","m","feedRichBodyModelPriority","getFieldStorageModels","raw","getFeedFieldStorageModels","getListElementStorageModels","getFeedListElementStorageModels","setFieldStorageModel","normalized","map","fieldKey","setFeedFieldStorageModel","setListElementStorageModels","outputKey","models","setFeedListElementStorageModels","RICH_TEXT_KEYS","MAX_BODY_BYTES","isArweaveTransactionGatewayUrl","u","host","isKnownArweaveGatewayHostname","id","fetchGatewayPayloadAsUtf8","res","url","ct","readArweaveContentResponse","bytes","text","BODY_CACHE_MAX_CHARS","bodyCache","bodyCacheChars","bodiesInFlight","resetArweaveBodyCache","cacheBody","oldest","oldText","fetchTransactionBody","cached","inFlight","request","resolveHydratedBody","readStorageBody","local","HYDRATE_CONCURRENCY","runWithConcurrency","next","limit","tasks","hydrateArweaveRichTextInItems","options","items","keysToHydrate","fieldModels","key","v","listModels","listKey","arr","n","i","el","hydrateArweaveRichTextInFeedItems","parseEasPropertyMetadata","decodedDataJson","parseEasPropertyMetadataForFeed","parseEasRelationPropertyName","modelName","idSegment","easPropertyName","isList","monthBoundsUnix","startDate","year","month","endDate","createRemoteQueryDataSource","seed","getSeedsByUidsFromEas","seedUid","getSeedsBySchemaName","opts","where","withExcludeRevokedFilter","startTs","endTs","EasClient","GET_SEEDS_LEAN","itemSeeds","getItemVersionsFromEas","seedUids","versionUids","getItemPropertiesFromEas","uids","getAttestationChangesSince","remoteSingleton","getRemoteQueryDataSource","IMAGE_SCHEMA","relationValuesToExclude","RESERVED_KEYS","toCamelCase$1","str","letter","createAssembleContext","requestedItems","ctx","ensureSeedIdentity","addRelatedSeedUid","relatedSeedUid","property","related","processItemProperty","refUID","schemaId","metadata","propertyNameSnake","schemaUid","isRelation","easType","isBytes32Relation","isNamingConventionRelation","result","propertyValue","isNumericEasType","decodeEasNumber","seedUidForProperty","existingItem","propertyNameCamel","activePins","active","pin","pins","pinnedVersion","asOf","candidates","versions","b","a","needle","processSeeds","seeds","modelType","requested","fetchedVersions","dataSource","allVersions","keepAttestationsFromRefAttester","itemVersions","seedsWithLiveVersion","version","itemVersion","existingVersions","latestVersionUids","asOfByVersionUid","pinned","latestVersion","rawProperties","itemProperties","pickLatestPropertyAttestationsByRefAndSchema","resolveRelationPropertiesToUrls","keysToProcess","coerced","urls","resolved","uid","modelForUid","camelKey","relatedModel","camelOut","expandRelationProperties","expandRelations","expanded","didExpand","toSeedRecords","versionUid","timeCreated","attester","dependenciesOf","headVersionUids","assembleSeedsWithDependencies","assembleSeedRecords","prefetched","hydrateStorage","relatedSeedUidsArray","relatedSeeds","relatedVersions","records","r","record","assembleSeeds","toCamelCase","changelogValuesEqual","decodePropertyAttestation","camelName","buildFlatSnapshotFromProperties","snapshot","properties","decoded","diffVersionSnapshots","entries","before","snap","sortedSnapshots","after","keySet","changedKeys","diffPropertyAttestations","sorted","previousByProperty","names","previousValue","nextValue","applyChangelogFilters","filtered","since","e","assembleSeedChangelog","changelogOpts","granularity","sortedVersions","latestVersionUid","changelog","byVersion","prop","list","snapshots","propsForVersion","canonical","generateETag","bytesToHex","sha256","utf8ToBytes","generateCollectionETag","optionsKey","itemETags","generateItemETag","stableStringify","env","defaultFreezeRecords","loadQueryCacheConfig","ttl","cacheDir","cacheDisabledByEnvVar","cacheEnabledByEnvVar","isDev","enabled","backgroundRefresh","refreshInterval","deepFreeze","child","MemoryCache","config","lastUpdated","data","existingLock","lockPromise","fn","persistentCacheFactory","configurePersistentCacheFactory","factory","isCurrentCollection","d","isCurrentItem","CacheManager","persistent","persisted","error","etag","cacheManager","getQueryCacheManager","resetQueryCacheManager","createQueryCacheManager","nowSeconds","checkedAtFor","startedAt","checkWindowAged","check","changeKey","change","findChangedSeeds","dependenciesBySeedUid","seedUidsByRef","seedUidsById","index","deps","changes","seen","changed","findChangedItems","seenChangeKeys","checks","refUIDs","ids","refs","own","keys","localSource","registerLocalQuerySource","source","clearLocalQuerySource","getRegisteredLocalQuerySource","hasLocalQuerySource","resolveQuerySource","mode","normalizeSourceMode","NO_DEPENDENCIES","shouldUseCache","allowCache","wantsChangelog","include","wantsData","fetchAndAssemble","withAutoFallbackForCollection","assembled","run","remote","writeThroughAssembled","refreshCollection","cache","listed","cachedBySeedUid","toCheck","meta","found","toAssemble","fresh","freshBySeedUid","unchanged","stored","MIN_UID_PREFIX_HEX_DIGITS","normalizeUidPrefix","hex","prefix","queryBySchema","skip","buildAssembleOptionsKey","uidPrefix","runAssemble","ds","lockKey","used","useQueryCache","getUnchangedCachedItems","requests","hits","getUnchangedCachedItem","pinOf","getSeed","trimmed","fetchSeedAndVersions","dependencies","assembleData","entry","getSeeds","givenByUid","given","optionsKeyFor","readFrom","useCache","toFetch","seedByUid","missing","queryBySchemaForMonth"],"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/config.ts","../src/cache/freeze.ts","../src/cache/MemoryCache.ts","../src/cache/CacheManager.ts","../src/cache/index.ts","../src/cache/changes.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 {\n BaseArweaveClient,\n isKnownArweaveGatewayHostname,\n readArweaveContentResponse,\n} 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\n/** Body goes through `transformArweaveContent` (`@seedprotocol/arweave`, `content/arweaveContent.ts`). */\nasync function fetchGatewayPayloadAsUtf8(url: string, transactionId: 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 { bytes } = await readArweaveContentResponse(res, { transactionId })\n if (bytes.byteLength > MAX_BODY_BYTES) return null\n const text = new TextDecoder('utf-8', { fatal: false }).decode(bytes)\n if (text.length === 0 || text.includes('\\0')) return null\n return text\n } catch {\n return null\n }\n}\n\n/** Upper bound on cached body text, in UTF-16 code units (~2 bytes each). */\nconst BODY_CACHE_MAX_CHARS = 32_000_000\n\n/**\n * Fetched bodies by Arweave transaction id, least recently used first. A transaction's data never\n * changes, so entries never go stale; they are only evicted for size. Failed fetches are not cached\n * (a new transaction can 404 until gateways have it).\n */\nconst bodyCache = new Map<string, string>()\nlet bodyCacheChars = 0\nconst bodiesInFlight = new Map<string, Promise<string | null>>()\n\n/** Clears the Arweave body cache. For tests. */\nexport function resetArweaveBodyCache(): void {\n bodyCache.clear()\n bodyCacheChars = 0\n bodiesInFlight.clear()\n}\n\nfunction cacheBody(txId: string, text: string): void {\n if (text.length > BODY_CACHE_MAX_CHARS) return\n bodyCache.set(txId, text)\n bodyCacheChars += text.length\n for (const [oldest, oldText] of bodyCache) {\n if (bodyCacheChars <= BODY_CACHE_MAX_CHARS) break\n bodyCache.delete(oldest)\n bodyCacheChars -= oldText.length\n }\n}\n\n/** Gateway body for a transaction URL: cached by transaction id, concurrent requests shared. */\nasync function fetchTransactionBody(url: string): Promise<string | null> {\n const txId = new URL(url.trim()).pathname.replace(/^\\//, '')\n const cached = bodyCache.get(txId)\n if (cached !== undefined) {\n // Most recently used goes last.\n bodyCache.delete(txId)\n bodyCache.set(txId, cached)\n return cached\n }\n const inFlight = bodiesInFlight.get(txId)\n if (inFlight) return inFlight\n\n const request = fetchGatewayPayloadAsUtf8(url, txId)\n .then((text) => {\n if (text !== null && bodiesInFlight.get(txId) === request) cacheBody(txId, text)\n return text\n })\n .finally(() => {\n if (bodiesInFlight.get(txId) === request) bodiesInFlight.delete(txId)\n })\n bodiesInFlight.set(txId, request)\n return request\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 fetchTransactionBody(value)\n}\n\n/** Bodies resolved at once, across all items. */\nconst HYDRATE_CONCURRENCY = 8\n\nasync function runWithConcurrency(\n tasks: Array<() => Promise<void>>,\n limit: number,\n): Promise<void> {\n let next = 0\n const worker = async (): Promise<void> => {\n while (next < tasks.length) {\n await tasks[next++]!()\n }\n }\n await Promise.all(Array.from({ length: Math.min(limit, tasks.length) }, worker))\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 * Up to HYDRATE_CONCURRENCY bodies are resolved at a time, across all items.\n */\nexport async function hydrateArweaveRichTextInItems(\n items: Record<string, unknown>[],\n options?: HydrateStorageOptions,\n): Promise<void> {\n const readStorageBody = options?.readStorageBody\n const tasks: Array<() => Promise<void>> = []\n\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 const v = item[key]\n if (typeof v !== 'string' || v.trim() === '') continue\n tasks.push(async () => {\n const text = await resolveHydratedBody(key, v, readStorageBody)\n if (text !== null) item[key] = text\n })\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 tasks.push(async () => {\n const text = await resolveHydratedBody(listKey, el, readStorageBody)\n if (text !== null) arr[i] = text\n })\n }\n }\n }\n }\n\n await runWithConcurrency(tasks, HYDRATE_CONCURRENCY)\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 (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 getSeedsByUidsFromEas,\n getAttestationChangesSince,\n getItemVersionsFromEas,\n getItemPropertiesFromEas,\n EasClient,\n withExcludeRevokedFilter,\n GET_SEEDS_LEAN,\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 [seed] = await getSeedsByUidsFromEas({ uids: [seedUid] })\n return (seed 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 listSeedsByUidPrefix(\n schemaName: string,\n uidPrefix: string,\n opts: { limit: number; skip: number },\n ): Promise<AttestationLike[]> {\n return (await getSeedsBySchemaName(schemaName, opts.limit, opts.skip, {\n uidPrefix,\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_LEAN, {\n where,\n take: 1000,\n skip: 0,\n })\n // Every seed matched `schemaName`; the lean query doesn't select it.\n return (itemSeeds ?? []).map((seed) => ({\n ...seed,\n schema: { schemaNames: [{ name: schemaName }] },\n })) 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(\n seedUids: string[],\n opts?: { includeRevoked?: boolean },\n ): Promise<AttestationLike[]> {\n if (seedUids.length === 0) return []\n // The query fields include `revoked`, so revoked versions come back marked.\n return (await getItemVersionsFromEas({\n seedUids,\n excludeRevoked: !opts?.includeRevoked,\n })) 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 return (await getSeedsByUidsFromEas({ uids })) as AttestationLike[]\n },\n\n async listChangesSince(opts) {\n return getAttestationChangesSince(opts)\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 decodeEasNumber,\n isNumericEasType,\n setSchemaUidForSchemaDefinition,\n pickLatestPropertyAttestationsByRefAndSchema,\n keepAttestationsFromRefAttester,\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, VersionPin } 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 /** Related seeds each seed's properties name (what its record depends on besides itself). */\n relatedSeedUidsBySeedUid: Map<string, 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 /** Requested seeds left out because every version is revoked; not fetched again as related. */\n droppedSeedUids: Set<string>\n /**\n * The seeds asked for, in order. Only these become records: a related seed is fetched to expand\n * relations into, even when it has the requested schema.\n */\n requestedSeedUids: Set<string>\n}\n\nfunction createAssembleContext(): AssembleContext {\n return {\n seedUidToModelType: new Map(),\n relatedSeedUids: new Set(),\n relatedSeedUidsBySeedUid: new Map(),\n versionUidToSeedUid: new Map(),\n assembledItems: new Map(),\n versionsBySeedUid: new Map(),\n latestVersionUidsBySeedUid: new Map(),\n droppedSeedUids: new Set(),\n requestedSeedUids: new Set(),\n }\n}\n\n/** Requested seeds still assembled (not dropped), in request order, with their items. */\nfunction requestedItems(ctx: AssembleContext): Array<[string, Record<string, unknown>]> {\n const items: Array<[string, Record<string, unknown>]> = []\n for (const seedUid of ctx.requestedSeedUids) {\n const item = ctx.assembledItems.get(seedUid)\n if (item) items.push([seedUid, item])\n }\n return items\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\nfunction addRelatedSeedUid(\n ctx: AssembleContext,\n property: AttestationLike,\n relatedSeedUid: string,\n): void {\n ctx.relatedSeedUids.add(relatedSeedUid)\n const seedUid = ctx.versionUidToSeedUid.get(property.refUID)\n if (!seedUid) return\n const related = ctx.relatedSeedUidsBySeedUid.get(seedUid) ?? new Set<string>()\n related.add(relatedSeedUid)\n ctx.relatedSeedUidsBySeedUid.set(seedUid, related)\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)) addRelatedSeedUid(ctx, property, value)\n })\n } else if (!relationValuesToExclude.includes(metadata.value as string)) {\n addRelatedSeedUid(ctx, property, 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 // ADR 0010: an integer value as its decimal string, not the indexer's `{ type: 'BigNumber', hex }`.\n const decimal = isNumericEasType(easType) ? decodeEasNumber(propertyValue) : undefined\n propertyValue = decimal ?? 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\n/** Pins that name a version or a time, by lowercase seed UID. */\nfunction activePins(pins: ReadonlyMap<string, VersionPin>): Map<string, VersionPin> {\n const active = new Map<string, VersionPin>()\n for (const [seedUid, pin] of pins) {\n if (pin.versionUid !== undefined || pin.asOf !== undefined) active.set(seedUid.toLowerCase(), pin)\n }\n return active\n}\n\n/** The seed's live version `pin` names (else its newest), if it was created by `pin.asOf`. */\nfunction pinnedVersion(\n versions: AttestationLike[],\n pin: VersionPin,\n): AttestationLike | undefined {\n const asOf = pin.asOf\n const candidates =\n asOf === undefined ? versions : versions.filter((v) => v.timeCreated <= asOf)\n if (pin.versionUid === undefined) {\n return [...candidates].sort((a, b) => b.timeCreated - a.timeCreated)[0]\n }\n const needle = pin.versionUid.toLowerCase()\n return candidates.find((v) => v.id.toLowerCase() === needle)\n}\n\nasync function processSeeds(\n ctx: AssembleContext,\n seeds: AttestationLike[],\n dataSource: QueryDataSource,\n opts: {\n dropSeedsWithOnlyRevokedVersions?: boolean\n /**\n * Versions already fetched with `getVersionsForSeeds(…, { includeRevoked: true })` for these\n * seeds (and possibly others, which are ignored), so the request isn't made again.\n */\n versions?: AttestationLike[]\n /** Versions to assemble instead of the latest, by lowercase seed UID (see VersionPin). */\n pins?: ReadonlyMap<string, VersionPin>\n } = {},\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 // Revoked versions come back too (marked), in the same request, only so a seed whose versions\n // were all revoked can be told from one that never had a version; they are never used below.\n const requested = new Set(seedUids)\n const fetchedVersions = opts.versions\n ? opts.versions.filter((v) => requested.has(v.refUID))\n : await dataSource.getVersionsForSeeds(seedUids, { includeRevoked: true })\n // Anyone can attest with any refUID: only the seed's attester's versions count.\n const allVersions = keepAttestationsFromRefAttester(fetchedVersions, seeds)\n const itemVersions = allVersions.filter((v) => v.revoked !== true)\n\n if (opts.dropSeedsWithOnlyRevokedVersions) {\n // Like the SDK (latest published version skips revoked ones): every version revoked means\n // no published version, so the seed is left out. A seed with no version at all is kept.\n const seedsWithLiveVersion = new Set(itemVersions.map((v) => v.refUID))\n for (const version of allVersions) {\n const seedUid = version.refUID\n if (seedsWithLiveVersion.has(seedUid) || !requested.has(seedUid)) continue\n ctx.assembledItems.delete(seedUid)\n ctx.seedUidToModelType.delete(seedUid)\n ctx.droppedSeedUids.add(seedUid)\n }\n }\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 // Each seed's assembled version: the pinned one, else the latest. A pinned seed without that\n // version (not the seed's, revoked, or created after `asOf`) is left out, like a seed whose\n // versions were all revoked.\n const latestVersionUids: string[] = []\n const asOfByVersionUid = new Map<string, number>()\n for (const seedUid of seedUids) {\n const pin = opts.pins?.get(seedUid.toLowerCase())\n if (!pin) continue\n const pinned = pinnedVersion(ctx.versionsBySeedUid.get(seedUid) ?? [], pin)\n if (!pinned) {\n ctx.assembledItems.delete(seedUid)\n ctx.seedUidToModelType.delete(seedUid)\n ctx.versionsBySeedUid.delete(seedUid)\n ctx.droppedSeedUids.add(seedUid)\n continue\n }\n latestVersionUids.push(pinned.id)\n ctx.latestVersionUidsBySeedUid.set(seedUid, pinned.id)\n if (pin.asOf !== undefined) asOfByVersionUid.set(pinned.id, pin.asOf)\n }\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 = keepAttestationsFromRefAttester(\n await dataSource.getPropertiesForVersionUids(latestVersionUids),\n itemVersions,\n ).filter((property) => {\n const asOf = asOfByVersionUid.get(property.refUID)\n return asOf === undefined || property.timeCreated <= asOf\n })\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): void {\n for (const [, item] of requestedItems(ctx)) {\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(ctx: AssembleContext, expandRelations: boolean): void {\n if (!expandRelations) return\n\n for (const [, item] of requestedItems(ctx)) {\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\n/** A record still being assembled (hydration fills in its data); read-only once returned. */\ntype AssembledRecord = Omit<SeedRecord, 'data'> & { data: Record<string, unknown> }\n\nfunction toSeedRecords(ctx: AssembleContext, schemaName?: string): AssembledRecord[] {\n return requestedItems(ctx).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: schemaName ?? ctx.seedUidToModelType.get(seedUid) ?? 'unknown',\n attester,\n timeCreated,\n versionUid,\n data: item,\n }\n })\n}\n\n/**\n * What an assembled record was built from, so a cache can tell when it changed: an attestation\n * created or revoked later that references one of `refUIDs` (a new or revoked Version of the seed\n * or of a seed it relates to, a property of one of their head Versions) or is one of `ids` (the\n * seed or a related seed, revoked).\n */\nexport type SeedDependencies = {\n refUIDs: string[]\n ids: string[]\n}\n\nfunction dependenciesOf(ctx: AssembleContext, seedUid: string): SeedDependencies {\n const seedUids = [seedUid, ...(ctx.relatedSeedUidsBySeedUid.get(seedUid) ?? [])]\n const headVersionUids = seedUids\n .map((uid) => ctx.latestVersionUidsBySeedUid.get(uid))\n .filter((uid): uid is string => !!uid)\n return { refUIDs: [...seedUids, ...headVersionUids], ids: seedUids }\n}\n\nexport type AssembleRequest = {\n /** The schema name every record gets. Default: each seed's own (its first schema name). */\n schemaName?: string\n /** Versions of the seeds already fetched with `includeRevoked: true` (see getSeed). */\n versions?: AttestationLike[]\n /**\n * Versions to assemble instead of the latest, by seed UID. Applies to `seeds` only: related\n * seeds are always assembled at their latest version.\n */\n pins?: ReadonlyMap<string, VersionPin>\n}\n\n/**\n * Like assembleSeeds, plus each record's dependencies by seedUid (see SeedDependencies).\n */\nexport async function assembleSeedsWithDependencies(\n schemaName: string,\n seeds: AttestationLike[],\n options?: AssembleOptions,\n dataSource: QueryDataSource = getRemoteQueryDataSource(),\n /** Versions of `seeds` already fetched with `includeRevoked: true` (see getSeed). */\n prefetched?: { versions?: AttestationLike[] },\n): Promise<{ records: SeedRecord[]; dependencies: Map<string, SeedDependencies> }> {\n return assembleSeedRecords(seeds, options, dataSource, {\n schemaName,\n versions: prefetched?.versions,\n })\n}\n\n/**\n * Records for `seeds`, in order, which may be of different schemas, with each record's\n * dependencies by seedUid. One set of requests for all of them: seeds and versions, properties,\n * related seeds and their versions, related properties, then storage bodies.\n */\nexport async function assembleSeedRecords(\n seeds: AttestationLike[],\n options: AssembleOptions | undefined,\n dataSource: QueryDataSource,\n request: AssembleRequest = {},\n): Promise<{ records: SeedRecord[]; dependencies: Map<string, SeedDependencies> }> {\n const expandRelations = options?.expandRelations !== false\n const hydrateStorage = options?.hydrateStorage !== false\n\n const ctx = createAssembleContext()\n for (const seed of seeds) if (seed) ctx.requestedSeedUids.add(seed.id)\n\n await processSeeds(ctx, seeds, dataSource, {\n dropSeedsWithOnlyRevokedVersions: true,\n versions: request.versions,\n pins: request.pins && activePins(request.pins),\n })\n\n const relatedSeedUidsArray = Array.from(ctx.relatedSeedUids).filter(\n (uid) => !ctx.assembledItems.has(uid) && !ctx.droppedSeedUids.has(uid),\n )\n if (relatedSeedUidsArray.length > 0) {\n // Their versions only need the UIDs, so they are fetched alongside the seeds. Versions of a\n // related seed that isn't returned (revoked, or not found) are ignored by processSeeds.\n const [relatedSeeds, relatedVersions] = await Promise.all([\n dataSource.getSeedsByUids(relatedSeedUidsArray),\n dataSource.getVersionsForSeeds(relatedSeedUidsArray, { includeRevoked: true }),\n ])\n await processSeeds(ctx, relatedSeeds, dataSource, { versions: relatedVersions })\n }\n\n resolveRelationPropertiesToUrls(ctx)\n expandRelationProperties(ctx, expandRelations)\n\n const records = toSeedRecords(ctx, request.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 const dependencies = new Map(\n records.map((record) => [record.seedUid, dependenciesOf(ctx, record.seedUid)]),\n )\n return { records, dependencies }\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 return (await assembleSeedsWithDependencies(schemaName, seeds, options, dataSource)).records\n}\n","import { decodeEasNumber, isNumericEasType } from '@seedprotocol/eas'\nimport { 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 // ADR 0010: an integer value as its decimal string, not the indexer's `{ type: 'BigNumber', hex }`.\n const decimal = isNumericEasType(easType) ? decodeEasNumber(propertyValue) : undefined\n propertyValue = decimal ?? 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 {\n keepAttestationsFromRefAttester,\n pickLatestPropertyAttestationsByRefAndSchema,\n} 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 // Anyone can attest with any refUID: only the seed's attester's versions, and each version's\n // attester's properties, count.\n const [seed, fetchedVersions] = await Promise.all([\n dataSource.getSeedByUid(seedUid),\n dataSource.getVersionsForSeed(seedUid),\n ])\n const itemVersions = keepAttestationsFromRefAttester(fetchedVersions, seed ? [seed] : [])\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 = keepAttestationsFromRefAttester(\n await dataSource.getPropertiesForVersionUids(versionUids),\n sortedVersions,\n )\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'\nimport type { GetSeedResult } from '../types.js'\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 from its records' ETags (in order), so it\n * changes whenever a record's content does.\n */\nexport function generateCollectionETag(\n schemaName: string,\n optionsKey: string,\n itemETags: string[],\n): string {\n return generateETag(`${schemaName}-${optionsKey}-${itemETags.join(',')}`)\n}\n\n/**\n * Generate an ETag for a single record from its content (a patch publish changes properties\n * without a new versionUid, so ids alone don't identify the content).\n */\nexport function generateItemETag(record: GetSeedResult, optionsKey: string): string {\n return generateETag(`${optionsKey}-${stableStringify(record)}`)\n}\n\n/**\n * JSON with object keys sorted: property order follows attestation order, which differs between\n * a seed assembled alone and in a batch, and must not change the ETag.\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(value, (_key, v: unknown) =>\n v && typeof v === 'object' && !Array.isArray(v)\n ? Object.fromEntries(\n Object.keys(v as Record<string, unknown>)\n .sort()\n .map((k) => [k, (v as Record<string, unknown>)[k]]),\n )\n : v,\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 *\n * Records are deep-frozen as they enter the memory cache unless NODE_ENV=production\n * (see {@link defaultFreezeRecords}).\n */\n/**\n * Cached records are handed to callers by reference, so a caller that mutates one corrupts the\n * cache. Outside production they are frozen when cached so such a write throws (in strict mode)\n * instead; production skips the walk.\n */\nexport function defaultFreezeRecords(): boolean {\n return env().NODE_ENV !== 'production'\n}\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 freezeRecords: defaultFreezeRecords(),\n }\n}\n","/**\n * Freezes `value` and everything reachable from it, children before parents, so a frozen object's\n * subtree is already frozen and is skipped (records share related-seed clones, and write-through\n * freezes the same nested objects more than once). Typed arrays can't be frozen and are left as is.\n */\nexport function deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== 'object' || Object.isFrozen(value)) return value\n if (ArrayBuffer.isView(value)) return value\n for (const child of Object.values(value)) deepFreeze(child)\n return Object.freeze(value)\n}\n","import type {\n CachedCollectionData,\n CachedItemData,\n QueryCacheConfig,\n} from './types.js'\nimport { defaultFreezeRecords } from './config.js'\nimport { deepFreeze } from './freeze.js'\n\n/**\n * In-memory collection + item cache with TTL and refresh locks.\n * Entries expire `ttl` seconds after their `lastUpdated` (their last full assembly).\n * Stored records are returned to callers by reference; with `freezeRecords` they are deep-frozen\n * on the way in so a caller can't mutate them silently.\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 collectionKey(schemaName: string, optionsKey: string): string {\n return `${schemaName}\\n${optionsKey}`\n }\n\n private itemKey(seedUid: string, optionsKey: string): string {\n return `${seedUid}:${optionsKey}`\n }\n\n private get freezeRecords(): boolean {\n return this.config.freezeRecords ?? defaultFreezeRecords()\n }\n\n private expired(lastUpdated: number): boolean {\n return Math.floor(Date.now() / 1000) - lastUpdated > this.config.ttl\n }\n\n getCollection(schemaName: string, optionsKey: string): CachedCollectionData | null {\n const key = this.collectionKey(schemaName, optionsKey)\n const cached = this.collectionCache.get(key)\n if (!cached) return null\n if (this.expired(cached.lastUpdated)) {\n this.collectionCache.delete(key)\n return null\n }\n return cached\n }\n\n setCollection(schemaName: string, optionsKey: string, data: CachedCollectionData): void {\n if (this.freezeRecords) for (const item of data.items) deepFreeze(item)\n this.collectionCache.set(this.collectionKey(schemaName, optionsKey), data)\n }\n\n getItem(seedUid: string, optionsKey: string): CachedItemData | null {\n const key = this.itemKey(seedUid, optionsKey)\n const cached = this.itemCache.get(key)\n if (!cached) return null\n if (this.expired(cached.lastUpdated)) {\n this.itemCache.delete(key)\n return null\n }\n return cached\n }\n\n setItem(data: CachedItemData): void {\n if (this.freezeRecords) deepFreeze(data.record)\n this.itemCache.set(this.itemKey(data.record.seedUid, data.optionsKey), data)\n }\n\n /** Every options variant of the schema's collection. */\n clearCollection(schemaName: string): void {\n for (const key of this.collectionCache.keys()) {\n if (key.startsWith(`${schemaName}\\n`)) this.collectionCache.delete(key)\n }\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 with the same key share one in-flight promise.\n */\n async withRefreshLock<T>(\n key: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n const existingLock = this.refreshLocks.get(key)\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(key)\n }\n })()\n\n this.refreshLocks.set(key, 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 { generateCollectionETag, generateItemETag } from './etag.js'\nimport { MemoryCache } from './MemoryCache.js'\nimport type {\n CachedCollectionData,\n CachedItemData,\n PersistentCache,\n QueryCacheConfig,\n QueryCacheStats,\n} from './types.js'\nimport type { GetSeedResult } 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 * Entries written before change tracking (or by another version) lack its bookkeeping and can't\n * be checked for changes, so they are treated as misses.\n */\nfunction isCurrentCollection(data: unknown): data is CachedCollectionData {\n const d = data as Partial<CachedCollectionData> | null\n return (\n !!d &&\n Array.isArray(d.items) &&\n typeof d.meta === 'object' &&\n d.meta !== null &&\n typeof d.checkedAt === 'number' &&\n Array.isArray(d.seenChangeKeys)\n )\n}\n\nfunction isCurrentItem(data: unknown): data is CachedItemData {\n const d = data as Partial<CachedItemData> | null\n return (\n !!d &&\n !!d.record &&\n !!d.dependencies &&\n typeof d.checkedAt === 'number' &&\n Array.isArray(d.seenChangeKeys)\n )\n}\n\n/**\n * Unified query cache: memory, with optional persistent (disk) layer.\n * Collections are kept per schema and assemble-options key.\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 optionsKey: string,\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n let cached = this.memoryCache.getCollection(schemaName, optionsKey)\n if (cached) {\n this.stats.hits++\n return cached\n }\n\n const persisted = (await this.persistent?.getCollection(schemaName, optionsKey)) ?? null\n if (isCurrentCollection(persisted)) {\n this.memoryCache.setCollection(schemaName, optionsKey, persisted)\n this.stats.hits++\n return persisted\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 /** Stores a collection; its ETag is derived from the records' content. */\n async setCollection(\n schemaName: string,\n optionsKey: string,\n data: Omit<CachedCollectionData, 'etag'>,\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n const items = data.items.map((r) => ({ ...r, data: { ...r.data } }))\n const etag = generateCollectionETag(\n schemaName,\n optionsKey,\n items.map((r) => generateItemETag(r, optionsKey)),\n )\n const cached: CachedCollectionData = { ...data, items, etag }\n this.memoryCache.setCollection(schemaName, optionsKey, cached)\n await this.persistent?.setCollection(schemaName, optionsKey, 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 const persisted = (await this.persistent?.getItem(seedUid, optionsKey)) ?? null\n if (isCurrentItem(persisted)) {\n this.memoryCache.setItem(persisted)\n this.stats.hits++\n return persisted\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 /** Stores an item; its ETag is derived from the record's content. */\n async setItem(\n data: Omit<CachedItemData, 'etag'>,\n ): Promise<CachedItemData | null> {\n if (!this.config.enabled) return null\n\n try {\n const record: GetSeedResult = {\n ...data.record,\n data: { ...data.record.data },\n ...(data.record.changelog && { changelog: [...data.record.changelog] }),\n }\n const cached: CachedItemData = {\n ...data,\n record,\n etag: generateItemETag(record, data.optionsKey),\n }\n this.memoryCache.setItem(cached)\n await this.persistent?.setItem(cached)\n return cached\n } catch (error) {\n console.error(\n `Error setting query item cache for ${data.record.seedUid}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async writeThroughItems(items: Array<Omit<CachedItemData, 'etag'>>): Promise<void> {\n if (!this.config.enabled) return\n for (const item of items) {\n await this.setItem(item)\n }\n }\n\n async clearItem(seedUid: string, optionsKey: string): Promise<void> {\n this.memoryCache.clearItem(seedUid, optionsKey)\n await this.persistent?.clearItem(seedUid, optionsKey)\n }\n\n /** Every options variant of the schema's collection. */\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 key: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n return this.memoryCache.withRefreshLock(key, fn)\n }\n\n /** Counts a cache hit that was checked against changes and refreshed in part. */\n recordRefresh(): void {\n this.stats.refreshes++\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 { 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 { SeedDependencies } from '../assembleSeeds.js'\nimport type { QueryDataSource } from '../source/types.js'\nimport type { AttestationChange } from '../types.js'\nimport type { ChangeCheck } from './types.js'\n\n/**\n * Each change check looks back this far before the previous check started, so an attestation\n * the indexer lists late, or a clock between here and the chain that is off, is still seen.\n * Changes inside the overlap that were already applied are skipped by their key.\n */\nexport const CHANGE_CHECK_OVERLAP_SECONDS = 600\n\nexport function nowSeconds(): number {\n return Math.floor(Date.now() / 1000)\n}\n\n/** `checkedAt` for a check that started at `startedAt`. */\nexport function checkedAtFor(startedAt: number): number {\n return startedAt - CHANGE_CHECK_OVERLAP_SECONDS\n}\n\n/**\n * True when a check found nothing but its window has grown past twice the overlap, so it is worth\n * storing the new `checkedAt` to keep later requests small. (Storing it is otherwise not needed:\n * an unchanged entry's next check sees only changes it has already seen.)\n */\nexport function checkWindowAged(check: ChangeCheck, startedAt: number): boolean {\n return checkedAtFor(startedAt) - check.checkedAt > CHANGE_CHECK_OVERLAP_SECONDS\n}\n\nconst changeKey = (change: AttestationChange): string => `${change.id}:${change.revocationTime}`\n\n/**\n * Which of the cached seeds changed since `check.checkedAt`: a new or revoked Version of a seed\n * it depends on, a new or revoked property on one of their head Versions, or one of those seeds\n * revoked. Returns null when the data source can't list changes (treat everything as changed).\n */\nexport async function findChangedSeeds(\n dataSource: QueryDataSource,\n dependenciesBySeedUid: Map<string, SeedDependencies>,\n check: ChangeCheck,\n): Promise<{ changed: Set<string>; seenChangeKeys: string[] } | null> {\n if (!dataSource.listChangesSince) return null\n if (dependenciesBySeedUid.size === 0) {\n return { changed: new Set(), seenChangeKeys: check.seenChangeKeys }\n }\n\n const seedUidsByRef = new Map<string, string[]>()\n const seedUidsById = new Map<string, string[]>()\n const index = (map: Map<string, string[]>, uid: string, seedUid: string) => {\n const seedUids = map.get(uid)\n if (seedUids) seedUids.push(seedUid)\n else map.set(uid, [seedUid])\n }\n for (const [seedUid, deps] of dependenciesBySeedUid) {\n for (const uid of deps.refUIDs) index(seedUidsByRef, uid, seedUid)\n for (const uid of deps.ids) index(seedUidsById, uid, seedUid)\n }\n\n const changes = await dataSource.listChangesSince({\n refUIDs: [...seedUidsByRef.keys()],\n ids: [...seedUidsById.keys()],\n since: check.checkedAt,\n })\n\n const seen = new Set(check.seenChangeKeys)\n const changed = new Set<string>()\n for (const change of changes) {\n if (seen.has(changeKey(change))) continue\n for (const seedUid of seedUidsByRef.get(change.refUID) ?? []) changed.add(seedUid)\n for (const seedUid of seedUidsById.get(change.id) ?? []) changed.add(seedUid)\n }\n return { changed, seenChangeKeys: changes.map(changeKey) }\n}\n\n/** A cached item to check: what it depends on, and its own check window. */\nexport type ItemChangeCheck = ChangeCheck & { dependencies: SeedDependencies }\n\n/**\n * Like findChangedSeeds for items checked at different times: one request from the oldest\n * `checkedAt`, then each item counts only changes after its own `checkedAt` that it hasn't seen.\n * `seenChangeKeys` is per item. Returns null when the data source can't list changes.\n */\nexport async function findChangedItems(\n dataSource: QueryDataSource,\n checks: Map<string, ItemChangeCheck>,\n): Promise<{ changed: Set<string>; seenChangeKeys: Map<string, string[]> } | null> {\n if (!dataSource.listChangesSince) return null\n const changed = new Set<string>()\n const seenChangeKeys = new Map<string, string[]>()\n if (checks.size === 0) return { changed, seenChangeKeys }\n\n const refUIDs = new Set<string>()\n const ids = new Set<string>()\n let since = Infinity\n for (const check of checks.values()) {\n for (const uid of check.dependencies.refUIDs) refUIDs.add(uid)\n for (const uid of check.dependencies.ids) ids.add(uid)\n since = Math.min(since, check.checkedAt)\n }\n const changes = await dataSource.listChangesSince({\n refUIDs: [...refUIDs],\n ids: [...ids],\n since,\n })\n\n for (const [seedUid, check] of checks) {\n const refs = new Set(check.dependencies.refUIDs)\n const own = new Set(check.dependencies.ids)\n const seen = new Set(check.seenChangeKeys)\n const keys: string[] = []\n for (const change of changes) {\n if (change.timeCreated <= check.checkedAt && change.revocationTime <= check.checkedAt) continue\n if (!refs.has(change.refUID) && !own.has(change.id)) continue\n keys.push(changeKey(change))\n if (!seen.has(changeKey(change))) changed.add(seedUid)\n }\n seenChangeKeys.set(seedUid, keys)\n }\n return { changed, seenChangeKeys }\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 {\n assembleSeedRecords,\n assembleSeedsWithDependencies,\n type SeedDependencies,\n} from './assembleSeeds.js'\nimport { assembleSeedChangelog } from './assembleChangelog.js'\nimport {\n buildAssembleOptionsKey,\n getQueryCacheManager,\n} from './cache/index.js'\nimport {\n checkedAtFor,\n checkWindowAged,\n findChangedItems,\n findChangedSeeds,\n nowSeconds,\n type ItemChangeCheck,\n} from './cache/changes.js'\nimport type { CachedItemData, CachedRecordMeta } from './cache/types.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 GetSeedsOptions,\n QueryBySchemaOptions,\n QueryBySchemaResult,\n AttestationLike,\n SeedRecord,\n VersionPin,\n} from './types.js'\n\nconst NO_DEPENDENCIES: SeedDependencies = { refUIDs: [], ids: [] }\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\ntype Assembled = {\n records: SeedRecord[]\n dependencies: Map<string, SeedDependencies>\n}\n\nasync function fetchAndAssemble(\n schemaName: string,\n limit: number,\n skip: number,\n options: AssembleOptions | undefined,\n dataSource: QueryDataSource,\n): Promise<Assembled> {\n const seeds = await dataSource.listSeedsBySchemaName(schemaName, {\n limit,\n skip,\n })\n return assembleSeedsWithDependencies(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<Assembled>,\n): Promise<{ assembled: Assembled; dataSource: QueryDataSource; useQueryCache: boolean }> {\n const assembled = await run(dataSource)\n if (mode !== 'auto' || dataSource.kind !== 'local') {\n return {\n assembled,\n dataSource,\n useQueryCache: dataSource.kind === 'remote',\n }\n }\n if (assembled.records.length > 0) {\n return { assembled, dataSource, useQueryCache: false }\n }\n const remote = getRemoteQueryDataSource()\n return { assembled: await run(remote), dataSource: remote, useQueryCache: true }\n}\n\n/** Item-cache write-through for records assembled by a read that started at `startedAt`. */\nasync function writeThroughAssembled(\n assembled: Assembled,\n optionsKey: string,\n startedAt: number,\n seenChangeKeys: string[] = [],\n): Promise<void> {\n await getQueryCacheManager().writeThroughItems(\n assembled.records.map((record) => ({\n record,\n optionsKey,\n dependencies: assembled.dependencies.get(record.seedUid) ?? NO_DEPENDENCIES,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys,\n lastUpdated: startedAt,\n })),\n )\n}\n\n/**\n * The schema's first `limit` seeds, newest first, from the collection cache where they haven't\n * changed. The seed list itself is always fetched (it's cheap, and shows new and revoked seeds);\n * cached seeds are checked for changes in one request (see findChangedSeeds), and only new or\n * changed seeds are assembled. The TTL counts from the last full assembly.\n */\nasync function refreshCollection(\n schemaName: string,\n limit: number,\n options: QueryBySchemaOptions | undefined,\n optionsKey: string,\n dataSource: QueryDataSource,\n): Promise<QueryBySchemaResult> {\n const cache = getQueryCacheManager()\n const startedAt = nowSeconds()\n const cached = await cache.getCollection(schemaName, optionsKey)\n const listed = await dataSource.listSeedsBySchemaName(schemaName, { limit, skip: 0 })\n\n const cachedBySeedUid = new Map(cached?.items.map((item) => [item.seedUid, item]) ?? [])\n let changed = new Set<string>()\n let seenChangeKeys: string[] = []\n if (cached) {\n const toCheck = new Map<string, SeedDependencies>()\n for (const seed of listed) {\n const meta = cached.meta[seed.id]\n if (cachedBySeedUid.has(seed.id)) toCheck.set(seed.id, meta?.dependencies ?? NO_DEPENDENCIES)\n }\n const found = await findChangedSeeds(dataSource, toCheck, cached)\n if (found) {\n changed = found.changed\n seenChangeKeys = found.seenChangeKeys\n } else {\n changed = new Set(toCheck.keys())\n }\n }\n\n const toAssemble = listed.filter((seed) => !cachedBySeedUid.has(seed.id) || changed.has(seed.id))\n const fresh =\n toAssemble.length > 0\n ? await assembleSeedsWithDependencies(schemaName, toAssemble, options, dataSource)\n : { records: [], dependencies: new Map<string, SeedDependencies>() } satisfies Assembled\n const freshBySeedUid = new Map(fresh.records.map((record) => [record.seedUid, record]))\n\n // In list order. A changed seed that no longer assembles (every version revoked) drops out,\n // as do cached seeds no longer listed (revoked, or pushed past `limit`).\n const items: SeedRecord[] = []\n const meta: Record<string, CachedRecordMeta> = {}\n for (const seed of listed) {\n const record = freshBySeedUid.get(seed.id)\n if (record) {\n items.push(record)\n meta[seed.id] = {\n dependencies: fresh.dependencies.get(seed.id) ?? NO_DEPENDENCIES,\n builtAt: startedAt,\n }\n } else if (cached && !changed.has(seed.id) && cachedBySeedUid.has(seed.id)) {\n items.push(cachedBySeedUid.get(seed.id)!)\n meta[seed.id] = cached.meta[seed.id] ?? { dependencies: NO_DEPENDENCIES, builtAt: startedAt }\n }\n }\n\n const unchanged =\n !!cached &&\n fresh.records.length === 0 &&\n items.length === cached.items.length &&\n items.every((item, i) => item === cached.items[i])\n if (cached && unchanged && !checkWindowAged(cached, startedAt)) {\n return { items, limit, skip: 0, etag: cached.etag }\n }\n if (cached) cache.recordRefresh()\n\n const stored = await cache.setCollection(schemaName, optionsKey, {\n items,\n meta,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys,\n lastUpdated: cached?.lastUpdated ?? startedAt,\n })\n await writeThroughAssembled(fresh, optionsKey, startedAt, seenChangeKeys)\n // The cached records (frozen outside production), so a fresh result behaves like a cache hit.\n return { items: stored ? [...stored.items] : items, limit, skip: 0, etag: stored?.etag }\n}\n\n/** Hex digits a uid prefix needs, so a stray short value can't list most of a schema. */\nconst MIN_UID_PREFIX_HEX_DIGITS = 4\n\n/**\n * `0x` + lowercase hex for a seed UID prefix given with or without `0x`, in any case (EAS indexes\n * UIDs lowercase and matches prefixes case-sensitively). Null when it isn't 4–64 hex digits.\n */\nexport function normalizeUidPrefix(prefix: string): string | null {\n const hex = prefix.trim().toLowerCase().replace(/^0x/, '')\n if (hex.length < MIN_UID_PREFIX_HEX_DIGITS || hex.length > 64) return null\n if (!/^[0-9a-f]+$/.test(hex)) return null\n return `0x${hex}`\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 let uidPrefix: string | null = null\n if (options?.uidPrefix !== undefined) {\n uidPrefix = normalizeUidPrefix(options.uidPrefix)\n if (!uidPrefix) return { items: [], limit, skip }\n }\n\n const runAssemble = async (ds: QueryDataSource): Promise<Assembled> => {\n if (!uidPrefix) return fetchAndAssemble(schemaName, limit, skip, options, ds)\n const seeds = await ds.listSeedsByUidPrefix(schemaName, uidPrefix, { limit, skip })\n return assembleSeedsWithDependencies(schemaName, seeds, options, ds)\n }\n\n // Collection cache only for remote + skip=0 working set (a uid-prefix match isn't one)\n if (\n !uidPrefix &&\n shouldUseCache(options, resolved.useQueryCache) &&\n skip === 0 &&\n resolved.dataSource.kind === 'remote'\n ) {\n const lockKey = `${schemaName}\\n${optionsKey}\\n${limit}`\n return getQueryCacheManager().withRefreshLock(lockKey, () =>\n refreshCollection(schemaName, limit, options, optionsKey, resolved.dataSource),\n )\n }\n\n const startedAt = nowSeconds()\n const {\n assembled,\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 writeThroughAssembled(assembled, optionsKey, startedAt)\n }\n return { items: assembled.records, limit, skip }\n}\n\n/**\n * Cached items, by seedUid, for the seeds whose dependencies haven't changed since each was last\n * checked (one change request for all; see findChangedItems). Changed items are dropped so the\n * caller assembles them again.\n */\nasync function getUnchangedCachedItems(\n requests: Array<{ seedUid: string; optionsKey: string }>,\n dataSource: QueryDataSource,\n): Promise<Map<string, GetSeedResult>> {\n const cache = getQueryCacheManager()\n const cachedBySeedUid = new Map<string, CachedItemData>()\n await Promise.all(\n requests.map(async ({ seedUid, optionsKey }) => {\n const cached = await cache.getItem(seedUid, optionsKey)\n if (cached) cachedBySeedUid.set(seedUid, cached)\n }),\n )\n const hits = new Map<string, GetSeedResult>()\n if (cachedBySeedUid.size === 0) return hits\n\n const startedAt = nowSeconds()\n const checks = new Map<string, ItemChangeCheck>()\n for (const [seedUid, cached] of cachedBySeedUid) checks.set(seedUid, cached)\n const found = await findChangedItems(dataSource, checks)\n for (const [seedUid, cached] of cachedBySeedUid) {\n if (!found || found.changed.has(seedUid)) {\n await cache.clearItem(seedUid, cached.optionsKey)\n continue\n }\n if (checkWindowAged(cached, startedAt)) {\n await cache.setItem({\n ...cached,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys: found.seenChangeKeys.get(seedUid) ?? [],\n })\n }\n hits.set(seedUid, cached.record)\n }\n return hits\n}\n\nasync function getUnchangedCachedItem(\n seedUid: string,\n optionsKey: string,\n dataSource: QueryDataSource,\n): Promise<GetSeedResult | null> {\n const hits = await getUnchangedCachedItems([{ seedUid, optionsKey }], dataSource)\n return hits.get(seedUid) ?? null\n}\n\n/** The pin in `options`, if it names a version or a time. */\nfunction pinOf(options: VersionPin | undefined): VersionPin | undefined {\n if (options?.versionUid === undefined && options?.asOf === undefined) return undefined\n return { versionUid: options.versionUid, asOf: options.asOf }\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 getUnchangedCachedItem(trimmed, optionsKey, dataSource)\n if (cached) return cached\n }\n\n // The seed's versions only need its UID, so they are fetched alongside the seed (assembly\n // would otherwise ask for them after it).\n const fetchSeedAndVersions = (ds: QueryDataSource) =>\n Promise.all([\n ds.getSeedByUid(trimmed),\n ds.getVersionsForSeeds([trimmed], { includeRevoked: true }),\n ])\n\n const startedAt = nowSeconds()\n let [seed, versions] = await fetchSeedAndVersions(dataSource)\n\n // auto: local miss → remote\n if (!seed && mode === 'auto' && dataSource.kind === 'local') {\n dataSource = getRemoteQueryDataSource()\n allowCache = true\n if (shouldUseCache(options, allowCache)) {\n const cached = await getUnchangedCachedItem(trimmed, optionsKey, dataSource)\n if (cached) return cached\n }\n ;[seed, versions] = await fetchSeedAndVersions(dataSource)\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 let dependencies: SeedDependencies = { refUIDs: [trimmed], ids: [trimmed] }\n\n const pin = pinOf(options)\n const assembleData = async (): Promise<SeedRecord | null> => {\n const assembled = await assembleSeedRecords([seed], options, dataSource, {\n schemaName,\n versions,\n pins: pin && new Map([[trimmed, pin]]),\n })\n const record = assembled.records[0]\n if (record) dependencies = assembled.dependencies.get(record.seedUid) ?? dependencies\n return record ?? null\n }\n\n if (!wantsChangelog(include)) {\n result = await assembleData()\n } else {\n const { latestVersionUid, changelog } = await assembleSeedChangelog(\n trimmed,\n options,\n dataSource,\n )\n\n if (wantsData(include)) {\n const record = await assembleData()\n result = record ? { ...record, changelog } : null\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 if (latestVersionUid) dependencies.refUIDs.push(latestVersionUid)\n }\n // Property changes on any version in the changelog change it.\n for (const entry of changelog) dependencies.refUIDs.push(entry.versionUid)\n dependencies = {\n refUIDs: [...new Set(dependencies.refUIDs)],\n ids: dependencies.ids,\n }\n }\n\n if (\n result &&\n shouldUseCache(options, allowCache) &&\n dataSource.kind === 'remote'\n ) {\n const stored = await getQueryCacheManager().setItem({\n record: result,\n optionsKey,\n dependencies,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys: [],\n lastUpdated: startedAt,\n })\n // The cached record (frozen outside production), so a fresh result behaves like a cache hit.\n if (stored) result = stored.record\n }\n\n return result\n}\n\n/**\n * Many seeds, of any schemas, keyed by UID as given (first spelling of each, in order). Seeds\n * not found, revoked, or without their pinned version are left out. Uncached seeds are\n * assembled together, in one set of requests (see assembleSeedRecords), and cached ones are\n * checked for changes in one request; records are shared with `getSeed` (same item cache).\n * A seed can be read at one version per call.\n */\nexport async function getSeeds(\n seedUids: readonly string[],\n options?: GetSeedsOptions,\n): Promise<Map<string, SeedRecord>> {\n await initializeQueryPlatform()\n\n // Read lowercase (EAS indexes UIDs lowercase and matches them case-sensitively); keyed as given.\n const givenByUid = new Map<string, string>()\n for (const given of seedUids) {\n if (typeof given !== 'string' || given.trim() === '') continue\n const uid = given.trim().toLowerCase()\n if (!givenByUid.has(uid)) givenByUid.set(uid, given.trim())\n }\n const requested = [...givenByUid.keys()]\n if (requested.length === 0) return new Map()\n\n const pins = new Map<string, VersionPin>()\n for (const [uid, pin] of options?.pins ?? []) {\n const active = pinOf(pin)\n if (active) pins.set(uid.trim().toLowerCase(), active)\n }\n const optionsKeyFor = (seedUid: string) =>\n buildAssembleOptionsKey({ ...options, ...pins.get(seedUid) })\n\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n const found = new Map<string, SeedRecord>()\n\n /** Reads `uids` from `dataSource` into `found`; returns the ones whose seed it doesn't have. */\n const readFrom = async (\n dataSource: QueryDataSource,\n allowCache: boolean,\n uids: string[],\n ): Promise<string[]> => {\n const useCache = shouldUseCache(options, allowCache) && dataSource.kind === 'remote'\n let toFetch = uids\n if (useCache) {\n const hits = await getUnchangedCachedItems(\n uids.map((seedUid) => ({ seedUid, optionsKey: optionsKeyFor(seedUid) })),\n dataSource,\n )\n for (const [seedUid, record] of hits) found.set(seedUid, record)\n toFetch = uids.filter((uid) => !hits.has(uid))\n }\n if (toFetch.length === 0) return []\n\n const startedAt = nowSeconds()\n const [seeds, versions] = await Promise.all([\n dataSource.getSeedsByUids(toFetch),\n dataSource.getVersionsForSeeds(toFetch, { includeRevoked: true }),\n ])\n const seedByUid = new Map(seeds.map((seed) => [seed.id.toLowerCase(), seed]))\n const missing = toFetch.filter((uid) => !seedByUid.has(uid))\n // Like getSeed: a seed without a schema name isn't assembled.\n const toAssemble = toFetch\n .map((uid) => seedByUid.get(uid))\n .filter((seed): seed is AttestationLike => !!seed?.schema?.schemaNames?.[0]?.name)\n\n const assembled = await assembleSeedRecords(toAssemble, options, dataSource, {\n versions,\n pins,\n })\n for (const record of assembled.records) {\n let result: SeedRecord = record\n if (useCache) {\n const stored = await getQueryCacheManager().setItem({\n record,\n optionsKey: optionsKeyFor(record.seedUid.toLowerCase()),\n dependencies: assembled.dependencies.get(record.seedUid) ?? {\n refUIDs: [record.seedUid],\n ids: [record.seedUid],\n },\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys: [],\n lastUpdated: startedAt,\n })\n // The cached record (frozen outside production), so a fresh result behaves like a cache hit.\n if (stored) result = stored.record\n }\n found.set(record.seedUid.toLowerCase(), result)\n }\n return missing\n }\n\n const missing = await readFrom(resolved.dataSource, resolved.useQueryCache, requested)\n // auto: seeds the local source doesn't have → remote\n if (missing.length > 0 && mode === 'auto' && resolved.dataSource.kind === 'local') {\n await readFrom(getRemoteQueryDataSource(), true, missing)\n }\n\n const result = new Map<string, SeedRecord>()\n for (const [uid, given] of givenByUid) {\n const record = found.get(uid)\n if (record) result.set(given, record)\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 assembleSeedsWithDependencies(schemaName, seeds, options, ds)\n }\n\n const startedAt = nowSeconds()\n const { assembled, dataSource: used, useQueryCache } =\n await withAutoFallbackForCollection(mode, resolved.dataSource, run)\n\n if (shouldUseCache(options, useQueryCache) && used.kind === 'remote') {\n await writeThroughAssembled(assembled, buildAssembleOptionsKey(options), startedAt)\n }\n\n return assembled.records\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"src-D20xeLMs.js","names":["toCamelCase","initializeQueryPlatform","pluralize","getArweaveUrlForTransaction","BaseArweaveClient","transactionId","CAMEL_LIST_RELATION_IDS","publicListRelationPropertyKey","camel","propertyKey","singularPart","base","segments","singularProperty","stripListRelationStorageAliasesForPublicKey","k","item","publicKey","tryCoerceJsonStringArray","value","s","parsed","enrichImageSeedClone","txId","clone","enrichImageSeedCloneForFeed","RICH_BODY_STORAGE_SCHEMAS","FEED_RICH_BODY_STORAGE_SCHEMAS","FIELD_MODELS_KEY","LIST_MODELS_KEY","normalizeModelName","schemaName","isRichBodyStorageSchema","isFeedRichBodyStorageSchema","richBodyModelPriority","m","feedRichBodyModelPriority","getFieldStorageModels","raw","getFeedFieldStorageModels","getListElementStorageModels","getFeedListElementStorageModels","setFieldStorageModel","normalized","map","fieldKey","setFeedFieldStorageModel","setListElementStorageModels","outputKey","models","setFeedListElementStorageModels","RICH_TEXT_KEYS","MAX_BODY_BYTES","isArweaveTransactionGatewayUrl","u","host","isKnownArweaveGatewayHostname","id","fetchGatewayPayloadAsUtf8","res","url","ct","readArweaveContentResponse","bytes","text","BODY_CACHE_MAX_CHARS","bodyCache","bodyCacheChars","bodiesInFlight","resetArweaveBodyCache","cacheBody","oldest","oldText","fetchTransactionBody","cached","inFlight","request","resolveHydratedBody","readStorageBody","local","HYDRATE_CONCURRENCY","runWithConcurrency","next","limit","tasks","hydrateArweaveRichTextInItems","options","items","keysToHydrate","fieldModels","key","v","listModels","listKey","arr","n","i","el","hydrateArweaveRichTextInFeedItems","parseEasPropertyMetadata","decodedDataJson","parseEasPropertyMetadataForFeed","parseEasRelationPropertyName","modelName","idSegment","easPropertyName","isList","monthBoundsUnix","startDate","year","month","endDate","createRemoteQueryDataSource","seed","getSeedsByUidsFromEas","seedUid","getSeedsBySchemaName","opts","where","withExcludeRevokedFilter","startTs","endTs","EasClient","GET_SEEDS_LEAN","itemSeeds","getItemVersionsFromEas","seedUids","versionUids","getItemPropertiesFromEas","uids","getAttestationChangesSince","remoteSingleton","getRemoteQueryDataSource","IMAGE_SCHEMA","relationValuesToExclude","RESERVED_KEYS","toCamelCase$1","str","letter","createAssembleContext","requestedItems","ctx","ensureSeedIdentity","addRelatedSeedUid","relatedSeedUid","property","related","processItemProperty","refUID","schemaId","metadata","propertyNameSnake","schemaUid","isRelation","easType","isBytes32Relation","isNamingConventionRelation","result","propertyValue","isNumericEasType","decodeEasNumber","seedUidForProperty","existingItem","propertyNameCamel","activePins","active","pin","pins","pinnedVersion","asOf","candidates","versions","b","a","needle","processSeeds","seeds","modelType","requested","fetchedVersions","dataSource","allVersions","keepAttestationsFromRefAttester","itemVersions","seedsWithLiveVersion","version","itemVersion","existingVersions","latestVersionUids","asOfByVersionUid","pinned","latestVersion","rawProperties","itemProperties","pickLatestPropertyAttestationsByRefAndSchema","resolveRelationPropertiesToUrls","keysToProcess","coerced","urls","resolved","uid","modelForUid","camelKey","relatedModel","camelOut","expandRelationProperties","expandRelations","expanded","didExpand","toSeedRecords","versionUid","timeCreated","attester","dependenciesOf","headVersionUids","assembleSeedsWithDependencies","assembleSeedRecords","prefetched","hydrateStorage","relatedSeedUidsArray","relatedSeeds","relatedVersions","records","r","record","assembleSeeds","toCamelCase","changelogValuesEqual","decodePropertyAttestation","camelName","buildFlatSnapshotFromProperties","snapshot","properties","decoded","diffVersionSnapshots","entries","before","snap","sortedSnapshots","after","keySet","changedKeys","diffPropertyAttestations","sorted","previousByProperty","names","previousValue","nextValue","applyChangelogFilters","filtered","since","e","assembleSeedChangelog","changelogOpts","granularity","sortedVersions","latestVersionUid","changelog","byVersion","prop","list","snapshots","propsForVersion","canonical","generateETag","bytesToHex","sha256","utf8ToBytes","generateCollectionETag","optionsKey","itemETags","generateItemETag","stableStringify","env","defaultFreezeRecords","loadQueryCacheConfig","ttl","cacheDir","cacheDisabledByEnvVar","cacheEnabledByEnvVar","isDev","enabled","backgroundRefresh","refreshInterval","deepFreeze","child","MemoryCache","config","lastUpdated","data","existingLock","lockPromise","fn","persistentCacheFactory","configurePersistentCacheFactory","factory","isCurrentCollection","d","isCurrentItem","CacheManager","persistent","persisted","error","etag","cacheManager","getQueryCacheManager","resetQueryCacheManager","createQueryCacheManager","nowSeconds","checkedAtFor","startedAt","checkWindowAged","check","changeKey","change","findChangedSeeds","dependenciesBySeedUid","seedUidsByRef","seedUidsById","index","deps","changes","seen","changed","findChangedItems","seenChangeKeys","checks","refUIDs","ids","refs","own","keys","localSource","registerLocalQuerySource","source","clearLocalQuerySource","getRegisteredLocalQuerySource","hasLocalQuerySource","resolveQuerySource","mode","normalizeSourceMode","NO_DEPENDENCIES","shouldUseCache","allowCache","wantsChangelog","include","wantsData","fetchAndAssemble","withAutoFallbackForCollection","assembled","run","remote","writeThroughAssembled","refreshCollection","cache","listed","cachedBySeedUid","toCheck","meta","found","toAssemble","fresh","freshBySeedUid","unchanged","stored","MIN_UID_PREFIX_HEX_DIGITS","normalizeUidPrefix","hex","prefix","queryBySchema","skip","buildAssembleOptionsKey","uidPrefix","runAssemble","ds","lockKey","used","useQueryCache","getUnchangedCachedItems","requests","hits","getUnchangedCachedItem","pinOf","getSeed","trimmed","fetchSeedAndVersions","dependencies","assembleData","entry","getSeeds","givenByUid","given","optionsKeyFor","readFrom","useCache","toFetch","seedByUid","missing","queryBySchemaForMonth"],"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/config.ts","../src/cache/freeze.ts","../src/cache/MemoryCache.ts","../src/cache/CacheManager.ts","../src/cache/index.ts","../src/cache/changes.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 {\n BaseArweaveClient,\n isKnownArweaveGatewayHostname,\n readArweaveContentResponse,\n} 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\n/** Body goes through `transformArweaveContent` (`@seedprotocol/arweave`, `content/arweaveContent.ts`). */\nasync function fetchGatewayPayloadAsUtf8(url: string, transactionId: 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 { bytes } = await readArweaveContentResponse(res, { transactionId })\n if (bytes.byteLength > MAX_BODY_BYTES) return null\n const text = new TextDecoder('utf-8', { fatal: false }).decode(bytes)\n if (text.length === 0 || text.includes('\\0')) return null\n return text\n } catch {\n return null\n }\n}\n\n/** Upper bound on cached body text, in UTF-16 code units (~2 bytes each). */\nconst BODY_CACHE_MAX_CHARS = 32_000_000\n\n/**\n * Fetched bodies by Arweave transaction id, least recently used first. A transaction's data never\n * changes, so entries never go stale; they are only evicted for size. Failed fetches are not cached\n * (a new transaction can 404 until gateways have it).\n */\nconst bodyCache = new Map<string, string>()\nlet bodyCacheChars = 0\nconst bodiesInFlight = new Map<string, Promise<string | null>>()\n\n/** Clears the Arweave body cache. For tests. */\nexport function resetArweaveBodyCache(): void {\n bodyCache.clear()\n bodyCacheChars = 0\n bodiesInFlight.clear()\n}\n\nfunction cacheBody(txId: string, text: string): void {\n if (text.length > BODY_CACHE_MAX_CHARS) return\n bodyCache.set(txId, text)\n bodyCacheChars += text.length\n for (const [oldest, oldText] of bodyCache) {\n if (bodyCacheChars <= BODY_CACHE_MAX_CHARS) break\n bodyCache.delete(oldest)\n bodyCacheChars -= oldText.length\n }\n}\n\n/** Gateway body for a transaction URL: cached by transaction id, concurrent requests shared. */\nasync function fetchTransactionBody(url: string): Promise<string | null> {\n const txId = new URL(url.trim()).pathname.replace(/^\\//, '')\n const cached = bodyCache.get(txId)\n if (cached !== undefined) {\n // Most recently used goes last.\n bodyCache.delete(txId)\n bodyCache.set(txId, cached)\n return cached\n }\n const inFlight = bodiesInFlight.get(txId)\n if (inFlight) return inFlight\n\n const request = fetchGatewayPayloadAsUtf8(url, txId)\n .then((text) => {\n if (text !== null && bodiesInFlight.get(txId) === request) cacheBody(txId, text)\n return text\n })\n .finally(() => {\n if (bodiesInFlight.get(txId) === request) bodiesInFlight.delete(txId)\n })\n bodiesInFlight.set(txId, request)\n return request\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 fetchTransactionBody(value)\n}\n\n/** Bodies resolved at once, across all items. */\nconst HYDRATE_CONCURRENCY = 8\n\nasync function runWithConcurrency(\n tasks: Array<() => Promise<void>>,\n limit: number,\n): Promise<void> {\n let next = 0\n const worker = async (): Promise<void> => {\n while (next < tasks.length) {\n await tasks[next++]!()\n }\n }\n await Promise.all(Array.from({ length: Math.min(limit, tasks.length) }, worker))\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 * Up to HYDRATE_CONCURRENCY bodies are resolved at a time, across all items.\n */\nexport async function hydrateArweaveRichTextInItems(\n items: Record<string, unknown>[],\n options?: HydrateStorageOptions,\n): Promise<void> {\n const readStorageBody = options?.readStorageBody\n const tasks: Array<() => Promise<void>> = []\n\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 const v = item[key]\n if (typeof v !== 'string' || v.trim() === '') continue\n tasks.push(async () => {\n const text = await resolveHydratedBody(key, v, readStorageBody)\n if (text !== null) item[key] = text\n })\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 tasks.push(async () => {\n const text = await resolveHydratedBody(listKey, el, readStorageBody)\n if (text !== null) arr[i] = text\n })\n }\n }\n }\n }\n\n await runWithConcurrency(tasks, HYDRATE_CONCURRENCY)\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 (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 getSeedsByUidsFromEas,\n getAttestationChangesSince,\n getItemVersionsFromEas,\n getItemPropertiesFromEas,\n EasClient,\n withExcludeRevokedFilter,\n GET_SEEDS_LEAN,\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 [seed] = await getSeedsByUidsFromEas({ uids: [seedUid] })\n return (seed 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 listSeedsByUidPrefix(\n schemaName: string,\n uidPrefix: string,\n opts: { limit: number; skip: number },\n ): Promise<AttestationLike[]> {\n return (await getSeedsBySchemaName(schemaName, opts.limit, opts.skip, {\n uidPrefix,\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_LEAN, {\n where,\n take: 1000,\n skip: 0,\n })\n // Every seed matched `schemaName`; the lean query doesn't select it.\n return (itemSeeds ?? []).map((seed) => ({\n ...seed,\n schema: { schemaNames: [{ name: schemaName }] },\n })) 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(\n seedUids: string[],\n opts?: { includeRevoked?: boolean },\n ): Promise<AttestationLike[]> {\n if (seedUids.length === 0) return []\n // The query fields include `revoked`, so revoked versions come back marked.\n return (await getItemVersionsFromEas({\n seedUids,\n excludeRevoked: !opts?.includeRevoked,\n })) 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 return (await getSeedsByUidsFromEas({ uids })) as AttestationLike[]\n },\n\n async listChangesSince(opts) {\n return getAttestationChangesSince(opts)\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 decodeEasNumber,\n isNumericEasType,\n setSchemaUidForSchemaDefinition,\n pickLatestPropertyAttestationsByRefAndSchema,\n keepAttestationsFromRefAttester,\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, VersionPin } 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 /** Related seeds each seed's properties name (what its record depends on besides itself). */\n relatedSeedUidsBySeedUid: Map<string, 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 /** Requested seeds left out because every version is revoked; not fetched again as related. */\n droppedSeedUids: Set<string>\n /**\n * The seeds asked for, in order. Only these become records: a related seed is fetched to expand\n * relations into, even when it has the requested schema.\n */\n requestedSeedUids: Set<string>\n}\n\nfunction createAssembleContext(): AssembleContext {\n return {\n seedUidToModelType: new Map(),\n relatedSeedUids: new Set(),\n relatedSeedUidsBySeedUid: new Map(),\n versionUidToSeedUid: new Map(),\n assembledItems: new Map(),\n versionsBySeedUid: new Map(),\n latestVersionUidsBySeedUid: new Map(),\n droppedSeedUids: new Set(),\n requestedSeedUids: new Set(),\n }\n}\n\n/** Requested seeds still assembled (not dropped), in request order, with their items. */\nfunction requestedItems(ctx: AssembleContext): Array<[string, Record<string, unknown>]> {\n const items: Array<[string, Record<string, unknown>]> = []\n for (const seedUid of ctx.requestedSeedUids) {\n const item = ctx.assembledItems.get(seedUid)\n if (item) items.push([seedUid, item])\n }\n return items\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\nfunction addRelatedSeedUid(\n ctx: AssembleContext,\n property: AttestationLike,\n relatedSeedUid: string,\n): void {\n ctx.relatedSeedUids.add(relatedSeedUid)\n const seedUid = ctx.versionUidToSeedUid.get(property.refUID)\n if (!seedUid) return\n const related = ctx.relatedSeedUidsBySeedUid.get(seedUid) ?? new Set<string>()\n related.add(relatedSeedUid)\n ctx.relatedSeedUidsBySeedUid.set(seedUid, related)\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)) addRelatedSeedUid(ctx, property, value)\n })\n } else if (!relationValuesToExclude.includes(metadata.value as string)) {\n addRelatedSeedUid(ctx, property, 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 // ADR 0010: an integer value as its decimal string, not the indexer's `{ type: 'BigNumber', hex }`.\n const decimal = isNumericEasType(easType) ? decodeEasNumber(propertyValue) : undefined\n propertyValue = decimal ?? 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\n/** Pins that name a version or a time, by lowercase seed UID. */\nfunction activePins(pins: ReadonlyMap<string, VersionPin>): Map<string, VersionPin> {\n const active = new Map<string, VersionPin>()\n for (const [seedUid, pin] of pins) {\n if (pin.versionUid !== undefined || pin.asOf !== undefined) active.set(seedUid.toLowerCase(), pin)\n }\n return active\n}\n\n/** The seed's live version `pin` names (else its newest), if it was created by `pin.asOf`. */\nfunction pinnedVersion(\n versions: AttestationLike[],\n pin: VersionPin,\n): AttestationLike | undefined {\n const asOf = pin.asOf\n const candidates =\n asOf === undefined ? versions : versions.filter((v) => v.timeCreated <= asOf)\n if (pin.versionUid === undefined) {\n return [...candidates].sort((a, b) => b.timeCreated - a.timeCreated)[0]\n }\n const needle = pin.versionUid.toLowerCase()\n return candidates.find((v) => v.id.toLowerCase() === needle)\n}\n\nasync function processSeeds(\n ctx: AssembleContext,\n seeds: AttestationLike[],\n dataSource: QueryDataSource,\n opts: {\n dropSeedsWithOnlyRevokedVersions?: boolean\n /**\n * Versions already fetched with `getVersionsForSeeds(…, { includeRevoked: true })` for these\n * seeds (and possibly others, which are ignored), so the request isn't made again.\n */\n versions?: AttestationLike[]\n /** Versions to assemble instead of the latest, by lowercase seed UID (see VersionPin). */\n pins?: ReadonlyMap<string, VersionPin>\n } = {},\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 // Revoked versions come back too (marked), in the same request, only so a seed whose versions\n // were all revoked can be told from one that never had a version; they are never used below.\n const requested = new Set(seedUids)\n const fetchedVersions = opts.versions\n ? opts.versions.filter((v) => requested.has(v.refUID))\n : await dataSource.getVersionsForSeeds(seedUids, { includeRevoked: true })\n // Anyone can attest with any refUID: only the seed's attester's versions count.\n const allVersions = keepAttestationsFromRefAttester(fetchedVersions, seeds)\n const itemVersions = allVersions.filter((v) => v.revoked !== true)\n\n if (opts.dropSeedsWithOnlyRevokedVersions) {\n // Like the SDK (latest published version skips revoked ones): every version revoked means\n // no published version, so the seed is left out. A seed with no version at all is kept.\n const seedsWithLiveVersion = new Set(itemVersions.map((v) => v.refUID))\n for (const version of allVersions) {\n const seedUid = version.refUID\n if (seedsWithLiveVersion.has(seedUid) || !requested.has(seedUid)) continue\n ctx.assembledItems.delete(seedUid)\n ctx.seedUidToModelType.delete(seedUid)\n ctx.droppedSeedUids.add(seedUid)\n }\n }\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 // Each seed's assembled version: the pinned one, else the latest. A pinned seed without that\n // version (not the seed's, revoked, or created after `asOf`) is left out, like a seed whose\n // versions were all revoked.\n const latestVersionUids: string[] = []\n const asOfByVersionUid = new Map<string, number>()\n for (const seedUid of seedUids) {\n const pin = opts.pins?.get(seedUid.toLowerCase())\n if (!pin) continue\n const pinned = pinnedVersion(ctx.versionsBySeedUid.get(seedUid) ?? [], pin)\n if (!pinned) {\n ctx.assembledItems.delete(seedUid)\n ctx.seedUidToModelType.delete(seedUid)\n ctx.versionsBySeedUid.delete(seedUid)\n ctx.droppedSeedUids.add(seedUid)\n continue\n }\n latestVersionUids.push(pinned.id)\n ctx.latestVersionUidsBySeedUid.set(seedUid, pinned.id)\n if (pin.asOf !== undefined) asOfByVersionUid.set(pinned.id, pin.asOf)\n }\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 = keepAttestationsFromRefAttester(\n await dataSource.getPropertiesForVersionUids(latestVersionUids),\n itemVersions,\n ).filter((property) => {\n const asOf = asOfByVersionUid.get(property.refUID)\n return asOf === undefined || property.timeCreated <= asOf\n })\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): void {\n for (const [, item] of requestedItems(ctx)) {\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(ctx: AssembleContext, expandRelations: boolean): void {\n if (!expandRelations) return\n\n for (const [, item] of requestedItems(ctx)) {\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\n/** A record still being assembled (hydration fills in its data); read-only once returned. */\ntype AssembledRecord = Omit<SeedRecord, 'data'> & { data: Record<string, unknown> }\n\nfunction toSeedRecords(ctx: AssembleContext, schemaName?: string): AssembledRecord[] {\n return requestedItems(ctx).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: schemaName ?? ctx.seedUidToModelType.get(seedUid) ?? 'unknown',\n attester,\n timeCreated,\n versionUid,\n data: item,\n }\n })\n}\n\n/**\n * What an assembled record was built from, so a cache can tell when it changed: an attestation\n * created or revoked later that references one of `refUIDs` (a new or revoked Version of the seed\n * or of a seed it relates to, a property of one of their head Versions) or is one of `ids` (the\n * seed or a related seed, revoked).\n */\nexport type SeedDependencies = {\n refUIDs: string[]\n ids: string[]\n}\n\nfunction dependenciesOf(ctx: AssembleContext, seedUid: string): SeedDependencies {\n const seedUids = [seedUid, ...(ctx.relatedSeedUidsBySeedUid.get(seedUid) ?? [])]\n const headVersionUids = seedUids\n .map((uid) => ctx.latestVersionUidsBySeedUid.get(uid))\n .filter((uid): uid is string => !!uid)\n return { refUIDs: [...seedUids, ...headVersionUids], ids: seedUids }\n}\n\nexport type AssembleRequest = {\n /** The schema name every record gets. Default: each seed's own (its first schema name). */\n schemaName?: string\n /** Versions of the seeds already fetched with `includeRevoked: true` (see getSeed). */\n versions?: AttestationLike[]\n /**\n * Versions to assemble instead of the latest, by seed UID. Applies to `seeds` only: related\n * seeds are always assembled at their latest version.\n */\n pins?: ReadonlyMap<string, VersionPin>\n}\n\n/**\n * Like assembleSeeds, plus each record's dependencies by seedUid (see SeedDependencies).\n */\nexport async function assembleSeedsWithDependencies(\n schemaName: string,\n seeds: AttestationLike[],\n options?: AssembleOptions,\n dataSource: QueryDataSource = getRemoteQueryDataSource(),\n /** Versions of `seeds` already fetched with `includeRevoked: true` (see getSeed). */\n prefetched?: { versions?: AttestationLike[] },\n): Promise<{ records: SeedRecord[]; dependencies: Map<string, SeedDependencies> }> {\n return assembleSeedRecords(seeds, options, dataSource, {\n schemaName,\n versions: prefetched?.versions,\n })\n}\n\n/**\n * Records for `seeds`, in order, which may be of different schemas, with each record's\n * dependencies by seedUid. One set of requests for all of them: seeds and versions, properties,\n * related seeds and their versions, related properties, then storage bodies.\n */\nexport async function assembleSeedRecords(\n seeds: AttestationLike[],\n options: AssembleOptions | undefined,\n dataSource: QueryDataSource,\n request: AssembleRequest = {},\n): Promise<{ records: SeedRecord[]; dependencies: Map<string, SeedDependencies> }> {\n const expandRelations = options?.expandRelations !== false\n const hydrateStorage = options?.hydrateStorage !== false\n\n const ctx = createAssembleContext()\n for (const seed of seeds) if (seed) ctx.requestedSeedUids.add(seed.id)\n\n await processSeeds(ctx, seeds, dataSource, {\n dropSeedsWithOnlyRevokedVersions: true,\n versions: request.versions,\n pins: request.pins && activePins(request.pins),\n })\n\n const relatedSeedUidsArray = Array.from(ctx.relatedSeedUids).filter(\n (uid) => !ctx.assembledItems.has(uid) && !ctx.droppedSeedUids.has(uid),\n )\n if (relatedSeedUidsArray.length > 0) {\n // Their versions only need the UIDs, so they are fetched alongside the seeds. Versions of a\n // related seed that isn't returned (revoked, or not found) are ignored by processSeeds.\n const [relatedSeeds, relatedVersions] = await Promise.all([\n dataSource.getSeedsByUids(relatedSeedUidsArray),\n dataSource.getVersionsForSeeds(relatedSeedUidsArray, { includeRevoked: true }),\n ])\n await processSeeds(ctx, relatedSeeds, dataSource, { versions: relatedVersions })\n }\n\n resolveRelationPropertiesToUrls(ctx)\n expandRelationProperties(ctx, expandRelations)\n\n const records = toSeedRecords(ctx, request.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 const dependencies = new Map(\n records.map((record) => [record.seedUid, dependenciesOf(ctx, record.seedUid)]),\n )\n return { records, dependencies }\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 return (await assembleSeedsWithDependencies(schemaName, seeds, options, dataSource)).records\n}\n","import { decodeEasNumber, isNumericEasType } from '@seedprotocol/eas'\nimport { 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 // ADR 0010: an integer value as its decimal string, not the indexer's `{ type: 'BigNumber', hex }`.\n const decimal = isNumericEasType(easType) ? decodeEasNumber(propertyValue) : undefined\n propertyValue = decimal ?? 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 {\n keepAttestationsFromRefAttester,\n pickLatestPropertyAttestationsByRefAndSchema,\n} 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 // Anyone can attest with any refUID: only the seed's attester's versions, and each version's\n // attester's properties, count.\n const [seed, fetchedVersions] = await Promise.all([\n dataSource.getSeedByUid(seedUid),\n dataSource.getVersionsForSeed(seedUid),\n ])\n const itemVersions = keepAttestationsFromRefAttester(fetchedVersions, seed ? [seed] : [])\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 = keepAttestationsFromRefAttester(\n await dataSource.getPropertiesForVersionUids(versionUids),\n sortedVersions,\n )\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'\nimport type { GetSeedResult } from '../types.js'\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 from its records' ETags (in order), so it\n * changes whenever a record's content does.\n */\nexport function generateCollectionETag(\n schemaName: string,\n optionsKey: string,\n itemETags: string[],\n): string {\n return generateETag(`${schemaName}-${optionsKey}-${itemETags.join(',')}`)\n}\n\n/**\n * Generate an ETag for a single record from its content (a patch publish changes properties\n * without a new versionUid, so ids alone don't identify the content).\n */\nexport function generateItemETag(record: GetSeedResult, optionsKey: string): string {\n return generateETag(`${optionsKey}-${stableStringify(record)}`)\n}\n\n/**\n * JSON with object keys sorted: property order follows attestation order, which differs between\n * a seed assembled alone and in a batch, and must not change the ETag.\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(value, (_key, v: unknown) =>\n v && typeof v === 'object' && !Array.isArray(v)\n ? Object.fromEntries(\n Object.keys(v as Record<string, unknown>)\n .sort()\n .map((k) => [k, (v as Record<string, unknown>)[k]]),\n )\n : v,\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 *\n * Records are deep-frozen as they enter the memory cache unless NODE_ENV=production\n * (see {@link defaultFreezeRecords}).\n */\n/**\n * Cached records are handed to callers by reference, so a caller that mutates one corrupts the\n * cache. Outside production they are frozen when cached so such a write throws (in strict mode)\n * instead; production skips the walk.\n */\nexport function defaultFreezeRecords(): boolean {\n return env().NODE_ENV !== 'production'\n}\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 freezeRecords: defaultFreezeRecords(),\n }\n}\n","/**\n * Freezes `value` and everything reachable from it, children before parents, so a frozen object's\n * subtree is already frozen and is skipped (records share related-seed clones, and write-through\n * freezes the same nested objects more than once). Typed arrays can't be frozen and are left as is.\n */\nexport function deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== 'object' || Object.isFrozen(value)) return value\n if (ArrayBuffer.isView(value)) return value\n for (const child of Object.values(value)) deepFreeze(child)\n return Object.freeze(value)\n}\n","import type {\n CachedCollectionData,\n CachedItemData,\n QueryCacheConfig,\n} from './types.js'\nimport { defaultFreezeRecords } from './config.js'\nimport { deepFreeze } from './freeze.js'\n\n/**\n * In-memory collection + item cache with TTL and refresh locks.\n * Entries expire `ttl` seconds after their `lastUpdated` (their last full assembly).\n * Stored records are returned to callers by reference; with `freezeRecords` they are deep-frozen\n * on the way in so a caller can't mutate them silently.\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 collectionKey(schemaName: string, optionsKey: string): string {\n return `${schemaName}\\n${optionsKey}`\n }\n\n private itemKey(seedUid: string, optionsKey: string): string {\n return `${seedUid}:${optionsKey}`\n }\n\n private get freezeRecords(): boolean {\n return this.config.freezeRecords ?? defaultFreezeRecords()\n }\n\n private expired(lastUpdated: number): boolean {\n return Math.floor(Date.now() / 1000) - lastUpdated > this.config.ttl\n }\n\n getCollection(schemaName: string, optionsKey: string): CachedCollectionData | null {\n const key = this.collectionKey(schemaName, optionsKey)\n const cached = this.collectionCache.get(key)\n if (!cached) return null\n if (this.expired(cached.lastUpdated)) {\n this.collectionCache.delete(key)\n return null\n }\n return cached\n }\n\n setCollection(schemaName: string, optionsKey: string, data: CachedCollectionData): void {\n if (this.freezeRecords) for (const item of data.items) deepFreeze(item)\n this.collectionCache.set(this.collectionKey(schemaName, optionsKey), data)\n }\n\n getItem(seedUid: string, optionsKey: string): CachedItemData | null {\n const key = this.itemKey(seedUid, optionsKey)\n const cached = this.itemCache.get(key)\n if (!cached) return null\n if (this.expired(cached.lastUpdated)) {\n this.itemCache.delete(key)\n return null\n }\n return cached\n }\n\n setItem(data: CachedItemData): void {\n if (this.freezeRecords) deepFreeze(data.record)\n this.itemCache.set(this.itemKey(data.record.seedUid, data.optionsKey), data)\n }\n\n /** Every options variant of the schema's collection. */\n clearCollection(schemaName: string): void {\n for (const key of this.collectionCache.keys()) {\n if (key.startsWith(`${schemaName}\\n`)) this.collectionCache.delete(key)\n }\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 with the same key share one in-flight promise.\n */\n async withRefreshLock<T>(\n key: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n const existingLock = this.refreshLocks.get(key)\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(key)\n }\n })()\n\n this.refreshLocks.set(key, 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 { generateCollectionETag, generateItemETag } from './etag.js'\nimport { MemoryCache } from './MemoryCache.js'\nimport type {\n CachedCollectionData,\n CachedItemData,\n PersistentCache,\n QueryCacheConfig,\n QueryCacheStats,\n} from './types.js'\nimport type { GetSeedResult } 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 * Entries written before change tracking (or by another version) lack its bookkeeping and can't\n * be checked for changes, so they are treated as misses.\n */\nfunction isCurrentCollection(data: unknown): data is CachedCollectionData {\n const d = data as Partial<CachedCollectionData> | null\n return (\n !!d &&\n Array.isArray(d.items) &&\n typeof d.meta === 'object' &&\n d.meta !== null &&\n typeof d.checkedAt === 'number' &&\n Array.isArray(d.seenChangeKeys)\n )\n}\n\nfunction isCurrentItem(data: unknown): data is CachedItemData {\n const d = data as Partial<CachedItemData> | null\n return (\n !!d &&\n !!d.record &&\n !!d.dependencies &&\n typeof d.checkedAt === 'number' &&\n Array.isArray(d.seenChangeKeys)\n )\n}\n\n/**\n * Unified query cache: memory, with optional persistent (disk) layer.\n * Collections are kept per schema and assemble-options key.\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 optionsKey: string,\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n const cached = this.memoryCache.getCollection(schemaName, optionsKey)\n if (cached) {\n this.stats.hits++\n return cached\n }\n\n const persisted = (await this.persistent?.getCollection(schemaName, optionsKey)) ?? null\n if (isCurrentCollection(persisted)) {\n this.memoryCache.setCollection(schemaName, optionsKey, persisted)\n this.stats.hits++\n return persisted\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 /** Stores a collection; its ETag is derived from the records' content. */\n async setCollection(\n schemaName: string,\n optionsKey: string,\n data: Omit<CachedCollectionData, 'etag'>,\n ): Promise<CachedCollectionData | null> {\n if (!this.config.enabled) return null\n\n try {\n const items = data.items.map((r) => ({ ...r, data: { ...r.data } }))\n const etag = generateCollectionETag(\n schemaName,\n optionsKey,\n items.map((r) => generateItemETag(r, optionsKey)),\n )\n const cached: CachedCollectionData = { ...data, items, etag }\n this.memoryCache.setCollection(schemaName, optionsKey, cached)\n await this.persistent?.setCollection(schemaName, optionsKey, 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 const cached = this.memoryCache.getItem(seedUid, optionsKey)\n if (cached) {\n this.stats.hits++\n return cached\n }\n\n const persisted = (await this.persistent?.getItem(seedUid, optionsKey)) ?? null\n if (isCurrentItem(persisted)) {\n this.memoryCache.setItem(persisted)\n this.stats.hits++\n return persisted\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 /** Stores an item; its ETag is derived from the record's content. */\n async setItem(\n data: Omit<CachedItemData, 'etag'>,\n ): Promise<CachedItemData | null> {\n if (!this.config.enabled) return null\n\n try {\n const record: GetSeedResult = {\n ...data.record,\n data: { ...data.record.data },\n ...(data.record.changelog && { changelog: [...data.record.changelog] }),\n }\n const cached: CachedItemData = {\n ...data,\n record,\n etag: generateItemETag(record, data.optionsKey),\n }\n this.memoryCache.setItem(cached)\n await this.persistent?.setItem(cached)\n return cached\n } catch (error) {\n console.error(\n `Error setting query item cache for ${data.record.seedUid}:`,\n error,\n )\n this.stats.errors++\n return null\n }\n }\n\n async writeThroughItems(items: Array<Omit<CachedItemData, 'etag'>>): Promise<void> {\n if (!this.config.enabled) return\n for (const item of items) {\n await this.setItem(item)\n }\n }\n\n async clearItem(seedUid: string, optionsKey: string): Promise<void> {\n this.memoryCache.clearItem(seedUid, optionsKey)\n await this.persistent?.clearItem(seedUid, optionsKey)\n }\n\n /** Every options variant of the schema's collection. */\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 key: string,\n fn: () => Promise<T>,\n ): Promise<T> {\n return this.memoryCache.withRefreshLock(key, fn)\n }\n\n /** Counts a cache hit that was checked against changes and refreshed in part. */\n recordRefresh(): void {\n this.stats.refreshes++\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 { 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 { SeedDependencies } from '../assembleSeeds.js'\nimport type { QueryDataSource } from '../source/types.js'\nimport type { AttestationChange } from '../types.js'\nimport type { ChangeCheck } from './types.js'\n\n/**\n * Each change check looks back this far before the previous check started, so an attestation\n * the indexer lists late, or a clock between here and the chain that is off, is still seen.\n * Changes inside the overlap that were already applied are skipped by their key.\n */\nexport const CHANGE_CHECK_OVERLAP_SECONDS = 600\n\nexport function nowSeconds(): number {\n return Math.floor(Date.now() / 1000)\n}\n\n/** `checkedAt` for a check that started at `startedAt`. */\nexport function checkedAtFor(startedAt: number): number {\n return startedAt - CHANGE_CHECK_OVERLAP_SECONDS\n}\n\n/**\n * True when a check found nothing but its window has grown past twice the overlap, so it is worth\n * storing the new `checkedAt` to keep later requests small. (Storing it is otherwise not needed:\n * an unchanged entry's next check sees only changes it has already seen.)\n */\nexport function checkWindowAged(check: ChangeCheck, startedAt: number): boolean {\n return checkedAtFor(startedAt) - check.checkedAt > CHANGE_CHECK_OVERLAP_SECONDS\n}\n\nconst changeKey = (change: AttestationChange): string => `${change.id}:${change.revocationTime}`\n\n/**\n * Which of the cached seeds changed since `check.checkedAt`: a new or revoked Version of a seed\n * it depends on, a new or revoked property on one of their head Versions, or one of those seeds\n * revoked. Returns null when the data source can't list changes (treat everything as changed).\n */\nexport async function findChangedSeeds(\n dataSource: QueryDataSource,\n dependenciesBySeedUid: Map<string, SeedDependencies>,\n check: ChangeCheck,\n): Promise<{ changed: Set<string>; seenChangeKeys: string[] } | null> {\n if (!dataSource.listChangesSince) return null\n if (dependenciesBySeedUid.size === 0) {\n return { changed: new Set(), seenChangeKeys: check.seenChangeKeys }\n }\n\n const seedUidsByRef = new Map<string, string[]>()\n const seedUidsById = new Map<string, string[]>()\n const index = (map: Map<string, string[]>, uid: string, seedUid: string) => {\n const seedUids = map.get(uid)\n if (seedUids) seedUids.push(seedUid)\n else map.set(uid, [seedUid])\n }\n for (const [seedUid, deps] of dependenciesBySeedUid) {\n for (const uid of deps.refUIDs) index(seedUidsByRef, uid, seedUid)\n for (const uid of deps.ids) index(seedUidsById, uid, seedUid)\n }\n\n const changes = await dataSource.listChangesSince({\n refUIDs: [...seedUidsByRef.keys()],\n ids: [...seedUidsById.keys()],\n since: check.checkedAt,\n })\n\n const seen = new Set(check.seenChangeKeys)\n const changed = new Set<string>()\n for (const change of changes) {\n if (seen.has(changeKey(change))) continue\n for (const seedUid of seedUidsByRef.get(change.refUID) ?? []) changed.add(seedUid)\n for (const seedUid of seedUidsById.get(change.id) ?? []) changed.add(seedUid)\n }\n return { changed, seenChangeKeys: changes.map(changeKey) }\n}\n\n/** A cached item to check: what it depends on, and its own check window. */\nexport type ItemChangeCheck = ChangeCheck & { dependencies: SeedDependencies }\n\n/**\n * Like findChangedSeeds for items checked at different times: one request from the oldest\n * `checkedAt`, then each item counts only changes after its own `checkedAt` that it hasn't seen.\n * `seenChangeKeys` is per item. Returns null when the data source can't list changes.\n */\nexport async function findChangedItems(\n dataSource: QueryDataSource,\n checks: Map<string, ItemChangeCheck>,\n): Promise<{ changed: Set<string>; seenChangeKeys: Map<string, string[]> } | null> {\n if (!dataSource.listChangesSince) return null\n const changed = new Set<string>()\n const seenChangeKeys = new Map<string, string[]>()\n if (checks.size === 0) return { changed, seenChangeKeys }\n\n const refUIDs = new Set<string>()\n const ids = new Set<string>()\n let since = Infinity\n for (const check of checks.values()) {\n for (const uid of check.dependencies.refUIDs) refUIDs.add(uid)\n for (const uid of check.dependencies.ids) ids.add(uid)\n since = Math.min(since, check.checkedAt)\n }\n const changes = await dataSource.listChangesSince({\n refUIDs: [...refUIDs],\n ids: [...ids],\n since,\n })\n\n for (const [seedUid, check] of checks) {\n const refs = new Set(check.dependencies.refUIDs)\n const own = new Set(check.dependencies.ids)\n const seen = new Set(check.seenChangeKeys)\n const keys: string[] = []\n for (const change of changes) {\n if (change.timeCreated <= check.checkedAt && change.revocationTime <= check.checkedAt) continue\n if (!refs.has(change.refUID) && !own.has(change.id)) continue\n keys.push(changeKey(change))\n if (!seen.has(changeKey(change))) changed.add(seedUid)\n }\n seenChangeKeys.set(seedUid, keys)\n }\n return { changed, seenChangeKeys }\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 {\n assembleSeedRecords,\n assembleSeedsWithDependencies,\n type SeedDependencies,\n} from './assembleSeeds.js'\nimport { assembleSeedChangelog } from './assembleChangelog.js'\nimport {\n buildAssembleOptionsKey,\n getQueryCacheManager,\n} from './cache/index.js'\nimport {\n checkedAtFor,\n checkWindowAged,\n findChangedItems,\n findChangedSeeds,\n nowSeconds,\n type ItemChangeCheck,\n} from './cache/changes.js'\nimport type { CachedItemData, CachedRecordMeta } from './cache/types.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 GetSeedsOptions,\n QueryBySchemaOptions,\n QueryBySchemaResult,\n AttestationLike,\n SeedRecord,\n VersionPin,\n} from './types.js'\n\nconst NO_DEPENDENCIES: SeedDependencies = { refUIDs: [], ids: [] }\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\ntype Assembled = {\n records: SeedRecord[]\n dependencies: Map<string, SeedDependencies>\n}\n\nasync function fetchAndAssemble(\n schemaName: string,\n limit: number,\n skip: number,\n options: AssembleOptions | undefined,\n dataSource: QueryDataSource,\n): Promise<Assembled> {\n const seeds = await dataSource.listSeedsBySchemaName(schemaName, {\n limit,\n skip,\n })\n return assembleSeedsWithDependencies(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<Assembled>,\n): Promise<{ assembled: Assembled; dataSource: QueryDataSource; useQueryCache: boolean }> {\n const assembled = await run(dataSource)\n if (mode !== 'auto' || dataSource.kind !== 'local') {\n return {\n assembled,\n dataSource,\n useQueryCache: dataSource.kind === 'remote',\n }\n }\n if (assembled.records.length > 0) {\n return { assembled, dataSource, useQueryCache: false }\n }\n const remote = getRemoteQueryDataSource()\n return { assembled: await run(remote), dataSource: remote, useQueryCache: true }\n}\n\n/** Item-cache write-through for records assembled by a read that started at `startedAt`. */\nasync function writeThroughAssembled(\n assembled: Assembled,\n optionsKey: string,\n startedAt: number,\n seenChangeKeys: string[] = [],\n): Promise<void> {\n await getQueryCacheManager().writeThroughItems(\n assembled.records.map((record) => ({\n record,\n optionsKey,\n dependencies: assembled.dependencies.get(record.seedUid) ?? NO_DEPENDENCIES,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys,\n lastUpdated: startedAt,\n })),\n )\n}\n\n/**\n * The schema's first `limit` seeds, newest first, from the collection cache where they haven't\n * changed. The seed list itself is always fetched (it's cheap, and shows new and revoked seeds);\n * cached seeds are checked for changes in one request (see findChangedSeeds), and only new or\n * changed seeds are assembled. The TTL counts from the last full assembly.\n */\nasync function refreshCollection(\n schemaName: string,\n limit: number,\n options: QueryBySchemaOptions | undefined,\n optionsKey: string,\n dataSource: QueryDataSource,\n): Promise<QueryBySchemaResult> {\n const cache = getQueryCacheManager()\n const startedAt = nowSeconds()\n const cached = await cache.getCollection(schemaName, optionsKey)\n const listed = await dataSource.listSeedsBySchemaName(schemaName, { limit, skip: 0 })\n\n const cachedBySeedUid = new Map(cached?.items.map((item) => [item.seedUid, item]) ?? [])\n let changed = new Set<string>()\n let seenChangeKeys: string[] = []\n if (cached) {\n const toCheck = new Map<string, SeedDependencies>()\n for (const seed of listed) {\n const meta = cached.meta[seed.id]\n if (cachedBySeedUid.has(seed.id)) toCheck.set(seed.id, meta?.dependencies ?? NO_DEPENDENCIES)\n }\n const found = await findChangedSeeds(dataSource, toCheck, cached)\n if (found) {\n changed = found.changed\n seenChangeKeys = found.seenChangeKeys\n } else {\n changed = new Set(toCheck.keys())\n }\n }\n\n const toAssemble = listed.filter((seed) => !cachedBySeedUid.has(seed.id) || changed.has(seed.id))\n const fresh =\n toAssemble.length > 0\n ? await assembleSeedsWithDependencies(schemaName, toAssemble, options, dataSource)\n : { records: [], dependencies: new Map<string, SeedDependencies>() } satisfies Assembled\n const freshBySeedUid = new Map(fresh.records.map((record) => [record.seedUid, record]))\n\n // In list order. A changed seed that no longer assembles (every version revoked) drops out,\n // as do cached seeds no longer listed (revoked, or pushed past `limit`).\n const items: SeedRecord[] = []\n const meta: Record<string, CachedRecordMeta> = {}\n for (const seed of listed) {\n const record = freshBySeedUid.get(seed.id)\n if (record) {\n items.push(record)\n meta[seed.id] = {\n dependencies: fresh.dependencies.get(seed.id) ?? NO_DEPENDENCIES,\n builtAt: startedAt,\n }\n } else if (cached && !changed.has(seed.id) && cachedBySeedUid.has(seed.id)) {\n items.push(cachedBySeedUid.get(seed.id)!)\n meta[seed.id] = cached.meta[seed.id] ?? { dependencies: NO_DEPENDENCIES, builtAt: startedAt }\n }\n }\n\n const unchanged =\n !!cached &&\n fresh.records.length === 0 &&\n items.length === cached.items.length &&\n items.every((item, i) => item === cached.items[i])\n if (cached && unchanged && !checkWindowAged(cached, startedAt)) {\n return { items, limit, skip: 0, etag: cached.etag }\n }\n if (cached) cache.recordRefresh()\n\n const stored = await cache.setCollection(schemaName, optionsKey, {\n items,\n meta,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys,\n lastUpdated: cached?.lastUpdated ?? startedAt,\n })\n await writeThroughAssembled(fresh, optionsKey, startedAt, seenChangeKeys)\n // The cached records (frozen outside production), so a fresh result behaves like a cache hit.\n return { items: stored ? [...stored.items] : items, limit, skip: 0, etag: stored?.etag }\n}\n\n/** Hex digits a uid prefix needs, so a stray short value can't list most of a schema. */\nconst MIN_UID_PREFIX_HEX_DIGITS = 4\n\n/**\n * `0x` + lowercase hex for a seed UID prefix given with or without `0x`, in any case (EAS indexes\n * UIDs lowercase and matches prefixes case-sensitively). Null when it isn't 4–64 hex digits.\n */\nexport function normalizeUidPrefix(prefix: string): string | null {\n const hex = prefix.trim().toLowerCase().replace(/^0x/, '')\n if (hex.length < MIN_UID_PREFIX_HEX_DIGITS || hex.length > 64) return null\n if (!/^[0-9a-f]+$/.test(hex)) return null\n return `0x${hex}`\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 let uidPrefix: string | null = null\n if (options?.uidPrefix !== undefined) {\n uidPrefix = normalizeUidPrefix(options.uidPrefix)\n if (!uidPrefix) return { items: [], limit, skip }\n }\n\n const runAssemble = async (ds: QueryDataSource): Promise<Assembled> => {\n if (!uidPrefix) return fetchAndAssemble(schemaName, limit, skip, options, ds)\n const seeds = await ds.listSeedsByUidPrefix(schemaName, uidPrefix, { limit, skip })\n return assembleSeedsWithDependencies(schemaName, seeds, options, ds)\n }\n\n // Collection cache only for remote + skip=0 working set (a uid-prefix match isn't one)\n if (\n !uidPrefix &&\n shouldUseCache(options, resolved.useQueryCache) &&\n skip === 0 &&\n resolved.dataSource.kind === 'remote'\n ) {\n const lockKey = `${schemaName}\\n${optionsKey}\\n${limit}`\n return getQueryCacheManager().withRefreshLock(lockKey, () =>\n refreshCollection(schemaName, limit, options, optionsKey, resolved.dataSource),\n )\n }\n\n const startedAt = nowSeconds()\n const {\n assembled,\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 writeThroughAssembled(assembled, optionsKey, startedAt)\n }\n return { items: assembled.records, limit, skip }\n}\n\n/**\n * Cached items, by seedUid, for the seeds whose dependencies haven't changed since each was last\n * checked (one change request for all; see findChangedItems). Changed items are dropped so the\n * caller assembles them again.\n */\nasync function getUnchangedCachedItems(\n requests: Array<{ seedUid: string; optionsKey: string }>,\n dataSource: QueryDataSource,\n): Promise<Map<string, GetSeedResult>> {\n const cache = getQueryCacheManager()\n const cachedBySeedUid = new Map<string, CachedItemData>()\n await Promise.all(\n requests.map(async ({ seedUid, optionsKey }) => {\n const cached = await cache.getItem(seedUid, optionsKey)\n if (cached) cachedBySeedUid.set(seedUid, cached)\n }),\n )\n const hits = new Map<string, GetSeedResult>()\n if (cachedBySeedUid.size === 0) return hits\n\n const startedAt = nowSeconds()\n const checks = new Map<string, ItemChangeCheck>()\n for (const [seedUid, cached] of cachedBySeedUid) checks.set(seedUid, cached)\n const found = await findChangedItems(dataSource, checks)\n for (const [seedUid, cached] of cachedBySeedUid) {\n if (!found || found.changed.has(seedUid)) {\n await cache.clearItem(seedUid, cached.optionsKey)\n continue\n }\n if (checkWindowAged(cached, startedAt)) {\n await cache.setItem({\n ...cached,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys: found.seenChangeKeys.get(seedUid) ?? [],\n })\n }\n hits.set(seedUid, cached.record)\n }\n return hits\n}\n\nasync function getUnchangedCachedItem(\n seedUid: string,\n optionsKey: string,\n dataSource: QueryDataSource,\n): Promise<GetSeedResult | null> {\n const hits = await getUnchangedCachedItems([{ seedUid, optionsKey }], dataSource)\n return hits.get(seedUid) ?? null\n}\n\n/** The pin in `options`, if it names a version or a time. */\nfunction pinOf(options: VersionPin | undefined): VersionPin | undefined {\n if (options?.versionUid === undefined && options?.asOf === undefined) return undefined\n return { versionUid: options.versionUid, asOf: options.asOf }\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 getUnchangedCachedItem(trimmed, optionsKey, dataSource)\n if (cached) return cached\n }\n\n // The seed's versions only need its UID, so they are fetched alongside the seed (assembly\n // would otherwise ask for them after it).\n const fetchSeedAndVersions = (ds: QueryDataSource) =>\n Promise.all([\n ds.getSeedByUid(trimmed),\n ds.getVersionsForSeeds([trimmed], { includeRevoked: true }),\n ])\n\n const startedAt = nowSeconds()\n let [seed, versions] = await fetchSeedAndVersions(dataSource)\n\n // auto: local miss → remote\n if (!seed && mode === 'auto' && dataSource.kind === 'local') {\n dataSource = getRemoteQueryDataSource()\n allowCache = true\n if (shouldUseCache(options, allowCache)) {\n const cached = await getUnchangedCachedItem(trimmed, optionsKey, dataSource)\n if (cached) return cached\n }\n ;[seed, versions] = await fetchSeedAndVersions(dataSource)\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 let dependencies: SeedDependencies = { refUIDs: [trimmed], ids: [trimmed] }\n\n const pin = pinOf(options)\n const assembleData = async (): Promise<SeedRecord | null> => {\n const assembled = await assembleSeedRecords([seed], options, dataSource, {\n schemaName,\n versions,\n pins: pin && new Map([[trimmed, pin]]),\n })\n const record = assembled.records[0]\n if (record) dependencies = assembled.dependencies.get(record.seedUid) ?? dependencies\n return record ?? null\n }\n\n if (!wantsChangelog(include)) {\n result = await assembleData()\n } else {\n const { latestVersionUid, changelog } = await assembleSeedChangelog(\n trimmed,\n options,\n dataSource,\n )\n\n if (wantsData(include)) {\n const record = await assembleData()\n result = record ? { ...record, changelog } : null\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 if (latestVersionUid) dependencies.refUIDs.push(latestVersionUid)\n }\n // Property changes on any version in the changelog change it.\n for (const entry of changelog) dependencies.refUIDs.push(entry.versionUid)\n dependencies = {\n refUIDs: [...new Set(dependencies.refUIDs)],\n ids: dependencies.ids,\n }\n }\n\n if (\n result &&\n shouldUseCache(options, allowCache) &&\n dataSource.kind === 'remote'\n ) {\n const stored = await getQueryCacheManager().setItem({\n record: result,\n optionsKey,\n dependencies,\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys: [],\n lastUpdated: startedAt,\n })\n // The cached record (frozen outside production), so a fresh result behaves like a cache hit.\n if (stored) result = stored.record\n }\n\n return result\n}\n\n/**\n * Many seeds, of any schemas, keyed by UID as given (first spelling of each, in order). Seeds\n * not found, revoked, or without their pinned version are left out. Uncached seeds are\n * assembled together, in one set of requests (see assembleSeedRecords), and cached ones are\n * checked for changes in one request; records are shared with `getSeed` (same item cache).\n * A seed can be read at one version per call.\n */\nexport async function getSeeds(\n seedUids: readonly string[],\n options?: GetSeedsOptions,\n): Promise<Map<string, SeedRecord>> {\n await initializeQueryPlatform()\n\n // Read lowercase (EAS indexes UIDs lowercase and matches them case-sensitively); keyed as given.\n const givenByUid = new Map<string, string>()\n for (const given of seedUids) {\n if (typeof given !== 'string' || given.trim() === '') continue\n const uid = given.trim().toLowerCase()\n if (!givenByUid.has(uid)) givenByUid.set(uid, given.trim())\n }\n const requested = [...givenByUid.keys()]\n if (requested.length === 0) return new Map()\n\n const pins = new Map<string, VersionPin>()\n for (const [uid, pin] of options?.pins ?? []) {\n const active = pinOf(pin)\n if (active) pins.set(uid.trim().toLowerCase(), active)\n }\n const optionsKeyFor = (seedUid: string) =>\n buildAssembleOptionsKey({ ...options, ...pins.get(seedUid) })\n\n const mode = normalizeSourceMode(options?.source)\n const resolved = resolveQuerySource(mode)\n const found = new Map<string, SeedRecord>()\n\n /** Reads `uids` from `dataSource` into `found`; returns the ones whose seed it doesn't have. */\n const readFrom = async (\n dataSource: QueryDataSource,\n allowCache: boolean,\n uids: string[],\n ): Promise<string[]> => {\n const useCache = shouldUseCache(options, allowCache) && dataSource.kind === 'remote'\n let toFetch = uids\n if (useCache) {\n const hits = await getUnchangedCachedItems(\n uids.map((seedUid) => ({ seedUid, optionsKey: optionsKeyFor(seedUid) })),\n dataSource,\n )\n for (const [seedUid, record] of hits) found.set(seedUid, record)\n toFetch = uids.filter((uid) => !hits.has(uid))\n }\n if (toFetch.length === 0) return []\n\n const startedAt = nowSeconds()\n const [seeds, versions] = await Promise.all([\n dataSource.getSeedsByUids(toFetch),\n dataSource.getVersionsForSeeds(toFetch, { includeRevoked: true }),\n ])\n const seedByUid = new Map(seeds.map((seed) => [seed.id.toLowerCase(), seed]))\n const missing = toFetch.filter((uid) => !seedByUid.has(uid))\n // Like getSeed: a seed without a schema name isn't assembled.\n const toAssemble = toFetch\n .map((uid) => seedByUid.get(uid))\n .filter((seed): seed is AttestationLike => !!seed?.schema?.schemaNames?.[0]?.name)\n\n const assembled = await assembleSeedRecords(toAssemble, options, dataSource, {\n versions,\n pins,\n })\n for (const record of assembled.records) {\n let result: SeedRecord = record\n if (useCache) {\n const stored = await getQueryCacheManager().setItem({\n record,\n optionsKey: optionsKeyFor(record.seedUid.toLowerCase()),\n dependencies: assembled.dependencies.get(record.seedUid) ?? {\n refUIDs: [record.seedUid],\n ids: [record.seedUid],\n },\n checkedAt: checkedAtFor(startedAt),\n seenChangeKeys: [],\n lastUpdated: startedAt,\n })\n // The cached record (frozen outside production), so a fresh result behaves like a cache hit.\n if (stored) result = stored.record\n }\n found.set(record.seedUid.toLowerCase(), result)\n }\n return missing\n }\n\n const missing = await readFrom(resolved.dataSource, resolved.useQueryCache, requested)\n // auto: seeds the local source doesn't have → remote\n if (missing.length > 0 && mode === 'auto' && resolved.dataSource.kind === 'local') {\n await readFrom(getRemoteQueryDataSource(), true, missing)\n }\n\n const result = new Map<string, SeedRecord>()\n for (const [uid, given] of givenByUid) {\n const record = found.get(uid)\n if (record) result.set(given, record)\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 assembleSeedsWithDependencies(schemaName, seeds, options, ds)\n }\n\n const startedAt = nowSeconds()\n const { assembled, dataSource: used, useQueryCache } =\n await withAutoFallbackForCollection(mode, resolved.dataSource, run)\n\n if (shouldUseCache(options, useQueryCache) && used.kind === 'remote') {\n await writeThroughAssembled(assembled, buildAssembleOptionsKey(options), startedAt)\n }\n\n return assembled.records\n}\n"],"mappings":";;;;;;;AAKA,SAAgBG,EAA4B,GAA+B;CACzE,OAAO,WAAWC,EAAkB,QAAQ,EAAE,GAAGC;AACnD;;;ACJA,IAAMC,KAA0B;AAMhC,SAAgBC,EAA8B,GAA6B;CACzE,IAAMC,IAAQF,GAAwB,KAAKG,CAAW;CACtD,IAAID,GAAO;EACT,IAAME,IAAeF,EAAM;EAC3B,IAAIE,GAAc,OAAOR,EAAUQ,CAAY;CACjD;CACA,IAAID,EAAY,SAAS,MAAM,GAAG;EAChC,IAAME,IAAOF,EAAY,MAAM,GAAG,EAAE,GAC9BG,IAAWD,EAAK,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;EAC/C,IAAIC,EAAS,UAAU,GAAG;GACxB,IAAMC,IAAmBD,EAAS;GAClC,OAAOC,EAAiB,SAAS,GAAG,IAAIA,IAAmBX,EAAUW,CAAgB;EACvF;EACA,OAAOX,EAAUS,CAAI;CACvB;CACA,OAAOF;AACT;AAMA,SAAgBK,GACd,GACA,GACM;CACN,KAAK,IAAMC,KAAK,OAAO,KAAKC,CAAI,GAC9B,AAAID,MAAME,KACNV,EAA8BQ,CAAC,MAAME,KACvC,OAAOD,EAAKD;AAGlB;AAGA,SAAgBG,EAAyB,GAAyB;CAEhE,IADI,MAAM,QAAQC,CAAK,KACnB,OAAOA,KAAU,UAAU,OAAOA;CACtC,IAAMC,IAAID,EAAM,KAAK;CACrB,IAAI,CAACC,EAAE,WAAW,GAAG,GAAG,OAAOD;CAC/B,IAAI;EACF,IAAME,IAAS,KAAK,MAAMD,CAAC;EAC3B,IAAI,MAAM,QAAQC,CAAM,GAAG,OAAOA;CACpC,QAAQ,CAER;CACA,OAAOF;AACT;;;AClDA,SAAgBG,EAAqB,GAAsC;CACzE,IAAMC,IAAQC,EAAM,wBAAwBA,EAAM;CAGlD,IAAID,KAAQ,OAAOA,KAAS,YAAYA,EAAK,KAAK,GAChD,IAAI;EACF,EAAM,aAAapB,EAA4BoB,EAAK,KAAK,CAAC;CAC5D,QAAQ,CAER;AAEJ;AAGA,IAAaE,KAA8BH,GCnB9BI,oBAA4B,IAAI,IAAI;CAAC;CAAQ;CAAQ;AAAM,CAAC,GAG5DC,KAAiCD,GAGxCE,KAAmB,2BACnBC,KAAkB;AAUxB,SAASC,EAAmB,GAA4B;CACtD,OAAOC,EAAW,KAAK,CAAC,CAAC,YAAY;AACvC;AAEA,SAAgBC,EAAwB,GAA6B;CACnE,OAAON,EAA0B,IAAII,EAAmBC,CAAU,CAAC;AACrE;AAGA,IAAaE,KAA8BD;AAG3C,SAAgBE,GAAsB,GAA4B;CAChE,IAAMC,IAAIL,EAAmBC,CAAU;CAIvC,OAHII,MAAM,SAAe,IACrBA,MAAM,SAAe,IACrBA,MAAM,SAAe,IAClB;AACT;AAGA,IAAaC,KAA4BF;AAEzC,SAAgBG,EACd,GACgC;CAChC,IAAMC,IAAMtB,EAAKY;CACjB,IAAoB,OAAOU,KAAQ,YAA/BA,KAA2C,CAAC,MAAM,QAAQA,CAAG,GAC/D,OAAOA;AAGX;AAGA,IAAaC,KAA4BF;AAEzC,SAAgBG,EACd,GACsC;CACtC,IAAMF,IAAMtB,EAAKa;CACjB,IAAoB,OAAOS,KAAQ,YAA/BA,KAA2C,CAAC,MAAM,QAAQA,CAAG,GAC/D,OAAOA;AAGX;AAGA,IAAaG,KAAkCD;AAE/C,SAAgBE,EACd,GACA,GACA,GACM;CACN,IAAMC,IAAab,EAAmBC,CAAU,GAC5Ca,IAAMP,EAAsBrB,CAAI;CAKpC,AAJK4B,MACH,IAAM,CAAC,GACP,EAAKhB,MAAoBgB,IAE3B,EAAIC,KAAYF;AAClB;AAGA,IAAaG,KAA2BJ;AAExC,SAAgBK,GACd,GACA,GACA,GACM;CACN,IAAIH,IAAMJ,EAA4BxB,CAAI;CAK1C,AAJK4B,MACH,IAAM,CAAC,GACP,EAAKf,MAAmBe,IAE1B,EAAII,KAAaC,EAAO,IAAInB,CAAkB;AAChD;AAGA,IAAaoB,KAAkCH,ICtFzCI,KAAiB;CAAC;CAAQ;CAAQ;CAAQ;CAAQ;CAAW;AAAS,GAGtEC,KAAiB;AAcvB,SAAgBC,GAA+B,GAAsB;CACnE,IAAMjC,IAAIkB,EAAI,KAAK;CACnB,IAAI,CAAClB,EAAE,WAAW,SAAS,KAAK,CAACA,EAAE,WAAW,UAAU,GAAG,OAAO;CAClE,IAAI;EACF,IAAMkC,IAAI,IAAI,IAAIlC,CAAC,GACbmC,IAAOD,EAAE,SAAS,YAAY;EAEpC,IAAIC,MADanD,EAAkB,QAAQ,CAAC,CAAC,YAChC,KAAY,CAACoD,EAA8BD,CAAI,GAAG,OAAO;EACtE,IAAM3C,IAAW0C,EAAE,SAAS,QAAQ,OAAO,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;EACxE,IAAI1C,EAAS,WAAW,GAAG,OAAO;EAClC,IAAM6C,IAAK7C,EAAS;EACpB,OAAO,sBAAsB,KAAK6C,CAAE;CACtC,QAAQ;EACN,OAAO;CACT;AACF;AAGA,eAAeC,GAA0B,GAAa,GAA+C;CACnG,IAAI;EACF,IAAMC,IAAM,MAAM,MAAMC,GAAK;GAC3B,SAAS,EAAE,QAAQ,8DAA8D;GACjF,QAAQ,YAAY,QAAQ,IAAM;EACpC,CAAC;EACD,IAAI,CAACD,EAAI,IAAI,OAAO;EACpB,IAAME,IAAKF,EAAI,QAAQ,IAAI,cAAc,KAAK;EAC9C,IAAI,0BAA0B,KAAKE,CAAE,GAAG,OAAO;EAC/C,IAAM,EAAE,aAAU,MAAMC,EAA2BH,GAAK,EAAE,iBAAc,CAAC;EACzE,IAAII,EAAM,aAAaX,IAAgB,OAAO;EAC9C,IAAMY,IAAO,IAAI,YAAY,SAAS,EAAE,OAAO,GAAM,CAAC,CAAC,CAAC,OAAOD,CAAK;EAEpE,OADIC,EAAK,WAAW,KAAKA,EAAK,SAAS,IAAI,IAAU,OAC9CA;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAGA,IAAMC,KAAuB,MAOvBC,oBAAY,IAAI,IAAoB,GACtCC,IAAiB,GACfC,oBAAiB,IAAI,IAAoC;AAG/D,SAAgBC,KAA8B;CAG5C,AAFAH,EAAU,MAAM,GAChB,IAAiB,GACjBE,EAAe,MAAM;AACvB;AAEA,SAASE,GAAU,GAAc,GAAoB;CACnD,IAAI,IAAK,SAASL,KAClB;EACA,AADAC,EAAU,IAAI3C,GAAMyC,CAAI,GACxB,KAAkBA,EAAK;EACvB,KAAK,IAAM,CAACO,GAAQC,MAAYN,GAAW;GACzC,IAAIC,KAAkBF,IAAsB;GAE5C,AADAC,EAAU,OAAOK,CAAM,GACvB,KAAkBC,EAAQ;EAC5B;CANwB;AAO1B;AAGA,eAAeC,GAAqB,GAAqC;CACvE,IAAMlD,IAAO,IAAI,IAAIqC,EAAI,KAAK,CAAC,CAAC,CAAC,SAAS,QAAQ,OAAO,EAAE,GACrDc,IAASR,EAAU,IAAI3C,CAAI;CACjC,IAAImD,MAAW,KAAA,GAIb,OAFAR,EAAU,OAAO3C,CAAI,GACrB2C,EAAU,IAAI3C,GAAMmD,CAAM,GACnBA;CAET,IAAMC,IAAWP,EAAe,IAAI7C,CAAI;CACxC,IAAIoD,GAAU,OAAOA;CAErB,IAAMC,IAAUlB,GAA0BE,GAAKrC,CAAI,CAAC,CACjD,MAAM,OACDyC,MAAS,QAAQI,EAAe,IAAI7C,CAAI,MAAMqD,KAASN,GAAU/C,GAAMyC,CAAI,GACxEA,EACR,CAAC,CACD,cAAc;EACb,AAAII,EAAe,IAAI7C,CAAI,MAAMqD,KAASR,EAAe,OAAO7C,CAAI;CACtE,CAAC;CAEH,OADA6C,EAAe,IAAI7C,GAAMqD,CAAO,GACzBA;AACT;AAEA,eAAeC,GACb,GACA,GACA,GACwB;CACxB,IAAIC,GACF,IAAI;EACF,IAAMC,IAAQ,MAAMD,EAAgB;GAAE;GAAc;EAAM,CAAC;EAC3D,IAAIC,KAAS,QAAQA,EAAM,SAAS,GAAG,OAAOA;CAChD,QAAQ,CAER;CAGF,OADK1B,GAA+BlC,CAAK,IAClCsD,GAAqBtD,CAAK,IADkB;AAErD;AAGA,IAAM6D,KAAsB;AAE5B,eAAeC,GACb,GACA,GACe;CACf,IAAIC,IAAO;CAMX,MAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAIC,GAAOC,EAAM,MAAM,EAAE,GAAG,YAL9B;EACxC,OAAOF,IAAOE,EAAM,SAClB,MAAMA,EAAM,IAAO,CAAE;CAEzB,CAC8E,CAAC;AACjF;AAOA,eAAsBC,EACpB,GACA,GACe;CACf,IAAMP,IAAkBQ,GAAS,iBAC3BF,IAAoC,CAAC;CAE3C,KAAK,IAAMpE,KAAQuE,GAAO;EACxB,IAAMC,oBAAgB,IAAI,IAAY,CAAC,GAAGrC,EAAc,CAAC,GACnDsC,IAAcpD,EAAsBrB,CAAI;EAC9C,IAAIyE,GACG,KAAA,IAAM,CAAC1E,GAAGoB,MAAM,OAAO,QAAQsD,CAAW,GAC7C,AAAIzD,EAAwBG,CAAC,KAAGqD,EAAc,IAAIzE,CAAC;EAGvD,KAAK,IAAM2E,KAAOF,GAAe;GAC/B,IAAMG,IAAI3E,EAAK0E;GACf,AAAI,OAAOC,KAAM,YAAYA,EAAE,KAAK,MAAM,MAC1CP,EAAM,KAAK,YAAY;IACrB,IAAMpB,IAAO,MAAMa,GAAoBa,GAAKC,GAAGb,CAAe;IAC9D,AAAId,MAAS,SAAM,EAAK0B,KAAO1B;GACjC,CAAC;EACH;EAEA,IAAM4B,IAAapD,EAA4BxB,CAAI;EACnD,IAAI4E,GACF,KAAK,IAAM,CAACC,GAAS5C,MAAW,OAAO,QAAQ2C,CAAU,GAAG;GAC1D,IAAME,IAAM9E,EAAK6E;GACjB,IAAI,CAAC,MAAM,QAAQC,CAAG,GAAG;GACzB,IAAMC,IAAI,KAAK,IAAI9C,EAAO,QAAQ6C,EAAI,MAAM;GAC5C,KAAK,IAAIE,IAAI,GAAGA,IAAID,GAAG,KAAK;IAC1B,IAAI,CAAC/D,EAAwBiB,EAAO+C,EAAG,GAAG;IAC1C,IAAMC,IAAKH,EAAIE;IACf,AAAI,OAAOC,KAAO,YAClBb,EAAM,KAAK,YAAY;KACrB,IAAMpB,IAAO,MAAMa,GAAoBgB,GAASI,GAAInB,CAAe;KACnE,AAAId,MAAS,SAAM,EAAIgC,KAAKhC;IAC9B,CAAC;GACH;EACF;CAEJ;CAEA,MAAMiB,GAAmBG,GAAOJ,EAAmB;AACrD;AAGA,IAAakB,KAAoCb;;;AC9LjD,SAAgBc,EACd,GACgC;CAChC,IAAM7D,IAAM,OAAO8D,KAAoB,WAAWA,EAAgB,KAAK,IAAI;CAC3E,IAAI,CAAC9D,GACH,OAAO;EAAE,IAAI;EAAO,QAAQ;CAAQ;CAGtC,IAAIjB;CACJ,IAAI;EACF,IAAS,KAAK,MAAMiB,CAAG;CACzB,SAAS,GAAG;EACV,OAAO;GAAE,IAAI;GAAO,QAAQ;GAAS,OAAO;EAAE;CAChD;CAOA,OALI,CAAC,MAAM,QAAQjB,CAAM,KAAKA,EAAO,WAAW,KAAK,CAACA,EAAO,EAAE,EAAE,QACxD;EAAE,IAAI;EAAO,QAAQ;CAAQ,IAI/B;EAAE,IAAI;EAAM,UADFA,EAAO,EAAE,CAAC;CACC;AAC9B;AAGA,IAAagF,KAAkCF;;;AC1B/C,SAAgBG,EACd,GACsC;CACtC,IAAM,CAACzF,GAAkB0F,GAAWC,KAAaC,EAAgB,MAAM,GAAG;CAC1E,IAAI,CAAC5F,KAAoB,CAAC0F,GAAW,OAAO;CAC5C,IAAMG,IAASF,MAAc;CAM7B,OAAO;EAAE,cALaE,IAElB7F,EAAiB,SAAS,GAAG,IAC3BA,IACAX,EAAUW,CAAgB,IAH5BA;EAImB;EAAW;CAAO;AAC3C;;;ACbA,SAAS8F,GAAgB,GAAc,GAAmD;CACxF,IAAMC,IAAY,IAAI,KAAKC,GAAMC,IAAQ,GAAG,CAAC,GACvCC,IAAU,IAAI,KAAKF,GAAMC,GAAO,GAAG,IAAI,IAAI,EAAE;CAGnD,OAAO;EAAE,SAFO,KAAK,MAAMF,EAAU,QAAQ,IAAI,GAExC;EAAS,OADJ,KAAK,MAAMG,EAAQ,QAAQ,IAAI,GAAI,IAAI;CAC7B;AAC1B;AAKA,SAAgBC,KAA+C;CAC7D,OAAO;EACL,MAAM;EAEN,MAAM,aAAa,GAAkD;GACnE,IAAM,CAACC,KAAQ,MAAMC,EAAsB,EAAE,MAAM,CAACC,CAAO,EAAE,CAAC;GAC9D,OAAQF,KAAwC;EAClD;EAEA,MAAM,sBACJ,GACA,GAC4B;GAC5B,OAAQ,MAAMG,EACZrF,GACAsF,EAAK,OACLA,EAAK,IACP;EACF;EAEA,MAAM,qBACJ,GACA,GACA,GAC4B;GAC5B,OAAQ,MAAMD,EAAqBrF,GAAYsF,EAAK,OAAOA,EAAK,MAAM,EACpE,aACF,CAAC;EACH;EAEA,MAAM,8BACJ,GACA,GACA,GAC4B;GAC5B,IAAM,EAAE,YAAS,aAAUV,GAAgBE,GAAMC,CAAK,GAChDQ,IAAQC,EAAyB,EACrC,KAAK,CACH,EACE,QAAQ,EACN,IAAI,EACF,aAAa,EACX,MAAM,EACJ,MAAM,EAAE,QAAQxF,EAAW,EAC7B,EACF,EACF,EACF,EACF,GACA,EACE,aAAa;IAAE,KAAKyF;IAAS,IAAIC;GAAM,EACzC,CACF,EACF,CAAC,GAGK,EAAE,iBAAc,MADJC,EAAU,aACA,CAAA,CAAU,QAAQC,GAAgB;IAC5D;IACA,MAAM;IACN,MAAM;GACR,CAAC;GAED,QAAQC,KAAa,CAAC,EAAA,CAAG,KAAK,OAAU;IACtC,GAAGX;IACH,QAAQ,EAAE,aAAa,CAAC,EAAE,MAAMlF,EAAW,CAAC,EAAE;GAChD,EAAE;EACJ;EAEA,MAAM,mBAAmB,GAA6C;GACpE,OAAQ,MAAM8F,EAAuB,EACnC,UAAU,CAACV,CAAO,EACpB,CAAC;EACH;EAEA,MAAM,oBACJ,GACA,GAC4B;GAG5B,OAFIW,EAAS,WAAW,IAAU,CAAC,IAE3B,MAAMD,EAAuB;IACnC;IACA,gBAAgB,CAACR,GAAM;GACzB,CAAC;EACH;EAEA,MAAM,4BACJ,GAC4B;GAE5B,OADIU,EAAY,WAAW,IAAU,CAAC,IAC9B,MAAMC,EAAyB,EACrC,eACF,CAAC;EACH;EAEA,MAAM,eAAe,GAA4C;GAE/D,OADIC,EAAK,WAAW,IAAU,CAAC,IACvB,MAAMf,EAAsB,EAAE,QAAK,CAAC;EAC9C;EAEA,MAAM,iBAAiB,GAAM;GAC3B,OAAOgB,EAA2Bb,CAAI;EACxC;CACF;AACF;AAEA,IAAIc,KAA0C;AAE9C,SAAgBC,IAA4C;CAI1D,OAHA,AACED,OAAkBnB,GAA4B,GAEzCmB;AACT;;;AChHA,IAAME,IAAe,SAEfC,IAA0B,CAC9B,oEACF,GAEMC,qBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,GAEKvI,KAAe,MACZyI,EAAI,QAAQ,cAAc,GAAG,MAAmBC,EAAO,YAAY,CAAC;AAqB7E,SAASC,KAAyC;CAChD,OAAO;EACL,oCAAoB,IAAI,IAAI;EAC5B,iCAAiB,IAAI,IAAI;EACzB,0CAA0B,IAAI,IAAI;EAClC,qCAAqB,IAAI,IAAI;EAC7B,gCAAgB,IAAI,IAAI;EACxB,mCAAmB,IAAI,IAAI;EAC3B,4CAA4B,IAAI,IAAI;EACpC,iCAAiB,IAAI,IAAI;EACzB,mCAAmB,IAAI,IAAI;CAC7B;AACF;AAGA,SAASC,EAAe,GAAgE;CACtF,IAAMrD,IAAkD,CAAC;CACzD,KAAK,IAAM4B,KAAW0B,EAAI,mBAAmB;EAC3C,IAAM7H,IAAO6H,EAAI,eAAe,IAAI1B,CAAO;EAC3C,AAAInG,KAAMuE,EAAM,KAAK,CAAC4B,GAASnG,CAAI,CAAC;CACtC;CACA,OAAOuE;AACT;AAEA,SAASuD,EAAmB,GAAgC,GAAuB;CASjF,AARI,CAACtH,EAAM,WAAW,CAACA,EAAM,WAC3B,EAAM,UAAU2F,GAChB,EAAM,UAAUA,KACP3F,EAAM,WAAW,CAACA,EAAM,UACjC,EAAM,UAAUA,EAAM,UACbA,EAAM,WAAW,CAACA,EAAM,YACjC,EAAM,UAAUA,EAAM,UAEpBA,EAAM,YAAY,CAACA,EAAM,WAC3B,EAAM,WAAWA,EAAM,WACdA,EAAM,YAAY,CAACA,EAAM,aAClC,EAAM,WAAWA,EAAM;AAE3B;AAEA,SAASuH,GACP,GACA,GACA,GACM;CACN,EAAI,gBAAgB,IAAIC,CAAc;CACtC,IAAM7B,IAAU0B,EAAI,oBAAoB,IAAII,EAAS,MAAM;CAC3D,IAAI,CAAC9B,GAAS;CACd,IAAM+B,IAAUL,EAAI,yBAAyB,IAAI1B,CAAO,qBAAK,IAAI,IAAY;CAE7E,AADA+B,EAAQ,IAAIF,CAAc,GAC1BH,EAAI,yBAAyB,IAAI1B,GAAS+B,CAAO;AACnD;AAEA,eAAeC,GACb,GACA,GACe;CACf,IAAM9H,IAAS8E,EAAyB8C,EAAS,eAAe;CAChE,IAAI,CAAC5H,EAAO,IAAI;EACd,IAAM,EAAE,OAAI,WAAQ,gBAAa4H;EACjC,AAAI5H,EAAO,WAAW,UACpB,QAAQ,KACN,qEACAoC,GACA2F,GACAC,CACF,IACShI,EAAO,WAAW,UAC3B,QAAQ,KACN,+EACAoC,GACA2F,GACAC,GACAhI,EAAO,KACT,IAEA,QAAQ,KACN,iFACAoC,GACA2F,GACAC,CACF;EAEF;CACF;CAEA,IAAMC,IAAWjI,EAAO,UAEpBkI,IAAoBD,EAAS;CACjC,IAAI,CAACC,GACH;CAGF,IAAMC,IAAYP,EAAS;CAC3B,EAAgC;EAC9B,MAAMM;EACN;CACF,CAAC;CAED,IAAIE,IAAa,IACb/C,IAAS,IACPgD,IAAUJ,EAAS,MACnBK,KACHD,MAAY,aAAaA,MAAY,gBACtCH,MAAsB,4BACtBA,MAAsB,mCAClBK,IACJ,CAACD,MACAJ,EAAkB,SAAS,KAAK,KAAKA,EAAkB,SAAS,MAAM,MACvEA,MAAsB,4BACtBA,MAAsB;CAExB,IAAII,KAAqBC,GAA4B;EAEnD,IADA,IAAa,IACT,MAAM,QAAQN,EAAS,KAAK,GAAG;GAEjC,IADA,IAAS,IACLM,GAA4B;IAC9B,IAAMC,IAASvD,EAA6BiD,CAAiB;IAC7D,AAAIM,MACF,IAAoBA,EAAO;GAE/B;GACA,EAAS,MAAM,SAAS,MAAkB;IACxC,AAAKvB,EAAwB,SAASnH,CAAK,KAAG4H,GAAkBF,GAAKI,GAAU9H,CAAK;GACtF,CAAC;EACH,OAAO,AAAKmH,EAAwB,SAASgB,EAAS,KAAe,KACnEP,GAAkBF,GAAKI,GAAUK,EAAS,KAAe;CAE7D;CAEA,IAAIQ,IAAmCR,EAAS;CAChD,AAAIG,KAAc/C,KAAU,MAAM,QAAQoD,CAAa,IACrD,IAAgBA,EAAc,KAAK,MAAM,OAAOnE,CAAC,CAAC,IACzC,OAAOmE,KAAkB,aAGlC,KADgBC,EAAiBL,CAAO,IAAIM,EAAgBF,CAAa,IAAI,KAAA,MAClD,KAAK,UAAUA,CAAa;CAGzD,IAAMG,IAAqBpB,EAAI,oBAAoB,IAAII,EAAS,MAAM;CACtE,IAAI,CAACgB,GACH;CAGF,IAAMC,IAAerB,EAAI,eAAe,IAAIoB,CAAkB,KAAK,CAAC;CACpE,EAAaV,KAAqBO;CAClC,IAAMK,IAAoBnK,EAAYuJ,CAAiB;CAIvD,AAHIY,MAAsBZ,MACxB,EAAaY,KAAqBL,IAEpCjB,EAAI,eAAe,IAAIoB,GAAoBC,CAAY;AACzD;AAGA,SAASE,GAAW,GAAgE;CAClF,IAAMC,oBAAS,IAAI,IAAwB;CAC3C,KAAK,IAAM,CAAClD,GAASmD,MAAQC,GAC3B,CAAID,EAAI,eAAe,KAAA,KAAaA,EAAI,SAAS,KAAA,MAAWD,EAAO,IAAIlD,EAAQ,YAAY,GAAGmD,CAAG;CAEnG,OAAOD;AACT;AAGA,SAASG,GACP,GACA,GAC6B;CAC7B,IAAMC,IAAOH,EAAI,MACXI,IACJD,MAAS,KAAA,IAAYE,IAAWA,EAAS,QAAQ,MAAMhF,EAAE,eAAe8E,CAAI;CAC9E,IAAIH,EAAI,eAAe,KAAA,GACrB,OAAO,CAAC,GAAGI,CAAU,CAAC,CAAC,MAAM,GAAG,MAAME,EAAE,cAAcC,EAAE,WAAW,CAAC,CAAC;CAEvE,IAAMC,IAASR,EAAI,WAAW,YAAY;CAC1C,OAAOI,EAAW,MAAM,MAAM/E,EAAE,GAAG,YAAY,MAAMmF,CAAM;AAC7D;AAEA,eAAeC,GACb,GACA,GACA,GACA,IASI,CAAC,GACU;CACf,IAAMjD,IAAqB,CAAC;CAE5B,KAAK,IAAI9B,IAAI,GAAGA,IAAIgF,EAAM,QAAQ,KAAK;EACrC,IAAM/D,IAAO+D,EAAMhF;EACnB,IAAI,CAACiB,GAAM;EACX,EAAS,KAAKA,EAAK,EAAE;EACrB,IAAMgE,IAAYhE,EAAK,QAAQ,cAAc,EAAE,EAAE,QAAQ;EAGzD,AAFA4B,EAAI,mBAAmB,IAAI5B,EAAK,IAAIgE,CAAS,GAExCpC,EAAI,eAAe,IAAI5B,EAAK,EAAE,KACjC4B,EAAI,eAAe,IAAI5B,EAAK,IAAI;GAC9B,SAASA,EAAK;GACd,aAAaA,EAAK;GAClB,UAAUA,EAAK;EACjB,CAAC;CAEL;CAEA,IAAIa,EAAS,WAAW,GAAG;CAI3B,IAAMoD,IAAY,IAAI,IAAIpD,CAAQ,GAC5BqD,IAAkB9D,EAAK,WACzBA,EAAK,SAAS,QAAQ,MAAM6D,EAAU,IAAIvF,EAAE,MAAM,CAAC,IACnD,MAAMyF,EAAW,oBAAoBtD,GAAU,EAAE,gBAAgB,GAAK,CAAC,GAErEuD,IAAcC,EAAgCH,GAAiBH,CAAK,GACpEO,IAAeF,EAAY,QAAQ,MAAM1F,EAAE,YAAY,EAAI;CAEjE,IAAI0B,EAAK,kCAAkC;EAGzC,IAAMmE,IAAuB,IAAI,IAAID,EAAa,KAAK,MAAM5F,EAAE,MAAM,CAAC;EACtE,KAAK,IAAM8F,KAAWJ,GAAa;GACjC,IAAMlE,IAAUsE,EAAQ;GACxB,AAAI,GAAqB,IAAItE,CAAO,KAAM+D,EAAU,IAAI/D,CAAO,MAC/D0B,EAAI,eAAe,OAAO1B,CAAO,GACjC0B,EAAI,mBAAmB,OAAO1B,CAAO,GACrC0B,EAAI,gBAAgB,IAAI1B,CAAO;EACjC;CACF;CAEA,KAAK,IAAInB,IAAI,GAAGA,IAAIuF,EAAa,QAAQ,KAAK;EAC5C,IAAMG,IAAcH,EAAavF,IAC3BmB,IAAUuE,EAAY;EAC5B,EAAI,oBAAoB,IAAIA,EAAY,IAAIvE,CAAO;EACnD,IAAMwE,IAAmB9C,EAAI,kBAAkB,IAAI1B,CAAO,KAAK,CAAC;EAChE,EAAI,kBAAkB,IAAIA,GAAS,CAAC,GAAGwE,GAAkBD,CAAW,CAAC;CACvE;CAKA,IAAME,IAA8B,CAAC,GAC/BC,oBAAmB,IAAI,IAAoB;CACjD,KAAK,IAAM1E,KAAWW,GAAU;EAC9B,IAAMwC,IAAMjD,EAAK,MAAM,IAAIF,EAAQ,YAAY,CAAC;EAChD,IAAI,CAACmD,GAAK;EACV,IAAMwB,IAAStB,GAAc3B,EAAI,kBAAkB,IAAI1B,CAAO,KAAK,CAAC,GAAGmD,CAAG;EAC1E,AAAKwB,KAOLF,EAAkB,KAAKE,EAAO,EAAE,GAChCjD,EAAI,2BAA2B,IAAI1B,GAAS2E,EAAO,EAAE,GACjDxB,EAAI,SAAS,KAAA,KAAWuB,EAAiB,IAAIC,EAAO,IAAIxB,EAAI,IAAI,MARlEzB,EAAI,eAAe,OAAO1B,CAAO,GACjC0B,EAAI,mBAAmB,OAAO1B,CAAO,GACrC0B,EAAI,kBAAkB,OAAO1B,CAAO,GACpC0B,EAAI,gBAAgB,IAAI1B,CAAO;CAMnC;CACA,KAAK,IAAM,CAACA,GAASwD,MAAa9B,EAAI,kBAAkB,QAAQ,GAAG;EACjE,IAAIA,EAAI,2BAA2B,IAAI1B,CAAO,GAAG;EAEjD,IAAM4E,IADiB,CAAC,GAAGpB,CAAQ,CAAC,CAAC,MAAM,GAAG,MAAMC,EAAE,cAAcC,EAAE,WAChD,CAAA,CAAe;EACrC,AAAIkB,MACFH,EAAkB,KAAKG,EAAc,EAAE,GACvClD,EAAI,2BAA2B,IAAI1B,GAAS4E,EAAc,EAAE;CAEhE;CAEA,IAAIH,EAAkB,WAAW,GAAG;CAEpC,IAAMI,IAAgBV,EACpB,MAAMF,EAAW,4BAA4BQ,CAAiB,GAC9DL,CACF,CAAC,CAAC,QAAQ,MAAa;EACrB,IAAMd,IAAOoB,EAAiB,IAAI5C,EAAS,MAAM;EACjD,OAAOwB,MAAS,KAAA,KAAaxB,EAAS,eAAewB;CACvD,CAAC,GACKwB,IAAiBC,EAA6CF,CAAa;CAEjF,KAAK,IAAIhG,IAAI,GAAGA,IAAIiG,EAAe,QAAQ,KACzC,MAAM9C,GAAoBN,GAAKoD,EAAejG,EAAqB;AAEvE;AAEA,SAASmG,GAAgC,GAA4B;CACnE,KAAK,IAAM,GAAGnL,MAAS4H,EAAeC,CAAG,GAAG;EAC1C,IAAMuD,IAAgB,OAAO,KAAKpL,CAAI,CAAC,CAAC,QACrC,MAAM,CAACD,EAAE,WAAW,GAAG,KAAK,CAACwH,GAAc,IAAIxH,CAAC,CACnD;EAEA,KAAK,IAAM2E,KAAO0G,GAAe;GAC/B,IAAIjL,IAAQH,EAAK0E,IACX2G,IAAUnL,EAAyBC,CAAK;GAO9C,IANIkL,MAAYlL,KAAS,MAAM,QAAQkL,CAAO,MAC5C,EAAK3G,KAAO2G,GACZ,IAAQA,IAEK,MAAM,QAAQlL,CAEzB,GAAQ;IACV,IAAM8G,IAAO9G;IAOb,IAAI,CANmB8G,EAAK,MACzB,MACC,OAAOtC,KAAM,YACb,CAAC2C,EAAwB,SAAS3C,CAAC,KACnCkD,EAAI,eAAe,IAAIlD,CAAC,CAEvB,GAAgB;IAErB,IAAM2G,IAAiB,CAAC,GAClBrJ,IAAmB,CAAC,GACtBsJ,IAAW;IACf,KAAK,IAAMC,KAAOvE,GAAM;KACtB,IAAI,OAAOuE,KAAQ,YAAYlE,EAAwB,SAASkE,CAAG,GAAG;MAEpE,AADAF,EAAK,KAAK,OAAOE,CAAG,CAAC,GACrBvJ,EAAO,KAAK,SAAS;MACrB;KACF;KACA,IAAMwJ,IAAc5D,EAAI,mBAAmB,IAAI2D,CAAG,KAAK;KACvD,IAAIC,MAAgBpE,GAAc;MAEhC,AADAiE,EAAK,KAAKE,CAAG,GACbvJ,EAAO,KAAKoF,CAAY;MACxB;KACF;KACA,IAAMa,IAAUL,EAAI,eAAe,IAAI2D,CAAG,GACpCjL,IAAQ2H,GAAS,wBACrBA,GAAS;KACX,IAAI3H,KAAQ,OAAOA,KAAS,YAAYA,EAAK,KAAK,GAChD,IAAI;MAGF,AAFA+K,EAAK,KAAKnM,EAA4BoB,CAAI,CAAC,GAC3C0B,EAAO,KAAKwJ,CAAW,GACvB,IAAW;KACb,QAAQ;MAEN,AADAH,EAAK,KAAKE,CAAG,GACbvJ,EAAO,KAAKwJ,CAAW;KACzB;UAGA,AADAH,EAAK,KAAKE,CAAG,GACbvJ,EAAO,KAAKwJ,CAAW;IAE3B;IACA,IAAIF,GAAU;KACZ,IAAMvJ,IAAYzC,EAA8BmF,CAAG;KAInD,IAHA,EAAK1C,KAAasJ,GAClBvJ,GAA4B/B,GAAMgC,GAAWC,CAAM,GACnDnC,GAA4CE,GAAMgC,CAAS,GACvDA,MAAc0C,GAAK;MACrB,OAAO1E,EAAK0E;MACZ,IAAMgH,IAAW1M,EAAY0F,CAAG;MAChC,AAAIgH,MAAahH,KAAK,OAAO1E,EAAK0L;KACpC;IACF;GACF,OAAO,IAAI,OAAOvL,KAAU,UAAU;IAEpC,IADImH,EAAwB,SAASnH,CAAK,KACtC,CAAC0H,EAAI,eAAe,IAAI1H,CAAK,GAAG;IAEpC,IAAM+H,IAAUL,EAAI,eAAe,IAAI1H,CAAK;IAC5C,IAAI0H,EAAI,mBAAmB,IAAI1H,CAAK,MAAMkH,GACxC;IAEF,IAAM9G,IAAQ2H,GAAS,wBAAwBA,GAAS;IAGxD,IAAI3H,KAAQ,OAAOA,KAAS,YAAYA,EAAK,KAAK,GAChD,IAAI;KACF,IAAMyB,IAAY0C,EAAI,SAAS,KAAK,IAAIA,EAAI,QAAQ,QAAQ,EAAE,IAAIA;KAClE,EAAK1C,KAAa7C,EAA4BoB,CAAI;KAClD,IAAMoL,IAAe9D,EAAI,mBAAmB,IAAI1H,CAAK,KAAK;KAC1D,EAAqBH,GAAMgC,GAAW2J,CAAY;KAClD,IAAMC,IAAW5M,EAAYgD,CAAS;KAItC,IAHI4J,MAAa5J,KACfN,EAAqB1B,GAAM4L,GAAUD,CAAY,GAE/C3J,MAAc0C,GAAK;MACrB,OAAO1E,EAAK0E;MACZ,IAAMgH,IAAW1M,EAAY0F,CAAG;MAChC,AAAIgH,MAAahH,KAAK,OAAO1E,EAAK0L;KACpC;IACF,QAAQ,CAER;GAEJ;EACF;CACF;AACF;AAEA,SAASG,GAAyB,GAAsB,GAAgC;CACtF,IAAKC,GAEL,KAAK,IAAM,GAAG9L,MAAS4H,EAAeC,CAAG,GAAG;EAC1C,IAAMuD,IAAgB,OAAO,KAAKpL,CAAI,CAAC,CAAC,QACrC,MAAM,CAACD,EAAE,WAAW,GAAG,KAAK,CAACwH,GAAc,IAAIxH,CAAC,CACnD;EAEA,KAAK,IAAM2E,KAAO0G,GAAe;GAC/B,IAAIjL,IAAQH,EAAK0E,IACX2G,IAAUnL,EAAyBC,CAAK;GAC9C,AAAIkL,MAAYlL,KAAS,MAAM,QAAQkL,CAAO,MAC5C,EAAK3G,KAAO2G,GACZ,IAAQA;GAEV,IAAM3F,IAAS,MAAM,QAAQvF,CAAK,GAC5B8G,IAAOvB,IAAUvF,IAAsB,CAACA,CAAK,GAE7C4L,IAAsB,CAAC,GACzBC,IAAY;GAEhB,KAAK,IAAMR,KAAOvE,GAAM;IACtB,IAAI,OAAOuE,KAAQ,YAAYlE,EAAwB,SAASkE,CAAG,GAAG;KACpE,EAAS,KAAKA,CAAG;KACjB;IACF;IACA,IAAMtD,IAAUL,EAAI,eAAe,IAAI2D,CAAG;IAC1C,IAAI,CAACtD,GAAS;KACZ,EAAS,KAAKsD,CAAG;KACjB;IACF;IACA,IAAMjL,IAAQ2H,GAAS,wBAAwBA,GAAS;IAKxD,IAFgBL,EAAI,mBAAmB,IAAI2D,CAAG,MAAMnE,GAEvC;KACX,IAAM7G,IAAQ,EAAE,GAAG0H,EAAQ;KAK3B,AAJAJ,EAAmBtH,GAAOgL,CAAG,GAC7B,EAAM,aAAanE,GACnB/G,EAAqBE,CAAK,GAC1BuL,EAAS,KAAKvL,CAAK,GACnB,IAAY;KACZ;IACF;IAEA,IAAID,KAAQ,OAAOA,KAAS,YAAYA,EAAK,KAAK,GAAG;KACnD,EAAS,KAAKiL,CAAG;KACjB;IACF;IACA,IAAMhL,IAAQ,EAAE,GAAG0H,EAAQ;IAG3B,AAFAJ,EAAmBtH,GAAOgL,CAAG,GAC7BO,EAAS,KAAKvL,CAAK,GACnB,IAAY;GACd;GAEA,IAAIwL,GAAW;IACb,IAAMhK,IAAY0D,IACdnG,EAA8BmF,CAAG,IACjCA,EAAI,SAAS,KAAK,IAChBA,EAAI,QAAQ,QAAQ,EAAE,IACtBA;IAGN,IAFA,EAAK1C,KAAa0D,IAASqG,IAAWA,EAAS,IAC/CjM,GAA4CE,GAAMgC,CAAS,GACvDA,MAAc0C,GAAK;KACrB,OAAO1E,EAAK0E;KACZ,IAAMgH,IAAW1M,EAAY0F,CAAG;KAChC,AAAIgH,MAAahH,KAAK,OAAO1E,EAAK0L;IACpC;GACF;EACF;CACF;AACF;AAKA,SAASO,GAAc,GAAsB,GAAwC;CACnF,OAAOrE,EAAeC,CAAG,CAAC,CAAC,KAAK,CAAC1B,GAASnG,OAAU;EAClD,IAAMkM,IAAarE,EAAI,2BAA2B,IAAI1B,CAAO,KAAK;EAIlE,AAHI+F,MACF,EAAK,aAAaA,IAEpBpE,EAAmB9H,GAAMmG,CAAO;EAChC,IAAMgG,IACJ,OAAOnM,EAAK,eAAgB,WAAWA,EAAK,cAAc,GACtDoM,IACJ,OAAOpM,EAAK,YAAa,WACrBA,EAAK,WACL,OAAOA,EAAK,YAAa,WACvBA,EAAK,WACL,KAAA;EACR,OAAO;GACL;GACA,YAAYe,KAAc8G,EAAI,mBAAmB,IAAI1B,CAAO,KAAK;GACjE;GACA;GACA;GACA,MAAMnG;EACR;CACF,CAAC;AACH;AAaA,SAASqM,GAAe,GAAsB,GAAmC;CAC/E,IAAMvF,IAAW,CAACX,GAAS,GAAI0B,EAAI,yBAAyB,IAAI1B,CAAO,KAAK,CAAC,CAAE,GACzEmG,IAAkBxF,EACrB,KAAK,MAAQe,EAAI,2BAA2B,IAAI2D,CAAG,CAAC,CAAC,CACrD,QAAQ,MAAuB,CAAC,CAACA,CAAG;CACvC,OAAO;EAAE,SAAS,CAAC,GAAG1E,GAAU,GAAGwF,CAAe;EAAG,KAAKxF;CAAS;AACrE;AAiBA,eAAsByF,EACpB,GACA,GACA,GACA,IAA8BnF,EAAyB,GAEvD,GACiF;CACjF,OAAOoF,EAAoBxC,GAAO1F,GAAS8F,GAAY;EACrD;EACA,UAAUqC,GAAY;CACxB,CAAC;AACH;AAOA,eAAsBD,EACpB,GACA,GACA,GACA,IAA2B,CAAC,GACqD;CACjF,IAAMV,IAAkBxH,GAAS,oBAAoB,IAC/CoI,IAAiBpI,GAAS,mBAAmB,IAE7CuD,IAAMF,GAAsB;CAClC,KAAK,IAAM1B,KAAQ+D,GAAO,AAAI/D,KAAM4B,EAAI,kBAAkB,IAAI5B,EAAK,EAAE;CAErE,MAAM8D,GAAalC,GAAKmC,GAAOI,GAAY;EACzC,kCAAkC;EAClC,UAAUxG,EAAQ;EAClB,MAAMA,EAAQ,QAAQwF,GAAWxF,EAAQ,IAAI;CAC/C,CAAC;CAED,IAAM+I,IAAuB,MAAM,KAAK9E,EAAI,eAAe,CAAC,CAAC,QAC1D,MAAQ,CAACA,EAAI,eAAe,IAAI2D,CAAG,KAAK,CAAC3D,EAAI,gBAAgB,IAAI2D,CAAG,CACvE;CACA,IAAImB,EAAqB,SAAS,GAAG;EAGnC,IAAM,CAACC,GAAcC,KAAmB,MAAM,QAAQ,IAAI,CACxDzC,EAAW,eAAeuC,CAAoB,GAC9CvC,EAAW,oBAAoBuC,GAAsB,EAAE,gBAAgB,GAAK,CAAC,CAC/E,CAAC;EACD,MAAM5C,GAAalC,GAAK+E,GAAcxC,GAAY,EAAE,UAAUyC,EAAgB,CAAC;CACjF;CAGA,AADA1B,GAAgCtD,CAAG,GACnCgE,GAAyBhE,GAAKiE,CAAe;CAE7C,IAAMgB,IAAUb,GAAcpE,GAAKjE,EAAQ,UAAU;CAcrD,OAZI8I,KACF,MAAMrI,EACJyI,EAAQ,KAAK,MAAMC,EAAE,IAAI,GACzB3C,EAAW,kBACP,EAAE,iBAAiBA,EAAW,gBAAgB,KAAKA,CAAU,EAAE,IAC/D,KAAA,CACN,GAMK;EAAE;EAAS,cAAA,IAHO,IACvB0C,EAAQ,KAAK,MAAW,CAACE,EAAO,SAASX,GAAexE,GAAKmF,EAAO,OAAO,CAAC,CAAC,CAE7D;CAAa;AACjC;AAMA,eAAsBC,GACpB,GACA,GACA,GACA,IAA8B7F,EAAyB,GAChC;CACvB,QAAQ,MAAMmF,EAA8BxL,GAAYiJ,GAAO1F,GAAS8F,CAAU,EAAA,CAAG;AACvF;;;ACzpBA,IAAM8C,MAAe,MACZzF,EAAI,QAAQ,cAAc,GAAG,MAAmBC,EAAO,YAAY,CAAC;AAM7E,SAAgByF,GAAqB,GAAY,GAAqB;CACpE,IAAI,OAAO,GAAGtD,GAAGD,CAAC,GAAG,OAAO;CAC5B,IAAIC,MAAM,KAAA,KAAaD,MAAM,KAAA,GAAW,OAAO;CAC/C,IAAIC,MAAM,QAAQD,MAAM,MAAM,OAAOC,MAAMD;CAE3C,IADI,OAAOC,KAAM,OAAOD,KACpB,OAAOC,KAAM,UAAU,OAAO;CAClC,IAAI;EACF,OAAO,KAAK,UAAUA,CAAC,MAAM,KAAK,UAAUD,CAAC;CAC/C,QAAQ;EACN,OAAO;CACT;AACF;AAYA,SAAgBwD,GACd,GACwB;CACxB,IAAM/M,IAAS8E,EAAyB8C,EAAS,eAAe;CAChE,IAAI,CAAC5H,EAAO,IAAI,OAAO;CAEvB,IAAMiI,IAAWjI,EAAO,UACpBkI,IAAoBD,EAAS;CACjC,IAAI,CAACC,GAAmB,OAAO;CAE/B,IAAMG,IAAUJ,EAAS,MACnBK,KACHD,MAAY,aAAaA,MAAY,gBACtCH,MAAsB,4BACtBA,MAAsB,mCAClBK,IACJ,CAACD,MACAJ,EAAkB,SAAS,KAAK,KAAKA,EAAkB,SAAS,MAAM,MACvEA,MAAsB,4BACtBA,MAAsB,mCAEpBE,IAAa,IACb/C,IAAS;CACb,KAAIiD,KAAqBC,OACvB,IAAa,IACT,MAAM,QAAQN,EAAS,KAAK,MAC9B,IAAS,IACLM,KAA4B;EAC9B,IAAMC,IAASvD,EAA6BiD,CAAiB;EAC7D,AAAIM,GAAQ,WACV,IAAoBA,EAAO;CAE/B;CAIJ,IAAIC,IAAmCR,EAAS;CAChD,AAAIG,KAAc/C,KAAU,MAAM,QAAQoD,CAAa,IACrD,IAAgBA,EAAc,KAAK,MAAM,OAAOnE,CAAC,CAAC,IACzC,OAAOmE,KAAkB,aAGlC,KADgBC,EAAiBL,CAAO,IAAIM,EAAgBF,CAAa,IAAI,KAAA,MAClD,KAAK,UAAUA,CAAa;CAGzD,IAAMuE,IAAYH,GAAY3E,CAAiB;CAC/C,OAAO;EACL,cAAcA;EACd,OAAOO;EACP,WAAWuE,MAAc9E,IAAgC,KAAA,IAAZ8E;CAC/C;AACF;AAKA,SAAgBC,GACd,GACyB;CACzB,IAAMC,IAAoC,CAAC;CAC3C,KAAK,IAAMtF,KAAYuF,GAAY;EACjC,IAAMC,IAAUL,GAA0BnF,CAAQ;EAClD,AAAKwF,MACL,EAASA,EAAQ,gBAAgBA,EAAQ,OACrCA,EAAQ,cACV,EAASA,EAAQ,aAAaA,EAAQ;CAE1C;CACA,OAAOF;AACT;AAYA,SAAgBG,GACd,GACyB;CACzB,IAAMC,IAAmC,CAAC,GACtCC,IAAkC,CAAC;CAEvC,KAAK,IAAMC,KAAQC,GAAiB;EAClC,IAAMC,IAAQF,EAAK,MACbG,oBAAS,IAAI,IAAI,CAAC,GAAG,OAAO,KAAKJ,CAAM,GAAG,GAAG,OAAO,KAAKG,CAAK,CAAC,CAAC,GAChEE,IAAwB,CAAC;EAC/B,KAAK,IAAMvJ,KAAOsJ,GAChB,AAAKb,GAAqBS,EAAOlJ,IAAMqJ,EAAMrJ,EAAI,KAC/CuJ,EAAY,KAAKvJ,CAAG;EAYxB,AATAuJ,EAAY,KAAK,GACjBN,EAAQ,KAAK;GACX,MAAM;GACN,IAAIE,EAAK;GACT,YAAYA,EAAK;GACjB,QAAQ,EAAE,GAAGD,EAAO;GACpB,OAAO,EAAE,GAAGG,EAAM;GAClB;EACF,CAAC,GACD,IAASA;CACX;CAEA,OAAOJ;AACT;AAKA,SAAgBO,GACd,GAC0B;CAC1B,IAAMC,IAAS,CAAC,GAAGX,CAAU,CAAC,CAAC,MAAM,GAAG,MAClC3D,EAAE,gBAAgBD,EAAE,cACjBC,EAAE,GAAG,cAAcD,EAAE,EAAE,IADcC,EAAE,cAAcD,EAAE,WAE/D,GAEKwE,oBAAqB,IAAI,IAAqB,GAC9CT,IAAoC,CAAC;CAE3C,KAAK,IAAM1F,KAAYkG,GAAQ;EAC7B,IAAMV,IAAUL,GAA0BnF,CAAQ;EAClD,IAAI,CAACwF,GAAS;EAEd,IAAMY,IAAQ,CAACZ,EAAQ,YAAY;EACnC,AAAIA,EAAQ,aAAWY,EAAM,KAAKZ,EAAQ,SAAS;EAGnD,IAAMa,IAAgBF,EAAmB,IAAIX,EAAQ,YAAY,IAC7DW,EAAmB,IAAIX,EAAQ,YAAY,IAC3C,KAAA,GACEc,IAAYd,EAAQ;EAe1B,AAbKN,GAAqBmB,GAAeC,CAAS,KAChDZ,EAAQ,KAAK;GACX,MAAM;GACN,IAAI1F,EAAS;GACb,YAAYA,EAAS;GACrB,UAAUwF,EAAQ;GAClB,gBAAgBxF,EAAS;GACzB;GACA;EACF,CAAC,GAGHmG,EAAmB,IAAIX,EAAQ,cAAcc,CAAS,GAClDd,EAAQ,aACVW,EAAmB,IAAIX,EAAQ,WAAWc,CAAS;CAEvD;CAEA,OAAOZ;AACT;AAMA,SAAgBa,GACd,GACA,GACkB;CAClB,IAAIC,IAAWd;CACf,IAAI,OAAOrJ,GAAS,SAAU,UAAU;EACtC,IAAMoK,IAAQpK,EAAQ;EACtB,IAAWmK,EAAS,QAAQ,MAAME,EAAE,MAAMD,CAAK;CACjD;CAWA,OATI,OAAOpK,GAAS,SAAU,YAAYA,EAAQ,SAAS,MAMzD,IAJoB,CAAC,GAAGmK,CAAQ,CAAC,CAAC,MAAM,GAAG,MACrC7E,EAAE,OAAOC,EAAE,KACR,IADmBD,EAAE,KAAKC,EAAE,EAG1B,CAAA,CAAY,MAAM,GAAGvF,EAAQ,KAAK,CAAC,CAAC,QAAQ,IAGlDmK;AACT;;;ACnMA,eAAsBG,GACpB,GACA,GACA,IAA8BxH,EAAyB,GACjB;CACtC,IAAMyH,IAAkCvK,GAAS,aAAa,CAAC,GACzDwK,IAAcD,EAAc,eAAe,WAI3C,CAAC5I,GAAMkE,KAAmB,MAAM,QAAQ,IAAI,CAChDC,EAAW,aAAajE,CAAO,GAC/BiE,EAAW,mBAAmBjE,CAAO,CACvC,CAAC,GAGK4I,IAAiB,CAAC,GAFHzE,EAAgCH,GAAiBlE,IAAO,CAACA,CAAI,IAAI,CAAC,CAE5D,CAAY,CAAC,CAAC,MACtC,GAAG,MAAM4D,EAAE,cAAcD,EAAE,WAC9B;CAEA,IAAImF,EAAe,WAAW,GAC5B,OAAO;EAAE,kBAAkB;EAAI,WAAW,CAAC;CAAE;CAG/C,IAAMC,IAAmBD,EAAeA,EAAe,SAAS,EAAE,CAAE,IAC9DhI,IAAcgI,EAAe,KAAK,MAAMpK,EAAE,EAAE,GAE5CqG,IAAgBV,EACpB,MAAMF,EAAW,4BAA4BrD,CAAW,GACxDgI,CACF,GAEIE;CAEJ,IAAIH,MAAgB,YAClB,IAAYZ,GAAyBlD,CAAa;MAC7C;EACL,IAAMkE,oBAAY,IAAI,IAA+B;EACrD,KAAK,IAAMC,KAAQnE,GAAe;GAChC,IAAMoE,IAAOF,EAAU,IAAIC,EAAK,MAAM,KAAK,CAAC;GAE5C,AADAC,EAAK,KAAKD,CAAI,GACdD,EAAU,IAAIC,EAAK,QAAQC,CAAI;EACjC;EAEA,IAAMC,IAA+B,CAAC;EACtC,KAAK,IAAM5E,KAAWsE,GAAgB;GACpC,IAAMO,IAAkBJ,EAAU,IAAIzE,EAAQ,EAAE,KAAK,CAAC,GAChD8E,IAAYrE,EAChBoE,CACF;GACA,EAAU,KAAK;IACb,YAAY7E,EAAQ;IACpB,IAAIA,EAAQ;IACZ,MAAM6C,GAAgCiC,CAAS;GACjD,CAAC;EACH;EACA,IAAY7B,GAAqB2B,CAAS;CAC5C;CAEA,OAAO;EACL;EACA,WAAWb,GAAsBS,GAAWJ,CAAa;CAC3D;AACF;;;ACrFA,SAAgBW,GAAa,GAAuB;CAElD,OAAO,IADMC,GAAWC,EAAOC,GAAYxP,CAAK,CAAC,CACtC,CAAA,CAAK,UAAU,GAAG,EAAE,EAAE;AACnC;AAMA,SAAgByP,GACd,GACA,GACA,GACQ;CACR,OAAOJ,GAAa,GAAGzO,EAAW,GAAG8O,EAAW,GAAGC,EAAU,KAAK,GAAG,GAAG;AAC1E;AAMA,SAAgBC,GAAiB,GAAuB,GAA4B;CAClF,OAAOP,GAAa,GAAGK,EAAW,GAAGG,GAAgBhD,CAAM,GAAG;AAChE;AAMA,SAASgD,GAAgB,GAAwB;CAC/C,OAAO,KAAK,UAAU7P,IAAQ,GAAM,MAClCwE,KAAK,OAAOA,KAAM,YAAY,CAAC,MAAM,QAAQA,CAAC,IAC1C,OAAO,YACL,OAAO,KAAKA,CAA4B,CAAC,CACtC,KAAK,CAAC,CACN,KAAK,MAAM,CAAC5E,GAAI4E,EAA8B5E,EAAE,CAAC,CACtD,IACA4E,CACN;AACF;;;AC5CA,SAASsL,KAA0C;CAGjD,OAFoB,WACjB,SAAS,OACS,CAAC;AACxB;AAsBA,SAAgBC,KAAgC;CAC9C,OAAOD,GAAI,CAAC,CAAC,aAAa;AAC5B;AAEA,SAAgBE,KAAyC;CACvD,IAAM,IAAIF,GAAI,GACRG,IAAM,SAAS,EAAE,aAAa,QAAQ,EAAE,GACxCC,IAAW,EAAE,aAAa,WAE1BC,IACJ,EAAE,kBAAkB,WACpB,EAAE,kBAAkB,OACpB,EAAE,kBAAkB,QACpB,EAAE,kBAAkB,OAChBC,IACJ,EAAE,kBAAkB,UACpB,EAAE,kBAAkB,OACpB,EAAE,kBAAkB,OAChBC,IAAQ,EAAE,aAAa,eAEzBC;CACJ,AAOEA,IAPEH,IACQ,KACDC,IACC,KACL,CAAIC;CAMX,IAAME,IAAoB,EAAE,6BAA6B,QACnDC,IAAkB,SAAS,EAAE,0BAA0B,OAAO,EAAE;CAEtE,OAAO;EACL;EACA;EACA;EACA;EACA;EACA,eAAeT,GAAqB;CACtC;AACF;;;ACjEA,SAAgBU,GAAc,GAAa;CAEzC,IADsB,OAAOzQ,KAAU,aAAnCA,KAA+C,OAAO,SAASA,CAAK,KACpE,YAAY,OAAOA,CAAK,GAAG,OAAOA;CACtC,KAAK,IAAM0Q,KAAS,OAAO,OAAO1Q,CAAK,GAAG,GAAW0Q,CAAK;CAC1D,OAAO,OAAO,OAAO1Q,CAAK;AAC5B;;;ACIA,IAAa2Q,KAAb,MAAyB;CACvB,kCAA6D,IAAI,IAAI;CACrE,4BAAiD,IAAI,IAAI;CACzD;CACA,+BAAsD,IAAI,IAAI;CAE9D,YAAY,GAA0B;EACpC,KAAK,SAASC;CAChB;CAEA,cAAsB,GAAoB,GAA4B;EACpE,OAAO,GAAGhQ,EAAW,IAAI8O;CAC3B;CAEA,QAAgB,GAAiB,GAA4B;EAC3D,OAAO,GAAG1J,EAAQ,GAAG0J;CACvB;CAEA,IAAY,gBAAyB;EACnC,OAAO,KAAK,OAAO,iBAAiBK,GAAqB;CAC3D;CAEA,QAAgB,GAA8B;EAC5C,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAIc,IAAc,KAAK,OAAO;CACnE;CAEA,cAAc,GAAoB,GAAiD;EACjF,IAAMtM,IAAM,KAAK,cAAc3D,GAAY8O,CAAU,GAC/CnM,IAAS,KAAK,gBAAgB,IAAIgB,CAAG;EAM3C,OALKhB,IACD,KAAK,QAAQA,EAAO,WAAW,KACjC,KAAK,gBAAgB,OAAOgB,CAAG,GACxB,QAEFhB,IALa;CAMtB;CAEA,cAAc,GAAoB,GAAoB,GAAkC;EACtF,IAAI,KAAK,eAAe,KAAK,IAAM1D,KAAQiR,EAAK,OAAO,GAAWjR,CAAI;EACtE,KAAK,gBAAgB,IAAI,KAAK,cAAce,GAAY8O,CAAU,GAAGoB,CAAI;CAC3E;CAEA,QAAQ,GAAiB,GAA2C;EAClE,IAAMvM,IAAM,KAAK,QAAQyB,GAAS0J,CAAU,GACtCnM,IAAS,KAAK,UAAU,IAAIgB,CAAG;EAMrC,OALKhB,IACD,KAAK,QAAQA,EAAO,WAAW,KACjC,KAAK,UAAU,OAAOgB,CAAG,GAClB,QAEFhB,IALa;CAMtB;CAEA,QAAQ,GAA4B;EAElC,AADI,KAAK,iBAAekN,GAAWK,EAAK,MAAM,GAC9C,KAAK,UAAU,IAAI,KAAK,QAAQA,EAAK,OAAO,SAASA,EAAK,UAAU,GAAGA,CAAI;CAC7E;CAGA,gBAAgB,GAA0B;EACxC,KAAK,IAAMvM,KAAO,KAAK,gBAAgB,KAAK,GAC1C,AAAIA,EAAI,WAAW,GAAG3D,EAAW,GAAG,KAAG,KAAK,gBAAgB,OAAO2D,CAAG;CAE1E;CAEA,UAAU,GAAiB,GAA2B;EACpD,IAAImL,GACF,KAAK,UAAU,OAAO,KAAK,QAAQ1J,GAAS0J,CAAU,CAAC;OAGzD,KAAK,IAAMnL,KAAO,KAAK,UAAU,KAAK,GACpC,AAAIA,EAAI,WAAW,GAAGyB,EAAQ,EAAE,KAC9B,KAAK,UAAU,OAAOzB,CAAG;CAG/B;CAEA,WAAiB;EAEf,AADA,KAAK,gBAAgB,MAAM,GAC3B,KAAK,UAAU,MAAM;CACvB;CAKA,MAAM,gBACJ,GACA,GACY;EACZ,IAAMwM,IAAe,KAAK,aAAa,IAAIxM,CAAG;EAC9C,IAAIwM,GACF,OAAOA;EAGT,IAAMC,KAAe,YAAY;GAC/B,IAAI;IACF,OAAO,MAAMC,EAAG;GAClB,UAAU;IACR,KAAK,aAAa,OAAO1M,CAAG;GAC9B;EACF,EAAA,CAAG;EAGH,OADA,KAAK,aAAa,IAAIA,GAAKyM,CAAW,GAC/BA;CACT;CAEA,aAAa,GAAyC;EACpD,KAAK,SAAS;GAAE,GAAG,KAAK;GAAQ,GAAGJ;EAAO;CAC5C;CAEA,WAIE;EACA,OAAO;GACL,iBAAiB,KAAK,gBAAgB;GACtC,WAAW,KAAK,UAAU;GAC1B,aAAa,KAAK,aAAa;EACjC;CACF;AACF,GC1HIM,WAAuD;AAM3D,SAAgBC,GACd,GACM;CACN,KAAyBC;AAC3B;AAMA,SAASC,GAAoB,GAA6C;CACxE,IAAMC,IAAIR;CACV,OACE,CAAC,CAACQ,KACF,MAAM,QAAQA,EAAE,KAAK,KACrB,OAAOA,EAAE,QAAS,YAClBA,EAAE,SAAS,QACX,OAAOA,EAAE,aAAc,YACvB,MAAM,QAAQA,EAAE,cAAc;AAElC;AAEA,SAASC,GAAc,GAAuC;CAC5D,IAAMD,IAAIR;CACV,OACE,CAAC,CAACQ,KACF,CAAC,CAACA,EAAE,UACJ,CAAC,CAACA,EAAE,gBACJ,OAAOA,EAAE,aAAc,YACvB,MAAM,QAAQA,EAAE,cAAc;AAElC;AAMA,IAAaE,KAAb,MAA0B;CACxB;CACA;CACA;CACA,QAAiC;EAC/B,MAAM;EACN,QAAQ;EACR,WAAW;EACX,QAAQ;CACV;CAEA,YAAY,GAA0B,GAAqC;EAGzE,AAFA,KAAK,SAASZ,GACd,KAAK,cAAc,IAAID,GAAYC,CAAM,GACzC,AAGE,KAAK,aAHHa,MAAe,KAAA,IACCP,GAAuBN,CAAM,IAE7Ba;CAEtB;CAEA,IAAI,UAAmB;EACrB,OAAO,KAAK,OAAO;CACrB;CAEA,YAA8B;EAC5B,OAAO,EAAE,GAAG,KAAK,OAAO;CAC1B;CAEA,MAAM,cACJ,GACA,GACsC;EACtC,IAAI,CAAC,KAAK,OAAO,SAAS,OAAO;EAEjC,IAAI;GACF,IAAMlO,IAAS,KAAK,YAAY,cAAc3C,GAAY8O,CAAU;GACpE,IAAInM,GAEF,OADA,KAAK,MAAM,QACJA;GAGT,IAAMmO,IAAa,MAAM,KAAK,YAAY,cAAc9Q,GAAY8O,CAAU,KAAM;GAQpF,OAPI2B,GAAoBK,CAAS,KAC/B,KAAK,YAAY,cAAc9Q,GAAY8O,GAAYgC,CAAS,GAChE,KAAK,MAAM,QACJA,MAGT,KAAK,MAAM,UACJ;EACT,SAASC,GAAO;GAMd,OALA,QAAQ,MACN,4CAA4C/Q,EAAW,IACvD+Q,CACF,GACA,KAAK,MAAM,UACJ;EACT;CACF;CAGA,MAAM,cACJ,GACA,GACA,GACsC;EACtC,IAAI,CAAC,KAAK,OAAO,SAAS,OAAO;EAEjC,IAAI;GACF,IAAMvN,IAAQ0M,EAAK,MAAM,KAAK,OAAO;IAAE,GAAGlE;IAAG,MAAM,EAAE,GAAGA,EAAE,KAAK;GAAE,EAAE,GAC7DgF,IAAOnC,GACX7O,GACA8O,GACAtL,EAAM,KAAK,MAAMwL,GAAiBhD,GAAG8C,CAAU,CAAC,CAClD,GACMnM,IAA+B;IAAE,GAAGuN;IAAM;IAAO;GAAK;GAG5D,OAFA,KAAK,YAAY,cAAclQ,GAAY8O,GAAYnM,CAAM,GAC7D,MAAM,KAAK,YAAY,cAAc3C,GAAY8O,GAAYnM,CAAM,GAC5DA;EACT,SAASoO,GAAO;GAMd,OALA,QAAQ,MACN,4CAA4C/Q,EAAW,IACvD+Q,CACF,GACA,KAAK,MAAM,UACJ;EACT;CACF;CAEA,MAAM,QACJ,GACA,GACgC;EAChC,IAAI,CAAC,KAAK,OAAO,SAAS,OAAO;EAEjC,IAAI;GACF,IAAMpO,IAAS,KAAK,YAAY,QAAQyC,GAAS0J,CAAU;GAC3D,IAAInM,GAEF,OADA,KAAK,MAAM,QACJA;GAGT,IAAMmO,IAAa,MAAM,KAAK,YAAY,QAAQ1L,GAAS0J,CAAU,KAAM;GAQ3E,OAPI6B,GAAcG,CAAS,KACzB,KAAK,YAAY,QAAQA,CAAS,GAClC,KAAK,MAAM,QACJA,MAGT,KAAK,MAAM,UACJ;EACT,SAASC,GAAO;GAGd,OAFA,QAAQ,MAAM,sCAAsC3L,EAAQ,IAAI2L,CAAK,GACrE,KAAK,MAAM,UACJ;EACT;CACF;CAGA,MAAM,QACJ,GACgC;EAChC,IAAI,CAAC,KAAK,OAAO,SAAS,OAAO;EAEjC,IAAI;GACF,IAAM9E,IAAwB;IAC5B,GAAGiE,EAAK;IACR,MAAM,EAAE,GAAGA,EAAK,OAAO,KAAK;IAC5B,GAAIA,EAAK,OAAO,aAAa,EAAE,WAAW,CAAC,GAAGA,EAAK,OAAO,SAAS,EAAE;GACvE,GACMvN,IAAyB;IAC7B,GAAGuN;IACH;IACA,MAAMlB,GAAiB/C,GAAQiE,EAAK,UAAU;GAChD;GAGA,OAFA,KAAK,YAAY,QAAQvN,CAAM,GAC/B,MAAM,KAAK,YAAY,QAAQA,CAAM,GAC9BA;EACT,SAASoO,GAAO;GAMd,OALA,QAAQ,MACN,sCAAsCb,EAAK,OAAO,QAAQ,IAC1Da,CACF,GACA,KAAK,MAAM,UACJ;EACT;CACF;CAEA,MAAM,kBAAkB,GAA2D;EACjF,IAAK,KAAK,OAAO,SACjB,KAAK,IAAM9R,KAAQuE,GACjB,MAAM,KAAK,QAAQvE,CAAI;CAE3B;CAEA,MAAM,UAAU,GAAiB,GAAmC;EAElE,AADA,KAAK,YAAY,UAAUmG,GAAS0J,CAAU,GAC9C,MAAM,KAAK,YAAY,UAAU1J,GAAS0J,CAAU;CACtD;CAGA,MAAM,gBAAgB,GAAmC;EAEvD,AADA,KAAK,YAAY,gBAAgB9O,CAAU,GAC3C,MAAM,KAAK,YAAY,gBAAgBA,CAAU;CACnD;CAEA,MAAM,WAA0B;EAE9B,AADA,KAAK,YAAY,SAAS,GAC1B,MAAM,KAAK,YAAY,SAAS;CAClC;CAEA,MAAM,gBACJ,GACA,GACY;EACZ,OAAO,KAAK,YAAY,gBAAgB2D,GAAK0M,CAAE;CACjD;CAGA,gBAAsB;EACpB,KAAK,MAAM;CACb;CAEA,aAAa,GAAyC;EAEpD,AADA,KAAK,SAAS;GAAE,GAAG,KAAK;GAAQ,GAAGL;EAAO,GAC1C,KAAK,YAAY,aAAa,KAAK,MAAM;CAC3C;CAEA,WAEE;EACA,OAAO;GACL,GAAG,KAAK;GACR,aAAa,KAAK,YAAY,SAAS;EACzC;CACF;CAEA,aAAmB;EACjB,KAAK,QAAQ;GACX,MAAM;GACN,QAAQ;GACR,WAAW;GACX,QAAQ;EACV;CACF;AACF,GC9OIiB,KAAoC;AAMxC,SAAgBC,IAAqC;CAInD,OAHA,AACED,OAAe,IAAIL,GAAaxB,GAAqB,CAAC,GAEjD6B;AACT;AAKA,SAAgBE,KAA+B;CAC7C,KAAe;AACjB;AAMA,SAAgBC,GACd,GACA,GACc;CACd,OAAO,IAAIR,GACT;EACE,GAAGxB,GAAqB;EACxB,GAAGY;CACL,GACAa,CACF;AACF;AC/CA,SAAgBQ,IAAqB;CACnC,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACrC;AAGA,SAAgBC,EAAa,GAA2B;CACtD,OAAOC,IAAA;AACT;AAOA,SAAgBC,GAAgB,GAAoB,GAA4B;CAC9E,OAAOF,EAAaC,CAAS,IAAIE,EAAM,YAAA;AACzC;AAEA,IAAMC,KAAa,MAAsC,GAAGC,EAAO,GAAG,GAAGA,EAAO;AAOhF,eAAsBC,GACpB,GACA,GACA,GACoE;CACpE,IAAI,CAACvI,EAAW,kBAAkB,OAAO;CACzC,IAAIwI,EAAsB,SAAS,GACjC,OAAO;EAAE,yBAAS,IAAI,IAAI;EAAG,gBAAgBJ,EAAM;CAAe;CAGpE,IAAMK,oBAAgB,IAAI,IAAsB,GAC1CC,oBAAe,IAAI,IAAsB,GACzCC,KAAS,GAA4B,GAAa,MAAoB;EAC1E,IAAMjM,IAAWlF,EAAI,IAAI4J,CAAG;EAC5B,AAAI1E,IAAUA,EAAS,KAAKX,CAAO,IAC9BvE,EAAI,IAAI4J,GAAK,CAACrF,CAAO,CAAC;CAC7B;CACA,KAAK,IAAM,CAACA,GAAS6M,MAASJ,GAAuB;EACnD,KAAK,IAAMpH,KAAOwH,EAAK,SAAS,EAAMH,GAAerH,GAAKrF,CAAO;EACjE,KAAK,IAAMqF,KAAOwH,EAAK,KAAK,EAAMF,GAActH,GAAKrF,CAAO;CAC9D;CAEA,IAAM8M,IAAU,MAAM7I,EAAW,iBAAiB;EAChD,SAAS,CAAC,GAAGyI,EAAc,KAAK,CAAC;EACjC,KAAK,CAAC,GAAGC,EAAa,KAAK,CAAC;EAC5B,OAAON,EAAM;CACf,CAAC,GAEKU,IAAO,IAAI,IAAIV,EAAM,cAAc,GACnCW,oBAAU,IAAI,IAAY;CAChC,KAAK,IAAMT,KAAUO,GACnB,IAAI,GAAK,IAAIR,EAAUC,CAAM,CAAC,GAC9B;OAAK,IAAMvM,KAAW0M,EAAc,IAAIH,EAAO,MAAM,KAAK,CAAC,GAAG,EAAQ,IAAIvM,CAAO;EACjF,KAAK,IAAMA,KAAW2M,EAAa,IAAIJ,EAAO,EAAE,KAAK,CAAC,GAAG,EAAQ,IAAIvM,CAAO;CADK;CAGnF,OAAO;EAAE;EAAS,gBAAgB8M,EAAQ,IAAIR,CAAS;CAAE;AAC3D;AAUA,eAAsBW,GACpB,GACA,GACiF;CACjF,IAAI,CAAChJ,EAAW,kBAAkB,OAAO;CACzC,IAAM+I,oBAAU,IAAI,IAAY,GAC1BE,oBAAiB,IAAI,IAAsB;CACjD,IAAIC,EAAO,SAAS,GAAG,OAAO;EAAE;EAAS;CAAe;CAExD,IAAMC,oBAAU,IAAI,IAAY,GAC1BC,oBAAM,IAAI,IAAY,GACxB9E,IAAQ;CACZ,KAAK,IAAM8D,KAASc,EAAO,OAAO,GAAG;EACnC,KAAK,IAAM9H,KAAOgH,EAAM,aAAa,SAAS,EAAQ,IAAIhH,CAAG;EAC7D,KAAK,IAAMA,KAAOgH,EAAM,aAAa,KAAK,EAAI,IAAIhH,CAAG;EACrD,IAAQ,KAAK,IAAIkD,GAAO8D,EAAM,SAAS;CACzC;CACA,IAAMS,IAAU,MAAM7I,EAAW,iBAAiB;EAChD,SAAS,CAAC,GAAGmJ,CAAO;EACpB,KAAK,CAAC,GAAGC,CAAG;EACZ;CACF,CAAC;CAED,KAAK,IAAM,CAACrN,GAASqM,MAAUc,GAAQ;EACrC,IAAMG,IAAO,IAAI,IAAIjB,EAAM,aAAa,OAAO,GACzCkB,IAAM,IAAI,IAAIlB,EAAM,aAAa,GAAG,GACpCU,IAAO,IAAI,IAAIV,EAAM,cAAc,GACnCmB,IAAiB,CAAC;EACxB,KAAK,IAAMjB,KAAUO,GACnB,AAAIP,EAAO,eAAeF,EAAM,aAAaE,EAAO,kBAAkBF,EAAM,cACvEiB,EAAK,IAAIf,EAAO,MAAM,KAAMgB,EAAI,IAAIhB,EAAO,EAAE,OAClDiB,EAAK,KAAKlB,EAAUC,CAAM,CAAC,GACtBQ,EAAK,IAAIT,EAAUC,CAAM,CAAC,KAAGS,EAAQ,IAAIhN,CAAO;EAEvD,EAAe,IAAIA,GAASwN,CAAI;CAClC;CACA,OAAO;EAAE;EAAS;CAAe;AACnC;;;ACtHA,IAAIC,IAAsC;AAM1C,SAAgBC,GAAyB,GAA+B;CACtE,IAAIC,EAAO,SAAS,SAClB,MAAU,MACR,wEACF;CAEF,IAAcA;AAChB;AAGA,SAAgBC,KAA8B;CAC5C,IAAc;AAChB;AAEA,SAAgBC,KAAwD;CACtE,OAAOJ;AACT;AAEA,SAAgBK,KAA+B;CAC7C,OAAOL,KAAe;AACxB;;;ACVA,SAAgBM,EACd,IAAwB,UACH;CACrB,IAAIC,MAAS,UACX,OAAO;EACL,MAAM;EACN,YAAY/M,EAAyB;EACrC,eAAe;CACjB;CAGF,IAAMrD,IAAQiQ,GAA8B;CAE5C,IAAIG,MAAS,SAAS;EACpB,IAAI,CAACpQ,GACH,MAAU,MACR,sFACF;EAEF,OAAO;GACL,MAAM;GACN,YAAYA;GACZ,eAAe;EACjB;CACF;CAUA,OAPIA,IACK;EACL,MAAM;EACN,YAAYA;EACZ,eAAe;CACjB,IAEK;EACL,MAAM;EACN,YAAYqD,EAAyB;EACrC,eAAe;CACjB;AACF;AAEA,SAAgBgN,EACd,GACiB;CACjB,OAAON,KAAU;AACnB;;;ACzBA,IAAMO,IAAoC;CAAE,SAAS,CAAC;CAAG,KAAK,CAAC;AAAE;AAEjE,SAASC,EACP,GACA,GACS;CAGT,OAFI,CAACC,KACDjQ,GAAS,UAAU,KAAc,KAC9B2N,EAAqB,CAAC,CAAC;AAChC;AAEA,SAASuC,GAAe,GAA6C;CACnE,OAAOC,MAAY,oBAAoBA,MAAY;AACrD;AAEA,SAASC,GAAU,GAA6C;CAC9D,OAAOD,MAAY;AACrB;AAOA,eAAeE,GACb,GACA,GACA,GACA,GACA,GACoB;CAKpB,OAAOpI,EAA8BxL,GAAY,MAJ7BqJ,EAAW,sBAAsBrJ,GAAY;EAC/D;EACA;CACF,CAAC,GACuDuD,GAAS8F,CAAU;AAC7E;AAKA,eAAewK,GACb,GACA,GACA,GACwF;CACxF,IAAMC,IAAY,MAAMC,EAAI1K,CAAU;CACtC,IAAI+J,MAAS,UAAU/J,EAAW,SAAS,SACzC,OAAO;EACL;EACA;EACA,eAAeA,EAAW,SAAS;CACrC;CAEF,IAAIyK,EAAU,QAAQ,SAAS,GAC7B,OAAO;EAAE;EAAW;EAAY,eAAe;CAAM;CAEvD,IAAME,IAAS3N,EAAyB;CACxC,OAAO;EAAE,WAAW,MAAM0N,EAAIC,CAAM;EAAG,YAAYA;EAAQ,eAAe;CAAK;AACjF;AAGA,eAAeC,EACb,GACA,GACA,GACA,IAA2B,CAAC,GACb;CACf,MAAM/C,EAAqB,CAAC,CAAC,kBAC3B4C,EAAU,QAAQ,KAAK,OAAY;EACjC;EACA;EACA,cAAcA,EAAU,aAAa,IAAI7H,EAAO,OAAO,KAAKqH;EAC5D,WAAWhC,EAAaC,CAAS;EACjC;EACA,aAAaA;CACf,EAAE,CACJ;AACF;AAQA,eAAe2C,GACb,GACA,GACA,GACA,GACA,GAC8B;CAC9B,IAAMC,IAAQjD,EAAqB,GAC7BK,IAAYF,EAAW,GACvB1O,IAAS,MAAMwR,EAAM,cAAcnU,GAAY8O,CAAU,GACzDsF,IAAS,MAAM/K,EAAW,sBAAsBrJ,GAAY;EAAE;EAAO,MAAM;CAAE,CAAC,GAE9EqU,IAAkB,IAAI,IAAI1R,GAAQ,MAAM,KAAK,MAAS,CAAC1D,EAAK,SAASA,CAAI,CAAC,KAAK,CAAC,CAAC,GACnFmT,oBAAU,IAAI,IAAY,GAC1BE,IAA2B,CAAC;CAChC,IAAI3P,GAAQ;EACV,IAAM2R,oBAAU,IAAI,IAA8B;EAClD,KAAK,IAAMpP,KAAQkP,GAAQ;GACzB,IAAMG,IAAO5R,EAAO,KAAKuC,EAAK;GAC9B,AAAImP,EAAgB,IAAInP,EAAK,EAAE,KAAGoP,EAAQ,IAAIpP,EAAK,IAAIqP,GAAM,gBAAgBjB,CAAe;EAC9F;EACA,IAAMkB,IAAQ,MAAM5C,GAAiBvI,GAAYiL,GAAS3R,CAAM;EAChE,AAAI6R,KACF,IAAUA,EAAM,SAChB,IAAiBA,EAAM,kBAEvB,IAAU,IAAI,IAAIF,EAAQ,KAAK,CAAC;CAEpC;CAEA,IAAMG,IAAaL,EAAO,QAAQ,MAAS,CAACC,EAAgB,IAAInP,EAAK,EAAE,KAAKkN,EAAQ,IAAIlN,EAAK,EAAE,CAAC,GAC1FwP,IACJD,EAAW,SAAS,IAChB,MAAMjJ,EAA8BxL,GAAYyU,GAAYlR,GAAS8F,CAAU,IAC/E;EAAE,SAAS,CAAC;EAAG,8BAAc,IAAI,IAA8B;CAAE,GACjEsL,IAAiB,IAAI,IAAID,EAAM,QAAQ,KAAK,MAAW,CAACzI,EAAO,SAASA,CAAM,CAAC,CAAC,GAIhFzI,IAAsB,CAAC,GACvB+Q,IAAyC,CAAC;CAChD,KAAK,IAAMrP,KAAQkP,GAAQ;EACzB,IAAMnI,IAAS0I,EAAe,IAAIzP,EAAK,EAAE;EACzC,AAAI+G,KACFzI,EAAM,KAAKyI,CAAM,GACjB,EAAK/G,EAAK,MAAM;GACd,cAAcwP,EAAM,aAAa,IAAIxP,EAAK,EAAE,KAAKoO;GACjD,SAAS/B;EACX,KACS5O,KAAU,CAACyP,EAAQ,IAAIlN,EAAK,EAAE,KAAKmP,EAAgB,IAAInP,EAAK,EAAE,MACvE1B,EAAM,KAAK6Q,EAAgB,IAAInP,EAAK,EAAE,CAAE,GACxC,EAAKA,EAAK,MAAMvC,EAAO,KAAKuC,EAAK,OAAO;GAAE,cAAcoO;GAAiB,SAAS/B;EAAU;CAEhG;CAEA,IAAMqD,IACJ,CAAC,CAACjS,KACF+R,EAAM,QAAQ,WAAW,KACzBlR,EAAM,WAAWb,EAAO,MAAM,UAC9Ba,EAAM,OAAO,GAAM,MAAMvE,MAAS0D,EAAO,MAAMsB,EAAE;CACnD,IAAItB,KAAUiS,KAAa,CAACpD,GAAgB7O,GAAQ4O,CAAS,GAC3D,OAAO;EAAE;EAAO;EAAO,MAAM;EAAG,MAAM5O,EAAO;CAAK;CAEpD,AAAIA,KAAQwR,EAAM,cAAc;CAEhC,IAAMU,IAAS,MAAMV,EAAM,cAAcnU,GAAY8O,GAAY;EAC/D;EACA;EACA,WAAWwC,EAAaC,CAAS;EACjC;EACA,aAAa5O,GAAQ,eAAe4O;CACtC,CAAC;CAGD,OAFA,MAAM0C,EAAsBS,GAAO5F,GAAYyC,GAAWe,CAAc,GAEjE;EAAE,OAAOuC,IAAS,CAAC,GAAGA,EAAO,KAAK,IAAIrR;EAAO;EAAO,MAAM;EAAG,MAAMqR,GAAQ;CAAK;AACzF;AAGA,IAAMC,KAA4B;AAMlC,SAAgBC,GAAmB,GAA+B;CAChE,IAAMC,IAAMC,EAAO,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,OAAO,EAAE;CAGzD,OAFID,EAAI,SAASF,MAA6BE,EAAI,SAAS,MACvD,CAAC,cAAc,KAAKA,CAAG,IAAU,OAC9B,KAAKA;AACd;AAEA,eAAsBE,GACpB,GACA,GAC8B;CAC9B,MAAMhX,EAAwB;CAC9B,IAAMkF,IAAQG,GAAS,SAAS,KAC1B4R,IAAO5R,GAAS,QAAQ,GACxB6P,IAAOC,EAAoB9P,GAAS,MAAM,GAC1CiH,IAAW2I,EAAmBC,CAAI,GAClCtE,IAAasG,EAAwB7R,CAAO,GAE9C8R,IAA2B;CAC/B,IAAI9R,GAAS,cAAc,KAAA,MACzB,IAAYwR,GAAmBxR,EAAQ,SAAS,GAC5C,CAAC8R,IAAW,OAAO;EAAE,OAAO,CAAC;EAAG;EAAO;CAAK;CAGlD,IAAMC,IAAc,OAAO,MACpBD,IAEE7J,EAA8BxL,GAAY,MAD7BuV,EAAG,qBAAqBvV,GAAYqV,GAAW;EAAE;EAAO;CAAK,CAAC,GAC1B9R,GAASgS,CAAE,IAF5C3B,GAAiB5T,GAAYoD,GAAO+R,GAAM5R,GAASgS,CAAE;CAM9E,IACE,CAACF,KACD9B,EAAehQ,GAASiH,EAAS,aAAa,KAC9C2K,MAAS,KACT3K,EAAS,WAAW,SAAS,UAC7B;EACA,IAAMgL,IAAU,GAAGxV,EAAW,IAAI8O,EAAW,IAAI1L;EACjD,OAAO8N,EAAqB,CAAC,CAAC,gBAAgBsE,SAC5CtB,GAAkBlU,GAAYoD,GAAOG,GAASuL,GAAYtE,EAAS,UAAU,CAC/E;CACF;CAEA,IAAM+G,IAAYF,EAAW,GACvB,EACJ,cACA,YAAYoE,GACZ,qBACE,MAAM5B,GAA8BT,GAAM5I,EAAS,aAAa,MAClE8K,EAAYC,CAAE,CAChB;CAKA,OAHIhC,EAAehQ,GAASmS,CAAa,KAAKD,EAAK,SAAS,YAC1D,MAAMxB,EAAsBH,GAAWhF,GAAYyC,CAAS,GAEvD;EAAE,OAAOuC,EAAU;EAAS;EAAO;CAAK;AACjD;AAOA,eAAe6B,GACb,GACA,GACqC;CACrC,IAAMxB,IAAQjD,EAAqB,GAC7BmD,oBAAkB,IAAI,IAA4B;CACxD,MAAM,QAAQ,IACZuB,EAAS,IAAI,OAAO,EAAE,YAAS,oBAAiB;EAC9C,IAAMjT,IAAS,MAAMwR,EAAM,QAAQ/O,GAAS0J,CAAU;EACtD,AAAInM,KAAQ0R,EAAgB,IAAIjP,GAASzC,CAAM;CACjD,CAAC,CACH;CACA,IAAMkT,oBAAO,IAAI,IAA2B;CAC5C,IAAIxB,EAAgB,SAAS,GAAG,OAAOwB;CAEvC,IAAMtE,IAAYF,EAAW,GACvBkB,oBAAS,IAAI,IAA6B;CAChD,KAAK,IAAM,CAACnN,GAASzC,MAAW0R,GAAiB,EAAO,IAAIjP,GAASzC,CAAM;CAC3E,IAAM6R,IAAQ,MAAMnC,GAAiBhJ,GAAYkJ,CAAM;CACvD,KAAK,IAAM,CAACnN,GAASzC,MAAW0R,GAC9B,AAAI,CAACG,KAASA,EAAM,QAAQ,IAAIpP,CAAO,IACrC,MAAM+O,EAAM,UAAU/O,GAASzC,EAAO,UAAU,KAG9C6O,GAAgB7O,GAAQ4O,CAAS,KACnC,MAAM4C,EAAM,QAAQ;EAClB,GAAGxR;EACH,WAAW2O,EAAaC,CAAS;EACjC,gBAAgBiD,EAAM,eAAe,IAAIpP,CAAO,KAAK,CAAC;CACxD,CAAC,GAEHyQ,EAAK,IAAIzQ,GAASzC,EAAO,MAAM;CAEjC,OAAOkT;AACT;AAEA,eAAeC,GACb,GACA,GACA,GAC+B;CAE/B,QAAO,MADYH,GAAwB,CAAC;EAAE;EAAS;CAAW,CAAC,GAAGtM,CAAU,EAAA,CACpE,IAAIjE,CAAO,KAAK;AAC9B;AAGA,SAAS2Q,GAAM,GAAyD;CACtE,IAAIxS,GAAS,eAAe,KAAA,KAAaA,GAAS,SAAS,KAAA,GAC3D,OAAO;EAAE,YAAYA,EAAQ;EAAY,MAAMA,EAAQ;CAAK;AAC9D;AAEA,eAAsByS,GACpB,GACA,GAC+B;CAE/B,IADA,MAAM9X,EAAwB,GAC1B,CAACkH,KAAW,OAAOA,KAAY,YAAYA,EAAQ,KAAK,MAAM,IAChE,OAAO;CAGT,IAAM6Q,IAAU7Q,EAAQ,KAAK,GACvBsO,IAAUnQ,GAAS,WAAW,QAC9B6P,IAAOC,EAAoB9P,GAAS,MAAM,GAC1CiH,IAAW2I,EAAmBC,CAAI,GAClCtE,IAAasG,EAAwB7R,CAAO,GAE9C8F,IAAamB,EAAS,YACtBgJ,IAAahJ,EAAS;CAE1B,IAAI+I,EAAehQ,GAASiQ,CAAU,KAAKnK,EAAW,SAAS,UAAU;EACvE,IAAM1G,IAAS,MAAMmT,GAAuBG,GAASnH,GAAYzF,CAAU;EAC3E,IAAI1G,GAAQ,OAAOA;CACrB;CAIA,IAAMuT,KAAwB,MAC5B,QAAQ,IAAI,CACVX,EAAG,aAAaU,CAAO,GACvBV,EAAG,oBAAoB,CAACU,CAAO,GAAG,EAAE,gBAAgB,GAAK,CAAC,CAC5D,CAAC,GAEG1E,IAAYF,EAAW,GACzB,CAACnM,GAAM0D,KAAY,MAAMsN,EAAqB7M,CAAU;CAG5D,IAAI,CAACnE,KAAQkO,MAAS,UAAU/J,EAAW,SAAS,SAAS;EAG3D,IAFA,IAAahD,EAAyB,GACtC,IAAa,IACTkN,EAAehQ,GAASiQ,CAAU,GAAG;GACvC,IAAM7Q,IAAS,MAAMmT,GAAuBG,GAASnH,GAAYzF,CAAU;GAC3E,IAAI1G,GAAQ,OAAOA;EACrB;EACC,CAACuC,GAAM0D,KAAY,MAAMsN,EAAqB7M,CAAU;CAC3D;CAEA,IAAI,CAACnE,GAAM,OAAO;CAElB,IAAMlF,IAAakF,EAAK,QAAQ,cAAc,EAAE,EAAE;CAClD,IAAI,CAAClF,GAAY,OAAO;CAExB,IAAI8H,IAA+B,MAC/BqO,IAAiC;EAAE,SAAS,CAACF,CAAO;EAAG,KAAK,CAACA,CAAO;CAAE,GAEpE1N,IAAMwN,GAAMxS,CAAO,GACnB6S,IAAe,YAAwC;EAC3D,IAAMtC,IAAY,MAAMrI,EAAoB,CAACvG,CAAI,GAAG3B,GAAS8F,GAAY;GACvE;GACA;GACA,MAAMd,qBAAO,IAAI,IAAI,CAAC,CAAC0N,GAAS1N,CAAG,CAAC,CAAC;EACvC,CAAC,GACK0D,IAAS6H,EAAU,QAAQ;EAEjC,OADI7H,MAAQ,IAAe6H,EAAU,aAAa,IAAI7H,EAAO,OAAO,KAAKkK,IAClElK,KAAU;CACnB;CAEA,IAAI,CAACwH,GAAeC,CAAO,GACzB,IAAS,MAAM0C,EAAa;MACvB;EACL,IAAM,EAAE,qBAAkB,iBAAc,MAAMvI,GAC5CoI,GACA1S,GACA8F,CACF;EAEA,IAAIsK,GAAUD,CAAO,GAAG;GACtB,IAAMzH,IAAS,MAAMmK,EAAa;GAClC,IAASnK,IAAS;IAAE,GAAGA;IAAQ;GAAU,IAAI;EAC/C,OAUE,AATA,IAAS;GACP,SAASgK;GACT;GACA,UAAU/Q,EAAK;GACf,aAAaA,EAAK;GAClB,YAAY+I;GACZ,MAAM,CAAC;GACP;EACF,GACIA,KAAkBkI,EAAa,QAAQ,KAAKlI,CAAgB;EAGlE,KAAK,IAAMoI,KAASnI,GAAW,EAAa,QAAQ,KAAKmI,EAAM,UAAU;EACzE,IAAe;GACb,SAAS,CAAC,GAAG,IAAI,IAAIF,EAAa,OAAO,CAAC;GAC1C,KAAKA,EAAa;EACpB;CACF;CAEA,IACErO,KACAyL,EAAehQ,GAASiQ,CAAU,KAClCnK,EAAW,SAAS,UACpB;EACA,IAAMwL,IAAS,MAAM3D,EAAqB,CAAC,CAAC,QAAQ;GAClD,QAAQpJ;GACR;GACA;GACA,WAAWwJ,EAAaC,CAAS;GACjC,gBAAgB,CAAC;GACjB,aAAaA;EACf,CAAC;EAED,AAAIsD,MAAQ,IAASA,EAAO;CAC9B;CAEA,OAAO/M;AACT;AASA,eAAsBwO,GACpB,GACA,GACkC;CAClC,MAAMpY,EAAwB;CAG9B,IAAMqY,oBAAa,IAAI,IAAoB;CAC3C,KAAK,IAAMC,KAASzQ,GAAU;EAC5B,IAAI,OAAOyQ,KAAU,YAAYA,EAAM,KAAK,MAAM,IAAI;EACtD,IAAM/L,IAAM+L,EAAM,KAAK,CAAC,CAAC,YAAY;EACrC,AAAKD,EAAW,IAAI9L,CAAG,KAAG8L,EAAW,IAAI9L,GAAK+L,EAAM,KAAK,CAAC;CAC5D;CACA,IAAMrN,IAAY,CAAC,GAAGoN,EAAW,KAAK,CAAC;CACvC,IAAIpN,EAAU,WAAW,GAAG,uBAAO,IAAI,IAAI;CAE3C,IAAMX,oBAAO,IAAI,IAAwB;CACzC,KAAK,IAAM,CAACiC,GAAKlC,MAAQhF,GAAS,QAAQ,CAAC,GAAG;EAC5C,IAAM+E,IAASyN,GAAMxN,CAAG;EACxB,AAAID,KAAQE,EAAK,IAAIiC,EAAI,KAAK,CAAC,CAAC,YAAY,GAAGnC,CAAM;CACvD;CACA,IAAMmO,KAAiB,MACrBrB,EAAwB;EAAE,GAAG7R;EAAS,GAAGiF,EAAK,IAAIpD,CAAO;CAAE,CAAC,GAExDgO,IAAOC,EAAoB9P,GAAS,MAAM,GAC1CiH,IAAW2I,EAAmBC,CAAI,GAClCoB,oBAAQ,IAAI,IAAwB,GAGpCkC,IAAW,OACf,GACA,GACA,MACsB;EACtB,IAAMC,IAAWpD,EAAehQ,GAASiQ,CAAU,KAAKnK,EAAW,SAAS,UACxEuN,IAAU1Q;EACd,IAAIyQ,GAAU;GACZ,IAAMd,IAAO,MAAMF,GACjBzP,EAAK,KAAK,OAAa;IAAE;IAAS,YAAYuQ,EAAcrR,CAAO;GAAE,EAAE,GACvEiE,CACF;GACA,KAAK,IAAM,CAACjE,GAAS6G,MAAW4J,GAAM,EAAM,IAAIzQ,GAAS6G,CAAM;GAC/D,IAAU/F,EAAK,QAAQ,MAAQ,CAAC2P,EAAK,IAAIpL,CAAG,CAAC;EAC/C;EACA,IAAImM,EAAQ,WAAW,GAAG,OAAO,CAAC;EAElC,IAAMrF,IAAYF,EAAW,GACvB,CAACpI,GAAOL,KAAY,MAAM,QAAQ,IAAI,CAC1CS,EAAW,eAAeuN,CAAO,GACjCvN,EAAW,oBAAoBuN,GAAS,EAAE,gBAAgB,GAAK,CAAC,CAClE,CAAC,GACKC,IAAY,IAAI,IAAI5N,EAAM,KAAK,MAAS,CAAC/D,EAAK,GAAG,YAAY,GAAGA,CAAI,CAAC,CAAC,GACtE4R,IAAUF,EAAQ,QAAQ,MAAQ,CAACC,EAAU,IAAIpM,CAAG,CAAC,GAMrDqJ,IAAY,MAAMrI,EAJLmL,EAChB,KAAK,MAAQC,EAAU,IAAIpM,CAAG,CAAC,CAAC,CAChC,QAAQ,MAAkC,CAAC,CAACvF,GAAM,QAAQ,cAAc,EAAE,EAAE,IAEnC,GAAY3B,GAAS8F,GAAY;GAC3E;GACA;EACF,CAAC;EACD,KAAK,IAAM4C,KAAU6H,EAAU,SAAS;GACtC,IAAIhM,IAAqBmE;GACzB,IAAI0K,GAAU;IACZ,IAAM9B,IAAS,MAAM3D,EAAqB,CAAC,CAAC,QAAQ;KAClD;KACA,YAAYuF,EAAcxK,EAAO,QAAQ,YAAY,CAAC;KACtD,cAAc6H,EAAU,aAAa,IAAI7H,EAAO,OAAO,KAAK;MAC1D,SAAS,CAACA,EAAO,OAAO;MACxB,KAAK,CAACA,EAAO,OAAO;KACtB;KACA,WAAWqF,EAAaC,CAAS;KACjC,gBAAgB,CAAC;KACjB,aAAaA;IACf,CAAC;IAED,AAAIsD,MAAQ,IAASA,EAAO;GAC9B;GACA,EAAM,IAAI5I,EAAO,QAAQ,YAAY,GAAGnE,CAAM;EAChD;EACA,OAAOgP;CACT,GAEMA,IAAU,MAAMJ,EAASlM,EAAS,YAAYA,EAAS,eAAerB,CAAS;CAErF,AAAI2N,EAAQ,SAAS,KAAK1D,MAAS,UAAU5I,EAAS,WAAW,SAAS,WACxE,MAAMkM,EAASrQ,EAAyB,GAAG,IAAMyQ,CAAO;CAG1D,IAAMhP,oBAAS,IAAI,IAAwB;CAC3C,KAAK,IAAM,CAAC2C,GAAK+L,MAAUD,GAAY;EACrC,IAAMtK,IAASuI,EAAM,IAAI/J,CAAG;EAC5B,AAAIwB,KAAQnE,EAAO,IAAI0O,GAAOvK,CAAM;CACtC;CACA,OAAOnE;AACT;AAMA,eAAsBiP,GACpB,GACA,GACA,GACA,GACuB;CACvB,MAAM7Y,EAAwB;CAC9B,IAAMkV,IAAOC,EAAoB9P,GAAS,MAAM,GAC1CiH,IAAW2I,EAAmBC,CAAI,GAElCW,IAAM,OAAO,MAMVvI,EAA8BxL,GAAY,MAL7BuV,EAAG,8BACrBvV,GACA8E,GACAC,CACF,GACwDxB,GAASgS,CAAE,GAG/DhE,IAAYF,EAAW,GACvB,EAAE,cAAW,YAAYoE,GAAM,qBACnC,MAAM5B,GAA8BT,GAAM5I,EAAS,YAAYuJ,CAAG;CAMpE,OAJIR,EAAehQ,GAASmS,CAAa,KAAKD,EAAK,SAAS,YAC1D,MAAMxB,EAAsBH,GAAWsB,EAAwB7R,CAAO,GAAGgO,CAAS,GAG7EuC,EAAU;AACnB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seedprotocol/query",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.7-next.988.g7046e66",
|
|
4
4
|
"description": "Read canonical Seed Protocol JSON (seeds, collections, changelogs) from EAS attestations or a local SQLite source, with memory and disk caching",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"seed-protocol",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@noble/hashes": "^1.8.0",
|
|
56
|
-
"@seedprotocol/arweave": "0.7.
|
|
57
|
-
"@seedprotocol/eas": "0.7.
|
|
56
|
+
"@seedprotocol/arweave": "0.7.7-next.988.g7046e66",
|
|
57
|
+
"@seedprotocol/eas": "0.7.7-next.988.g7046e66",
|
|
58
58
|
"graphql-request": "^7.3.5",
|
|
59
59
|
"pluralize": "^8.0.0"
|
|
60
60
|
},
|