jazz-tools 0.19.2 → 0.19.4

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 (89) hide show
  1. package/.svelte-kit/__package__/jazz.class.svelte.d.ts +2 -2
  2. package/.svelte-kit/__package__/jazz.class.svelte.d.ts.map +1 -1
  3. package/.svelte-kit/__package__/jazz.class.svelte.js +15 -17
  4. package/.turbo/turbo-build.log +54 -54
  5. package/CHANGELOG.md +24 -0
  6. package/dist/{chunk-NCNM6UDZ.js → chunk-PT7FCV26.js} +148 -78
  7. package/dist/chunk-PT7FCV26.js.map +1 -0
  8. package/dist/index.js +14 -7
  9. package/dist/index.js.map +1 -1
  10. package/dist/inspector/{custom-element-ABVPHX53.js → custom-element-P76EIWEV.js} +322 -146
  11. package/dist/inspector/custom-element-P76EIWEV.js.map +1 -0
  12. package/dist/inspector/index.js +302 -126
  13. package/dist/inspector/index.js.map +1 -1
  14. package/dist/inspector/register-custom-element.js +1 -1
  15. package/dist/inspector/tests/viewer/co-plain-text-view.test.d.ts +2 -0
  16. package/dist/inspector/tests/viewer/co-plain-text-view.test.d.ts.map +1 -0
  17. package/dist/inspector/utils/history.d.ts +5 -1
  18. package/dist/inspector/utils/history.d.ts.map +1 -1
  19. package/dist/inspector/utils/permissions.d.ts +3 -0
  20. package/dist/inspector/utils/permissions.d.ts.map +1 -0
  21. package/dist/inspector/viewer/co-map-view.d.ts.map +1 -1
  22. package/dist/inspector/viewer/co-plain-text-view.d.ts +4 -2
  23. package/dist/inspector/viewer/co-plain-text-view.d.ts.map +1 -1
  24. package/dist/inspector/viewer/grid-view.d.ts.map +1 -1
  25. package/dist/inspector/viewer/page.d.ts.map +1 -1
  26. package/dist/inspector/viewer/use-resolve-covalue.d.ts +0 -1
  27. package/dist/inspector/viewer/use-resolve-covalue.d.ts.map +1 -1
  28. package/dist/react-core/hooks.d.ts.map +1 -1
  29. package/dist/react-core/index.js +4 -17
  30. package/dist/react-core/index.js.map +1 -1
  31. package/dist/svelte/jazz.class.svelte.d.ts +2 -2
  32. package/dist/svelte/jazz.class.svelte.d.ts.map +1 -1
  33. package/dist/svelte/jazz.class.svelte.js +15 -17
  34. package/dist/testing.js +1 -1
  35. package/dist/tools/coValues/coFeed.d.ts.map +1 -1
  36. package/dist/tools/coValues/group.d.ts.map +1 -1
  37. package/dist/tools/coValues/interfaces.d.ts +7 -6
  38. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  39. package/dist/tools/coValues/promise.d.ts +9 -0
  40. package/dist/tools/coValues/promise.d.ts.map +1 -0
  41. package/dist/tools/coValues/request.d.ts.map +1 -1
  42. package/dist/tools/exports.d.ts +1 -1
  43. package/dist/tools/exports.d.ts.map +1 -1
  44. package/dist/tools/implementation/refs.d.ts +1 -1
  45. package/dist/tools/implementation/refs.d.ts.map +1 -1
  46. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +3 -1
  47. package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -1
  48. package/dist/tools/implementation/zodSchema/unionUtils.d.ts.map +1 -1
  49. package/dist/tools/subscribe/SubscriptionScope.d.ts +5 -2
  50. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  51. package/dist/tools/subscribe/index.d.ts +1 -1
  52. package/dist/tools/subscribe/index.d.ts.map +1 -1
  53. package/dist/tools/subscribe/types.d.ts +2 -1
  54. package/dist/tools/subscribe/types.d.ts.map +1 -1
  55. package/dist/tools/tests/SubscriptionScope.test.d.ts +2 -0
  56. package/dist/tools/tests/SubscriptionScope.test.d.ts.map +1 -0
  57. package/package.json +4 -4
  58. package/src/inspector/tests/utils/history.test.ts +233 -2
  59. package/src/inspector/tests/viewer/co-plain-text-view.test.tsx +125 -0
  60. package/src/inspector/tests/viewer/comap-view.test.tsx +309 -1
  61. package/src/inspector/tests/viewer/history-view.test.tsx +134 -2
  62. package/src/inspector/utils/history.ts +168 -1
  63. package/src/inspector/utils/permissions.ts +10 -0
  64. package/src/inspector/viewer/co-map-view.tsx +27 -15
  65. package/src/inspector/viewer/co-plain-text-view.tsx +102 -3
  66. package/src/inspector/viewer/grid-view.tsx +2 -1
  67. package/src/inspector/viewer/history-view.tsx +5 -23
  68. package/src/inspector/viewer/page.tsx +8 -1
  69. package/src/inspector/viewer/use-resolve-covalue.ts +2 -6
  70. package/src/react-core/hooks.ts +5 -29
  71. package/src/svelte/jazz.class.svelte.ts +16 -34
  72. package/src/tools/coValues/coFeed.ts +10 -7
  73. package/src/tools/coValues/coMap.ts +10 -7
  74. package/src/tools/coValues/group.ts +6 -2
  75. package/src/tools/coValues/interfaces.ts +48 -28
  76. package/src/tools/coValues/promise.ts +34 -0
  77. package/src/tools/coValues/request.ts +12 -8
  78. package/src/tools/exports.ts +1 -0
  79. package/src/tools/implementation/refs.ts +9 -17
  80. package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +62 -30
  81. package/src/tools/implementation/zodSchema/unionUtils.ts +3 -4
  82. package/src/tools/subscribe/SubscriptionScope.ts +45 -2
  83. package/src/tools/subscribe/index.ts +28 -13
  84. package/src/tools/subscribe/types.ts +5 -2
  85. package/src/tools/tests/SubscriptionScope.test.ts +397 -0
  86. package/src/tools/tests/deepLoading.test.ts +22 -0
  87. package/src/tools/tests/subscribe.test.ts +69 -0
  88. package/dist/chunk-NCNM6UDZ.js.map +0 -1
  89. package/dist/inspector/custom-element-ABVPHX53.js.map +0 -1
@@ -6,6 +6,7 @@ import { Button, Icon, Input, Modal } from "../ui";
6
6
  import { styled } from "goober";
7
7
  import { restoreCoMapToTimestamp } from "../utils/history";
8
8
  import { CoValueEditor } from "./co-value-editor.js";
9
+ import { isWriter } from "../utils/permissions";
9
10
 
10
11
  export function CoMapView({
11
12
  coValue,
@@ -27,7 +28,11 @@ export function CoMapView({
27
28
  coValue={coValue}
28
29
  />
29
30
  <div>
30
- <AddPropertyModal coValue={coValue} node={node} />{" "}
31
+ <AddPropertyModal
32
+ disabled={!isWriter(coValue.group.myRole())}
33
+ coValue={coValue}
34
+ node={node}
35
+ />{" "}
31
36
  <RestoreSnapshotModal coValue={coValue} />
32
37
  </div>
33
38
  </>
@@ -37,9 +42,11 @@ export function CoMapView({
37
42
  function AddPropertyModal({
38
43
  coValue,
39
44
  node,
45
+ disabled,
40
46
  }: {
41
47
  coValue: RawCoMap;
42
48
  node: LocalNode;
49
+ disabled: boolean;
43
50
  }) {
44
51
  const [isAddPropertyModalOpen, setIsAddPropertyModalOpen] = useState(false);
45
52
  const [propertyName, setPropertyName] = useState("");
@@ -59,9 +66,10 @@ function AddPropertyModal({
59
66
  <Button
60
67
  title="Add Property"
61
68
  variant="secondary"
69
+ disabled={disabled}
62
70
  onClick={openAddPropertyModal}
63
71
  >
64
- <Icon name="edit" />
72
+ <Icon name="add" />
65
73
  </Button>
66
74
 
67
75
  <Modal
@@ -132,6 +140,8 @@ function RestoreSnapshotModal({ coValue }: { coValue: RawCoMap }) {
132
140
  setIsRestoreModalOpen(false);
133
141
  };
134
142
 
143
+ const canRestore = isWriter(coValue.group.myRole());
144
+
135
145
  return (
136
146
  <>
137
147
  <Button title="Timeline" variant="secondary" onClick={openRestoreModal}>
@@ -146,7 +156,7 @@ function RestoreSnapshotModal({ coValue }: { coValue: RawCoMap }) {
146
156
  cancelText="Cancel"
147
157
  onConfirm={handleRestore}
148
158
  onCancel={handleClose}
149
- showButtons={timestamps.length > 1}
159
+ showButtons={timestamps.length > 1 && canRestore}
150
160
  >
151
161
  {timestamps.length > 1 && (
152
162
  <>
@@ -167,18 +177,20 @@ function RestoreSnapshotModal({ coValue }: { coValue: RawCoMap }) {
167
177
  </TimestampDisplay>
168
178
  </RangeContainer>
169
179
 
170
- <CheckboxContainer>
171
- <CheckboxInput
172
- type="checkbox"
173
- id="remove-unknown-properties"
174
- checked={removeUnknownProperties}
175
- onChange={(e) => setRemoveUnknownProperties(e.target.checked)}
176
- />
177
- <CheckboxLabel htmlFor="remove-unknown-properties">
178
- Remove unknown properties (properties that don't exist in the
179
- selected snapshot)
180
- </CheckboxLabel>
181
- </CheckboxContainer>
180
+ {canRestore && (
181
+ <CheckboxContainer>
182
+ <CheckboxInput
183
+ type="checkbox"
184
+ id="remove-unknown-properties"
185
+ checked={removeUnknownProperties}
186
+ onChange={(e) => setRemoveUnknownProperties(e.target.checked)}
187
+ />
188
+ <CheckboxLabel htmlFor="remove-unknown-properties">
189
+ Remove unknown properties (properties that don't exist in the
190
+ selected snapshot)
191
+ </CheckboxLabel>
192
+ </CheckboxContainer>
193
+ )}
182
194
  </>
183
195
  )}
184
196
 
@@ -1,13 +1,112 @@
1
- import { JsonObject } from "cojson";
1
+ import { JsonObject, LocalNode, RawCoPlainText } from "cojson";
2
+ import { useState } from "react";
3
+ import { styled } from "goober";
4
+ import { CoPlainText } from "jazz-tools";
5
+ import { isWriter } from "../utils/permissions.js";
6
+ import { Button } from "../ui/button.js";
2
7
  import { RawDataCard } from "./raw-data-card.js";
8
+ import { Icon } from "../ui/icon.js";
9
+
10
+ export function CoPlainTextView({
11
+ data,
12
+ coValue,
13
+ }: {
14
+ data: JsonObject;
15
+ coValue: RawCoPlainText;
16
+ node: LocalNode;
17
+ }) {
18
+ const currentText = Object.values(data).join("");
19
+ const [isEditing, setIsEditing] = useState(false);
20
+ const [editValue, setEditValue] = useState("");
21
+ const canEdit = isWriter(coValue.group.myRole());
22
+
23
+ const handleEditClick = () => {
24
+ setIsEditing(true);
25
+ setEditValue(currentText);
26
+ };
27
+
28
+ const handleCancel = () => {
29
+ setIsEditing(false);
30
+ setEditValue(currentText);
31
+ };
32
+
33
+ const handleSave = (e: React.FormEvent) => {
34
+ e.preventDefault();
35
+ e.stopPropagation();
36
+
37
+ const coPlainText = CoPlainText.fromRaw(coValue);
38
+ coPlainText.$jazz.applyDiff(editValue);
39
+
40
+ setIsEditing(false);
41
+ };
3
42
 
4
- export function CoPlainTextView({ data }: { data: JsonObject }) {
5
43
  if (!data) return;
6
44
 
45
+ if (isEditing) {
46
+ return (
47
+ <>
48
+ <EditForm onSubmit={handleSave}>
49
+ <StyledTextarea
50
+ value={editValue}
51
+ onChange={(e) => setEditValue(e.target.value)}
52
+ onClick={(e) => e.stopPropagation()}
53
+ />
54
+ <FormActions>
55
+ <Button type="button" variant="secondary" onClick={handleCancel}>
56
+ Cancel
57
+ </Button>
58
+ <Button type="submit" variant="primary">
59
+ Save
60
+ </Button>
61
+ </FormActions>
62
+ </EditForm>
63
+ <RawDataCard data={data} />
64
+ </>
65
+ );
66
+ }
67
+
7
68
  return (
8
69
  <>
9
- <p>{Object.values(data).join("")}</p>
70
+ <p>{currentText}</p>
71
+ <div>
72
+ {canEdit && (
73
+ <Button variant="secondary" onClick={handleEditClick} title="Edit">
74
+ <Icon name="edit" />
75
+ </Button>
76
+ )}
77
+ </div>
10
78
  <RawDataCard data={data} />
11
79
  </>
12
80
  );
13
81
  }
82
+
83
+ const EditForm = styled("form")`
84
+ display: flex;
85
+ flex-direction: column;
86
+ gap: 0.75rem;
87
+ margin-bottom: 1rem;
88
+ `;
89
+
90
+ const StyledTextarea = styled("textarea")`
91
+ width: 100%;
92
+ min-height: 120px;
93
+ border-radius: var(--j-radius-md);
94
+ border: 1px solid var(--j-border-color);
95
+ padding: 0.5rem 0.875rem;
96
+ box-shadow: var(--j-shadow-sm);
97
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
98
+ font-size: 0.875rem;
99
+ background-color: white;
100
+ color: var(--j-text-color-strong);
101
+ resize: vertical;
102
+
103
+ @media (prefers-color-scheme: dark) {
104
+ background-color: var(--j-foreground);
105
+ }
106
+ `;
107
+
108
+ const FormActions = styled("div")`
109
+ display: flex;
110
+ gap: 0.5rem;
111
+ justify-content: flex-end;
112
+ `;
@@ -12,6 +12,7 @@ import { Card, CardBody, CardHeader } from "../ui/card.js";
12
12
  import { Grid } from "../ui/grid.js";
13
13
  import { Icon } from "../ui/icon.js";
14
14
  import { Text } from "../ui/text.js";
15
+ import { isWriter } from "../utils/permissions.js";
15
16
 
16
17
  function GridItem({
17
18
  entry,
@@ -115,7 +116,7 @@ function GridItem({
115
116
  <Text strong>{key}</Text>
116
117
  )}
117
118
  </div>
118
- {coValue && (
119
+ {coValue && isWriter(coValue.group.myRole()) && (
119
120
  <ActionButtons>
120
121
  <EditButton
121
122
  onClick={handleEditClick}
@@ -3,9 +3,9 @@ import { useMemo } from "react";
3
3
  import { styled } from "goober";
4
4
  import { AccountOrGroupText } from "./account-or-group-text";
5
5
  import { DataTable, ColumnDef } from "../ui/data-table";
6
- import type { VerifiedTransaction } from "cojson/dist/coValueCore/coValueCore.js";
7
6
  import { Icon, Accordion } from "../ui";
8
7
  import * as TransactionChanges from "../utils/transactions-changes";
8
+ import { getTransactionChanges } from "../utils/history";
9
9
 
10
10
  type HistoryEntry = {
11
11
  id: string;
@@ -108,28 +108,6 @@ export function HistoryView({
108
108
  );
109
109
  }
110
110
 
111
- function getTransactionChanges(
112
- tx: VerifiedTransaction,
113
- coValue: RawCoValue,
114
- ): JsonValue[] {
115
- if (tx.isValid === false && tx.tx.privacy === "private") {
116
- const readKey = coValue.core.getReadKey(tx.tx.keyUsed);
117
- if (!readKey) {
118
- throw new Error("Read key not found");
119
- }
120
-
121
- return (
122
- coValue.core.verified.decryptTransaction(
123
- tx.txID.sessionID,
124
- tx.txID.txIndex,
125
- readKey,
126
- ) ?? []
127
- );
128
- }
129
-
130
- return tx.changes ?? (tx.tx as any).changes ?? [];
131
- }
132
-
133
111
  function getHistory(coValue: RawCoValue): HistoryEntry[] {
134
112
  return coValue.core.verifiedTransactions.flatMap((tx, index) => {
135
113
  const changes = getTransactionChanges(tx, coValue);
@@ -238,6 +216,10 @@ function mapTransactionToAction(
238
216
  return `Property "${change.key}" has been deleted`;
239
217
  }
240
218
 
219
+ if ((change as any).op === "custom") {
220
+ return (change as any).action;
221
+ }
222
+
241
223
  return "Unknown action: " + JSON.stringify(change);
242
224
  }
243
225
 
@@ -3,6 +3,7 @@ import {
3
3
  LocalNode,
4
4
  RawCoList,
5
5
  RawCoMap,
6
+ RawCoPlainText,
6
7
  RawCoStream,
7
8
  RawCoValue,
8
9
  RawGroup,
@@ -142,7 +143,13 @@ function View(
142
143
  }
143
144
 
144
145
  if (type === "coplaintext") {
145
- return <CoPlainTextView data={snapshot} />;
146
+ return (
147
+ <CoPlainTextView
148
+ data={snapshot}
149
+ coValue={value as RawCoPlainText}
150
+ node={node}
151
+ />
152
+ );
146
153
  }
147
154
 
148
155
  if (type === "colist") {
@@ -48,10 +48,6 @@ export type ResolvedAccount = {
48
48
  [key: string]: JSON;
49
49
  };
50
50
 
51
- export const isAccount = (coValue: JSONObject): coValue is ResolvedAccount => {
52
- return isGroup(coValue) && "profile" in coValue;
53
- };
54
-
55
51
  export async function resolveCoValue(
56
52
  coValueId: CoID<RawCoValue>,
57
53
  node: LocalNode,
@@ -89,7 +85,7 @@ export async function resolveCoValue(
89
85
  if (type === "comap") {
90
86
  if (isBrowserImage(snapshot)) {
91
87
  extendedType = "image";
92
- } else if (isAccount(snapshot)) {
88
+ } else if (value.headerMeta?.type === "account") {
93
89
  extendedType = "account";
94
90
  } else if (value.core.isGroup()) {
95
91
  extendedType = "group";
@@ -125,7 +121,7 @@ function subscribeToCoValue(
125
121
  if (type === "comap") {
126
122
  if (isBrowserImage(snapshot)) {
127
123
  extendedType = "image";
128
- } else if (isAccount(snapshot)) {
124
+ } else if (value.headerMeta?.type === "account") {
129
125
  extendedType = "account";
130
126
  } else if (value.core.isGroup()) {
131
127
  extendedType = "group";
@@ -26,7 +26,7 @@ import {
26
26
  SchemaResolveQuery,
27
27
  SubscriptionScope,
28
28
  coValueClassFromCoValueClassOrSchema,
29
- createUnloadedCoValue,
29
+ getUnloadedCoValueWithoutId,
30
30
  type BranchDefinition,
31
31
  } from "jazz-tools";
32
32
  import { JazzContext, JazzContextManagerContext } from "./provider.js";
@@ -172,39 +172,15 @@ export function useCoValueSubscription<
172
172
  return subscription.subscription as CoValueSubscription<S, R>;
173
173
  }
174
174
 
175
- function getSubscriptionValue<C extends CoValue>(
176
- subscription: SubscriptionScope<C> | null,
177
- ): MaybeLoaded<C> {
178
- if (!subscription) {
179
- return createUnloadedCoValue("", CoValueLoadingState.UNAVAILABLE);
180
- }
181
- const value = subscription.getCurrentValue();
182
- if (typeof value === "string") {
183
- return createUnloadedCoValue(subscription.id, value);
184
- }
185
- return value;
186
- }
187
-
188
175
  function useGetCurrentValue<C extends CoValue>(
189
176
  subscription: SubscriptionScope<C> | null,
190
177
  ) {
191
- const previousValue = useRef<MaybeLoaded<CoValue> | undefined>(undefined);
192
-
193
178
  return useCallback(() => {
194
- const currentValue = getSubscriptionValue(subscription);
195
- // Avoid re-renders if the value is not loaded and didn't change
196
- if (
197
- previousValue.current !== undefined &&
198
- previousValue.current.$jazz.id === currentValue.$jazz.id &&
199
- !previousValue.current.$isLoaded &&
200
- !currentValue.$isLoaded &&
201
- previousValue.current.$jazz.loadingState ===
202
- currentValue.$jazz.loadingState
203
- ) {
204
- return previousValue.current as MaybeLoaded<C>;
179
+ if (!subscription) {
180
+ return getUnloadedCoValueWithoutId(CoValueLoadingState.UNAVAILABLE);
205
181
  }
206
- previousValue.current = currentValue;
207
- return currentValue;
182
+
183
+ return subscription.getCurrentValue();
208
184
  }, [subscription]);
209
185
  }
210
186
 
@@ -17,8 +17,8 @@ import type {
17
17
  import {
18
18
  coValueClassFromCoValueClassOrSchema,
19
19
  subscribeToCoValue,
20
- createUnloadedCoValue,
21
20
  CoValueLoadingState,
21
+ getUnloadedCoValueWithoutId,
22
22
  } from "jazz-tools";
23
23
  import { untrack } from "svelte";
24
24
  import { createSubscriber } from "svelte/reactivity";
@@ -55,11 +55,9 @@ export class CoState<
55
55
  // @ts-expect-error we can't statically enforce the schema's resolve query is a valid resolve query, but in practice it is
56
56
  R extends ResolveQuery<V> = SchemaResolveQuery<V>,
57
57
  > {
58
- #value: MaybeLoaded<Loaded<V, R>> = createUnloadedCoValue(
59
- "",
58
+ #value: MaybeLoaded<Loaded<V, R>> = getUnloadedCoValueWithoutId(
60
59
  CoValueLoadingState.LOADING,
61
60
  );
62
- #previousValue: MaybeLoaded<CoValue> | undefined = undefined;
63
61
  #ctx = getJazzContext<InstanceOfSchema<AccountClass<Account>>>();
64
62
  #id: CoStateId;
65
63
  #subscribe: () => void;
@@ -86,9 +84,9 @@ export class CoState<
86
84
  const options = this.#options;
87
85
 
88
86
  return untrack(() => {
89
- if (!ctx || !id) {
87
+ if (!id) {
90
88
  return this.update(
91
- createUnloadedCoValue(id ?? "", CoValueLoadingState.UNAVAILABLE),
89
+ getUnloadedCoValueWithoutId(CoValueLoadingState.UNAVAILABLE),
92
90
  );
93
91
  }
94
92
  const agent = "me" in ctx ? ctx.me : ctx.guest;
@@ -101,15 +99,11 @@ export class CoState<
101
99
  // @ts-expect-error The resolve query type isn't compatible with the coValueClassFromCoValueClassOrSchema conversion
102
100
  resolve,
103
101
  loadAs: agent,
104
- onUnavailable: () => {
105
- this.update(
106
- createUnloadedCoValue(id, CoValueLoadingState.UNAVAILABLE),
107
- );
102
+ onUnavailable: (value) => {
103
+ this.update(value);
108
104
  },
109
- onUnauthorized: () => {
110
- this.update(
111
- createUnloadedCoValue(id, CoValueLoadingState.UNAUTHORIZED),
112
- );
105
+ onUnauthorized: (value) => {
106
+ this.update(value);
113
107
  },
114
108
  syncResolution: true,
115
109
  unstable_branch: options?.unstable_branch,
@@ -130,7 +124,6 @@ export class CoState<
130
124
  if (shouldSkipUpdate(value, this.#value)) {
131
125
  return;
132
126
  }
133
- this.#previousValue = value;
134
127
  this.#value = value;
135
128
  this.#update();
136
129
  }
@@ -148,11 +141,10 @@ export class AccountCoState<
148
141
  // @ts-expect-error we can't statically enforce the schema's resolve query is a valid resolve query, but in practice it is
149
142
  R extends ResolveQuery<A> = SchemaResolveQuery<A>,
150
143
  > {
151
- #value: MaybeLoaded<Loaded<A, R>> = createUnloadedCoValue(
152
- "",
144
+ #value: MaybeLoaded<Loaded<A, R>> = getUnloadedCoValueWithoutId(
153
145
  CoValueLoadingState.LOADING,
154
146
  );
155
- #ctx = getJazzContext<InstanceOfSchema<A>>();
147
+ #ctx = getJazzContext<InstanceOfSchema<AccountClass<Account>>>();
156
148
  #subscribe: () => void;
157
149
  #options: CoStateOptions<A, R> | undefined;
158
150
  #update = () => {};
@@ -174,9 +166,9 @@ export class AccountCoState<
174
166
  const options = this.#options;
175
167
 
176
168
  return untrack(() => {
177
- if (!ctx || !("me" in ctx)) {
169
+ if (!("me" in ctx)) {
178
170
  return this.update(
179
- createUnloadedCoValue("", CoValueLoadingState.UNAVAILABLE),
171
+ getUnloadedCoValueWithoutId(CoValueLoadingState.UNAVAILABLE),
180
172
  );
181
173
  }
182
174
 
@@ -189,21 +181,11 @@ export class AccountCoState<
189
181
  {
190
182
  resolve,
191
183
  loadAs: me,
192
- onUnavailable: () => {
193
- this.update(
194
- createUnloadedCoValue(
195
- me.$jazz.id,
196
- CoValueLoadingState.UNAVAILABLE,
197
- ),
198
- );
184
+ onUnavailable: (value) => {
185
+ this.update(value);
199
186
  },
200
- onUnauthorized: () => {
201
- this.update(
202
- createUnloadedCoValue(
203
- me.$jazz.id,
204
- CoValueLoadingState.UNAUTHORIZED,
205
- ),
206
- );
187
+ onUnauthorized: (value) => {
188
+ this.update(value);
207
189
  },
208
190
  syncResolution: true,
209
191
  unstable_branch: options?.unstable_branch,
@@ -512,13 +512,16 @@ function entryFromRawEntry<Item>(
512
512
  }
513
513
  },
514
514
  get by() {
515
- return (
516
- accountID &&
517
- accessChildById(accessFrom, accountID, {
518
- ref: Account,
519
- optional: false,
520
- })
521
- );
515
+ if (!accountID) return null;
516
+
517
+ const account = accessChildById(accessFrom, accountID, {
518
+ ref: Account,
519
+ optional: false,
520
+ }) as Account;
521
+
522
+ if (!account.$isLoaded) return null;
523
+
524
+ return account;
522
525
  },
523
526
  madeAt: rawEntry.at,
524
527
  tx: rawEntry.tx,
@@ -1051,13 +1051,16 @@ function getEditFromRaw(
1051
1051
  )
1052
1052
  : undefined,
1053
1053
  get by() {
1054
- return (
1055
- rawEdit.by &&
1056
- accessChildById(target, rawEdit.by, {
1057
- ref: Account,
1058
- optional: false,
1059
- })
1060
- );
1054
+ if (!rawEdit.by) return null;
1055
+
1056
+ const account = accessChildById(target, rawEdit.by, {
1057
+ ref: Account,
1058
+ optional: false,
1059
+ }) as Account;
1060
+
1061
+ if (!account.$isLoaded) return null;
1062
+
1063
+ return account;
1061
1064
  },
1062
1065
  madeAt: rawEdit.at,
1063
1066
  key,
@@ -178,7 +178,11 @@ export class Group extends CoValueBase implements CoValue {
178
178
  ref,
179
179
  get account() {
180
180
  // Accounts values are non-nullable because are loaded as dependencies
181
- return accessChildById(group, accountID, refEncodedAccountSchema);
181
+ return accessChildById(
182
+ group,
183
+ accountID,
184
+ refEncodedAccountSchema,
185
+ ) as Account;
182
186
  },
183
187
  });
184
188
  }
@@ -410,7 +414,7 @@ export function getCoValueOwner(coValue: CoValue): Group {
410
414
  ref: RegisteredSchemas["Group"],
411
415
  optional: false,
412
416
  });
413
- if (!group) {
417
+ if (!group.$isLoaded) {
414
418
  throw new Error("CoValue has no owner");
415
419
  }
416
420
  return group;