@dxos/echo-query 0.8.4-main.dedc0f3 → 0.8.4-main.e00bdcdb52

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.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/neutral/index.mjs +917 -0
  3. package/dist/lib/neutral/index.mjs.map +7 -0
  4. package/dist/lib/neutral/meta.json +1 -0
  5. package/dist/query-lite/index.d.ts +9975 -0
  6. package/dist/query-lite/index.d.ts.map +1 -0
  7. package/dist/query-lite/index.js +548 -0
  8. package/dist/query-lite/index.js.map +1 -0
  9. package/dist/types/src/index.d.ts +2 -0
  10. package/dist/types/src/index.d.ts.map +1 -1
  11. package/dist/types/src/parser/gen/index.d.ts +8 -0
  12. package/dist/types/src/parser/gen/index.d.ts.map +1 -0
  13. package/dist/types/src/parser/gen/query.d.ts +3 -0
  14. package/dist/types/src/parser/gen/query.d.ts.map +1 -0
  15. package/dist/types/src/parser/gen/query.terms.d.ts +2 -0
  16. package/dist/types/src/parser/gen/query.terms.d.ts.map +1 -0
  17. package/dist/types/src/parser/index.d.ts +3 -0
  18. package/dist/types/src/parser/index.d.ts.map +1 -0
  19. package/dist/types/src/parser/query-builder.d.ts +89 -0
  20. package/dist/types/src/parser/query-builder.d.ts.map +1 -0
  21. package/dist/types/src/parser/query.test.d.ts +2 -0
  22. package/dist/types/src/parser/query.test.d.ts.map +1 -0
  23. package/dist/types/src/query-lite/index.d.ts +2 -0
  24. package/dist/types/src/query-lite/index.d.ts.map +1 -0
  25. package/dist/types/src/query-lite/query-lite.d.ts +8 -0
  26. package/dist/types/src/query-lite/query-lite.d.ts.map +1 -0
  27. package/dist/types/src/sandbox/index.d.ts +2 -0
  28. package/dist/types/src/sandbox/index.d.ts.map +1 -0
  29. package/dist/types/src/sandbox/query-sandbox.d.ts +21 -0
  30. package/dist/types/src/sandbox/query-sandbox.d.ts.map +1 -0
  31. package/dist/types/src/sandbox/query-sandbox.test.d.ts +2 -0
  32. package/dist/types/src/sandbox/query-sandbox.test.d.ts.map +1 -0
  33. package/dist/types/src/sandbox/quickjs.d.ts +8 -0
  34. package/dist/types/src/sandbox/quickjs.d.ts.map +1 -0
  35. package/dist/types/src/sandbox/quickjs.test.d.ts +2 -0
  36. package/dist/types/src/sandbox/quickjs.test.d.ts.map +1 -0
  37. package/dist/types/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +29 -13
  39. package/src/env.d.ts +8 -0
  40. package/src/index.ts +3 -0
  41. package/src/parser/gen/index.ts +13 -0
  42. package/src/parser/gen/query.terms.ts +27 -0
  43. package/src/parser/gen/query.ts +18 -0
  44. package/src/parser/index.ts +6 -0
  45. package/src/parser/query-builder.ts +799 -0
  46. package/src/parser/query.grammar +130 -0
  47. package/src/parser/query.test.ts +529 -0
  48. package/src/query-lite/index.ts +5 -0
  49. package/src/query-lite/query-lite.ts +744 -0
  50. package/src/sandbox/index.ts +5 -0
  51. package/src/sandbox/query-sandbox.test.ts +53 -0
  52. package/src/sandbox/query-sandbox.ts +72 -0
  53. package/src/sandbox/quickjs.test.ts +67 -0
  54. package/src/sandbox/quickjs.ts +33 -0
  55. package/dist/lib/browser/index.mjs +0 -2
  56. package/dist/lib/browser/index.mjs.map +0 -7
  57. package/dist/lib/browser/meta.json +0 -1
  58. package/dist/lib/node-esm/index.mjs +0 -2
  59. package/dist/lib/node-esm/index.mjs.map +0 -7
  60. package/dist/lib/node-esm/meta.json +0 -1
  61. package/dist/types/src/search.test.d.ts +0 -2
  62. package/dist/types/src/search.test.d.ts.map +0 -1
  63. package/src/search.test.ts +0 -49
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './query-sandbox';
@@ -0,0 +1,53 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { afterAll, beforeAll, describe, expect, test } from 'vitest';
6
+
7
+ import { Filter, Order, Query } from '@dxos/echo';
8
+ import { trim } from '@dxos/util';
9
+
10
+ import { QuerySandbox } from './query-sandbox';
11
+
12
+ describe('QuerySandbox', () => {
13
+ const sandbox = new QuerySandbox();
14
+ beforeAll(() => sandbox.open());
15
+ afterAll(() => sandbox.close());
16
+
17
+ test('works', { timeout: 10_000 }, async () => {
18
+ const ast = sandbox.eval(trim`
19
+ Query.select(Filter.typename('org.dxos.type.person'))
20
+ `);
21
+ expect(ast).toEqual(Query.select(Filter.typename('org.dxos.type.person')).ast);
22
+ });
23
+
24
+ test('works with just Filter passed in', () => {
25
+ const ast = sandbox.eval(trim`
26
+ Filter.typename('org.dxos.type.person')
27
+ `);
28
+ expect(ast).toEqual(Query.select(Filter.typename('org.dxos.type.person')).ast);
29
+ });
30
+
31
+ test('Order', () => {
32
+ const ast = sandbox.eval(trim`
33
+ Query.type('org.dxos.type.person').orderBy(Order.property('name', 'desc'))
34
+ `);
35
+ expect(ast).toEqual(Query.type('org.dxos.type.person').orderBy(Order.property('name', 'desc')).ast);
36
+ });
37
+
38
+ test('traversal', () => {
39
+ const ast = sandbox.eval(trim`
40
+ Query.select(Filter.type('org.dxos.type.person', { jobTitle: 'investor' }))
41
+ .reference('organization')
42
+ .targetOf('org.dxos.relation.hasSubject')
43
+ .source()
44
+ `);
45
+
46
+ expect(ast).toEqual(
47
+ Query.select(Filter.type('org.dxos.type.person', { jobTitle: 'investor' }))
48
+ .reference('organization')
49
+ .targetOf('org.dxos.relation.hasSubject')
50
+ .source().ast,
51
+ );
52
+ });
53
+ });
@@ -0,0 +1,72 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Resource } from '@dxos/context';
6
+ import { Query, type QueryAST } from '@dxos/echo';
7
+ import { trim } from '@dxos/util';
8
+ import { type QuickJSRuntime, type QuickJSWASMModule, createQuickJS } from '@dxos/vendor-quickjs';
9
+
10
+ import envCode from '#query-lite?raw';
11
+
12
+ import { unwrapResult } from './quickjs';
13
+
14
+ /**
15
+ * Evaluates queries written in JavaScript using QuickJS.
16
+ * Queries are expected to use the echo Query API.
17
+ * `Query`, `Filter` and `Order` are provided as globals.
18
+ */
19
+ export class QuerySandbox extends Resource {
20
+ // Caching the wasm module.
21
+ private static quickJS: Promise<QuickJSWASMModule> | null = null;
22
+ static getQuickJS() {
23
+ if (!QuerySandbox.quickJS) {
24
+ QuerySandbox.quickJS = createQuickJS();
25
+ }
26
+
27
+ return QuerySandbox.quickJS;
28
+ }
29
+
30
+ #runtime!: QuickJSRuntime;
31
+
32
+ protected override async _open() {
33
+ const quickJS = await QuerySandbox.getQuickJS();
34
+ this.#runtime = quickJS.newRuntime({
35
+ moduleLoader: (moduleName, _context) => {
36
+ switch (moduleName) {
37
+ case 'dxos:query-lite':
38
+ return envCode;
39
+ default:
40
+ throw new Error(`Module not found: ${moduleName}`);
41
+ }
42
+ },
43
+ });
44
+ }
45
+
46
+ protected override async _close() {
47
+ this.#runtime.dispose();
48
+ }
49
+
50
+ /**
51
+ * Evaluates the query code.
52
+ * @param queryCode Example: `Query.select(Filter.typename('org.dxos.type.person'))`
53
+ */
54
+ eval(queryCode: string): QueryAST.Query {
55
+ using context = this.#runtime.newContext();
56
+ const globals = trim`
57
+ import { Filter, Order, Query } from 'dxos:query-lite';
58
+ globalThis.Filter = Filter;
59
+ globalThis.Order = Order;
60
+ globalThis.Query = Query;
61
+ `;
62
+
63
+ unwrapResult(context, context.evalCode(globals)).dispose();
64
+ using query = unwrapResult(context, context.evalCode(queryCode));
65
+ const result = context.dump(query);
66
+ if ('~Filter' in result) {
67
+ return Query.select(result).ast;
68
+ } else {
69
+ return result.ast;
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,67 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { expect, test } from 'vitest';
6
+
7
+ import { createQuickJS } from '@dxos/vendor-quickjs';
8
+
9
+ import { unwrapResult } from './quickjs';
10
+
11
+ test('works', async () => {
12
+ const QuickJS = await createQuickJS();
13
+ using context = QuickJS.newContext();
14
+
15
+ using world = context.newString('world');
16
+ context.setProp(context.global, 'NAME', world);
17
+
18
+ using result = unwrapResult(context, context.evalCode(`"Hello " + NAME + "!"`));
19
+ expect(context.dump(result)).toBe('Hello world!');
20
+ });
21
+
22
+ test('errors get propagated', async () => {
23
+ const QuickJS = await createQuickJS();
24
+ using runtime = QuickJS.newRuntime();
25
+ using context = runtime.newContext();
26
+ expect(() => unwrapResult(context, context.evalCode(`throw new Error('test')`))).toThrow();
27
+ });
28
+
29
+ test('global variables are shared in a context', async () => {
30
+ const QuickJS = await createQuickJS();
31
+ const context = QuickJS.newContext();
32
+
33
+ unwrapResult(context, context.evalCode('globalThis.name = "world"')).dispose();
34
+ using result = unwrapResult(context, context.evalCode(`"Hello " + name + "!"`));
35
+ expect(context.dump(result)).toBe('Hello world!');
36
+ });
37
+
38
+ test('global variables are shared in a context created from runtime', async () => {
39
+ const QuickJS = await createQuickJS();
40
+ using runtime = QuickJS.newRuntime();
41
+ using context = runtime.newContext();
42
+
43
+ unwrapResult(context, context.evalCode('globalThis.name = "world"'));
44
+ using result = unwrapResult(context, context.evalCode(`"Hello " + name + "!"`));
45
+ expect(context.dump(result)).toBe('Hello world!');
46
+ });
47
+
48
+ test('load module', async () => {
49
+ const QuickJS = await createQuickJS();
50
+ using runtime = QuickJS.newRuntime({
51
+ moduleLoader: (name, _context) => {
52
+ switch (name) {
53
+ case 'test:name':
54
+ return `
55
+ export const name = 'world';
56
+ `;
57
+ default:
58
+ throw new Error('unknown module');
59
+ }
60
+ },
61
+ });
62
+ using context = runtime.newContext();
63
+
64
+ unwrapResult(context, context.evalCode('import { name } from "test:name"; globalThis.name = name;')).dispose();
65
+ using result = unwrapResult(context, context.evalCode(`"Hello " + name + "!"`));
66
+ expect(context.dump(result)).toBe('Hello world!');
67
+ });
@@ -0,0 +1,33 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type QuickJSContext, type QuickJSHandle, type SuccessOrFail } from '@dxos/vendor-quickjs';
6
+
7
+ /**
8
+ * Unwraps a result and throws the underlying error.
9
+ *
10
+ * Replacement for `QuickJScontext.unwrapResult` because that seems to cause an OOM.
11
+ */
12
+ // TODO(burdon): Factor out.
13
+ export const unwrapResult = <T>(context: QuickJSContext, result: SuccessOrFail<T, QuickJSHandle>): T => {
14
+ if (result.error) {
15
+ const contextError = context.dump(result.error);
16
+ result.error.dispose();
17
+ if (
18
+ typeof contextError === 'object' &&
19
+ typeof contextError.name === 'string' &&
20
+ typeof contextError.message === 'string'
21
+ ) {
22
+ const error = new Error(contextError.message);
23
+ Object.defineProperty(error, 'name', { value: contextError.name });
24
+ const originalStack = error.stack;
25
+ error.stack = `${contextError.name}: ${contextError.message}\n${contextError.stack}${originalStack?.split('\n').slice(1).join('\n') ?? ''}`;
26
+ throw error;
27
+ } else {
28
+ throw new Error(String(contextError));
29
+ }
30
+ }
31
+
32
+ return result.value;
33
+ };
@@ -1,2 +0,0 @@
1
- import "@dxos/node-std/globals";
2
- //# sourceMappingURL=index.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1 +0,0 @@
1
- {"inputs":{"src/index.ts":{"bytes":368,"imports":[],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/lib/browser/index.mjs":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":68}}}
@@ -1,2 +0,0 @@
1
- import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
- //# sourceMappingURL=index.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1 +0,0 @@
1
- {"inputs":{"src/index.ts":{"bytes":368,"imports":[],"format":"esm"}},"outputs":{"dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/lib/node-esm/index.mjs":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":127}}}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=search.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../../src/search.test.ts"],"names":[],"mappings":""}
@@ -1,49 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import { create, insert, search } from '@orama/orama';
6
- import { describe, expect, test } from 'vitest';
7
-
8
- import { createTestObjectGenerator } from '@dxos/echo-generator';
9
- import { faker } from '@dxos/random';
10
- import { range } from '@dxos/util';
11
-
12
- faker.seed(1);
13
-
14
- // TODO(burdon): Factor out functions.
15
- // TODO(burdon): Chat/search/suggest.
16
- // TODO(burdon): Integrate with schema.
17
- // TODO(burdon): Factor out agent/plugin-search.
18
- // TODO(burdon): Proto defs.
19
- // TODO(burdon): Client/server cascading calls?
20
- // TODO(burdon): SDK/API.
21
-
22
- describe('Orama', () => {
23
- test('basic', async () => {
24
- // TODO(burdon): Create Client/spaces.
25
- const generator = createTestObjectGenerator();
26
-
27
- // https://www.npmjs.com/package/@orama/orama
28
- const db = await create({
29
- schema: {
30
- // TODO(burdon): Index TypedObject using schema; separate db for each schema?
31
- title: 'string',
32
- embedding: 'vector[1536]', // Vector size must be expressed during schema initialization.
33
- meta: {
34
- rating: 'number',
35
- },
36
- },
37
- });
38
-
39
- {
40
- const objects = await Promise.all(range(10, () => generator.createObject()));
41
- await Promise.all(objects.map((object) => insert<any>(db, object)));
42
- }
43
-
44
- {
45
- const result = await search(db, { term: 'shoes' });
46
- expect(result.hits).to.have.length;
47
- }
48
- });
49
- });