UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

1 lines • 5.51 kB
{"version":3,"file":"health-tree.cjs","sources":["../../../src/collection/health-tree.ts"],"sourcesContent":["import { getCollectionBuilder } from '../query/live/collection-registry.js'\nimport type { HealthNode } from '../types'\nimport type { CollectionImpl } from './index.js'\n\n/** A Collection that another Collection reads, under its query alias. */\nexport interface HealthSource {\n readonly alias: string\n /** Tells apart two sources under one alias, such as two includes. */\n readonly id?: string\n readonly collection: CollectionImpl<any, any, any, any, any>\n readonly kind?: HealthNode[`kind`]\n}\n\n// One cached node per Collection and source. A node keeps its identity until\n// its own fields or one of its children change, so a change replaces only the\n// nodes on its path and readers can compare nodes with `===`.\nconst nodeCache = new WeakMap<object, Map<string, HealthNode>>()\n\n/**\n * Build the health tree for a Collection. A base Collection is one node. A live\n * query is a node with one child per source alias, in query order, and each\n * child that is itself a live query recurses. The tree is read from current\n * state, so every node mirrors its Collection at the moment it is read.\n */\nexport function buildHealthTree(\n collection: CollectionImpl<any, any, any, any, any>,\n { alias, id, kind }: Omit<HealthSource, `collection`> = {\n alias: `root`,\n },\n // The reader that caches this node, so a source's node lives only as long\n // as the query that reads it.\n owner: object = collection,\n): HealthNode {\n // A live query's tree shape comes from its query definition.\n const builder = getCollectionBuilder(collection)\n const sources = builder?.healthSources() ?? []\n const { failureReason, error } = collection._lifecycle.problems\n const children = sources.map((source) =>\n buildHealthTree(source.collection, source, collection),\n )\n return healthNode(owner, id, {\n alias,\n collectionId: collection.id,\n kind: kind ?? (builder ? `live-query` : `source`),\n status: collection.status,\n failureReason,\n error,\n reloading: collection._lifecycle.reloading,\n sources: children,\n })\n}\n\n/**\n * A node from its own facts and its children. It has errors when it or\n * anything below it has a `failureReason` or an `error`.\n */\nexport function healthNode(\n owner: object,\n id: string | undefined,\n fields: Omit<HealthNode, `hasErrors`>,\n): HealthNode {\n const { failureReason, error, sources } = fields\n return cachedNode(owner, id ?? fields.alias, {\n ...fields,\n hasErrors:\n failureReason !== null ||\n error !== null ||\n sources.some((child) => child.hasErrors),\n })\n}\n\n/**\n * Every node in a health tree that shows a problem of its own, in tree order:\n * a `failureReason` or an `error`. A node whose only problems are below it is\n * not listed; its descendants are.\n */\nexport function findProblems(health: HealthNode): Array<HealthNode> {\n if (!health.hasErrors) return []\n const ownProblem = health.failureReason !== null || health.error !== null\n return [\n ...(ownProblem ? [health] : []),\n ...health.sources.flatMap(findProblems),\n ]\n}\n\n/** Return the cached node for this Collection and alias if nothing changed. */\nfunction cachedNode(owner: object, key: string, next: HealthNode): HealthNode {\n let nodes = nodeCache.get(owner)\n if (!nodes) nodeCache.set(owner, (nodes = new Map()))\n const previous = nodes.get(key)\n if (previous && sameNode(previous, next)) return previous\n nodes.set(key, next)\n return next\n}\n\nfunction sameNode(a: HealthNode, b: HealthNode): boolean {\n return (\n a.collectionId === b.collectionId &&\n a.kind === b.kind &&\n a.status === b.status &&\n a.hasErrors === b.hasErrors &&\n a.failureReason === b.failureReason &&\n a.error === b.error &&\n a.reloading === b.reloading &&\n a.sources.length === b.sources.length &&\n a.sources.every((source, index) => source === b.sources[index])\n )\n}\n"],"names":["getCollectionBuilder"],"mappings":";;;AAgBA,MAAM,gCAAgB,QAAA;AAQf,SAAS,gBACd,YACA,EAAE,OAAO,IAAI,SAA2C;AAAA,EACtD,OAAO;AACT,GAGA,QAAgB,YACJ;AAEZ,QAAM,UAAUA,mBAAAA,qBAAqB,UAAU;AAC/C,QAAM,UAAU,SAAS,cAAA,KAAmB,CAAA;AAC5C,QAAM,EAAE,eAAe,MAAA,IAAU,WAAW,WAAW;AACvD,QAAM,WAAW,QAAQ;AAAA,IAAI,CAAC,WAC5B,gBAAgB,OAAO,YAAY,QAAQ,UAAU;AAAA,EAAA;AAEvD,SAAO,WAAW,OAAO,IAAI;AAAA,IAC3B;AAAA,IACA,cAAc,WAAW;AAAA,IACzB,MAAM,SAAS,UAAU,eAAe;AAAA,IACxC,QAAQ,WAAW;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW,WAAW,WAAW;AAAA,IACjC,SAAS;AAAA,EAAA,CACV;AACH;AAMO,SAAS,WACd,OACA,IACA,QACY;AACZ,QAAM,EAAE,eAAe,OAAO,QAAA,IAAY;AAC1C,SAAO,WAAW,OAAO,MAAM,OAAO,OAAO;AAAA,IAC3C,GAAG;AAAA,IACH,WACE,kBAAkB,QAClB,UAAU,QACV,QAAQ,KAAK,CAAC,UAAU,MAAM,SAAS;AAAA,EAAA,CAC1C;AACH;AAOO,SAAS,aAAa,QAAuC;AAClE,MAAI,CAAC,OAAO,UAAW,QAAO,CAAA;AAC9B,QAAM,aAAa,OAAO,kBAAkB,QAAQ,OAAO,UAAU;AACrE,SAAO;AAAA,IACL,GAAI,aAAa,CAAC,MAAM,IAAI,CAAA;AAAA,IAC5B,GAAG,OAAO,QAAQ,QAAQ,YAAY;AAAA,EAAA;AAE1C;AAGA,SAAS,WAAW,OAAe,KAAa,MAA8B;AAC5E,MAAI,QAAQ,UAAU,IAAI,KAAK;AAC/B,MAAI,CAAC,MAAO,WAAU,IAAI,OAAQ,QAAQ,oBAAI,KAAM;AACpD,QAAM,WAAW,MAAM,IAAI,GAAG;AAC9B,MAAI,YAAY,SAAS,UAAU,IAAI,EAAG,QAAO;AACjD,QAAM,IAAI,KAAK,IAAI;AACnB,SAAO;AACT;AAEA,SAAS,SAAS,GAAe,GAAwB;AACvD,SACE,EAAE,iBAAiB,EAAE,gBACrB,EAAE,SAAS,EAAE,QACb,EAAE,WAAW,EAAE,UACf,EAAE,cAAc,EAAE,aAClB,EAAE,kBAAkB,EAAE,iBACtB,EAAE,UAAU,EAAE,SACd,EAAE,cAAc,EAAE,aAClB,EAAE,QAAQ,WAAW,EAAE,QAAQ,UAC/B,EAAE,QAAQ,MAAM,CAAC,QAAQ,UAAU,WAAW,EAAE,QAAQ,KAAK,CAAC;AAElE;;;;"}