jazz-tools 0.7.0-alpha.0
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/.eslintrc.cjs +24 -0
- package/.turbo/turbo-build.log +24 -0
- package/CHANGELOG.md +42 -0
- package/LICENSE.txt +19 -0
- package/README.md +3 -0
- package/dist/coValueInterfaces.js +8 -0
- package/dist/coValueInterfaces.js.map +1 -0
- package/dist/coValues/account/account.js +11 -0
- package/dist/coValues/account/account.js.map +1 -0
- package/dist/coValues/account/accountOf.js +150 -0
- package/dist/coValues/account/accountOf.js.map +1 -0
- package/dist/coValues/account/migration.js +4 -0
- package/dist/coValues/account/migration.js.map +1 -0
- package/dist/coValues/coList/coList.js +2 -0
- package/dist/coValues/coList/coList.js.map +1 -0
- package/dist/coValues/coList/coListOf.js +235 -0
- package/dist/coValues/coList/coListOf.js.map +1 -0
- package/dist/coValues/coList/internalDocs.js +2 -0
- package/dist/coValues/coList/internalDocs.js.map +1 -0
- package/dist/coValues/coMap/coMap.js +2 -0
- package/dist/coValues/coMap/coMap.js.map +1 -0
- package/dist/coValues/coMap/coMapOf.js +262 -0
- package/dist/coValues/coMap/coMapOf.js.map +1 -0
- package/dist/coValues/coMap/internalDocs.js +2 -0
- package/dist/coValues/coMap/internalDocs.js.map +1 -0
- package/dist/coValues/coStream/coStream.js +2 -0
- package/dist/coValues/coStream/coStream.js.map +1 -0
- package/dist/coValues/coStream/coStreamOf.js +244 -0
- package/dist/coValues/coStream/coStreamOf.js.map +1 -0
- package/dist/coValues/construction.js +34 -0
- package/dist/coValues/construction.js.map +1 -0
- package/dist/coValues/extensions/imageDef.js +36 -0
- package/dist/coValues/extensions/imageDef.js.map +1 -0
- package/dist/coValues/group/group.js +2 -0
- package/dist/coValues/group/group.js.map +1 -0
- package/dist/coValues/group/groupOf.js +109 -0
- package/dist/coValues/group/groupOf.js.map +1 -0
- package/dist/coValues/resolution.js +66 -0
- package/dist/coValues/resolution.js.map +1 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/refs.js +95 -0
- package/dist/refs.js.map +1 -0
- package/dist/schemaHelpers.js +14 -0
- package/dist/schemaHelpers.js.map +1 -0
- package/dist/subscriptionScope.js +81 -0
- package/dist/subscriptionScope.js.map +1 -0
- package/dist/tests/coList.test.js +207 -0
- package/dist/tests/coList.test.js.map +1 -0
- package/dist/tests/coMap.test.js +238 -0
- package/dist/tests/coMap.test.js.map +1 -0
- package/dist/tests/coStream.test.js +263 -0
- package/dist/tests/coStream.test.js.map +1 -0
- package/dist/tests/types.test.js +33 -0
- package/dist/tests/types.test.js.map +1 -0
- package/package.json +23 -0
- package/src/coValueInterfaces.ts +105 -0
- package/src/coValues/account/account.ts +106 -0
- package/src/coValues/account/accountOf.ts +284 -0
- package/src/coValues/account/migration.ts +12 -0
- package/src/coValues/coList/coList.ts +57 -0
- package/src/coValues/coList/coListOf.ts +377 -0
- package/src/coValues/coList/internalDocs.ts +1 -0
- package/src/coValues/coMap/coMap.ts +110 -0
- package/src/coValues/coMap/coMapOf.ts +451 -0
- package/src/coValues/coMap/internalDocs.ts +1 -0
- package/src/coValues/coStream/coStream.ts +63 -0
- package/src/coValues/coStream/coStreamOf.ts +404 -0
- package/src/coValues/construction.ts +110 -0
- package/src/coValues/extensions/imageDef.ts +51 -0
- package/src/coValues/group/group.ts +27 -0
- package/src/coValues/group/groupOf.ts +183 -0
- package/src/coValues/resolution.ts +111 -0
- package/src/errors.ts +1 -0
- package/src/index.ts +68 -0
- package/src/refs.ts +128 -0
- package/src/schemaHelpers.ts +72 -0
- package/src/subscriptionScope.ts +118 -0
- package/src/tests/coList.test.ts +283 -0
- package/src/tests/coMap.test.ts +357 -0
- package/src/tests/coStream.test.ts +415 -0
- package/src/tests/types.test.ts +37 -0
- package/tsconfig.json +15 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
import { RawCoID } from "cojson/src/ids";
|
2
|
+
import {
|
3
|
+
AnyAccount,
|
4
|
+
ControlledAccount,
|
5
|
+
ControlledAccountCtx,
|
6
|
+
} from "./coValues/account/account.js";
|
7
|
+
import { CoValueCore } from "cojson";
|
8
|
+
import { Effect, Stream } from "effect";
|
9
|
+
import { UnavailableError } from "./errors.js";
|
10
|
+
import { Schema } from "@effect/schema";
|
11
|
+
import { AnyGroup } from "./coValues/group/group.js";
|
12
|
+
import { SchemaWithInputAndOutput } from "./schemaHelpers.js";
|
13
|
+
|
14
|
+
export type SubclassedConstructor<T> = {
|
15
|
+
new (...args: any[]): T;
|
16
|
+
type: string;
|
17
|
+
};
|
18
|
+
|
19
|
+
export interface CoValueConstructor<
|
20
|
+
Value extends CoValue = CoValue,
|
21
|
+
Type extends string = string,
|
22
|
+
Init = any,
|
23
|
+
> {
|
24
|
+
readonly type: Type;
|
25
|
+
|
26
|
+
/** @category Construction and loading */
|
27
|
+
new (init: Init, options: { owner: AnyAccount | AnyGroup }): Value;
|
28
|
+
|
29
|
+
/** @ignore */
|
30
|
+
fromRaw(raw: Value["_raw"]): Value;
|
31
|
+
|
32
|
+
/** @category Construction and loading */
|
33
|
+
load<V extends Value>(
|
34
|
+
this: SubclassedConstructor<V>,
|
35
|
+
id: ID<V>,
|
36
|
+
options: { as: ControlledAccount, onProgress?: (progress: number) => void }
|
37
|
+
): Promise<V | undefined>;
|
38
|
+
|
39
|
+
/** @category Construction and loading */
|
40
|
+
loadEf<V extends Value>(
|
41
|
+
this: SubclassedConstructor<V>,
|
42
|
+
id: ID<V>
|
43
|
+
): Effect.Effect<V, UnavailableError, ControlledAccountCtx>;
|
44
|
+
|
45
|
+
/** @category Subscription */
|
46
|
+
subscribe<V extends Value>(
|
47
|
+
this: SubclassedConstructor<V>,
|
48
|
+
id: ID<V>,
|
49
|
+
options: { as: ControlledAccount },
|
50
|
+
onUpdate: (value: V) => void
|
51
|
+
): () => void;
|
52
|
+
|
53
|
+
/** @category Subscription */
|
54
|
+
subscribeEf<V extends Value>(
|
55
|
+
this: SubclassedConstructor<V>,
|
56
|
+
id: ID<V>
|
57
|
+
): Stream.Stream<V, UnavailableError, ControlledAccountCtx>;
|
58
|
+
}
|
59
|
+
|
60
|
+
/** @category Schemas & CoValues - Abstract interfaces */
|
61
|
+
export interface CoValueSchema<
|
62
|
+
Self = any,
|
63
|
+
Value extends CoValue = CoValue,
|
64
|
+
Type extends string = string,
|
65
|
+
Init = any,
|
66
|
+
> extends CoValueConstructor<Value, Type, Init>,
|
67
|
+
SchemaWithInputAndOutput<Self, Self> {}
|
68
|
+
|
69
|
+
export function isCoValueSchema(value: any): value is CoValueSchema {
|
70
|
+
return value && value.type !== undefined;
|
71
|
+
}
|
72
|
+
|
73
|
+
export const inspect = Symbol.for("nodejs.util.inspect.custom");
|
74
|
+
export type inspect = typeof inspect;
|
75
|
+
|
76
|
+
/** @category Schemas & CoValues - Abstract interfaces */
|
77
|
+
export interface CoValue<Type extends string = string, Raw = any> {
|
78
|
+
/** @category Value identity */
|
79
|
+
id: ID<this>;
|
80
|
+
/** @category Value identity */
|
81
|
+
_type: Type;
|
82
|
+
/** @category Collaboration */
|
83
|
+
_owner: AnyAccount | AnyGroup;
|
84
|
+
/** @category Subscription */
|
85
|
+
subscribe(listener: (update: this) => void): () => void;
|
86
|
+
/** @category Subscription */
|
87
|
+
subscribeEf(): Stream.Stream<this, UnavailableError, never>;
|
88
|
+
/** @category Internals */
|
89
|
+
_raw: Raw;
|
90
|
+
/** @category Internals */
|
91
|
+
_loadedAs: ControlledAccount;
|
92
|
+
/** @category Internals */
|
93
|
+
_schema: CoValueSchema;
|
94
|
+
/** @category Stringifying & inspection */
|
95
|
+
toJSON(): any[] | object;
|
96
|
+
/** @category Stringifying & inspection */
|
97
|
+
[inspect](): any;
|
98
|
+
}
|
99
|
+
|
100
|
+
export function isCoValue(value: any): value is CoValue {
|
101
|
+
return value && value._type !== undefined;
|
102
|
+
}
|
103
|
+
|
104
|
+
/** @category Schemas & CoValues - Abstract interfaces */
|
105
|
+
export type ID<T> = RawCoID & { readonly __type: (_: never) => T };
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import * as S from "@effect/schema/Schema";
|
2
|
+
import {
|
3
|
+
CoValue,
|
4
|
+
ID,
|
5
|
+
CoValueSchema,
|
6
|
+
SubclassedConstructor,
|
7
|
+
} from "../../coValueInterfaces.js";
|
8
|
+
import { CoMap, CoMapSchema } from "../coMap/coMap.js";
|
9
|
+
import {
|
10
|
+
AgentSecret,
|
11
|
+
InviteSecret,
|
12
|
+
Peer,
|
13
|
+
RawAccount,
|
14
|
+
RawControlledAccount,
|
15
|
+
Role,
|
16
|
+
SessionID,
|
17
|
+
} from "cojson";
|
18
|
+
import { AccountMigration } from "./migration.js";
|
19
|
+
import { Context } from "effect";
|
20
|
+
import { ValueRef } from "../../refs.js";
|
21
|
+
import { SchemaWithInputAndOutput, SchemaWithOutput } from "../../schemaHelpers.js";
|
22
|
+
|
23
|
+
export type ProfileSchema = CoMapSchema<any, {
|
24
|
+
name: S.Schema<string>
|
25
|
+
}, any> & SchemaWithInputAndOutput<CoMap<{
|
26
|
+
name: S.Schema<string>
|
27
|
+
}>>;
|
28
|
+
|
29
|
+
export type RootSchema = CoValueSchema | S.Schema<null>;
|
30
|
+
|
31
|
+
export interface AnyAccount<
|
32
|
+
P extends ProfileSchema = ProfileSchema,
|
33
|
+
R extends RootSchema = RootSchema,
|
34
|
+
> extends CoValue<"Account", RawAccount> {
|
35
|
+
profile?: S.Schema.To<P>;
|
36
|
+
root?: S.Schema.To<R>;
|
37
|
+
isMe: boolean;
|
38
|
+
_refs: {
|
39
|
+
profile: ValueRef<S.Schema.To<P>>;
|
40
|
+
root: ValueRef<S.Schema.To<R>>;
|
41
|
+
};
|
42
|
+
myRole(): 'admin';
|
43
|
+
}
|
44
|
+
|
45
|
+
export function isAccount(value: CoValue): value is AnyAccount {
|
46
|
+
return value._type === "Account";
|
47
|
+
}
|
48
|
+
|
49
|
+
export function isControlledAccount(
|
50
|
+
value: CoValue
|
51
|
+
): value is ControlledAccount {
|
52
|
+
return isAccount(value) && value.isMe;
|
53
|
+
}
|
54
|
+
|
55
|
+
export type ControlledAccount<
|
56
|
+
P extends ProfileSchema = ProfileSchema,
|
57
|
+
R extends RootSchema = RootSchema,
|
58
|
+
> = AnyAccount<P, R> &
|
59
|
+
CoValue<"Account", RawControlledAccount> & {
|
60
|
+
isMe: true;
|
61
|
+
|
62
|
+
acceptInvite<V extends CoValueSchema>(
|
63
|
+
valueID: ID<S.Schema.To<V>>,
|
64
|
+
inviteSecret: InviteSecret,
|
65
|
+
valueSchema: V
|
66
|
+
): Promise<S.Schema.To<V>>;
|
67
|
+
|
68
|
+
sessionID: SessionID;
|
69
|
+
};
|
70
|
+
|
71
|
+
export interface AccountSchema<
|
72
|
+
Self = any,
|
73
|
+
P extends ProfileSchema = ProfileSchema,
|
74
|
+
R extends RootSchema = RootSchema,
|
75
|
+
> extends CoValueSchema<Self, AnyAccount<P, R>, "Account", undefined> {
|
76
|
+
readonly [controlledAccountSym]: ControlledAccount<P, R>;
|
77
|
+
|
78
|
+
create<A extends AnyAccount<P, R>>(
|
79
|
+
this: SubclassedConstructor<A>,
|
80
|
+
options: {
|
81
|
+
name: string;
|
82
|
+
migration?: AccountMigration<AccountSchema<AnyAccount<P, R>, P, R>>;
|
83
|
+
initialAgentSecret?: AgentSecret;
|
84
|
+
peersToLoadFrom?: Peer[];
|
85
|
+
}
|
86
|
+
): Promise<ControlledAccount<P, R>>;
|
87
|
+
|
88
|
+
become<A extends AnyAccount<P, R>>(
|
89
|
+
this: SubclassedConstructor<A>,
|
90
|
+
options: {
|
91
|
+
accountID: ID<AnyAccount<P, R>>;
|
92
|
+
accountSecret: AgentSecret;
|
93
|
+
sessionID: SessionID;
|
94
|
+
peersToLoadFrom: Peer[];
|
95
|
+
migration?: AccountMigration<AccountSchema<AnyAccount<P, R>, P, R>>;
|
96
|
+
}
|
97
|
+
): Promise<ControlledAccount<P, R>>;
|
98
|
+
}
|
99
|
+
|
100
|
+
export const controlledAccountSym = Symbol("@jazz/controlledAccount");
|
101
|
+
export type controlledAccountSym = typeof controlledAccountSym;
|
102
|
+
|
103
|
+
export class ControlledAccountCtx extends Context.Tag("ControlledAccount")<
|
104
|
+
ControlledAccountCtx,
|
105
|
+
ControlledAccount
|
106
|
+
>() {}
|
@@ -0,0 +1,284 @@
|
|
1
|
+
import {
|
2
|
+
AgentSecret,
|
3
|
+
CoID,
|
4
|
+
InviteSecret,
|
5
|
+
LocalNode,
|
6
|
+
Peer,
|
7
|
+
RawAccount,
|
8
|
+
RawCoValue,
|
9
|
+
RawControlledAccount,
|
10
|
+
SessionID,
|
11
|
+
} from "cojson";
|
12
|
+
import {
|
13
|
+
ID,
|
14
|
+
CoValueSchema,
|
15
|
+
inspect,
|
16
|
+
CoValue,
|
17
|
+
} from "../../coValueInterfaces.js";
|
18
|
+
import { CoMapOf } from "../coMap/coMapOf.js";
|
19
|
+
import {
|
20
|
+
AnyAccount,
|
21
|
+
AccountSchema,
|
22
|
+
ProfileSchema,
|
23
|
+
ControlledAccount,
|
24
|
+
controlledAccountSym,
|
25
|
+
} from "./account.js";
|
26
|
+
import * as S from "@effect/schema/Schema";
|
27
|
+
import { AccountMigration } from "./migration.js";
|
28
|
+
import { AST, Schema } from "@effect/schema";
|
29
|
+
import { AnyGroup } from "../group/group.js";
|
30
|
+
import { SharedCoValueConstructor } from "../construction.js";
|
31
|
+
import { constructorOfSchemaSym } from "../resolution.js";
|
32
|
+
import { pipeArguments } from "effect/Pipeable";
|
33
|
+
import { ValueRef } from "../../refs.js";
|
34
|
+
|
35
|
+
export function AccountOf<
|
36
|
+
P extends ProfileSchema,
|
37
|
+
R extends CoValueSchema | S.Schema<null>,
|
38
|
+
>(fields: { profile: P; root: R }) {
|
39
|
+
class AccountOfProfileAndRoot
|
40
|
+
extends SharedCoValueConstructor
|
41
|
+
implements AnyAccount<P, R>
|
42
|
+
{
|
43
|
+
static get ast() {
|
44
|
+
return AST.setAnnotation(
|
45
|
+
Schema.instanceOf(this).ast,
|
46
|
+
constructorOfSchemaSym,
|
47
|
+
this
|
48
|
+
);
|
49
|
+
}
|
50
|
+
static [Schema.TypeId]: Schema.Schema.Variance<
|
51
|
+
AnyAccount<P, R> & AccountOfProfileAndRoot,
|
52
|
+
AnyAccount<P, R> & AccountOfProfileAndRoot,
|
53
|
+
never
|
54
|
+
>[Schema.TypeId];
|
55
|
+
static pipe() {
|
56
|
+
// eslint-disable-next-line prefer-rest-params
|
57
|
+
return pipeArguments(this, arguments);
|
58
|
+
}
|
59
|
+
static type = "Account" as const;
|
60
|
+
static [controlledAccountSym]: AccountOfProfileAndRoot &
|
61
|
+
ControlledAccount<P, R>;
|
62
|
+
|
63
|
+
id!: ID<this>;
|
64
|
+
_type!: "Account";
|
65
|
+
_owner!: AnyAccount | AnyGroup;
|
66
|
+
_refs!: AnyAccount<P, R>["_refs"];
|
67
|
+
_raw!: RawAccount | RawControlledAccount;
|
68
|
+
_loadedAs!: ControlledAccount;
|
69
|
+
_schema!: typeof AccountOfProfileAndRoot;
|
70
|
+
|
71
|
+
isMe: boolean;
|
72
|
+
sessionID?: SessionID;
|
73
|
+
|
74
|
+
constructor(
|
75
|
+
init: undefined,
|
76
|
+
options: { owner: ControlledAccount | AnyGroup | AnyAccount }
|
77
|
+
);
|
78
|
+
constructor(
|
79
|
+
init: undefined,
|
80
|
+
options: { fromRaw: RawAccount | RawControlledAccount }
|
81
|
+
);
|
82
|
+
constructor(
|
83
|
+
init: undefined,
|
84
|
+
options:
|
85
|
+
| { fromRaw: RawAccount | RawControlledAccount }
|
86
|
+
| { owner: ControlledAccount | AnyGroup | AnyAccount }
|
87
|
+
) {
|
88
|
+
super();
|
89
|
+
if (!("fromRaw" in options)) {
|
90
|
+
throw new Error(
|
91
|
+
"Can only construct account from raw or with .create()"
|
92
|
+
);
|
93
|
+
}
|
94
|
+
this.isMe =
|
95
|
+
options.fromRaw.id == options.fromRaw.core.node.account.id;
|
96
|
+
|
97
|
+
const refs = {
|
98
|
+
get profile() {
|
99
|
+
const profileID = options.fromRaw.get("profile");
|
100
|
+
return profileID && new ValueRef(
|
101
|
+
profileID as unknown as ID<Schema.Schema.To<P>>,
|
102
|
+
controlledAccountFromNode(options.fromRaw.core.node),
|
103
|
+
fields.profile
|
104
|
+
);
|
105
|
+
},
|
106
|
+
get root() {
|
107
|
+
const rootID = options.fromRaw.get("root");
|
108
|
+
return rootID && new ValueRef(
|
109
|
+
rootID as unknown as ID<Schema.Schema.To<P>>,
|
110
|
+
controlledAccountFromNode(options.fromRaw.core.node),
|
111
|
+
fields.root
|
112
|
+
);
|
113
|
+
},
|
114
|
+
};
|
115
|
+
|
116
|
+
Object.defineProperties(this, {
|
117
|
+
id: { value: options.fromRaw.id, enumerable: false },
|
118
|
+
_type: { value: "Account", enumerable: false },
|
119
|
+
_owner: { value: this, enumerable: false },
|
120
|
+
_refs: { value: refs, enumerable: false },
|
121
|
+
_raw: { value: options.fromRaw, enumerable: false },
|
122
|
+
_loadedAs: {
|
123
|
+
get: () =>
|
124
|
+
this.isMe
|
125
|
+
? this
|
126
|
+
: controlledAccountFromNode(
|
127
|
+
options.fromRaw.core.node
|
128
|
+
),
|
129
|
+
enumerable: false,
|
130
|
+
},
|
131
|
+
_schema: { value: AccountOfProfileAndRoot, enumerable: false },
|
132
|
+
});
|
133
|
+
|
134
|
+
if (this.isMe) {
|
135
|
+
(this as ControlledAccount).sessionID =
|
136
|
+
options.fromRaw.core.node.currentSessionID;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
static fromRaw(raw: RawAccount | RawControlledAccount) {
|
141
|
+
return new AccountOfProfileAndRoot(undefined, {
|
142
|
+
fromRaw: raw,
|
143
|
+
});
|
144
|
+
}
|
145
|
+
|
146
|
+
static async create(options: {
|
147
|
+
name: string;
|
148
|
+
migration?: AccountMigration<AccountSchema<AnyAccount<P, R>, P, R>>;
|
149
|
+
initialAgentSecret?: AgentSecret;
|
150
|
+
peersToLoadFrom?: Peer[];
|
151
|
+
}): Promise<AccountOfProfileAndRoot & ControlledAccount<P, R>> {
|
152
|
+
const { node } = await LocalNode.withNewlyCreatedAccount({
|
153
|
+
...options,
|
154
|
+
migration:
|
155
|
+
options.migration &&
|
156
|
+
(async (rawAccount) => {
|
157
|
+
const account = new AccountOfProfileAndRoot(undefined, {
|
158
|
+
fromRaw: rawAccount,
|
159
|
+
}) as AccountOfProfileAndRoot & ControlledAccount<P, R>;
|
160
|
+
|
161
|
+
await options.migration!(account);
|
162
|
+
}),
|
163
|
+
});
|
164
|
+
|
165
|
+
return new AccountOfProfileAndRoot(undefined, {
|
166
|
+
fromRaw: node.account as RawControlledAccount,
|
167
|
+
}) as AccountOfProfileAndRoot & ControlledAccount<P, R>;
|
168
|
+
}
|
169
|
+
|
170
|
+
static async become(options: {
|
171
|
+
accountID: ID<AnyAccount<P, R>>;
|
172
|
+
accountSecret: AgentSecret;
|
173
|
+
sessionID: SessionID;
|
174
|
+
peersToLoadFrom: Peer[];
|
175
|
+
migration?: AccountMigration<AccountSchema<AnyAccount<P, R>, P, R>>;
|
176
|
+
}): Promise<AccountOfProfileAndRoot & ControlledAccount<P, R>> {
|
177
|
+
const node = await LocalNode.withLoadedAccount({
|
178
|
+
accountID: options.accountID as unknown as CoID<RawAccount>,
|
179
|
+
accountSecret: options.accountSecret,
|
180
|
+
sessionID: options.sessionID,
|
181
|
+
peersToLoadFrom: options.peersToLoadFrom,
|
182
|
+
migration:
|
183
|
+
options.migration &&
|
184
|
+
(async (rawAccount) => {
|
185
|
+
const account = new AccountOfProfileAndRoot(undefined, {
|
186
|
+
fromRaw: rawAccount,
|
187
|
+
}) as AccountOfProfileAndRoot & ControlledAccount<P, R>;
|
188
|
+
|
189
|
+
await options.migration!(account);
|
190
|
+
}),
|
191
|
+
});
|
192
|
+
|
193
|
+
return new AccountOfProfileAndRoot(undefined, {
|
194
|
+
fromRaw: node.account as RawControlledAccount,
|
195
|
+
}) as AccountOfProfileAndRoot & ControlledAccount<P, R>;
|
196
|
+
}
|
197
|
+
|
198
|
+
async acceptInvite<V extends CoValue>(
|
199
|
+
valueID: ID<V>,
|
200
|
+
inviteSecret: InviteSecret,
|
201
|
+
valueSchema: CoValueSchema<V, V>
|
202
|
+
): Promise<V | undefined> {
|
203
|
+
if (!this.isMe) {
|
204
|
+
throw new Error("Only a controlled account can accept invites");
|
205
|
+
}
|
206
|
+
|
207
|
+
await (this._raw as RawControlledAccount).acceptInvite(
|
208
|
+
valueID as unknown as CoID<RawCoValue>,
|
209
|
+
inviteSecret
|
210
|
+
);
|
211
|
+
|
212
|
+
return valueSchema.load(valueID, { as: this as ControlledAccount });
|
213
|
+
}
|
214
|
+
|
215
|
+
get profile(): S.Schema.To<P> | undefined {
|
216
|
+
return this._refs.profile.accessFrom(this);
|
217
|
+
}
|
218
|
+
|
219
|
+
get root(): S.Schema.To<R> | undefined {
|
220
|
+
return this._refs.root.accessFrom(this);
|
221
|
+
}
|
222
|
+
|
223
|
+
myRole(): "admin" {
|
224
|
+
return "admin";
|
225
|
+
}
|
226
|
+
|
227
|
+
toJSON() {
|
228
|
+
return {
|
229
|
+
profile: this.profile?.toJSON(),
|
230
|
+
root: this.root?.toJSON(),
|
231
|
+
};
|
232
|
+
}
|
233
|
+
|
234
|
+
[inspect]() {
|
235
|
+
return this.toJSON();
|
236
|
+
}
|
237
|
+
|
238
|
+
static as<SubClass>() {
|
239
|
+
return this as unknown as AccountSchema<SubClass, P, R>;
|
240
|
+
}
|
241
|
+
}
|
242
|
+
|
243
|
+
return AccountOfProfileAndRoot as AccountSchema<
|
244
|
+
AccountOfProfileAndRoot & AnyAccount<P, R>,
|
245
|
+
P,
|
246
|
+
R
|
247
|
+
> & {
|
248
|
+
as<SubClass>(): AccountSchema<SubClass, P, R>;
|
249
|
+
};
|
250
|
+
}
|
251
|
+
|
252
|
+
export class BaseProfile extends CoMapOf({
|
253
|
+
name: S.string,
|
254
|
+
}).as<BaseProfile>() {}
|
255
|
+
|
256
|
+
export class Account extends AccountOf<
|
257
|
+
typeof BaseProfile,
|
258
|
+
Schema.Schema<null>
|
259
|
+
>({
|
260
|
+
profile: BaseProfile,
|
261
|
+
root: S.null,
|
262
|
+
}).as<Account>() {}
|
263
|
+
|
264
|
+
const simpleControlledAccounts = new WeakMap<
|
265
|
+
RawControlledAccount,
|
266
|
+
Account & ControlledAccount
|
267
|
+
>();
|
268
|
+
|
269
|
+
export function controlledAccountFromNode(node: LocalNode): ControlledAccount {
|
270
|
+
if (!(node.account instanceof RawControlledAccount)) {
|
271
|
+
throw new Error("Expected a controlled account");
|
272
|
+
}
|
273
|
+
let simpleAccount;
|
274
|
+
|
275
|
+
if (simpleControlledAccounts.has(node.account)) {
|
276
|
+
simpleAccount = simpleControlledAccounts.get(node.account);
|
277
|
+
} else {
|
278
|
+
simpleAccount = Account.fromRaw(node.account) as Account &
|
279
|
+
ControlledAccount;
|
280
|
+
simpleControlledAccounts.set(node.account, simpleAccount);
|
281
|
+
}
|
282
|
+
|
283
|
+
return simpleAccount!;
|
284
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { AccountSchema, controlledAccountSym } from "./account.js";
|
2
|
+
|
3
|
+
export type AccountMigration<A extends AccountSchema> = (
|
4
|
+
me: A[controlledAccountSym]
|
5
|
+
) => void | Promise<void>;
|
6
|
+
|
7
|
+
export function createAccountMigration<A extends AccountSchema>(
|
8
|
+
accountSchema: A,
|
9
|
+
migration: AccountMigration<A>
|
10
|
+
): AccountMigration<A> {
|
11
|
+
return migration;
|
12
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import { JsonValue, RawCoList, CojsonInternalTypes } from "cojson";
|
2
|
+
import { SchemaWithOutput } from "../../schemaHelpers.js";
|
3
|
+
import { CoValue, CoValueSchema } from "../../coValueInterfaces.js";
|
4
|
+
import { Schema } from "@effect/schema";
|
5
|
+
import { ValueRef } from "../../refs.js";
|
6
|
+
import { AnyAccount } from "../account/account.js";
|
7
|
+
|
8
|
+
/**
|
9
|
+
* @category Schemas & CoValues - CoList
|
10
|
+
*/
|
11
|
+
export interface CoListBase<
|
12
|
+
Item extends CoValueSchema | SchemaWithOutput<JsonValue>,
|
13
|
+
> extends CoValue<"CoList", RawCoList> {
|
14
|
+
/** @category Collaboration metadata */
|
15
|
+
readonly _refs: {
|
16
|
+
[idx: number]: ValueRef<Schema.Schema.To<Item>>;
|
17
|
+
length: number;
|
18
|
+
[Symbol.iterator]: () => IterableIterator<
|
19
|
+
ValueRef<Schema.Schema.To<Item>>
|
20
|
+
>;
|
21
|
+
};
|
22
|
+
readonly _edits: {
|
23
|
+
[idx: number]: {
|
24
|
+
value?: Schema.Schema.To<Item>;
|
25
|
+
ref?: Item extends CoValueSchema
|
26
|
+
? ValueRef<Schema.Schema.To<Item>>
|
27
|
+
: never;
|
28
|
+
by?: AnyAccount;
|
29
|
+
madeAt: Date;
|
30
|
+
tx: CojsonInternalTypes.TransactionID;
|
31
|
+
};
|
32
|
+
};
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* @category Schemas & CoValues - CoList
|
37
|
+
*/
|
38
|
+
export type CoList<Item extends CoValueSchema | SchemaWithOutput<JsonValue>> =
|
39
|
+
Array<
|
40
|
+
Item extends CoValueSchema
|
41
|
+
? Schema.Schema.To<Item> | undefined
|
42
|
+
: Schema.Schema.To<Item>
|
43
|
+
> &
|
44
|
+
CoListBase<Item>;
|
45
|
+
|
46
|
+
/**
|
47
|
+
* @category Schemas & CoValues - CoList
|
48
|
+
*/
|
49
|
+
export interface CoListSchema<
|
50
|
+
Self,
|
51
|
+
Item extends CoValueSchema | SchemaWithOutput<JsonValue>,
|
52
|
+
> extends CoValueSchema<
|
53
|
+
Self,
|
54
|
+
CoList<Item>,
|
55
|
+
"CoList",
|
56
|
+
Schema.Schema.To<Item>[]
|
57
|
+
> {}
|