From dfd820cc25b18df628d0a8705f91417700be2a73 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Tue, 17 May 2022 15:54:55 +0200 Subject: [PATCH] Changed how data is stored quite a bit with nice query capabilities --- packages/plugos-silverbullet-syscall/index.ts | 12 +- packages/plugos-syscall/store.ts | 22 ++- packages/plugos/runtime.test.ts | 6 +- .../plugos/syscalls/store.knex_node.test.ts | 77 +++++++++- packages/plugos/syscalls/store.knex_node.ts | 50 +++++++ packages/plugs/build/test/engine.test.js | 1 - packages/plugs/build/test/engine.test.js.map | 2 +- packages/plugs/core/item.ts | 4 +- packages/plugs/core/page.ts | 8 +- packages/plugs/query/data.ts | 4 +- packages/plugs/query/engine.ts | 1 - packages/plugs/query/materialized_queries.ts | 34 ++--- packages/plugs/query/query.plug.yaml | 6 +- packages/plugs/search/search.ts | 4 +- packages/plugs/tasks/task.ts | 4 +- packages/server/express_server.ts | 4 +- packages/server/syscalls/index.ts | 132 ++++++++---------- packages/web/app_event.ts | 2 +- packages/web/editor.tsx | 5 +- packages/web/syscalls/editor.ts | 7 - packages/web/syscalls/index.ts | 3 +- 21 files changed, 256 insertions(+), 132 deletions(-) diff --git a/packages/plugos-silverbullet-syscall/index.ts b/packages/plugos-silverbullet-syscall/index.ts index 5f6ecda6..a5c13118 100644 --- a/packages/plugos-silverbullet-syscall/index.ts +++ b/packages/plugos-silverbullet-syscall/index.ts @@ -1,3 +1,4 @@ +import type { Query } from "@plugos/plugos-syscall/store"; import { syscall } from "./syscall"; export type KV = { @@ -25,17 +26,16 @@ export async function del(page: string, key: string): Promise { return syscall("index.delete", page, key); } -export async function scanPrefixForPage( - page: string, +export async function queryPrefix( prefix: string ): Promise<{ key: string; page: string; value: any }[]> { - return syscall("index.scanPrefixForPage", page, prefix); + return syscall("index.queryPrefix", prefix); } -export async function scanPrefixGlobal( - prefix: string +export async function query( + query: Query ): Promise<{ key: string; page: string; value: any }[]> { - return syscall("index.scanPrefixGlobal", prefix); + return syscall("index.query", query); } export async function clearPageIndexForPage(page: string): Promise { diff --git a/packages/plugos-syscall/store.ts b/packages/plugos-syscall/store.ts index 4d7a3c25..6173c805 100644 --- a/packages/plugos-syscall/store.ts +++ b/packages/plugos-syscall/store.ts @@ -5,6 +5,20 @@ export type KV = { value: any; }; +export type Query = { + filter?: Filter[]; + orderBy?: string; + orderDesc?: boolean; + limit?: number; + select?: string[]; +}; + +export type Filter = { + op: string; + prop: string; + value: any; +}; + export async function set(key: string, value: any): Promise { return syscall("store.set", key, value); } @@ -28,7 +42,13 @@ export async function batchDel(keys: string[]): Promise { export async function queryPrefix( prefix: string ): Promise<{ key: string; value: any }[]> { - return syscall("store.scanPrefix", prefix); + return syscall("store.queryPrefix", prefix); +} + +export async function query( + query: Query +): Promise<{ key: string; value: any }[]> { + return syscall("store.query", query); } export async function deletePrefix(prefix: string): Promise { diff --git a/packages/plugos/runtime.test.ts b/packages/plugos/runtime.test.ts index 52ffd429..f40b4378 100644 --- a/packages/plugos/runtime.test.ts +++ b/packages/plugos/runtime.test.ts @@ -93,19 +93,19 @@ test("Run a Node sandbox", async () => { await plug.invoke("errorOut", []); expect(true).toBe(false); } catch (e: any) { - expect(e.message).toBe("BOOM"); + expect(e.message).toContain("BOOM"); } try { await plug.invoke("errorOutSys", []); expect(true).toBe(false); } catch (e: any) { - expect(e.message).toBe("#fail"); + expect(e.message).toContain("#fail"); } try { await plug.invoke("restrictedTest", []); expect(true).toBe(false); } catch (e: any) { - expect(e.message).toBe( + expect(e.message).toContain( "Missing permission 'restricted' for syscall restrictedSyscall" ); } diff --git a/packages/plugos/syscalls/store.knex_node.test.ts b/packages/plugos/syscalls/store.knex_node.test.ts index 00159302..b0bf66c5 100644 --- a/packages/plugos/syscalls/store.knex_node.test.ts +++ b/packages/plugos/syscalls/store.knex_node.test.ts @@ -15,7 +15,8 @@ test("Test store", async () => { }); await ensureTable(db, "test_table"); let system = new System("server"); - system.registerSyscalls([], storeSyscalls(db, "test_table")); + let syscalls = storeSyscalls(db, "test_table"); + system.registerSyscalls([], syscalls); let plug = await system.load( { name: "test", @@ -36,5 +37,79 @@ test("Test store", async () => { ); expect(await plug.invoke("test1", [])).toBe("Pete"); await system.unloadAll(); + + let dummyCtx: any = {}; + + await syscalls["store.deleteAll"](dummyCtx); + await syscalls["store.batchSet"](dummyCtx, [ + { + key: "pete", + value: { + age: 20, + firstName: "Pete", + lastName: "Roberts", + }, + }, + { + key: "petejr", + value: { + age: 8, + firstName: "Pete Jr", + lastName: "Roberts", + }, + }, + { + key: "petesr", + value: { + age: 78, + firstName: "Pete Sr", + lastName: "Roberts", + }, + }, + ]); + + let allRoberts = await syscalls["store.query"](dummyCtx, { + filter: [{ op: "=", prop: "lastName", value: "Roberts" }], + orderBy: "age", + orderDesc: true, + }); + + expect(allRoberts.length).toBe(3); + expect(allRoberts[0].key).toBe("petesr"); + + allRoberts = await syscalls["store.query"](dummyCtx, { + filter: [{ op: "=", prop: "lastName", value: "Roberts" }], + orderBy: "age", + limit: 1, + }); + + expect(allRoberts.length).toBe(1); + expect(allRoberts[0].key).toBe("petejr"); + + allRoberts = await syscalls["store.query"](dummyCtx, { + filter: [ + { op: ">", prop: "age", value: 10 }, + { op: "<", prop: "age", value: 30 }, + ], + orderBy: "age", + }); + + expect(allRoberts.length).toBe(1); + expect(allRoberts[0].key).toBe("pete"); + + // Delete the middle one + + await syscalls["store.deleteQuery"](dummyCtx, { + filter: [ + { op: ">", prop: "age", value: 10 }, + { op: "<", prop: "age", value: 30 }, + ], + }); + + allRoberts = await syscalls["store.query"](dummyCtx, {}); + expect(allRoberts.length).toBe(2); + + await db.destroy(); + await fs.unlink("test.db"); }); diff --git a/packages/plugos/syscalls/store.knex_node.ts b/packages/plugos/syscalls/store.knex_node.ts index 6b5ceb58..18d48ea6 100644 --- a/packages/plugos/syscalls/store.knex_node.ts +++ b/packages/plugos/syscalls/store.knex_node.ts @@ -24,6 +24,45 @@ export async function ensureTable(db: Knex, tableName: string) { } } +export type Query = { + filter?: Filter[]; + orderBy?: string; + orderDesc?: boolean; + limit?: number; + select?: string[]; +}; + +export type Filter = { + op: string; + prop: string; + value: any; +}; + +export function queryToKnex( + queryBuilder: Knex.QueryBuilder, + query: Query +): Knex.QueryBuilder { + if (query.filter) { + for (let filter of query.filter) { + queryBuilder = queryBuilder.andWhereRaw( + `json_extract(value, '$.${filter.prop}') ${filter.op} ?`, + [filter.value] + ); + } + } + if (query.limit) { + queryBuilder = queryBuilder.limit(query.limit); + } + if (query.orderBy) { + queryBuilder = queryBuilder.orderByRaw( + `json_extract(value, '$.${query.orderBy}') ${ + query.orderDesc ? "desc" : "asc" + }` + ); + } + return queryBuilder; +} + export function storeSyscalls( db: Knex, tableName: string @@ -35,6 +74,9 @@ export function storeSyscalls( "store.deletePrefix": async (ctx, prefix: string) => { return db(tableName).andWhereLike("key", `${prefix}%`).del(); }, + "store.deleteQuery": async (ctx, query: Query) => { + await queryToKnex(db(tableName), query).del(); + }, "store.deleteAll": async (ctx) => { await db(tableName).del(); }, @@ -78,6 +120,14 @@ export function storeSyscalls( value: JSON.parse(value), })); }, + "store.query": async (ctx, query: Query) => { + return ( + await queryToKnex(db(tableName), query).select("key", "value") + ).map(({ key, value }: { key: string; value: string }) => ({ + key, + value: JSON.parse(value), + })); + }, }; return apiObj; } diff --git a/packages/plugs/build/test/engine.test.js b/packages/plugs/build/test/engine.test.js index 14ca30fa..8d467c68 100644 --- a/packages/plugs/build/test/engine.test.js +++ b/packages/plugs/build/test/engine.test.js @@ -422,7 +422,6 @@ function $9072202279b76d33$export$5884dae03c64f759(parsedQuery, records) { } async function $9072202279b76d33$export$b3c659c1456e61b0(parsedQuery, data) { if (parsedQuery.render) { - console.log("Handlebars", ($parcel$interopDefault($hVExJ$handlebars))); ($parcel$interopDefault($hVExJ$handlebars)).registerHelper("json", (v)=>JSON.stringify(v) ); ($parcel$interopDefault($hVExJ$handlebars)).registerHelper("niceDate", (ts)=>$c3893eec0c49ec96$export$5dc1410f87262ed6(new Date(ts)) diff --git a/packages/plugs/build/test/engine.test.js.map b/packages/plugs/build/test/engine.test.js.map index 1f60b201..2fc80b21 100644 --- a/packages/plugs/build/test/engine.test.js.map +++ b/packages/plugs/build/test/engine.test.js.map @@ -1 +1 @@ -{"mappings":";;;;;;;;;SEUgB,yCAAiB,CAAC,IAAe,EAAE,CAAC;IAClD,EAAE,GAAG,IAAI,CAAC,QAAQ,EAChB,MAAM;IAER,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAE,CAAC;QAChC,EAAE,EAAE,KAAK,CAAC,MAAM,EACd,EAAuC,AAAvC,qCAAuC;QACvC,MAAM;QAER,KAAK,CAAC,MAAM,GAAG,IAAI;QACnB,yCAAiB,CAAC,KAAK;IACzB,CAAC;AACH,CAAC;SAEe,yCAAoB,CAAC,IAAe,EAAE,CAAC;IACrD,MAAM,CAAC,IAAI,CAAC,MAAM;IAClB,EAAE,GAAG,IAAI,CAAC,QAAQ,EAChB,MAAM;IAER,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAC7B,yCAAoB,CAAC,KAAK;AAE9B,CAAC;SAEe,yCAAkB,CAChC,IAAe,EACf,OAAqC,EACnB,CAAC;IACnB,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM;UACf,IAAI,CAAE,CAAC;QACZ,EAAE,EAAE,OAAO,CAAC,IAAI,GACd,MAAM,CAAC,IAAI;QAEb,IAAI,GAAG,IAAI,CAAC,MAAM;IACpB,CAAC;IACD,MAAM,CAAC,IAAI;AACb,CAAC;SAEe,yCAAkB,CAChC,IAAe,EACf,QAAgB,EACH,CAAC;IACd,MAAM,CAAC,wCAAoB,CAAC,IAAI,GAAG,CAAC,GAAK,CAAC,CAAC,IAAI,KAAK,QAAQ;;AAC9D,CAAC;SAEe,wCAAoB,CAClC,IAAe,EACf,OAAqC,EACxB,CAAC;IACd,EAAE,EAAE,OAAO,CAAC,IAAI,GACd,MAAM,CAAC,CAAC;QAAA,IAAI;IAAA,CAAC;IAEf,GAAG,CAAC,OAAO,GAAgB,CAAC,CAAC;IAC7B,EAAE,EAAE,IAAI,CAAC,QAAQ,EACf,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAC7B,OAAO,GAAG,CAAC;WAAG,OAAO;WAAK,wCAAoB,CAAC,KAAK,EAAE,OAAO;IAAC,CAAC;IAGnE,MAAM,CAAC,OAAO;AAChB,CAAC;SAGe,yCAAoB,CAClC,IAAe,EACf,YAA+D,EAC/D,CAAC;IACD,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK;QAClC,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,QAAQ,CAAE,CAAC;YAC3B,GAAG,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK;YAC9B,EAAE,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK;gBACrC,EAAE,EAAE,KAAK,EACP,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK;qBAElC,EAAgB,AAAhB,cAAgB;gBAChB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YAE/B,CAAC,MACC,yCAAoB,CAAC,KAAK,EAAE,YAAY;QAE5C,CAAC;IACH,CAAC;AACH,CAAC;SAEe,yCAAgB,CAC9B,IAAe,EACf,OAAqC,EACnB,CAAC;IACnB,MAAM,CAAC,wCAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;AAC9C,CAAC;SAEe,yCAAc,CAC5B,IAAe,EACf,QAAgB,EACE,CAAC;IACnB,MAAM,CAAC,wCAAoB,CAAC,IAAI,GAAG,CAAC,GAAK,CAAC,CAAC,IAAI,KAAK,QAAQ;MAAE,CAAC;AACjE,CAAC;SAGe,yCAAS,CAAC,IAAe,EAAE,GAAW,EAAoB,CAAC;IACzE,EAAE,EAAE,GAAG,GAAG,IAAI,CAAC,IAAI,IAAK,GAAG,GAAG,IAAI,CAAC,EAAE,EACnC,MAAM,CAAC,IAAI;IAEb,EAAE,GAAG,IAAI,CAAC,QAAQ,EAChB,MAAM,CAAC,IAAI;IAEb,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAE,CAAC;QAChC,GAAG,CAAC,CAAC,GAAG,yCAAS,CAAC,KAAK,EAAE,GAAG;QAC5B,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAC3B,EAA2C,AAA3C,yCAA2C;QAC3C,MAAM,CAAC,IAAI;aACN,EAAE,EAAE,CAAC,EACV,EAAS,AAAT,OAAS;QACT,MAAM,CAAC,CAAC;IAEZ,CAAC;IACD,MAAM,CAAC,IAAI;AACb,CAAC;SAGe,yCAAY,CAAC,IAAe,EAAU,CAAC;IACrD,GAAG,CAAC,MAAM,GAAa,CAAC,CAAC;IACzB,EAAE,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,EACzB,MAAM,CAAC,IAAI,CAAC,IAAI;IAElB,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAC7B,MAAM,CAAC,IAAI,CAAC,yCAAY,CAAC,KAAK;IAEhC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAE;AACvB,CAAC;;;SCxIe,yCAAgB,CAC9B,IAAY,EACZ,CAAa,EACb,MAAM,GAAG,CAAC,EACC,CAAC;IACZ,GAAG,CAAC,QAAQ,GAAgB,CAAC,CAAC;IAC9B,GAAG,CAAC,QAAQ;IACZ,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,UAAU;UACjB,KAAK,CAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CAAC,yCAAgB,CAAC,IAAI,EAAE,KAAK;QAC1C,KAAK,GAAG,KAAK,CAAC,WAAW;IAC3B,CAAC;IAED,EAAE,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,EACvB,QAAQ,GAAG,CAAC;QACV,CAAC;YACC,IAAI,EAAE,CAAC,CAAC,IAAI,GAAG,MAAM;YACrB,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM;YACjB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE;QACnC,CAAC;IACH,CAAC;SACI,CAAC;QACN,GAAG,CAAC,WAAW,GAAgB,CAAC,CAAC;QACjC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI;QAClB,GAAG,EAAE,GAAG,CAAC,KAAK,IAAI,QAAQ,CAAE,CAAC;YAC3B,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI;YACxC,EAAE,EAAE,CAAC,EACH,WAAW,CAAC,IAAI,CAAC,CAAC;gBAChB,IAAI,EAAE,KAAK,GAAG,MAAM;gBACpB,EAAE,EAAE,KAAK,CAAC,IAAI,GAAI,MAAM;gBACxB,IAAI,EAAE,CAAC;YACT,CAAC;YAEH,WAAW,CAAC,IAAI,CAAC,KAAK;YACtB,KAAK,GAAG,KAAK,CAAC,EAAE;QAClB,CAAC;QACD,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE;QAClC,EAAE,EAAE,CAAC,EACH,WAAW,CAAC,IAAI,CAAC,CAAC;YAAC,IAAI,EAAE,KAAK,GAAG,MAAM;YAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM;YAAE,IAAI,EAAE,CAAC;QAAC,CAAC;QAEvE,QAAQ,GAAG,WAAW;IACxB,CAAC;IAED,GAAG,CAAC,MAAM,GAAc,CAAC;QACvB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI,GAAG,MAAM;QACrB,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM;IACnB,CAAC;IACD,EAAE,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,EACrB,MAAM,CAAC,QAAQ,GAAG,QAAQ;IAE5B,EAAE,EAAE,QAAQ,EACV,MAAM,CAAC,IAAI,GAAG,QAAQ;IAExB,MAAM,CAAC,MAAM;AACf,CAAC;SAEe,yCAAK,CAAC,QAAkB,EAAE,IAAY,EAAa,CAAC;IAClE,GAAG,CAAC,IAAI,GAAG,yCAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO;IACrE,EAAuE,AAAvE,qEAAuE;IACvE,EAAmC,AAAnC,iCAAmC;IACnC,EAAqE,AAArE,mEAAqE;IACrE,EAA+C,AAA/C,6CAA+C;IAC/C,EAAqE,AAArE,mEAAqE;IACrE,EAA4C,AAA5C,0CAA4C;IAC5C,EAAE;IACF,EAAmC,AAAnC,iCAAmC;IACnC,EAA0B,AAA1B,wBAA0B;IAC1B,EAAqB,AAArB,mBAAqB;IACrB,EAAuE,AAAvE,qEAAuE;IACvE,EAAiE,AAAjE,+DAAiE;IACjE,EAA4D,AAA5D,0DAA4D;IAC5D,EAAiC,AAAjC,+BAAiC;IACjC,EAA0B,AAA1B,wBAA0B;IAC1B,EAAQ,AAAR,MAAQ;IACR,EAAM,AAAN,IAAM;IACN,EAAY,AAAZ,UAAY;IACZ,EAAM,AAAN,IAAM;IACN,MAAM,CAAC,IAAI;AACb,CAAC;;;;;;ACjFM,KAAK,CAAC,yCAAM,GAAG,uBAAQ,CAAC,WAAW,CAAC,CAAC;IAC1C,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,CAAkc;IAC1c,SAAS,EAAE,CAAuR;IAClS,IAAI,EAAE,CAAwI;IAC9I,SAAS,EAAE,CAAkK;IAC7K,OAAO,EAAE,EAAE;IACX,YAAY,EAAE,CAAC;AAAA,SAAC;IAAA,CAAC;IACjB,eAAe,EAAE,CAAC;IAClB,SAAS,EAAE,CAA6lF;IACxmF,UAAU,EAAE,CAAC;AAAA,SAAC;AAAE,SAAC;IAAA,CAAC;IAClB,QAAQ,EAAE,CAAC;QAAA,CAAS,UAAC,CAAC;AAAA,aAAC;AAAC,aAAC;QAAA,CAAC;IAAA,CAAC;IAC3B,SAAS,EAAE,CAAC;AACd,CAAC;;;AEXM,KAAK,CAAC,wCAAO,GAAG,IAAI,CAAC,OAAO;;;eDDb,yCAAS,CAAC,UAAU,GAAG,KAAK,EAAuB,CAAC;IACxE,MAAM,CAAC,wCAAO,CAAC,CAAiB,kBAAE,UAAU;AAC9C,CAAC;eAEqB,wCAAQ,CAC5B,IAAY,EAC+B,CAAC;IAC5C,MAAM,CAAC,wCAAO,CAAC,CAAgB,iBAAE,IAAI;AACvC,CAAC;eAEqB,yCAAS,CAAC,IAAY,EAAE,IAAY,EAAqB,CAAC;IAC9E,MAAM,CAAC,wCAAO,CAAC,CAAiB,kBAAE,IAAI,EAAE,IAAI;AAC9C,CAAC;eAEqB,yCAAU,CAAC,IAAY,EAAqB,CAAC;IACjE,MAAM,CAAC,wCAAO,CAAC,CAAkB,mBAAE,IAAI;AACzC,CAAC;;;;SGhBe,yCAAc,GAAoB,CAAC;IACjD,MAAM,CAAC,wCAAO,CAAC,CAAuB;AACxC,CAAC;SAEe,yCAAO,CAAC,OAAe,EAAiB,CAAC;IACvD,MAAM,CAAC,wCAAO,CAAC,CAAgB,iBAAE,OAAO;AAC1C,CAAC;SAEe,yCAAO,GAAoB,CAAC;IAC1C,MAAM,CAAC,wCAAO,CAAC,CAAgB;AACjC,CAAC;SAEe,wCAAS,GAAoB,CAAC;IAC5C,MAAM,CAAC,wCAAO,CAAC,CAAkB;AACnC,CAAC;SAEe,yCAAI,GAAkB,CAAC;IACrC,MAAM,CAAC,wCAAO,CAAC,CAAa;AAC9B,CAAC;SAEe,yCAAQ,CAAC,IAAY,EAAE,GAAY,EAAiB,CAAC;IACnE,MAAM,CAAC,wCAAO,CAAC,CAAiB,kBAAE,IAAI,EAAE,GAAG;AAC7C,CAAC;SAEe,yCAAU,GAAkB,CAAC;IAC3C,MAAM,CAAC,wCAAO,CAAC,CAAmB;AACpC,CAAC;SAEe,yCAAO,CAAC,GAAW,EAAiB,CAAC;IACnD,MAAM,CAAC,wCAAO,CAAC,CAAgB,iBAAE,GAAG;AACtC,CAAC;SAEe,yCAAiB,CAAC,OAAe,EAAiB,CAAC;IACjE,MAAM,CAAC,wCAAO,CAAC,CAA0B,2BAAE,OAAO;AACpD,CAAC;SAEe,yCAAS,CACvB,KAAa,EACb,OAAuB,EACvB,QAAgB,GAAG,CAAE,GACrB,WAAmB,GAAG,CAAE,GACW,CAAC;IACpC,MAAM,CAAC,wCAAO,CAAC,CAAkB,mBAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW;AAC1E,CAAC;SAEe,yCAAO,CACrB,IAAY,EACZ,MAAe,EACf,IAAI,GAAG,CAAC,EACO,CAAC;IAChB,MAAM,CAAC,wCAAO,CAAC,CAAgB,iBAAE,IAAI,EAAE,MAAM,EAAE,IAAI;AACrD,CAAC;SAEe,yCAAO,GAAkB,CAAC;IACxC,MAAM,CAAC,wCAAO,CAAC,CAAgB;AACjC,CAAC;SAEe,yCAAO,CACrB,IAAY,EACZ,MAAe,EACf,IAAI,GAAG,CAAC,EACO,CAAC;IAChB,MAAM,CAAC,wCAAO,CAAC,CAAgB,iBAAE,IAAI,EAAE,MAAM,EAAE,IAAI;AACrD,CAAC;SAEe,yCAAO,GAAkB,CAAC;IACxC,MAAM,CAAC,wCAAO,CAAC,CAAgB;AACjC,CAAC;SAEe,yCAAO,CACrB,IAAY,EACZ,MAAe,EACf,IAAI,GAAG,CAAC,EACO,CAAC;IAChB,MAAM,CAAC,wCAAO,CAAC,CAAgB,iBAAE,IAAI,EAAE,MAAM,EAAE,IAAI;AACrD,CAAC;SAEe,yCAAO,GAAkB,CAAC;IACxC,MAAM,CAAC,wCAAO,CAAC,CAAgB;AACjC,CAAC;SAEe,yCAAW,CAAC,IAAY,EAAE,GAAW,EAAiB,CAAC;IACrE,MAAM,CAAC,wCAAO,CAAC,CAAoB,qBAAE,IAAI,EAAE,GAAG;AAChD,CAAC;SAEe,yCAAY,CAC1B,IAAY,EACZ,EAAU,EACV,IAAY,EACG,CAAC;IAChB,MAAM,CAAC,wCAAO,CAAC,CAAqB,sBAAE,IAAI,EAAE,EAAE,EAAE,IAAI;AACtD,CAAC;SAEe,yCAAU,CAAC,GAAW,EAAiB,CAAC;IACtD,MAAM,CAAC,wCAAO,CAAC,CAAmB,oBAAE,GAAG;AACzC,CAAC;SAEe,yCAAc,CAAC,IAAY,EAAiB,CAAC;IAC3D,MAAM,CAAC,wCAAO,CAAC,CAAuB,wBAAE,IAAI;AAC9C,CAAC;SAEe,yCAAW,CACzB,EAAU,EACkD,CAAC;IAC7D,MAAM,CAAC,wCAAO,CAAC,CAAoB,qBAAE,EAAE;AACzC,CAAC;SAEe,yCAAQ,CAAC,MAAW,EAAiB,CAAC;IACpD,MAAM,CAAC,wCAAO,CAAC,CAAiB,kBAAE,MAAM;AAC1C,CAAC;SAEe,yCAAM,CACpB,OAAe,EACf,YAAY,GAAG,CAAE,GACY,CAAC;IAC9B,MAAM,CAAC,wCAAO,CAAC,CAAe,gBAAE,OAAO,EAAE,YAAY;AACvD,CAAC;;;ADrHD,KAAK,CAAC,oCAAc;SAEJ,yCAAQ,CAAC,CAAO,EAAU,CAAC;IACzC,MAAM,CAAC,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC,CAAG,IAAE,CAAC;AACrC,CAAC;eAEqB,yCAAW,GAAG,CAAC;IACnC,KAAK,CAAC,yCAAc,CAAC,yCAAQ,CAAC,GAAG,CAAC,IAAI;AACxC,CAAC;eAEqB,yCAAc,GAAG,CAAC;IACtC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI;IAChB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC;IACzB,KAAK,CAAC,yCAAc,CAAC,yCAAQ,CAAC,CAAC;AACjC,CAAC;;;SNoBe,yCAAU,CAAC,KAAa,EAAe,CAAC;IACtD,GAAG,CAAC,EAAC,GAAG,yCAAgB,CAAC,KAAK,EAAE,yCAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO;IAC3D,EAAuB,AAAvB,qBAAuB;IACvB,yCAAoB,CAAC,EAAC,GAAG,CAAC,GAAK,CAAC;QAC9B,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACZ,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAE,IAAI;YAC1B,EAAE,GAAG,OAAO,EACV,MAAM,CAAC,IAAI;YAEb,CAAC,CAAC,IAAI,GAAG,OAAO;QAClB,CAAC;IACH,CAAC;IAED,EAAqD,AAArD,mDAAqD;IAErD,GAAG,CAAC,SAAS,GAAG,EAAC,CAAC,QAAQ,CAAE,CAAC;IAC7B,GAAG,CAAC,WAAW,GAAgB,CAAC;QAC9B,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAE,CAAC,EAAE,QAAQ,CAAE,CAAC,EAAE,IAAI;QAC/C,MAAM,EAAE,CAAC,CAAC;IACZ,CAAC;IACD,GAAG,CAAC,WAAW,GAAG,yCAAc,CAAC,SAAS,EAAE,CAAa;IACzD,EAAE,EAAE,WAAW,EAAE,CAAC;QAChB,GAAG,CAAC,QAAQ,GAAG,yCAAc,CAAC,WAAW,EAAE,CAAM;QACjD,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAE,QAAQ,CAAE,CAAC,EAAE,IAAI;QACjD,GAAG,CAAC,SAAS,GAAG,yCAAc,CAAC,WAAW,EAAE,CAAO;QACnD,WAAW,CAAC,SAAS,GAAG,SAAS,GAC7B,SAAS,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI,KAAM,CAAM,QACvC,KAAK;IACX,CAAC;IACD,GAAG,CAAC,SAAS,GAAG,yCAAc,CAAC,SAAS,EAAE,CAAa;IACvD,EAAE,EAAE,SAAS,EAAE,CAAC;QACd,GAAG,CAAC,QAAQ,GAAG,yCAAc,CAAC,SAAS,EAAE,CAAQ;QACjD,WAAW,CAAC,KAAK,GAAG,oCAAc,CAAC,QAAQ;IAC7C,CAAC;IAED,GAAG,CAAC,WAAW,GAAG,yCAAkB,CAAC,SAAS,EAAE,CAAY;IAC5D,GAAG,EAAE,GAAG,CAAC,UAAU,IAAI,WAAW,CAAE,CAAC;QACnC,GAAG,CAAC,GAAG,GAAQ,SAAS;QACxB,GAAG,CAAC,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAE,CAAC,EAAE,QAAQ,CAAE,CAAC;QACjD,GAAG,GAAG,oCAAc,CAAC,OAAO;QAC5B,GAAG,CAAC,CAAC,GAAW,CAAC;YACf,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAE,CAAC,EAAE,QAAQ,CAAE,CAAC,EAAE,IAAI;YAC/C,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI;YAChC,KAAK,EAAE,GAAG;QACZ,CAAC;QACD,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IACD,GAAG,CAAC,UAAU,GAAG,yCAAc,CAAC,SAAS,EAAE,CAAc;IACzD,EAAE,EAAE,UAAU,EAAE,CAAC;QACf,EAA0D,AAA1D,wDAA0D;QAC1D,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;QACvB,yCAAkB,CAAC,UAAU,EAAE,CAAM,OAAE,OAAO,EAAE,CAAC,GAAK,CAAC;YACrD,WAAW,CAAC,MAAM,CAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI;QAC9C,CAAC;IACD,EAAuD,AAAvD,qDAAuD;IACvD,EAAqD,AAArD,mDAAqD;IACvD,CAAC;IAED,GAAG,CAAC,UAAU,GAAG,yCAAc,CAAC,SAAS,EAAE,CAAc;IACzD,EAAE,EAAE,UAAU,EAAE,CAAC;QACf,GAAG,CAAC,cAAc,GAAG,yCAAc,CAAC,UAAU,EAAE,CAAQ;QACxD,WAAW,CAAC,MAAM,GAAG,oCAAc,CAAC,cAAc;IACpD,CAAC;IAED,EAAmD,AAAnD,iDAAmD;IACnD,MAAM,CAAC,WAAW;AACpB,CAAC;SAEQ,oCAAc,CAAC,OAAkB,EAAO,CAAC;IAChD,MAAM,CAAE,OAAO,CAAC,IAAI;QAClB,IAAI,CAAC,CAAQ;YACX,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI;QACnC,IAAI,CAAC,CAAM;YACT,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI,KAAM,CAAM;QAC9C,IAAI,CAAC,CAAM;YACT,MAAM,CAAC,IAAI;QACb,IAAI,CAAC,CAAM;YACT,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI;QAClC,IAAI,CAAC,CAAO;YACV,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI;YACnC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC;QACxC,IAAI,CAAC,CAAQ;YACX,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAE,CAAC,EAAE,IAAI;YACzC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC;QACpD,IAAI,CAAC,CAAM;YACT,MAAM,CAAC,yCAAkB,CAAC,OAAO,EAAE,CAAO,QAAE,GAAG,EAAE,CAAC,GAChD,oCAAc,CAAC,CAAC,CAAC,QAAQ,CAAE,CAAC;;;AAGpC,CAAC;SAEe,yCAAU,CAAI,WAAwB,EAAE,OAAY,EAAO,CAAC;IAC1E,GAAG,CAAC,aAAa,GAAU,CAAC,CAAC;IAC7B,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EACjC,aAAa,GAAG,OAAO,CAAC,KAAK;SAE7B,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,IAAI,OAAO,CAAE,CAAC;QACvC,KAAK,CAAC,SAAS,GAAQ,MAAM;QAC7B,GAAG,EAAE,GAAG,CAAC,CAAC,KAAC,EAAE,SAAE,IAAI,UAAE,KAAK,EAAC,CAAC,IAAI,WAAW,CAAC,MAAM,CAChD,MAAM,CAAE,EAAE;YACR,IAAI,CAAC,CAAG;gBACN,EAAE,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,GAC5B,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAI;gBACP,EAAE,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,GAC5B,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAG;gBACN,EAAE,IAAI,SAAS,CAAC,IAAI,IAAI,KAAK,GAC3B,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAI;gBACP,EAAE,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,GAC5B,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAG;gBACN,EAAE,IAAI,SAAS,CAAC,IAAI,IAAI,KAAK,GAC3B,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAI;gBACP,EAAE,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,GAC5B,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAI;gBACP,EAA8B,AAA9B,4BAA8B;gBAC9B,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,IACxC,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAK;gBACR,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,IACvC,QAAQ,CAAC,UAAU;gBAErB,KAAK;YACP,IAAI,CAAC,CAAI;gBACP,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,IAChC,QAAQ,CAAC,UAAU;gBAErB,KAAK;;QAGX,aAAa,CAAC,IAAI,CAAC,SAAS;IAC9B,CAAC;IAEH,EAAkB,AAAlB,gBAAkB;IAClB,EAAE,EAAE,WAAW,CAAC,OAAO,EACrB,aAAa,GAAG,aAAa,CAAC,IAAI,EAAE,CAAM,EAAE,CAAM,GAAK,CAAC;QACtD,KAAK,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO;QACnC,KAAK,CAAC,SAAS,GAAG,WAAW,CAAC,SAAS;QACvC,EAAE,EAAE,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,OAAO,GAC1B,MAAM,CAAC,CAAC;QAGV,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,GACxB,MAAM,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE;aAEzB,MAAM,CAAC,SAAS,GAAG,EAAE,GAAG,CAAC;IAE7B,CAAC;IAEH,EAAE,EAAE,WAAW,CAAC,KAAK,EACnB,aAAa,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK;IAE1D,EAAE,EAAE,WAAW,CAAC,MAAM,EACpB,aAAa,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,GAAK,CAAC;QAC1C,GAAG,CAAC,MAAM,GAAQ,CAAC;QAAA,CAAC;QACpB,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,WAAW,CAAC,MAAM,CAC9B,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;QAEnB,MAAM,CAAC,MAAM;IACf,CAAC;IAEH,MAAM,CAAC,aAAa;AACtB,CAAC;eAEqB,yCAAW,CAC/B,WAAwB,EACxB,IAAW,EACM,CAAC;IAClB,EAAE,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,CAAY,aAAE,2CAAU;QACpC,2CAAU,CAAC,cAAc,CAAC,CAAM,QAAG,CAAC,GAAK,IAAI,CAAC,SAAS,CAAC,CAAC;;QACzD,2CAAU,CAAC,cAAc,CAAC,CAAU,YAAG,EAAE,GAAK,yCAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;;QAClE,2CAAU,CAAC,cAAc,CAAC,CAAM,QAAG,CAAC,EAAE,MAAM,GAAK,CAAC;YAChD,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAQ,SAAE,CAAC;gBAC/B,GAAG,CAAC,IAAI,GAAG,qCAAI,CAAC,SAAS,CAAC,CAAC,EACxB,KAAK,CAAC,CAAI,KACV,IAAI,CAAC,CAAI,MAAG,MAAM,EAClB,IAAI;gBACP,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,GACjB,MAAM,CAAC,CAAI,MAAG,MAAM,GAAG,IAAI;qBAE3B,MAAM,CAAC,IAAI;YAEf,CAAC,MACC,MAAM,CAAC,qCAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI;QAEjC,CAAC;QACD,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,YAAY,EAAC,CAAC,GAAG,KAAK,CAAC,wCAAQ,CAAC,WAAW,CAAC,MAAM;QAC9D,GAAG,CAAC,QAAQ,GAAG,2CAAU,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAAC,QAAQ,EAAE,IAAI;QAAC,CAAC;QAClE,MAAM,CAAC,QAAQ,CAAC,IAAI;IACtB,CAAC;IAED,MAAM,CAAC,CAAO;AAChB,CAAC;;;ADpPD,uBAAI,CAAC,CAAa,kBAAQ,CAAC;IACzB,GAAG,CAAC,gBAAgB,GAAG,yCAAU,EAAE,IAAI;IACvC,yBAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAM;IAE1C,GAAG,CAAC,YAAY,GAAG,yCAAU,EAC1B,qFAAqF;IAExF,yBAAM,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAM;IACtC,yBAAM,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAS;IAC3C,yBAAM,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI;IACxC,yBAAM,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,yBAAM,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzC,yBAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;QAC5C,EAAE,EAAE,CAAG;QACP,IAAI,EAAE,CAAW;QACjB,KAAK,EAAE,KAAK;IACd,CAAC;IACD,yBAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;QAC5C,EAAE,EAAE,CAAI;QACR,IAAI,EAAE,CAAS;QACf,KAAK,EAAE,CAAW;IACpB,CAAC;IAED,GAAG,CAAC,YAAY,GAAG,yCAAU,EAAE,oCAAoC;IACnE,yBAAM,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAM;IACtC,yBAAM,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzC,yBAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;QAC5C,EAAE,EAAE,CAAI;QACR,IAAI,EAAE,CAAM;QACZ,KAAK,EAAE,CAAgB;IACzB,CAAC;IAED,GAAG,CAAC,YAAY,GAAG,yCAAU,EAAE,4BAA4B;IAC3D,yBAAM,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAM;IACtC,yBAAM,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzC,yBAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC;QAC5C,EAAE,EAAE,CAAI;QACR,IAAI,EAAE,CAAW;QACjB,KAAK,EAAE,IAAI;IACb,CAAC;IAED,yBAAM,CAAC,yCAAU,EAAE,gBAAgB,GAAG,MAAM,EAAE,aAAa,CAAC,CAAC;QAAA,CAAM;IAAA,CAAC;IACpE,yBAAM,CAAC,yCAAU,EAAE,qBAAqB,GAAG,MAAM,EAAE,aAAa,CAAC,CAAC;QAChE,CAAM;QACN,CAAK;IACP,CAAC;IAED,yBAAM,CACJ,yCAAU,EAAE,sDAAsD,IAClE,aAAa,CAAC,CAAC;QACf,KAAK,EAAE,CAAW;QAClB,MAAM,EAAE,CAAC;YACP,CAAC;gBACC,EAAE,EAAE,CAAI;gBACR,IAAI,EAAE,CAAM;gBACZ,KAAK,EAAE,CAAC;oBAAA,CAAW;oBAAE,CAAe;gBAAA,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,yBAAM,CAAC,yCAAU,EAAE,iCAAiC,IAAI,aAAa,CAAC,CAAC;QACrE,KAAK,EAAE,CAAW;QAClB,MAAM,EAAE,CAAC,CAAC;QACV,MAAM,EAAE,CAAgB;IAC1B,CAAC;AACH,CAAC;AAED,uBAAI,CAAC,CAA6B,kCAAQ,CAAC;IACzC,GAAG,CAAC,IAAI,GAAU,CAAC;QACjB,CAAC;YAAC,IAAI,EAAE,CAAwB;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;QACnD,CAAC;YAAC,IAAI,EAAE,CAA0B;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;QACrD,CAAC;YAAC,IAAI,EAAE,CAAM;YAAE,GAAG,EAAE,EAAE;QAAC,CAAC;QACzB,CAAC;YAAC,IAAI,EAAE,CAAO;YAAE,GAAG,EAAE,EAAE;QAAC,CAAC;IAC5B,CAAC;IAED,yBAAM,CACJ,yCAAU,CAAC,yCAAU,EAAE,mCAAmC,IAAI,IAAI,GAClE,aAAa,CAAC,CAAC;QACf,CAAC;YAAC,IAAI,EAAE,CAAwB;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;QACnD,CAAC;YAAC,IAAI,EAAE,CAA0B;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;IACvD,CAAC;IACD,yBAAM,CACJ,yCAAU,CACR,yCAAU,EAAE,yDAAyD,IACrE,IAAI,GAEN,aAAa,CAAC,CAAC;QACf,CAAC;YAAC,IAAI,EAAE,CAAwB;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;QACnD,CAAC;YAAC,IAAI,EAAE,CAA0B;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;IACvD,CAAC;IACD,yBAAM,CACJ,yCAAU,CACR,yCAAU,EACP,+DAA+D,IAElE,IAAI,GAEN,aAAa,CAAC,CAAC;QACf,CAAC;YAAC,IAAI,EAAE,CAA0B;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;QACrD,CAAC;YAAC,IAAI,EAAE,CAAwB;YAAE,YAAY,EAAE,CAAC;QAAC,CAAC;IACrD,CAAC;IACD,yBAAM,CAAC,yCAAU,CAAC,yCAAU,EAAE,mBAAmB,IAAI,IAAI,GAAG,aAAa,CAAC,CAAC;QACzE,CAAC;YAAC,IAAI,EAAE,CAAM;YAAE,GAAG,EAAE,EAAE;QAAC,CAAC;IAC3B,CAAC;IACD,yBAAM,CACJ,yCAAU,CAAC,yCAAU,EAAE,gCAAgC,IAAI,IAAI,GAC/D,aAAa,CAAC,CAAC,CAAC;IAClB,yBAAM,CACJ,yCAAU,CAAC,yCAAU,EAAE,+BAA+B,IAAI,IAAI,GAC9D,aAAa,CAAC,CAAC;QAAA,CAAC;YAAC,IAAI,EAAE,CAAM;QAAC,CAAC;IAAA,CAAC;IAElC,yBAAM,CACJ,yCAAU,CAAC,yCAAU,EAAE,uCAAuC,IAAI,IAAI,GACtE,aAAa,CAAC,CAAC;QAAA,CAAC;YAAC,IAAI,EAAE,CAAM;QAAC,CAAC;IAAA,CAAC;AACpC,CAAC","sources":["packages/plugs/query/engine.test.ts","packages/plugs/query/engine.ts","packages/common/tree.ts","packages/common/parse_tree.ts","packages/plugs/query/parse-query.js","packages/plugos-silverbullet-syscall/space.ts","packages/plugos-silverbullet-syscall/syscall.ts","packages/plugs/core/dates.ts","packages/plugos-silverbullet-syscall/editor.ts"],"sourcesContent":["import { expect, test } from \"@jest/globals\";\nimport { applyQuery, parseQuery } from \"./engine\";\n\ntest(\"Test parser\", () => {\n let parsedBasicQuery = parseQuery(`page`);\n expect(parsedBasicQuery.table).toBe(\"page\");\n\n let parsedQuery1 = parseQuery(\n `task where completed = false and dueDate <= \"{{today}}\" order by dueDate desc limit 5`\n );\n expect(parsedQuery1.table).toBe(\"task\");\n expect(parsedQuery1.orderBy).toBe(\"dueDate\");\n expect(parsedQuery1.orderDesc).toBe(true);\n expect(parsedQuery1.limit).toBe(5);\n expect(parsedQuery1.filter.length).toBe(2);\n expect(parsedQuery1.filter[0]).toStrictEqual({\n op: \"=\",\n prop: \"completed\",\n value: false,\n });\n expect(parsedQuery1.filter[1]).toStrictEqual({\n op: \"<=\",\n prop: \"dueDate\",\n value: \"{{today}}\",\n });\n\n let parsedQuery2 = parseQuery(`page where name =~ /interview\\\\/.*/\"`);\n expect(parsedQuery2.table).toBe(\"page\");\n expect(parsedQuery2.filter.length).toBe(1);\n expect(parsedQuery2.filter[0]).toStrictEqual({\n op: \"=~\",\n prop: \"name\",\n value: \"interview\\\\/.*\",\n });\n\n let parsedQuery3 = parseQuery(`page where something != null`);\n expect(parsedQuery3.table).toBe(\"page\");\n expect(parsedQuery3.filter.length).toBe(1);\n expect(parsedQuery3.filter[0]).toStrictEqual({\n op: \"!=\",\n prop: \"something\",\n value: null,\n });\n\n expect(parseQuery(`page select name`).select).toStrictEqual([\"name\"]);\n expect(parseQuery(`page select name, age`).select).toStrictEqual([\n \"name\",\n \"age\",\n ]);\n\n expect(\n parseQuery(`gh-events where type in [\"PushEvent\", \"somethingElse\"]`)\n ).toStrictEqual({\n table: \"gh-events\",\n filter: [\n {\n op: \"in\",\n prop: \"type\",\n value: [\"PushEvent\", \"somethingElse\"],\n },\n ],\n });\n\n expect(parseQuery(`something render \"template/table\"`)).toStrictEqual({\n table: \"something\",\n filter: [],\n render: \"template/table\",\n });\n});\n\ntest(\"Test performing the queries\", () => {\n let data: any[] = [\n { name: \"interview/My Interview\", lastModified: 1 },\n { name: \"interview/My Interview 2\", lastModified: 2 },\n { name: \"Pete\", age: 38 },\n { name: \"Angie\", age: 28 },\n ];\n\n expect(\n applyQuery(parseQuery(`page where name =~ /interview\\\\/.*/`), data)\n ).toStrictEqual([\n { name: \"interview/My Interview\", lastModified: 1 },\n { name: \"interview/My Interview 2\", lastModified: 2 },\n ]);\n expect(\n applyQuery(\n parseQuery(`page where name =~ /interview\\\\/.*/ order by lastModified`),\n data\n )\n ).toStrictEqual([\n { name: \"interview/My Interview\", lastModified: 1 },\n { name: \"interview/My Interview 2\", lastModified: 2 },\n ]);\n expect(\n applyQuery(\n parseQuery(\n `page where name =~ /interview\\\\/.*/ order by lastModified desc`\n ),\n data\n )\n ).toStrictEqual([\n { name: \"interview/My Interview 2\", lastModified: 2 },\n { name: \"interview/My Interview\", lastModified: 1 },\n ]);\n expect(applyQuery(parseQuery(`page where age > 30`), data)).toStrictEqual([\n { name: \"Pete\", age: 38 },\n ]);\n expect(\n applyQuery(parseQuery(`page where age > 28 and age < 38`), data)\n ).toStrictEqual([]);\n expect(\n applyQuery(parseQuery(`page where age > 30 select name`), data)\n ).toStrictEqual([{ name: \"Pete\" }]);\n\n expect(\n applyQuery(parseQuery(`page where name in [\"Pete\"] select name`), data)\n ).toStrictEqual([{ name: \"Pete\" }]);\n});\n","import {\n collectNodesOfType,\n findNodeOfType,\n ParseTree,\n replaceNodesMatching,\n} from \"@silverbulletmd/common/tree\";\nimport { lezerToParseTree } from \"@silverbulletmd/common/parse_tree\";\nimport Handlebars from \"handlebars\";\nimport YAML from \"yaml\";\n\n// @ts-ignore\nimport { parser } from \"./parse-query\";\nimport { readPage } from \"@silverbulletmd/plugos-silverbullet-syscall/space\";\nimport { niceDate } from \"../core/dates\";\n\nexport type QueryProviderEvent = {\n query: ParsedQuery;\n pageName: string;\n};\n\nexport type Filter = {\n op: string;\n prop: string;\n value: any;\n};\n\nexport type ParsedQuery = {\n table: string;\n orderBy?: string;\n orderDesc?: boolean;\n limit?: number;\n filter: Filter[];\n select?: string[];\n render?: string;\n};\n\nexport function parseQuery(query: string): ParsedQuery {\n let n = lezerToParseTree(query, parser.parse(query).topNode);\n // Clean the tree a bit\n replaceNodesMatching(n, (n) => {\n if (!n.type) {\n let trimmed = n.text!.trim();\n if (!trimmed) {\n return null;\n }\n n.text = trimmed;\n }\n });\n\n // console.log(\"Parsed\", JSON.stringify(n, null, 2));\n\n let queryNode = n.children![0];\n let parsedQuery: ParsedQuery = {\n table: queryNode.children![0].children![0].text!,\n filter: [],\n };\n let orderByNode = findNodeOfType(queryNode, \"OrderClause\");\n if (orderByNode) {\n let nameNode = findNodeOfType(orderByNode, \"Name\");\n parsedQuery.orderBy = nameNode!.children![0].text!;\n let orderNode = findNodeOfType(orderByNode, \"Order\");\n parsedQuery.orderDesc = orderNode\n ? orderNode.children![0].text! === \"desc\"\n : false;\n }\n let limitNode = findNodeOfType(queryNode, \"LimitClause\");\n if (limitNode) {\n let nameNode = findNodeOfType(limitNode, \"Number\");\n parsedQuery.limit = valueNodeToVal(nameNode!);\n }\n\n let filterNodes = collectNodesOfType(queryNode, \"FilterExpr\");\n for (let filterNode of filterNodes) {\n let val: any = undefined;\n let valNode = filterNode.children![2].children![0];\n val = valueNodeToVal(valNode);\n let f: Filter = {\n prop: filterNode.children![0].children![0].text!,\n op: filterNode.children![1].text!,\n value: val,\n };\n parsedQuery.filter.push(f);\n }\n let selectNode = findNodeOfType(queryNode, \"SelectClause\");\n if (selectNode) {\n // console.log(\"Select node\", JSON.stringify(selectNode));\n parsedQuery.select = [];\n collectNodesOfType(selectNode, \"Name\").forEach((t) => {\n parsedQuery.select!.push(t.children![0].text!);\n });\n // let nameNode = findNodeOfType(selectNode, \"Number\");\n // parsedQuery.limit = +nameNode!.children![0].text!;\n }\n\n let renderNode = findNodeOfType(queryNode, \"RenderClause\");\n if (renderNode) {\n let renderNameNode = findNodeOfType(renderNode, \"String\");\n parsedQuery.render = valueNodeToVal(renderNameNode!);\n }\n\n // console.log(JSON.stringify(queryNode, null, 2));\n return parsedQuery;\n}\n\nfunction valueNodeToVal(valNode: ParseTree): any {\n switch (valNode.type) {\n case \"Number\":\n return +valNode.children![0].text!;\n case \"Bool\":\n return valNode.children![0].text! === \"true\";\n case \"Null\":\n return null;\n case \"Name\":\n return valNode.children![0].text!;\n case \"Regex\":\n let val = valNode.children![0].text!;\n return val.substring(1, val.length - 1);\n case \"String\":\n let stringVal = valNode.children![0].text!;\n return stringVal.substring(1, stringVal.length - 1);\n case \"List\":\n return collectNodesOfType(valNode, \"Value\").map((t) =>\n valueNodeToVal(t.children![0])\n );\n }\n}\n\nexport function applyQuery(parsedQuery: ParsedQuery, records: T[]): T[] {\n let resultRecords: any[] = [];\n if (parsedQuery.filter.length === 0) {\n resultRecords = records.slice();\n } else {\n recordLoop: for (let record of records) {\n const recordAny: any = record;\n for (let { op, prop, value } of parsedQuery.filter) {\n switch (op) {\n case \"=\":\n if (!(recordAny[prop] == value)) {\n continue recordLoop;\n }\n break;\n case \"!=\":\n if (!(recordAny[prop] != value)) {\n continue recordLoop;\n }\n break;\n case \"<\":\n if (!(recordAny[prop] < value)) {\n continue recordLoop;\n }\n break;\n case \"<=\":\n if (!(recordAny[prop] <= value)) {\n continue recordLoop;\n }\n break;\n case \">\":\n if (!(recordAny[prop] > value)) {\n continue recordLoop;\n }\n break;\n case \">=\":\n if (!(recordAny[prop] >= value)) {\n continue recordLoop;\n }\n break;\n case \"=~\":\n // TODO: Cache regexps somehow\n if (!new RegExp(value).exec(recordAny[prop])) {\n continue recordLoop;\n }\n break;\n case \"!=~\":\n if (new RegExp(value).exec(recordAny[prop])) {\n continue recordLoop;\n }\n break;\n case \"in\":\n if (!value.includes(recordAny[prop])) {\n continue recordLoop;\n }\n break;\n }\n }\n resultRecords.push(recordAny);\n }\n }\n // Now the sorting\n if (parsedQuery.orderBy) {\n resultRecords = resultRecords.sort((a: any, b: any) => {\n const orderBy = parsedQuery.orderBy!;\n const orderDesc = parsedQuery.orderDesc!;\n if (a[orderBy] === b[orderBy]) {\n return 0;\n }\n\n if (a[orderBy] < b[orderBy]) {\n return orderDesc ? 1 : -1;\n } else {\n return orderDesc ? -1 : 1;\n }\n });\n }\n if (parsedQuery.limit) {\n resultRecords = resultRecords.slice(0, parsedQuery.limit);\n }\n if (parsedQuery.select) {\n resultRecords = resultRecords.map((rec) => {\n let newRec: any = {};\n for (let k of parsedQuery.select!) {\n newRec[k] = rec[k];\n }\n return newRec;\n });\n }\n return resultRecords;\n}\n\nexport async function renderQuery(\n parsedQuery: ParsedQuery,\n data: any[]\n): Promise {\n if (parsedQuery.render) {\n console.log(\"Handlebars\", Handlebars);\n Handlebars.registerHelper(\"json\", (v) => JSON.stringify(v));\n Handlebars.registerHelper(\"niceDate\", (ts) => niceDate(new Date(ts)));\n Handlebars.registerHelper(\"yaml\", (v, prefix) => {\n if (typeof prefix === \"string\") {\n let yaml = YAML.stringify(v)\n .split(\"\\n\")\n .join(\"\\n\" + prefix)\n .trim();\n if (Array.isArray(v)) {\n return \"\\n\" + prefix + yaml;\n } else {\n return yaml;\n }\n } else {\n return YAML.stringify(v).trim();\n }\n });\n let { text: templateText } = await readPage(parsedQuery.render);\n let template = Handlebars.compile(templateText, { noEscape: true });\n return template(data);\n }\n\n return \"ERROR\";\n}\n","export type ParseTree = {\n type?: string; // undefined === text node\n from?: number;\n to?: number;\n text?: string;\n children?: ParseTree[];\n // Only present after running addParentPointers\n parent?: ParseTree;\n};\n\nexport function addParentPointers(tree: ParseTree) {\n if (!tree.children) {\n return;\n }\n for (let child of tree.children) {\n if (child.parent) {\n // Already added parent pointers before\n return;\n }\n child.parent = tree;\n addParentPointers(child);\n }\n}\n\nexport function removeParentPointers(tree: ParseTree) {\n delete tree.parent;\n if (!tree.children) {\n return;\n }\n for (let child of tree.children) {\n removeParentPointers(child);\n }\n}\n\nexport function findParentMatching(\n tree: ParseTree,\n matchFn: (tree: ParseTree) => boolean\n): ParseTree | null {\n let node = tree.parent;\n while (node) {\n if (matchFn(node)) {\n return node;\n }\n node = node.parent;\n }\n return null;\n}\n\nexport function collectNodesOfType(\n tree: ParseTree,\n nodeType: string\n): ParseTree[] {\n return collectNodesMatching(tree, (n) => n.type === nodeType);\n}\n\nexport function collectNodesMatching(\n tree: ParseTree,\n matchFn: (tree: ParseTree) => boolean\n): ParseTree[] {\n if (matchFn(tree)) {\n return [tree];\n }\n let results: ParseTree[] = [];\n if (tree.children) {\n for (let child of tree.children) {\n results = [...results, ...collectNodesMatching(child, matchFn)];\n }\n }\n return results;\n}\n\n// return value: returning undefined = not matched, continue, null = delete, new node = replace\nexport function replaceNodesMatching(\n tree: ParseTree,\n substituteFn: (tree: ParseTree) => ParseTree | null | undefined\n) {\n if (tree.children) {\n let children = tree.children.slice();\n for (let child of children) {\n let subst = substituteFn(child);\n if (subst !== undefined) {\n let pos = tree.children.indexOf(child);\n if (subst) {\n tree.children.splice(pos, 1, subst);\n } else {\n // null = delete\n tree.children.splice(pos, 1);\n }\n } else {\n replaceNodesMatching(child, substituteFn);\n }\n }\n }\n}\n\nexport function findNodeMatching(\n tree: ParseTree,\n matchFn: (tree: ParseTree) => boolean\n): ParseTree | null {\n return collectNodesMatching(tree, matchFn)[0];\n}\n\nexport function findNodeOfType(\n tree: ParseTree,\n nodeType: string\n): ParseTree | null {\n return collectNodesMatching(tree, (n) => n.type === nodeType)[0];\n}\n\n// Finds non-text node at position\nexport function nodeAtPos(tree: ParseTree, pos: number): ParseTree | null {\n if (pos < tree.from! || pos > tree.to!) {\n return null;\n }\n if (!tree.children) {\n return tree;\n }\n for (let child of tree.children) {\n let n = nodeAtPos(child, pos);\n if (n && n.text !== undefined) {\n // Got a text node, let's return its parent\n return tree;\n } else if (n) {\n // Got it\n return n;\n }\n }\n return null;\n}\n\n// Turn ParseTree back into text\nexport function renderToText(tree: ParseTree): string {\n let pieces: string[] = [];\n if (tree.text !== undefined) {\n return tree.text;\n }\n for (let child of tree.children!) {\n pieces.push(renderToText(child));\n }\n return pieces.join(\"\");\n}\n","import type { SyntaxNode } from \"@lezer/common\";\nimport type { Language } from \"@codemirror/language\";\nimport { ParseTree } from \"./tree\";\n\nexport function lezerToParseTree(\n text: string,\n n: SyntaxNode,\n offset = 0\n): ParseTree {\n let children: ParseTree[] = [];\n let nodeText: string | undefined;\n let child = n.firstChild;\n while (child) {\n children.push(lezerToParseTree(text, child));\n child = child.nextSibling;\n }\n\n if (children.length === 0) {\n children = [\n {\n from: n.from + offset,\n to: n.to + offset,\n text: text.substring(n.from, n.to),\n },\n ];\n } else {\n let newChildren: ParseTree[] = [];\n let index = n.from;\n for (let child of children) {\n let s = text.substring(index, child.from);\n if (s) {\n newChildren.push({\n from: index + offset,\n to: child.from! + offset,\n text: s,\n });\n }\n newChildren.push(child);\n index = child.to!;\n }\n let s = text.substring(index, n.to);\n if (s) {\n newChildren.push({ from: index + offset, to: n.to + offset, text: s });\n }\n children = newChildren;\n }\n\n let result: ParseTree = {\n type: n.name,\n from: n.from + offset,\n to: n.to + offset,\n };\n if (children.length > 0) {\n result.children = children;\n }\n if (nodeText) {\n result.text = nodeText;\n }\n return result;\n}\n\nexport function parse(language: Language, text: string): ParseTree {\n let tree = lezerToParseTree(text, language.parser.parse(text).topNode);\n // replaceNodesMatching(tree, (n): MarkdownTree | undefined | null => {\n // if (n.type === \"FencedCode\") {\n // let infoN = findNodeMatching(n, (n) => n.type === \"CodeInfo\");\n // let language = infoN!.children![0].text;\n // let textN = findNodeMatching(n, (n) => n.type === \"CodeText\");\n // let text = textN!.children![0].text!;\n //\n // console.log(language, text);\n // switch (language) {\n // case \"yaml\":\n // let parsed = StreamLanguage.define(yaml).parser.parse(text);\n // let subTree = treeToAST(text, parsed.topNode, n.from);\n // // console.log(JSON.stringify(subTree, null, 2));\n // subTree.type = \"yaml\";\n // return subTree;\n // }\n // }\n // return;\n // });\n return tree;\n}\n","// This file was generated by lezer-generator. You probably shouldn't edit it.\nimport {LRParser} from \"@lezer/lr\"\nexport const parser = LRParser.deserialize({\n version: 13,\n states: \"&fOVQPOOOmQQO'#C^QOQPOOOtQPO'#C`OyQQO'#CkO!OQPO'#CmO!TQPO'#CnO!YQPO'#CoOOQO'#Cp'#CpO!_QQO,58xO!fQQO'#CcO#TQQO'#CaOOQO'#Ca'#CaOOQO,58z,58zO#lQPO,59VOOQO,59X,59XO#qQQO'#D`OOQO,59Y,59YOOQO,59Z,59ZOOQO-E6n-E6nO$YQQO,58}OtQPO,58|O$qQQO1G.qO%]QPO'#CrO%bQQO,59zOOQO'#Cg'#CgOOQO'#Ci'#CiO$YQQO'#CjOOQO'#Cd'#CdOOQO1G.i1G.iOOQO1G.h1G.hOOQO'#Cl'#ClOOQO7+$]7+$]OOQO,59^,59^OOQO-E6p-E6pO%yQPO'#C|O&RQPO,59UO$YQQO'#CqO&WQPO,59hOOQO1G.p1G.pOOQO,59],59]OOQO-E6o-E6o\",\n stateData: \"&`~OiOS~ORPO~OjRO|SO!QTO!RUO!TVO~OgQX~P[ORYO~O}^O~OX_O~OR`O~OYbO~OgQa~P[OkdOsdOtdOudOvdOwdOxdOydOzdO~O{eOgTXjTX|TX!QTX!RTX!TTX~ORfO~OqgOg!SXj!SX|!SX!Q!SX!R!SX!T!SX~OXlOYlO[lOliOmiOnjOokO~O!OoO!PoOg_ij_i|_i!Q_i!R_i!T_i~ORqO~OqgOg!Saj!Sa|!Sa!Q!Sa!R!Sa!T!Sa~OquOrpX~OrwO~OquOrpa~O\",\n goto: \"#d!TPP!UP!X!]!`!c!iPP!rP!r!r!X!w!X!X!X!z#Q#WPPPPPPPPP#^PPPPPPPPPPPPPPPPP#aRQOTWPXR]RR[RQZRRneQmdQskRxuVldkuRpfQXPRcXQvsRyvQh`RrhRtkRaU\",\n nodeNames: \"⚠ Program Query Name WhereClause LogicalExpr AndExpr FilterExpr Value Number String Bool Regex Null List OrderClause Order LimitClause SelectClause RenderClause\",\n maxTerm: 51,\n skippedNodes: [0],\n repeatNodeCount: 3,\n tokenData: \"Ap~R}X^$Opq$Oqr$srs%W|}%r}!O%w!P!Q&Y!Q!['P!^!_'X!_!`'f!`!a's!c!}%w!}#O(Q#P#Q(V#R#S%w#T#U([#U#V*q#V#W%w#W#X+m#X#Y%w#Y#Z-i#Z#]%w#]#^/y#^#`%w#`#a0u#a#b%w#b#c3Y#c#d5U#d#f%w#f#g7i#g#h:e#h#i=a#i#k%w#k#l?]#l#o%w#y#z$O$f$g$O#BY#BZ$O$IS$I_$O$Ip$Iq%W$Iq$Ir%W$I|$JO$O$JT$JU$O$KV$KW$O&FU&FV$O~$TYi~X^$Opq$O#y#z$O$f$g$O#BY#BZ$O$IS$I_$O$I|$JO$O$JT$JU$O$KV$KW$O&FU&FV$O~$vP!_!`$y~%OPu~#r#s%R~%WOy~~%ZUOr%Wrs%ms$Ip%W$Ip$Iq%m$Iq$Ir%m$Ir~%W~%rOY~~%wOq~P%|SRP}!O%w!c!}%w#R#S%w#T#o%w~&_V[~OY&YZ]&Y^!P&Y!P!Q&t!Q#O&Y#O#P&y#P~&Y~&yO[~~&|PO~&Y~'UPX~!Q!['P~'^Pk~!_!`'a~'fOs~~'kPt~#r#s'n~'sOx~~'xPw~!_!`'{~(QOv~~(VOo~~([Or~R(aWRP}!O%w!c!}%w#R#S%w#T#b%w#b#c(y#c#g%w#g#h)u#h#o%wR)OURP}!O%w!c!}%w#R#S%w#T#W%w#W#X)b#X#o%wR)iS{QRP}!O%w!c!}%w#R#S%w#T#o%wR)zURP}!O%w!c!}%w#R#S%w#T#V%w#V#W*^#W#o%wR*eS!PQRP}!O%w!c!}%w#R#S%w#T#o%wR*vURP}!O%w!c!}%w#R#S%w#T#m%w#m#n+Y#n#o%wR+aS}QRP}!O%w!c!}%w#R#S%w#T#o%wR+rURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y,U#Y#o%wR,ZURP}!O%w!c!}%w#R#S%w#T#g%w#g#h,m#h#o%wR,rURP}!O%w!c!}%w#R#S%w#T#V%w#V#W-U#W#o%wR-]S!OQRP}!O%w!c!}%w#R#S%w#T#o%wR-nTRP}!O%w!c!}%w#R#S%w#T#U-}#U#o%wR.SURP}!O%w!c!}%w#R#S%w#T#`%w#`#a.f#a#o%wR.kURP}!O%w!c!}%w#R#S%w#T#g%w#g#h.}#h#o%wR/SURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y/f#Y#o%wR/mSmQRP}!O%w!c!}%w#R#S%w#T#o%wR0OURP}!O%w!c!}%w#R#S%w#T#b%w#b#c0b#c#o%wR0iSzQRP}!O%w!c!}%w#R#S%w#T#o%wR0zURP}!O%w!c!}%w#R#S%w#T#]%w#]#^1^#^#o%wR1cURP}!O%w!c!}%w#R#S%w#T#a%w#a#b1u#b#o%wR1zURP}!O%w!c!}%w#R#S%w#T#]%w#]#^2^#^#o%wR2cURP}!O%w!c!}%w#R#S%w#T#h%w#h#i2u#i#o%wR2|S!QQRP}!O%w!c!}%w#R#S%w#T#o%wR3_URP}!O%w!c!}%w#R#S%w#T#i%w#i#j3q#j#o%wR3vURP}!O%w!c!}%w#R#S%w#T#`%w#`#a4Y#a#o%wR4_URP}!O%w!c!}%w#R#S%w#T#`%w#`#a4q#a#o%wR4xSnQRP}!O%w!c!}%w#R#S%w#T#o%wR5ZURP}!O%w!c!}%w#R#S%w#T#f%w#f#g5m#g#o%wR5rURP}!O%w!c!}%w#R#S%w#T#W%w#W#X6U#X#o%wR6ZURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y6m#Y#o%wR6rURP}!O%w!c!}%w#R#S%w#T#f%w#f#g7U#g#o%wR7]S|QRP}!O%w!c!}%w#R#S%w#T#o%wR7nURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y8Q#Y#o%wR8VURP}!O%w!c!}%w#R#S%w#T#b%w#b#c8i#c#o%wR8nURP}!O%w!c!}%w#R#S%w#T#W%w#W#X9Q#X#o%wR9VURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y9i#Y#o%wR9nURP}!O%w!c!}%w#R#S%w#T#f%w#f#g:Q#g#o%wR:XS!TQRP}!O%w!c!}%w#R#S%w#T#o%wR:jURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y:|#Y#o%wR;RURP}!O%w!c!}%w#R#S%w#T#`%w#`#a;e#a#o%wR;jURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y;|#Y#o%wRa#j#o%wR>fURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y>x#Y#o%wR?PSlQRP}!O%w!c!}%w#R#S%w#T#o%wR?bURP}!O%w!c!}%w#R#S%w#T#[%w#[#]?t#]#o%wR?yURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y@]#Y#o%wR@bURP}!O%w!c!}%w#R#S%w#T#f%w#f#g@t#g#o%wR@yURP}!O%w!c!}%w#R#S%w#T#X%w#X#YA]#Y#o%wRAdSjQRP}!O%w!c!}%w#R#S%w#T#o%w\",\n tokenizers: [0, 1],\n topRules: {\"Program\":[0,1]},\n tokenPrec: 0\n})\n","import { syscall } from \"./syscall\";\nimport { PageMeta } from \"../common/types\";\n\nexport async function listPages(unfiltered = false): Promise {\n return syscall(\"space.listPages\", unfiltered);\n}\n\nexport async function readPage(\n name: string\n): Promise<{ text: string; meta: PageMeta }> {\n return syscall(\"space.readPage\", name);\n}\n\nexport async function writePage(name: string, text: string): Promise {\n return syscall(\"space.writePage\", name, text);\n}\n\nexport async function deletePage(name: string): Promise {\n return syscall(\"space.deletePage\", name);\n}\n","declare global {\n function syscall(name: string, ...args: any[]): Promise;\n}\n\nexport const syscall = self.syscall;\n","import { insertAtCursor } from \"@silverbulletmd/plugos-silverbullet-syscall/editor\";\n\nconst dateMatchRegex = /(\\d{4}\\-\\d{2}\\-\\d{2})/g;\n\nexport function niceDate(d: Date): string {\n return d.toISOString().split(\"T\")[0];\n}\n\nexport async function insertToday() {\n await insertAtCursor(niceDate(new Date()));\n}\n\nexport async function insertTomorrow() {\n let d = new Date();\n d.setDate(d.getDate() + 1);\n await insertAtCursor(niceDate(d));\n}\n","import { syscall } from \"./syscall\";\nimport { FilterOption } from \"../common/types\";\n\nexport function getCurrentPage(): Promise {\n return syscall(\"editor.getCurrentPage\");\n}\n\nexport function setPage(newName: string): Promise {\n return syscall(\"editor.setPage\", newName);\n}\n\nexport function getText(): Promise {\n return syscall(\"editor.getText\");\n}\n\nexport function getCursor(): Promise {\n return syscall(\"editor.getCursor\");\n}\n\nexport function save(): Promise {\n return syscall(\"editor.save\");\n}\n\nexport function navigate(name: string, pos?: number): Promise {\n return syscall(\"editor.navigate\", name, pos);\n}\n\nexport function reloadPage(): Promise {\n return syscall(\"editor.reloadPage\");\n}\n\nexport function openUrl(url: string): Promise {\n return syscall(\"editor.openUrl\", url);\n}\n\nexport function flashNotification(message: string): Promise {\n return syscall(\"editor.flashNotification\", message);\n}\n\nexport function filterBox(\n label: string,\n options: FilterOption[],\n helpText: string = \"\",\n placeHolder: string = \"\"\n): Promise {\n return syscall(\"editor.filterBox\", label, options, helpText, placeHolder);\n}\n\nexport function showRhs(\n html: string,\n script?: string,\n flex = 1\n): Promise {\n return syscall(\"editor.showRhs\", html, script, flex);\n}\n\nexport function hideRhs(): Promise {\n return syscall(\"editor.hideRhs\");\n}\n\nexport function showLhs(\n html: string,\n script?: string,\n flex = 1\n): Promise {\n return syscall(\"editor.showLhs\", html, script, flex);\n}\n\nexport function hideLhs(): Promise {\n return syscall(\"editor.hideLhs\");\n}\n\nexport function showBhs(\n html: string,\n script?: string,\n flex = 1\n): Promise {\n return syscall(\"editor.showBhs\", html, script, flex);\n}\n\nexport function hideBhs(): Promise {\n return syscall(\"editor.hideBhs\");\n}\n\nexport function insertAtPos(text: string, pos: number): Promise {\n return syscall(\"editor.insertAtPos\", text, pos);\n}\n\nexport function replaceRange(\n from: number,\n to: number,\n text: string\n): Promise {\n return syscall(\"editor.replaceRange\", from, to, text);\n}\n\nexport function moveCursor(pos: number): Promise {\n return syscall(\"editor.moveCursor\", pos);\n}\n\nexport function insertAtCursor(text: string): Promise {\n return syscall(\"editor.insertAtCursor\", text);\n}\n\nexport function matchBefore(\n re: string\n): Promise<{ from: number; to: number; text: string } | null> {\n return syscall(\"editor.matchBefore\", re);\n}\n\nexport function dispatch(change: any): Promise {\n return syscall(\"editor.dispatch\", change);\n}\n\nexport function prompt(\n message: string,\n defaultValue = \"\"\n): Promise {\n return syscall(\"editor.prompt\", message, defaultValue);\n}\n"],"names":[],"version":3,"file":"engine.test.js.map","sourceRoot":"../../../../"} \ No newline at end of file +{"mappings":"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","sources":["packages/plugs/query/engine.test.ts","packages/plugs/query/engine.ts","packages/common/tree.ts","packages/common/parse_tree.ts","packages/plugs/query/parse-query.js","packages/plugos-silverbullet-syscall/space.ts","packages/plugos-silverbullet-syscall/syscall.ts","packages/plugs/core/dates.ts","packages/plugos-silverbullet-syscall/editor.ts"],"sourcesContent":["import { expect, test } from \"@jest/globals\";\nimport { applyQuery, parseQuery } from \"./engine\";\n\ntest(\"Test parser\", () => {\n let parsedBasicQuery = parseQuery(`page`);\n expect(parsedBasicQuery.table).toBe(\"page\");\n\n let parsedQuery1 = parseQuery(\n `task where completed = false and dueDate <= \"{{today}}\" order by dueDate desc limit 5`\n );\n expect(parsedQuery1.table).toBe(\"task\");\n expect(parsedQuery1.orderBy).toBe(\"dueDate\");\n expect(parsedQuery1.orderDesc).toBe(true);\n expect(parsedQuery1.limit).toBe(5);\n expect(parsedQuery1.filter.length).toBe(2);\n expect(parsedQuery1.filter[0]).toStrictEqual({\n op: \"=\",\n prop: \"completed\",\n value: false,\n });\n expect(parsedQuery1.filter[1]).toStrictEqual({\n op: \"<=\",\n prop: \"dueDate\",\n value: \"{{today}}\",\n });\n\n let parsedQuery2 = parseQuery(`page where name =~ /interview\\\\/.*/\"`);\n expect(parsedQuery2.table).toBe(\"page\");\n expect(parsedQuery2.filter.length).toBe(1);\n expect(parsedQuery2.filter[0]).toStrictEqual({\n op: \"=~\",\n prop: \"name\",\n value: \"interview\\\\/.*\",\n });\n\n let parsedQuery3 = parseQuery(`page where something != null`);\n expect(parsedQuery3.table).toBe(\"page\");\n expect(parsedQuery3.filter.length).toBe(1);\n expect(parsedQuery3.filter[0]).toStrictEqual({\n op: \"!=\",\n prop: \"something\",\n value: null,\n });\n\n expect(parseQuery(`page select name`).select).toStrictEqual([\"name\"]);\n expect(parseQuery(`page select name, age`).select).toStrictEqual([\n \"name\",\n \"age\",\n ]);\n\n expect(\n parseQuery(`gh-events where type in [\"PushEvent\", \"somethingElse\"]`)\n ).toStrictEqual({\n table: \"gh-events\",\n filter: [\n {\n op: \"in\",\n prop: \"type\",\n value: [\"PushEvent\", \"somethingElse\"],\n },\n ],\n });\n\n expect(parseQuery(`something render \"template/table\"`)).toStrictEqual({\n table: \"something\",\n filter: [],\n render: \"template/table\",\n });\n});\n\ntest(\"Test performing the queries\", () => {\n let data: any[] = [\n { name: \"interview/My Interview\", lastModified: 1 },\n { name: \"interview/My Interview 2\", lastModified: 2 },\n { name: \"Pete\", age: 38 },\n { name: \"Angie\", age: 28 },\n ];\n\n expect(\n applyQuery(parseQuery(`page where name =~ /interview\\\\/.*/`), data)\n ).toStrictEqual([\n { name: \"interview/My Interview\", lastModified: 1 },\n { name: \"interview/My Interview 2\", lastModified: 2 },\n ]);\n expect(\n applyQuery(\n parseQuery(`page where name =~ /interview\\\\/.*/ order by lastModified`),\n data\n )\n ).toStrictEqual([\n { name: \"interview/My Interview\", lastModified: 1 },\n { name: \"interview/My Interview 2\", lastModified: 2 },\n ]);\n expect(\n applyQuery(\n parseQuery(\n `page where name =~ /interview\\\\/.*/ order by lastModified desc`\n ),\n data\n )\n ).toStrictEqual([\n { name: \"interview/My Interview 2\", lastModified: 2 },\n { name: \"interview/My Interview\", lastModified: 1 },\n ]);\n expect(applyQuery(parseQuery(`page where age > 30`), data)).toStrictEqual([\n { name: \"Pete\", age: 38 },\n ]);\n expect(\n applyQuery(parseQuery(`page where age > 28 and age < 38`), data)\n ).toStrictEqual([]);\n expect(\n applyQuery(parseQuery(`page where age > 30 select name`), data)\n ).toStrictEqual([{ name: \"Pete\" }]);\n\n expect(\n applyQuery(parseQuery(`page where name in [\"Pete\"] select name`), data)\n ).toStrictEqual([{ name: \"Pete\" }]);\n});\n","import {\n collectNodesOfType,\n findNodeOfType,\n ParseTree,\n replaceNodesMatching,\n} from \"@silverbulletmd/common/tree\";\nimport { lezerToParseTree } from \"@silverbulletmd/common/parse_tree\";\nimport Handlebars from \"handlebars\";\nimport YAML from \"yaml\";\n\n// @ts-ignore\nimport { parser } from \"./parse-query\";\nimport { readPage } from \"@silverbulletmd/plugos-silverbullet-syscall/space\";\nimport { niceDate } from \"../core/dates\";\n\nexport type QueryProviderEvent = {\n query: ParsedQuery;\n pageName: string;\n};\n\nexport type Filter = {\n op: string;\n prop: string;\n value: any;\n};\n\nexport type ParsedQuery = {\n table: string;\n orderBy?: string;\n orderDesc?: boolean;\n limit?: number;\n filter: Filter[];\n select?: string[];\n render?: string;\n};\n\nexport function parseQuery(query: string): ParsedQuery {\n let n = lezerToParseTree(query, parser.parse(query).topNode);\n // Clean the tree a bit\n replaceNodesMatching(n, (n) => {\n if (!n.type) {\n let trimmed = n.text!.trim();\n if (!trimmed) {\n return null;\n }\n n.text = trimmed;\n }\n });\n\n // console.log(\"Parsed\", JSON.stringify(n, null, 2));\n\n let queryNode = n.children![0];\n let parsedQuery: ParsedQuery = {\n table: queryNode.children![0].children![0].text!,\n filter: [],\n };\n let orderByNode = findNodeOfType(queryNode, \"OrderClause\");\n if (orderByNode) {\n let nameNode = findNodeOfType(orderByNode, \"Name\");\n parsedQuery.orderBy = nameNode!.children![0].text!;\n let orderNode = findNodeOfType(orderByNode, \"Order\");\n parsedQuery.orderDesc = orderNode\n ? orderNode.children![0].text! === \"desc\"\n : false;\n }\n let limitNode = findNodeOfType(queryNode, \"LimitClause\");\n if (limitNode) {\n let nameNode = findNodeOfType(limitNode, \"Number\");\n parsedQuery.limit = valueNodeToVal(nameNode!);\n }\n\n let filterNodes = collectNodesOfType(queryNode, \"FilterExpr\");\n for (let filterNode of filterNodes) {\n let val: any = undefined;\n let valNode = filterNode.children![2].children![0];\n val = valueNodeToVal(valNode);\n let f: Filter = {\n prop: filterNode.children![0].children![0].text!,\n op: filterNode.children![1].text!,\n value: val,\n };\n parsedQuery.filter.push(f);\n }\n let selectNode = findNodeOfType(queryNode, \"SelectClause\");\n if (selectNode) {\n // console.log(\"Select node\", JSON.stringify(selectNode));\n parsedQuery.select = [];\n collectNodesOfType(selectNode, \"Name\").forEach((t) => {\n parsedQuery.select!.push(t.children![0].text!);\n });\n // let nameNode = findNodeOfType(selectNode, \"Number\");\n // parsedQuery.limit = +nameNode!.children![0].text!;\n }\n\n let renderNode = findNodeOfType(queryNode, \"RenderClause\");\n if (renderNode) {\n let renderNameNode = findNodeOfType(renderNode, \"String\");\n parsedQuery.render = valueNodeToVal(renderNameNode!);\n }\n\n // console.log(JSON.stringify(queryNode, null, 2));\n return parsedQuery;\n}\n\nfunction valueNodeToVal(valNode: ParseTree): any {\n switch (valNode.type) {\n case \"Number\":\n return +valNode.children![0].text!;\n case \"Bool\":\n return valNode.children![0].text! === \"true\";\n case \"Null\":\n return null;\n case \"Name\":\n return valNode.children![0].text!;\n case \"Regex\":\n let val = valNode.children![0].text!;\n return val.substring(1, val.length - 1);\n case \"String\":\n let stringVal = valNode.children![0].text!;\n return stringVal.substring(1, stringVal.length - 1);\n case \"List\":\n return collectNodesOfType(valNode, \"Value\").map((t) =>\n valueNodeToVal(t.children![0])\n );\n }\n}\n\nexport function applyQuery(parsedQuery: ParsedQuery, records: T[]): T[] {\n let resultRecords: any[] = [];\n if (parsedQuery.filter.length === 0) {\n resultRecords = records.slice();\n } else {\n recordLoop: for (let record of records) {\n const recordAny: any = record;\n for (let { op, prop, value } of parsedQuery.filter) {\n switch (op) {\n case \"=\":\n if (!(recordAny[prop] == value)) {\n continue recordLoop;\n }\n break;\n case \"!=\":\n if (!(recordAny[prop] != value)) {\n continue recordLoop;\n }\n break;\n case \"<\":\n if (!(recordAny[prop] < value)) {\n continue recordLoop;\n }\n break;\n case \"<=\":\n if (!(recordAny[prop] <= value)) {\n continue recordLoop;\n }\n break;\n case \">\":\n if (!(recordAny[prop] > value)) {\n continue recordLoop;\n }\n break;\n case \">=\":\n if (!(recordAny[prop] >= value)) {\n continue recordLoop;\n }\n break;\n case \"=~\":\n // TODO: Cache regexps somehow\n if (!new RegExp(value).exec(recordAny[prop])) {\n continue recordLoop;\n }\n break;\n case \"!=~\":\n if (new RegExp(value).exec(recordAny[prop])) {\n continue recordLoop;\n }\n break;\n case \"in\":\n if (!value.includes(recordAny[prop])) {\n continue recordLoop;\n }\n break;\n }\n }\n resultRecords.push(recordAny);\n }\n }\n // Now the sorting\n if (parsedQuery.orderBy) {\n resultRecords = resultRecords.sort((a: any, b: any) => {\n const orderBy = parsedQuery.orderBy!;\n const orderDesc = parsedQuery.orderDesc!;\n if (a[orderBy] === b[orderBy]) {\n return 0;\n }\n\n if (a[orderBy] < b[orderBy]) {\n return orderDesc ? 1 : -1;\n } else {\n return orderDesc ? -1 : 1;\n }\n });\n }\n if (parsedQuery.limit) {\n resultRecords = resultRecords.slice(0, parsedQuery.limit);\n }\n if (parsedQuery.select) {\n resultRecords = resultRecords.map((rec) => {\n let newRec: any = {};\n for (let k of parsedQuery.select!) {\n newRec[k] = rec[k];\n }\n return newRec;\n });\n }\n return resultRecords;\n}\n\nexport async function renderQuery(\n parsedQuery: ParsedQuery,\n data: any[]\n): Promise {\n if (parsedQuery.render) {\n Handlebars.registerHelper(\"json\", (v) => JSON.stringify(v));\n Handlebars.registerHelper(\"niceDate\", (ts) => niceDate(new Date(ts)));\n Handlebars.registerHelper(\"yaml\", (v, prefix) => {\n if (typeof prefix === \"string\") {\n let yaml = YAML.stringify(v)\n .split(\"\\n\")\n .join(\"\\n\" + prefix)\n .trim();\n if (Array.isArray(v)) {\n return \"\\n\" + prefix + yaml;\n } else {\n return yaml;\n }\n } else {\n return YAML.stringify(v).trim();\n }\n });\n let { text: templateText } = await readPage(parsedQuery.render);\n let template = Handlebars.compile(templateText, { noEscape: true });\n return template(data);\n }\n\n return \"ERROR\";\n}\n","export type ParseTree = {\n type?: string; // undefined === text node\n from?: number;\n to?: number;\n text?: string;\n children?: ParseTree[];\n // Only present after running addParentPointers\n parent?: ParseTree;\n};\n\nexport function addParentPointers(tree: ParseTree) {\n if (!tree.children) {\n return;\n }\n for (let child of tree.children) {\n if (child.parent) {\n // Already added parent pointers before\n return;\n }\n child.parent = tree;\n addParentPointers(child);\n }\n}\n\nexport function removeParentPointers(tree: ParseTree) {\n delete tree.parent;\n if (!tree.children) {\n return;\n }\n for (let child of tree.children) {\n removeParentPointers(child);\n }\n}\n\nexport function findParentMatching(\n tree: ParseTree,\n matchFn: (tree: ParseTree) => boolean\n): ParseTree | null {\n let node = tree.parent;\n while (node) {\n if (matchFn(node)) {\n return node;\n }\n node = node.parent;\n }\n return null;\n}\n\nexport function collectNodesOfType(\n tree: ParseTree,\n nodeType: string\n): ParseTree[] {\n return collectNodesMatching(tree, (n) => n.type === nodeType);\n}\n\nexport function collectNodesMatching(\n tree: ParseTree,\n matchFn: (tree: ParseTree) => boolean\n): ParseTree[] {\n if (matchFn(tree)) {\n return [tree];\n }\n let results: ParseTree[] = [];\n if (tree.children) {\n for (let child of tree.children) {\n results = [...results, ...collectNodesMatching(child, matchFn)];\n }\n }\n return results;\n}\n\n// return value: returning undefined = not matched, continue, null = delete, new node = replace\nexport function replaceNodesMatching(\n tree: ParseTree,\n substituteFn: (tree: ParseTree) => ParseTree | null | undefined\n) {\n if (tree.children) {\n let children = tree.children.slice();\n for (let child of children) {\n let subst = substituteFn(child);\n if (subst !== undefined) {\n let pos = tree.children.indexOf(child);\n if (subst) {\n tree.children.splice(pos, 1, subst);\n } else {\n // null = delete\n tree.children.splice(pos, 1);\n }\n } else {\n replaceNodesMatching(child, substituteFn);\n }\n }\n }\n}\n\nexport function findNodeMatching(\n tree: ParseTree,\n matchFn: (tree: ParseTree) => boolean\n): ParseTree | null {\n return collectNodesMatching(tree, matchFn)[0];\n}\n\nexport function findNodeOfType(\n tree: ParseTree,\n nodeType: string\n): ParseTree | null {\n return collectNodesMatching(tree, (n) => n.type === nodeType)[0];\n}\n\n// Finds non-text node at position\nexport function nodeAtPos(tree: ParseTree, pos: number): ParseTree | null {\n if (pos < tree.from! || pos > tree.to!) {\n return null;\n }\n if (!tree.children) {\n return tree;\n }\n for (let child of tree.children) {\n let n = nodeAtPos(child, pos);\n if (n && n.text !== undefined) {\n // Got a text node, let's return its parent\n return tree;\n } else if (n) {\n // Got it\n return n;\n }\n }\n return null;\n}\n\n// Turn ParseTree back into text\nexport function renderToText(tree: ParseTree): string {\n let pieces: string[] = [];\n if (tree.text !== undefined) {\n return tree.text;\n }\n for (let child of tree.children!) {\n pieces.push(renderToText(child));\n }\n return pieces.join(\"\");\n}\n","import type { SyntaxNode } from \"@lezer/common\";\nimport type { Language } from \"@codemirror/language\";\nimport { ParseTree } from \"./tree\";\n\nexport function lezerToParseTree(\n text: string,\n n: SyntaxNode,\n offset = 0\n): ParseTree {\n let children: ParseTree[] = [];\n let nodeText: string | undefined;\n let child = n.firstChild;\n while (child) {\n children.push(lezerToParseTree(text, child));\n child = child.nextSibling;\n }\n\n if (children.length === 0) {\n children = [\n {\n from: n.from + offset,\n to: n.to + offset,\n text: text.substring(n.from, n.to),\n },\n ];\n } else {\n let newChildren: ParseTree[] = [];\n let index = n.from;\n for (let child of children) {\n let s = text.substring(index, child.from);\n if (s) {\n newChildren.push({\n from: index + offset,\n to: child.from! + offset,\n text: s,\n });\n }\n newChildren.push(child);\n index = child.to!;\n }\n let s = text.substring(index, n.to);\n if (s) {\n newChildren.push({ from: index + offset, to: n.to + offset, text: s });\n }\n children = newChildren;\n }\n\n let result: ParseTree = {\n type: n.name,\n from: n.from + offset,\n to: n.to + offset,\n };\n if (children.length > 0) {\n result.children = children;\n }\n if (nodeText) {\n result.text = nodeText;\n }\n return result;\n}\n\nexport function parse(language: Language, text: string): ParseTree {\n let tree = lezerToParseTree(text, language.parser.parse(text).topNode);\n // replaceNodesMatching(tree, (n): MarkdownTree | undefined | null => {\n // if (n.type === \"FencedCode\") {\n // let infoN = findNodeMatching(n, (n) => n.type === \"CodeInfo\");\n // let language = infoN!.children![0].text;\n // let textN = findNodeMatching(n, (n) => n.type === \"CodeText\");\n // let text = textN!.children![0].text!;\n //\n // console.log(language, text);\n // switch (language) {\n // case \"yaml\":\n // let parsed = StreamLanguage.define(yaml).parser.parse(text);\n // let subTree = treeToAST(text, parsed.topNode, n.from);\n // // console.log(JSON.stringify(subTree, null, 2));\n // subTree.type = \"yaml\";\n // return subTree;\n // }\n // }\n // return;\n // });\n return tree;\n}\n","// This file was generated by lezer-generator. You probably shouldn't edit it.\nimport {LRParser} from \"@lezer/lr\"\nexport const parser = LRParser.deserialize({\n version: 13,\n states: \"&fOVQPOOOmQQO'#C^QOQPOOOtQPO'#C`OyQQO'#CkO!OQPO'#CmO!TQPO'#CnO!YQPO'#CoOOQO'#Cp'#CpO!_QQO,58xO!fQQO'#CcO#TQQO'#CaOOQO'#Ca'#CaOOQO,58z,58zO#lQPO,59VOOQO,59X,59XO#qQQO'#D`OOQO,59Y,59YOOQO,59Z,59ZOOQO-E6n-E6nO$YQQO,58}OtQPO,58|O$qQQO1G.qO%]QPO'#CrO%bQQO,59zOOQO'#Cg'#CgOOQO'#Ci'#CiO$YQQO'#CjOOQO'#Cd'#CdOOQO1G.i1G.iOOQO1G.h1G.hOOQO'#Cl'#ClOOQO7+$]7+$]OOQO,59^,59^OOQO-E6p-E6pO%yQPO'#C|O&RQPO,59UO$YQQO'#CqO&WQPO,59hOOQO1G.p1G.pOOQO,59],59]OOQO-E6o-E6o\",\n stateData: \"&`~OiOS~ORPO~OjRO|SO!QTO!RUO!TVO~OgQX~P[ORYO~O}^O~OX_O~OR`O~OYbO~OgQa~P[OkdOsdOtdOudOvdOwdOxdOydOzdO~O{eOgTXjTX|TX!QTX!RTX!TTX~ORfO~OqgOg!SXj!SX|!SX!Q!SX!R!SX!T!SX~OXlOYlO[lOliOmiOnjOokO~O!OoO!PoOg_ij_i|_i!Q_i!R_i!T_i~ORqO~OqgOg!Saj!Sa|!Sa!Q!Sa!R!Sa!T!Sa~OquOrpX~OrwO~OquOrpa~O\",\n goto: \"#d!TPP!UP!X!]!`!c!iPP!rP!r!r!X!w!X!X!X!z#Q#WPPPPPPPPP#^PPPPPPPPPPPPPPPPP#aRQOTWPXR]RR[RQZRRneQmdQskRxuVldkuRpfQXPRcXQvsRyvQh`RrhRtkRaU\",\n nodeNames: \"⚠ Program Query Name WhereClause LogicalExpr AndExpr FilterExpr Value Number String Bool Regex Null List OrderClause Order LimitClause SelectClause RenderClause\",\n maxTerm: 51,\n skippedNodes: [0],\n repeatNodeCount: 3,\n tokenData: \"Ap~R}X^$Opq$Oqr$srs%W|}%r}!O%w!P!Q&Y!Q!['P!^!_'X!_!`'f!`!a's!c!}%w!}#O(Q#P#Q(V#R#S%w#T#U([#U#V*q#V#W%w#W#X+m#X#Y%w#Y#Z-i#Z#]%w#]#^/y#^#`%w#`#a0u#a#b%w#b#c3Y#c#d5U#d#f%w#f#g7i#g#h:e#h#i=a#i#k%w#k#l?]#l#o%w#y#z$O$f$g$O#BY#BZ$O$IS$I_$O$Ip$Iq%W$Iq$Ir%W$I|$JO$O$JT$JU$O$KV$KW$O&FU&FV$O~$TYi~X^$Opq$O#y#z$O$f$g$O#BY#BZ$O$IS$I_$O$I|$JO$O$JT$JU$O$KV$KW$O&FU&FV$O~$vP!_!`$y~%OPu~#r#s%R~%WOy~~%ZUOr%Wrs%ms$Ip%W$Ip$Iq%m$Iq$Ir%m$Ir~%W~%rOY~~%wOq~P%|SRP}!O%w!c!}%w#R#S%w#T#o%w~&_V[~OY&YZ]&Y^!P&Y!P!Q&t!Q#O&Y#O#P&y#P~&Y~&yO[~~&|PO~&Y~'UPX~!Q!['P~'^Pk~!_!`'a~'fOs~~'kPt~#r#s'n~'sOx~~'xPw~!_!`'{~(QOv~~(VOo~~([Or~R(aWRP}!O%w!c!}%w#R#S%w#T#b%w#b#c(y#c#g%w#g#h)u#h#o%wR)OURP}!O%w!c!}%w#R#S%w#T#W%w#W#X)b#X#o%wR)iS{QRP}!O%w!c!}%w#R#S%w#T#o%wR)zURP}!O%w!c!}%w#R#S%w#T#V%w#V#W*^#W#o%wR*eS!PQRP}!O%w!c!}%w#R#S%w#T#o%wR*vURP}!O%w!c!}%w#R#S%w#T#m%w#m#n+Y#n#o%wR+aS}QRP}!O%w!c!}%w#R#S%w#T#o%wR+rURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y,U#Y#o%wR,ZURP}!O%w!c!}%w#R#S%w#T#g%w#g#h,m#h#o%wR,rURP}!O%w!c!}%w#R#S%w#T#V%w#V#W-U#W#o%wR-]S!OQRP}!O%w!c!}%w#R#S%w#T#o%wR-nTRP}!O%w!c!}%w#R#S%w#T#U-}#U#o%wR.SURP}!O%w!c!}%w#R#S%w#T#`%w#`#a.f#a#o%wR.kURP}!O%w!c!}%w#R#S%w#T#g%w#g#h.}#h#o%wR/SURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y/f#Y#o%wR/mSmQRP}!O%w!c!}%w#R#S%w#T#o%wR0OURP}!O%w!c!}%w#R#S%w#T#b%w#b#c0b#c#o%wR0iSzQRP}!O%w!c!}%w#R#S%w#T#o%wR0zURP}!O%w!c!}%w#R#S%w#T#]%w#]#^1^#^#o%wR1cURP}!O%w!c!}%w#R#S%w#T#a%w#a#b1u#b#o%wR1zURP}!O%w!c!}%w#R#S%w#T#]%w#]#^2^#^#o%wR2cURP}!O%w!c!}%w#R#S%w#T#h%w#h#i2u#i#o%wR2|S!QQRP}!O%w!c!}%w#R#S%w#T#o%wR3_URP}!O%w!c!}%w#R#S%w#T#i%w#i#j3q#j#o%wR3vURP}!O%w!c!}%w#R#S%w#T#`%w#`#a4Y#a#o%wR4_URP}!O%w!c!}%w#R#S%w#T#`%w#`#a4q#a#o%wR4xSnQRP}!O%w!c!}%w#R#S%w#T#o%wR5ZURP}!O%w!c!}%w#R#S%w#T#f%w#f#g5m#g#o%wR5rURP}!O%w!c!}%w#R#S%w#T#W%w#W#X6U#X#o%wR6ZURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y6m#Y#o%wR6rURP}!O%w!c!}%w#R#S%w#T#f%w#f#g7U#g#o%wR7]S|QRP}!O%w!c!}%w#R#S%w#T#o%wR7nURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y8Q#Y#o%wR8VURP}!O%w!c!}%w#R#S%w#T#b%w#b#c8i#c#o%wR8nURP}!O%w!c!}%w#R#S%w#T#W%w#W#X9Q#X#o%wR9VURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y9i#Y#o%wR9nURP}!O%w!c!}%w#R#S%w#T#f%w#f#g:Q#g#o%wR:XS!TQRP}!O%w!c!}%w#R#S%w#T#o%wR:jURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y:|#Y#o%wR;RURP}!O%w!c!}%w#R#S%w#T#`%w#`#a;e#a#o%wR;jURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y;|#Y#o%wRa#j#o%wR>fURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y>x#Y#o%wR?PSlQRP}!O%w!c!}%w#R#S%w#T#o%wR?bURP}!O%w!c!}%w#R#S%w#T#[%w#[#]?t#]#o%wR?yURP}!O%w!c!}%w#R#S%w#T#X%w#X#Y@]#Y#o%wR@bURP}!O%w!c!}%w#R#S%w#T#f%w#f#g@t#g#o%wR@yURP}!O%w!c!}%w#R#S%w#T#X%w#X#YA]#Y#o%wRAdSjQRP}!O%w!c!}%w#R#S%w#T#o%w\",\n tokenizers: [0, 1],\n topRules: {\"Program\":[0,1]},\n tokenPrec: 0\n})\n","import { syscall } from \"./syscall\";\nimport { PageMeta } from \"../common/types\";\n\nexport async function listPages(unfiltered = false): Promise {\n return syscall(\"space.listPages\", unfiltered);\n}\n\nexport async function readPage(\n name: string\n): Promise<{ text: string; meta: PageMeta }> {\n return syscall(\"space.readPage\", name);\n}\n\nexport async function writePage(name: string, text: string): Promise {\n return syscall(\"space.writePage\", name, text);\n}\n\nexport async function deletePage(name: string): Promise {\n return syscall(\"space.deletePage\", name);\n}\n","declare global {\n function syscall(name: string, ...args: any[]): Promise;\n}\n\nexport const syscall = self.syscall;\n","import { insertAtCursor } from \"@silverbulletmd/plugos-silverbullet-syscall/editor\";\n\nconst dateMatchRegex = /(\\d{4}\\-\\d{2}\\-\\d{2})/g;\n\nexport function niceDate(d: Date): string {\n return d.toISOString().split(\"T\")[0];\n}\n\nexport async function insertToday() {\n await insertAtCursor(niceDate(new Date()));\n}\n\nexport async function insertTomorrow() {\n let d = new Date();\n d.setDate(d.getDate() + 1);\n await insertAtCursor(niceDate(d));\n}\n","import { syscall } from \"./syscall\";\nimport { FilterOption } from \"../common/types\";\n\nexport function getCurrentPage(): Promise {\n return syscall(\"editor.getCurrentPage\");\n}\n\nexport function setPage(newName: string): Promise {\n return syscall(\"editor.setPage\", newName);\n}\n\nexport function getText(): Promise {\n return syscall(\"editor.getText\");\n}\n\nexport function getCursor(): Promise {\n return syscall(\"editor.getCursor\");\n}\n\nexport function save(): Promise {\n return syscall(\"editor.save\");\n}\n\nexport function navigate(name: string, pos?: number): Promise {\n return syscall(\"editor.navigate\", name, pos);\n}\n\nexport function reloadPage(): Promise {\n return syscall(\"editor.reloadPage\");\n}\n\nexport function openUrl(url: string): Promise {\n return syscall(\"editor.openUrl\", url);\n}\n\nexport function flashNotification(message: string): Promise {\n return syscall(\"editor.flashNotification\", message);\n}\n\nexport function filterBox(\n label: string,\n options: FilterOption[],\n helpText: string = \"\",\n placeHolder: string = \"\"\n): Promise {\n return syscall(\"editor.filterBox\", label, options, helpText, placeHolder);\n}\n\nexport function showRhs(\n html: string,\n script?: string,\n flex = 1\n): Promise {\n return syscall(\"editor.showRhs\", html, script, flex);\n}\n\nexport function hideRhs(): Promise {\n return syscall(\"editor.hideRhs\");\n}\n\nexport function showLhs(\n html: string,\n script?: string,\n flex = 1\n): Promise {\n return syscall(\"editor.showLhs\", html, script, flex);\n}\n\nexport function hideLhs(): Promise {\n return syscall(\"editor.hideLhs\");\n}\n\nexport function showBhs(\n html: string,\n script?: string,\n flex = 1\n): Promise {\n return syscall(\"editor.showBhs\", html, script, flex);\n}\n\nexport function hideBhs(): Promise {\n return syscall(\"editor.hideBhs\");\n}\n\nexport function insertAtPos(text: string, pos: number): Promise {\n return syscall(\"editor.insertAtPos\", text, pos);\n}\n\nexport function replaceRange(\n from: number,\n to: number,\n text: string\n): Promise {\n return syscall(\"editor.replaceRange\", from, to, text);\n}\n\nexport function moveCursor(pos: number): Promise {\n return syscall(\"editor.moveCursor\", pos);\n}\n\nexport function insertAtCursor(text: string): Promise {\n return syscall(\"editor.insertAtCursor\", text);\n}\n\nexport function matchBefore(\n re: string\n): Promise<{ from: number; to: number; text: string } | null> {\n return syscall(\"editor.matchBefore\", re);\n}\n\nexport function dispatch(change: any): Promise {\n return syscall(\"editor.dispatch\", change);\n}\n\nexport function prompt(\n message: string,\n defaultValue = \"\"\n): Promise {\n return syscall(\"editor.prompt\", message, defaultValue);\n}\n"],"names":[],"version":3,"file":"engine.test.js.map","sourceRoot":"../../../../"} \ No newline at end of file diff --git a/packages/plugs/core/item.ts b/packages/plugs/core/item.ts index a36c107d..4b3fe584 100644 --- a/packages/plugs/core/item.ts +++ b/packages/plugs/core/item.ts @@ -2,7 +2,7 @@ import type { IndexTreeEvent } from "@silverbulletmd/web/app_event"; import { batchSet, - scanPrefixGlobal, + queryPrefix, } from "@silverbulletmd/plugos-silverbullet-syscall/index"; import { collectNodesOfType, @@ -61,7 +61,7 @@ export async function queryProvider({ query, }: QueryProviderEvent): Promise { let allItems: Item[] = []; - for (let { key, page, value } of await scanPrefixGlobal("it:")) { + for (let { key, page, value } of await queryPrefix("it:")) { let [, pos] = key.split(":"); allItems.push({ ...value, diff --git a/packages/plugs/core/page.ts b/packages/plugs/core/page.ts index a2f4fad3..830868b7 100644 --- a/packages/plugs/core/page.ts +++ b/packages/plugs/core/page.ts @@ -3,7 +3,7 @@ import { batchSet, clearPageIndex as clearPageIndexSyscall, clearPageIndexForPage, - scanPrefixGlobal, + queryPrefix, set, } from "@silverbulletmd/plugos-silverbullet-syscall/index"; import { @@ -73,7 +73,7 @@ export async function pageQueryProvider({ let allPageMap: Map = new Map( allPages.map((pm) => [pm.name, pm]) ); - for (let { page, value } of await scanPrefixGlobal("meta:")) { + for (let { page, value } of await queryPrefix("meta:")) { let p = allPageMap.get(page); if (p) { for (let [k, v] of Object.entries(value)) { @@ -90,7 +90,7 @@ export async function linkQueryProvider({ pageName, }: QueryProviderEvent): Promise { let uniqueLinks = new Set(); - for (let { value: name } of await scanPrefixGlobal(`pl:${pageName}:`)) { + for (let { value: name } of await queryPrefix(`pl:${pageName}:`)) { uniqueLinks.add(name); } return applyQuery( @@ -176,7 +176,7 @@ type BackLink = { }; async function getBackLinks(pageName: string): Promise { - let allBackLinks = await scanPrefixGlobal(`pl:${pageName}:`); + let allBackLinks = await queryPrefix(`pl:${pageName}:`); let pagesToUpdate: BackLink[] = []; for (let { key, value } of allBackLinks) { let keyParts = key.split(":"); diff --git a/packages/plugs/query/data.ts b/packages/plugs/query/data.ts index ce0be8f5..5508e705 100644 --- a/packages/plugs/query/data.ts +++ b/packages/plugs/query/data.ts @@ -4,7 +4,7 @@ import type { IndexTreeEvent } from "@silverbulletmd/web/app_event"; import { batchSet, - scanPrefixGlobal, + queryPrefix, } from "@silverbulletmd/plugos-silverbullet-syscall"; import { collectNodesOfType, @@ -102,7 +102,7 @@ export async function queryProvider({ query, }: QueryProviderEvent): Promise { let allData: any[] = []; - for (let { key, page, value } of await scanPrefixGlobal("data:")) { + for (let { key, page, value } of await queryPrefix("data:")) { let [, pos] = key.split("@"); allData.push({ ...value, diff --git a/packages/plugs/query/engine.ts b/packages/plugs/query/engine.ts index 7c0adbec..2024cf7b 100644 --- a/packages/plugs/query/engine.ts +++ b/packages/plugs/query/engine.ts @@ -221,7 +221,6 @@ export async function renderQuery( data: any[] ): Promise { if (parsedQuery.render) { - console.log("Handlebars", Handlebars); Handlebars.registerHelper("json", (v) => JSON.stringify(v)); Handlebars.registerHelper("niceDate", (ts) => niceDate(new Date(ts))); Handlebars.registerHelper("yaml", (v, prefix) => { diff --git a/packages/plugs/query/materialized_queries.ts b/packages/plugs/query/materialized_queries.ts index f55f2525..c600e313 100644 --- a/packages/plugs/query/materialized_queries.ts +++ b/packages/plugs/query/materialized_queries.ts @@ -22,25 +22,24 @@ export async function updateMaterializedQueriesCommand() { const currentPage = await getCurrentPage(); await save(); await flashNotification("Updating materialized queries..."); - await invokeFunction( - "server", - "updateMaterializedQueriesOnPage", - currentPage - ); - await reloadPage(); -} - -export async function whiteOutQueriesCommand() { - const text = await getText(); - const parsed = await parseMarkdown(text); - console.log(removeQueries(parsed)); + if ( + await invokeFunction( + "server", + "updateMaterializedQueriesOnPage", + currentPage + ) + ) { + await reloadPage(); + } } // Called from client, running on server -export async function updateMaterializedQueriesOnPage(pageName: string) { +export async function updateMaterializedQueriesOnPage( + pageName: string +): Promise { let { text } = await readPage(pageName); - text = await replaceAsync( + let newText = await replaceAsync( text, queryRegex, async (fullMatch, startQuery, query, body, endQuery) => { @@ -68,6 +67,9 @@ export async function updateMaterializedQueriesOnPage(pageName: string) { } } ); - // console.log("New text", text); - await writePage(pageName, text); + if (text !== newText) { + await writePage(pageName, newText); + return true; + } + return false; } diff --git a/packages/plugs/query/query.plug.yaml b/packages/plugs/query/query.plug.yaml index 6d5f55fd..7e332cbd 100644 --- a/packages/plugs/query/query.plug.yaml +++ b/packages/plugs/query/query.plug.yaml @@ -12,10 +12,8 @@ functions: key: "Alt-q" button: label: "🔄" - whiteOutQueriesCommand: - path: ./materialized_queries.ts:whiteOutQueriesCommand - command: - name: "Debug: Whiteout Queries" + events: + - editor:pageLoaded indexData: path: ./data.ts:indexData events: diff --git a/packages/plugs/search/search.ts b/packages/plugs/search/search.ts index 7912e1ee..7cd5d855 100644 --- a/packages/plugs/search/search.ts +++ b/packages/plugs/search/search.ts @@ -1,7 +1,7 @@ import { fullTextIndex, fullTextSearch } from "@plugos/plugos-syscall/fulltext"; import { renderToText } from "@silverbulletmd/common/tree"; import { PageMeta } from "@silverbulletmd/common/types"; -import { scanPrefixGlobal } from "@silverbulletmd/plugos-silverbullet-syscall"; +import { queryPrefix } from "@silverbulletmd/plugos-silverbullet-syscall"; import { navigate, prompt, @@ -28,7 +28,7 @@ export async function queryProvider({ let allPageMap: Map = new Map( results.map((r: any) => [r.name, r]) ); - for (let { page, value } of await scanPrefixGlobal("meta:")) { + for (let { page, value } of await queryPrefix("meta:")) { let p = allPageMap.get(page); if (p) { for (let [k, v] of Object.entries(value)) { diff --git a/packages/plugs/tasks/task.ts b/packages/plugs/tasks/task.ts index 10f9d8d0..667aa3f2 100644 --- a/packages/plugs/tasks/task.ts +++ b/packages/plugs/tasks/task.ts @@ -2,7 +2,7 @@ import type { ClickEvent, IndexTreeEvent } from "@silverbulletmd/web/app_event"; import { batchSet, - scanPrefixGlobal, + queryPrefix, } from "@silverbulletmd/plugos-silverbullet-syscall/index"; import { readPage, @@ -197,7 +197,7 @@ export async function queryProvider({ query, }: QueryProviderEvent): Promise { let allTasks: Task[] = []; - for (let { key, page, value } of await scanPrefixGlobal("task:")) { + for (let { key, page, value } of await queryPrefix("task:")) { let [, pos] = key.split(":"); allTasks.push({ ...value, diff --git a/packages/server/express_server.ts b/packages/server/express_server.ts index 56047049..1fd8a1c1 100644 --- a/packages/server/express_server.ts +++ b/packages/server/express_server.ts @@ -10,7 +10,7 @@ import bodyParser from "body-parser"; import { EventHook } from "@plugos/plugos/hooks/event"; import spaceSyscalls from "./syscalls/space"; import { eventSyscalls } from "@plugos/plugos/syscalls/event"; -import { ensurePageIndexTable, pageIndexSyscalls } from "./syscalls"; +import { ensureTable, pageIndexSyscalls } from "./syscalls"; import knex, { Knex } from "knex"; import shellSyscalls from "@plugos/plugos/syscalls/shell.node"; import { NodeCronHook } from "@plugos/plugos/hooks/node_cron"; @@ -207,7 +207,7 @@ export class ExpressServer { next(); }; - await ensurePageIndexTable(this.db); + await ensureTable(this.db); await ensureFTSTable(this.db, "fts"); console.log("Setting up router"); diff --git a/packages/server/syscalls/index.ts b/packages/server/syscalls/index.ts index a70f0a30..e90f04c6 100644 --- a/packages/server/syscalls/index.ts +++ b/packages/server/syscalls/index.ts @@ -1,12 +1,8 @@ import { Knex } from "knex"; import { SysCallMapping } from "@plugos/plugos/system"; +import { Query, queryToKnex } from "@plugos/plugos/syscalls/store.knex_node"; -import { - ensureTable, - storeSyscalls, -} from "@plugos/plugos/syscalls/store.knex_node"; - -type IndexItem = { +type Item = { page: string; key: string; value: any; @@ -17,45 +13,35 @@ export type KV = { value: any; }; -/* - Keyspace design: +const tableName = "page_index"; - for page lookups: - p~page~key +export async function ensureTable(db: Knex) { + if (!(await db.schema.hasTable(tableName))) { + await db.schema.createTable(tableName, (table) => { + table.string("page"); + table.string("key"); + table.text("value"); + table.primary(["page", "key"]); + table.index(["key"]); + }); - for global lookups: - k~key~page - - */ - -function pageKey(page: string, key: string) { - return `p~${page}~${key}`; -} - -function unpackPageKey(dbKey: string): { page: string; key: string } { - const [, page, key] = dbKey.split("~"); - return { page, key }; -} - -function globalKey(page: string, key: string) { - return `k~${key}~${page}`; -} - -function unpackGlobalKey(dbKey: string): { page: string; key: string } { - const [, key, page] = dbKey.split("~"); - return { page, key }; -} - -export async function ensurePageIndexTable(db: Knex) { - await ensureTable(db, "page_index"); + console.log(`Created table ${tableName}`); + } } export function pageIndexSyscalls(db: Knex): SysCallMapping { - const storeCalls = storeSyscalls(db, "page_index"); const apiObj: SysCallMapping = { "index.set": async (ctx, page: string, key: string, value: any) => { - await storeCalls["store.set"](ctx, pageKey(page, key), value); - await storeCalls["store.set"](ctx, globalKey(page, key), value); + let changed = await db(tableName) + .where({ key, page }) + .update("value", JSON.stringify(value)); + if (changed === 0) { + await db(tableName).insert({ + key, + page, + value: JSON.stringify(value), + }); + } }, "index.batchSet": async (ctx, page: string, kvs: KV[]) => { for (let { key, value } of kvs) { @@ -63,53 +49,53 @@ export function pageIndexSyscalls(db: Knex): SysCallMapping { } }, "index.delete": async (ctx, page: string, key: string) => { - await storeCalls["store.delete"](ctx, pageKey(page, key)); - await storeCalls["store.delete"](ctx, globalKey(page, key)); + await db(tableName).where({ key, page }).del(); }, "index.get": async (ctx, page: string, key: string) => { - return storeCalls["store.get"](ctx, pageKey(page, key)); + let result = await db(tableName) + .where({ key, page }) + .select("value"); + if (result.length) { + return JSON.parse(result[0].value); + } else { + return null; + } }, - "index.scanPrefixForPage": async (ctx, page: string, prefix: string) => { + "index.queryPrefix": async (ctx, prefix: string) => { return ( - await storeCalls["store.queryPrefix"](ctx, pageKey(page, prefix)) - ).map(({ key, value }: { key: string; value: any }) => { - const { key: pageKey } = unpackPageKey(key); - return { - page, - key: pageKey, - value, - }; - }); + await db(tableName) + .andWhereLike("key", `${prefix}%`) + .select("key", "value", "page") + ).map(({ key, value, page }) => ({ + key, + page, + value: JSON.parse(value), + })); }, - "index.scanPrefixGlobal": async (ctx, prefix: string) => { - return (await storeCalls["store.queryPrefix"](ctx, `k~${prefix}`)).map( - ({ key, value }: { key: string; value: any }) => { - const { page, key: pageKey } = unpackGlobalKey(key); - return { - page, - key: pageKey, - value, - }; - } - ); + "index.query": async (ctx, query: Query) => { + return ( + await queryToKnex(db(tableName), query).select( + "key", + "value", + "page" + ) + ).map(({ key, value, page }: any) => ({ + key, + page, + value: JSON.parse(value), + })); }, "index.clearPageIndexForPage": async (ctx, page: string) => { await apiObj["index.deletePrefixForPage"](ctx, page, ""); }, "index.deletePrefixForPage": async (ctx, page: string, prefix: string) => { - // Collect all global keys for this page to delete - let keysToDelete = ( - await storeCalls["store.queryPrefix"](ctx, pageKey(page, prefix)) - ).map(({ key }: { key: string; value: string }) => - globalKey(page, unpackPageKey(key).key) - ); - // Delete all page keys - await storeCalls["store.deletePrefix"](ctx, pageKey(page, prefix)); - // console.log("Deleting keys", keysToDelete); - await storeCalls["store.batchDelete"](ctx, keysToDelete); + return db(tableName) + .where({ page }) + .andWhereLike("key", `${prefix}%`) + .del(); }, "index.clearPageIndex": async (ctx) => { - await storeCalls["store.deleteAll"](ctx); + await db(tableName).del(); }, }; return apiObj; diff --git a/packages/web/app_event.ts b/packages/web/app_event.ts index 101f393c..e5709d41 100644 --- a/packages/web/app_event.ts +++ b/packages/web/app_event.ts @@ -1,6 +1,6 @@ import type { ParseTree } from "@silverbulletmd/common/tree"; -export type AppEvent = "page:click" | "page:complete"; +export type AppEvent = "page:click" | "page:complete" | "page:load"; export type ClickEvent = { page: string; diff --git a/packages/web/editor.tsx b/packages/web/editor.tsx index 6b69899f..5a95985b 100644 --- a/packages/web/editor.tsx +++ b/packages/web/editor.tsx @@ -509,6 +509,7 @@ export class Editor { } async loadPage(pageName: string) { + const loadingDifferentPage = pageName !== this.currentPage; const editorView = this.editorView; if (!editorView) { return; @@ -547,7 +548,9 @@ export class Editor { meta: doc.meta, }); - await this.eventHook.dispatchEvent("editor:pageSwitched"); + if (loadingDifferentPage) { + await this.eventHook.dispatchEvent("editor:pageLoaded", pageName); + } } tweakEditorDOM(contentDOM: HTMLElement, readOnly: boolean) { diff --git a/packages/web/syscalls/editor.ts b/packages/web/syscalls/editor.ts index 1ca42c6b..b03db57d 100644 --- a/packages/web/syscalls/editor.ts +++ b/packages/web/syscalls/editor.ts @@ -31,13 +31,6 @@ export function editorSyscalls(editor: Editor): SysCallMapping { "editor.getCurrentPage": (): string => { return editor.currentPage!; }, - // sets the current page name, without changing the content - "editor.setPage": (ctx, newName: string) => { - return editor.viewDispatch({ - type: "page-loaded", - name: newName, - }); - }, "editor.getText": () => { return editor.editorView?.state.sliceDoc(); }, diff --git a/packages/web/syscalls/index.ts b/packages/web/syscalls/index.ts index adee2cff..c0f7f8fc 100644 --- a/packages/web/syscalls/index.ts +++ b/packages/web/syscalls/index.ts @@ -5,8 +5,7 @@ import { Space } from "@silverbulletmd/common/spaces/space"; export function indexerSyscalls(space: Space): SysCallMapping { return proxySyscalls( [ - "index.scanPrefixForPage", - "index.scanPrefixGlobal", + "index.queryPrefix", "index.get", "index.set", "index.batchSet",