@tldraw/store
Version:
tldraw infinite canvas SDK (store).
8 lines (7 loc) • 3.74 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/lib/executeQuery.ts"],
"sourcesContent": ["import { IdOf, UnknownRecord } from './BaseRecord'\nimport { intersectSets } from './setUtils'\nimport { StoreQueries } from './StoreQueries'\n\n/** @public */\nexport type QueryValueMatcher<T> = { eq: T } | { neq: T } | { gt: number }\n\n/** @public */\nexport type QueryExpression<R extends object> = {\n\t[k in keyof R & string]?: QueryValueMatcher<R[k]>\n\t// todo: handle nesting\n\t// | (R[k] extends object ? { match: QueryExpression<R[k]> } : never)\n}\n\nexport function objectMatchesQuery<T extends object>(query: QueryExpression<T>, object: T) {\n\tfor (const [key, _matcher] of Object.entries(query)) {\n\t\tconst matcher = _matcher as QueryValueMatcher<T>\n\t\tconst value = object[key as keyof T]\n\t\t// if you add matching logic here, make sure you also update executeQuery,\n\t\t// where initial data is pulled out of the indexes, since that requires different\n\t\t// matching logic\n\t\tif ('eq' in matcher && value !== matcher.eq) return false\n\t\tif ('neq' in matcher && value === matcher.neq) return false\n\t\tif ('gt' in matcher && (typeof value !== 'number' || value <= matcher.gt)) return false\n\t}\n\treturn true\n}\n\nexport function executeQuery<R extends UnknownRecord, TypeName extends R['typeName']>(\n\tstore: StoreQueries<R>,\n\ttypeName: TypeName,\n\tquery: QueryExpression<Extract<R, { typeName: TypeName }>>\n): Set<IdOf<Extract<R, { typeName: TypeName }>>> {\n\tconst matchIds = Object.fromEntries(Object.keys(query).map((key) => [key, new Set()]))\n\n\tfor (const [k, matcher] of Object.entries(query)) {\n\t\tif ('eq' in matcher) {\n\t\t\tconst index = store.index(typeName, k as any)\n\t\t\tconst ids = index.get().get(matcher.eq)\n\t\t\tif (ids) {\n\t\t\t\tfor (const id of ids) {\n\t\t\t\t\tmatchIds[k].add(id)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ('neq' in matcher) {\n\t\t\tconst index = store.index(typeName, k as any)\n\t\t\tfor (const [value, ids] of index.get()) {\n\t\t\t\tif (value !== matcher.neq) {\n\t\t\t\t\tfor (const id of ids) {\n\t\t\t\t\t\tmatchIds[k].add(id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ('gt' in matcher) {\n\t\t\tconst index = store.index(typeName, k as any)\n\t\t\tfor (const [value, ids] of index.get()) {\n\t\t\t\tif (value > matcher.gt) {\n\t\t\t\t\tfor (const id of ids) {\n\t\t\t\t\t\tmatchIds[k].add(id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn intersectSets(Object.values(matchIds)) as Set<IdOf<Extract<R, { typeName: TypeName }>>>\n}\n"],
"mappings": "AACA,SAAS,qBAAqB;AAavB,SAAS,mBAAqC,OAA2B,QAAW;AAC1F,aAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,KAAK,GAAG;AACpD,UAAM,UAAU;AAChB,UAAM,QAAQ,OAAO,GAAc;AAInC,QAAI,QAAQ,WAAW,UAAU,QAAQ,GAAI,QAAO;AACpD,QAAI,SAAS,WAAW,UAAU,QAAQ,IAAK,QAAO;AACtD,QAAI,QAAQ,YAAY,OAAO,UAAU,YAAY,SAAS,QAAQ,IAAK,QAAO;AAAA,EACnF;AACA,SAAO;AACR;AAEO,SAAS,aACf,OACA,UACA,OACgD;AAChD,QAAM,WAAW,OAAO,YAAY,OAAO,KAAK,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,oBAAI,IAAI,CAAC,CAAC,CAAC;AAErF,aAAW,CAAC,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,QAAI,QAAQ,SAAS;AACpB,YAAM,QAAQ,MAAM,MAAM,UAAU,CAAQ;AAC5C,YAAM,MAAM,MAAM,IAAI,EAAE,IAAI,QAAQ,EAAE;AACtC,UAAI,KAAK;AACR,mBAAW,MAAM,KAAK;AACrB,mBAAS,CAAC,EAAE,IAAI,EAAE;AAAA,QACnB;AAAA,MACD;AAAA,IACD,WAAW,SAAS,SAAS;AAC5B,YAAM,QAAQ,MAAM,MAAM,UAAU,CAAQ;AAC5C,iBAAW,CAAC,OAAO,GAAG,KAAK,MAAM,IAAI,GAAG;AACvC,YAAI,UAAU,QAAQ,KAAK;AAC1B,qBAAW,MAAM,KAAK;AACrB,qBAAS,CAAC,EAAE,IAAI,EAAE;AAAA,UACnB;AAAA,QACD;AAAA,MACD;AAAA,IACD,WAAW,QAAQ,SAAS;AAC3B,YAAM,QAAQ,MAAM,MAAM,UAAU,CAAQ;AAC5C,iBAAW,CAAC,OAAO,GAAG,KAAK,MAAM,IAAI,GAAG;AACvC,YAAI,QAAQ,QAAQ,IAAI;AACvB,qBAAW,MAAM,KAAK;AACrB,qBAAS,CAAC,EAAE,IAAI,EAAE;AAAA,UACnB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO,cAAc,OAAO,OAAO,QAAQ,CAAC;AAC7C;",
"names": []
}