@dxos/echo 0.8.4-main.8360d9e660 → 0.8.4-main.8baae0fced
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.
- package/LICENSE +102 -5
- package/README.md +3 -3
- package/dist/lib/neutral/Annotation.mjs +5 -3
- package/dist/lib/neutral/Database.mjs +8 -4
- package/dist/lib/neutral/Entity.mjs +16 -14
- package/dist/lib/neutral/Err.mjs +1 -1
- package/dist/lib/neutral/Extension.mjs +18 -0
- package/dist/lib/neutral/Extension.mjs.map +7 -0
- package/dist/lib/neutral/Feed.mjs +23 -18
- package/dist/lib/neutral/Filter.mjs +23 -13
- package/dist/lib/neutral/Format.mjs +3 -3
- package/dist/lib/neutral/JsonSchema.mjs +8 -8
- package/dist/lib/neutral/Key.mjs +1 -1
- package/dist/lib/neutral/Migration.mjs +17 -0
- package/dist/lib/neutral/Migration.mjs.map +7 -0
- package/dist/lib/neutral/Obj.mjs +16 -13
- package/dist/lib/neutral/Order.mjs +1 -1
- package/dist/lib/neutral/Query.mjs +19 -17
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +9 -7
- package/dist/lib/neutral/Relation.mjs +15 -14
- package/dist/lib/neutral/SchemaRegistry.mjs +1 -1
- package/dist/lib/neutral/Tag.mjs +14 -13
- package/dist/lib/neutral/Type.mjs +10 -10
- package/dist/lib/neutral/{chunk-FZO7LQO7.mjs → chunk-44HT3MEC.mjs} +2 -2
- package/dist/lib/neutral/{chunk-ROAGDPV7.mjs → chunk-4A2GS5LQ.mjs} +12 -8
- package/dist/lib/neutral/chunk-4A2GS5LQ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-OENWMTE6.mjs → chunk-5SL5LDLD.mjs} +4 -2
- package/dist/lib/neutral/chunk-5SL5LDLD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7RVZT53K.mjs} +1 -1
- package/dist/lib/neutral/{chunk-YWXWXIE5.mjs → chunk-APHSOTIX.mjs} +2 -2
- package/dist/lib/neutral/{chunk-YWXWXIE5.mjs.map → chunk-APHSOTIX.mjs.map} +2 -2
- package/dist/lib/neutral/{chunk-6DNYDXCV.mjs → chunk-B2P7IVG3.mjs} +61 -14
- package/dist/lib/neutral/chunk-B2P7IVG3.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BNCCGLJN.mjs → chunk-BICZKPQG.mjs} +1 -1
- package/dist/lib/neutral/{chunk-43Y5DOS6.mjs → chunk-BMB7IHGB.mjs} +16 -66
- package/dist/lib/neutral/chunk-BMB7IHGB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-6K2MVI2O.mjs → chunk-BUBEC474.mjs} +4 -4
- package/dist/lib/neutral/{chunk-YMNSMKKW.mjs → chunk-C4PSESGN.mjs} +6 -22
- package/dist/lib/neutral/{chunk-YMNSMKKW.mjs.map → chunk-C4PSESGN.mjs.map} +3 -3
- package/dist/lib/neutral/chunk-FIWO2FZK.mjs +36 -0
- package/dist/lib/neutral/chunk-FIWO2FZK.mjs.map +7 -0
- package/dist/lib/neutral/chunk-GWFFC34K.mjs +50 -0
- package/dist/lib/neutral/chunk-GWFFC34K.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-NXMFBIT5.mjs → chunk-HKETO4L4.mjs} +72 -6
- package/dist/lib/neutral/chunk-HKETO4L4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-NEGC54NE.mjs → chunk-I2DARWPX.mjs} +17 -19
- package/dist/lib/neutral/chunk-I2DARWPX.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-7VNVH63N.mjs → chunk-IVSI7QO6.mjs} +50 -20
- package/dist/lib/neutral/chunk-IVSI7QO6.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BOZZPUXE.mjs → chunk-MLS7U7AT.mjs} +12 -65
- package/dist/lib/neutral/chunk-MLS7U7AT.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WYOKA6AE.mjs → chunk-N4B7FHQT.mjs} +2 -2
- package/dist/lib/neutral/{chunk-WYOKA6AE.mjs.map → chunk-N4B7FHQT.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-FXEG7EOK.mjs → chunk-N7VOEPSV.mjs} +6 -3
- package/dist/lib/neutral/{chunk-FXEG7EOK.mjs.map → chunk-N7VOEPSV.mjs.map} +3 -3
- package/dist/lib/neutral/{chunk-UTBRYVQC.mjs → chunk-QRZ2I3ZM.mjs} +2 -2
- package/dist/lib/neutral/{chunk-SEMVAGBM.mjs → chunk-TNBK56IN.mjs} +19 -24
- package/dist/lib/neutral/chunk-TNBK56IN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-B5OXLWZL.mjs → chunk-TRPZU2HV.mjs} +2 -2
- package/dist/lib/neutral/{chunk-UI6MWK5W.mjs → chunk-TTCSATUD.mjs} +1 -1
- package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-V72DY6LU.mjs} +1 -1
- package/dist/lib/neutral/{chunk-6GPU7XC3.mjs → chunk-VW42HESL.mjs} +54 -17
- package/dist/lib/neutral/chunk-VW42HESL.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-4JRI2ZJI.mjs → chunk-X3356HPV.mjs} +120 -12
- package/dist/lib/neutral/chunk-X3356HPV.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-W47JKR3X.mjs → chunk-XEXM5HWQ.mjs} +18 -46
- package/dist/lib/neutral/chunk-XEXM5HWQ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-C4JZK4J7.mjs → chunk-Z5GKP74O.mjs} +231 -479
- package/dist/lib/neutral/chunk-Z5GKP74O.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UBEZSGXY.mjs → chunk-ZISMEVKD.mjs} +1 -1
- package/dist/lib/neutral/{chunk-UBEZSGXY.mjs.map → chunk-ZISMEVKD.mjs.map} +2 -2
- package/dist/lib/neutral/index.mjs +38 -28
- package/dist/lib/neutral/internal/index.mjs +15 -9
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +185 -129
- package/dist/lib/neutral/testing/index.mjs.map +3 -3
- package/dist/types/src/Annotation.d.ts +1 -1
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Collection.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +14 -2
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +2 -1
- package/dist/types/src/Dataset.d.ts.map +1 -1
- package/dist/types/src/Entity.d.ts +17 -11
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +18 -18
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Extension.d.ts +80 -0
- package/dist/types/src/Extension.d.ts.map +1 -0
- package/dist/types/src/Extension.test.d.ts +2 -0
- package/dist/types/src/Extension.test.d.ts.map +1 -0
- package/dist/types/src/Feed.d.ts +62 -21
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +54 -4
- package/dist/types/src/Filter.d.ts.map +1 -1
- package/dist/types/src/Filter.test.d.ts +2 -0
- package/dist/types/src/Filter.test.d.ts.map +1 -0
- package/dist/types/src/Hypergraph.d.ts +3 -3
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/Json.d.ts +33 -0
- package/dist/types/src/Json.d.ts.map +1 -0
- package/dist/types/src/Json.test.d.ts +2 -0
- package/dist/types/src/Json.test.d.ts.map +1 -0
- package/dist/types/src/JsonSchema.d.ts +1 -1
- package/dist/types/src/Migration.d.ts +69 -0
- package/dist/types/src/Migration.d.ts.map +1 -0
- package/dist/types/src/Obj.d.ts +42 -28
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Order.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +13 -2
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +1 -0
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Relation.d.ts +17 -18
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Tag.d.ts +2 -2
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/Type.d.ts +3 -3
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +1 -1
- package/dist/types/src/View.d.ts.map +1 -1
- package/dist/types/src/exemplars.test.d.ts +2 -0
- package/dist/types/src/exemplars.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/annotations.d.ts +12 -2
- package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/util.d.ts +1 -1
- package/dist/types/src/internal/Annotation/util.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/model.d.ts +2 -0
- package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/version.d.ts.map +1 -1
- package/dist/types/src/internal/Format/date.d.ts.map +1 -1
- package/dist/types/src/internal/Format/format.d.ts.map +1 -1
- package/dist/types/src/internal/Format/number.d.ts.map +1 -1
- package/dist/types/src/internal/Format/object.d.ts.map +1 -1
- package/dist/types/src/internal/Format/types.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +28 -28
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/common.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/ids.d.ts +1 -1
- package/dist/types/src/internal/Obj/ids.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/json-serializer.d.ts +4 -3
- package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -1
- package/dist/types/src/internal/Query.d.ts +10 -0
- package/dist/types/src/internal/Query.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/ref-array.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/ref.d.ts +14 -1
- package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/Type/compose.d.ts.map +1 -1
- package/dist/types/src/internal/Type/echo-schema.d.ts +2 -2
- package/dist/types/src/internal/Type/echo-schema.d.ts.map +1 -1
- package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -1
- package/dist/types/src/internal/common/api/meta.d.ts +3 -3
- package/dist/types/src/internal/common/api/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive-array.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts +2 -0
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/base.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/entity.d.ts +4 -4
- package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/meta.d.ts +10 -0
- package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/version.d.ts +1 -1
- package/dist/types/src/internal/index.d.ts +1 -0
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-data.d.ts +8 -8
- package/dist/types/src/testing/test-data.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +53 -53
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/src/testing/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +25 -15
- package/src/Annotation.ts +1 -0
- package/src/Collection.ts +2 -2
- package/src/Database.ts +50 -15
- package/src/Entity.ts +18 -12
- package/src/Extension.test.ts +235 -0
- package/src/Extension.ts +122 -0
- package/src/Feed.ts +107 -34
- package/src/Filter.test.ts +90 -0
- package/src/Filter.ts +97 -3
- package/src/Hypergraph.ts +3 -3
- package/src/Json.test.ts +175 -0
- package/src/Json.ts +102 -0
- package/src/Migration.ts +106 -0
- package/src/Obj.test.ts +105 -13
- package/src/Obj.ts +154 -33
- package/src/Query.test.ts +199 -9
- package/src/Query.ts +58 -8
- package/src/Ref.ts +2 -0
- package/src/Relation.ts +24 -20
- package/src/Type.ts +1 -1
- package/src/View.ts +1 -1
- package/src/exemplars.test.ts +21 -0
- package/src/index.ts +4 -0
- package/src/internal/Annotation/annotations.test.ts +51 -2
- package/src/internal/Annotation/annotations.ts +33 -14
- package/src/internal/Annotation/sorting.ts +0 -1
- package/src/internal/Entity/api.ts +0 -1
- package/src/internal/Entity/model.ts +2 -0
- package/src/internal/Entity/object.ts +0 -1
- package/src/internal/Entity/version.ts +0 -1
- package/src/internal/Format/date.test.ts +0 -1
- package/src/internal/Format/format.test.ts +0 -1
- package/src/internal/JsonSchema/json-schema-type.ts +1 -1
- package/src/internal/JsonSchema/json-schema.test.ts +1 -2
- package/src/internal/JsonSchema/json-schema.ts +1 -2
- package/src/internal/Obj/clone.ts +1 -1
- package/src/internal/Obj/create-object.test.ts +2 -4
- package/src/internal/Obj/create-object.ts +2 -3
- package/src/internal/Obj/deleted.ts +1 -1
- package/src/internal/Obj/ids.ts +1 -1
- package/src/internal/Obj/json-serializer.test.ts +49 -5
- package/src/internal/Obj/json-serializer.ts +47 -25
- package/src/internal/Obj/set-value.test.ts +24 -24
- package/src/internal/Obj/set-value.ts +1 -1
- package/src/internal/Query.ts +156 -0
- package/src/internal/Ref/ref-array.ts +0 -1
- package/src/internal/Ref/ref.test.ts +0 -1
- package/src/internal/Ref/ref.ts +18 -1
- package/src/internal/Type/compose.test.ts +0 -1
- package/src/internal/Type/echo-schema.ts +3 -4
- package/src/internal/common/README.md +1 -1
- package/src/internal/common/api/meta.ts +3 -3
- package/src/internal/common/proxy/change-context.ts +1 -1
- package/src/internal/common/proxy/change.test.ts +94 -94
- package/src/internal/common/proxy/errors.ts +2 -2
- package/src/internal/common/proxy/handler.test.ts +0 -2
- package/src/internal/common/proxy/json-serializer.ts +4 -1
- package/src/internal/common/proxy/make-object.ts +0 -1
- package/src/internal/common/proxy/ownership.ts +0 -1
- package/src/internal/common/proxy/reactive-array.ts +1 -1
- package/src/internal/common/proxy/reactive.test.ts +54 -0
- package/src/internal/common/proxy/reactive.ts +11 -3
- package/src/internal/common/proxy/typed-handler.test.ts +0 -1
- package/src/internal/common/proxy/typed-handler.ts +8 -10
- package/src/internal/common/proxy/typed-object.test.ts +2 -3
- package/src/internal/common/types/entity.ts +1 -1
- package/src/internal/common/types/meta.ts +12 -1
- package/src/internal/index.ts +1 -0
- package/src/testing/api.test.ts +0 -1
- package/src/testing/test-data.ts +157 -98
- package/dist/lib/neutral/chunk-43Y5DOS6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-4JRI2ZJI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-6DNYDXCV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-6GPU7XC3.mjs.map +0 -7
- package/dist/lib/neutral/chunk-7VNVH63N.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BOZZPUXE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-C4JZK4J7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NEGC54NE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NXMFBIT5.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OENWMTE6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ROAGDPV7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SEMVAGBM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-W47JKR3X.mjs.map +0 -7
- /package/dist/lib/neutral/{chunk-FZO7LQO7.mjs.map → chunk-44HT3MEC.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-ANHVGJI4.mjs.map → chunk-7RVZT53K.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-BNCCGLJN.mjs.map → chunk-BICZKPQG.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-6K2MVI2O.mjs.map → chunk-BUBEC474.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-UTBRYVQC.mjs.map → chunk-QRZ2I3ZM.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-B5OXLWZL.mjs.map → chunk-TRPZU2HV.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-UI6MWK5W.mjs.map → chunk-TTCSATUD.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-OMUPQMLR.mjs.map → chunk-V72DY6LU.mjs.map} +0 -0
package/src/Feed.ts
CHANGED
|
@@ -12,6 +12,7 @@ import * as Schema from 'effect/Schema';
|
|
|
12
12
|
|
|
13
13
|
import { DXN } from '@dxos/keys';
|
|
14
14
|
|
|
15
|
+
import * as Annotation from './Annotation';
|
|
15
16
|
import type * as Entity from './Entity';
|
|
16
17
|
import type * as Filter from './Filter';
|
|
17
18
|
import * as internal from './internal';
|
|
@@ -19,7 +20,6 @@ import * as Obj from './Obj';
|
|
|
19
20
|
import type * as Query from './Query';
|
|
20
21
|
import type * as QueryResult from './QueryResult';
|
|
21
22
|
import * as Type from './Type';
|
|
22
|
-
import * as Annotation from './Annotation';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Runtime schema for a Feed object.
|
|
@@ -34,6 +34,14 @@ export const Feed = Schema.Struct({
|
|
|
34
34
|
name: Schema.String.pipe(Schema.optional),
|
|
35
35
|
/** Identifier for the feed's kind (e.g., plugin id). */
|
|
36
36
|
kind: Schema.String.pipe(internal.FormInputAnnotation.set(false), Schema.optional),
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Feed namespace.
|
|
40
|
+
* Controls how feed data is stored and replicated.
|
|
41
|
+
* - `data`: Data feed (default).
|
|
42
|
+
* - `trace`: Trace feed.
|
|
43
|
+
*/
|
|
44
|
+
namespace: Schema.optional(Schema.Literal('data', 'trace')),
|
|
37
45
|
}).pipe(
|
|
38
46
|
Type.object({
|
|
39
47
|
typename: 'org.dxos.type.feed',
|
|
@@ -55,12 +63,6 @@ export interface Feed extends Schema.Schema.Type<typeof Feed> {}
|
|
|
55
63
|
// Types
|
|
56
64
|
//
|
|
57
65
|
|
|
58
|
-
/**
|
|
59
|
-
* Meta key source for storing the backing DXN bound to a feed object.
|
|
60
|
-
*/
|
|
61
|
-
// TODO(dmaretskyi): Enforce that Feed ObjectId = feed storage ID. And remove this key.
|
|
62
|
-
export const DXN_KEY = 'org.dxos.key.feed';
|
|
63
|
-
|
|
64
66
|
/**
|
|
65
67
|
* Opaque cursor for iterating over feed items.
|
|
66
68
|
*/
|
|
@@ -78,6 +80,16 @@ export interface RetentionOptions {
|
|
|
78
80
|
cursor?: string;
|
|
79
81
|
}
|
|
80
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Sync options for a feed.
|
|
85
|
+
*/
|
|
86
|
+
export interface SyncOptions {
|
|
87
|
+
/** Push local changes to the server. Defaults to true. */
|
|
88
|
+
shouldPush?: boolean;
|
|
89
|
+
/** Pull remote changes from the server. Defaults to true. */
|
|
90
|
+
shouldPull?: boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
81
93
|
//
|
|
82
94
|
// Factory
|
|
83
95
|
//
|
|
@@ -94,14 +106,17 @@ export interface RetentionOptions {
|
|
|
94
106
|
export const make = (props: Obj.MakeProps<typeof Feed> = {}): Feed => Obj.make(Feed, props);
|
|
95
107
|
|
|
96
108
|
/**
|
|
97
|
-
*
|
|
109
|
+
* Derives the queue DXN from the feed object's DXN.
|
|
110
|
+
* Returns `undefined` when the feed is not stored in a space yet.
|
|
98
111
|
*
|
|
99
|
-
*
|
|
112
|
+
* Used internally by the feed service layer.
|
|
100
113
|
*/
|
|
101
|
-
// TODO(wittjosiah): Align backing feed dxn's with object DXN.
|
|
102
114
|
export const getQueueDxn = (feed: Feed): DXN | undefined => {
|
|
103
|
-
const
|
|
104
|
-
|
|
115
|
+
const self = Obj.getDXN(feed).asEchoDXN();
|
|
116
|
+
if (!self || !self.spaceId) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
return new DXN(DXN.kind.QUEUE, [feed.namespace ?? 'data', self.spaceId, self.echoId]);
|
|
105
120
|
};
|
|
106
121
|
|
|
107
122
|
//
|
|
@@ -113,8 +128,8 @@ export const getQueueDxn = (feed: Feed): DXN | undefined => {
|
|
|
113
128
|
* Provides the bridge to the underlying storage implementation.
|
|
114
129
|
* Must be provided by the application layer (e.g., echo-db).
|
|
115
130
|
*/
|
|
116
|
-
export class
|
|
117
|
-
|
|
131
|
+
export class FeedService extends Context.Tag('@dxos/echo/Feed/FeedService')<
|
|
132
|
+
FeedService,
|
|
118
133
|
{
|
|
119
134
|
/**
|
|
120
135
|
* Appends items to a feed.
|
|
@@ -134,24 +149,61 @@ export class Service extends Context.Tag('@dxos/echo/Feed/Service')<
|
|
|
134
149
|
<Q extends Query.Any>(feed: Feed, query: Q): QueryResult.QueryResult<Query.Type<Q>>;
|
|
135
150
|
<F extends Filter.Any>(feed: Feed, filter: F): QueryResult.QueryResult<Filter.Type<F>>;
|
|
136
151
|
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Syncs the feed with the server.
|
|
155
|
+
*/
|
|
156
|
+
sync(feed: Feed, options?: SyncOptions): Promise<void>;
|
|
137
157
|
}
|
|
138
158
|
>() {}
|
|
139
159
|
|
|
160
|
+
/**
|
|
161
|
+
* @deprecated Use `FeedService` instead.
|
|
162
|
+
*/
|
|
163
|
+
export type Service = FeedService;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @deprecated Use `FeedService` instead.
|
|
167
|
+
*/
|
|
168
|
+
export const Service = FeedService;
|
|
169
|
+
|
|
140
170
|
/**
|
|
141
171
|
* Layer that provides a Feed service that throws when accessed.
|
|
142
172
|
* Useful as a default layer when no feed service is available.
|
|
143
173
|
*/
|
|
144
|
-
export const notAvailable: Layer.Layer<
|
|
174
|
+
export const notAvailable: Layer.Layer<FeedService> = Layer.succeed(FeedService, {
|
|
145
175
|
append: () => {
|
|
146
|
-
throw new Error('Feed.
|
|
176
|
+
throw new Error('Feed.FeedService not available');
|
|
147
177
|
},
|
|
148
178
|
remove: () => {
|
|
149
|
-
throw new Error('Feed.
|
|
179
|
+
throw new Error('Feed.FeedService not available');
|
|
150
180
|
},
|
|
151
181
|
query: () => {
|
|
152
|
-
throw new Error('Feed.
|
|
182
|
+
throw new Error('Feed.FeedService not available');
|
|
153
183
|
},
|
|
154
|
-
|
|
184
|
+
sync: () => {
|
|
185
|
+
throw new Error('Feed.FeedService not available');
|
|
186
|
+
},
|
|
187
|
+
} as Context.Tag.Service<FeedService>);
|
|
188
|
+
|
|
189
|
+
//
|
|
190
|
+
// Context (per-call) service
|
|
191
|
+
//
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Effect service exposing a single `Feed.Feed` as the "current" feed for a call site.
|
|
195
|
+
*
|
|
196
|
+
* @deprecated Prefer threading a `Feed.Feed` explicitly through function signatures
|
|
197
|
+
* over hiding it behind a context service.
|
|
198
|
+
*/
|
|
199
|
+
export class ContextFeedService extends Context.Tag('@dxos/echo/Feed/ContextFeedService')<
|
|
200
|
+
ContextFeedService,
|
|
201
|
+
{
|
|
202
|
+
readonly feed: Feed;
|
|
203
|
+
}
|
|
204
|
+
>() {
|
|
205
|
+
static layer = (feed: Feed): Layer.Layer<ContextFeedService> => Layer.succeed(ContextFeedService, { feed });
|
|
206
|
+
}
|
|
155
207
|
|
|
156
208
|
//
|
|
157
209
|
// Operations
|
|
@@ -165,9 +217,9 @@ export const notAvailable: Layer.Layer<Service> = Layer.succeed(Service, {
|
|
|
165
217
|
* yield* Feed.append(feed, [Obj.make(Notification, { title: 'Hello' })]);
|
|
166
218
|
* ```
|
|
167
219
|
*/
|
|
168
|
-
export const append = (feed: Feed, items: Entity.Unknown[]): Effect.Effect<void, never,
|
|
220
|
+
export const append = (feed: Feed, items: Entity.Unknown[]): Effect.Effect<void, never, FeedService> =>
|
|
169
221
|
Effect.gen(function* () {
|
|
170
|
-
const service = yield*
|
|
222
|
+
const service = yield* FeedService;
|
|
171
223
|
yield* Effect.promise(() => service.append(feed, items));
|
|
172
224
|
});
|
|
173
225
|
|
|
@@ -180,9 +232,9 @@ export const append = (feed: Feed, items: Entity.Unknown[]): Effect.Effect<void,
|
|
|
180
232
|
* ```
|
|
181
233
|
*/
|
|
182
234
|
// TODO(dmaretskyi): Should we allow snapshots here? - what does it mean to remove a snapshot?
|
|
183
|
-
export const remove = (feed: Feed, items: (Entity.Unknown | Obj.Snapshot)[]): Effect.Effect<void, never,
|
|
235
|
+
export const remove = (feed: Feed, items: (Entity.Unknown | Obj.Snapshot)[]): Effect.Effect<void, never, FeedService> =>
|
|
184
236
|
Effect.gen(function* () {
|
|
185
|
-
const service = yield*
|
|
237
|
+
const service = yield* FeedService;
|
|
186
238
|
const ids = items.map((item) => item.id);
|
|
187
239
|
yield* Effect.promise(() => service.remove(feed, ids));
|
|
188
240
|
});
|
|
@@ -201,10 +253,16 @@ export const remove = (feed: Feed, items: (Entity.Unknown | Obj.Snapshot)[]): Ef
|
|
|
201
253
|
// const object = yield* feed.pipe(Feed.query(Filter.type(Person))).first;
|
|
202
254
|
// ... unify for Database and schema queries.
|
|
203
255
|
export const query: {
|
|
204
|
-
<Q extends Query.Any>(
|
|
205
|
-
|
|
256
|
+
<Q extends Query.Any>(
|
|
257
|
+
feed: Feed,
|
|
258
|
+
query: Q,
|
|
259
|
+
): Effect.Effect<QueryResult.QueryResult<Query.Type<Q>>, never, FeedService>;
|
|
260
|
+
<F extends Filter.Any>(
|
|
261
|
+
feed: Feed,
|
|
262
|
+
filter: F,
|
|
263
|
+
): Effect.Effect<QueryResult.QueryResult<Filter.Type<F>>, never, FeedService>;
|
|
206
264
|
} = (feed: Feed, queryOrFilter: Query.Any | Filter.Any) =>
|
|
207
|
-
|
|
265
|
+
FeedService.pipe(Effect.map((service) => service.query(feed, queryOrFilter as any) as QueryResult.QueryResult<any>));
|
|
208
266
|
|
|
209
267
|
/**
|
|
210
268
|
* Executes a feed query once and returns the results.
|
|
@@ -215,11 +273,26 @@ export const query: {
|
|
|
215
273
|
* ```
|
|
216
274
|
*/
|
|
217
275
|
export const runQuery: {
|
|
218
|
-
<Q extends Query.Any>(feed: Feed, query: Q): Effect.Effect<Query.Type<Q>[], never,
|
|
219
|
-
<F extends Filter.Any>(feed: Feed, filter: F): Effect.Effect<Filter.Type<F>[], never,
|
|
276
|
+
<Q extends Query.Any>(feed: Feed, query: Q): Effect.Effect<Query.Type<Q>[], never, FeedService>;
|
|
277
|
+
<F extends Filter.Any>(feed: Feed, filter: F): Effect.Effect<Filter.Type<F>[], never, FeedService>;
|
|
220
278
|
} = (feed: Feed, queryOrFilter: Query.Any | Filter.Any) =>
|
|
221
279
|
query(feed, queryOrFilter as any).pipe(Effect.flatMap((queryResult) => Effect.promise(() => queryResult.run())));
|
|
222
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Syncs the feed with the server.
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* yield* Feed.sync(feed);
|
|
287
|
+
* yield* Feed.sync(feed, { shouldPush: false });
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
export const sync = (feed: Feed, options?: SyncOptions): Effect.Effect<void, never, FeedService> =>
|
|
291
|
+
Effect.gen(function* () {
|
|
292
|
+
const service = yield* FeedService;
|
|
293
|
+
yield* Effect.promise(() => service.sync(feed, options));
|
|
294
|
+
});
|
|
295
|
+
|
|
223
296
|
/**
|
|
224
297
|
* Creates a cursor for iterating over feed items.
|
|
225
298
|
* Currently stubbed — cursor operations are not yet implemented.
|
|
@@ -231,32 +304,32 @@ export const runQuery: {
|
|
|
231
304
|
* ```
|
|
232
305
|
*/
|
|
233
306
|
// TODO(wittjosiah): Implement cursor operations. Use Effect streams?
|
|
234
|
-
export const cursor = <T = Obj.Snapshot>(_feed: Feed): Effect.Effect<Cursor<T>, never,
|
|
307
|
+
export const cursor = <T = Obj.Snapshot>(_feed: Feed): Effect.Effect<Cursor<T>, never, FeedService> =>
|
|
235
308
|
Effect.succeed({ _tag: 'Cursor' } as Cursor<T>);
|
|
236
309
|
|
|
237
310
|
/**
|
|
238
311
|
* Returns the next item from a feed cursor.
|
|
239
312
|
* Currently stubbed — cursor operations are not yet implemented.
|
|
240
313
|
*/
|
|
241
|
-
export const next = <T = Obj.Snapshot>(_cursor: Cursor<T>): Effect.Effect<T, never,
|
|
314
|
+
export const next = <T = Obj.Snapshot>(_cursor: Cursor<T>): Effect.Effect<T, never, FeedService> =>
|
|
242
315
|
Effect.die('Feed.next is not yet implemented');
|
|
243
316
|
|
|
244
317
|
/**
|
|
245
318
|
* Returns the next item from a feed cursor as an Option.
|
|
246
319
|
* Currently stubbed — cursor operations are not yet implemented.
|
|
247
320
|
*/
|
|
248
|
-
export const nextOption = <T = Obj.Snapshot>(_cursor: Cursor<T>): Effect.Effect<Option.Option<T>, never,
|
|
321
|
+
export const nextOption = <T = Obj.Snapshot>(_cursor: Cursor<T>): Effect.Effect<Option.Option<T>, never, FeedService> =>
|
|
249
322
|
Effect.die('Feed.nextOption is not yet implemented');
|
|
250
323
|
|
|
251
324
|
/**
|
|
252
325
|
* Sets the local retention policy for a feed.
|
|
253
|
-
* Currently stubbed —
|
|
326
|
+
* Currently stubbed — feeds do not yet support retention.
|
|
254
327
|
*
|
|
255
328
|
* @example
|
|
256
329
|
* ```ts
|
|
257
330
|
* yield* Feed.setRetention(feed, { count: 1000 });
|
|
258
331
|
* ```
|
|
259
332
|
*/
|
|
260
|
-
// TODO(
|
|
261
|
-
export const setRetention = (_feed: Feed, _options: RetentionOptions): Effect.Effect<void, never,
|
|
333
|
+
// TODO(dmaretskyi): Implement when feed retention is supported.
|
|
334
|
+
export const setRetention = (_feed: Feed, _options: RetentionOptions): Effect.Effect<void, never, FeedService> =>
|
|
262
335
|
Effect.void;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import * as Filter from './Filter';
|
|
8
|
+
|
|
9
|
+
describe('Filter timestamp builders', () => {
|
|
10
|
+
test('updated({ after }) produces correct AST', () => {
|
|
11
|
+
const ts = 1700000000000;
|
|
12
|
+
const f = Filter.updated({ after: ts });
|
|
13
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: ts });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('updated({ before }) produces correct AST', () => {
|
|
17
|
+
const ts = 1700000000000;
|
|
18
|
+
const f = Filter.updated({ before: ts });
|
|
19
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'updatedAt', operator: 'lte', value: ts });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('created({ after }) produces correct AST', () => {
|
|
23
|
+
const ts = 1700000000000;
|
|
24
|
+
const f = Filter.created({ after: ts });
|
|
25
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'createdAt', operator: 'gte', value: ts });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('created({ before }) produces correct AST', () => {
|
|
29
|
+
const ts = 1700000000000;
|
|
30
|
+
const f = Filter.created({ before: ts });
|
|
31
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'createdAt', operator: 'lte', value: ts });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('updated() accepts Date objects', () => {
|
|
35
|
+
const date = new Date('2026-03-20T21:00:00Z');
|
|
36
|
+
const f = Filter.updated({ after: date });
|
|
37
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: date.getTime() });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('created() accepts Date objects', () => {
|
|
41
|
+
const date = new Date('2026-03-20T09:00:00Z');
|
|
42
|
+
const f = Filter.created({ before: date });
|
|
43
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'createdAt', operator: 'lte', value: date.getTime() });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('updated({ after, before }) produces AND of two timestamp nodes', () => {
|
|
47
|
+
const from = 1700000000000;
|
|
48
|
+
const to = 1700086400000;
|
|
49
|
+
const f = Filter.updated({ after: from, before: to });
|
|
50
|
+
expect(f.ast).toEqual({
|
|
51
|
+
type: 'and',
|
|
52
|
+
filters: [
|
|
53
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: from },
|
|
54
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'lte', value: to },
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('updated({ after, before }) accepts Date objects', () => {
|
|
60
|
+
const from = new Date('2026-03-19T00:00:00Z');
|
|
61
|
+
const to = new Date('2026-03-20T00:00:00Z');
|
|
62
|
+
const f = Filter.updated({ after: from, before: to });
|
|
63
|
+
expect(f.ast).toEqual({
|
|
64
|
+
type: 'and',
|
|
65
|
+
filters: [
|
|
66
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: from.getTime() },
|
|
67
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'lte', value: to.getTime() },
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('timestamp filters compose with and()', () => {
|
|
73
|
+
const typeFilter = Filter.everything();
|
|
74
|
+
const timeFilter = Filter.updated({ after: 1700000000000 });
|
|
75
|
+
const combined = Filter.and(typeFilter, timeFilter);
|
|
76
|
+
expect(combined.ast.type).toBe('and');
|
|
77
|
+
expect((combined.ast as any).filters).toHaveLength(2);
|
|
78
|
+
expect((combined.ast as any).filters[1]).toEqual({
|
|
79
|
+
type: 'timestamp',
|
|
80
|
+
field: 'updatedAt',
|
|
81
|
+
operator: 'gte',
|
|
82
|
+
value: 1700000000000,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('timestamp filters pass the is() check', () => {
|
|
87
|
+
const f = Filter.updated({ after: Date.now() });
|
|
88
|
+
expect(Filter.is(f)).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/Filter.ts
CHANGED
|
@@ -14,11 +14,12 @@ import { assertArgument } from '@dxos/invariant';
|
|
|
14
14
|
import { DXN, ObjectId } from '@dxos/keys';
|
|
15
15
|
|
|
16
16
|
import * as internal from './internal';
|
|
17
|
+
import type * as Obj from './Obj';
|
|
17
18
|
import * as Ref from './Ref';
|
|
18
19
|
|
|
19
20
|
export interface Filter<T> {
|
|
20
21
|
// TODO(dmaretskyi): See new effect-schema approach to variance.
|
|
21
|
-
'~Filter': { value: Types.
|
|
22
|
+
'~Filter': { value: Types.Covariant<T> };
|
|
22
23
|
|
|
23
24
|
ast: QueryAST.Filter;
|
|
24
25
|
}
|
|
@@ -157,6 +158,37 @@ export const tag = (tag: string): Any => {
|
|
|
157
158
|
});
|
|
158
159
|
};
|
|
159
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Options for {@link key} filter.
|
|
163
|
+
*/
|
|
164
|
+
export type KeyFilterOptions = {
|
|
165
|
+
/**
|
|
166
|
+
* Optional semver range expression (e.g. `^1.2.3`, `~2.0.0`, `>=1.0.0 <2.0.0`).
|
|
167
|
+
* Matches the object's meta `version` field against the range.
|
|
168
|
+
* If omitted, matches any version (including objects with no version).
|
|
169
|
+
*/
|
|
170
|
+
version?: string;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Filter by registry key stored in object meta.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* Filter.key('org.example.type.foo');
|
|
179
|
+
* Filter.key('org.example.type.foo', { version: '^1.2.3' });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export const key = (key: string, options?: KeyFilterOptions): Any => {
|
|
183
|
+
return new FilterClass({
|
|
184
|
+
type: 'object',
|
|
185
|
+
typename: null,
|
|
186
|
+
props: {},
|
|
187
|
+
metaKey: key,
|
|
188
|
+
metaVersion: options?.version,
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
|
|
160
192
|
/**
|
|
161
193
|
* Filter by properties.
|
|
162
194
|
*/
|
|
@@ -278,7 +310,7 @@ export const lte = <T>(value: T): Filter<T | undefined> => {
|
|
|
278
310
|
* Predicate for property to be in the provided array.
|
|
279
311
|
* @param values - Values to check against.
|
|
280
312
|
*/
|
|
281
|
-
const in$ = <T>(...values: T[]): Filter<T
|
|
313
|
+
const in$ = <T>(...values: T[]): Filter<T> => {
|
|
282
314
|
return new FilterClass({
|
|
283
315
|
type: 'in',
|
|
284
316
|
values,
|
|
@@ -302,7 +334,7 @@ export const contains = <T>(value: T): Filter<readonly T[] | undefined> => {
|
|
|
302
334
|
* @param from - Start of the range (inclusive).
|
|
303
335
|
* @param to - End of the range (exclusive).
|
|
304
336
|
*/
|
|
305
|
-
export const between = <T>(from: T, to: T): Filter<
|
|
337
|
+
export const between = <T>(from: T, to: T): Filter<T> => {
|
|
306
338
|
return new FilterClass({
|
|
307
339
|
type: 'range',
|
|
308
340
|
from,
|
|
@@ -310,6 +342,63 @@ export const between = <T>(from: T, to: T): Filter<unknown> => {
|
|
|
310
342
|
});
|
|
311
343
|
};
|
|
312
344
|
|
|
345
|
+
type TimeRange = { after?: Date | number; before?: Date | number };
|
|
346
|
+
|
|
347
|
+
const _toUnixMs = (date: Date | number): number => (typeof date === 'number' ? date : date.getTime());
|
|
348
|
+
|
|
349
|
+
const _timeRangeFilter = (field: 'updatedAt' | 'createdAt', range: TimeRange): Any => {
|
|
350
|
+
const filters: Any[] = [];
|
|
351
|
+
if (range.after != null) {
|
|
352
|
+
filters.push(new FilterClass({ type: 'timestamp', field, operator: 'gte', value: _toUnixMs(range.after) }));
|
|
353
|
+
}
|
|
354
|
+
if (range.before != null) {
|
|
355
|
+
filters.push(new FilterClass({ type: 'timestamp', field, operator: 'lte', value: _toUnixMs(range.before) }));
|
|
356
|
+
}
|
|
357
|
+
if (filters.length === 0) {
|
|
358
|
+
return everything();
|
|
359
|
+
}
|
|
360
|
+
return filters.length === 1 ? filters[0] : and(...filters);
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Filter objects by updatedAt timestamp.
|
|
365
|
+
*/
|
|
366
|
+
export const updated = (range: TimeRange): Any => _timeRangeFilter('updatedAt', range);
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Filter objects by createdAt timestamp.
|
|
370
|
+
*/
|
|
371
|
+
export const created = (range: TimeRange): Any => _timeRangeFilter('createdAt', range);
|
|
372
|
+
|
|
373
|
+
export type ChildOfOptions = {
|
|
374
|
+
/** Whether to match transitively (grandchildren, etc.). Defaults to true. */
|
|
375
|
+
transitive?: boolean;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Filter objects that are children of the specified parent(s).
|
|
380
|
+
* Accepts ECHO objects, Refs, or arrays of either.
|
|
381
|
+
* Refs are resolved to DXNs without loading; objects use {@link Obj.getDXN}.
|
|
382
|
+
* With transitive=true (default), also matches grandchildren and beyond.
|
|
383
|
+
*/
|
|
384
|
+
export const childOf = (
|
|
385
|
+
parents: Obj.Unknown | Ref.Unknown | readonly (Obj.Unknown | Ref.Unknown)[],
|
|
386
|
+
options?: ChildOfOptions,
|
|
387
|
+
): Any => {
|
|
388
|
+
const items = Array.isArray(parents) ? parents : [parents];
|
|
389
|
+
const dxns = items.map((item) => {
|
|
390
|
+
if (Ref.isRef(item)) {
|
|
391
|
+
return item.dxn.toString();
|
|
392
|
+
}
|
|
393
|
+
return internal.getDXN(item).toString();
|
|
394
|
+
});
|
|
395
|
+
return new FilterClass({
|
|
396
|
+
type: 'child-of',
|
|
397
|
+
parents: dxns,
|
|
398
|
+
transitive: options?.transitive ?? true,
|
|
399
|
+
});
|
|
400
|
+
};
|
|
401
|
+
|
|
313
402
|
/**
|
|
314
403
|
* Negate the filter.
|
|
315
404
|
*/
|
|
@@ -389,3 +478,8 @@ const processPredicate = (predicate: any): QueryAST.Filter => {
|
|
|
389
478
|
Match.orElse((value) => eq(value).ast),
|
|
390
479
|
);
|
|
391
480
|
};
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Returns a human-readable string representation of a Filter AST.
|
|
484
|
+
*/
|
|
485
|
+
export const pretty = (filter: Any): string => internal.prettyFilter(filter.ast);
|
package/src/Hypergraph.ts
CHANGED
|
@@ -22,10 +22,10 @@ export interface RefResolutionContext {
|
|
|
22
22
|
space?: Key.SpaceId;
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* This
|
|
25
|
+
* Feed that the resolution is happening from (as the underlying queue DXN).
|
|
26
|
+
* This feed will be searched first, and then the space it belongs to.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
feed?: DXN;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export interface RefResolverOptions {
|