@agentshouse/mdruntime 0.1.0-alpha.25 → 0.1.0-alpha.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/observation.ts"],"sourcesContent":["import type { QueryDocument, QueryGroup, QueryResult } from './query.js';\n\nexport type Observation<T> = {\n current(): T;\n subscribe(listener: (value: T) => void): () => void;\n close(): void;\n};\n\nexport type RowKey = string | number;\n\nexport type KeyedResult = { result: QueryResult; keys: readonly RowKey[] };\n\nexport type QueryChange = {\n changed: readonly (readonly [RowKey, QueryDocument | QueryGroup])[];\n removed: readonly RowKey[];\n order: readonly RowKey[] | null;\n};\n\nexport type Observed = {\n observation: Observation<unknown>;\n receive(message: unknown): void;\n end(): void;\n};\n\nexport function rowsOf(result: QueryResult): readonly (QueryDocument | QueryGroup)[] {\n return 'groups' in result ? result.groups : result.documents;\n}\n\nfunction keyedResult(first: KeyedResult) {\n const grouped = 'groups' in first.result;\n const rows = rowsOf(first.result);\n const byKey = new Map(first.keys.map((key, index) => [key, rows[index]]));\n let keys = first.keys;\n return {\n value: first.result,\n next(message: unknown): QueryResult {\n const change = message as QueryChange;\n for (const key of change.removed) byKey.delete(key);\n for (const [key, row] of change.changed) byKey.set(key, row);\n keys = change.order ?? keys.filter((key) => byKey.has(key));\n const next = keys.map((key) => byKey.get(key) as QueryDocument | QueryGroup);\n return grouped\n ? { groups: next as readonly QueryGroup[] }\n : { documents: next as readonly QueryDocument[] };\n },\n };\n}\n\nfunction whole(first: unknown) {\n return { value: first, next: (message: unknown) => message };\n}\n\nexport function observed(first: unknown, stop: () => void, keyed: boolean): Observed {\n const reducer = keyed ? keyedResult(first as KeyedResult) : whole(first);\n let value = reducer.value;\n let open = true;\n const listeners = new Set<{ hear: (value: unknown) => void }>();\n const end = () => {\n open = false;\n listeners.clear();\n };\n return {\n observation: {\n current: () => value,\n subscribe(listener) {\n const entry = { hear: listener };\n if (open) listeners.add(entry);\n return () => {\n listeners.delete(entry);\n };\n },\n close() {\n if (!open) return;\n end();\n stop();\n },\n },\n receive(message) {\n if (!open) return;\n value = reducer.next(message);\n for (const entry of [...listeners]) {\n if (listeners.has(entry)) entry.hear(value);\n }\n },\n end,\n };\n}\n\nexport function opened(\n watch: (deliver: (message: unknown) => void) => () => void,\n keyed: boolean,\n): Promise<Observation<unknown>> {\n return new Promise((resolve, reject) => {\n let handle: Observed | undefined;\n let stop = () => {};\n try {\n stop = watch((message) => {\n if (handle !== undefined) {\n handle.receive(message);\n return;\n }\n handle = observed(message, () => stop(), keyed);\n resolve(handle.observation);\n });\n } catch (error) {\n reject(error);\n }\n });\n}\n"],"names":["rowsOf","result","groups","documents","keyedResult","first","grouped","rows","byKey","Map","keys","map","key","index","value","next","message","change","removed","delete","row","changed","set","order","filter","has","get","whole","observed","stop","keyed","reducer","open","listeners","Set","end","clear","observation","current","subscribe","listener","entry","hear","add","close","receive","opened","watch","Promise","resolve","reject","handle","undefined","error"],"mappings":"AAwBA,OAAO,SAASA,OAAOC,MAAmB;IACxC,OAAO,YAAYA,SAASA,OAAOC,MAAM,GAAGD,OAAOE,SAAS;AAC9D;AAEA,SAASC,YAAYC,KAAkB;IACrC,MAAMC,UAAU,YAAYD,MAAMJ,MAAM;IACxC,MAAMM,OAAOP,OAAOK,MAAMJ,MAAM;IAChC,MAAMO,QAAQ,IAAIC,IAAIJ,MAAMK,IAAI,CAACC,GAAG,CAAC,CAACC,KAAKC,QAAU;YAACD;YAAKL,IAAI,CAACM,MAAM;SAAC;IACvE,IAAIH,OAAOL,MAAMK,IAAI;IACrB,OAAO;QACLI,OAAOT,MAAMJ,MAAM;QACnBc,MAAKC,OAAgB;YACnB,MAAMC,SAASD;YACf,KAAK,MAAMJ,OAAOK,OAAOC,OAAO,CAAEV,MAAMW,MAAM,CAACP;YAC/C,KAAK,MAAM,CAACA,KAAKQ,IAAI,IAAIH,OAAOI,OAAO,CAAEb,MAAMc,GAAG,CAACV,KAAKQ;YACxDV,OAAOO,OAAOM,KAAK,IAAIb,KAAKc,MAAM,CAAC,CAACZ,MAAQJ,MAAMiB,GAAG,CAACb;YACtD,MAAMG,OAAOL,KAAKC,GAAG,CAAC,CAACC,MAAQJ,MAAMkB,GAAG,CAACd;YACzC,OAAON,UACH;gBAAEJ,QAAQa;YAA8B,IACxC;gBAAEZ,WAAWY;YAAiC;QACpD;IACF;AACF;AAEA,SAASY,MAAMtB,KAAc;IAC3B,OAAO;QAAES,OAAOT;QAAOU,MAAM,CAACC,UAAqBA;IAAQ;AAC7D;AAEA,OAAO,SAASY,SAASvB,KAAc,EAAEwB,IAAgB,EAAEC,KAAc;IACvE,MAAMC,UAAUD,QAAQ1B,YAAYC,SAAwBsB,MAAMtB;IAClE,IAAIS,QAAQiB,QAAQjB,KAAK;IACzB,IAAIkB,OAAO;IACX,MAAMC,YAAY,IAAIC;IACtB,MAAMC,MAAM;QACVH,OAAO;QACPC,UAAUG,KAAK;IACjB;IACA,OAAO;QACLC,aAAa;YACXC,SAAS,IAAMxB;YACfyB,WAAUC,QAAQ;gBAChB,MAAMC,QAAQ;oBAAEC,MAAMF;gBAAS;gBAC/B,IAAIR,MAAMC,UAAUU,GAAG,CAACF;gBACxB,OAAO;oBACLR,UAAUd,MAAM,CAACsB;gBACnB;YACF;YACAG;gBACE,IAAI,CAACZ,MAAM;gBACXG;gBACAN;YACF;QACF;QACAgB,SAAQ7B,OAAO;YACb,IAAI,CAACgB,MAAM;YACXlB,QAAQiB,QAAQhB,IAAI,CAACC;YACrB,KAAK,MAAMyB,SAAS;mBAAIR;aAAU,CAAE;gBAClC,IAAIA,UAAUR,GAAG,CAACgB,QAAQA,MAAMC,IAAI,CAAC5B;YACvC;QACF;QACAqB;IACF;AACF;AAEA,OAAO,SAASW,OACdC,KAA0D,EAC1DjB,KAAc;IAEd,OAAO,IAAIkB,QAAQ,CAACC,SAASC;QAC3B,IAAIC;QACJ,IAAItB,OAAO,KAAO;QAClB,IAAI;YACFA,OAAOkB,MAAM,CAAC/B;gBACZ,IAAImC,WAAWC,WAAW;oBACxBD,OAAON,OAAO,CAAC7B;oBACf;gBACF;gBACAmC,SAASvB,SAASZ,SAAS,IAAMa,QAAQC;gBACzCmB,QAAQE,OAAOd,WAAW;YAC5B;QACF,EAAE,OAAOgB,OAAO;YACdH,OAAOG;QACT;IACF;AACF"}
package/dist/query.d.ts CHANGED
@@ -197,6 +197,13 @@ export type Plan = {
197
197
  export declare class QueryError extends Error {
198
198
  constructor(code: QueryErrorCode, at: string, problem: string);
199
199
  }
200
+ type Entries = Readonly<Record<string, unknown>>;
201
+ export declare function invalid(at: string, problem: string): never;
202
+ export declare function plain(value: unknown): value is Entries;
203
+ export declare function known(value: Entries, allowed: readonly string[], at: string): void;
200
204
  export declare function planOf(input: unknown, facts: HeldRooms): Plan;
205
+ export declare function limitOf(input: unknown): number | null;
206
+ export declare function filterOf(input: unknown, facts: HeldRooms): Plan;
201
207
  export declare function identityOf(plan: Plan): string;
208
+ export {};
202
209
  //# sourceMappingURL=query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,sBAAsB,CAAC;AAGlE,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAErD,MAAM,MAAM,SAAS,GACjB,KAAK,GACL;IAAE,GAAG,EAAE,KAAK,CAAA;CAAE,GACd;IAAE,GAAG,EAAE,KAAK,CAAA;CAAE,GACd;IAAE,GAAG,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,GACzB;IAAE,IAAI,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,GAC1B;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IAAC,GAAG,CAAC,EAAE,KAAK,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,GAC1B;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEzB,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IACvB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,KAAK,EAAE,GAAG,SAAS,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExF,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,MAAM,MAAM,MAAM,GACd,KAAK,GACL;IACE,MAAM,CAAC,EAAE,KAAK,GAAG,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB,CAAC;AAEN,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAEvC,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,SAAS,CAAC;QAAE,EAAE,EAAE,GAAG,CAAC;QAAC,SAAS,CAAC,EAAE,SAAS,CAAA;KAAE,GAAG,YAAY,CAAC,EAAE,CAAC;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG;IAChC,OAAO,EAAE,SAAS,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC;IACzC,OAAO,CAAC,EAAE,SAAS;QAAE,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAAC,SAAS,CAAC,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,UAAU,CAAC;AAEpD,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IAAE,GAAG,EAAE,SAAS,OAAO,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG;IAAE,SAAS,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAAC;AAErE,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,CAAC;AAE5D,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,WAAW,CAAC;AAEvD,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,cAAc,GAAG,eAAe,GAAG,YAAY,CAAC;AAE/F,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,IAAI,GACZ;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,GACtC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,CAAA;CAAE,GACnF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtC,MAAM,MAAM,SAAS,GACjB;IAAE,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,SAAS,SAAS,EAAE,CAAA;CAAE,GAC9B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAElC,MAAM,MAAM,KAAK,GAAG;IAClB,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,OAAO,GACf;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GACd;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GACd;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GACd;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,KAAK,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACzC,QAAQ,EAAE,KAAK,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3C,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,SAAS;QAAE,GAAG,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,YAAY,GAAG;YAAE,SAAS,EAAE,SAAS,CAAA;SAAE,CAAA;KAAE,EAAE,CAAC;CACxF,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,SAAS,OAAO,EAAE,CAAC;IAC5B,OAAO,EAAE,SAAS;QAAE,EAAE,EAAE,OAAO,GAAG,MAAM,CAAC;QAAC,SAAS,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;CACpE,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IACrD,KAAK,EAAE,aAAa,GAAG,UAAU,CAAC;IAClC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,qBAAa,UAAW,SAAQ,KAAK;IACnC,YAAY,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAE5D;CACF;AAED,KAAK,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAYjD,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAE1D;AAMD,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAOtD;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,QAI3E;AA8WD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAiB7D;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAMrD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAI/D;AAaD,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE7C"}
package/dist/query.js CHANGED
@@ -25,9 +25,7 @@ const FILTER = [
25
25
  'where',
26
26
  'pathPrefix',
27
27
  'hop',
28
- 'backlinks',
29
- 'orderBy',
30
- 'limit'
28
+ 'backlinks'
31
29
  ];
32
30
  const RELATED = [
33
31
  'types',
@@ -51,16 +49,16 @@ const ORDER = [
51
49
  'localeOptions'
52
50
  ];
53
51
  const CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
54
- function invalid(at, problem) {
52
+ export function invalid(at, problem) {
55
53
  throw new QueryError('invalid-query', at, problem);
56
54
  }
57
55
  function place(at, name) {
58
56
  return at === '' ? name : `${at}.${name}`;
59
57
  }
60
- function plain(value) {
58
+ export function plain(value) {
61
59
  return typeof value === 'object' && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
62
60
  }
63
- function known(value, allowed, at) {
61
+ export function known(value, allowed, at) {
64
62
  for (const name of Object.keys(value)){
65
63
  if (!allowed.includes(name)) invalid(place(at, name), 'unknown part');
66
64
  }
@@ -424,11 +422,11 @@ export function planOf(input, facts) {
424
422
  if (!grouped && input.select === undefined) invalid('select', 'a Document query must select');
425
423
  known(input, [
426
424
  ...FILTER,
425
+ 'orderBy',
426
+ 'limit',
427
427
  grouped ? 'groupBy' : 'select'
428
428
  ], '');
429
- if (input.limit !== undefined && (!Number.isSafeInteger(input.limit) || input.limit < 0)) {
430
- invalid('limit', 'expects a nonnegative integer');
431
- }
429
+ const limit = limitOf(input.limit);
432
430
  const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');
433
431
  const { typed, ...root } = scope(facts, rooms, input, '');
434
432
  return {
@@ -437,9 +435,24 @@ export function planOf(input, facts) {
437
435
  hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),
438
436
  backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),
439
437
  shape: grouped ? groupShape(typed, input) : documentShape(typed, input),
440
- limit: input.limit ?? null
438
+ limit
441
439
  };
442
440
  }
441
+ export function limitOf(input) {
442
+ if (input === undefined) return null;
443
+ if (!Number.isSafeInteger(input) || input < 0) {
444
+ invalid('limit', 'expects a nonnegative integer');
445
+ }
446
+ return input;
447
+ }
448
+ export function filterOf(input, facts) {
449
+ if (!plain(input)) invalid('documents', 'expects a filter object');
450
+ known(input, FILTER, '');
451
+ return planOf({
452
+ ...input,
453
+ select: {}
454
+ }, facts);
455
+ }
443
456
  function canonical(value) {
444
457
  if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
445
458
  if (typeof value === 'object' && value !== null) {
package/dist/query.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdruntime/src/query.ts"],"sourcesContent":["import type { Definition, FieldSpec } from '@agentshouse/mdmodel';\nimport { normalize } from './paths.js';\n\nexport type Value = string | number | boolean | null;\n\nexport type Predicate =\n | Value\n | { $eq: Value }\n | { $ne: Value }\n | { $in: readonly Value[] }\n | { $nin: readonly Value[] }\n | { $gt?: Value; $gte?: Value; $lt?: Value; $lte?: Value }\n | { $all: readonly Value[] }\n | { $size: number }\n | { $exists: boolean };\n\nexport type Where = {\n $and?: readonly Where[];\n $or?: readonly Where[];\n [field: string]: Predicate | readonly Where[] | undefined;\n};\n\nexport type Related = { types?: readonly string[]; where?: Where; pathPrefix?: string };\n\nexport type Filter = {\n rooms?: readonly string[];\n types?: readonly string[];\n where?: Where;\n pathPrefix?: string;\n hop?: Related & { field: string };\n backlinks?: Related & { field?: string };\n};\n\nexport type Key = 'room' | 'path' | 'type' | { field: string };\n\nexport type Select =\n | 'all'\n | {\n fields?: 'all' | readonly string[];\n sections?: 'all' | readonly string[];\n preamble?: true;\n markdown?: true;\n backlinks?: true;\n };\n\nexport type OrderOptions = {\n nulls?: 'first' | 'last';\n stringSort?: 'lexical' | 'locale';\n locale?: string;\n localeOptions?: Readonly<Record<string, unknown>>;\n};\n\nexport type Direction = 'asc' | 'desc';\n\nexport type DocumentQuery = Filter & {\n select: Select;\n orderBy?: readonly ({ by: Key; direction?: Direction } & OrderOptions)[];\n limit?: number;\n};\n\nexport type GroupQuery = Filter & {\n groupBy: readonly Exclude<Key, 'path'>[];\n orderBy?: readonly { by: 'count' | Exclude<Key, 'path'>; direction?: Direction }[];\n limit?: number;\n};\n\nexport type LocalQuery = DocumentQuery | GroupQuery;\n\nexport type Backlink = { path: string; type: string; field: string };\n\nexport type QueryDocument = {\n room: string;\n path: string;\n type: string;\n fields?: Readonly<Record<string, unknown>>;\n sections?: Readonly<Record<string, string>>;\n preamble?: string;\n markdown?: string;\n backlinks?: readonly Backlink[];\n};\n\nexport type QueryGroup = { key: readonly unknown[]; count: number };\n\nexport type DocumentResult = { documents: readonly QueryDocument[] };\n\nexport type GroupResult = { groups: readonly QueryGroup[] };\n\nexport type QueryResult = DocumentResult | GroupResult;\n\nexport type QueryErrorCode = 'invalid-query' | 'unknown-type' | 'unknown-field' | 'wrong-kind';\n\nexport type RoomFacts = {\n locator: string;\n available: boolean;\n types: readonly Definition[];\n};\n\nexport type HeldRooms = {\n listed: boolean;\n rooms: readonly RoomFacts[];\n};\n\nexport type Test =\n | { op: 'eq'; value: Value }\n | { op: 'ne'; value: Value }\n | { op: 'in'; values: readonly Value[] }\n | { op: 'nin'; values: readonly Value[] }\n | { op: 'range'; bounds: readonly (readonly ['gt' | 'gte' | 'lt' | 'lte', Value])[] }\n | { op: 'all'; values: readonly Value[] }\n | { op: 'size'; size: number }\n | { op: 'exists'; exists: boolean };\n\nexport type Condition =\n | { every: readonly Condition[] }\n | { some: readonly Condition[] }\n | { field: string; test: Test };\n\nexport type Scope = {\n types: readonly string[] | null;\n where: Condition | null;\n pathPrefix: string | null;\n};\n\nexport type KeyPlan =\n | { of: 'room' }\n | { of: 'path' }\n | { of: 'type' }\n | { of: 'field'; field: string };\n\nexport type DocumentShape = {\n kind: 'documents';\n fields: 'all' | readonly string[] | null;\n sections: 'all' | readonly string[] | null;\n preamble: boolean;\n markdown: boolean;\n backlinks: boolean;\n orderBy: readonly { key: KeyPlan; options: OrderOptions & { direction: Direction } }[];\n};\n\nexport type GroupShape = {\n kind: 'groups';\n groupBy: readonly KeyPlan[];\n orderBy: readonly { by: 'count' | number; direction: Direction }[];\n};\n\nexport type Plan = {\n rooms: readonly string[] | null;\n root: Scope;\n hop: (Scope & { field: string }) | null;\n backlinks: (Scope & { field: string | null }) | null;\n shape: DocumentShape | GroupShape;\n limit: number | null;\n};\n\nexport class QueryError extends Error {\n constructor(code: QueryErrorCode, at: string, problem: string) {\n super(`${code} at ${at}: ${problem}`);\n }\n}\n\ntype Entries = Readonly<Record<string, unknown>>;\n\ntype Typing = { untyped: boolean; types: readonly Definition[] };\n\nconst RANGE = ['$gt', '$gte', '$lt', '$lte'] as const;\nconst SINGLE = ['$eq', '$ne', '$in', '$nin', '$all', '$size', '$exists'] as const;\nconst FILTER = ['rooms', 'types', 'where', 'pathPrefix', 'hop', 'backlinks', 'orderBy', 'limit'];\nconst RELATED = ['types', 'where', 'pathPrefix', 'field'];\nconst PARTS = ['fields', 'sections', 'preamble', 'markdown', 'backlinks'];\nconst ORDER = ['by', 'direction', 'nulls', 'stringSort', 'locale', 'localeOptions'];\nconst CALENDAR_DATE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nfunction invalid(at: string, problem: string): never {\n throw new QueryError('invalid-query', at, problem);\n}\n\nfunction place(at: string, name: string): string {\n return at === '' ? name : `${at}.${name}`;\n}\n\nfunction plain(value: unknown): value is Entries {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)\n );\n}\n\nfunction known(value: Entries, allowed: readonly string[], at: string) {\n for (const name of Object.keys(value)) {\n if (!allowed.includes(name)) invalid(place(at, name), 'unknown part');\n }\n}\n\nfunction list(input: unknown, at: string): readonly unknown[] {\n if (!Array.isArray(input)) invalid(at, 'expects a list');\n return input;\n}\n\nfunction value(input: unknown, at: string): Value {\n if (Array.isArray(input)) invalid(at, 'a list is not a value');\n if (\n input !== null &&\n typeof input !== 'string' &&\n typeof input !== 'boolean' &&\n !(typeof input === 'number' && Number.isFinite(input))\n ) {\n invalid(at, 'not a value');\n }\n return input;\n}\n\nfunction values(input: unknown, at: string): readonly Value[] {\n return list(input, at).map((item, index) => value(item, `${at}[${index}]`));\n}\n\nfunction names(input: unknown, at: string): readonly string[] {\n const listed = list(input, at);\n if (listed.some((item) => typeof item !== 'string')) invalid(at, 'expects a list of names');\n return [...new Set(listed as readonly string[])].sort();\n}\n\nfunction directory(input: unknown, at: string): string {\n if (typeof input !== 'string' || normalize(input) !== input) {\n invalid(at, 'expects a normalized directory');\n }\n return input;\n}\n\nfunction calendarDate(value: string): boolean {\n const match = CALENDAR_DATE.exec(value);\n if (match === null) return false;\n const [year, month, day] = match.slice(1).map(Number);\n const date = new Date(Date.UTC(year, month - 1, day));\n return (\n date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day\n );\n}\n\nfunction fits(spec: FieldSpec, value: Value): boolean {\n const item = spec.kind === 'list' ? spec.of : spec;\n if (item.kind === 'number') return typeof value === 'number';\n if (typeof value !== 'string') return false;\n if (item.kind === 'enum') return item.values.includes(value);\n if (item.kind === 'date') return calendarDate(value);\n if (item.kind === 'reference') return value !== '' && normalize(value) === value;\n return true;\n}\n\nfunction reference(spec: FieldSpec): boolean {\n return spec.kind === 'reference' || (spec.kind === 'list' && spec.of.kind === 'reference');\n}\n\nfunction typing(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n types: readonly string[] | null,\n at: string,\n): Typing {\n const read =\n rooms === null ? facts.rooms : facts.rooms.filter((room) => rooms.includes(room.locator));\n const acquiring =\n !facts.listed &&\n (rooms === null ||\n rooms.some((locator) => !facts.rooms.some((room) => room.locator === locator)));\n const available = !acquiring && read.every((room) => room.available);\n const declared = read.flatMap((room) => room.types);\n for (const name of types ?? []) {\n if (name === 'any' || !available || declared.some((type) => type.name === name)) continue;\n throw new QueryError('unknown-type', place(at, 'types'), `no model it reads declares ${name}`);\n }\n return {\n untyped: types === null || types.includes('any') || !available,\n types: types === null ? declared : declared.filter((type) => types.includes(type.name)),\n };\n}\n\nfunction specs(typed: Typing, field: string, at: string): readonly FieldSpec[] {\n const declared = typed.types.flatMap((type) =>\n Object.hasOwn(type.fields, field) ? [type.fields[field]] : [],\n );\n if (declared.length === 0 && !typed.untyped) {\n throw new QueryError('unknown-field', at, `no MD Type it reads declares ${field}`);\n }\n return declared;\n}\n\nfunction kind(declared: readonly FieldSpec[], checked: Value, at: string) {\n if (checked === null || declared.length === 0 || declared.some((spec) => fits(spec, checked))) {\n return;\n }\n throw new QueryError('wrong-kind', at, `${JSON.stringify(checked)} is not of its field's kind`);\n}\n\nfunction listed(declared: readonly FieldSpec[], list: boolean): boolean {\n return declared.length > 0 && declared.every((spec) => (spec.kind === 'list') === list);\n}\n\nfunction test(declared: readonly FieldSpec[], input: unknown, at: string): Test {\n if (!plain(input)) {\n const equal = value(input, at);\n kind(declared, equal, at);\n return { op: 'eq', value: equal };\n }\n const operators = Object.keys(input);\n if (operators.length === 0) invalid(at, 'names no operator');\n if (operators.some((operator) => (RANGE as readonly string[]).includes(operator))) {\n const stray = operators.find((operator) => !(RANGE as readonly string[]).includes(operator));\n if (stray !== undefined) invalid(place(at, stray), 'cannot join a range');\n if (listed(declared, true)) invalid(at, 'a range on a list');\n return {\n op: 'range',\n bounds: RANGE.filter((operator) => operators.includes(operator)).map((operator) => {\n const bound = value(input[operator], place(at, operator));\n if (bound === null) invalid(place(at, operator), 'a range bound is never null');\n kind(declared, bound, place(at, operator));\n return [operator.slice(1) as 'gt' | 'gte' | 'lt' | 'lte', bound] as const;\n }),\n };\n }\n if (operators.length > 1) invalid(place(at, operators[1]), 'names a second operator');\n const [operator] = operators;\n const where = place(at, operator);\n if (!(SINGLE as readonly string[]).includes(operator)) invalid(where, 'unknown operator');\n const operand = input[operator];\n if (operator === '$eq' || operator === '$ne') {\n const compared = value(operand, where);\n kind(declared, compared, where);\n return operator === '$eq' ? { op: 'eq', value: compared } : { op: 'ne', value: compared };\n }\n if (operator === '$in' || operator === '$nin' || operator === '$all') {\n const compared = values(operand, where);\n compared.forEach((item, index) => kind(declared, item, `${where}[${index}]`));\n if (operator === '$in') return { op: 'in', values: compared };\n if (operator === '$nin') return { op: 'nin', values: compared };\n if (compared.includes(null)) invalid(where, 'a list holds no null');\n if (listed(declared, false)) invalid(where, 'the field is not a list');\n return { op: 'all', values: compared };\n }\n if (operator === '$size') {\n if (!Number.isSafeInteger(operand) || (operand as number) < 0) {\n invalid(where, 'expects a nonnegative integer');\n }\n if (listed(declared, false)) invalid(where, 'the field is not a list');\n return { op: 'size', size: operand as number };\n }\n if (typeof operand !== 'boolean') invalid(where, 'expects true or false');\n return { op: 'exists', exists: operand };\n}\n\nfunction condition(typed: Typing, input: unknown, at: string): Condition {\n if (!plain(input)) invalid(at, 'expects an object of field predicates');\n const conditions: Condition[] = [];\n for (const name of Object.keys(input).sort()) {\n const where = place(at, name);\n const entry = input[name];\n if (name === '$and' || name === '$or') {\n const nested = list(entry, where).map((item, index) =>\n condition(typed, item, `${where}[${index}]`),\n );\n if (nested.length === 0) invalid(where, 'expects a nonempty list');\n conditions.push(name === '$and' ? { every: nested } : { some: nested });\n continue;\n }\n if (name.startsWith('$')) invalid(where, 'unknown operator');\n conditions.push({ field: name, test: test(specs(typed, name, where), entry, where) });\n }\n if (conditions.length === 0) invalid(at, 'names no field');\n return conditions.length === 1 ? conditions[0] : { every: conditions };\n}\n\nfunction scope(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n input: Entries,\n at: string,\n): Scope & { typed: Typing } {\n const types = input.types === undefined ? null : names(input.types, place(at, 'types'));\n const typed = typing(facts, rooms, types, at);\n return {\n typed,\n types,\n where:\n input.where === undefined || (plain(input.where) && Object.keys(input.where).length === 0)\n ? null\n : condition(typed, input.where, place(at, 'where')),\n pathPrefix:\n input.pathPrefix === undefined ? null : directory(input.pathPrefix, place(at, 'pathPrefix')),\n };\n}\n\nfunction referenceField(typed: Typing, field: unknown, at: string): string {\n if (typeof field !== 'string') invalid(at, 'expects a field name');\n const declared = specs(typed, field, at);\n if (declared.length > 0 && !declared.some(reference)) invalid(at, 'not a reference field');\n return field;\n}\n\nfunction hopOf(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n root: Typing,\n input: unknown,\n): Plan['hop'] {\n if (!plain(input)) invalid('hop', 'expects an object');\n known(input, RELATED, 'hop');\n const field = referenceField(root, input.field, 'hop.field');\n const { types, where, pathPrefix } = scope(facts, rooms, input, 'hop');\n return { types, where, pathPrefix, field };\n}\n\nfunction backlinksOf(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n input: unknown,\n): Plan['backlinks'] {\n if (!plain(input)) invalid('backlinks', 'expects an object');\n known(input, RELATED, 'backlinks');\n const { typed, types, where, pathPrefix } = scope(facts, rooms, input, 'backlinks');\n const field =\n input.field === undefined ? null : referenceField(typed, input.field, 'backlinks.field');\n return { types, where, pathPrefix, field };\n}\n\nfunction keyPlan(typed: Typing, input: unknown, at: string, path: boolean): KeyPlan {\n if (input === 'room' || input === 'type' || (path && input === 'path')) return { of: input };\n if (plain(input) && typeof input.field === 'string' && Object.keys(input).length === 1) {\n specs(typed, input.field, place(at, 'field'));\n return { of: 'field', field: input.field };\n }\n return invalid(\n at,\n path ? 'expects room, path, type or a field' : 'expects room, type or a field',\n );\n}\n\nfunction direction(input: unknown, at: string): Direction {\n if (input === undefined) return 'asc';\n if (input !== 'asc' && input !== 'desc') invalid(at, 'expects asc or desc');\n return input;\n}\n\nfunction orderOptions(input: Entries, at: string): OrderOptions & { direction: Direction } {\n const options: OrderOptions & { direction: Direction } = {\n direction: direction(input.direction, place(at, 'direction')),\n };\n if (input.nulls !== undefined) {\n if (input.nulls !== 'first' && input.nulls !== 'last') {\n invalid(place(at, 'nulls'), 'expects first or last');\n }\n options.nulls = input.nulls;\n }\n if (input.stringSort !== undefined) {\n if (input.stringSort !== 'lexical' && input.stringSort !== 'locale') {\n invalid(place(at, 'stringSort'), 'expects lexical or locale');\n }\n options.stringSort = input.stringSort;\n }\n if (input.locale !== undefined) {\n if (typeof input.locale !== 'string' || !collates(input.locale, undefined)) {\n invalid(place(at, 'locale'), 'expects a locale name');\n }\n options.locale = input.locale;\n }\n if (input.localeOptions !== undefined) {\n if (!plain(input.localeOptions) || !collates(options.locale, input.localeOptions)) {\n invalid(place(at, 'localeOptions'), 'expects collation options');\n }\n options.localeOptions = input.localeOptions;\n }\n return options;\n}\n\nfunction collates(locale: string | undefined, options: Entries | undefined): boolean {\n try {\n ''.localeCompare('', locale, options);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction parts(typed: Typing, input: unknown, at: string, fields: boolean) {\n if (input === undefined) return null;\n if (input === 'all') return 'all';\n const named = list(input, at);\n named.forEach((name, index) => {\n if (typeof name !== 'string') invalid(`${at}[${index}]`, 'expects a name');\n if (fields) specs(typed, name, `${at}[${index}]`);\n });\n return named as readonly string[];\n}\n\nfunction flag(input: unknown, at: string): boolean {\n if (input === undefined) return false;\n if (input !== true) invalid(at, 'expects true');\n return true;\n}\n\nfunction documentShape(typed: Typing, input: Entries): DocumentShape {\n const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map(\n (clause, index) => {\n const at = `orderBy[${index}]`;\n if (!plain(clause)) invalid(at, 'expects an order clause');\n known(clause, ORDER, at);\n return {\n key: keyPlan(typed, clause.by, place(at, 'by'), true),\n options: orderOptions(clause, at),\n };\n },\n );\n const select = input.select;\n if (select === 'all') {\n return {\n kind: 'documents',\n fields: 'all',\n sections: 'all',\n preamble: true,\n markdown: true,\n backlinks: true,\n orderBy,\n };\n }\n if (!plain(select)) invalid('select', \"expects 'all' or the parts to return\");\n known(select, PARTS, 'select');\n return {\n kind: 'documents',\n fields: parts(typed, select.fields, 'select.fields', true),\n sections: parts(typed, select.sections, 'select.sections', false),\n preamble: flag(select.preamble, 'select.preamble'),\n markdown: flag(select.markdown, 'select.markdown'),\n backlinks: flag(select.backlinks, 'select.backlinks'),\n orderBy,\n };\n}\n\nfunction groupShape(typed: Typing, input: Entries): GroupShape {\n const groupBy = list(input.groupBy, 'groupBy').map((key, index) =>\n keyPlan(typed, key, `groupBy[${index}]`, false),\n );\n if (groupBy.length === 0) invalid('groupBy', 'names no key');\n const grouped = groupBy.map((key) => JSON.stringify(key));\n const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map(\n (clause, index) => {\n const at = `orderBy[${index}]`;\n if (!plain(clause)) invalid(at, 'expects an order clause');\n known(clause, ['by', 'direction'], at);\n const by =\n clause.by === 'count'\n ? ('count' as const)\n : grouped.indexOf(JSON.stringify(keyPlan(typed, clause.by, place(at, 'by'), false)));\n if (by === -1) invalid(place(at, 'by'), 'orders by a key the query does not group by');\n return { by, direction: direction(clause.direction, place(at, 'direction')) };\n },\n );\n return { kind: 'groups', groupBy, orderBy };\n}\n\nexport function planOf(input: unknown, facts: HeldRooms): Plan {\n if (!plain(input)) invalid('query', 'expects a query object');\n const grouped = input.groupBy !== undefined;\n if (grouped && input.select !== undefined) invalid('select', 'a grouped query selects nothing');\n if (!grouped && input.select === undefined) invalid('select', 'a Document query must select');\n known(input, [...FILTER, grouped ? 'groupBy' : 'select'], '');\n if (\n input.limit !== undefined &&\n (!Number.isSafeInteger(input.limit) || (input.limit as number) < 0)\n ) {\n invalid('limit', 'expects a nonnegative integer');\n }\n const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');\n const { typed, ...root } = scope(facts, rooms, input, '');\n return {\n rooms,\n root,\n hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),\n backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),\n shape: grouped ? groupShape(typed, input) : documentShape(typed, input),\n limit: (input.limit as number | undefined) ?? null,\n };\n}\n\nfunction canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;\n if (typeof value === 'object' && value !== null) {\n return `{${Object.keys(value)\n .sort()\n .map((name) => `${JSON.stringify(name)}:${canonical((value as Entries)[name])}`)\n .join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\nexport function identityOf(plan: Plan): string {\n return canonical(plan);\n}\n"],"names":["normalize","QueryError","Error","code","at","problem","RANGE","SINGLE","FILTER","RELATED","PARTS","ORDER","CALENDAR_DATE","invalid","place","name","plain","value","Array","isArray","Object","getPrototypeOf","prototype","known","allowed","keys","includes","list","input","Number","isFinite","values","map","item","index","names","listed","some","Set","sort","directory","calendarDate","match","exec","year","month","day","slice","date","Date","UTC","getUTCFullYear","getUTCMonth","getUTCDate","fits","spec","kind","of","reference","typing","facts","rooms","types","read","filter","room","locator","acquiring","available","every","declared","flatMap","type","untyped","specs","typed","field","hasOwn","fields","length","checked","JSON","stringify","test","equal","op","operators","operator","stray","find","undefined","bounds","bound","where","operand","compared","forEach","isSafeInteger","size","exists","condition","conditions","entry","nested","push","startsWith","scope","pathPrefix","referenceField","hopOf","root","backlinksOf","keyPlan","path","direction","orderOptions","options","nulls","stringSort","locale","collates","localeOptions","localeCompare","parts","named","flag","documentShape","orderBy","clause","key","by","select","sections","preamble","markdown","backlinks","groupShape","groupBy","grouped","indexOf","planOf","limit","hop","shape","canonical","join","identityOf","plan"],"mappings":"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"}
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/query.ts"],"sourcesContent":["import type { Definition, FieldSpec } from '@agentshouse/mdmodel';\nimport { normalize } from './paths.js';\n\nexport type Value = string | number | boolean | null;\n\nexport type Predicate =\n | Value\n | { $eq: Value }\n | { $ne: Value }\n | { $in: readonly Value[] }\n | { $nin: readonly Value[] }\n | { $gt?: Value; $gte?: Value; $lt?: Value; $lte?: Value }\n | { $all: readonly Value[] }\n | { $size: number }\n | { $exists: boolean };\n\nexport type Where = {\n $and?: readonly Where[];\n $or?: readonly Where[];\n [field: string]: Predicate | readonly Where[] | undefined;\n};\n\nexport type Related = { types?: readonly string[]; where?: Where; pathPrefix?: string };\n\nexport type Filter = {\n rooms?: readonly string[];\n types?: readonly string[];\n where?: Where;\n pathPrefix?: string;\n hop?: Related & { field: string };\n backlinks?: Related & { field?: string };\n};\n\nexport type Key = 'room' | 'path' | 'type' | { field: string };\n\nexport type Select =\n | 'all'\n | {\n fields?: 'all' | readonly string[];\n sections?: 'all' | readonly string[];\n preamble?: true;\n markdown?: true;\n backlinks?: true;\n };\n\nexport type OrderOptions = {\n nulls?: 'first' | 'last';\n stringSort?: 'lexical' | 'locale';\n locale?: string;\n localeOptions?: Readonly<Record<string, unknown>>;\n};\n\nexport type Direction = 'asc' | 'desc';\n\nexport type DocumentQuery = Filter & {\n select: Select;\n orderBy?: readonly ({ by: Key; direction?: Direction } & OrderOptions)[];\n limit?: number;\n};\n\nexport type GroupQuery = Filter & {\n groupBy: readonly Exclude<Key, 'path'>[];\n orderBy?: readonly { by: 'count' | Exclude<Key, 'path'>; direction?: Direction }[];\n limit?: number;\n};\n\nexport type LocalQuery = DocumentQuery | GroupQuery;\n\nexport type Backlink = { path: string; type: string; field: string };\n\nexport type QueryDocument = {\n room: string;\n path: string;\n type: string;\n fields?: Readonly<Record<string, unknown>>;\n sections?: Readonly<Record<string, string>>;\n preamble?: string;\n markdown?: string;\n backlinks?: readonly Backlink[];\n};\n\nexport type QueryGroup = { key: readonly unknown[]; count: number };\n\nexport type DocumentResult = { documents: readonly QueryDocument[] };\n\nexport type GroupResult = { groups: readonly QueryGroup[] };\n\nexport type QueryResult = DocumentResult | GroupResult;\n\nexport type QueryErrorCode = 'invalid-query' | 'unknown-type' | 'unknown-field' | 'wrong-kind';\n\nexport type RoomFacts = {\n locator: string;\n available: boolean;\n types: readonly Definition[];\n};\n\nexport type HeldRooms = {\n listed: boolean;\n rooms: readonly RoomFacts[];\n};\n\nexport type Test =\n | { op: 'eq'; value: Value }\n | { op: 'ne'; value: Value }\n | { op: 'in'; values: readonly Value[] }\n | { op: 'nin'; values: readonly Value[] }\n | { op: 'range'; bounds: readonly (readonly ['gt' | 'gte' | 'lt' | 'lte', Value])[] }\n | { op: 'all'; values: readonly Value[] }\n | { op: 'size'; size: number }\n | { op: 'exists'; exists: boolean };\n\nexport type Condition =\n | { every: readonly Condition[] }\n | { some: readonly Condition[] }\n | { field: string; test: Test };\n\nexport type Scope = {\n types: readonly string[] | null;\n where: Condition | null;\n pathPrefix: string | null;\n};\n\nexport type KeyPlan =\n | { of: 'room' }\n | { of: 'path' }\n | { of: 'type' }\n | { of: 'field'; field: string };\n\nexport type DocumentShape = {\n kind: 'documents';\n fields: 'all' | readonly string[] | null;\n sections: 'all' | readonly string[] | null;\n preamble: boolean;\n markdown: boolean;\n backlinks: boolean;\n orderBy: readonly { key: KeyPlan; options: OrderOptions & { direction: Direction } }[];\n};\n\nexport type GroupShape = {\n kind: 'groups';\n groupBy: readonly KeyPlan[];\n orderBy: readonly { by: 'count' | number; direction: Direction }[];\n};\n\nexport type Plan = {\n rooms: readonly string[] | null;\n root: Scope;\n hop: (Scope & { field: string }) | null;\n backlinks: (Scope & { field: string | null }) | null;\n shape: DocumentShape | GroupShape;\n limit: number | null;\n};\n\nexport class QueryError extends Error {\n constructor(code: QueryErrorCode, at: string, problem: string) {\n super(`${code} at ${at}: ${problem}`);\n }\n}\n\ntype Entries = Readonly<Record<string, unknown>>;\n\ntype Typing = { untyped: boolean; types: readonly Definition[] };\n\nconst RANGE = ['$gt', '$gte', '$lt', '$lte'] as const;\nconst SINGLE = ['$eq', '$ne', '$in', '$nin', '$all', '$size', '$exists'] as const;\nconst FILTER = ['rooms', 'types', 'where', 'pathPrefix', 'hop', 'backlinks'];\nconst RELATED = ['types', 'where', 'pathPrefix', 'field'];\nconst PARTS = ['fields', 'sections', 'preamble', 'markdown', 'backlinks'];\nconst ORDER = ['by', 'direction', 'nulls', 'stringSort', 'locale', 'localeOptions'];\nconst CALENDAR_DATE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport function invalid(at: string, problem: string): never {\n throw new QueryError('invalid-query', at, problem);\n}\n\nfunction place(at: string, name: string): string {\n return at === '' ? name : `${at}.${name}`;\n}\n\nexport function plain(value: unknown): value is Entries {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)\n );\n}\n\nexport function known(value: Entries, allowed: readonly string[], at: string) {\n for (const name of Object.keys(value)) {\n if (!allowed.includes(name)) invalid(place(at, name), 'unknown part');\n }\n}\n\nfunction list(input: unknown, at: string): readonly unknown[] {\n if (!Array.isArray(input)) invalid(at, 'expects a list');\n return input;\n}\n\nfunction value(input: unknown, at: string): Value {\n if (Array.isArray(input)) invalid(at, 'a list is not a value');\n if (\n input !== null &&\n typeof input !== 'string' &&\n typeof input !== 'boolean' &&\n !(typeof input === 'number' && Number.isFinite(input))\n ) {\n invalid(at, 'not a value');\n }\n return input;\n}\n\nfunction values(input: unknown, at: string): readonly Value[] {\n return list(input, at).map((item, index) => value(item, `${at}[${index}]`));\n}\n\nfunction names(input: unknown, at: string): readonly string[] {\n const listed = list(input, at);\n if (listed.some((item) => typeof item !== 'string')) invalid(at, 'expects a list of names');\n return [...new Set(listed as readonly string[])].sort();\n}\n\nfunction directory(input: unknown, at: string): string {\n if (typeof input !== 'string' || normalize(input) !== input) {\n invalid(at, 'expects a normalized directory');\n }\n return input;\n}\n\nfunction calendarDate(value: string): boolean {\n const match = CALENDAR_DATE.exec(value);\n if (match === null) return false;\n const [year, month, day] = match.slice(1).map(Number);\n const date = new Date(Date.UTC(year, month - 1, day));\n return (\n date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day\n );\n}\n\nfunction fits(spec: FieldSpec, value: Value): boolean {\n const item = spec.kind === 'list' ? spec.of : spec;\n if (item.kind === 'number') return typeof value === 'number';\n if (typeof value !== 'string') return false;\n if (item.kind === 'enum') return item.values.includes(value);\n if (item.kind === 'date') return calendarDate(value);\n if (item.kind === 'reference') return value !== '' && normalize(value) === value;\n return true;\n}\n\nfunction reference(spec: FieldSpec): boolean {\n return spec.kind === 'reference' || (spec.kind === 'list' && spec.of.kind === 'reference');\n}\n\nfunction typing(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n types: readonly string[] | null,\n at: string,\n): Typing {\n const read =\n rooms === null ? facts.rooms : facts.rooms.filter((room) => rooms.includes(room.locator));\n const acquiring =\n !facts.listed &&\n (rooms === null ||\n rooms.some((locator) => !facts.rooms.some((room) => room.locator === locator)));\n const available = !acquiring && read.every((room) => room.available);\n const declared = read.flatMap((room) => room.types);\n for (const name of types ?? []) {\n if (name === 'any' || !available || declared.some((type) => type.name === name)) continue;\n throw new QueryError('unknown-type', place(at, 'types'), `no model it reads declares ${name}`);\n }\n return {\n untyped: types === null || types.includes('any') || !available,\n types: types === null ? declared : declared.filter((type) => types.includes(type.name)),\n };\n}\n\nfunction specs(typed: Typing, field: string, at: string): readonly FieldSpec[] {\n const declared = typed.types.flatMap((type) =>\n Object.hasOwn(type.fields, field) ? [type.fields[field]] : [],\n );\n if (declared.length === 0 && !typed.untyped) {\n throw new QueryError('unknown-field', at, `no MD Type it reads declares ${field}`);\n }\n return declared;\n}\n\nfunction kind(declared: readonly FieldSpec[], checked: Value, at: string) {\n if (checked === null || declared.length === 0 || declared.some((spec) => fits(spec, checked))) {\n return;\n }\n throw new QueryError('wrong-kind', at, `${JSON.stringify(checked)} is not of its field's kind`);\n}\n\nfunction listed(declared: readonly FieldSpec[], list: boolean): boolean {\n return declared.length > 0 && declared.every((spec) => (spec.kind === 'list') === list);\n}\n\nfunction test(declared: readonly FieldSpec[], input: unknown, at: string): Test {\n if (!plain(input)) {\n const equal = value(input, at);\n kind(declared, equal, at);\n return { op: 'eq', value: equal };\n }\n const operators = Object.keys(input);\n if (operators.length === 0) invalid(at, 'names no operator');\n if (operators.some((operator) => (RANGE as readonly string[]).includes(operator))) {\n const stray = operators.find((operator) => !(RANGE as readonly string[]).includes(operator));\n if (stray !== undefined) invalid(place(at, stray), 'cannot join a range');\n if (listed(declared, true)) invalid(at, 'a range on a list');\n return {\n op: 'range',\n bounds: RANGE.filter((operator) => operators.includes(operator)).map((operator) => {\n const bound = value(input[operator], place(at, operator));\n if (bound === null) invalid(place(at, operator), 'a range bound is never null');\n kind(declared, bound, place(at, operator));\n return [operator.slice(1) as 'gt' | 'gte' | 'lt' | 'lte', bound] as const;\n }),\n };\n }\n if (operators.length > 1) invalid(place(at, operators[1]), 'names a second operator');\n const [operator] = operators;\n const where = place(at, operator);\n if (!(SINGLE as readonly string[]).includes(operator)) invalid(where, 'unknown operator');\n const operand = input[operator];\n if (operator === '$eq' || operator === '$ne') {\n const compared = value(operand, where);\n kind(declared, compared, where);\n return operator === '$eq' ? { op: 'eq', value: compared } : { op: 'ne', value: compared };\n }\n if (operator === '$in' || operator === '$nin' || operator === '$all') {\n const compared = values(operand, where);\n compared.forEach((item, index) => kind(declared, item, `${where}[${index}]`));\n if (operator === '$in') return { op: 'in', values: compared };\n if (operator === '$nin') return { op: 'nin', values: compared };\n if (compared.includes(null)) invalid(where, 'a list holds no null');\n if (listed(declared, false)) invalid(where, 'the field is not a list');\n return { op: 'all', values: compared };\n }\n if (operator === '$size') {\n if (!Number.isSafeInteger(operand) || (operand as number) < 0) {\n invalid(where, 'expects a nonnegative integer');\n }\n if (listed(declared, false)) invalid(where, 'the field is not a list');\n return { op: 'size', size: operand as number };\n }\n if (typeof operand !== 'boolean') invalid(where, 'expects true or false');\n return { op: 'exists', exists: operand };\n}\n\nfunction condition(typed: Typing, input: unknown, at: string): Condition {\n if (!plain(input)) invalid(at, 'expects an object of field predicates');\n const conditions: Condition[] = [];\n for (const name of Object.keys(input).sort()) {\n const where = place(at, name);\n const entry = input[name];\n if (name === '$and' || name === '$or') {\n const nested = list(entry, where).map((item, index) =>\n condition(typed, item, `${where}[${index}]`),\n );\n if (nested.length === 0) invalid(where, 'expects a nonempty list');\n conditions.push(name === '$and' ? { every: nested } : { some: nested });\n continue;\n }\n if (name.startsWith('$')) invalid(where, 'unknown operator');\n conditions.push({ field: name, test: test(specs(typed, name, where), entry, where) });\n }\n if (conditions.length === 0) invalid(at, 'names no field');\n return conditions.length === 1 ? conditions[0] : { every: conditions };\n}\n\nfunction scope(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n input: Entries,\n at: string,\n): Scope & { typed: Typing } {\n const types = input.types === undefined ? null : names(input.types, place(at, 'types'));\n const typed = typing(facts, rooms, types, at);\n return {\n typed,\n types,\n where:\n input.where === undefined || (plain(input.where) && Object.keys(input.where).length === 0)\n ? null\n : condition(typed, input.where, place(at, 'where')),\n pathPrefix:\n input.pathPrefix === undefined ? null : directory(input.pathPrefix, place(at, 'pathPrefix')),\n };\n}\n\nfunction referenceField(typed: Typing, field: unknown, at: string): string {\n if (typeof field !== 'string') invalid(at, 'expects a field name');\n const declared = specs(typed, field, at);\n if (declared.length > 0 && !declared.some(reference)) invalid(at, 'not a reference field');\n return field;\n}\n\nfunction hopOf(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n root: Typing,\n input: unknown,\n): Plan['hop'] {\n if (!plain(input)) invalid('hop', 'expects an object');\n known(input, RELATED, 'hop');\n const field = referenceField(root, input.field, 'hop.field');\n const { types, where, pathPrefix } = scope(facts, rooms, input, 'hop');\n return { types, where, pathPrefix, field };\n}\n\nfunction backlinksOf(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n input: unknown,\n): Plan['backlinks'] {\n if (!plain(input)) invalid('backlinks', 'expects an object');\n known(input, RELATED, 'backlinks');\n const { typed, types, where, pathPrefix } = scope(facts, rooms, input, 'backlinks');\n const field =\n input.field === undefined ? null : referenceField(typed, input.field, 'backlinks.field');\n return { types, where, pathPrefix, field };\n}\n\nfunction keyPlan(typed: Typing, input: unknown, at: string, path: boolean): KeyPlan {\n if (input === 'room' || input === 'type' || (path && input === 'path')) return { of: input };\n if (plain(input) && typeof input.field === 'string' && Object.keys(input).length === 1) {\n specs(typed, input.field, place(at, 'field'));\n return { of: 'field', field: input.field };\n }\n return invalid(\n at,\n path ? 'expects room, path, type or a field' : 'expects room, type or a field',\n );\n}\n\nfunction direction(input: unknown, at: string): Direction {\n if (input === undefined) return 'asc';\n if (input !== 'asc' && input !== 'desc') invalid(at, 'expects asc or desc');\n return input;\n}\n\nfunction orderOptions(input: Entries, at: string): OrderOptions & { direction: Direction } {\n const options: OrderOptions & { direction: Direction } = {\n direction: direction(input.direction, place(at, 'direction')),\n };\n if (input.nulls !== undefined) {\n if (input.nulls !== 'first' && input.nulls !== 'last') {\n invalid(place(at, 'nulls'), 'expects first or last');\n }\n options.nulls = input.nulls;\n }\n if (input.stringSort !== undefined) {\n if (input.stringSort !== 'lexical' && input.stringSort !== 'locale') {\n invalid(place(at, 'stringSort'), 'expects lexical or locale');\n }\n options.stringSort = input.stringSort;\n }\n if (input.locale !== undefined) {\n if (typeof input.locale !== 'string' || !collates(input.locale, undefined)) {\n invalid(place(at, 'locale'), 'expects a locale name');\n }\n options.locale = input.locale;\n }\n if (input.localeOptions !== undefined) {\n if (!plain(input.localeOptions) || !collates(options.locale, input.localeOptions)) {\n invalid(place(at, 'localeOptions'), 'expects collation options');\n }\n options.localeOptions = input.localeOptions;\n }\n return options;\n}\n\nfunction collates(locale: string | undefined, options: Entries | undefined): boolean {\n try {\n ''.localeCompare('', locale, options);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction parts(typed: Typing, input: unknown, at: string, fields: boolean) {\n if (input === undefined) return null;\n if (input === 'all') return 'all';\n const named = list(input, at);\n named.forEach((name, index) => {\n if (typeof name !== 'string') invalid(`${at}[${index}]`, 'expects a name');\n if (fields) specs(typed, name, `${at}[${index}]`);\n });\n return named as readonly string[];\n}\n\nfunction flag(input: unknown, at: string): boolean {\n if (input === undefined) return false;\n if (input !== true) invalid(at, 'expects true');\n return true;\n}\n\nfunction documentShape(typed: Typing, input: Entries): DocumentShape {\n const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map(\n (clause, index) => {\n const at = `orderBy[${index}]`;\n if (!plain(clause)) invalid(at, 'expects an order clause');\n known(clause, ORDER, at);\n return {\n key: keyPlan(typed, clause.by, place(at, 'by'), true),\n options: orderOptions(clause, at),\n };\n },\n );\n const select = input.select;\n if (select === 'all') {\n return {\n kind: 'documents',\n fields: 'all',\n sections: 'all',\n preamble: true,\n markdown: true,\n backlinks: true,\n orderBy,\n };\n }\n if (!plain(select)) invalid('select', \"expects 'all' or the parts to return\");\n known(select, PARTS, 'select');\n return {\n kind: 'documents',\n fields: parts(typed, select.fields, 'select.fields', true),\n sections: parts(typed, select.sections, 'select.sections', false),\n preamble: flag(select.preamble, 'select.preamble'),\n markdown: flag(select.markdown, 'select.markdown'),\n backlinks: flag(select.backlinks, 'select.backlinks'),\n orderBy,\n };\n}\n\nfunction groupShape(typed: Typing, input: Entries): GroupShape {\n const groupBy = list(input.groupBy, 'groupBy').map((key, index) =>\n keyPlan(typed, key, `groupBy[${index}]`, false),\n );\n if (groupBy.length === 0) invalid('groupBy', 'names no key');\n const grouped = groupBy.map((key) => JSON.stringify(key));\n const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map(\n (clause, index) => {\n const at = `orderBy[${index}]`;\n if (!plain(clause)) invalid(at, 'expects an order clause');\n known(clause, ['by', 'direction'], at);\n const by =\n clause.by === 'count'\n ? ('count' as const)\n : grouped.indexOf(JSON.stringify(keyPlan(typed, clause.by, place(at, 'by'), false)));\n if (by === -1) invalid(place(at, 'by'), 'orders by a key the query does not group by');\n return { by, direction: direction(clause.direction, place(at, 'direction')) };\n },\n );\n return { kind: 'groups', groupBy, orderBy };\n}\n\nexport function planOf(input: unknown, facts: HeldRooms): Plan {\n if (!plain(input)) invalid('query', 'expects a query object');\n const grouped = input.groupBy !== undefined;\n if (grouped && input.select !== undefined) invalid('select', 'a grouped query selects nothing');\n if (!grouped && input.select === undefined) invalid('select', 'a Document query must select');\n known(input, [...FILTER, 'orderBy', 'limit', grouped ? 'groupBy' : 'select'], '');\n const limit = limitOf(input.limit);\n const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');\n const { typed, ...root } = scope(facts, rooms, input, '');\n return {\n rooms,\n root,\n hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),\n backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),\n shape: grouped ? groupShape(typed, input) : documentShape(typed, input),\n limit,\n };\n}\n\nexport function limitOf(input: unknown): number | null {\n if (input === undefined) return null;\n if (!Number.isSafeInteger(input) || (input as number) < 0) {\n invalid('limit', 'expects a nonnegative integer');\n }\n return input as number;\n}\n\nexport function filterOf(input: unknown, facts: HeldRooms): Plan {\n if (!plain(input)) invalid('documents', 'expects a filter object');\n known(input, FILTER, '');\n return planOf({ ...input, select: {} }, facts);\n}\n\nfunction canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;\n if (typeof value === 'object' && value !== null) {\n return `{${Object.keys(value)\n .sort()\n .map((name) => `${JSON.stringify(name)}:${canonical((value as Entries)[name])}`)\n .join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\nexport function identityOf(plan: Plan): string {\n return canonical(plan);\n}\n"],"names":["normalize","QueryError","Error","code","at","problem","RANGE","SINGLE","FILTER","RELATED","PARTS","ORDER","CALENDAR_DATE","invalid","place","name","plain","value","Array","isArray","Object","getPrototypeOf","prototype","known","allowed","keys","includes","list","input","Number","isFinite","values","map","item","index","names","listed","some","Set","sort","directory","calendarDate","match","exec","year","month","day","slice","date","Date","UTC","getUTCFullYear","getUTCMonth","getUTCDate","fits","spec","kind","of","reference","typing","facts","rooms","types","read","filter","room","locator","acquiring","available","every","declared","flatMap","type","untyped","specs","typed","field","hasOwn","fields","length","checked","JSON","stringify","test","equal","op","operators","operator","stray","find","undefined","bounds","bound","where","operand","compared","forEach","isSafeInteger","size","exists","condition","conditions","entry","nested","push","startsWith","scope","pathPrefix","referenceField","hopOf","root","backlinksOf","keyPlan","path","direction","orderOptions","options","nulls","stringSort","locale","collates","localeOptions","localeCompare","parts","named","flag","documentShape","orderBy","clause","key","by","select","sections","preamble","markdown","backlinks","groupShape","groupBy","grouped","indexOf","planOf","limit","limitOf","hop","shape","filterOf","canonical","join","identityOf","plan"],"mappings":"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"}
@@ -1,9 +1,13 @@
1
1
  import type { ChangeSet } from './change-set.js';
2
+ import { type KeyedResult, type QueryChange } from './observation.js';
2
3
  import type { Plan, QueryResult } from './query.js';
4
+ import type { SearchedDocument } from './search.js';
3
5
  export type ReadSide = {
4
6
  apply(set: ChangeSet): void;
5
7
  query(plan: Plan): Promise<QueryResult>;
6
- observe(plan: Plan, identity: string, listener: (result: QueryResult) => void): () => void;
8
+ watch(plan: Plan, identity: string, deliver: (message: KeyedResult | QueryChange) => void): () => void;
9
+ documents(): readonly SearchedDocument[];
10
+ document(room: string, path: string): SearchedDocument | null;
7
11
  close(): void;
8
12
  };
9
13
  export declare function createReadSide(): ReadSide;
@@ -1 +1 @@
1
- {"version":3,"file":"read-side.d.ts","sourceRoot":"","sources":["../src/read-side.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAOV,IAAI,EAEJ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAqDpB,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC3F,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAqPF,wBAAgB,cAAc,IAAI,QAAQ,CAgGzC"}
1
+ {"version":3,"file":"read-side.d.ts","sourceRoot":"","sources":["../src/read-side.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAU,KAAK,WAAW,EAAE,KAAK,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAC3F,OAAO,KAAK,EAOV,IAAI,EAGJ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoDpD,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,KAAK,CACH,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,KAAK,IAAI,GACpD,MAAM,IAAI,CAAC;IACd,SAAS,IAAI,SAAS,gBAAgB,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC9D,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AA+RF,wBAAgB,cAAc,IAAI,QAAQ,CAuHzC"}
package/dist/read-side.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { and, BasicIndex, configureIndexDevMode, count, createCollection, createLiveQueryCollection, deepEquals, eq, gt, gte, inArray, isNull, isUndefined, lt, lte, not, or, toArray } from '@tanstack/db';
2
+ import { rowsOf } from './observation.js';
3
+ import { documentKey } from './rows.js';
2
4
  function every(expressions) {
3
5
  const [first, second, ...rest] = expressions;
4
6
  return second === undefined ? first : and(first, second, ...rest);
@@ -252,20 +254,64 @@ function documentOf(row, shape) {
252
254
  } : {}
253
255
  };
254
256
  }
255
- function resultOf(plan, rows) {
257
+ function keyedOf(plan, entries) {
256
258
  const shape = plan.shape;
257
259
  if (shape.kind === 'documents') {
258
- return structuredClone({
259
- documents: rows.map((row)=>documentOf(row, shape))
260
- });
260
+ return {
261
+ result: structuredClone({
262
+ documents: entries.map(([, row])=>documentOf(row, shape))
263
+ }),
264
+ keys: entries.map(([key])=>key)
265
+ };
261
266
  }
262
- const bounded = shape.orderBy.length === 0 && plan.limit !== null ? rows.slice(0, plan.limit) : rows;
263
- return structuredClone({
264
- groups: bounded.map((row)=>({
265
- key: shape.groupBy.map((_, index)=>row[`key${index}`]),
266
- count: row.count
267
- }))
267
+ const bounded = shape.orderBy.length === 0 && plan.limit !== null ? entries.slice(0, plan.limit) : entries;
268
+ return {
269
+ result: structuredClone({
270
+ groups: bounded.map(([, row])=>({
271
+ key: shape.groupBy.map((_, index)=>row[`key${index}`]),
272
+ count: row.count
273
+ }))
274
+ }),
275
+ keys: bounded.map(([key])=>key)
276
+ };
277
+ }
278
+ function reconciled(previous, next) {
279
+ const before = rowsOf(previous.result);
280
+ const held = new Map(previous.keys.map((key, index)=>[
281
+ key,
282
+ before[index]
283
+ ]));
284
+ const changed = [];
285
+ const rows = rowsOf(next.result).map((row, index)=>{
286
+ const key = next.keys[index];
287
+ const kept = held.get(key);
288
+ if (kept !== undefined && deepEquals(kept, row)) return kept;
289
+ changed.push([
290
+ key,
291
+ row
292
+ ]);
293
+ return row;
268
294
  });
295
+ const present = new Set(next.keys);
296
+ const survivors = previous.keys.filter((key)=>present.has(key));
297
+ const removed = previous.keys.filter((key)=>!present.has(key));
298
+ const moved = survivors.length !== next.keys.length || survivors.some((key, index)=>key !== next.keys[index]);
299
+ if (changed.length === 0 && removed.length === 0 && !moved) return null;
300
+ return {
301
+ keyed: {
302
+ result: 'groups' in next.result ? {
303
+ groups: rows
304
+ } : {
305
+ documents: rows
306
+ },
307
+ keys: next.keys
308
+ },
309
+ change: {
310
+ changed,
311
+ removed,
312
+ order: moved ? next.keys : null
313
+ }
314
+ };
269
315
  }
270
316
  export function createReadSide() {
271
317
  configureIndexDevMode({
@@ -287,11 +333,24 @@ export function createReadSide() {
287
333
  }
288
334
  });
289
335
  const shared = new Map();
336
+ function searched(row) {
337
+ const body = rows.get(row.body);
338
+ return {
339
+ room: row.room,
340
+ path: row.path,
341
+ type: row.type,
342
+ fields: row.fields,
343
+ preamble: body.preamble,
344
+ sections: body.sections
345
+ };
346
+ }
290
347
  function publish(entry) {
291
- const next = resultOf(entry.plan, entry.built.live.toArray);
292
- if (deepEquals(entry.result, next)) return;
293
- entry.result = next;
294
- for (const listener of entry.listeners)listener(next);
348
+ const next = reconciled(entry.result, keyedOf(entry.plan, [
349
+ ...entry.built.live.entries()
350
+ ]));
351
+ if (next === null) return;
352
+ entry.result = next.keyed;
353
+ for (const listener of entry.listeners)listener(next.change);
295
354
  }
296
355
  return {
297
356
  apply (set) {
@@ -320,12 +379,15 @@ export function createReadSide() {
320
379
  async query (plan) {
321
380
  const { live: collection, dispose } = built(rows, plan);
322
381
  try {
323
- return resultOf(plan, await collection.toArrayWhenReady());
382
+ await collection.toArrayWhenReady();
383
+ return keyedOf(plan, [
384
+ ...collection.entries()
385
+ ]).result;
324
386
  } finally{
325
387
  dispose();
326
388
  }
327
389
  },
328
- observe (plan, identity, listener) {
390
+ watch (plan, identity, deliver) {
329
391
  let entry = shared.get(identity);
330
392
  if (entry === undefined) {
331
393
  const created = {
@@ -342,23 +404,32 @@ export function createReadSide() {
342
404
  entry = created;
343
405
  }
344
406
  const observed = entry;
345
- observed.listeners.add(listener);
407
+ observed.listeners.add(deliver);
346
408
  observed.built.live.onFirstReady(()=>{
347
- if (!observed.listeners.has(listener)) return;
409
+ if (!observed.listeners.has(deliver)) return;
348
410
  if (observed.subscription === null) {
349
- observed.result = resultOf(observed.plan, observed.built.live.toArray);
411
+ observed.result = keyedOf(observed.plan, [
412
+ ...observed.built.live.entries()
413
+ ]);
350
414
  observed.subscription = observed.built.live.subscribeChanges(()=>{
351
415
  publish(observed);
352
416
  });
353
417
  }
354
- listener(observed.result);
418
+ deliver(observed.result);
355
419
  });
356
420
  return ()=>{
357
- if (!observed.listeners.delete(listener) || observed.listeners.size > 0) return;
421
+ if (!observed.listeners.delete(deliver) || observed.listeners.size > 0) return;
358
422
  observed.subscription?.unsubscribe();
359
423
  observed.subscription = null;
360
424
  };
361
425
  },
426
+ documents () {
427
+ return rows.toArray.filter((row)=>row.kind === 'document').map(searched);
428
+ },
429
+ document (room, path) {
430
+ const row = rows.get(documentKey(room, path));
431
+ return row === undefined ? null : searched(row);
432
+ },
362
433
  close () {
363
434
  for (const entry of shared.values()){
364
435
  entry.listeners.clear();