jazz-tools 0.18.5 → 0.18.7
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 +57 -57
- package/CHANGELOG.md +33 -0
- package/dist/better-auth/auth/client.d.ts.map +1 -1
- package/dist/better-auth/auth/client.js +7 -1
- package/dist/better-auth/auth/client.js.map +1 -1
- package/dist/better-auth/auth/react.d.ts +0 -2145
- package/dist/better-auth/auth/react.d.ts.map +1 -1
- package/dist/better-auth/auth/react.js +2 -14
- package/dist/better-auth/auth/react.js.map +1 -1
- package/dist/better-auth/auth/server.d.ts.map +1 -1
- package/dist/better-auth/auth/server.js +77 -22
- package/dist/better-auth/auth/server.js.map +1 -1
- package/dist/better-auth/auth/tests/react.test.d.ts +2 -0
- package/dist/better-auth/auth/tests/react.test.d.ts.map +1 -0
- package/dist/{chunk-3LE7N6TH.js → chunk-CFAY3FMQ.js} +192 -101
- package/dist/chunk-CFAY3FMQ.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/inspector/{custom-element-WCY6D3QJ.js → custom-element-G6SPZEBR.js} +308 -97
- package/dist/inspector/custom-element-G6SPZEBR.js.map +1 -0
- package/dist/inspector/index.d.ts +5 -1
- package/dist/inspector/index.d.ts.map +1 -1
- package/dist/inspector/index.js +318 -56
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/ui/button.d.ts +1 -1
- package/dist/inspector/ui/button.d.ts.map +1 -1
- package/dist/inspector/ui/heading.d.ts +2 -1
- package/dist/inspector/ui/heading.d.ts.map +1 -1
- package/dist/inspector/ui/input.d.ts.map +1 -1
- package/dist/inspector/ui/modal.d.ts +16 -0
- package/dist/inspector/ui/modal.d.ts.map +1 -0
- package/dist/inspector/viewer/delete-local-data.d.ts +2 -0
- package/dist/inspector/viewer/delete-local-data.d.ts.map +1 -0
- package/dist/inspector/viewer/{inpsector-button.d.ts → inspector-button.d.ts} +1 -1
- package/dist/inspector/viewer/{inpsector-button.d.ts.map → inspector-button.d.ts.map} +1 -1
- package/dist/inspector/viewer/new-app.d.ts +1 -4
- package/dist/inspector/viewer/new-app.d.ts.map +1 -1
- package/dist/react/hooks.d.ts +1 -1
- package/dist/react/hooks.d.ts.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +3 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react-core/hooks.d.ts +133 -0
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +83 -17
- package/dist/react-core/index.js.map +1 -1
- package/dist/react-core/tests/useCoStateWithSelector.test.d.ts +2 -0
- package/dist/react-core/tests/useCoStateWithSelector.test.d.ts.map +1 -0
- package/dist/react-native-core/hooks.d.ts +1 -1
- package/dist/react-native-core/hooks.d.ts.map +1 -1
- package/dist/react-native-core/index.js +3 -1
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/testing.js +2 -2
- package/dist/testing.js.map +1 -1
- package/dist/tools/coValues/CoValueBase.d.ts +14 -0
- package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts +0 -12
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/inbox.d.ts +5 -5
- package/dist/tools/coValues/inbox.d.ts.map +1 -1
- package/dist/tools/implementation/createContext.d.ts +2 -1
- package/dist/tools/implementation/createContext.d.ts.map +1 -1
- package/dist/tools/tests/utils.d.ts.map +1 -1
- package/dist/worker/index.d.ts +12 -2
- package/dist/worker/index.d.ts.map +1 -1
- package/dist/worker/index.js +10 -4
- package/dist/worker/index.js.map +1 -1
- package/package.json +6 -4
- package/src/better-auth/auth/client.ts +8 -2
- package/src/better-auth/auth/react.tsx +2 -51
- package/src/better-auth/auth/server.ts +98 -24
- package/src/better-auth/auth/tests/client.test.ts +92 -4
- package/src/better-auth/auth/tests/react.test.tsx +43 -0
- package/src/better-auth/auth/tests/server.test.ts +276 -98
- package/src/inspector/custom-element.tsx +1 -1
- package/src/inspector/index.tsx +44 -0
- package/src/inspector/ui/button.tsx +15 -1
- package/src/inspector/ui/heading.tsx +7 -2
- package/src/inspector/ui/input.tsx +6 -2
- package/src/inspector/ui/modal.tsx +158 -0
- package/src/inspector/viewer/delete-local-data.tsx +101 -0
- package/src/inspector/viewer/new-app.tsx +3 -19
- package/src/react/hooks.tsx +1 -0
- package/src/react/index.ts +1 -0
- package/src/react-core/hooks.ts +162 -0
- package/src/react-core/tests/useCoStateWithSelector.test.ts +149 -0
- package/src/react-native-core/hooks.tsx +1 -0
- package/src/tools/coValues/CoValueBase.ts +32 -0
- package/src/tools/coValues/coList.ts +35 -0
- package/src/tools/coValues/coMap.ts +0 -18
- package/src/tools/coValues/inbox.ts +190 -108
- package/src/tools/implementation/createContext.ts +9 -2
- package/src/tools/testing.ts +1 -1
- package/src/tools/tests/coFeed.test.ts +33 -22
- package/src/tools/tests/coList.test.ts +47 -4
- package/src/tools/tests/coMap.test.ts +13 -5
- package/src/tools/tests/coPlainText.test.ts +24 -0
- package/src/tools/tests/createContext.test.ts +24 -0
- package/src/tools/tests/deepLoading.test.ts +2 -0
- package/src/tools/tests/exportImport.test.ts +3 -1
- package/src/tools/tests/groupsAndAccounts.test.ts +56 -44
- package/src/tools/tests/inbox.test.ts +293 -31
- package/src/tools/tests/patterns/requestToJoin.test.ts +14 -6
- package/src/tools/tests/utils.ts +1 -0
- package/src/worker/index.ts +21 -5
- package/tsup.config.ts +1 -1
- package/dist/chunk-3LE7N6TH.js.map +0 -1
- package/dist/inspector/custom-element-WCY6D3QJ.js.map +0 -1
- package/src/inspector/index.ts +0 -23
- /package/src/inspector/viewer/{inpsector-button.tsx → inspector-button.tsx} +0 -0
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/react.tsx"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/react.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,KAAK,UAAU,GAAG,UAAU,CAC1B,OAAO,gBAAgB,CAAC;IACtB,OAAO,EAAE,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC;CAChD,CAAC,CACH,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,gBAAgB,GACjB,EAAE,iBAAiB,CAAC;IACnB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAAC,6BAmBD"}
|
@@ -1,15 +1,8 @@
|
|
1
1
|
"use client";
|
2
2
|
|
3
3
|
// src/better-auth/auth/react.tsx
|
4
|
-
import {
|
5
|
-
JazzReactProvider,
|
6
|
-
useAuthSecretStorage,
|
7
|
-
useJazzContext
|
8
|
-
} from "jazz-tools/react";
|
4
|
+
import { useAuthSecretStorage, useJazzContext } from "jazz-tools/react-core";
|
9
5
|
import { useEffect } from "react";
|
10
|
-
import { createContext } from "react";
|
11
|
-
import { jsx } from "react/jsx-runtime";
|
12
|
-
var AuthContext = createContext(null);
|
13
6
|
function AuthProvider({
|
14
7
|
children,
|
15
8
|
betterAuthClient
|
@@ -29,12 +22,7 @@ function AuthProvider({
|
|
29
22
|
}, [betterAuthClient, context, authSecretStorage]);
|
30
23
|
return children;
|
31
24
|
}
|
32
|
-
var JazzReactProviderWithBetterAuth = (props) => {
|
33
|
-
return /* @__PURE__ */ jsx(JazzReactProvider, { ...props, children: /* @__PURE__ */ jsx(AuthProvider, { betterAuthClient: props.betterAuthClient, children: props.children }) });
|
34
|
-
};
|
35
25
|
export {
|
36
|
-
|
37
|
-
AuthProvider,
|
38
|
-
JazzReactProviderWithBetterAuth
|
26
|
+
AuthProvider
|
39
27
|
};
|
40
28
|
//# sourceMappingURL=react.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/better-auth/auth/react.tsx"],"sourcesContent":["\"use client\";\n\nimport
|
1
|
+
{"version":3,"sources":["../../../src/better-auth/auth/react.tsx"],"sourcesContent":["\"use client\";\n\nimport { createAuthClient } from \"better-auth/client\";\nimport { useAuthSecretStorage, useJazzContext } from \"jazz-tools/react-core\";\nimport { useEffect } from \"react\";\nimport { type PropsWithChildren } from \"react\";\nimport { jazzPluginClient } from \"./client.js\";\n\ntype AuthClient = ReturnType<\n typeof createAuthClient<{\n plugins: [ReturnType<typeof jazzPluginClient>];\n }>\n>;\n\n/**\n * @param props.children - The children to render.\n * @param props.betterAuthClient - The BetterAuth client with the Jazz plugin.\n *\n * @example\n * ```ts\n * const betterAuthClient = createAuthClient({\n * plugins: [\n * jazzPluginClient(),\n * ],\n * });\n *\n * <AuthProvider betterAuthClient={betterAuthClient}>\n * <App />\n * </AuthProvider>\n * ```\n */\nexport function AuthProvider({\n children,\n betterAuthClient,\n}: PropsWithChildren<{\n betterAuthClient: AuthClient;\n}>) {\n const context = useJazzContext();\n const authSecretStorage = useAuthSecretStorage();\n\n if (betterAuthClient.jazz === undefined) {\n throw new Error(\n \"Better Auth client has been initialized without the jazzPluginClient\",\n );\n }\n\n useEffect(() => {\n betterAuthClient.jazz.setJazzContext(context);\n betterAuthClient.jazz.setAuthSecretStorage(authSecretStorage);\n\n // We need to subscribe to the session to let the plugin keep sync Jazz's and BetterAuth's session\n return betterAuthClient.useSession.subscribe(() => {});\n }, [betterAuthClient, context, authSecretStorage]);\n\n return children;\n}\n"],"mappings":";;;AAGA,SAAS,sBAAsB,sBAAsB;AACrD,SAAS,iBAAiB;AA2BnB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AACF,GAEI;AACF,QAAM,UAAU,eAAe;AAC/B,QAAM,oBAAoB,qBAAqB;AAE/C,MAAI,iBAAiB,SAAS,QAAW;AACvC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,YAAU,MAAM;AACd,qBAAiB,KAAK,eAAe,OAAO;AAC5C,qBAAiB,KAAK,qBAAqB,iBAAiB;AAG5D,WAAO,iBAAiB,WAAW,UAAU,MAAM;AAAA,IAAC,CAAC;AAAA,EACvD,GAAG,CAAC,kBAAkB,SAAS,iBAAiB,CAAC;AAEjD,SAAO;AACT;","names":[]}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAwB,MAAM,qBAAqB,CAAC;AAM7E,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACnC,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;iBACd,CAAC;gBACF,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;oBACb,QAAQ,EAAE,KAAK,CAAC;iBACjB,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAwB,MAAM,qBAAqB,CAAC;AAM7E,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACnC,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;iBACd,CAAC;gBACF,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ,CAAC;oBACf,QAAQ,EAAE,KAAK,CAAC;oBAChB,KAAK,EAAE,KAAK,CAAC;oBACb,QAAQ,EAAE,KAAK,CAAC;iBACjB,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,UA0Q9B,CAAC"}
|
@@ -45,18 +45,19 @@ var jazzPlugin = () => {
|
|
45
45
|
},
|
46
46
|
verification: {
|
47
47
|
create: {
|
48
|
-
|
49
|
-
if (contextContainsJazzAuth(context)) {
|
50
|
-
const
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
48
|
+
after: async (verification, context) => {
|
49
|
+
if (contextContainsJazzAuth(context) && verification.identifier.startsWith("sign-in-otp-")) {
|
50
|
+
const identifier = `jazz-auth-${verification.identifier}`;
|
51
|
+
await context.context.internalAdapter.deleteVerificationValue(
|
52
|
+
identifier
|
53
|
+
);
|
54
|
+
await context.context.internalAdapter.createVerificationValue(
|
55
|
+
{
|
56
|
+
value: JSON.stringify({ jazzAuth: context.jazzAuth }),
|
57
|
+
identifier,
|
58
|
+
expiresAt: verification.expiresAt
|
58
59
|
}
|
59
|
-
|
60
|
+
);
|
60
61
|
}
|
61
62
|
}
|
62
63
|
}
|
@@ -100,6 +101,7 @@ var jazzPlugin = () => {
|
|
100
101
|
})
|
101
102
|
},
|
102
103
|
/**
|
104
|
+
* For: Social / OAuth2 plugin
|
103
105
|
* /callback is the endpoint that BetterAuth uses to authenticate the user coming from a social provider.
|
104
106
|
* 1. Catch the state
|
105
107
|
* 2. Find the verification value
|
@@ -111,17 +113,10 @@ var jazzPlugin = () => {
|
|
111
113
|
},
|
112
114
|
handler: createAuthMiddleware(async (ctx) => {
|
113
115
|
const state = ctx.query?.state || ctx.body?.state;
|
114
|
-
const
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
field: "identifier",
|
119
|
-
operator: "eq",
|
120
|
-
value: state
|
121
|
-
}
|
122
|
-
],
|
123
|
-
select: ["value"]
|
124
|
-
});
|
116
|
+
const identifier = `jazz-auth-${state}`;
|
117
|
+
const data = await ctx.context.internalAdapter.findVerificationValue(
|
118
|
+
identifier
|
119
|
+
);
|
125
120
|
if (!data) {
|
126
121
|
throw new APIError(404, {
|
127
122
|
message: "Verification not found"
|
@@ -141,6 +136,39 @@ var jazzPlugin = () => {
|
|
141
136
|
});
|
142
137
|
}
|
143
138
|
})
|
139
|
+
},
|
140
|
+
/**
|
141
|
+
* For: Email OTP plugin
|
142
|
+
* When the user sends an OTP, we try to find the jazzAuth.
|
143
|
+
* If it isn't a sign-up, we expect to not find a verification value.
|
144
|
+
*/
|
145
|
+
{
|
146
|
+
matcher: (context) => {
|
147
|
+
return context.path.startsWith("/sign-in/email-otp");
|
148
|
+
},
|
149
|
+
handler: createAuthMiddleware(async (ctx) => {
|
150
|
+
const email = ctx.body.email;
|
151
|
+
const identifier = `jazz-auth-sign-in-otp-${email}`;
|
152
|
+
const data = await ctx.context.internalAdapter.findVerificationValue(
|
153
|
+
identifier
|
154
|
+
);
|
155
|
+
if (!data || data.expiresAt < /* @__PURE__ */ new Date()) {
|
156
|
+
return;
|
157
|
+
}
|
158
|
+
const parsed = JSON.parse(data.value);
|
159
|
+
if (parsed && "jazzAuth" in parsed) {
|
160
|
+
return {
|
161
|
+
context: {
|
162
|
+
...ctx,
|
163
|
+
jazzAuth: parsed.jazzAuth
|
164
|
+
}
|
165
|
+
};
|
166
|
+
} else {
|
167
|
+
throw new APIError(500, {
|
168
|
+
message: "JazzAuth not found in verification value"
|
169
|
+
});
|
170
|
+
}
|
171
|
+
})
|
144
172
|
}
|
145
173
|
],
|
146
174
|
after: [
|
@@ -166,6 +194,33 @@ var jazzPlugin = () => {
|
|
166
194
|
jazzAuth
|
167
195
|
});
|
168
196
|
})
|
197
|
+
},
|
198
|
+
/**
|
199
|
+
* For: Social / OAuth2 plugin
|
200
|
+
* When the user sign-in via social, we create a verification value with the jazzAuth.
|
201
|
+
*/
|
202
|
+
{
|
203
|
+
matcher: (context) => {
|
204
|
+
return context.path.startsWith("/sign-in/social");
|
205
|
+
},
|
206
|
+
handler: createAuthMiddleware(async (ctx) => {
|
207
|
+
if (!contextContainsJazzAuth(ctx)) {
|
208
|
+
throw new APIError(500, {
|
209
|
+
message: "JazzAuth not found in context"
|
210
|
+
});
|
211
|
+
}
|
212
|
+
const returned = ctx.context.returned;
|
213
|
+
const url = new URL(returned.url);
|
214
|
+
const state = url.searchParams.get("state");
|
215
|
+
const value = JSON.stringify({ jazzAuth: ctx.jazzAuth });
|
216
|
+
const expiresAt = /* @__PURE__ */ new Date();
|
217
|
+
expiresAt.setMinutes(expiresAt.getMinutes() + 10);
|
218
|
+
await ctx.context.internalAdapter.createVerificationValue({
|
219
|
+
value,
|
220
|
+
identifier: `jazz-auth-${state}`,
|
221
|
+
expiresAt
|
222
|
+
});
|
223
|
+
})
|
169
224
|
}
|
170
225
|
]
|
171
226
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/better-auth/auth/server.ts"],"sourcesContent":["import { AuthContext, MiddlewareContext, MiddlewareOptions } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport { symmetricDecrypt, symmetricEncrypt } from \"better-auth/crypto\";\nimport { BetterAuthPlugin, createAuthMiddleware } from \"better-auth/plugins\";\nimport type { Account, AuthCredentials, ID } from \"jazz-tools\";\n\n// Define a type to have user fields mapped in the better-auth instance\n// It should be automatic, but it needs an hard reference to BetterAuthPlugin type\n// in order to be exported as library.\ntype JazzPlugin = BetterAuthPlugin & {\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\";\n required: false;\n input: false;\n };\n encryptedCredentials: {\n type: \"string\";\n required: false;\n input: false;\n returned: false;\n };\n };\n };\n };\n};\n\n/**\n * @returns The BetterAuth server plugin.\n *\n * @example\n * ```ts\n * const auth = betterAuth({\n * plugins: [jazzPlugin()],\n * // ... other BetterAuth options\n * });\n * ```\n */\nexport const jazzPlugin: () => JazzPlugin = () => {\n return {\n id: \"jazz-plugin\",\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\",\n required: false,\n input: false,\n },\n encryptedCredentials: {\n type: \"string\",\n required: false,\n input: false,\n returned: false,\n },\n },\n },\n },\n\n init() {\n return {\n options: {\n databaseHooks: {\n user: {\n create: {\n before: async (user, context) => {\n // If the user is created without a jazzAuth, it will throw an error.\n if (!contextContainsJazzAuth(context)) {\n throw new APIError(422, {\n message: \"JazzAuth is required on user creation\",\n });\n }\n // Decorate the user with the jazz's credentials.\n return {\n data: {\n accountID: context.jazzAuth.accountID,\n encryptedCredentials:\n context.jazzAuth.encryptedCredentials,\n },\n };\n },\n },\n },\n verification: {\n create: {\n before: async (verification, context) => {\n // If a jazzAuth is provided, save it for later usage.\n if (contextContainsJazzAuth(context)) {\n const parsed = JSON.parse(verification.value);\n const newValue = JSON.stringify({\n ...parsed,\n jazzAuth: context.jazzAuth,\n });\n\n return {\n data: {\n value: newValue,\n },\n };\n }\n },\n },\n },\n },\n },\n };\n },\n\n hooks: {\n before: [\n /**\n * If the client sends a x-jazz-auth header,\n * we encrypt the credentials and inject them into the context.\n */\n {\n matcher: (context) => {\n return !!context.headers?.get(\"x-jazz-auth\");\n },\n handler: createAuthMiddleware(async (ctx) => {\n const jazzAuth = JSON.parse(ctx.headers?.get(\"x-jazz-auth\")!);\n\n const credentials: AuthCredentials = {\n accountID: jazzAuth.accountID as ID<Account>,\n secretSeed: jazzAuth.secretSeed,\n accountSecret: jazzAuth.accountSecret as any,\n // If the provider remains 'anonymous', Jazz will not consider us authenticated later.\n provider: \"better-auth\",\n };\n\n const encryptedCredentials = await symmetricEncrypt({\n key: ctx.context.secret,\n data: JSON.stringify(credentials),\n });\n\n return {\n context: {\n ...ctx,\n jazzAuth: {\n accountID: jazzAuth.accountID,\n encryptedCredentials: encryptedCredentials,\n },\n },\n };\n }),\n },\n\n /**\n * /callback is the endpoint that BetterAuth uses to authenticate the user coming from a social provider.\n * 1. Catch the state\n * 2. Find the verification value\n * 3. If the verification value contains a jazzAuth, inject into the context to have it in case of registration.\n */\n {\n matcher: (context) => {\n return (\n context.path.startsWith(\"/callback\") ||\n context.path.startsWith(\"/oauth2/callback\")\n );\n },\n handler: createAuthMiddleware(async (ctx) => {\n const state = ctx.query?.state || ctx.body?.state;\n\n const data = await ctx.context.adapter.findOne<{ value: string }>({\n model: ctx.context.tables.verification!.modelName,\n where: [\n {\n field: \"identifier\",\n operator: \"eq\",\n value: state,\n },\n ],\n select: [\"value\"],\n });\n\n // if not found, the social plugin will throw later anyway\n if (!data) {\n throw new APIError(404, {\n message: \"Verification not found\",\n });\n }\n\n const parsed = JSON.parse(data.value);\n\n if (parsed && \"jazzAuth\" in parsed) {\n return {\n context: {\n ...ctx,\n jazzAuth: parsed.jazzAuth,\n },\n };\n } else {\n throw new APIError(404, {\n message: \"JazzAuth not found in verification value\",\n });\n }\n }),\n },\n ],\n after: [\n /**\n * This middleware is used to extract the jazzAuth from the user and return it in the response.\n * It is used in the following endpoints that return the user:\n * - /sign-up/email\n * - /sign-in/email\n * - /get-session\n */\n {\n matcher: (context) => {\n return (\n context.path.startsWith(\"/sign-up\") ||\n context.path.startsWith(\"/sign-in\") ||\n context.path.startsWith(\"/get-session\")\n );\n },\n handler: createAuthMiddleware({}, async (ctx) => {\n const returned = ctx.context.returned as any;\n if (!returned?.user?.id) {\n return;\n }\n const jazzAuth = await extractJazzAuth(returned.user.id, ctx);\n\n return ctx.json({\n ...returned,\n jazzAuth: jazzAuth,\n });\n }),\n },\n ],\n },\n } satisfies JazzPlugin;\n};\n\nfunction contextContainsJazzAuth(ctx: unknown): ctx is {\n jazzAuth: {\n accountID: string;\n encryptedCredentials: string;\n };\n} {\n return !!ctx && typeof ctx === \"object\" && \"jazzAuth\" in ctx;\n}\n\nasync function extractJazzAuth(\n userId: string,\n ctx: MiddlewareContext<\n MiddlewareOptions,\n AuthContext & {\n returned?: unknown;\n responseHeaders?: Headers;\n }\n >,\n) {\n const user = await ctx.context.adapter.findOne<{\n accountID: string;\n encryptedCredentials: string;\n }>({\n model: ctx.context.tables.user!.modelName,\n where: [\n {\n field: \"id\",\n operator: \"eq\",\n value: userId,\n },\n ],\n select: [\"accountID\", \"encryptedCredentials\"],\n });\n\n if (!user) {\n return;\n }\n\n const jazzAuth = JSON.parse(\n await symmetricDecrypt({\n key: ctx.context.secret,\n data: user.encryptedCredentials,\n }),\n );\n\n return jazzAuth;\n}\n"],"mappings":"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","names":[]}
|
1
|
+
{"version":3,"sources":["../../../src/better-auth/auth/server.ts"],"sourcesContent":["import { AuthContext, MiddlewareContext, MiddlewareOptions } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport { symmetricDecrypt, symmetricEncrypt } from \"better-auth/crypto\";\nimport { BetterAuthPlugin, createAuthMiddleware } from \"better-auth/plugins\";\nimport type { Account, AuthCredentials, ID } from \"jazz-tools\";\n\n// Define a type to have user fields mapped in the better-auth instance\n// It should be automatic, but it needs an hard reference to BetterAuthPlugin type\n// in order to be exported as library.\ntype JazzPlugin = BetterAuthPlugin & {\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\";\n required: false;\n input: false;\n };\n encryptedCredentials: {\n type: \"string\";\n required: false;\n input: false;\n returned: false;\n };\n };\n };\n };\n};\n\n/**\n * @returns The BetterAuth server plugin.\n *\n * @example\n * ```ts\n * const auth = betterAuth({\n * plugins: [jazzPlugin()],\n * // ... other BetterAuth options\n * });\n * ```\n */\nexport const jazzPlugin: () => JazzPlugin = () => {\n return {\n id: \"jazz-plugin\",\n schema: {\n user: {\n fields: {\n accountID: {\n type: \"string\",\n required: false,\n input: false,\n },\n encryptedCredentials: {\n type: \"string\",\n required: false,\n input: false,\n returned: false,\n },\n },\n },\n },\n\n init() {\n return {\n options: {\n databaseHooks: {\n user: {\n create: {\n before: async (user, context) => {\n // If the user is created without a jazzAuth, it will throw an error.\n if (!contextContainsJazzAuth(context)) {\n throw new APIError(422, {\n message: \"JazzAuth is required on user creation\",\n });\n }\n // Decorate the user with the jazz's credentials.\n return {\n data: {\n accountID: context.jazzAuth.accountID,\n encryptedCredentials:\n context.jazzAuth.encryptedCredentials,\n },\n };\n },\n },\n },\n verification: {\n create: {\n after: async (verification, context) => {\n /**\n * For: Email OTP plugin\n * After a verification is created, if it is from the EmailOTP plugin,\n * create a new verification value with the jazzAuth with the same expiration.\n */\n if (\n contextContainsJazzAuth(context) &&\n verification.identifier.startsWith(\"sign-in-otp-\")\n ) {\n const identifier = `jazz-auth-${verification.identifier}`;\n await context.context.internalAdapter.deleteVerificationValue(\n identifier,\n );\n await context.context.internalAdapter.createVerificationValue(\n {\n value: JSON.stringify({ jazzAuth: context.jazzAuth }),\n identifier: identifier,\n expiresAt: verification.expiresAt,\n },\n );\n }\n },\n },\n },\n },\n },\n };\n },\n\n hooks: {\n before: [\n /**\n * If the client sends a x-jazz-auth header,\n * we encrypt the credentials and inject them into the context.\n */\n {\n matcher: (context) => {\n return !!context.headers?.get(\"x-jazz-auth\");\n },\n handler: createAuthMiddleware(async (ctx) => {\n const jazzAuth = JSON.parse(ctx.headers?.get(\"x-jazz-auth\")!);\n\n const credentials: AuthCredentials = {\n accountID: jazzAuth.accountID as ID<Account>,\n secretSeed: jazzAuth.secretSeed,\n accountSecret: jazzAuth.accountSecret as any,\n // If the provider remains 'anonymous', Jazz will not consider us authenticated later.\n provider: \"better-auth\",\n };\n\n const encryptedCredentials = await symmetricEncrypt({\n key: ctx.context.secret,\n data: JSON.stringify(credentials),\n });\n\n return {\n context: {\n ...ctx,\n jazzAuth: {\n accountID: jazzAuth.accountID,\n encryptedCredentials: encryptedCredentials,\n },\n },\n };\n }),\n },\n\n /**\n * For: Social / OAuth2 plugin\n * /callback is the endpoint that BetterAuth uses to authenticate the user coming from a social provider.\n * 1. Catch the state\n * 2. Find the verification value\n * 3. If the verification value contains a jazzAuth, inject into the context to have it in case of registration.\n */\n {\n matcher: (context) => {\n return (\n context.path.startsWith(\"/callback\") ||\n context.path.startsWith(\"/oauth2/callback\")\n );\n },\n handler: createAuthMiddleware(async (ctx) => {\n const state = ctx.query?.state || ctx.body?.state;\n\n const identifier = `jazz-auth-${state}`;\n\n const data =\n await ctx.context.internalAdapter.findVerificationValue(\n identifier,\n );\n\n // if not found, the social plugin will throw later anyway\n if (!data) {\n throw new APIError(404, {\n message: \"Verification not found\",\n });\n }\n\n const parsed = JSON.parse(data.value);\n\n if (parsed && \"jazzAuth\" in parsed) {\n return {\n context: {\n ...ctx,\n jazzAuth: parsed.jazzAuth,\n },\n };\n } else {\n throw new APIError(404, {\n message: \"JazzAuth not found in verification value\",\n });\n }\n }),\n },\n /**\n * For: Email OTP plugin\n * When the user sends an OTP, we try to find the jazzAuth.\n * If it isn't a sign-up, we expect to not find a verification value.\n */\n {\n matcher: (context) => {\n return context.path.startsWith(\"/sign-in/email-otp\");\n },\n handler: createAuthMiddleware(async (ctx) => {\n const email = ctx.body.email;\n const identifier = `jazz-auth-sign-in-otp-${email}`;\n\n const data =\n await ctx.context.internalAdapter.findVerificationValue(\n identifier,\n );\n\n // if not found, it isn't a sign-up\n if (!data || data.expiresAt < new Date()) {\n return;\n }\n\n const parsed = JSON.parse(data.value);\n\n if (parsed && \"jazzAuth\" in parsed) {\n return {\n context: {\n ...ctx,\n jazzAuth: parsed.jazzAuth,\n },\n };\n } else {\n throw new APIError(500, {\n message: \"JazzAuth not found in verification value\",\n });\n }\n }),\n },\n ],\n after: [\n /**\n * This middleware is used to extract the jazzAuth from the user and return it in the response.\n * It is used in the following endpoints that return the user:\n * - /sign-up/email\n * - /sign-in/email\n * - /get-session\n */\n {\n matcher: (context) => {\n return (\n context.path.startsWith(\"/sign-up\") ||\n context.path.startsWith(\"/sign-in\") ||\n context.path.startsWith(\"/get-session\")\n );\n },\n handler: createAuthMiddleware({}, async (ctx) => {\n const returned = ctx.context.returned as any;\n if (!returned?.user?.id) {\n return;\n }\n const jazzAuth = await extractJazzAuth(returned.user.id, ctx);\n\n return ctx.json({\n ...returned,\n jazzAuth: jazzAuth,\n });\n }),\n },\n\n /**\n * For: Social / OAuth2 plugin\n * When the user sign-in via social, we create a verification value with the jazzAuth.\n */\n {\n matcher: (context) => {\n return context.path.startsWith(\"/sign-in/social\");\n },\n handler: createAuthMiddleware(async (ctx) => {\n if (!contextContainsJazzAuth(ctx)) {\n throw new APIError(500, {\n message: \"JazzAuth not found in context\",\n });\n }\n\n const returned = ctx.context.returned as { url: string };\n\n const url = new URL(returned.url);\n const state = url.searchParams.get(\"state\");\n\n const value = JSON.stringify({ jazzAuth: ctx.jazzAuth });\n const expiresAt = new Date();\n expiresAt.setMinutes(expiresAt.getMinutes() + 10);\n\n await ctx.context.internalAdapter.createVerificationValue({\n value,\n identifier: `jazz-auth-${state}`,\n expiresAt,\n });\n }),\n },\n ],\n },\n } satisfies JazzPlugin;\n};\n\nfunction contextContainsJazzAuth(ctx: unknown): ctx is {\n jazzAuth: {\n accountID: string;\n encryptedCredentials: string;\n };\n} {\n return !!ctx && typeof ctx === \"object\" && \"jazzAuth\" in ctx;\n}\n\nasync function extractJazzAuth(\n userId: string,\n ctx: MiddlewareContext<\n MiddlewareOptions,\n AuthContext & {\n returned?: unknown;\n responseHeaders?: Headers;\n }\n >,\n) {\n const user = await ctx.context.adapter.findOne<{\n accountID: string;\n encryptedCredentials: string;\n }>({\n model: ctx.context.tables.user!.modelName,\n where: [\n {\n field: \"id\",\n operator: \"eq\",\n value: userId,\n },\n ],\n select: [\"accountID\", \"encryptedCredentials\"],\n });\n\n if (!user) {\n return;\n }\n\n const jazzAuth = JSON.parse(\n await symmetricDecrypt({\n key: ctx.context.secret,\n data: user.encryptedCredentials,\n }),\n );\n\n return jazzAuth;\n}\n"],"mappings":"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","names":[]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"react.test.d.ts","sourceRoot":"","sources":["../../../../src/better-auth/auth/tests/react.test.tsx"],"names":[],"mappings":""}
|
@@ -162,6 +162,32 @@ var CoValueJazzApi = class {
|
|
162
162
|
}
|
163
163
|
return new AnonymousJazzAgent(this.localNode);
|
164
164
|
}
|
165
|
+
/**
|
166
|
+
* The timestamp of the creation time of the CoValue
|
167
|
+
*
|
168
|
+
* @category Content
|
169
|
+
*/
|
170
|
+
get createdAt() {
|
171
|
+
const createdAt = this.raw.core.verified.header.meta?.createdAt;
|
172
|
+
if (typeof createdAt === "string") {
|
173
|
+
return new Date(createdAt).getTime();
|
174
|
+
}
|
175
|
+
return this.raw.core.earliestTxMadeAt;
|
176
|
+
}
|
177
|
+
/**
|
178
|
+
* The timestamp of the last updated time of the CoValue
|
179
|
+
*
|
180
|
+
* Returns the creation time if there are no updates.
|
181
|
+
*
|
182
|
+
* @category Content
|
183
|
+
*/
|
184
|
+
get lastUpdatedAt() {
|
185
|
+
const value = this.raw.core.latestTxMadeAt;
|
186
|
+
if (value === 0) {
|
187
|
+
return this.createdAt;
|
188
|
+
}
|
189
|
+
return value;
|
190
|
+
}
|
165
191
|
};
|
166
192
|
|
167
193
|
// src/tools/implementation/inspect.ts
|
@@ -679,22 +705,6 @@ var CoMapJazzApi = class extends CoValueJazzApi {
|
|
679
705
|
get raw() {
|
680
706
|
return this.getRaw();
|
681
707
|
}
|
682
|
-
/**
|
683
|
-
* The timestamp of the creation time of the CoMap
|
684
|
-
*
|
685
|
-
* @category Content
|
686
|
-
*/
|
687
|
-
get createdAt() {
|
688
|
-
return this.raw.earliestTxMadeAt ?? Number.MAX_SAFE_INTEGER;
|
689
|
-
}
|
690
|
-
/**
|
691
|
-
* The timestamp of the last updated time of the CoMap
|
692
|
-
*
|
693
|
-
* @category Content
|
694
|
-
*/
|
695
|
-
get lastUpdatedAt() {
|
696
|
-
return this.raw.latestTxMadeAt;
|
697
|
-
}
|
698
708
|
/** @internal */
|
699
709
|
get schema() {
|
700
710
|
return this.coMap.constructor._schema;
|
@@ -1437,6 +1447,39 @@ var CoListProxyHandler = {
|
|
1437
1447
|
} else {
|
1438
1448
|
return Reflect.has(target, key);
|
1439
1449
|
}
|
1450
|
+
},
|
1451
|
+
ownKeys(target) {
|
1452
|
+
const keys = Reflect.ownKeys(target);
|
1453
|
+
const indexKeys = target.$jazz.raw.entries().map((_entry, i) => String(i));
|
1454
|
+
keys.push(...indexKeys);
|
1455
|
+
return keys;
|
1456
|
+
},
|
1457
|
+
getOwnPropertyDescriptor(target, key) {
|
1458
|
+
if (key === TypeSym) {
|
1459
|
+
return {
|
1460
|
+
enumerable: false,
|
1461
|
+
configurable: true,
|
1462
|
+
writable: false,
|
1463
|
+
value: target[TypeSym]
|
1464
|
+
};
|
1465
|
+
} else if (key in target) {
|
1466
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
1467
|
+
} else if (typeof key === "string" && !isNaN(+key)) {
|
1468
|
+
const index = Number(key);
|
1469
|
+
if (index >= 0 && index < target.$jazz.raw.entries().length) {
|
1470
|
+
return {
|
1471
|
+
enumerable: true,
|
1472
|
+
configurable: true,
|
1473
|
+
writable: true
|
1474
|
+
};
|
1475
|
+
}
|
1476
|
+
} else if (key === "length") {
|
1477
|
+
return {
|
1478
|
+
enumerable: false,
|
1479
|
+
configurable: false,
|
1480
|
+
writable: false
|
1481
|
+
};
|
1482
|
+
}
|
1440
1483
|
}
|
1441
1484
|
};
|
1442
1485
|
|
@@ -2677,7 +2720,9 @@ var Profile = class extends CoMap {
|
|
2677
2720
|
};
|
2678
2721
|
|
2679
2722
|
// src/tools/coValues/inbox.ts
|
2680
|
-
import {
|
2723
|
+
import {
|
2724
|
+
RawAccount as RawAccount2
|
2725
|
+
} from "cojson";
|
2681
2726
|
|
2682
2727
|
// src/tools/lib/id.ts
|
2683
2728
|
function isCoValueId(id) {
|
@@ -2704,6 +2749,20 @@ function createInboxRoot(account) {
|
|
2704
2749
|
inviteLink
|
2705
2750
|
};
|
2706
2751
|
}
|
2752
|
+
var IncrementalFeed = class {
|
2753
|
+
constructor(feed) {
|
2754
|
+
this.feed = feed;
|
2755
|
+
this.sessions = {};
|
2756
|
+
}
|
2757
|
+
getNewItems() {
|
2758
|
+
const items = this.feed.getValidTransactions({
|
2759
|
+
ignorePrivateTransactions: false,
|
2760
|
+
from: this.sessions
|
2761
|
+
});
|
2762
|
+
this.sessions = this.feed.knownState().sessions;
|
2763
|
+
return items;
|
2764
|
+
}
|
2765
|
+
};
|
2707
2766
|
async function createInboxMessage(payload, inboxOwner) {
|
2708
2767
|
const group = payload.$jazz.raw.group;
|
2709
2768
|
if (group instanceof RawAccount2) {
|
@@ -2720,108 +2779,133 @@ async function createInboxMessage(payload, inboxOwner) {
|
|
2720
2779
|
await message.core.waitForSync();
|
2721
2780
|
return message;
|
2722
2781
|
}
|
2782
|
+
var MessageQueue = class {
|
2783
|
+
constructor(concurrencyLimit = 10, processMessage, handleError) {
|
2784
|
+
this.processMessage = processMessage;
|
2785
|
+
this.handleError = handleError;
|
2786
|
+
this.queue = [];
|
2787
|
+
this.processing = /* @__PURE__ */ new Set();
|
2788
|
+
this.activeCount = 0;
|
2789
|
+
this.concurrencyLimit = concurrencyLimit;
|
2790
|
+
}
|
2791
|
+
enqueue(txKey, messageId) {
|
2792
|
+
this.queue.push({ txKey, messageId });
|
2793
|
+
this.processNext();
|
2794
|
+
}
|
2795
|
+
async processNext() {
|
2796
|
+
if (this.activeCount >= this.concurrencyLimit || this.queue.length === 0) {
|
2797
|
+
return;
|
2798
|
+
}
|
2799
|
+
const { txKey, messageId } = this.queue.shift();
|
2800
|
+
if (this.processing.has(txKey)) {
|
2801
|
+
this.processNext();
|
2802
|
+
return;
|
2803
|
+
}
|
2804
|
+
this.processing.add(txKey);
|
2805
|
+
this.activeCount++;
|
2806
|
+
try {
|
2807
|
+
await this.processMessage(txKey, messageId);
|
2808
|
+
} catch (error) {
|
2809
|
+
this.handleError(txKey, messageId, error);
|
2810
|
+
} finally {
|
2811
|
+
this.processing.delete(txKey);
|
2812
|
+
this.activeCount--;
|
2813
|
+
this.processNext();
|
2814
|
+
}
|
2815
|
+
}
|
2816
|
+
};
|
2723
2817
|
var Inbox = class _Inbox {
|
2724
2818
|
constructor(account, root, messages, processed, failed) {
|
2725
|
-
this.processing = /* @__PURE__ */ new Set();
|
2726
2819
|
this.account = account;
|
2727
2820
|
this.root = root;
|
2728
2821
|
this.messages = messages;
|
2729
2822
|
this.processed = processed;
|
2730
2823
|
this.failed = failed;
|
2731
2824
|
}
|
2732
|
-
subscribe(Schema4, callback, options
|
2825
|
+
subscribe(Schema4, callback, options) {
|
2733
2826
|
const processed = /* @__PURE__ */ new Set();
|
2734
|
-
const failed = /* @__PURE__ */ new Map();
|
2735
2827
|
const node = this.account.$jazz.localNode;
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2828
|
+
const concurrencyLimit = options?.concurrencyLimit ?? 10;
|
2829
|
+
const processedFeed = new IncrementalFeed(this.processed.core);
|
2830
|
+
this.processed.subscribe(() => {
|
2831
|
+
for (const { changes } of processedFeed.getNewItems()) {
|
2832
|
+
processed.add(changes[0]);
|
2741
2833
|
}
|
2742
2834
|
});
|
2743
2835
|
const { account } = this;
|
2744
|
-
const
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2836
|
+
const messagesFeed = new IncrementalFeed(this.messages.core);
|
2837
|
+
const processMessage = async (txKey, messageId) => {
|
2838
|
+
const message = await node.load(messageId);
|
2839
|
+
if (message === "unavailable") {
|
2840
|
+
throw new Error(`Inbox: message ${messageId} is unavailable`);
|
2841
|
+
}
|
2842
|
+
const value = await loadCoValue(
|
2843
|
+
coValueClassFromCoValueClassOrSchema(Schema4),
|
2844
|
+
message.get("payload"),
|
2845
|
+
{
|
2846
|
+
loadAs: account
|
2847
|
+
}
|
2848
|
+
);
|
2849
|
+
if (!value) {
|
2850
|
+
throw new Error(
|
2851
|
+
`Inbox: Unable to load the payload of message ${messageId}`
|
2852
|
+
);
|
2853
|
+
}
|
2854
|
+
const accountID = getAccountIDfromSessionID(
|
2855
|
+
txKey.split("/")[0]
|
2856
|
+
);
|
2857
|
+
if (!accountID) {
|
2858
|
+
throw new Error(`Inbox: Unknown account for message ${messageId}`);
|
2859
|
+
}
|
2860
|
+
const result = await callback(value, accountID);
|
2861
|
+
const inboxMessage = node.expectCoValueLoaded(messageId).getCurrentContent();
|
2862
|
+
if (result) {
|
2863
|
+
inboxMessage.set("result", result.$jazz.id);
|
2864
|
+
}
|
2865
|
+
inboxMessage.set("processed", true);
|
2866
|
+
this.processed.push(txKey);
|
2749
2867
|
};
|
2750
|
-
const
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2868
|
+
const handleError = (txKey, messageId, error) => {
|
2869
|
+
console.error(error);
|
2870
|
+
const stringifiedError = String(error);
|
2871
|
+
this.processed.push(txKey);
|
2872
|
+
this.failed.push({ errors: [stringifiedError], value: messageId });
|
2873
|
+
try {
|
2874
|
+
const inboxMessage = node.expectCoValueLoaded(messageId).getCurrentContent();
|
2875
|
+
inboxMessage.set("error", stringifiedError);
|
2876
|
+
inboxMessage.set("processed", true);
|
2877
|
+
} catch (error2) {
|
2878
|
+
}
|
2879
|
+
};
|
2880
|
+
const messageQueue = new MessageQueue(
|
2881
|
+
concurrencyLimit,
|
2882
|
+
processMessage,
|
2883
|
+
handleError
|
2884
|
+
);
|
2885
|
+
const handleNewMessages = () => {
|
2886
|
+
for (const tx of messagesFeed.getNewItems()) {
|
2887
|
+
const accountID = getAccountIDfromSessionID(tx.txID.sessionID);
|
2754
2888
|
if (!accountID) {
|
2755
|
-
console.warn(
|
2889
|
+
console.warn(
|
2890
|
+
"Received message from unknown account",
|
2891
|
+
tx.txID.sessionID
|
2892
|
+
);
|
2756
2893
|
continue;
|
2757
2894
|
}
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2764
|
-
|
2765
|
-
return Promise.reject(
|
2766
|
-
new Error("Unable to load inbox message " + id)
|
2767
|
-
);
|
2768
|
-
}
|
2769
|
-
return loadCoValue(
|
2770
|
-
coValueClassFromCoValueClassOrSchema(Schema4),
|
2771
|
-
message.get("payload"),
|
2772
|
-
{
|
2773
|
-
loadAs: account
|
2774
|
-
}
|
2775
|
-
);
|
2776
|
-
}).then((value) => {
|
2777
|
-
if (!value) {
|
2778
|
-
return Promise.reject(
|
2779
|
-
new Error("Unable to load inbox message " + id)
|
2780
|
-
);
|
2781
|
-
}
|
2782
|
-
return callback(value, accountID);
|
2783
|
-
}).then((result) => {
|
2784
|
-
const inboxMessage = node.expectCoValueLoaded(item.value).getCurrentContent();
|
2785
|
-
if (result) {
|
2786
|
-
inboxMessage.set("result", result.$jazz.id);
|
2787
|
-
}
|
2788
|
-
inboxMessage.set("processed", true);
|
2789
|
-
this.processed.push(txKey);
|
2790
|
-
this.processing.delete(txKey);
|
2791
|
-
}).catch((error) => {
|
2792
|
-
console.error("Error processing inbox message", error);
|
2793
|
-
this.processing.delete(txKey);
|
2794
|
-
const errors = failed.get(txKey) ?? [];
|
2795
|
-
const stringifiedError = String(error);
|
2796
|
-
errors.push(stringifiedError);
|
2797
|
-
let inboxMessage;
|
2798
|
-
try {
|
2799
|
-
inboxMessage = node.expectCoValueLoaded(item.value).getCurrentContent();
|
2800
|
-
inboxMessage.set("error", stringifiedError);
|
2801
|
-
} catch (error2) {
|
2802
|
-
}
|
2803
|
-
if (errors.length > retries) {
|
2804
|
-
inboxMessage?.set("processed", true);
|
2805
|
-
this.processed.push(txKey);
|
2806
|
-
this.failed.push({ errors, value: item.value });
|
2807
|
-
} else {
|
2808
|
-
failed.set(txKey, errors);
|
2809
|
-
if (!failTimer) {
|
2810
|
-
failTimer = setTimeout(
|
2811
|
-
() => handleNewMessages(stream),
|
2812
|
-
100
|
2813
|
-
);
|
2814
|
-
}
|
2815
|
-
}
|
2816
|
-
});
|
2817
|
-
}
|
2895
|
+
const id = tx.changes[0];
|
2896
|
+
if (!isCoValueId(id)) {
|
2897
|
+
continue;
|
2898
|
+
}
|
2899
|
+
const txKey = `${tx.txID.sessionID}/${tx.txID.txIndex}`;
|
2900
|
+
if (processed.has(txKey)) {
|
2901
|
+
continue;
|
2818
2902
|
}
|
2903
|
+
messageQueue.enqueue(txKey, id);
|
2819
2904
|
}
|
2820
2905
|
};
|
2821
2906
|
const unsubscribe = this.messages.subscribe(handleNewMessages);
|
2822
2907
|
return () => {
|
2823
2908
|
unsubscribe();
|
2824
|
-
clearFailTimer();
|
2825
2909
|
};
|
2826
2910
|
}
|
2827
2911
|
static async load(account) {
|
@@ -2845,6 +2929,7 @@ var Inbox = class _Inbox {
|
|
2845
2929
|
if (messages === "unavailable" || processed === "unavailable" || failed === "unavailable") {
|
2846
2930
|
throw new Error("Inbox not found");
|
2847
2931
|
}
|
2932
|
+
await processed.core.waitForFullStreaming();
|
2848
2933
|
return new _Inbox(account, root, messages, processed, failed);
|
2849
2934
|
}
|
2850
2935
|
};
|
@@ -4159,7 +4244,8 @@ async function createJazzContextFromExistingCredentials({
|
|
4159
4244
|
storage,
|
4160
4245
|
AccountSchema: PropsAccountSchema,
|
4161
4246
|
sessionProvider,
|
4162
|
-
onLogOut
|
4247
|
+
onLogOut,
|
4248
|
+
asActiveAccount
|
4163
4249
|
}) {
|
4164
4250
|
const { sessionID, sessionDone } = await sessionProvider(
|
4165
4251
|
credentials.accountID,
|
@@ -4176,12 +4262,16 @@ async function createJazzContextFromExistingCredentials({
|
|
4176
4262
|
storage,
|
4177
4263
|
migration: async (rawAccount, _node, creationProps) => {
|
4178
4264
|
const account2 = AccountClass.fromRaw(rawAccount);
|
4179
|
-
|
4265
|
+
if (asActiveAccount) {
|
4266
|
+
activeAccountContext.set(account2);
|
4267
|
+
}
|
4180
4268
|
await account2.applyMigration(creationProps);
|
4181
4269
|
}
|
4182
4270
|
});
|
4183
4271
|
const account = AccountClass.fromNode(node);
|
4184
|
-
|
4272
|
+
if (asActiveAccount) {
|
4273
|
+
activeAccountContext.set(account);
|
4274
|
+
}
|
4185
4275
|
return {
|
4186
4276
|
node,
|
4187
4277
|
account,
|
@@ -4252,7 +4342,8 @@ async function createJazzContext(options) {
|
|
4252
4342
|
onLogOut: () => {
|
4253
4343
|
authSecretStorage.clearWithoutNotify();
|
4254
4344
|
},
|
4255
|
-
storage: options.storage
|
4345
|
+
storage: options.storage,
|
4346
|
+
asActiveAccount: true
|
4256
4347
|
});
|
4257
4348
|
} else {
|
4258
4349
|
const secretSeed = options.crypto.newRandomSecretSeed();
|
@@ -5816,4 +5907,4 @@ export {
|
|
5816
5907
|
JazzContextManager
|
5817
5908
|
};
|
5818
5909
|
/* istanbul ignore file -- @preserve */
|
5819
|
-
//# sourceMappingURL=chunk-
|
5910
|
+
//# sourceMappingURL=chunk-CFAY3FMQ.js.map
|