jazz-vue 0.8.51 → 0.9.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/.turbo/turbo-build.log +7 -5
- package/CHANGELOG.md +17 -0
- package/dist/composables.d.ts +10079 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +213 -266
- package/dist/provider-BZnz6FpX.js +69 -0
- package/dist/provider.d.ts +48 -0
- package/dist/testing.d.ts +20 -0
- package/dist/testing.js +26 -0
- package/dist/tests/testUtils.d.ts +8 -0
- package/dist/tests/useAcceptInvite.test.d.ts +1 -0
- package/dist/tests/useAccount.test.d.ts +1 -0
- package/dist/tests/useAccountOrGuest.test.d.ts +1 -0
- package/dist/tests/useCoState.test.d.ts +1 -0
- package/package.json +15 -5
- package/src/auth/useDemoAuth.ts +1 -1
- package/src/composables.ts +250 -0
- package/src/index.ts +4 -1
- package/src/provider.ts +106 -0
- package/src/testing.ts +27 -0
- package/src/tests/testUtils.ts +66 -0
- package/src/tests/useAcceptInvite.test.ts +53 -0
- package/src/tests/useAccount.test.ts +51 -0
- package/src/tests/useAccountOrGuest.test.ts +80 -0
- package/src/tests/useCoState.test.ts +127 -0
- package/vite.config.ts +12 -12
- package/dist/createJazzVueApp.d.ts +0 -29
- package/src/createJazzVueApp.ts +0 -356
@@ -0,0 +1,48 @@
|
|
1
|
+
import { Account, AccountClass, AuthMethod } from 'jazz-tools';
|
2
|
+
import { PropType } from 'vue';
|
3
|
+
export declare const logoutHandler: import('vue').Ref<(() => void) | undefined, (() => void) | undefined>;
|
4
|
+
export interface Register {
|
5
|
+
}
|
6
|
+
export type RegisteredAccount = Register extends {
|
7
|
+
Account: infer Acc;
|
8
|
+
} ? Acc : Account;
|
9
|
+
export declare const JazzContextSymbol: unique symbol;
|
10
|
+
export declare const JazzProvider: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
11
|
+
auth: {
|
12
|
+
type: PropType<AuthMethod | "guest">;
|
13
|
+
required: true;
|
14
|
+
};
|
15
|
+
AccountSchema: {
|
16
|
+
type: PropType<AccountClass<RegisteredAccount>>;
|
17
|
+
required: false;
|
18
|
+
};
|
19
|
+
peer: {
|
20
|
+
type: PropType<`wss://${string}` | `ws://${string}`>;
|
21
|
+
required: true;
|
22
|
+
};
|
23
|
+
storage: {
|
24
|
+
type: PropType<"indexedDB" | "singleTabOPFS">;
|
25
|
+
default: undefined;
|
26
|
+
};
|
27
|
+
}>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
|
28
|
+
[key: string]: any;
|
29
|
+
}>[] | null | undefined, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
30
|
+
auth: {
|
31
|
+
type: PropType<AuthMethod | "guest">;
|
32
|
+
required: true;
|
33
|
+
};
|
34
|
+
AccountSchema: {
|
35
|
+
type: PropType<AccountClass<RegisteredAccount>>;
|
36
|
+
required: false;
|
37
|
+
};
|
38
|
+
peer: {
|
39
|
+
type: PropType<`wss://${string}` | `ws://${string}`>;
|
40
|
+
required: true;
|
41
|
+
};
|
42
|
+
storage: {
|
43
|
+
type: PropType<"indexedDB" | "singleTabOPFS">;
|
44
|
+
default: undefined;
|
45
|
+
};
|
46
|
+
}>> & Readonly<{}>, {
|
47
|
+
storage: "indexedDB" | "singleTabOPFS";
|
48
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Account, AnonymousJazzAgent } from 'jazz-tools';
|
2
|
+
import { PropType } from 'vue';
|
3
|
+
export declare const JazzTestProvider: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
4
|
+
account: {
|
5
|
+
type: PropType<Account | {
|
6
|
+
guest: AnonymousJazzAgent;
|
7
|
+
}>;
|
8
|
+
required: true;
|
9
|
+
};
|
10
|
+
}>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
|
11
|
+
[key: string]: any;
|
12
|
+
}>[] | undefined, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
13
|
+
account: {
|
14
|
+
type: PropType<Account | {
|
15
|
+
guest: AnonymousJazzAgent;
|
16
|
+
}>;
|
17
|
+
required: true;
|
18
|
+
};
|
19
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
20
|
+
export { createJazzTestAccount, createJazzTestGuest, linkAccounts, } from 'jazz-tools/testing';
|
package/dist/testing.js
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
import { getJazzContextShape as a } from "jazz-tools/testing";
|
2
|
+
import { createJazzTestAccount as x, createJazzTestGuest as T, linkAccounts as s } from "jazz-tools/testing";
|
3
|
+
import { defineComponent as c, ref as n, provide as p } from "vue";
|
4
|
+
import { J as z } from "./provider-BZnz6FpX.js";
|
5
|
+
const f = c({
|
6
|
+
name: "JazzTestProvider",
|
7
|
+
props: {
|
8
|
+
account: {
|
9
|
+
type: Object,
|
10
|
+
required: !0
|
11
|
+
}
|
12
|
+
},
|
13
|
+
setup(r, { slots: e }) {
|
14
|
+
const o = n(a(r.account));
|
15
|
+
return p(z, o), () => {
|
16
|
+
var t;
|
17
|
+
return (t = e.default) == null ? void 0 : t.call(e);
|
18
|
+
};
|
19
|
+
}
|
20
|
+
});
|
21
|
+
export {
|
22
|
+
f as JazzTestProvider,
|
23
|
+
x as createJazzTestAccount,
|
24
|
+
T as createJazzTestGuest,
|
25
|
+
s as linkAccounts
|
26
|
+
};
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { Account, AnonymousJazzAgent } from 'jazz-tools';
|
2
|
+
import { createApp } from 'vue';
|
3
|
+
export declare const withJazzTestSetup: <C extends (...args: any[]) => any>(composable: C, { account }: {
|
4
|
+
account: Account | {
|
5
|
+
guest: AnonymousJazzAgent;
|
6
|
+
};
|
7
|
+
}) => [ReturnType<C>, ReturnType<typeof createApp>];
|
8
|
+
export declare function waitFor(callback: () => boolean | void): Promise<void>;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
package/package.json
CHANGED
@@ -1,18 +1,28 @@
|
|
1
1
|
{
|
2
2
|
"name": "jazz-vue",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.9.0",
|
4
4
|
"type": "module",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "src/index.ts",
|
7
7
|
"license": "MIT",
|
8
|
+
"exports": {
|
9
|
+
".": {
|
10
|
+
"types": "./dist/index.d.ts",
|
11
|
+
"default": "./dist/index.js"
|
12
|
+
},
|
13
|
+
"./testing": {
|
14
|
+
"types": "./dist/testing.d.ts",
|
15
|
+
"default": "./dist/testing.js"
|
16
|
+
}
|
17
|
+
},
|
8
18
|
"dependencies": {
|
9
|
-
"
|
10
|
-
"
|
11
|
-
"
|
12
|
-
"jazz-tools": "0.8.51"
|
19
|
+
"jazz-tools": "0.9.0",
|
20
|
+
"jazz-browser": "0.9.0",
|
21
|
+
"cojson": "0.9.0"
|
13
22
|
},
|
14
23
|
"devDependencies": {
|
15
24
|
"@vitejs/plugin-vue": "^5.1.4",
|
25
|
+
"rollup-plugin-node-externals": "^8.0.0",
|
16
26
|
"typescript": "~5.6.2",
|
17
27
|
"vite": "^5.4.10",
|
18
28
|
"vite-plugin-dts": "^4.2.4",
|
package/src/auth/useDemoAuth.ts
CHANGED
@@ -2,7 +2,7 @@ import { AgentSecret } from "cojson";
|
|
2
2
|
import { BrowserDemoAuth } from "jazz-browser";
|
3
3
|
import { Account, ID } from "jazz-tools";
|
4
4
|
import { onUnmounted, reactive, ref } from "vue";
|
5
|
-
import { logoutHandler } from "../
|
5
|
+
import { logoutHandler } from "../provider.js";
|
6
6
|
|
7
7
|
export type DemoAuthState = (
|
8
8
|
| {
|
@@ -0,0 +1,250 @@
|
|
1
|
+
import {
|
2
|
+
BrowserContext,
|
3
|
+
BrowserGuestContext,
|
4
|
+
consumeInviteLinkFromWindowLocation,
|
5
|
+
} from "jazz-browser";
|
6
|
+
import {
|
7
|
+
Account,
|
8
|
+
AnonymousJazzAgent,
|
9
|
+
CoValue,
|
10
|
+
CoValueClass,
|
11
|
+
DeeplyLoaded,
|
12
|
+
DepthsIn,
|
13
|
+
ID,
|
14
|
+
subscribeToCoValue,
|
15
|
+
} from "jazz-tools";
|
16
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
17
|
+
import {
|
18
|
+
ComputedRef,
|
19
|
+
MaybeRef,
|
20
|
+
Ref,
|
21
|
+
ShallowRef,
|
22
|
+
computed,
|
23
|
+
inject,
|
24
|
+
onMounted,
|
25
|
+
onUnmounted,
|
26
|
+
ref,
|
27
|
+
shallowRef,
|
28
|
+
toRaw,
|
29
|
+
unref,
|
30
|
+
watch,
|
31
|
+
} from "vue";
|
32
|
+
import { JazzContextSymbol, RegisteredAccount } from "./provider.js";
|
33
|
+
|
34
|
+
export const logoutHandler = ref<() => void>();
|
35
|
+
|
36
|
+
function useJazzContext() {
|
37
|
+
const context =
|
38
|
+
inject<Ref<BrowserContext<RegisteredAccount> | BrowserGuestContext>>(
|
39
|
+
JazzContextSymbol,
|
40
|
+
);
|
41
|
+
if (!context) {
|
42
|
+
throw new Error("useJazzContext must be used within a JazzProvider");
|
43
|
+
}
|
44
|
+
return context;
|
45
|
+
}
|
46
|
+
|
47
|
+
export function createUseAccountComposables<Acc extends Account>() {
|
48
|
+
function useAccount(): {
|
49
|
+
me: ComputedRef<Acc>;
|
50
|
+
logOut: () => void;
|
51
|
+
};
|
52
|
+
function useAccount<D extends DepthsIn<Acc>>(
|
53
|
+
depth: D,
|
54
|
+
): {
|
55
|
+
me: ComputedRef<DeeplyLoaded<Acc, D> | undefined>;
|
56
|
+
logOut: () => void;
|
57
|
+
};
|
58
|
+
function useAccount<D extends DepthsIn<Acc>>(
|
59
|
+
depth?: D,
|
60
|
+
): {
|
61
|
+
me: ComputedRef<Acc | DeeplyLoaded<Acc, D> | undefined>;
|
62
|
+
logOut: () => void;
|
63
|
+
} {
|
64
|
+
const context = useJazzContext();
|
65
|
+
|
66
|
+
if (!context.value) {
|
67
|
+
throw new Error("useAccount must be used within a JazzProvider");
|
68
|
+
}
|
69
|
+
|
70
|
+
if (!("me" in context.value)) {
|
71
|
+
throw new Error(
|
72
|
+
"useAccount can't be used in a JazzProvider with auth === 'guest' - consider using useAccountOrGuest()",
|
73
|
+
);
|
74
|
+
}
|
75
|
+
|
76
|
+
const contextMe = context.value.me as Acc;
|
77
|
+
|
78
|
+
const me = useCoState<Acc, D>(
|
79
|
+
contextMe.constructor as CoValueClass<Acc>,
|
80
|
+
contextMe.id,
|
81
|
+
depth,
|
82
|
+
);
|
83
|
+
|
84
|
+
return {
|
85
|
+
me: computed(() => {
|
86
|
+
const value =
|
87
|
+
depth === undefined
|
88
|
+
? me.value || toRaw((context.value as BrowserContext<Acc>).me)
|
89
|
+
: me.value;
|
90
|
+
|
91
|
+
return value ? toRaw(value) : value;
|
92
|
+
}),
|
93
|
+
logOut: context.value.logOut,
|
94
|
+
};
|
95
|
+
}
|
96
|
+
|
97
|
+
function useAccountOrGuest(): {
|
98
|
+
me: ComputedRef<Acc | AnonymousJazzAgent>;
|
99
|
+
};
|
100
|
+
function useAccountOrGuest<D extends DepthsIn<Acc>>(
|
101
|
+
depth: D,
|
102
|
+
): {
|
103
|
+
me: ComputedRef<DeeplyLoaded<Acc, D> | undefined | AnonymousJazzAgent>;
|
104
|
+
};
|
105
|
+
function useAccountOrGuest<D extends DepthsIn<Acc>>(
|
106
|
+
depth?: D,
|
107
|
+
): {
|
108
|
+
me: ComputedRef<
|
109
|
+
Acc | DeeplyLoaded<Acc, D> | undefined | AnonymousJazzAgent
|
110
|
+
>;
|
111
|
+
} {
|
112
|
+
const context = useJazzContext();
|
113
|
+
|
114
|
+
if (!context.value) {
|
115
|
+
throw new Error("useAccountOrGuest must be used within a JazzProvider");
|
116
|
+
}
|
117
|
+
|
118
|
+
const contextMe = computed(() =>
|
119
|
+
"me" in context.value ? (context.value.me as Acc) : undefined,
|
120
|
+
);
|
121
|
+
|
122
|
+
const me = useCoState<Acc, D>(
|
123
|
+
contextMe.value?.constructor as CoValueClass<Acc>,
|
124
|
+
contextMe.value?.id,
|
125
|
+
depth,
|
126
|
+
);
|
127
|
+
|
128
|
+
if ("me" in context.value) {
|
129
|
+
return {
|
130
|
+
me: computed(() =>
|
131
|
+
depth === undefined
|
132
|
+
? me.value || toRaw((context.value as BrowserContext<Acc>).me)
|
133
|
+
: me.value,
|
134
|
+
),
|
135
|
+
};
|
136
|
+
} else {
|
137
|
+
return {
|
138
|
+
me: computed(() => toRaw((context.value as BrowserGuestContext).guest)),
|
139
|
+
};
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
return {
|
144
|
+
useAccount,
|
145
|
+
useAccountOrGuest,
|
146
|
+
};
|
147
|
+
}
|
148
|
+
|
149
|
+
const { useAccount, useAccountOrGuest } =
|
150
|
+
createUseAccountComposables<RegisteredAccount>();
|
151
|
+
|
152
|
+
export { useAccount, useAccountOrGuest };
|
153
|
+
|
154
|
+
export function useCoState<V extends CoValue, D>(
|
155
|
+
Schema: CoValueClass<V>,
|
156
|
+
id: MaybeRef<ID<V> | undefined>,
|
157
|
+
depth: D & DepthsIn<V> = [] as D & DepthsIn<V>,
|
158
|
+
): Ref<DeeplyLoaded<V, D> | undefined> {
|
159
|
+
const state: ShallowRef<DeeplyLoaded<V, D> | undefined> =
|
160
|
+
shallowRef(undefined);
|
161
|
+
const context = useJazzContext();
|
162
|
+
|
163
|
+
if (!context.value) {
|
164
|
+
throw new Error("useCoState must be used within a JazzProvider");
|
165
|
+
}
|
166
|
+
|
167
|
+
let unsubscribe: (() => void) | undefined;
|
168
|
+
|
169
|
+
watch(
|
170
|
+
[() => unref(id), () => context, () => Schema, () => depth],
|
171
|
+
() => {
|
172
|
+
if (unsubscribe) unsubscribe();
|
173
|
+
|
174
|
+
const idValue = unref(id);
|
175
|
+
if (!idValue) return;
|
176
|
+
|
177
|
+
unsubscribe = subscribeToCoValue(
|
178
|
+
Schema,
|
179
|
+
idValue,
|
180
|
+
"me" in context.value
|
181
|
+
? toRaw(context.value.me)
|
182
|
+
: toRaw(context.value.guest),
|
183
|
+
depth,
|
184
|
+
(value) => {
|
185
|
+
state.value = value;
|
186
|
+
},
|
187
|
+
undefined,
|
188
|
+
true,
|
189
|
+
);
|
190
|
+
},
|
191
|
+
{ deep: true, immediate: true },
|
192
|
+
);
|
193
|
+
|
194
|
+
onUnmounted(() => {
|
195
|
+
if (unsubscribe) unsubscribe();
|
196
|
+
});
|
197
|
+
|
198
|
+
const computedState = computed(() => state.value);
|
199
|
+
|
200
|
+
return computedState;
|
201
|
+
}
|
202
|
+
|
203
|
+
export function useAcceptInvite<V extends CoValue>({
|
204
|
+
invitedObjectSchema,
|
205
|
+
onAccept,
|
206
|
+
forValueHint,
|
207
|
+
}: {
|
208
|
+
invitedObjectSchema: CoValueClass<V>;
|
209
|
+
onAccept: (projectID: ID<V>) => void;
|
210
|
+
forValueHint?: string;
|
211
|
+
}): void {
|
212
|
+
const context = useJazzContext();
|
213
|
+
|
214
|
+
if (!context.value) {
|
215
|
+
throw new Error("useAcceptInvite must be used within a JazzProvider");
|
216
|
+
}
|
217
|
+
|
218
|
+
if (!("me" in context.value)) {
|
219
|
+
throw new Error(
|
220
|
+
"useAcceptInvite can't be used in a JazzProvider with auth === 'guest'.",
|
221
|
+
);
|
222
|
+
}
|
223
|
+
|
224
|
+
const runInviteAcceptance = () => {
|
225
|
+
const result = consumeInviteLinkFromWindowLocation({
|
226
|
+
as: toRaw((context.value as BrowserContext<RegisteredAccount>).me),
|
227
|
+
invitedObjectSchema,
|
228
|
+
forValueHint,
|
229
|
+
});
|
230
|
+
|
231
|
+
result
|
232
|
+
.then((res) => res && onAccept(res.valueID))
|
233
|
+
.catch((e) => {
|
234
|
+
console.error("Failed to accept invite", e);
|
235
|
+
});
|
236
|
+
};
|
237
|
+
|
238
|
+
onMounted(() => {
|
239
|
+
runInviteAcceptance();
|
240
|
+
});
|
241
|
+
|
242
|
+
watch(
|
243
|
+
() => onAccept,
|
244
|
+
(newOnAccept, oldOnAccept) => {
|
245
|
+
if (newOnAccept !== oldOnAccept) {
|
246
|
+
runInviteAcceptance();
|
247
|
+
}
|
248
|
+
},
|
249
|
+
);
|
250
|
+
}
|
package/src/index.ts
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
export * from "./
|
1
|
+
export * from "./composables.js";
|
2
|
+
export { JazzProvider } from "./provider.js";
|
2
3
|
export * from "./auth/useDemoAuth.js";
|
3
4
|
export { default as DemoAuthBasicUI } from "./auth/DemoAuthBasicUI.vue";
|
4
5
|
export { default as ProgressiveImg } from "./ProgressiveImg.vue";
|
6
|
+
|
7
|
+
export { createInviteLink, parseInviteLink } from "jazz-browser";
|
package/src/provider.ts
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
import {
|
2
|
+
BrowserContext,
|
3
|
+
BrowserGuestContext,
|
4
|
+
createJazzBrowserContext,
|
5
|
+
} from "jazz-browser";
|
6
|
+
import { Account, AccountClass, AuthMethod } from "jazz-tools";
|
7
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
8
|
+
import {
|
9
|
+
PropType,
|
10
|
+
defineComponent,
|
11
|
+
onMounted,
|
12
|
+
onUnmounted,
|
13
|
+
provide,
|
14
|
+
ref,
|
15
|
+
watch,
|
16
|
+
} from "vue";
|
17
|
+
|
18
|
+
export const logoutHandler = ref<() => void>();
|
19
|
+
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
21
|
+
export interface Register {}
|
22
|
+
|
23
|
+
export type RegisteredAccount = Register extends { Account: infer Acc }
|
24
|
+
? Acc
|
25
|
+
: Account;
|
26
|
+
|
27
|
+
export const JazzContextSymbol = Symbol("JazzContext");
|
28
|
+
|
29
|
+
export const JazzProvider = defineComponent({
|
30
|
+
name: "JazzProvider",
|
31
|
+
props: {
|
32
|
+
auth: {
|
33
|
+
type: [String, Object] as PropType<AuthMethod | "guest">,
|
34
|
+
required: true,
|
35
|
+
},
|
36
|
+
AccountSchema: {
|
37
|
+
type: Object as PropType<AccountClass<RegisteredAccount>>,
|
38
|
+
required: false,
|
39
|
+
},
|
40
|
+
peer: {
|
41
|
+
type: String as PropType<`wss://${string}` | `ws://${string}`>,
|
42
|
+
required: true,
|
43
|
+
},
|
44
|
+
storage: {
|
45
|
+
type: String as PropType<"indexedDB" | "singleTabOPFS">,
|
46
|
+
default: undefined,
|
47
|
+
},
|
48
|
+
},
|
49
|
+
setup(props, { slots }) {
|
50
|
+
const ctx = ref<
|
51
|
+
BrowserContext<RegisteredAccount> | BrowserGuestContext | undefined
|
52
|
+
>(undefined);
|
53
|
+
|
54
|
+
const key = ref(0);
|
55
|
+
|
56
|
+
provide(JazzContextSymbol, ctx);
|
57
|
+
|
58
|
+
const initializeContext = async () => {
|
59
|
+
if (ctx.value) {
|
60
|
+
ctx.value.done?.();
|
61
|
+
ctx.value = undefined;
|
62
|
+
}
|
63
|
+
|
64
|
+
try {
|
65
|
+
const context = await createJazzBrowserContext<RegisteredAccount>(
|
66
|
+
props.auth === "guest"
|
67
|
+
? { peer: props.peer, storage: props.storage }
|
68
|
+
: {
|
69
|
+
AccountSchema: props.AccountSchema,
|
70
|
+
auth: props.auth,
|
71
|
+
peer: props.peer,
|
72
|
+
storage: props.storage,
|
73
|
+
},
|
74
|
+
);
|
75
|
+
|
76
|
+
ctx.value = {
|
77
|
+
...context,
|
78
|
+
logOut: () => {
|
79
|
+
logoutHandler.value?.();
|
80
|
+
// context.logOut();
|
81
|
+
key.value += 1;
|
82
|
+
},
|
83
|
+
};
|
84
|
+
} catch (e) {
|
85
|
+
console.error("Error creating Jazz browser context:", e);
|
86
|
+
}
|
87
|
+
};
|
88
|
+
|
89
|
+
onMounted(() => {
|
90
|
+
void initializeContext();
|
91
|
+
});
|
92
|
+
|
93
|
+
watch(
|
94
|
+
() => key.value,
|
95
|
+
async () => {
|
96
|
+
await initializeContext();
|
97
|
+
},
|
98
|
+
);
|
99
|
+
|
100
|
+
onUnmounted(() => {
|
101
|
+
if (ctx.value) ctx.value.done?.();
|
102
|
+
});
|
103
|
+
|
104
|
+
return () => (ctx.value ? slots.default?.() : null);
|
105
|
+
},
|
106
|
+
});
|
package/src/testing.ts
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
import { Account, AnonymousJazzAgent } from "jazz-tools";
|
2
|
+
import { getJazzContextShape } from "jazz-tools/testing";
|
3
|
+
import { provide } from "vue";
|
4
|
+
import { PropType, defineComponent, ref } from "vue";
|
5
|
+
import { JazzContextSymbol } from "./provider.js";
|
6
|
+
|
7
|
+
export const JazzTestProvider = defineComponent({
|
8
|
+
name: "JazzTestProvider",
|
9
|
+
props: {
|
10
|
+
account: {
|
11
|
+
type: Object as PropType<Account | { guest: AnonymousJazzAgent }>,
|
12
|
+
required: true,
|
13
|
+
},
|
14
|
+
},
|
15
|
+
setup(props, { slots }) {
|
16
|
+
const ctx = ref(getJazzContextShape(props.account));
|
17
|
+
provide(JazzContextSymbol, ctx);
|
18
|
+
|
19
|
+
return () => slots.default?.();
|
20
|
+
},
|
21
|
+
});
|
22
|
+
|
23
|
+
export {
|
24
|
+
createJazzTestAccount,
|
25
|
+
createJazzTestGuest,
|
26
|
+
linkAccounts,
|
27
|
+
} from "jazz-tools/testing";
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import { Account, AnonymousJazzAgent } from "jazz-tools";
|
2
|
+
import { createApp, defineComponent, h } from "vue";
|
3
|
+
import { JazzTestProvider } from "../testing";
|
4
|
+
|
5
|
+
export const withJazzTestSetup = <C extends (...args: any[]) => any>(
|
6
|
+
composable: C,
|
7
|
+
{ account }: { account: Account | { guest: AnonymousJazzAgent } },
|
8
|
+
) => {
|
9
|
+
let result;
|
10
|
+
|
11
|
+
const wrapper = defineComponent({
|
12
|
+
setup() {
|
13
|
+
result = composable();
|
14
|
+
// suppress missing template warning
|
15
|
+
return () => {};
|
16
|
+
},
|
17
|
+
});
|
18
|
+
|
19
|
+
const app = createApp({
|
20
|
+
setup() {
|
21
|
+
return () =>
|
22
|
+
h(
|
23
|
+
JazzTestProvider,
|
24
|
+
{
|
25
|
+
account,
|
26
|
+
},
|
27
|
+
{
|
28
|
+
default: () => h(wrapper),
|
29
|
+
},
|
30
|
+
);
|
31
|
+
},
|
32
|
+
});
|
33
|
+
|
34
|
+
app.mount(document.createElement("div"));
|
35
|
+
// return the result and the app instance
|
36
|
+
// for testing provide/unmount
|
37
|
+
return [result, app] as [ReturnType<C>, ReturnType<typeof createApp>];
|
38
|
+
};
|
39
|
+
|
40
|
+
export function waitFor(callback: () => boolean | void) {
|
41
|
+
return new Promise<void>((resolve, reject) => {
|
42
|
+
const checkPassed = () => {
|
43
|
+
try {
|
44
|
+
return { ok: callback(), error: null };
|
45
|
+
} catch (error) {
|
46
|
+
return { ok: false, error };
|
47
|
+
}
|
48
|
+
};
|
49
|
+
|
50
|
+
let retries = 0;
|
51
|
+
|
52
|
+
const interval = setInterval(() => {
|
53
|
+
const { ok, error } = checkPassed();
|
54
|
+
|
55
|
+
if (ok !== false) {
|
56
|
+
clearInterval(interval);
|
57
|
+
resolve();
|
58
|
+
}
|
59
|
+
|
60
|
+
if (++retries > 10) {
|
61
|
+
clearInterval(interval);
|
62
|
+
reject(error);
|
63
|
+
}
|
64
|
+
}, 100);
|
65
|
+
});
|
66
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
// @vitest-environment happy-dom
|
2
|
+
|
3
|
+
import { CoMap, Group, ID, co } from "jazz-tools";
|
4
|
+
import { describe, expect, it } from "vitest";
|
5
|
+
import { createInviteLink, useAcceptInvite } from "../index.js";
|
6
|
+
import { createJazzTestAccount, linkAccounts } from "../testing.js";
|
7
|
+
import { waitFor, withJazzTestSetup } from "./testUtils.js";
|
8
|
+
|
9
|
+
describe("useAcceptInvite", () => {
|
10
|
+
it("should accept the invite", async () => {
|
11
|
+
class TestMap extends CoMap {
|
12
|
+
value = co.string;
|
13
|
+
}
|
14
|
+
|
15
|
+
const account = await createJazzTestAccount();
|
16
|
+
const inviteSender = await createJazzTestAccount();
|
17
|
+
|
18
|
+
linkAccounts(account, inviteSender);
|
19
|
+
|
20
|
+
let acceptedId: ID<TestMap> | undefined;
|
21
|
+
|
22
|
+
const invitelink = createInviteLink(
|
23
|
+
TestMap.create(
|
24
|
+
{ value: "hello" },
|
25
|
+
{ owner: Group.create({ owner: inviteSender }) },
|
26
|
+
),
|
27
|
+
"reader",
|
28
|
+
);
|
29
|
+
|
30
|
+
location.href = invitelink;
|
31
|
+
|
32
|
+
withJazzTestSetup(
|
33
|
+
() =>
|
34
|
+
useAcceptInvite({
|
35
|
+
invitedObjectSchema: TestMap,
|
36
|
+
onAccept: (id) => {
|
37
|
+
acceptedId = id;
|
38
|
+
},
|
39
|
+
}),
|
40
|
+
{
|
41
|
+
account,
|
42
|
+
},
|
43
|
+
);
|
44
|
+
|
45
|
+
await waitFor(() => {
|
46
|
+
expect(acceptedId).toBeDefined();
|
47
|
+
});
|
48
|
+
|
49
|
+
const accepted = await TestMap.load(acceptedId!, account, {});
|
50
|
+
|
51
|
+
expect(accepted?.value).toEqual("hello");
|
52
|
+
});
|
53
|
+
});
|