@dxos/echo-pipeline 0.8.3 → 0.8.4-main.1c7ec43d41

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 (239) hide show
  1. package/dist/lib/{browser/chunk-35I6ERLG.mjs → neutral/chunk-VIHYDCCC.mjs} +313 -709
  2. package/dist/lib/neutral/chunk-VIHYDCCC.mjs.map +7 -0
  3. package/dist/lib/neutral/chunk-YBC6ONBZ.mjs +247 -0
  4. package/dist/lib/neutral/chunk-YBC6ONBZ.mjs.map +7 -0
  5. package/dist/lib/{browser → neutral}/filter/index.mjs +3 -2
  6. package/dist/lib/neutral/index.mjs +7065 -0
  7. package/dist/lib/neutral/index.mjs.map +7 -0
  8. package/dist/lib/neutral/meta.json +1 -0
  9. package/dist/lib/{browser → neutral}/testing/index.mjs +90 -311
  10. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  11. package/dist/types/src/automerge/automerge-host-subduction.test.d.ts +2 -0
  12. package/dist/types/src/automerge/automerge-host-subduction.test.d.ts.map +1 -0
  13. package/dist/types/src/automerge/automerge-host.d.ts +99 -54
  14. package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
  15. package/dist/types/src/automerge/automerge-repo-subduction.test.d.ts +2 -0
  16. package/dist/types/src/automerge/automerge-repo-subduction.test.d.ts.map +1 -0
  17. package/dist/types/src/automerge/automerge-repo.test.d.ts +1 -1
  18. package/dist/types/src/automerge/automerge-repo.test.d.ts.map +1 -1
  19. package/dist/types/src/automerge/automerge-subduction.test.d.ts +2 -0
  20. package/dist/types/src/automerge/automerge-subduction.test.d.ts.map +1 -0
  21. package/dist/types/src/automerge/collection-synchronizer.d.ts +25 -4
  22. package/dist/types/src/automerge/collection-synchronizer.d.ts.map +1 -1
  23. package/dist/types/src/automerge/echo-data-monitor.d.ts.map +1 -1
  24. package/dist/types/src/automerge/echo-network-adapter.d.ts +23 -10
  25. package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
  26. package/dist/types/src/automerge/echo-replicator.d.ts +38 -15
  27. package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
  28. package/dist/types/src/automerge/handle-state.d.ts +52 -0
  29. package/dist/types/src/automerge/handle-state.d.ts.map +1 -0
  30. package/dist/types/src/automerge/heads-store.d.ts +9 -2
  31. package/dist/types/src/automerge/heads-store.d.ts.map +1 -1
  32. package/dist/types/src/automerge/index.d.ts +2 -1
  33. package/dist/types/src/automerge/index.d.ts.map +1 -1
  34. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts +9 -5
  35. package/dist/types/src/automerge/leveldb-storage-adapter.d.ts.map +1 -1
  36. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts +9 -8
  37. package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
  38. package/dist/types/src/automerge/mesh-echo-replicator.d.ts +6 -5
  39. package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
  40. package/dist/types/src/automerge/network-protocol.d.ts.map +1 -1
  41. package/dist/types/src/automerge/space-collection.d.ts.map +1 -1
  42. package/dist/types/src/common/codec.d.ts +1 -1
  43. package/dist/types/src/common/codec.d.ts.map +1 -1
  44. package/dist/types/src/common/feeds.d.ts.map +1 -1
  45. package/dist/types/src/common/space-id.d.ts.map +1 -1
  46. package/dist/types/src/db-host/automerge-data-source.d.ts +35 -0
  47. package/dist/types/src/db-host/automerge-data-source.d.ts.map +1 -0
  48. package/dist/types/src/db-host/automerge-data-source.test.d.ts +2 -0
  49. package/dist/types/src/db-host/automerge-data-source.test.d.ts.map +1 -0
  50. package/dist/types/src/db-host/automerge-metrics.d.ts.map +1 -1
  51. package/dist/types/src/db-host/data-service.d.ts +8 -7
  52. package/dist/types/src/db-host/data-service.d.ts.map +1 -1
  53. package/dist/types/src/db-host/database-root.d.ts +9 -3
  54. package/dist/types/src/db-host/database-root.d.ts.map +1 -1
  55. package/dist/types/src/db-host/documents-synchronizer.d.ts +9 -8
  56. package/dist/types/src/db-host/documents-synchronizer.d.ts.map +1 -1
  57. package/dist/types/src/db-host/echo-host.d.ts +62 -27
  58. package/dist/types/src/db-host/echo-host.d.ts.map +1 -1
  59. package/dist/types/src/db-host/index.d.ts +2 -0
  60. package/dist/types/src/db-host/index.d.ts.map +1 -1
  61. package/dist/types/src/db-host/invalidation-hint.d.ts +19 -0
  62. package/dist/types/src/db-host/invalidation-hint.d.ts.map +1 -0
  63. package/dist/types/src/db-host/local-queue-service.d.ts +19 -0
  64. package/dist/types/src/db-host/local-queue-service.d.ts.map +1 -0
  65. package/dist/types/src/db-host/query-invalidation.test.d.ts +2 -0
  66. package/dist/types/src/db-host/query-invalidation.test.d.ts.map +1 -0
  67. package/dist/types/src/db-host/query-service.d.ts +19 -11
  68. package/dist/types/src/db-host/query-service.d.ts.map +1 -1
  69. package/dist/types/src/db-host/queue-data-source.d.ts +38 -0
  70. package/dist/types/src/db-host/queue-data-source.d.ts.map +1 -0
  71. package/dist/types/src/db-host/queue-service.test.d.ts +2 -0
  72. package/dist/types/src/db-host/queue-service.test.d.ts.map +1 -0
  73. package/dist/types/src/db-host/space-state-manager.d.ts +4 -3
  74. package/dist/types/src/db-host/space-state-manager.d.ts.map +1 -1
  75. package/dist/types/src/db-host/stub.d.ts +11 -0
  76. package/dist/types/src/db-host/stub.d.ts.map +1 -0
  77. package/dist/types/src/edge/echo-edge-replicator.d.ts +10 -7
  78. package/dist/types/src/edge/echo-edge-replicator.d.ts.map +1 -1
  79. package/dist/types/src/edge/echo-edge-subduction-replicator.d.ts +39 -0
  80. package/dist/types/src/edge/echo-edge-subduction-replicator.d.ts.map +1 -0
  81. package/dist/types/src/edge/echo-edge-subduction-replicator.test.d.ts +2 -0
  82. package/dist/types/src/edge/echo-edge-subduction-replicator.test.d.ts.map +1 -0
  83. package/dist/types/src/edge/index.d.ts +1 -0
  84. package/dist/types/src/edge/index.d.ts.map +1 -1
  85. package/dist/types/src/edge/inflight-request-limiter.d.ts.map +1 -1
  86. package/dist/types/src/filter/filter-match.d.ts +4 -1
  87. package/dist/types/src/filter/filter-match.d.ts.map +1 -1
  88. package/dist/types/src/metadata/metadata-store.d.ts +1 -1
  89. package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
  90. package/dist/types/src/pipeline/message-selector.d.ts.map +1 -1
  91. package/dist/types/src/pipeline/pipeline.d.ts +3 -3
  92. package/dist/types/src/pipeline/pipeline.d.ts.map +1 -1
  93. package/dist/types/src/pipeline/timeframe-clock.d.ts.map +1 -1
  94. package/dist/types/src/query/errors.d.ts +22 -10
  95. package/dist/types/src/query/errors.d.ts.map +1 -1
  96. package/dist/types/src/query/plan.d.ts +66 -8
  97. package/dist/types/src/query/plan.d.ts.map +1 -1
  98. package/dist/types/src/query/query-executor.d.ts +66 -11
  99. package/dist/types/src/query/query-executor.d.ts.map +1 -1
  100. package/dist/types/src/query/query-planner.d.ts +12 -1
  101. package/dist/types/src/query/query-planner.d.ts.map +1 -1
  102. package/dist/types/src/space/admission-discovery-extension.d.ts.map +1 -1
  103. package/dist/types/src/space/auth.d.ts +3 -3
  104. package/dist/types/src/space/auth.d.ts.map +1 -1
  105. package/dist/types/src/space/control-pipeline.d.ts +5 -4
  106. package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
  107. package/dist/types/src/space/space-manager.d.ts +8 -8
  108. package/dist/types/src/space/space-manager.d.ts.map +1 -1
  109. package/dist/types/src/space/space-protocol.d.ts +10 -9
  110. package/dist/types/src/space/space-protocol.d.ts.map +1 -1
  111. package/dist/types/src/space/space.d.ts +6 -6
  112. package/dist/types/src/space/space.d.ts.map +1 -1
  113. package/dist/types/src/testing/change-metadata.d.ts.map +1 -1
  114. package/dist/types/src/testing/index.d.ts +0 -2
  115. package/dist/types/src/testing/index.d.ts.map +1 -1
  116. package/dist/types/src/testing/test-agent-builder.d.ts +2 -2
  117. package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
  118. package/dist/types/src/testing/test-feed-builder.d.ts.map +1 -1
  119. package/dist/types/src/testing/test-network-adapter.d.ts +1 -1
  120. package/dist/types/src/testing/test-network-adapter.d.ts.map +1 -1
  121. package/dist/types/src/testing/test-replicator.d.ts +14 -13
  122. package/dist/types/src/testing/test-replicator.d.ts.map +1 -1
  123. package/dist/types/src/util.d.ts +1 -1
  124. package/dist/types/src/util.d.ts.map +1 -1
  125. package/dist/types/tsconfig.tsbuildinfo +1 -1
  126. package/package.json +56 -54
  127. package/src/automerge/automerge-host-subduction.test.ts +247 -0
  128. package/src/automerge/automerge-host.test.ts +65 -39
  129. package/src/automerge/automerge-host.ts +589 -206
  130. package/src/automerge/automerge-repo-subduction.test.ts +1049 -0
  131. package/src/automerge/automerge-repo.test.ts +349 -91
  132. package/src/automerge/automerge-subduction.test.ts +330 -0
  133. package/src/automerge/collection-synchronizer.test.ts +53 -17
  134. package/src/automerge/collection-synchronizer.ts +119 -36
  135. package/src/automerge/echo-data-monitor.ts +1 -1
  136. package/src/automerge/echo-network-adapter.test.ts +5 -4
  137. package/src/automerge/echo-network-adapter.ts +74 -30
  138. package/src/automerge/echo-replicator.ts +41 -15
  139. package/src/automerge/handle-state.ts +62 -0
  140. package/src/automerge/heads-store.ts +42 -3
  141. package/src/automerge/index.ts +2 -1
  142. package/src/automerge/leveldb-storage-adapter.ts +40 -11
  143. package/src/automerge/mesh-echo-replicator-connection.ts +12 -8
  144. package/src/automerge/mesh-echo-replicator.ts +15 -11
  145. package/src/automerge/storage-adapter.test.ts +1 -1
  146. package/src/common/space-id.ts +1 -1
  147. package/src/db-host/automerge-data-source.test.ts +299 -0
  148. package/src/db-host/automerge-data-source.ts +187 -0
  149. package/src/db-host/data-service.ts +25 -26
  150. package/src/db-host/database-root.ts +20 -8
  151. package/src/db-host/documents-synchronizer.test.ts +143 -14
  152. package/src/db-host/documents-synchronizer.ts +72 -55
  153. package/src/db-host/echo-host.ts +348 -96
  154. package/src/db-host/index.ts +2 -0
  155. package/src/db-host/invalidation-hint.ts +50 -0
  156. package/src/db-host/local-queue-service.ts +127 -0
  157. package/src/db-host/query-invalidation.test.ts +270 -0
  158. package/src/db-host/query-service.ts +111 -106
  159. package/src/db-host/queue-data-source.ts +160 -0
  160. package/src/db-host/queue-service.test.ts +145 -0
  161. package/src/db-host/space-state-manager.ts +12 -10
  162. package/src/db-host/stub.ts +33 -0
  163. package/src/edge/echo-edge-replicator.test.ts +12 -10
  164. package/src/edge/echo-edge-replicator.ts +144 -58
  165. package/src/edge/echo-edge-subduction-replicator.test.ts +158 -0
  166. package/src/edge/echo-edge-subduction-replicator.ts +377 -0
  167. package/src/edge/index.ts +1 -0
  168. package/src/filter/filter-match.test.ts +68 -32
  169. package/src/filter/filter-match.ts +184 -20
  170. package/src/metadata/metadata-store.ts +11 -8
  171. package/src/pipeline/pipeline-stress.test.ts +1 -1
  172. package/src/pipeline/pipeline.test.ts +2 -2
  173. package/src/pipeline/pipeline.ts +9 -7
  174. package/src/query/errors.ts +3 -1
  175. package/src/query/plan.ts +82 -8
  176. package/src/query/query-executor.ts +1199 -164
  177. package/src/query/query-planner.test.ts +993 -81
  178. package/src/query/query-planner.ts +467 -27
  179. package/src/space/admission-discovery-extension.ts +3 -3
  180. package/src/space/auth.ts +6 -6
  181. package/src/space/control-pipeline.test.ts +5 -4
  182. package/src/space/control-pipeline.ts +16 -13
  183. package/src/space/space-manager.browser.test.ts +1 -1
  184. package/src/space/space-manager.ts +16 -20
  185. package/src/space/space-protocol.browser.test.ts +15 -14
  186. package/src/space/space-protocol.test.ts +15 -14
  187. package/src/space/space-protocol.ts +22 -18
  188. package/src/space/space.test.ts +3 -3
  189. package/src/space/space.ts +11 -11
  190. package/src/testing/index.ts +0 -2
  191. package/src/testing/test-agent-builder.ts +3 -3
  192. package/src/testing/test-network-adapter.ts +24 -3
  193. package/src/testing/test-replicator.ts +19 -20
  194. package/src/util.ts +7 -3
  195. package/dist/lib/browser/chunk-35I6ERLG.mjs.map +0 -7
  196. package/dist/lib/browser/chunk-CGS2ULMK.mjs +0 -11
  197. package/dist/lib/browser/chunk-CGS2ULMK.mjs.map +0 -7
  198. package/dist/lib/browser/chunk-TQJTKNMS.mjs +0 -126
  199. package/dist/lib/browser/chunk-TQJTKNMS.mjs.map +0 -7
  200. package/dist/lib/browser/index.mjs +0 -4743
  201. package/dist/lib/browser/index.mjs.map +0 -7
  202. package/dist/lib/browser/meta.json +0 -1
  203. package/dist/lib/browser/testing/index.mjs.map +0 -7
  204. package/dist/lib/node/chunk-HOPOFWAL.cjs +0 -147
  205. package/dist/lib/node/chunk-HOPOFWAL.cjs.map +0 -7
  206. package/dist/lib/node/chunk-JXX6LF5U.cjs +0 -2084
  207. package/dist/lib/node/chunk-JXX6LF5U.cjs.map +0 -7
  208. package/dist/lib/node/chunk-Q7SFCCGT.cjs +0 -33
  209. package/dist/lib/node/chunk-Q7SFCCGT.cjs.map +0 -7
  210. package/dist/lib/node/filter/index.cjs +0 -32
  211. package/dist/lib/node/filter/index.cjs.map +0 -7
  212. package/dist/lib/node/index.cjs +0 -4699
  213. package/dist/lib/node/index.cjs.map +0 -7
  214. package/dist/lib/node/meta.json +0 -1
  215. package/dist/lib/node/testing/index.cjs +0 -753
  216. package/dist/lib/node/testing/index.cjs.map +0 -7
  217. package/dist/lib/node-esm/chunk-5BHLPT24.mjs +0 -2067
  218. package/dist/lib/node-esm/chunk-5BHLPT24.mjs.map +0 -7
  219. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  220. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
  221. package/dist/lib/node-esm/chunk-RVK35BS7.mjs +0 -126
  222. package/dist/lib/node-esm/chunk-RVK35BS7.mjs.map +0 -7
  223. package/dist/lib/node-esm/filter/index.mjs +0 -11
  224. package/dist/lib/node-esm/filter/index.mjs.map +0 -7
  225. package/dist/lib/node-esm/index.mjs +0 -4743
  226. package/dist/lib/node-esm/index.mjs.map +0 -7
  227. package/dist/lib/node-esm/meta.json +0 -1
  228. package/dist/lib/node-esm/testing/index.mjs +0 -742
  229. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  230. package/dist/types/src/db-host/documents-iterator.d.ts +0 -7
  231. package/dist/types/src/db-host/documents-iterator.d.ts.map +0 -1
  232. package/dist/types/src/testing/test-data.d.ts +0 -18
  233. package/dist/types/src/testing/test-data.d.ts.map +0 -1
  234. package/dist/types/src/testing/test-schema.d.ts +0 -37
  235. package/dist/types/src/testing/test-schema.d.ts.map +0 -1
  236. package/src/db-host/documents-iterator.ts +0 -74
  237. package/src/testing/test-data.ts +0 -127
  238. package/src/testing/test-schema.ts +0 -53
  239. /package/dist/lib/{browser → neutral}/filter/index.mjs.map +0 -0
@@ -1,15 +1,19 @@
1
+ //
2
+ // Copyright 2025 example.com
3
+ //
4
+
1
5
  //
2
6
  // Copyright 2025 DXOS.org
3
7
  //
4
8
 
5
9
  import { describe, expect, test } from 'vitest';
6
10
 
7
- import { Filter, Query } from '@dxos/echo';
11
+ import { Filter, Order, Query } from '@dxos/echo';
8
12
  import { type QueryAST } from '@dxos/echo-protocol';
9
- import { SpaceId } from '@dxos/keys';
13
+ import { TestSchema } from '@dxos/echo/testing';
14
+ import { DXN, SpaceId } from '@dxos/keys';
10
15
 
11
16
  import { QueryPlanner } from './query-planner';
12
- import { TestSchema } from '../testing';
13
17
 
14
18
  describe('QueryPlanner', () => {
15
19
  const planner = new QueryPlanner();
@@ -23,21 +27,90 @@ describe('QueryPlanner', () => {
23
27
  "steps": [
24
28
  {
25
29
  "_tag": "SelectStep",
30
+ "scope": {
31
+ "spaceIds": [
32
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
33
+ ],
34
+ },
26
35
  "selector": {
27
36
  "_tag": "TypeSelector",
28
37
  "inverted": false,
29
38
  "typename": [
30
- "dxn:type:dxos.org/type/Person:0.1.0",
39
+ "dxn:type:com.example.type.person:0.1.0",
31
40
  ],
32
41
  },
33
- "spaces": [
34
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
42
+ },
43
+ {
44
+ "_tag": "FilterDeletedStep",
45
+ "mode": "only-non-deleted",
46
+ },
47
+ {
48
+ "_tag": "FilterStep",
49
+ "filter": {
50
+ "id": undefined,
51
+ "props": {},
52
+ "type": "object",
53
+ "typename": "dxn:type:com.example.type.person:0.1.0",
54
+ },
55
+ },
56
+ {
57
+ "_tag": "OrderStep",
58
+ "order": [
59
+ {
60
+ "kind": "natural",
61
+ },
35
62
  ],
36
63
  },
64
+ ],
65
+ }
66
+ `);
67
+ });
68
+
69
+ test('get all people ordered by name', () => {
70
+ const query = Query.select(Filter.type(TestSchema.Person)).orderBy(Order.property('name', 'asc'));
71
+
72
+ const plan = planner.createPlan(withSpaceIdOptions(query.ast));
73
+ expect(plan).toMatchInlineSnapshot(`
74
+ {
75
+ "steps": [
76
+ {
77
+ "_tag": "SelectStep",
78
+ "scope": {
79
+ "spaceIds": [
80
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
81
+ ],
82
+ },
83
+ "selector": {
84
+ "_tag": "TypeSelector",
85
+ "inverted": false,
86
+ "typename": [
87
+ "dxn:type:com.example.type.person:0.1.0",
88
+ ],
89
+ },
90
+ },
37
91
  {
38
92
  "_tag": "FilterDeletedStep",
39
93
  "mode": "only-non-deleted",
40
94
  },
95
+ {
96
+ "_tag": "FilterStep",
97
+ "filter": {
98
+ "id": undefined,
99
+ "props": {},
100
+ "type": "object",
101
+ "typename": "dxn:type:com.example.type.person:0.1.0",
102
+ },
103
+ },
104
+ {
105
+ "_tag": "OrderStep",
106
+ "order": [
107
+ {
108
+ "direction": "asc",
109
+ "kind": "property",
110
+ "property": "name",
111
+ },
112
+ ],
113
+ },
41
114
  ],
42
115
  }
43
116
  `);
@@ -52,16 +125,18 @@ describe('QueryPlanner', () => {
52
125
  "steps": [
53
126
  {
54
127
  "_tag": "SelectStep",
128
+ "scope": {
129
+ "spaceIds": [
130
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
131
+ ],
132
+ },
55
133
  "selector": {
56
134
  "_tag": "TypeSelector",
57
135
  "inverted": false,
58
136
  "typename": [
59
- "dxn:type:dxos.org/type/Person:0.1.0",
137
+ "dxn:type:com.example.type.person:0.1.0",
60
138
  ],
61
139
  },
62
- "spaces": [
63
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
64
- ],
65
140
  },
66
141
  {
67
142
  "_tag": "FilterDeletedStep",
@@ -79,9 +154,17 @@ describe('QueryPlanner', () => {
79
154
  },
80
155
  },
81
156
  "type": "object",
82
- "typename": null,
157
+ "typename": "dxn:type:com.example.type.person:0.1.0",
83
158
  },
84
159
  },
160
+ {
161
+ "_tag": "OrderStep",
162
+ "order": [
163
+ {
164
+ "kind": "natural",
165
+ },
166
+ ],
167
+ },
85
168
  ],
86
169
  }
87
170
  `);
@@ -89,7 +172,9 @@ describe('QueryPlanner', () => {
89
172
 
90
173
  test('get all orgs Fred worked for since 2020', () => {
91
174
  const query = Query.select(Filter.type(TestSchema.Person, { id: '01JVS9YYT5VMVJW0GGTM1YHCCH' }))
92
- .sourceOf(TestSchema.WorksFor, { since: Filter.gt('2020') })
175
+ .sourceOf(TestSchema.EmployedBy, {
176
+ since: Filter.gt<string | undefined>('2020'),
177
+ })
93
178
  .target();
94
179
 
95
180
  const plan = planner.createPlan(withSpaceIdOptions(query.ast));
@@ -98,15 +183,17 @@ describe('QueryPlanner', () => {
98
183
  "steps": [
99
184
  {
100
185
  "_tag": "SelectStep",
186
+ "scope": {
187
+ "spaceIds": [
188
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
189
+ ],
190
+ },
101
191
  "selector": {
102
192
  "_tag": "IdSelector",
103
193
  "objectIds": [
104
194
  "01JVS9YYT5VMVJW0GGTM1YHCCH",
105
195
  ],
106
196
  },
107
- "spaces": [
108
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
109
- ],
110
197
  },
111
198
  {
112
199
  "_tag": "FilterDeletedStep",
@@ -118,7 +205,7 @@ describe('QueryPlanner', () => {
118
205
  "id": undefined,
119
206
  "props": {},
120
207
  "type": "object",
121
- "typename": "dxn:type:dxos.org/type/Person:0.1.0",
208
+ "typename": "dxn:type:com.example.type.person:0.1.0",
122
209
  },
123
210
  },
124
211
  {
@@ -144,7 +231,7 @@ describe('QueryPlanner', () => {
144
231
  },
145
232
  },
146
233
  "type": "object",
147
- "typename": "dxn:type:dxos.org/type/WorksFor:0.1.0",
234
+ "typename": "dxn:type:com.example.type.employed-by:0.1.0",
148
235
  },
149
236
  },
150
237
  {
@@ -158,6 +245,14 @@ describe('QueryPlanner', () => {
158
245
  "_tag": "FilterDeletedStep",
159
246
  "mode": "only-non-deleted",
160
247
  },
248
+ {
249
+ "_tag": "OrderStep",
250
+ "order": [
251
+ {
252
+ "kind": "natural",
253
+ },
254
+ ],
255
+ },
161
256
  ],
162
257
  }
163
258
  `);
@@ -175,15 +270,17 @@ describe('QueryPlanner', () => {
175
270
  "steps": [
176
271
  {
177
272
  "_tag": "SelectStep",
273
+ "scope": {
274
+ "spaceIds": [
275
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
276
+ ],
277
+ },
178
278
  "selector": {
179
279
  "_tag": "IdSelector",
180
280
  "objectIds": [
181
281
  "01JVS9YYT7H6A6DXRN56RSHT6Z",
182
282
  ],
183
283
  },
184
- "spaces": [
185
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
186
- ],
187
284
  },
188
285
  {
189
286
  "_tag": "FilterDeletedStep",
@@ -195,7 +292,7 @@ describe('QueryPlanner', () => {
195
292
  "id": undefined,
196
293
  "props": {},
197
294
  "type": "object",
198
- "typename": "dxn:type:dxos.org/type/Person:0.1.0",
295
+ "typename": "dxn:type:com.example.type.person:0.1.0",
199
296
  },
200
297
  },
201
298
  {
@@ -215,9 +312,17 @@ describe('QueryPlanner', () => {
215
312
  "filter": {
216
313
  "props": {},
217
314
  "type": "object",
218
- "typename": "dxn:type:dxos.org/type/Task:0.1.0",
315
+ "typename": "dxn:type:com.example.type.task:0.1.0",
219
316
  },
220
317
  },
318
+ {
319
+ "_tag": "OrderStep",
320
+ "order": [
321
+ {
322
+ "kind": "natural",
323
+ },
324
+ ],
325
+ },
221
326
  ],
222
327
  }
223
328
  `);
@@ -225,7 +330,7 @@ describe('QueryPlanner', () => {
225
330
 
226
331
  test('get all tasks for employees of Cyberdyne', () => {
227
332
  const query = Query.select(Filter.type(TestSchema.Organization, { name: 'Cyberdyne' }))
228
- .targetOf(TestSchema.WorksFor)
333
+ .targetOf(TestSchema.EmployedBy)
229
334
  .source()
230
335
  .referencedBy(TestSchema.Task, 'assignee');
231
336
 
@@ -235,16 +340,18 @@ describe('QueryPlanner', () => {
235
340
  "steps": [
236
341
  {
237
342
  "_tag": "SelectStep",
343
+ "scope": {
344
+ "spaceIds": [
345
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
346
+ ],
347
+ },
238
348
  "selector": {
239
349
  "_tag": "TypeSelector",
240
350
  "inverted": false,
241
351
  "typename": [
242
- "dxn:type:dxos.org/type/Organization:0.1.0",
352
+ "dxn:type:com.example.type.organization:0.1.0",
243
353
  ],
244
354
  },
245
- "spaces": [
246
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
247
- ],
248
355
  },
249
356
  {
250
357
  "_tag": "FilterDeletedStep",
@@ -262,7 +369,7 @@ describe('QueryPlanner', () => {
262
369
  },
263
370
  },
264
371
  "type": "object",
265
- "typename": null,
372
+ "typename": "dxn:type:com.example.type.organization:0.1.0",
266
373
  },
267
374
  },
268
375
  {
@@ -282,7 +389,7 @@ describe('QueryPlanner', () => {
282
389
  "id": undefined,
283
390
  "props": {},
284
391
  "type": "object",
285
- "typename": "dxn:type:dxos.org/type/WorksFor:0.1.0",
392
+ "typename": "dxn:type:com.example.type.employed-by:0.1.0",
286
393
  },
287
394
  },
288
395
  {
@@ -313,9 +420,17 @@ describe('QueryPlanner', () => {
313
420
  "filter": {
314
421
  "props": {},
315
422
  "type": "object",
316
- "typename": "dxn:type:dxos.org/type/Task:0.1.0",
423
+ "typename": "dxn:type:com.example.type.task:0.1.0",
317
424
  },
318
425
  },
426
+ {
427
+ "_tag": "OrderStep",
428
+ "order": [
429
+ {
430
+ "kind": "natural",
431
+ },
432
+ ],
433
+ },
319
434
  ],
320
435
  }
321
436
  `);
@@ -338,46 +453,92 @@ describe('QueryPlanner', () => {
338
453
  "steps": [
339
454
  {
340
455
  "_tag": "SelectStep",
456
+ "scope": {
457
+ "spaceIds": [
458
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
459
+ ],
460
+ },
341
461
  "selector": {
342
462
  "_tag": "TypeSelector",
343
463
  "inverted": false,
344
464
  "typename": [
345
- "dxn:type:dxos.org/type/Person:0.1.0",
465
+ "dxn:type:com.example.type.person:0.1.0",
346
466
  ],
347
467
  },
348
- "spaces": [
349
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
350
- ],
351
468
  },
352
469
  {
353
470
  "_tag": "FilterDeletedStep",
354
471
  "mode": "only-non-deleted",
355
472
  },
473
+ {
474
+ "_tag": "FilterStep",
475
+ "filter": {
476
+ "id": undefined,
477
+ "props": {},
478
+ "type": "object",
479
+ "typename": "dxn:type:com.example.type.person:0.1.0",
480
+ },
481
+ },
482
+ {
483
+ "_tag": "OrderStep",
484
+ "order": [
485
+ {
486
+ "kind": "natural",
487
+ },
488
+ ],
489
+ },
356
490
  ],
357
491
  },
358
492
  {
359
493
  "steps": [
360
494
  {
361
495
  "_tag": "SelectStep",
496
+ "scope": {
497
+ "spaceIds": [
498
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
499
+ ],
500
+ },
362
501
  "selector": {
363
502
  "_tag": "TypeSelector",
364
503
  "inverted": false,
365
504
  "typename": [
366
- "dxn:type:dxos.org/type/Organization:0.1.0",
505
+ "dxn:type:com.example.type.organization:0.1.0",
367
506
  ],
368
507
  },
369
- "spaces": [
370
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
371
- ],
372
508
  },
373
509
  {
374
510
  "_tag": "FilterDeletedStep",
375
511
  "mode": "only-non-deleted",
376
512
  },
513
+ {
514
+ "_tag": "FilterStep",
515
+ "filter": {
516
+ "id": undefined,
517
+ "props": {},
518
+ "type": "object",
519
+ "typename": "dxn:type:com.example.type.organization:0.1.0",
520
+ },
521
+ },
522
+ {
523
+ "_tag": "OrderStep",
524
+ "order": [
525
+ {
526
+ "kind": "natural",
527
+ },
528
+ ],
529
+ },
377
530
  ],
378
531
  },
379
532
  ],
380
533
  },
534
+ {
535
+ "_tag": "OrderStep",
536
+ "order": [
537
+ {
538
+ "kind": "natural",
539
+ },
540
+ ],
541
+ },
381
542
  ],
382
543
  }
383
544
  `);
@@ -386,7 +547,7 @@ describe('QueryPlanner', () => {
386
547
  test('get all people not in orgs', () => {
387
548
  const query = Query.without(
388
549
  Query.select(Filter.type(TestSchema.Person)),
389
- Query.select(Filter.type(TestSchema.Person)).sourceOf(TestSchema.WorksFor).source(),
550
+ Query.select(Filter.type(TestSchema.Person)).sourceOf(TestSchema.EmployedBy).source(),
390
551
  );
391
552
 
392
553
  const plan = planner.createPlan(withSpaceIdOptions(query.ast));
@@ -399,16 +560,18 @@ describe('QueryPlanner', () => {
399
560
  "steps": [
400
561
  {
401
562
  "_tag": "SelectStep",
563
+ "scope": {
564
+ "spaceIds": [
565
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
566
+ ],
567
+ },
402
568
  "selector": {
403
569
  "_tag": "TypeSelector",
404
570
  "inverted": false,
405
571
  "typename": [
406
- "dxn:type:dxos.org/type/Person:0.1.0",
572
+ "dxn:type:com.example.type.person:0.1.0",
407
573
  ],
408
574
  },
409
- "spaces": [
410
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
411
- ],
412
575
  },
413
576
  {
414
577
  "_tag": "FilterDeletedStep",
@@ -420,7 +583,7 @@ describe('QueryPlanner', () => {
420
583
  "id": undefined,
421
584
  "props": {},
422
585
  "type": "object",
423
- "typename": null,
586
+ "typename": "dxn:type:com.example.type.person:0.1.0",
424
587
  },
425
588
  },
426
589
  {
@@ -440,7 +603,7 @@ describe('QueryPlanner', () => {
440
603
  "id": undefined,
441
604
  "props": {},
442
605
  "type": "object",
443
- "typename": "dxn:type:dxos.org/type/WorksFor:0.1.0",
606
+ "typename": "dxn:type:com.example.type.employed-by:0.1.0",
444
607
  },
445
608
  },
446
609
  {
@@ -454,22 +617,32 @@ describe('QueryPlanner', () => {
454
617
  "_tag": "FilterDeletedStep",
455
618
  "mode": "only-non-deleted",
456
619
  },
620
+ {
621
+ "_tag": "OrderStep",
622
+ "order": [
623
+ {
624
+ "kind": "natural",
625
+ },
626
+ ],
627
+ },
457
628
  ],
458
629
  },
459
630
  "source": {
460
631
  "steps": [
461
632
  {
462
633
  "_tag": "SelectStep",
634
+ "scope": {
635
+ "spaceIds": [
636
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
637
+ ],
638
+ },
463
639
  "selector": {
464
640
  "_tag": "TypeSelector",
465
641
  "inverted": false,
466
642
  "typename": [
467
- "dxn:type:dxos.org/type/Person:0.1.0",
643
+ "dxn:type:com.example.type.person:0.1.0",
468
644
  ],
469
645
  },
470
- "spaces": [
471
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
472
- ],
473
646
  },
474
647
  {
475
648
  "_tag": "FilterDeletedStep",
@@ -481,19 +654,39 @@ describe('QueryPlanner', () => {
481
654
  "id": undefined,
482
655
  "props": {},
483
656
  "type": "object",
484
- "typename": null,
657
+ "typename": "dxn:type:com.example.type.person:0.1.0",
485
658
  },
486
659
  },
660
+ {
661
+ "_tag": "OrderStep",
662
+ "order": [
663
+ {
664
+ "kind": "natural",
665
+ },
666
+ ],
667
+ },
487
668
  ],
488
669
  },
489
670
  },
671
+ {
672
+ "_tag": "OrderStep",
673
+ "order": [
674
+ {
675
+ "kind": "natural",
676
+ },
677
+ ],
678
+ },
490
679
  ],
491
680
  }
492
681
  `);
493
682
  });
494
683
 
495
684
  test('get assignees of all tasks created after 2020', () => {
496
- const query = Query.select(Filter.type(TestSchema.Task, { createdAt: Filter.gt('2020') })).reference('assignee');
685
+ const query = Query.select(
686
+ Filter.type(TestSchema.Task, {
687
+ deadline: Filter.gt<string | undefined>('2020'),
688
+ }),
689
+ ).reference('assignee');
497
690
 
498
691
  const plan = planner.createPlan(withSpaceIdOptions(query.ast));
499
692
  expect(plan).toMatchInlineSnapshot(`
@@ -501,16 +694,18 @@ describe('QueryPlanner', () => {
501
694
  "steps": [
502
695
  {
503
696
  "_tag": "SelectStep",
697
+ "scope": {
698
+ "spaceIds": [
699
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
700
+ ],
701
+ },
504
702
  "selector": {
505
703
  "_tag": "TypeSelector",
506
704
  "inverted": false,
507
705
  "typename": [
508
- "dxn:type:dxos.org/type/Task:0.1.0",
706
+ "dxn:type:com.example.type.task:0.1.0",
509
707
  ],
510
708
  },
511
- "spaces": [
512
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
513
- ],
514
709
  },
515
710
  {
516
711
  "_tag": "FilterDeletedStep",
@@ -521,14 +716,14 @@ describe('QueryPlanner', () => {
521
716
  "filter": {
522
717
  "id": undefined,
523
718
  "props": {
524
- "createdAt": {
719
+ "deadline": {
525
720
  "operator": "gt",
526
721
  "type": "compare",
527
722
  "value": "2020",
528
723
  },
529
724
  },
530
725
  "type": "object",
531
- "typename": null,
726
+ "typename": "dxn:type:com.example.type.task:0.1.0",
532
727
  },
533
728
  },
534
729
  {
@@ -543,6 +738,14 @@ describe('QueryPlanner', () => {
543
738
  "_tag": "FilterDeletedStep",
544
739
  "mode": "only-non-deleted",
545
740
  },
741
+ {
742
+ "_tag": "OrderStep",
743
+ "order": [
744
+ {
745
+ "kind": "natural",
746
+ },
747
+ ],
748
+ },
546
749
  ],
547
750
  }
548
751
  `);
@@ -557,14 +760,17 @@ describe('QueryPlanner', () => {
557
760
  "steps": [
558
761
  {
559
762
  "_tag": "SelectStep",
763
+ "scope": {
764
+ "spaceIds": [
765
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
766
+ ],
767
+ },
560
768
  "selector": {
561
769
  "_tag": "TextSelector",
562
770
  "searchKind": "full-text",
563
771
  "text": "Bill",
772
+ "typename": null,
564
773
  },
565
- "spaces": [
566
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
567
- ],
568
774
  },
569
775
  {
570
776
  "_tag": "FilterDeletedStep",
@@ -576,9 +782,17 @@ describe('QueryPlanner', () => {
576
782
  "id": undefined,
577
783
  "props": {},
578
784
  "type": "object",
579
- "typename": "dxn:type:dxos.org/type/Person:0.1.0",
785
+ "typename": "dxn:type:com.example.type.person:0.1.0",
580
786
  },
581
787
  },
788
+ {
789
+ "_tag": "OrderStep",
790
+ "order": [
791
+ {
792
+ "kind": "natural",
793
+ },
794
+ ],
795
+ },
582
796
  ],
583
797
  }
584
798
  `);
@@ -593,19 +807,30 @@ describe('QueryPlanner', () => {
593
807
  "steps": [
594
808
  {
595
809
  "_tag": "SelectStep",
810
+ "scope": {
811
+ "spaceIds": [
812
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
813
+ ],
814
+ },
596
815
  "selector": {
597
816
  "_tag": "TextSelector",
598
817
  "searchKind": "vector",
599
818
  "text": "Bill",
819
+ "typename": null,
600
820
  },
601
- "spaces": [
602
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
603
- ],
604
821
  },
605
822
  {
606
823
  "_tag": "FilterDeletedStep",
607
824
  "mode": "only-non-deleted",
608
825
  },
826
+ {
827
+ "_tag": "OrderStep",
828
+ "order": [
829
+ {
830
+ "kind": "natural",
831
+ },
832
+ ],
833
+ },
609
834
  ],
610
835
  }
611
836
  `);
@@ -620,22 +845,52 @@ describe('QueryPlanner', () => {
620
845
  "steps": [
621
846
  {
622
847
  "_tag": "SelectStep",
848
+ "scope": {
849
+ "spaceIds": [
850
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
851
+ ],
852
+ },
623
853
  "selector": {
624
854
  "_tag": "TypeSelector",
625
855
  "inverted": false,
626
856
  "typename": [
627
- "dxn:type:dxos.org/type/Organization:0.1.0",
628
- "dxn:type:dxos.org/type/Person:0.1.0",
857
+ "dxn:type:com.example.type.organization:0.1.0",
858
+ "dxn:type:com.example.type.person:0.1.0",
629
859
  ],
630
860
  },
631
- "spaces": [
632
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
633
- ],
634
861
  },
635
862
  {
636
863
  "_tag": "FilterDeletedStep",
637
864
  "mode": "only-non-deleted",
638
865
  },
866
+ {
867
+ "_tag": "FilterStep",
868
+ "filter": {
869
+ "filters": [
870
+ {
871
+ "id": undefined,
872
+ "props": {},
873
+ "type": "object",
874
+ "typename": "dxn:type:com.example.type.organization:0.1.0",
875
+ },
876
+ {
877
+ "id": undefined,
878
+ "props": {},
879
+ "type": "object",
880
+ "typename": "dxn:type:com.example.type.person:0.1.0",
881
+ },
882
+ ],
883
+ "type": "or",
884
+ },
885
+ },
886
+ {
887
+ "_tag": "OrderStep",
888
+ "order": [
889
+ {
890
+ "kind": "natural",
891
+ },
892
+ ],
893
+ },
639
894
  ],
640
895
  }
641
896
  `);
@@ -660,22 +915,52 @@ describe('QueryPlanner', () => {
660
915
  "steps": [
661
916
  {
662
917
  "_tag": "SelectStep",
918
+ "scope": {
919
+ "spaceIds": [
920
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
921
+ ],
922
+ },
663
923
  "selector": {
664
924
  "_tag": "TypeSelector",
665
925
  "inverted": true,
666
926
  "typename": [
667
- "dxn:type:dxos.org/type/Organization:0.1.0",
668
- "dxn:type:dxos.org/type/Person:0.1.0",
927
+ "dxn:type:com.example.type.organization:0.1.0",
928
+ "dxn:type:com.example.type.person:0.1.0",
669
929
  ],
670
930
  },
671
- "spaces": [
672
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
673
- ],
674
931
  },
675
932
  {
676
933
  "_tag": "FilterDeletedStep",
677
934
  "mode": "only-non-deleted",
678
935
  },
936
+ {
937
+ "_tag": "FilterStep",
938
+ "filter": {
939
+ "filters": [
940
+ {
941
+ "id": undefined,
942
+ "props": {},
943
+ "type": "object",
944
+ "typename": "dxn:type:com.example.type.organization:0.1.0",
945
+ },
946
+ {
947
+ "id": undefined,
948
+ "props": {},
949
+ "type": "object",
950
+ "typename": "dxn:type:com.example.type.person:0.1.0",
951
+ },
952
+ ],
953
+ "type": "or",
954
+ },
955
+ },
956
+ {
957
+ "_tag": "OrderStep",
958
+ "order": [
959
+ {
960
+ "kind": "natural",
961
+ },
962
+ ],
963
+ },
679
964
  ],
680
965
  }
681
966
  `);
@@ -690,33 +975,660 @@ describe('QueryPlanner', () => {
690
975
  "steps": [
691
976
  {
692
977
  "_tag": "SelectStep",
978
+ "scope": {
979
+ "spaceIds": [
980
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
981
+ ],
982
+ },
693
983
  "selector": {
694
984
  "_tag": "TypeSelector",
695
985
  "inverted": false,
696
986
  "typename": [
697
- "dxn:type:dxos.org/type/Task:0.1.0",
987
+ "dxn:type:com.example.type.task:0.1.0",
698
988
  ],
699
989
  },
700
- "spaces": [
701
- "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
702
- ],
703
990
  },
704
991
  {
705
992
  "_tag": "FilterDeletedStep",
706
993
  "mode": "only-deleted",
707
994
  },
995
+ {
996
+ "_tag": "FilterStep",
997
+ "filter": {
998
+ "id": undefined,
999
+ "props": {},
1000
+ "type": "object",
1001
+ "typename": "dxn:type:com.example.type.task:0.1.0",
1002
+ },
1003
+ },
1004
+ {
1005
+ "_tag": "OrderStep",
1006
+ "order": [
1007
+ {
1008
+ "kind": "natural",
1009
+ },
1010
+ ],
1011
+ },
1012
+ ],
1013
+ }
1014
+ `);
1015
+ });
1016
+
1017
+ test('select items from a specific queue', () => {
1018
+ const query = Query.select(Filter.type(TestSchema.Task)).from({ queues: [QUEUE_DXN] });
1019
+
1020
+ const plan = planner.createPlan(query.ast);
1021
+ expect(plan).toMatchInlineSnapshot(`
1022
+ {
1023
+ "steps": [
1024
+ {
1025
+ "_tag": "SelectStep",
1026
+ "scope": {
1027
+ "queues": [
1028
+ "dxn:queue:data:B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO:01JJRA86VK4H1TEB6QQVSWXP0E",
1029
+ ],
1030
+ },
1031
+ "selector": {
1032
+ "_tag": "TypeSelector",
1033
+ "inverted": false,
1034
+ "typename": [
1035
+ "dxn:type:com.example.type.task:0.1.0",
1036
+ ],
1037
+ },
1038
+ },
1039
+ {
1040
+ "_tag": "FilterDeletedStep",
1041
+ "mode": "only-non-deleted",
1042
+ },
1043
+ {
1044
+ "_tag": "FilterStep",
1045
+ "filter": {
1046
+ "id": undefined,
1047
+ "props": {},
1048
+ "type": "object",
1049
+ "typename": "dxn:type:com.example.type.task:0.1.0",
1050
+ },
1051
+ },
1052
+ {
1053
+ "_tag": "OrderStep",
1054
+ "order": [
1055
+ {
1056
+ "kind": "natural",
1057
+ },
1058
+ ],
1059
+ },
708
1060
  ],
709
1061
  }
710
1062
  `);
711
1063
  });
1064
+
1065
+ test('select items from all queues in a space', () => {
1066
+ const query = Query.select(Filter.type(TestSchema.Task)).from({
1067
+ spaceIds: [SPACE_ID],
1068
+ allQueuesFromSpaces: true,
1069
+ });
1070
+
1071
+ const plan = planner.createPlan(query.ast);
1072
+ expect(plan).toMatchInlineSnapshot(`
1073
+ {
1074
+ "steps": [
1075
+ {
1076
+ "_tag": "SelectStep",
1077
+ "scope": {
1078
+ "allQueuesFromSpaces": true,
1079
+ "spaceIds": [
1080
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
1081
+ ],
1082
+ },
1083
+ "selector": {
1084
+ "_tag": "TypeSelector",
1085
+ "inverted": false,
1086
+ "typename": [
1087
+ "dxn:type:com.example.type.task:0.1.0",
1088
+ ],
1089
+ },
1090
+ },
1091
+ {
1092
+ "_tag": "FilterDeletedStep",
1093
+ "mode": "only-non-deleted",
1094
+ },
1095
+ {
1096
+ "_tag": "FilterStep",
1097
+ "filter": {
1098
+ "id": undefined,
1099
+ "props": {},
1100
+ "type": "object",
1101
+ "typename": "dxn:type:com.example.type.task:0.1.0",
1102
+ },
1103
+ },
1104
+ {
1105
+ "_tag": "OrderStep",
1106
+ "order": [
1107
+ {
1108
+ "kind": "natural",
1109
+ },
1110
+ ],
1111
+ },
1112
+ ],
1113
+ }
1114
+ `);
1115
+ });
1116
+
1117
+ test('limit results', () => {
1118
+ const query = Query.select(Filter.type(TestSchema.Task)).limit(10);
1119
+
1120
+ const plan = planner.createPlan(withSpaceIdOptions(query.ast));
1121
+ expect(plan).toMatchInlineSnapshot(`
1122
+ {
1123
+ "steps": [
1124
+ {
1125
+ "_tag": "SelectStep",
1126
+ "limit": 10,
1127
+ "scope": {
1128
+ "spaceIds": [
1129
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
1130
+ ],
1131
+ },
1132
+ "selector": {
1133
+ "_tag": "TypeSelector",
1134
+ "inverted": false,
1135
+ "typename": [
1136
+ "dxn:type:com.example.type.task:0.1.0",
1137
+ ],
1138
+ },
1139
+ },
1140
+ {
1141
+ "_tag": "FilterDeletedStep",
1142
+ "mode": "only-non-deleted",
1143
+ },
1144
+ {
1145
+ "_tag": "FilterStep",
1146
+ "filter": {
1147
+ "id": undefined,
1148
+ "props": {},
1149
+ "type": "object",
1150
+ "typename": "dxn:type:com.example.type.task:0.1.0",
1151
+ },
1152
+ },
1153
+ {
1154
+ "_tag": "OrderStep",
1155
+ "limit": 10,
1156
+ "order": [
1157
+ {
1158
+ "kind": "natural",
1159
+ },
1160
+ ],
1161
+ },
1162
+ ],
1163
+ }
1164
+ `);
1165
+ });
1166
+
1167
+ test('ordered and limited results', () => {
1168
+ const query = Query.select(Filter.type(TestSchema.Task)).orderBy(Order.property('title', 'asc')).limit(10);
1169
+
1170
+ const plan = planner.createPlan(withSpaceIdOptions(query.ast));
1171
+ expect(plan).toMatchInlineSnapshot(`
1172
+ {
1173
+ "steps": [
1174
+ {
1175
+ "_tag": "SelectStep",
1176
+ "limit": 10,
1177
+ "scope": {
1178
+ "spaceIds": [
1179
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
1180
+ ],
1181
+ },
1182
+ "selector": {
1183
+ "_tag": "TypeSelector",
1184
+ "inverted": false,
1185
+ "typename": [
1186
+ "dxn:type:com.example.type.task:0.1.0",
1187
+ ],
1188
+ },
1189
+ },
1190
+ {
1191
+ "_tag": "FilterDeletedStep",
1192
+ "mode": "only-non-deleted",
1193
+ },
1194
+ {
1195
+ "_tag": "FilterStep",
1196
+ "filter": {
1197
+ "id": undefined,
1198
+ "props": {},
1199
+ "type": "object",
1200
+ "typename": "dxn:type:com.example.type.task:0.1.0",
1201
+ },
1202
+ },
1203
+ {
1204
+ "_tag": "OrderStep",
1205
+ "limit": 10,
1206
+ "order": [
1207
+ {
1208
+ "direction": "asc",
1209
+ "kind": "property",
1210
+ "property": "title",
1211
+ },
1212
+ ],
1213
+ },
1214
+ ],
1215
+ }
1216
+ `);
1217
+ });
1218
+
1219
+ test('union of limited queries', () => {
1220
+ const query = Query.all(
1221
+ Query.select(Filter.type(TestSchema.Person)).limit(5),
1222
+ Query.select(Filter.type(TestSchema.Organization)).limit(5),
1223
+ );
1224
+
1225
+ const plan = planner.createPlan(withSpaceIdOptions(query.ast));
1226
+ expect(plan).toMatchInlineSnapshot(`
1227
+ {
1228
+ "steps": [
1229
+ {
1230
+ "_tag": "UnionStep",
1231
+ "plans": [
1232
+ {
1233
+ "steps": [
1234
+ {
1235
+ "_tag": "SelectStep",
1236
+ "limit": 5,
1237
+ "scope": {
1238
+ "spaceIds": [
1239
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
1240
+ ],
1241
+ },
1242
+ "selector": {
1243
+ "_tag": "TypeSelector",
1244
+ "inverted": false,
1245
+ "typename": [
1246
+ "dxn:type:com.example.type.person:0.1.0",
1247
+ ],
1248
+ },
1249
+ },
1250
+ {
1251
+ "_tag": "FilterDeletedStep",
1252
+ "mode": "only-non-deleted",
1253
+ },
1254
+ {
1255
+ "_tag": "FilterStep",
1256
+ "filter": {
1257
+ "id": undefined,
1258
+ "props": {},
1259
+ "type": "object",
1260
+ "typename": "dxn:type:com.example.type.person:0.1.0",
1261
+ },
1262
+ },
1263
+ {
1264
+ "_tag": "OrderStep",
1265
+ "limit": 5,
1266
+ "order": [
1267
+ {
1268
+ "kind": "natural",
1269
+ },
1270
+ ],
1271
+ },
1272
+ ],
1273
+ },
1274
+ {
1275
+ "steps": [
1276
+ {
1277
+ "_tag": "SelectStep",
1278
+ "limit": 5,
1279
+ "scope": {
1280
+ "spaceIds": [
1281
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
1282
+ ],
1283
+ },
1284
+ "selector": {
1285
+ "_tag": "TypeSelector",
1286
+ "inverted": false,
1287
+ "typename": [
1288
+ "dxn:type:com.example.type.organization:0.1.0",
1289
+ ],
1290
+ },
1291
+ },
1292
+ {
1293
+ "_tag": "FilterDeletedStep",
1294
+ "mode": "only-non-deleted",
1295
+ },
1296
+ {
1297
+ "_tag": "FilterStep",
1298
+ "filter": {
1299
+ "id": undefined,
1300
+ "props": {},
1301
+ "type": "object",
1302
+ "typename": "dxn:type:com.example.type.organization:0.1.0",
1303
+ },
1304
+ },
1305
+ {
1306
+ "_tag": "OrderStep",
1307
+ "limit": 5,
1308
+ "order": [
1309
+ {
1310
+ "kind": "natural",
1311
+ },
1312
+ ],
1313
+ },
1314
+ ],
1315
+ },
1316
+ ],
1317
+ },
1318
+ {
1319
+ "_tag": "OrderStep",
1320
+ "order": [
1321
+ {
1322
+ "kind": "natural",
1323
+ },
1324
+ ],
1325
+ },
1326
+ ],
1327
+ }
1328
+ `);
1329
+ });
1330
+ test('throws when query has no from clause', () => {
1331
+ const query = Query.select(Filter.type(TestSchema.Person));
1332
+ expect(() => planner.createPlan(query.ast)).toThrow('Query must be scoped with a from() clause');
1333
+ });
1334
+
1335
+ test('from all accessible spaces', () => {
1336
+ const query = Query.select(Filter.type(TestSchema.Person)).from('all-accessible-spaces');
1337
+
1338
+ const plan = planner.createPlan(query.ast);
1339
+ expect(plan).toMatchInlineSnapshot(`
1340
+ {
1341
+ "steps": [
1342
+ {
1343
+ "_tag": "SelectStep",
1344
+ "scope": {},
1345
+ "selector": {
1346
+ "_tag": "TypeSelector",
1347
+ "inverted": false,
1348
+ "typename": [
1349
+ "dxn:type:com.example.type.person:0.1.0",
1350
+ ],
1351
+ },
1352
+ },
1353
+ {
1354
+ "_tag": "FilterDeletedStep",
1355
+ "mode": "only-non-deleted",
1356
+ },
1357
+ {
1358
+ "_tag": "FilterStep",
1359
+ "filter": {
1360
+ "id": undefined,
1361
+ "props": {},
1362
+ "type": "object",
1363
+ "typename": "dxn:type:com.example.type.person:0.1.0",
1364
+ },
1365
+ },
1366
+ {
1367
+ "_tag": "OrderStep",
1368
+ "order": [
1369
+ {
1370
+ "kind": "natural",
1371
+ },
1372
+ ],
1373
+ },
1374
+ ],
1375
+ }
1376
+ `);
1377
+ });
1378
+
1379
+ test('from all accessible spaces with feeds', () => {
1380
+ const query = Query.select(Filter.type(TestSchema.Person)).from('all-accessible-spaces', {
1381
+ includeFeeds: true,
1382
+ });
1383
+
1384
+ const plan = planner.createPlan(query.ast);
1385
+ expect(plan).toMatchInlineSnapshot(`
1386
+ {
1387
+ "steps": [
1388
+ {
1389
+ "_tag": "SelectStep",
1390
+ "scope": {
1391
+ "allQueuesFromSpaces": true,
1392
+ },
1393
+ "selector": {
1394
+ "_tag": "TypeSelector",
1395
+ "inverted": false,
1396
+ "typename": [
1397
+ "dxn:type:com.example.type.person:0.1.0",
1398
+ ],
1399
+ },
1400
+ },
1401
+ {
1402
+ "_tag": "FilterDeletedStep",
1403
+ "mode": "only-non-deleted",
1404
+ },
1405
+ {
1406
+ "_tag": "FilterStep",
1407
+ "filter": {
1408
+ "id": undefined,
1409
+ "props": {},
1410
+ "type": "object",
1411
+ "typename": "dxn:type:com.example.type.person:0.1.0",
1412
+ },
1413
+ },
1414
+ {
1415
+ "_tag": "OrderStep",
1416
+ "order": [
1417
+ {
1418
+ "kind": "natural",
1419
+ },
1420
+ ],
1421
+ },
1422
+ ],
1423
+ }
1424
+ `);
1425
+ });
1426
+
1427
+ test('from specific feed via queues scope', () => {
1428
+ const query = Query.select(Filter.type(TestSchema.Task)).from({ queues: [QUEUE_DXN] });
1429
+
1430
+ const plan = planner.createPlan(query.ast);
1431
+ expect(plan.steps[0]).toMatchObject({
1432
+ _tag: 'SelectStep',
1433
+ scope: { queues: [QUEUE_DXN] },
1434
+ });
1435
+ });
1436
+
1437
+ test('from specific space with feeds', () => {
1438
+ const query = Query.select(Filter.type(TestSchema.Person)).from({
1439
+ spaceIds: [SPACE_ID],
1440
+ allQueuesFromSpaces: true,
1441
+ });
1442
+
1443
+ const plan = planner.createPlan(query.ast);
1444
+ expect(plan.steps[0]).toMatchObject({
1445
+ _tag: 'SelectStep',
1446
+ scope: { spaceIds: [SPACE_ID], allQueuesFromSpaces: true },
1447
+ });
1448
+ });
1449
+
1450
+ test('from subquery flattens into filter on subquery results', () => {
1451
+ // Query.select(Filter.props({ name: 'Alice' })).from(Query.select(Filter.type(Person)))
1452
+ // Should flatten to: select type Person -> filter props { name: 'Alice' }.
1453
+ const subquery = Query.select(Filter.type(TestSchema.Person)).from({ spaceIds: [SPACE_ID] });
1454
+ const query = Query.select(Filter.props<TestSchema.Person>({ name: 'Alice' })).from(subquery);
1455
+
1456
+ const plan = planner.createPlan(query.ast);
1457
+ expect(plan).toMatchInlineSnapshot(`
1458
+ {
1459
+ "steps": [
1460
+ {
1461
+ "_tag": "SelectStep",
1462
+ "scope": {
1463
+ "spaceIds": [
1464
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
1465
+ ],
1466
+ },
1467
+ "selector": {
1468
+ "_tag": "TypeSelector",
1469
+ "inverted": false,
1470
+ "typename": [
1471
+ "dxn:type:com.example.type.person:0.1.0",
1472
+ ],
1473
+ },
1474
+ },
1475
+ {
1476
+ "_tag": "FilterDeletedStep",
1477
+ "mode": "only-non-deleted",
1478
+ },
1479
+ {
1480
+ "_tag": "FilterStep",
1481
+ "filter": {
1482
+ "id": undefined,
1483
+ "props": {},
1484
+ "type": "object",
1485
+ "typename": "dxn:type:com.example.type.person:0.1.0",
1486
+ },
1487
+ },
1488
+ {
1489
+ "_tag": "FilterStep",
1490
+ "filter": {
1491
+ "id": undefined,
1492
+ "props": {
1493
+ "name": {
1494
+ "operator": "eq",
1495
+ "type": "compare",
1496
+ "value": "Alice",
1497
+ },
1498
+ },
1499
+ "type": "object",
1500
+ "typename": null,
1501
+ },
1502
+ },
1503
+ {
1504
+ "_tag": "OrderStep",
1505
+ "order": [
1506
+ {
1507
+ "kind": "natural",
1508
+ },
1509
+ ],
1510
+ },
1511
+ ],
1512
+ }
1513
+ `);
1514
+ });
1515
+
1516
+ test('from subquery with reference traversal', () => {
1517
+ // Query.select(Filter.type(Task)).reference('assignee').from(subquery)
1518
+ // The reference traversal wraps the outer select; flattening should still work.
1519
+ const subquery = Query.select(Filter.type(TestSchema.Person)).from({ spaceIds: [SPACE_ID] });
1520
+ const query = Query.select(Filter.type(TestSchema.Task)).reference('assignee').from(subquery);
1521
+
1522
+ const plan = planner.createPlan(query.ast);
1523
+ expect(plan).toMatchInlineSnapshot(`
1524
+ {
1525
+ "steps": [
1526
+ {
1527
+ "_tag": "SelectStep",
1528
+ "scope": {
1529
+ "spaceIds": [
1530
+ "B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO",
1531
+ ],
1532
+ },
1533
+ "selector": {
1534
+ "_tag": "TypeSelector",
1535
+ "inverted": false,
1536
+ "typename": [
1537
+ "dxn:type:com.example.type.person:0.1.0",
1538
+ ],
1539
+ },
1540
+ },
1541
+ {
1542
+ "_tag": "FilterDeletedStep",
1543
+ "mode": "only-non-deleted",
1544
+ },
1545
+ {
1546
+ "_tag": "FilterStep",
1547
+ "filter": {
1548
+ "id": undefined,
1549
+ "props": {},
1550
+ "type": "object",
1551
+ "typename": "dxn:type:com.example.type.person:0.1.0",
1552
+ },
1553
+ },
1554
+ {
1555
+ "_tag": "FilterStep",
1556
+ "filter": {
1557
+ "id": undefined,
1558
+ "props": {},
1559
+ "type": "object",
1560
+ "typename": "dxn:type:com.example.type.task:0.1.0",
1561
+ },
1562
+ },
1563
+ {
1564
+ "_tag": "TraverseStep",
1565
+ "traversal": {
1566
+ "_tag": "ReferenceTraversal",
1567
+ "direction": "outgoing",
1568
+ "property": "assignee",
1569
+ },
1570
+ },
1571
+ {
1572
+ "_tag": "FilterDeletedStep",
1573
+ "mode": "only-non-deleted",
1574
+ },
1575
+ {
1576
+ "_tag": "OrderStep",
1577
+ "order": [
1578
+ {
1579
+ "kind": "natural",
1580
+ },
1581
+ ],
1582
+ },
1583
+ ],
1584
+ }
1585
+ `);
1586
+ });
1587
+
1588
+ test('from subquery inherits scope from inner query', () => {
1589
+ // The outer query has no scope — the subquery carries the scope.
1590
+ const subquery = Query.select(Filter.type(TestSchema.Task)).from({ spaceIds: [SPACE_ID] });
1591
+ const query = Query.select(Filter.props<TestSchema.Task>({ title: 'Test' })).from(subquery);
1592
+
1593
+ const plan = planner.createPlan(query.ast);
1594
+ const selectStep = plan.steps.find((step) => step._tag === 'SelectStep');
1595
+ expect(selectStep).toMatchObject({
1596
+ _tag: 'SelectStep',
1597
+ scope: { spaceIds: [SPACE_ID] },
1598
+ });
1599
+ });
1600
+
1601
+ test('and(type, compare, timestamp) throws descriptive error about timestamp limitation', () => {
1602
+ const query = Query.select(
1603
+ Filter.and(
1604
+ Filter.type(TestSchema.Person),
1605
+ Filter.type(TestSchema.Person, { name: 'Alice' }),
1606
+ Filter.updated({ after: Date.now() }),
1607
+ ),
1608
+ );
1609
+ expect(() => planner.createPlan(withSpaceIdOptions(query.ast))).toThrow(/[Tt]imestamp/);
1610
+ });
1611
+
1612
+ test('and(type, timestamp) produces valid plan', () => {
1613
+ const query = Query.select(Filter.and(Filter.type(TestSchema.Person), Filter.updated({ after: Date.now() })));
1614
+ const plan = planner.createPlan(withSpaceIdOptions(query.ast));
1615
+ const hasTimestampFilter = plan.steps.some(
1616
+ (step) => step._tag === 'FilterStep' && JSON.stringify(step.filter).includes('timestamp'),
1617
+ );
1618
+ expect(hasTimestampFilter).toBe(true);
1619
+ });
712
1620
  });
713
1621
 
714
1622
  const SPACE_ID = SpaceId.make('B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO'); // Stable id for inline snapshots.
1623
+ const QUEUE_DXN = DXN.parse('dxn:queue:data:B2NJDFNVZIW77OQSXUBNAD7BUMBD3G5PO:01JJRA86VK4H1TEB6QQVSWXP0E').toString(); // Stable queue DXN for inline snapshots.
715
1624
 
716
1625
  const withSpaceIdOptions = (query: QueryAST.Query): QueryAST.Query => ({
717
- type: 'options',
1626
+ type: 'from',
718
1627
  query,
719
- options: {
720
- spaceIds: [SPACE_ID],
1628
+ from: {
1629
+ _tag: 'scope',
1630
+ scope: {
1631
+ spaceIds: [SPACE_ID],
1632
+ },
721
1633
  },
722
1634
  });