@dxos/echo 0.8.4-main.21d9917 → 0.8.4-main.2244d791bb
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/dist/lib/{browser → neutral}/Annotation.mjs +7 -5
- package/dist/lib/neutral/Database.mjs +45 -0
- package/dist/lib/{browser → neutral}/Entity.mjs +8 -9
- package/dist/lib/{browser → neutral}/Err.mjs +4 -3
- package/dist/lib/{browser → neutral}/Filter.mjs +9 -10
- package/dist/lib/{browser → neutral}/Format.mjs +4 -5
- package/dist/lib/neutral/JsonSchema.mjs +19 -0
- package/dist/lib/{browser → neutral}/Key.mjs +2 -3
- package/dist/lib/{node-esm → neutral}/Obj.mjs +23 -10
- package/dist/lib/{browser → neutral}/Order.mjs +2 -3
- package/dist/lib/neutral/Query.mjs +26 -0
- package/dist/lib/neutral/QueryResult.mjs +2 -0
- package/dist/lib/neutral/Ref.mjs +22 -0
- package/dist/lib/{browser → neutral}/Relation.mjs +9 -10
- package/dist/lib/neutral/SchemaRegistry.mjs +2 -0
- package/dist/lib/neutral/Tag.mjs +25 -0
- package/dist/lib/{browser → neutral}/Type.mjs +8 -9
- package/dist/lib/{browser/chunk-W5D2GWAW.mjs → neutral/chunk-36GDMODZ.mjs} +5 -6
- package/dist/lib/{browser/chunk-W5D2GWAW.mjs.map → neutral/chunk-36GDMODZ.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-ZHXZGIXD.mjs → neutral/chunk-4L6DOFXP.mjs} +1 -3
- package/dist/lib/{browser/chunk-ZHXZGIXD.mjs.map → neutral/chunk-4L6DOFXP.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-NOPVNWPT.mjs → neutral/chunk-5MGEVDUW.mjs} +73 -8
- package/dist/lib/neutral/chunk-5MGEVDUW.mjs.map +7 -0
- package/dist/lib/{browser/chunk-FRDT7RA4.mjs → neutral/chunk-7WE7SBA2.mjs} +4 -5
- package/dist/lib/neutral/chunk-7WE7SBA2.mjs.map +7 -0
- package/dist/lib/{browser/chunk-INHXFXY5.mjs → neutral/chunk-ANHVGJI4.mjs} +2 -3
- package/dist/lib/{node-esm/chunk-AJEMYSIR.mjs.map → neutral/chunk-ANHVGJI4.mjs.map} +1 -1
- package/dist/lib/neutral/chunk-B4FLOYG7.mjs +130 -0
- package/dist/lib/neutral/chunk-B4FLOYG7.mjs.map +7 -0
- package/dist/lib/{browser/chunk-U2J7TA7K.mjs → neutral/chunk-BHR4XVJK.mjs} +5 -6
- package/dist/lib/{node-esm/chunk-DMR7OAFK.mjs.map → neutral/chunk-BHR4XVJK.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-ZAGAOZVY.mjs → neutral/chunk-CH3HX4Z5.mjs} +4 -5
- package/dist/lib/{node-esm/chunk-QYR67VBV.mjs.map → neutral/chunk-CH3HX4Z5.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-CGS2ULMK.mjs → neutral/chunk-J5LGTIGS.mjs} +1 -2
- package/dist/lib/{browser/chunk-YKTSSMDS.mjs → neutral/chunk-KB7RIVLK.mjs} +1 -3
- package/dist/lib/neutral/chunk-KB7RIVLK.mjs.map +7 -0
- package/dist/lib/{browser/chunk-2SBB7OWV.mjs → neutral/chunk-KSFI2POM.mjs} +11 -10
- package/dist/lib/neutral/chunk-KSFI2POM.mjs.map +7 -0
- package/dist/lib/{browser/chunk-6L5HHUVU.mjs → neutral/chunk-LKQBTRJX.mjs} +18 -5
- package/dist/lib/neutral/chunk-LKQBTRJX.mjs.map +7 -0
- package/dist/lib/{browser/chunk-CJ5YELTO.mjs → neutral/chunk-MXQJZCPY.mjs} +15 -3
- package/dist/lib/neutral/chunk-MXQJZCPY.mjs.map +7 -0
- package/dist/lib/{browser/chunk-PQZW3S6L.mjs → neutral/chunk-N2QNHMT5.mjs} +3 -4
- package/dist/lib/{node-esm/chunk-Y75VU7LB.mjs.map → neutral/chunk-N2QNHMT5.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-IXVWLTG7.mjs → neutral/chunk-OMUPQMLR.mjs} +1 -3
- package/dist/lib/{browser/chunk-IXVWLTG7.mjs.map → neutral/chunk-OMUPQMLR.mjs.map} +1 -1
- package/dist/lib/{node-esm/chunk-YOLH5KS4.mjs → neutral/chunk-RIMHNJ3E.mjs} +17 -4
- package/dist/lib/neutral/chunk-RIMHNJ3E.mjs.map +7 -0
- package/dist/lib/{browser/chunk-JMKVF2YQ.mjs → neutral/chunk-ROKO4RKJ.mjs} +2 -3
- package/dist/lib/{node-esm/chunk-K37NA7PO.mjs.map → neutral/chunk-ROKO4RKJ.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-KQQGVHFN.mjs → neutral/chunk-SHLKRGRB.mjs} +5 -6
- package/dist/lib/{node-esm/chunk-NRN3ZW2T.mjs.map → neutral/chunk-SHLKRGRB.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-22JMFST2.mjs → neutral/chunk-UW4T7PAL.mjs} +3 -4
- package/dist/lib/{browser/chunk-22JMFST2.mjs.map → neutral/chunk-UW4T7PAL.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-XDIUHAAX.mjs → neutral/chunk-WSPASOLU.mjs} +3 -4
- package/dist/lib/{node-esm/chunk-QLI2EIJ2.mjs.map → neutral/chunk-WSPASOLU.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-MYCCGG2T.mjs → neutral/chunk-X2MPMYYN.mjs} +1 -3
- package/dist/lib/{node-esm/chunk-MOWUEW5P.mjs.map → neutral/chunk-X2MPMYYN.mjs.map} +1 -1
- package/dist/lib/{browser/chunk-FPOISFQK.mjs → neutral/chunk-XAJMXQ4H.mjs} +7 -4
- package/dist/lib/neutral/chunk-XAJMXQ4H.mjs.map +7 -0
- package/dist/lib/{browser/chunk-BJPE6CIC.mjs → neutral/chunk-ZUG3PNXU.mjs} +146 -83
- package/dist/lib/neutral/chunk-ZUG3PNXU.mjs.map +7 -0
- package/dist/lib/{browser → neutral}/index.mjs +23 -24
- package/dist/lib/{browser → neutral}/internal/index.mjs +13 -8
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/{browser → neutral}/testing/index.mjs +23 -24
- package/dist/lib/{node-esm → neutral}/testing/index.mjs.map +1 -1
- package/dist/types/src/Annotation.d.ts +22 -0
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +72 -50
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +43 -0
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Obj.d.ts +84 -4
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +10 -0
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/Relation.d.ts +2 -2
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/hierarchy.test.d.ts +2 -0
- package/dist/types/src/hierarchy.test.d.ts.map +1 -0
- package/dist/types/src/internal/annotations/annotations.d.ts +13 -6
- package/dist/types/src/internal/annotations/annotations.d.ts.map +1 -1
- package/dist/types/src/internal/annotations/util.d.ts +12 -0
- package/dist/types/src/internal/annotations/util.d.ts.map +1 -1
- package/dist/types/src/internal/api/meta.d.ts +2 -2
- package/dist/types/src/internal/api/meta.d.ts.map +1 -1
- package/dist/types/src/internal/entities/model.d.ts +3 -1
- package/dist/types/src/internal/entities/model.d.ts.map +1 -1
- package/dist/types/src/internal/entities/object.d.ts.map +1 -1
- package/dist/types/src/internal/entities/relation.d.ts.map +1 -1
- package/dist/types/src/internal/formats/select.d.ts +2 -2
- package/dist/types/src/internal/formats/select.d.ts.map +1 -1
- package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts.map +1 -1
- package/dist/types/src/internal/json-schema/json-schema-type.d.ts +130 -29
- package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +1 -1
- package/dist/types/src/internal/json-schema/json-schema.d.ts +2 -1
- package/dist/types/src/internal/json-schema/json-schema.d.ts.map +1 -1
- package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/object/snapshot.d.ts.map +1 -1
- package/dist/types/src/internal/proxy/make-object.d.ts.map +1 -1
- package/dist/types/src/internal/proxy/typed-handler.d.ts +2 -1
- package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/ref/ref.d.ts +16 -2
- package/dist/types/src/internal/ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/schema/compose.d.ts +2 -1
- package/dist/types/src/internal/schema/compose.d.ts.map +1 -1
- package/dist/types/src/internal/schema/echo-schema.d.ts +2 -1
- package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -1
- package/dist/types/src/internal/schema/persistent-schema.d.ts.map +1 -1
- package/dist/types/src/internal/types/meta.d.ts +5 -5
- package/dist/types/src/internal/types/meta.d.ts.map +1 -1
- package/dist/types/src/internal/types/typename.d.ts +8 -0
- package/dist/types/src/internal/types/typename.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +34 -113
- package/src/Annotation.ts +27 -0
- package/src/Database.ts +141 -124
- package/src/Err.ts +20 -0
- package/src/Obj.test.ts +56 -0
- package/src/Obj.ts +140 -11
- package/src/Query.ts +28 -0
- package/src/Relation.ts +5 -3
- package/src/hierarchy.test.ts +33 -0
- package/src/internal/annotations/annotations.ts +28 -1
- package/src/internal/annotations/util.ts +13 -0
- package/src/internal/api/meta.ts +3 -3
- package/src/internal/entities/model.ts +4 -0
- package/src/internal/entities/object.ts +1 -3
- package/src/internal/entities/relation.ts +1 -3
- package/src/internal/formats/format.test.ts +1 -1
- package/src/internal/formats/select.ts +1 -1
- package/src/internal/formats/types.ts +1 -1
- package/src/internal/json-schema/json-schema-normalize.ts +4 -2
- package/src/internal/json-schema/json-schema-type.ts +30 -31
- package/src/internal/json-schema/json-schema.ts +10 -6
- package/src/internal/object/json-serializer.test.ts +26 -2
- package/src/internal/object/json-serializer.ts +25 -9
- package/src/internal/object/schema-validator.test.ts +3 -7
- package/src/internal/object/set-value.test.ts +9 -9
- package/src/internal/object/snapshot.ts +29 -6
- package/src/internal/proxy/make-object.ts +12 -2
- package/src/internal/proxy/typed-handler.test.ts +8 -12
- package/src/internal/proxy/typed-handler.ts +9 -1
- package/src/internal/proxy/typed-object.test.ts +11 -11
- package/src/internal/ref/ref.test.ts +1 -1
- package/src/internal/ref/ref.ts +26 -2
- package/src/internal/schema/compose.ts +13 -8
- package/src/internal/schema/echo-schema.ts +3 -2
- package/src/internal/schema/persistent-schema.ts +2 -1
- package/src/internal/types/meta.ts +12 -13
- package/src/internal/types/typename.ts +10 -0
- package/dist/lib/browser/Database.mjs +0 -18
- package/dist/lib/browser/JsonSchema.mjs +0 -20
- package/dist/lib/browser/Obj.mjs +0 -91
- package/dist/lib/browser/Query.mjs +0 -27
- package/dist/lib/browser/QueryResult.mjs +0 -3
- package/dist/lib/browser/Ref.mjs +0 -23
- package/dist/lib/browser/SchemaRegistry.mjs +0 -3
- package/dist/lib/browser/Tag.mjs +0 -26
- package/dist/lib/browser/chunk-2SBB7OWV.mjs.map +0 -7
- package/dist/lib/browser/chunk-6L5HHUVU.mjs.map +0 -7
- package/dist/lib/browser/chunk-7STIBCP7.mjs +0 -133
- package/dist/lib/browser/chunk-7STIBCP7.mjs.map +0 -7
- package/dist/lib/browser/chunk-BJPE6CIC.mjs.map +0 -7
- package/dist/lib/browser/chunk-CJ5YELTO.mjs.map +0 -7
- package/dist/lib/browser/chunk-FPOISFQK.mjs.map +0 -7
- package/dist/lib/browser/chunk-FRDT7RA4.mjs.map +0 -7
- package/dist/lib/browser/chunk-INHXFXY5.mjs.map +0 -7
- package/dist/lib/browser/chunk-JMKVF2YQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-KQQGVHFN.mjs.map +0 -7
- package/dist/lib/browser/chunk-MYCCGG2T.mjs.map +0 -7
- package/dist/lib/browser/chunk-NOPVNWPT.mjs.map +0 -7
- package/dist/lib/browser/chunk-PQZW3S6L.mjs.map +0 -7
- package/dist/lib/browser/chunk-RK4Z4JUZ.mjs +0 -283
- package/dist/lib/browser/chunk-RK4Z4JUZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-U2J7TA7K.mjs.map +0 -7
- package/dist/lib/browser/chunk-XDIUHAAX.mjs.map +0 -7
- package/dist/lib/browser/chunk-YKTSSMDS.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZAGAOZVY.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/Annotation.mjs +0 -33
- package/dist/lib/node-esm/Annotation.mjs.map +0 -7
- package/dist/lib/node-esm/Database.mjs +0 -18
- package/dist/lib/node-esm/Database.mjs.map +0 -7
- package/dist/lib/node-esm/Entity.mjs +0 -52
- package/dist/lib/node-esm/Entity.mjs.map +0 -7
- package/dist/lib/node-esm/Err.mjs +0 -11
- package/dist/lib/node-esm/Err.mjs.map +0 -7
- package/dist/lib/node-esm/Filter.mjs +0 -62
- package/dist/lib/node-esm/Filter.mjs.map +0 -7
- package/dist/lib/node-esm/Format.mjs +0 -67
- package/dist/lib/node-esm/Format.mjs.map +0 -7
- package/dist/lib/node-esm/JsonSchema.mjs +0 -20
- package/dist/lib/node-esm/JsonSchema.mjs.map +0 -7
- package/dist/lib/node-esm/Key.mjs +0 -13
- package/dist/lib/node-esm/Key.mjs.map +0 -7
- package/dist/lib/node-esm/Obj.mjs.map +0 -7
- package/dist/lib/node-esm/Order.mjs +0 -13
- package/dist/lib/node-esm/Order.mjs.map +0 -7
- package/dist/lib/node-esm/Query.mjs +0 -27
- package/dist/lib/node-esm/Query.mjs.map +0 -7
- package/dist/lib/node-esm/QueryResult.mjs +0 -3
- package/dist/lib/node-esm/QueryResult.mjs.map +0 -7
- package/dist/lib/node-esm/Ref.mjs +0 -23
- package/dist/lib/node-esm/Ref.mjs.map +0 -7
- package/dist/lib/node-esm/Relation.mjs +0 -85
- package/dist/lib/node-esm/Relation.mjs.map +0 -7
- package/dist/lib/node-esm/SchemaRegistry.mjs +0 -3
- package/dist/lib/node-esm/SchemaRegistry.mjs.map +0 -7
- package/dist/lib/node-esm/Tag.mjs +0 -26
- package/dist/lib/node-esm/Tag.mjs.map +0 -7
- package/dist/lib/node-esm/Type.mjs +0 -48
- package/dist/lib/node-esm/Type.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-4PNXQA64.mjs +0 -250
- package/dist/lib/node-esm/chunk-4PNXQA64.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-5OBN7GZW.mjs +0 -158
- package/dist/lib/node-esm/chunk-5OBN7GZW.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AJEMYSIR.mjs +0 -22
- package/dist/lib/node-esm/chunk-ANLVLWME.mjs +0 -98
- package/dist/lib/node-esm/chunk-ANLVLWME.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-DMR7OAFK.mjs +0 -57
- package/dist/lib/node-esm/chunk-FWTSPIFF.mjs +0 -133
- package/dist/lib/node-esm/chunk-FWTSPIFF.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ILMLLM4R.mjs +0 -204
- package/dist/lib/node-esm/chunk-ILMLLM4R.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-K37NA7PO.mjs +0 -43
- package/dist/lib/node-esm/chunk-LT3H4JOX.mjs +0 -3847
- package/dist/lib/node-esm/chunk-LT3H4JOX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-MOLNWFNL.mjs +0 -9
- package/dist/lib/node-esm/chunk-MOLNWFNL.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-MOWUEW5P.mjs +0 -15
- package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs +0 -40
- package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NRN3ZW2T.mjs +0 -143
- package/dist/lib/node-esm/chunk-QLI2EIJ2.mjs +0 -41
- package/dist/lib/node-esm/chunk-QYR67VBV.mjs +0 -288
- package/dist/lib/node-esm/chunk-UKGVOINP.mjs +0 -9
- package/dist/lib/node-esm/chunk-UKGVOINP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs +0 -403
- package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XHJRMQZD.mjs +0 -69
- package/dist/lib/node-esm/chunk-XHJRMQZD.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Y75VU7LB.mjs +0 -74
- package/dist/lib/node-esm/chunk-YOLH5KS4.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs +0 -39
- package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZBB67AKD.mjs +0 -24
- package/dist/lib/node-esm/chunk-ZBB67AKD.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -85
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/internal/index.mjs +0 -457
- package/dist/lib/node-esm/internal/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/testing/index.mjs +0 -367
- /package/dist/lib/{browser → neutral}/Annotation.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Database.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Entity.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Err.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Filter.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Format.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/JsonSchema.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Key.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Obj.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Order.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Query.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/QueryResult.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Ref.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Relation.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/SchemaRegistry.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Tag.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/Type.mjs.map +0 -0
- /package/dist/lib/{browser/chunk-CGS2ULMK.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
- /package/dist/lib/{browser → neutral}/index.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/internal/index.mjs.map +0 -0
package/src/Obj.ts
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
5
6
|
import * as Function from 'effect/Function';
|
|
7
|
+
import * as Option from 'effect/Option';
|
|
6
8
|
import * as Schema from 'effect/Schema';
|
|
7
9
|
|
|
8
10
|
import type { ForeignKey } from '@dxos/echo-protocol';
|
|
@@ -13,6 +15,7 @@ import { assumeType } from '@dxos/util';
|
|
|
13
15
|
|
|
14
16
|
import type * as Database from './Database';
|
|
15
17
|
import * as Entity from './Entity';
|
|
18
|
+
import * as Err from './Err';
|
|
16
19
|
import {
|
|
17
20
|
type ObjectJSON as APIJSON,
|
|
18
21
|
type AnyEntity,
|
|
@@ -27,7 +30,9 @@ import {
|
|
|
27
30
|
MetaId,
|
|
28
31
|
type Mutable,
|
|
29
32
|
type ObjectMeta,
|
|
30
|
-
|
|
33
|
+
// TODO(dmaretskyi): Export ParentId?
|
|
34
|
+
ParentId,
|
|
35
|
+
SnapshotKindId,
|
|
31
36
|
type VersionCompareResult,
|
|
32
37
|
VersionTypeId,
|
|
33
38
|
addTag as addTag$,
|
|
@@ -133,6 +138,7 @@ type Props<T = any> = {
|
|
|
133
138
|
export type MakeProps<S extends Schema.Schema.AnyNoContext> = {
|
|
134
139
|
id?: ObjectId;
|
|
135
140
|
[Meta]?: Partial<ObjectMeta>;
|
|
141
|
+
[Parent]?: Unknown;
|
|
136
142
|
} & NoInfer<Props<Schema.Schema.Type<S>>>;
|
|
137
143
|
|
|
138
144
|
/**
|
|
@@ -169,8 +175,16 @@ export const make: {
|
|
|
169
175
|
delete props[MetaId];
|
|
170
176
|
}
|
|
171
177
|
|
|
172
|
-
// Filter undefined values.
|
|
173
|
-
const filterUndefined = Object.fromEntries(Object.entries(props).filter(([_, v]) => v !== undefined));
|
|
178
|
+
// Filter undefined values (Object.entries only returns string-keyed properties).
|
|
179
|
+
const filterUndefined: any = Object.fromEntries(Object.entries(props).filter(([_, v]) => v !== undefined));
|
|
180
|
+
|
|
181
|
+
// Copy symbol properties (like ParentId) that Object.entries doesn't include.
|
|
182
|
+
for (const sym of Object.getOwnPropertySymbols(props)) {
|
|
183
|
+
const value = (props as any)[sym];
|
|
184
|
+
if (value !== undefined) {
|
|
185
|
+
filterUndefined[sym] = value;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
174
188
|
|
|
175
189
|
return makeObject<Schema.Schema.Type<S>>(schema, filterUndefined as any, {
|
|
176
190
|
...defaultMeta,
|
|
@@ -207,6 +221,60 @@ export const subscribe = (obj: Unknown, callback: () => void): (() => void) => {
|
|
|
207
221
|
*/
|
|
208
222
|
export const getSnapshot: <T extends Unknown>(obj: T) => Snapshot<T> = getSnapshot$ as any;
|
|
209
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Returns the reactive version of an object from the database, given its snapshot.
|
|
226
|
+
* Inverse of `Obj.getSnapshot`.
|
|
227
|
+
*
|
|
228
|
+
* Uses `Obj.getDatabase` internally to get the database from the snapshot,
|
|
229
|
+
* then resolves the reactive object by ID.
|
|
230
|
+
*
|
|
231
|
+
* @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).
|
|
232
|
+
* @returns Effect that succeeds with the reactive object, or fails with `GetReactiveError`.
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* const snapshot = Obj.getSnapshot(obj);
|
|
236
|
+
* const reactive = Obj.getReactive(snapshot).pipe(
|
|
237
|
+
* Effect.runSync
|
|
238
|
+
* );
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
export const getReactive = <T extends Unknown>(snapshot: Snapshot<T>): Effect.Effect<T, Err.GetReactiveError> =>
|
|
242
|
+
Effect.gen(function* () {
|
|
243
|
+
const db = getDatabase$(snapshot);
|
|
244
|
+
if (!db) {
|
|
245
|
+
return yield* Effect.fail(new Err.GetReactiveError({ reason: 'no-database', snapshotId: snapshot.id }));
|
|
246
|
+
}
|
|
247
|
+
const obj = db.getObjectById(snapshot.id);
|
|
248
|
+
if (!obj) {
|
|
249
|
+
return yield* Effect.fail(new Err.GetReactiveError({ reason: 'object-not-found', snapshotId: snapshot.id }));
|
|
250
|
+
}
|
|
251
|
+
return obj as T;
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Like `Obj.getReactive` but returns `Option.none()` instead of failing when the object
|
|
256
|
+
* cannot be resolved (no database, object not found).
|
|
257
|
+
*
|
|
258
|
+
* @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).
|
|
259
|
+
* @returns Effect that succeeds with `Option.some(reactive)` or `Option.none()`.
|
|
260
|
+
*/
|
|
261
|
+
export const getReactiveOption = <T extends Unknown>(snapshot: Snapshot<T>): Effect.Effect<Option.Option<T>, never> =>
|
|
262
|
+
getReactive(snapshot).pipe(
|
|
263
|
+
Effect.map(Option.some),
|
|
264
|
+
Effect.catchAll(() => Effect.succeed(Option.none())),
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Synchronous version of `Obj.getReactive`. Returns the reactive object or throws
|
|
269
|
+
* `GetReactiveError` when the object cannot be resolved (no database, object not found).
|
|
270
|
+
*
|
|
271
|
+
* @param snapshot - A snapshot of the object (from `Obj.getSnapshot`).
|
|
272
|
+
* @returns The reactive object.
|
|
273
|
+
* @throws {Err.GetReactiveError} When the object cannot be resolved.
|
|
274
|
+
*/
|
|
275
|
+
export const getReactiveOrThrow = <T extends Unknown>(snapshot: Snapshot<T>): T =>
|
|
276
|
+
Effect.runSync(getReactive(snapshot));
|
|
277
|
+
|
|
210
278
|
export type CloneOptions = {
|
|
211
279
|
/**
|
|
212
280
|
* Retain the original object's ID.
|
|
@@ -316,7 +384,7 @@ export const getValue = (obj: Unknown | Snapshot, path: readonly (string | numbe
|
|
|
316
384
|
* @example
|
|
317
385
|
* ```ts
|
|
318
386
|
* const person = Obj.make(Person, { name: 'John' });
|
|
319
|
-
* // Person schema has: addresses: Schema.
|
|
387
|
+
* // Person schema has: addresses: Schema.Array(Address)
|
|
320
388
|
* Obj.change(person, (p) => {
|
|
321
389
|
* Obj.setValue(p, ['addresses', 0, 'street'], '123 Main St');
|
|
322
390
|
* });
|
|
@@ -357,6 +425,33 @@ export const instanceOf: {
|
|
|
357
425
|
return isInstanceOf(args[0], args[1]);
|
|
358
426
|
}) as any;
|
|
359
427
|
|
|
428
|
+
/**
|
|
429
|
+
* Test if a snapshot is an instance of a schema.
|
|
430
|
+
* Mirrors `instanceOf` but only accepts values branded with SnapshotKindId.
|
|
431
|
+
* Use when the value is known to be a snapshot (e.g. from `getSnapshot` or `useObject`).
|
|
432
|
+
*
|
|
433
|
+
* @example
|
|
434
|
+
* ```ts
|
|
435
|
+
* const snapshot = Obj.getSnapshot(person);
|
|
436
|
+
* if (Obj.snapshotOf(Person, snapshot)) {
|
|
437
|
+
* // snapshot is Obj.Snapshot<Person>
|
|
438
|
+
* }
|
|
439
|
+
* ```
|
|
440
|
+
*/
|
|
441
|
+
export const snapshotOf: {
|
|
442
|
+
<S extends Type.Entity.Any>(schema: S): (value: unknown) => value is Snapshot<Schema.Schema.Type<S>>;
|
|
443
|
+
<S extends Type.Entity.Any>(schema: S, value: unknown): value is Snapshot<Schema.Schema.Type<S>>;
|
|
444
|
+
} = ((...args: [schema: Type.Entity.Any, value: unknown] | [schema: Type.Entity.Any]) => {
|
|
445
|
+
const check = (entity: unknown) =>
|
|
446
|
+
entity != null && typeof entity === 'object' && SnapshotKindId in entity && isInstanceOf(args[0], entity);
|
|
447
|
+
|
|
448
|
+
if (args.length === 1) {
|
|
449
|
+
return (entity: unknown) => check(entity);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return check(args[1]);
|
|
453
|
+
}) as any;
|
|
454
|
+
|
|
360
455
|
// TODO(dmaretskyi): Allow returning undefined.
|
|
361
456
|
/**
|
|
362
457
|
* Get the DXN of the object.
|
|
@@ -396,7 +491,8 @@ export const getTypename = (entity: Unknown | Snapshot): string | undefined => g
|
|
|
396
491
|
* Get the database the object belongs to.
|
|
397
492
|
* Accepts both reactive objects and snapshots.
|
|
398
493
|
*/
|
|
399
|
-
export const getDatabase = (entity: Unknown | Snapshot): Database.Database | undefined =>
|
|
494
|
+
export const getDatabase = (entity: Entity.Unknown | Entity.Snapshot): Database.Database | undefined =>
|
|
495
|
+
getDatabase$(entity);
|
|
400
496
|
|
|
401
497
|
//
|
|
402
498
|
// Meta
|
|
@@ -436,9 +532,9 @@ export type Meta = ApiMeta;
|
|
|
436
532
|
* ```
|
|
437
533
|
*/
|
|
438
534
|
// TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
|
|
439
|
-
export function getMeta(entity: Mutable<Unknown>):
|
|
535
|
+
export function getMeta(entity: Mutable<Unknown>): Meta;
|
|
440
536
|
export function getMeta(entity: Unknown | Snapshot): ReadonlyMeta;
|
|
441
|
-
export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>):
|
|
537
|
+
export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): Meta | ReadonlyMeta {
|
|
442
538
|
return getMeta$(entity);
|
|
443
539
|
}
|
|
444
540
|
|
|
@@ -520,6 +616,43 @@ export const getDescription = (entity: Unknown | Snapshot): string | undefined =
|
|
|
520
616
|
export const setDescription = (entity: Mutable<Unknown>, description: string): void =>
|
|
521
617
|
setDescription$(entity, description);
|
|
522
618
|
|
|
619
|
+
/**
|
|
620
|
+
* Symbol to set parent when creating objects with `Obj.make`.
|
|
621
|
+
* @example
|
|
622
|
+
* ```ts
|
|
623
|
+
* Obj.make(TestSchema.Person, {
|
|
624
|
+
* [Obj.Parent]: parentObject,
|
|
625
|
+
* name: 'John',
|
|
626
|
+
* })
|
|
627
|
+
* ```
|
|
628
|
+
*/
|
|
629
|
+
export const Parent: unique symbol = ParentId as any;
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Get the parent of an object.
|
|
633
|
+
* The parent is always loaded together with the object.
|
|
634
|
+
* Only objects are allowed to have a parent
|
|
635
|
+
* @returns The parent object, or undefined if the object has no parent.
|
|
636
|
+
*/
|
|
637
|
+
export const getParent = (entity: Unknown | Snapshot): Unknown | undefined => {
|
|
638
|
+
assertArgument(isObject(entity), 'Expected an object');
|
|
639
|
+
assumeType<InternalObjectProps>(entity);
|
|
640
|
+
return entity[ParentId] as Unknown | undefined;
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Sets the parent of an object.
|
|
645
|
+
* If a parent (or any transitive parent) is deleted, the object will be deleted.
|
|
646
|
+
* Only objects are allowed to have a parent.
|
|
647
|
+
*/
|
|
648
|
+
export const setParent = (entity: Unknown, parent: Any | undefined) => {
|
|
649
|
+
assertArgument(isObject(entity), 'Expected an object');
|
|
650
|
+
assertArgument(parent === undefined || isObject(parent), 'Expected an object');
|
|
651
|
+
assumeType<InternalObjectProps>(entity);
|
|
652
|
+
assumeType<InternalObjectProps | undefined>(parent);
|
|
653
|
+
entity[ParentId] = parent;
|
|
654
|
+
};
|
|
655
|
+
|
|
523
656
|
//
|
|
524
657
|
// JSON
|
|
525
658
|
//
|
|
@@ -549,10 +682,6 @@ export const toJSON = (entity: Unknown | Snapshot): JSON => toJSON$(entity);
|
|
|
549
682
|
export const fromJSON: (json: unknown, options?: { refResolver?: Ref.Resolver; dxn?: DXN }) => Promise<Unknown> =
|
|
550
683
|
objectFromJSON as any;
|
|
551
684
|
|
|
552
|
-
//
|
|
553
|
-
// Sorting
|
|
554
|
-
//
|
|
555
|
-
|
|
556
685
|
/**
|
|
557
686
|
* Comparator function type for sorting objects.
|
|
558
687
|
* Accepts both reactive objects and snapshots.
|
package/src/Query.ts
CHANGED
|
@@ -102,6 +102,18 @@ export interface Query<T> {
|
|
|
102
102
|
*/
|
|
103
103
|
target(): Query<Type$.Relation.Target<T>>;
|
|
104
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Get the parent object of the current selection.
|
|
107
|
+
* @returns Query for the parent objects.
|
|
108
|
+
*/
|
|
109
|
+
parent(): Query<any>;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get all child objects of the current selection.
|
|
113
|
+
* @returns Query for the child objects.
|
|
114
|
+
*/
|
|
115
|
+
children(): Query<any>;
|
|
116
|
+
|
|
105
117
|
/**
|
|
106
118
|
* Order the query results.
|
|
107
119
|
* Orders are specified in priority order. The first order will be applied first, etc.
|
|
@@ -202,6 +214,22 @@ class QueryClass implements Any {
|
|
|
202
214
|
});
|
|
203
215
|
}
|
|
204
216
|
|
|
217
|
+
parent(): Any {
|
|
218
|
+
return new QueryClass({
|
|
219
|
+
type: 'hierarchy-traversal',
|
|
220
|
+
anchor: this.ast,
|
|
221
|
+
direction: 'to-parent',
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
children(): Any {
|
|
226
|
+
return new QueryClass({
|
|
227
|
+
type: 'hierarchy-traversal',
|
|
228
|
+
anchor: this.ast,
|
|
229
|
+
direction: 'to-children',
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
205
233
|
orderBy(...order: Order.Order<any>[]): Any {
|
|
206
234
|
return new QueryClass({
|
|
207
235
|
type: 'order',
|
package/src/Relation.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
MetaId,
|
|
30
30
|
type Mutable,
|
|
31
31
|
type ObjectMeta,
|
|
32
|
+
ParentId,
|
|
32
33
|
RelationSourceDXNId,
|
|
33
34
|
RelationSourceId,
|
|
34
35
|
RelationTargetDXNId,
|
|
@@ -133,7 +134,7 @@ export type MakeProps<S extends Type.Relation.Any> = RelationMakeProps<Schema.Sc
|
|
|
133
134
|
* Creates new relation.
|
|
134
135
|
* @param schema - Relation schema.
|
|
135
136
|
* @param props - Relation properties. Endpoints are passed as [Relation.Source] and [Relation.Target] keys.
|
|
136
|
-
* @param meta - Relation metadata.
|
|
137
|
+
* @param meta - Relation metadata. (deprecated; use [Obj.Meta] instead)
|
|
137
138
|
* @returns
|
|
138
139
|
*/
|
|
139
140
|
// NOTE: Writing the definition this way (with generic over schema) makes typescript perfer to infer the type from the first param (this schema) rather than the second param (the props).
|
|
@@ -144,6 +145,7 @@ export const make = <S extends Type.Relation.Any>(
|
|
|
144
145
|
meta?: ObjectMeta,
|
|
145
146
|
): Schema.Schema.Type<S> & Entity.OfKind<typeof Entity.Kind.Relation> => {
|
|
146
147
|
assertArgument(getTypeAnnotation(schema)?.kind === EntityKind.Relation, 'schema', 'Expected a relation schema');
|
|
148
|
+
assertArgument(props[ParentId] === undefined, 'props', 'Parent is not allowed for relations');
|
|
147
149
|
|
|
148
150
|
if (props[MetaId] != null) {
|
|
149
151
|
meta = props[MetaId] as any;
|
|
@@ -372,9 +374,9 @@ export type Meta = ApiMeta;
|
|
|
372
374
|
* Returns read-only meta when passed a regular relation or snapshot.
|
|
373
375
|
*/
|
|
374
376
|
// TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
|
|
375
|
-
export function getMeta(entity: Mutable<Unknown>):
|
|
377
|
+
export function getMeta(entity: Mutable<Unknown>): Meta;
|
|
376
378
|
export function getMeta(entity: Unknown | Snapshot): ReadonlyMeta;
|
|
377
|
-
export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>):
|
|
379
|
+
export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): Meta | ReadonlyMeta {
|
|
378
380
|
return getMeta$(entity);
|
|
379
381
|
}
|
|
380
382
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import * as Obj from './Obj';
|
|
8
|
+
import { TestSchema } from './testing';
|
|
9
|
+
|
|
10
|
+
describe('Hierarchy', () => {
|
|
11
|
+
test('setParent and getParent', async () => {
|
|
12
|
+
const parent = Obj.make(TestSchema.Organization, { name: 'parent' });
|
|
13
|
+
const child = Obj.make(TestSchema.Person, { name: 'child' });
|
|
14
|
+
expect(Obj.getParent(child)).toBeUndefined();
|
|
15
|
+
|
|
16
|
+
Obj.setParent(child, parent);
|
|
17
|
+
expect(Obj.getParent(child)).toBe(parent);
|
|
18
|
+
|
|
19
|
+
Obj.setParent(child, undefined);
|
|
20
|
+
expect(Obj.getParent(child)).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('create object with Obj.Parent in props', () => {
|
|
24
|
+
const parent = Obj.make(TestSchema.Organization, { name: 'DXOS' });
|
|
25
|
+
const child = Obj.make(TestSchema.Person, {
|
|
26
|
+
[Obj.Parent]: parent,
|
|
27
|
+
name: 'John',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(child.name).toBe('John');
|
|
31
|
+
expect(Obj.getParent(child)).toBe(parent);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -15,7 +15,7 @@ import { type Primitive } from '@dxos/util';
|
|
|
15
15
|
|
|
16
16
|
import { type AnyProperties, EntityKind, TypeId, getSchema } from '../types';
|
|
17
17
|
|
|
18
|
-
import { createAnnotationHelper } from './util';
|
|
18
|
+
import { type AnnotationHelper, createAnnotationHelper } from './util';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* @internal
|
|
@@ -458,3 +458,30 @@ export type GeneratorAnnotationValue =
|
|
|
458
458
|
};
|
|
459
459
|
|
|
460
460
|
export const GeneratorAnnotation = createAnnotationHelper<GeneratorAnnotationValue>(GeneratorAnnotationId);
|
|
461
|
+
|
|
462
|
+
interface MakeAnnoationsProps<T> {
|
|
463
|
+
id: string;
|
|
464
|
+
schema: Schema.Schema<T, any, never>;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// TODO(wittjosiah): Comment.
|
|
468
|
+
export const makeUserAnnotation = <T>(props: MakeAnnoationsProps<T>): AnnotationHelper<T> => {
|
|
469
|
+
assertArgument(
|
|
470
|
+
/[a-zA-Z0-9]+\.[a-zA-Z.]+\/[a-zA-Z/]+/.test(props.id),
|
|
471
|
+
'id',
|
|
472
|
+
'Annotation id must be in the FQN format (dxos.org/annotation/Example).',
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
const getFromAst = (ast: SchemaAST.AST) =>
|
|
476
|
+
SchemaAST.getAnnotation<PropertyMetaAnnotation>(PropertyMetaAnnotationId)(ast).pipe(
|
|
477
|
+
Option.map((meta) => meta[props.id] as unknown),
|
|
478
|
+
Option.map(Schema.decodeUnknownSync(props.schema)),
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
return {
|
|
482
|
+
get: (schema) => getFromAst(schema.ast),
|
|
483
|
+
getFromAst: (ast) => getFromAst(ast),
|
|
484
|
+
set: (value) =>
|
|
485
|
+
PropertyMeta(props.id, Schema.encodeSync(props.schema)(value)) as <S extends Schema.Schema.Any>(schema: S) => S,
|
|
486
|
+
};
|
|
487
|
+
};
|
|
@@ -12,11 +12,24 @@ import { DXN } from '@dxos/keys';
|
|
|
12
12
|
import { EntityKind } from '../types';
|
|
13
13
|
|
|
14
14
|
export interface AnnotationHelper<T> {
|
|
15
|
+
/**
|
|
16
|
+
* Get the annotation value from the schema.
|
|
17
|
+
*/
|
|
15
18
|
get: (schema: Schema.Schema.Any) => Option.Option<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the annotation value from the AST.
|
|
21
|
+
*/
|
|
16
22
|
getFromAst: (ast: SchemaAST.AST) => Option.Option<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Set the annotation value on the schema.
|
|
25
|
+
*/
|
|
17
26
|
set: (value: T) => <S extends Schema.Schema.Any>(schema: S) => S;
|
|
18
27
|
}
|
|
19
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Note: only for system annotations.
|
|
31
|
+
*/
|
|
32
|
+
// TODO(dmaretskyi): Rename to createSystemAnnotationHelper.
|
|
20
33
|
export const createAnnotationHelper = <T>(id: symbol): AnnotationHelper<T> => {
|
|
21
34
|
return {
|
|
22
35
|
get: (schema) => SchemaAST.getAnnotation(schema.ast, id),
|
package/src/internal/api/meta.ts
CHANGED
|
@@ -17,7 +17,7 @@ export type ReadonlyMeta = DeepReadonly<ObjectMeta>;
|
|
|
17
17
|
/**
|
|
18
18
|
* Mutable meta type received in meta mutation callbacks.
|
|
19
19
|
*/
|
|
20
|
-
export type Meta = ObjectMeta
|
|
20
|
+
export type Meta = Mutable<ObjectMeta>;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Get the metadata for an entity with validation.
|
|
@@ -26,9 +26,9 @@ export type Meta = ObjectMeta;
|
|
|
26
26
|
*
|
|
27
27
|
* TODO(burdon): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
|
|
28
28
|
*/
|
|
29
|
-
export function getMetaChecked(entity: Mutable<AnyProperties>):
|
|
29
|
+
export function getMetaChecked(entity: Mutable<AnyProperties>): Meta;
|
|
30
30
|
export function getMetaChecked(entity: AnyProperties): ReadonlyMeta;
|
|
31
|
-
export function getMetaChecked(entity: AnyProperties):
|
|
31
|
+
export function getMetaChecked(entity: AnyProperties): Meta | ReadonlyMeta {
|
|
32
32
|
assertArgument(entity, 'entity', 'Should be an entity.');
|
|
33
33
|
const meta = getMeta$(entity);
|
|
34
34
|
invariant(meta != null, 'Invalid entity.');
|
|
@@ -12,11 +12,13 @@ import { assumeType } from '@dxos/util';
|
|
|
12
12
|
import type * as Database from '../../Database';
|
|
13
13
|
import {
|
|
14
14
|
type ATTR_META,
|
|
15
|
+
type ATTR_PARENT,
|
|
15
16
|
type ATTR_TYPE,
|
|
16
17
|
EntityKind,
|
|
17
18
|
KindId,
|
|
18
19
|
type MetaId,
|
|
19
20
|
type ObjectMeta,
|
|
21
|
+
type ParentId,
|
|
20
22
|
type SchemaId,
|
|
21
23
|
TypeId,
|
|
22
24
|
type Version,
|
|
@@ -77,6 +79,7 @@ export interface InternalObjectProps {
|
|
|
77
79
|
readonly [SchemaId]: Schema.Schema.AnyNoContext;
|
|
78
80
|
readonly [TypeId]: DXN;
|
|
79
81
|
readonly [MetaId]?: ObjectMeta;
|
|
82
|
+
[ParentId]?: InternalObjectProps;
|
|
80
83
|
readonly [ObjectDatabaseId]?: Database.Database;
|
|
81
84
|
readonly [ObjectDeletedId]?: boolean;
|
|
82
85
|
readonly [ObjectVersionId]?: Version;
|
|
@@ -101,6 +104,7 @@ export interface ObjectJSON {
|
|
|
101
104
|
id: string;
|
|
102
105
|
[ATTR_TYPE]: DXN.String;
|
|
103
106
|
[ATTR_SELF_DXN]?: DXN.String;
|
|
107
|
+
[ATTR_PARENT]?: string; // Encoded reference
|
|
104
108
|
[ATTR_DELETED]?: boolean;
|
|
105
109
|
[ATTR_META]?: ObjectMetaJSON;
|
|
106
110
|
[ATTR_RELATION_SOURCE]?: DXN.String;
|
|
@@ -40,9 +40,7 @@ export const EchoObjectSchema: {
|
|
|
40
40
|
// Extract fields from the schema if available (Struct schemas have .fields).
|
|
41
41
|
const fields = ((self as any).fields ?? {}) as Fields;
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
// TODO(dmaretskyi): Do not do mutable here.
|
|
45
|
-
const schemaWithId = Schema.extend(Schema.mutable(self), Schema.Struct({ id: Schema.String }));
|
|
43
|
+
const schemaWithId = Schema.extend(self, Schema.Struct({ id: Schema.String }));
|
|
46
44
|
const ast = SchemaAST.annotations(schemaWithId.ast, {
|
|
47
45
|
// TODO(dmaretskyi): `extend` kills the annotations.
|
|
48
46
|
...self.ast.annotations,
|
|
@@ -129,9 +129,7 @@ export const EchoRelationSchema = <
|
|
|
129
129
|
// Extract fields from the schema if available (Struct schemas have .fields).
|
|
130
130
|
const fields = ((self as any).fields ?? {}) as Fields;
|
|
131
131
|
|
|
132
|
-
|
|
133
|
-
// TODO(dmaretskyi): Do not do mutable here.
|
|
134
|
-
const schemaWithId = Schema.extend(Schema.mutable(self), Schema.Struct({ id: Schema.String }));
|
|
132
|
+
const schemaWithId = Schema.extend(self, Schema.Struct({ id: Schema.String }));
|
|
135
133
|
const ast = SchemaAST.annotations(schemaWithId.ast, {
|
|
136
134
|
// TODO(dmaretskyi): `extend` kills the annotations.
|
|
137
135
|
...self.ast.annotations,
|
|
@@ -135,7 +135,7 @@ export const typeToFormat: Partial<Record<TypeEnum, TypeFormat>> = {
|
|
|
135
135
|
* Map of format to type.
|
|
136
136
|
*/
|
|
137
137
|
export const formatToType: Record<TypeFormat, TypeEnum> = {
|
|
138
|
-
[TypeFormat.None]:
|
|
138
|
+
[TypeFormat.None]: TypeEnum.String,
|
|
139
139
|
[TypeFormat.String]: TypeEnum.String,
|
|
140
140
|
[TypeFormat.Number]: TypeEnum.Number,
|
|
141
141
|
[TypeFormat.Boolean]: TypeEnum.Boolean,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import type * as Types from 'effect/Types';
|
|
6
|
+
|
|
5
7
|
import { JsonSchemaFields, type JsonSchemaType } from './json-schema-type';
|
|
6
8
|
|
|
7
9
|
/**
|
|
@@ -9,12 +11,12 @@ import { JsonSchemaFields, type JsonSchemaType } from './json-schema-type';
|
|
|
9
11
|
* Note: the input type does not necessarily match the {@link JsonSchemaType} type.
|
|
10
12
|
*/
|
|
11
13
|
export const normalizeSchema = (schema: JsonSchemaType): JsonSchemaType => {
|
|
12
|
-
const copy = structuredClone(schema)
|
|
14
|
+
const copy = structuredClone(schema) as Types.DeepMutable<JsonSchemaType>;
|
|
13
15
|
go(copy);
|
|
14
16
|
return copy;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
const go = (schema: JsonSchemaType) => {
|
|
19
|
+
const go = (schema: Types.DeepMutable<JsonSchemaType>) => {
|
|
18
20
|
if (typeof schema !== 'object' || schema === null) {
|
|
19
21
|
return;
|
|
20
22
|
}
|