jazz-tools 0.17.14 → 0.18.1
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/.svelte-kit/__package__/jazz.class.svelte.js +1 -1
- package/.svelte-kit/__package__/media/image.svelte +3 -9
- package/.svelte-kit/__package__/media/image.svelte.d.ts +1 -6
- package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -1
- package/.svelte-kit/__package__/media/image.types.d.ts +7 -0
- package/.svelte-kit/__package__/media/image.types.d.ts.map +1 -0
- package/.svelte-kit/__package__/media/image.types.js +1 -0
- package/.svelte-kit/__package__/tests/media/image.svelte.test.js +31 -31
- package/.turbo/turbo-build.log +60 -46
- package/CHANGELOG.md +41 -0
- package/dist/better-auth/auth/client.d.ts +29 -0
- package/dist/better-auth/auth/client.d.ts.map +1 -0
- package/dist/better-auth/auth/client.js +127 -0
- package/dist/better-auth/auth/client.js.map +1 -0
- package/dist/better-auth/auth/react.d.ts +2170 -0
- package/dist/better-auth/auth/react.d.ts.map +1 -0
- package/dist/better-auth/auth/react.js +40 -0
- package/dist/better-auth/auth/react.js.map +1 -0
- package/dist/better-auth/auth/server.d.ts +14 -0
- package/dist/better-auth/auth/server.d.ts.map +1 -0
- package/dist/better-auth/auth/server.js +198 -0
- package/dist/better-auth/auth/server.js.map +1 -0
- package/dist/better-auth/auth/tests/client.test.d.ts +2 -0
- package/dist/better-auth/auth/tests/client.test.d.ts.map +1 -0
- package/dist/better-auth/auth/tests/server.test.d.ts +2 -0
- package/dist/better-auth/auth/tests/server.test.d.ts.map +1 -0
- package/dist/browser/index.js +2 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-LZOF6WP5.js → chunk-IERUTUXB.js} +1336 -1017
- package/dist/chunk-IERUTUXB.js.map +1 -0
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/dist/inspector/{custom-element-ZSNTCECD.js → custom-element-WCY6D3QJ.js} +3 -3
- package/dist/inspector/{custom-element-ZSNTCECD.js.map → custom-element-WCY6D3QJ.js.map} +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/media/{chunk-E5J3WLQW.js → chunk-KR2V6X2N.js} +14 -9
- package/dist/media/chunk-KR2V6X2N.js.map +1 -0
- package/dist/media/create-image.d.ts +6 -6
- package/dist/media/index.browser.d.ts +6 -6
- package/dist/media/index.browser.js +1 -1
- package/dist/media/index.d.ts +1 -1
- package/dist/media/index.js +1 -1
- package/dist/media/index.native.d.ts +6 -6
- package/dist/media/index.native.js +1 -1
- package/dist/media/utils.d.ts.map +1 -1
- package/dist/prosemirror/index.js +2 -2
- package/dist/prosemirror/index.js.map +1 -1
- package/dist/react/index.js +7 -5
- package/dist/react/index.js.map +1 -1
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +4675 -23
- package/dist/react-core/index.js.map +1 -1
- package/dist/react-native-core/index.js +1 -1
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/svelte/jazz.class.svelte.js +1 -1
- package/dist/svelte/media/image.svelte +3 -9
- package/dist/svelte/media/image.svelte.d.ts +1 -6
- package/dist/svelte/media/image.svelte.d.ts.map +1 -1
- package/dist/svelte/media/image.types.d.ts +7 -0
- package/dist/svelte/media/image.types.d.ts.map +1 -0
- package/dist/svelte/media/image.types.js +1 -0
- package/dist/svelte/tests/media/image.svelte.test.js +31 -31
- package/dist/testing.js +18 -14
- package/dist/testing.js.map +1 -1
- package/dist/tools/coValues/CoFieldInit.d.ts +13 -0
- package/dist/tools/coValues/CoFieldInit.d.ts.map +1 -0
- package/dist/tools/coValues/CoValueBase.d.ts +18 -15
- package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
- package/dist/tools/coValues/account.d.ts +101 -46
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/coValues/coFeed.d.ts +78 -62
- package/dist/tools/coValues/coFeed.d.ts.map +1 -1
- package/dist/tools/coValues/coList.d.ts +212 -99
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts +210 -192
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/coPlainText.d.ts +30 -22
- package/dist/tools/coValues/coPlainText.d.ts.map +1 -1
- package/dist/tools/coValues/deepLoading.d.ts +13 -13
- package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
- package/dist/tools/coValues/extensions/imageDef.d.ts +1 -1
- package/dist/tools/coValues/group.d.ts +32 -32
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/inbox.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +18 -17
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/coValues/profile.d.ts +6 -5
- package/dist/tools/coValues/profile.d.ts.map +1 -1
- package/dist/tools/coValues/schemaUnion.d.ts +3 -3
- package/dist/tools/coValues/schemaUnion.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +1 -1
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/implementation/anonymousJazzAgent.d.ts +2 -1
- package/dist/tools/implementation/anonymousJazzAgent.d.ts.map +1 -1
- package/dist/tools/implementation/schema.d.ts +5 -5
- package/dist/tools/implementation/schema.d.ts.map +1 -1
- package/dist/tools/implementation/symbols.d.ts +2 -0
- package/dist/tools/implementation/symbols.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +2 -2
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +6 -2
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +8 -3
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +12 -7
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +13 -7
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +11 -2
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +4 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +4 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/{CoFieldInit.d.ts → CoFieldSchemaInit.d.ts} +7 -7
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldSchemaInit.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +4 -4
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +4 -4
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts +3 -3
- package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/tools/internal.d.ts +2 -1
- package/dist/tools/internal.d.ts.map +1 -1
- package/dist/tools/lib/migration.d.ts +1 -1
- package/dist/tools/lib/migration.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/tools/subscribe/index.d.ts +1 -1
- package/dist/tools/subscribe/index.d.ts.map +1 -1
- package/dist/tools/subscribe/utils.d.ts +2 -2
- package/dist/tools/subscribe/utils.d.ts.map +1 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/tests/utils.d.ts +2 -6
- package/dist/tools/tests/utils.d.ts.map +1 -1
- package/dist/worker/index.js +3 -3
- package/dist/worker/index.js.map +1 -1
- package/package.json +23 -4
- package/src/better-auth/auth/client.ts +169 -0
- package/src/better-auth/auth/react.tsx +105 -0
- package/src/better-auth/auth/server.ts +250 -0
- package/src/better-auth/auth/tests/client.test.ts +249 -0
- package/src/better-auth/auth/tests/server.test.ts +226 -0
- package/src/browser/auth/PasskeyAuth.ts +2 -2
- package/src/browser/createBrowserContext.ts +2 -2
- package/src/browser/tests/PasskeyAuth.test.ts +2 -2
- package/src/inspector/custom-element.tsx +2 -2
- package/src/inspector/viewer/new-app.tsx +1 -1
- package/src/media/create-image.test.ts +7 -7
- package/src/media/create-image.ts +5 -3
- package/src/media/index.ts +1 -1
- package/src/media/utils.test.ts +72 -66
- package/src/media/utils.ts +9 -6
- package/src/prosemirror/lib/plugin.ts +1 -1
- package/src/prosemirror/lib/sync.ts +1 -1
- package/src/prosemirror/tests/plugin.test.ts +4 -4
- package/src/react/media/image.tsx +2 -2
- package/src/react/tests/media/image.test.tsx +52 -32
- package/src/react-core/hooks.ts +11 -5
- package/src/react-core/tests/useAccount.test.ts +16 -22
- package/src/react-core/tests/useCoState.test.ts +19 -19
- package/src/react-core/tests/useInboxSender.test.ts +5 -2
- package/src/react-core/tests/usePassPhraseAuth.test.ts +6 -6
- package/src/react-native-core/media/image.tsx +1 -1
- package/src/svelte/jazz.class.svelte.ts +1 -1
- package/src/svelte/media/image.svelte +3 -9
- package/src/svelte/media/image.types.ts +7 -0
- package/src/svelte/tests/media/image.svelte.test.ts +34 -32
- package/src/tools/auth/DemoAuth.ts +2 -2
- package/src/tools/auth/PassphraseAuth.ts +2 -2
- package/src/tools/auth/clerk/index.ts +2 -2
- package/src/tools/auth/clerk/tests/JazzClerkAuth.test.ts +1 -1
- package/src/tools/coValues/CoFieldInit.ts +20 -0
- package/src/tools/coValues/CoValueBase.ts +40 -60
- package/src/tools/coValues/account.ts +311 -232
- package/src/tools/coValues/coFeed.ts +185 -153
- package/src/tools/coValues/coList.ts +507 -334
- package/src/tools/coValues/coMap.ts +434 -286
- package/src/tools/coValues/coPlainText.ts +94 -110
- package/src/tools/coValues/deepLoading.ts +13 -13
- package/src/tools/coValues/group.ts +100 -114
- package/src/tools/coValues/inbox.ts +16 -14
- package/src/tools/coValues/interfaces.ts +49 -31
- package/src/tools/coValues/profile.ts +8 -6
- package/src/tools/coValues/request.ts +9 -9
- package/src/tools/coValues/schemaUnion.ts +11 -5
- package/src/tools/exports.ts +1 -1
- package/src/tools/implementation/ContextManager.ts +4 -4
- package/src/tools/implementation/anonymousJazzAgent.ts +2 -1
- package/src/tools/implementation/createContext.ts +1 -1
- package/src/tools/implementation/devtoolsFormatters.ts +9 -9
- package/src/tools/implementation/invites.ts +2 -2
- package/src/tools/implementation/schema.ts +7 -7
- package/src/tools/implementation/symbols.ts +3 -0
- package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +2 -2
- package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +11 -2
- package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +18 -7
- package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +17 -7
- package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +20 -11
- package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +19 -2
- package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +6 -0
- package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +6 -0
- package/src/tools/implementation/zodSchema/typeConverters/{CoFieldInit.ts → CoFieldSchemaInit.ts} +11 -11
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +4 -4
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +4 -4
- package/src/tools/implementation/zodSchema/zodCo.ts +3 -3
- package/src/tools/internal.ts +2 -1
- package/src/tools/lib/migration.ts +5 -5
- package/src/tools/subscribe/SubscriptionScope.ts +32 -24
- package/src/tools/subscribe/index.ts +4 -4
- package/src/tools/subscribe/utils.ts +11 -11
- package/src/tools/testing.ts +17 -13
- package/src/tools/tests/ContextManager.test.ts +70 -59
- package/src/tools/tests/PassphraseAuth.test.ts +2 -2
- package/src/tools/tests/account.test.ts +188 -67
- package/src/tools/tests/coDiscriminatedUnion.test-d.ts +12 -6
- package/src/tools/tests/coDiscriminatedUnion.test.ts +26 -17
- package/src/tools/tests/coFeed.test-d.ts +18 -17
- package/src/tools/tests/coFeed.test.ts +108 -97
- package/src/tools/tests/coList.test-d.ts +18 -23
- package/src/tools/tests/coList.test.ts +350 -165
- package/src/tools/tests/coMap.record.test-d.ts +9 -13
- package/src/tools/tests/coMap.record.test.ts +37 -23
- package/src/tools/tests/coMap.test-d.ts +43 -21
- package/src/tools/tests/coMap.test.ts +459 -182
- package/src/tools/tests/coOptional.test.ts +28 -13
- package/src/tools/tests/coPlainText.test.ts +15 -15
- package/src/tools/tests/createContext.test.ts +14 -14
- package/src/tools/tests/deepLoading.test.ts +95 -94
- package/src/tools/tests/exportImport.test.ts +61 -41
- package/src/tools/tests/groupsAndAccounts.test.ts +333 -116
- package/src/tools/tests/inbox.test.ts +22 -17
- package/src/tools/tests/interfaces.test.ts +12 -11
- package/src/tools/tests/invites.test.ts +6 -4
- package/src/tools/tests/load.test.ts +20 -18
- package/src/tools/tests/patterns/notifications.test.ts +7 -7
- package/src/tools/tests/patterns/quest.test.ts +3 -3
- package/src/tools/tests/patterns/requestToJoin.test.ts +22 -22
- package/src/tools/tests/request.test.ts +38 -39
- package/src/tools/tests/schemaUnion.test.ts +64 -10
- package/src/tools/tests/subscribe.test.ts +64 -64
- package/src/tools/tests/testing.test.ts +7 -11
- package/src/tools/tests/utils.ts +3 -3
- package/src/tools/tests/zod.test.ts +3 -3
- package/src/worker/index.ts +3 -3
- package/tsup.config.ts +9 -0
- package/dist/chunk-LZOF6WP5.js.map +0 -1
- package/dist/media/chunk-E5J3WLQW.js.map +0 -1
- package/dist/tools/implementation/zodSchema/typeConverters/CoFieldInit.d.ts.map +0 -1
@@ -1,7 +1,7 @@
|
|
1
|
-
import { RawCoValue } from "cojson";
|
1
|
+
import { RawCoValue, Role } from "cojson";
|
2
2
|
import { CoValue, RefEncoded } from "../internal.js";
|
3
3
|
import { SubscriptionScope } from "./SubscriptionScope.js";
|
4
|
-
export declare function
|
4
|
+
export declare function myRoleForRawValue(raw: RawCoValue): Role | undefined;
|
5
5
|
export declare function createCoValue<D extends CoValue>(ref: RefEncoded<D>, raw: RawCoValue, subscriptionScope: SubscriptionScope<D>): {
|
6
6
|
type: "loaded";
|
7
7
|
value: D;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,UAAU,EAAE,MAAM,QAAQ,CAAC;
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/tools/subscribe/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEtD,OAAO,EACL,OAAO,EACP,UAAU,EAGX,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAUnE;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,OAAO,EAC7C,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,EAClB,GAAG,EAAE,UAAU,EACf,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC;;;;EAgBxC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/tools/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EACL,OAAO,EACP,YAAY,EACZ,KAAK,kBAAkB,EAEvB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAM5B,MAAM,eAAe,CAAC;AAOvB,qBAAa,YAAa,SAAQ,YAAY;WAC/B,MAAM;CAoBpB;AAED,wBAAgB,gCAAgC,0BAiC/C;AAKD,wBAAsB,qBAAqB,CACzC,CAAC,SACG,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,GACjD,iBAAiB,EACrB,OAAO,CAAC,EAAE;IACV,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAuD/B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,QAEhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAC5C,QAAQ,EAAE,MAAM,MAAM,GACrB,MAAM,CAcR;AAED,wBAAsB,mBAAmB;;GASxC;AAED,MAAM,MAAM,2BAA2B,CAAC,GAAG,SAAS,OAAO,IACzD,2BAA2B,CAAC,GAAG,CAAC,GAAG;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEJ,qBAAa,sBAAsB,CACjC,GAAG,SAAS,OAAO,CACnB,SAAQ,kBAAkB,CAAC,GAAG,EAAE,2BAA2B,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,CAAC,kBAAkB,CAAC,GAAG,SAAS,OAAO,EAC3C,OAAO,CAAC,EAAE,GAAG,GAAG;QAAE,KAAK,EAAE,kBAAkB,CAAA;KAAE,EAC7C,KAAK,CAAC,EAAE,2BAA2B,CAAC,GAAG,CAAC;IAS1C,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,OAAO,EACpC,OAAO,EAAE,GAAG,EACZ,KAAK,CAAC,EAAE,2BAA2B,CAAC,GAAG,CAAC;IA0C1C,MAAM,CAAC,SAAS,CAAC,GAAG,SAAS,OAAO,EAClC,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,kBAAkB,CAAA;KAAE,EACxC,KAAK,GAAE,2BAA2B,CAAC,GAAG,CAAM;IAmBxC,aAAa,CACjB,KAAK,EAAE,2BAA2B,CAAC,GAAG,CAAC,EACvC,SAAS,CAAC,EAAE,2BAA2B;;
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/tools/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EACL,OAAO,EACP,YAAY,EACZ,KAAK,kBAAkB,EAEvB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAM5B,MAAM,eAAe,CAAC;AAOvB,qBAAa,YAAa,SAAQ,YAAY;WAC/B,MAAM;CAoBpB;AAED,wBAAgB,gCAAgC,0BAiC/C;AAKD,wBAAsB,qBAAqB,CACzC,CAAC,SACG,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,GACjD,iBAAiB,EACrB,OAAO,CAAC,EAAE;IACV,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAuD/B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,QAEhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAC5C,QAAQ,EAAE,MAAM,MAAM,GACrB,MAAM,CAcR;AAED,wBAAsB,mBAAmB;;GASxC;AAED,MAAM,MAAM,2BAA2B,CAAC,GAAG,SAAS,OAAO,IACzD,2BAA2B,CAAC,GAAG,CAAC,GAAG;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEJ,qBAAa,sBAAsB,CACjC,GAAG,SAAS,OAAO,CACnB,SAAQ,kBAAkB,CAAC,GAAG,EAAE,2BAA2B,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,CAAC,kBAAkB,CAAC,GAAG,SAAS,OAAO,EAC3C,OAAO,CAAC,EAAE,GAAG,GAAG;QAAE,KAAK,EAAE,kBAAkB,CAAA;KAAE,EAC7C,KAAK,CAAC,EAAE,2BAA2B,CAAC,GAAG,CAAC;IAS1C,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,OAAO,EACpC,OAAO,EAAE,GAAG,EACZ,KAAK,CAAC,EAAE,2BAA2B,CAAC,GAAG,CAAC;IA0C1C,MAAM,CAAC,SAAS,CAAC,GAAG,SAAS,OAAO,EAClC,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,kBAAkB,CAAA;KAAE,EACxC,KAAK,GAAE,2BAA2B,CAAC,GAAG,CAAM;IAmBxC,aAAa,CACjB,KAAK,EAAE,2BAA2B,CAAC,GAAG,CAAC,EACvC,SAAS,CAAC,EAAE,2BAA2B;;uBA2E2mO,cAAc;;;;;;;;CA7CnqO;AAED,wBAAsB,YAAY,CAChC,CAAC,EAAE,OAAO,EACV,CAAC,EAAE,OAAO,EACV,KAAK,GAAE,QAAQ,GAAG,QAAmB,EACrC,KAAK,GAAE,QAAQ,GAAG,QAAmB,iBAgBtC;AAED,wBAAsB,iBAAiB,CAAC,EACtC,UAAkB,GACnB,GAAE;IACD,UAAU,CAAC,EAAE,OAAO,CAAC;CACjB,oBAgBL"}
|
@@ -3,13 +3,9 @@ import { CoID, LocalNode, RawCoValue } from "cojson";
|
|
3
3
|
import { Account } from "../index";
|
4
4
|
import { CoValueFromRaw } from "../internal";
|
5
5
|
export declare function setupAccount(): Promise<{
|
6
|
-
me:
|
7
|
-
isLocalNodeOwner: true;
|
8
|
-
sessionID: import("cojson").SessionID;
|
9
|
-
_raw: import("cojson").RawAccount;
|
10
|
-
};
|
6
|
+
me: import("../internal").ControlledAccount;
|
11
7
|
meOnSecondPeer: Account | ({
|
12
|
-
[x: string]: any;
|
8
|
+
readonly [x: string]: any;
|
13
9
|
} & Account);
|
14
10
|
}>;
|
15
11
|
export declare function setupTwoNodes(options?: {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/tools/tests/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,qBAAqB,CAAC;AAExE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGrD,OAAO,EACL,OAAO,EAGR,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI7C,wBAAsB,YAAY
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/tools/tests/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,qBAAqB,CAAC;AAExE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGrD,OAAO,EACL,OAAO,EAGR,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI7C,wBAAsB,YAAY;;;;;GA+BjC;AAED,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE;IAC5C,mBAAmB,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;CACvE;;;;;GAgDA;AAED,wBAAgB,OAAO,CACrB,QAAQ,EAAE,MAAM,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,iBA2BzD;AAED,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,UAAU,EAC1D,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,GACV,OAAO,CAAC,CAAC,CAAC,CAMZ"}
|
package/dist/worker/index.js
CHANGED
@@ -57,13 +57,13 @@ async function startWorker(options) {
|
|
57
57
|
crypto: options.crypto ?? await WasmCrypto.create()
|
58
58
|
});
|
59
59
|
const account = context.account;
|
60
|
-
node = account.
|
61
|
-
if (!account.
|
60
|
+
node = account.$jazz.localNode;
|
61
|
+
if (!account.$jazz.refs.profile?.id) {
|
62
62
|
throw new Error("Account has no profile");
|
63
63
|
}
|
64
64
|
const inbox = await Inbox.load(account);
|
65
65
|
async function done() {
|
66
|
-
await context.account.waitForAllCoValuesSync();
|
66
|
+
await context.account.$jazz.waitForAllCoValuesSync();
|
67
67
|
wsPeer.disable();
|
68
68
|
context.done();
|
69
69
|
}
|
package/dist/worker/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/worker/index.ts"],"sourcesContent":["import { AgentSecret, CryptoProvider, LocalNode, Peer } from \"cojson\";\nimport {\n type AnyWebSocketConstructor,\n WebSocketPeerWithReconnection,\n} from \"cojson-transport-ws\";\nimport { WasmCrypto } from \"cojson/crypto/WasmCrypto\";\nimport {\n Account,\n AccountClass,\n AnyAccountSchema,\n CoValueFromRaw,\n Inbox,\n InstanceOfSchema,\n createJazzContextFromExistingCredentials,\n randomSessionProvider,\n} from \"jazz-tools\";\n\ntype WorkerOptions<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> = {\n accountID?: string;\n accountSecret?: string;\n syncServer?: string;\n WebSocket?: AnyWebSocketConstructor;\n AccountSchema?: S;\n crypto?: CryptoProvider;\n};\n\n/** @category Context Creation */\nexport async function startWorker<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n>(options: WorkerOptions<S>) {\n const {\n accountID = process.env.JAZZ_WORKER_ACCOUNT,\n accountSecret = process.env.JAZZ_WORKER_SECRET,\n syncServer = \"wss://cloud.jazz.tools\",\n AccountSchema = Account as unknown as S,\n } = options;\n\n let node: LocalNode | undefined = undefined;\n\n const peersToLoadFrom: Peer[] = [];\n\n const wsPeer = new WebSocketPeerWithReconnection({\n peer: syncServer,\n reconnectionTimeout: 100,\n addPeer: (peer) => {\n if (node) {\n node.syncManager.addPeer(peer);\n } else {\n peersToLoadFrom.push(peer);\n }\n },\n removePeer: () => {},\n WebSocketConstructor: options.WebSocket,\n });\n\n wsPeer.enable();\n\n if (!accountID) {\n throw new Error(\"No accountID provided\");\n }\n if (!accountSecret) {\n throw new Error(\"No accountSecret provided\");\n }\n if (!accountID.startsWith(\"co_\")) {\n throw new Error(\"Invalid accountID\");\n }\n if (!accountSecret?.startsWith(\"sealerSecret_\")) {\n throw new Error(\"Invalid accountSecret\");\n }\n\n const context = await createJazzContextFromExistingCredentials({\n credentials: {\n accountID: accountID,\n secret: accountSecret as AgentSecret,\n },\n AccountSchema,\n // TODO: locked sessions similar to browser\n sessionProvider: randomSessionProvider,\n peersToLoadFrom,\n crypto: options.crypto ?? (await WasmCrypto.create()),\n });\n\n const account = context.account as InstanceOfSchema<S>;\n node = account.
|
1
|
+
{"version":3,"sources":["../../src/worker/index.ts"],"sourcesContent":["import { AgentSecret, CryptoProvider, LocalNode, Peer } from \"cojson\";\nimport {\n type AnyWebSocketConstructor,\n WebSocketPeerWithReconnection,\n} from \"cojson-transport-ws\";\nimport { WasmCrypto } from \"cojson/crypto/WasmCrypto\";\nimport {\n Account,\n AccountClass,\n AnyAccountSchema,\n CoValueFromRaw,\n Inbox,\n InstanceOfSchema,\n createJazzContextFromExistingCredentials,\n randomSessionProvider,\n} from \"jazz-tools\";\n\ntype WorkerOptions<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n> = {\n accountID?: string;\n accountSecret?: string;\n syncServer?: string;\n WebSocket?: AnyWebSocketConstructor;\n AccountSchema?: S;\n crypto?: CryptoProvider;\n};\n\n/** @category Context Creation */\nexport async function startWorker<\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n>(options: WorkerOptions<S>) {\n const {\n accountID = process.env.JAZZ_WORKER_ACCOUNT,\n accountSecret = process.env.JAZZ_WORKER_SECRET,\n syncServer = \"wss://cloud.jazz.tools\",\n AccountSchema = Account as unknown as S,\n } = options;\n\n let node: LocalNode | undefined = undefined;\n\n const peersToLoadFrom: Peer[] = [];\n\n const wsPeer = new WebSocketPeerWithReconnection({\n peer: syncServer,\n reconnectionTimeout: 100,\n addPeer: (peer) => {\n if (node) {\n node.syncManager.addPeer(peer);\n } else {\n peersToLoadFrom.push(peer);\n }\n },\n removePeer: () => {},\n WebSocketConstructor: options.WebSocket,\n });\n\n wsPeer.enable();\n\n if (!accountID) {\n throw new Error(\"No accountID provided\");\n }\n if (!accountSecret) {\n throw new Error(\"No accountSecret provided\");\n }\n if (!accountID.startsWith(\"co_\")) {\n throw new Error(\"Invalid accountID\");\n }\n if (!accountSecret?.startsWith(\"sealerSecret_\")) {\n throw new Error(\"Invalid accountSecret\");\n }\n\n const context = await createJazzContextFromExistingCredentials({\n credentials: {\n accountID: accountID,\n secret: accountSecret as AgentSecret,\n },\n AccountSchema,\n // TODO: locked sessions similar to browser\n sessionProvider: randomSessionProvider,\n peersToLoadFrom,\n crypto: options.crypto ?? (await WasmCrypto.create()),\n });\n\n const account = context.account as InstanceOfSchema<S>;\n node = account.$jazz.localNode;\n\n if (!account.$jazz.refs.profile?.id) {\n throw new Error(\"Account has no profile\");\n }\n\n const inbox = await Inbox.load(account);\n\n async function done() {\n await context.account.$jazz.waitForAllCoValuesSync();\n\n wsPeer.disable();\n context.done();\n }\n\n const inboxPublicApi = {\n subscribe: inbox.subscribe.bind(inbox) as Inbox[\"subscribe\"],\n };\n\n return {\n worker: context.account as InstanceOfSchema<S>,\n experimental: {\n inbox: inboxPublicApi,\n },\n waitForConnection() {\n return wsPeer.waitUntilConnected();\n },\n subscribeToConnectionChange(listener: (connected: boolean) => void) {\n wsPeer.subscribe(listener);\n\n return () => {\n wsPeer.unsubscribe(listener);\n };\n },\n done,\n };\n}\n"],"mappings":";AACA;AAAA,EAEE;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EAIA;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AAgBP,eAAsB,YAIpB,SAA2B;AAC3B,QAAM;AAAA,IACJ,YAAY,QAAQ,IAAI;AAAA,IACxB,gBAAgB,QAAQ,IAAI;AAAA,IAC5B,aAAa;AAAA,IACb,gBAAgB;AAAA,EAClB,IAAI;AAEJ,MAAI,OAA8B;AAElC,QAAM,kBAA0B,CAAC;AAEjC,QAAM,SAAS,IAAI,8BAA8B;AAAA,IAC/C,MAAM;AAAA,IACN,qBAAqB;AAAA,IACrB,SAAS,CAAC,SAAS;AACjB,UAAI,MAAM;AACR,aAAK,YAAY,QAAQ,IAAI;AAAA,MAC/B,OAAO;AACL,wBAAgB,KAAK,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,YAAY,MAAM;AAAA,IAAC;AAAA,IACnB,sBAAsB,QAAQ;AAAA,EAChC,CAAC;AAED,SAAO,OAAO;AAEd,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,uBAAuB;AAAA,EACzC;AACA,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC7C;AACA,MAAI,CAAC,UAAU,WAAW,KAAK,GAAG;AAChC,UAAM,IAAI,MAAM,mBAAmB;AAAA,EACrC;AACA,MAAI,CAAC,eAAe,WAAW,eAAe,GAAG;AAC/C,UAAM,IAAI,MAAM,uBAAuB;AAAA,EACzC;AAEA,QAAM,UAAU,MAAM,yCAAyC;AAAA,IAC7D,aAAa;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IACA;AAAA;AAAA,IAEA,iBAAiB;AAAA,IACjB;AAAA,IACA,QAAQ,QAAQ,UAAW,MAAM,WAAW,OAAO;AAAA,EACrD,CAAC;AAED,QAAM,UAAU,QAAQ;AACxB,SAAO,QAAQ,MAAM;AAErB,MAAI,CAAC,QAAQ,MAAM,KAAK,SAAS,IAAI;AACnC,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC1C;AAEA,QAAM,QAAQ,MAAM,MAAM,KAAK,OAAO;AAEtC,iBAAe,OAAO;AACpB,UAAM,QAAQ,QAAQ,MAAM,uBAAuB;AAEnD,WAAO,QAAQ;AACf,YAAQ,KAAK;AAAA,EACf;AAEA,QAAM,iBAAiB;AAAA,IACrB,WAAW,MAAM,UAAU,KAAK,KAAK;AAAA,EACvC;AAEA,SAAO;AAAA,IACL,QAAQ,QAAQ;AAAA,IAChB,cAAc;AAAA,MACZ,OAAO;AAAA,IACT;AAAA,IACA,oBAAoB;AAClB,aAAO,OAAO,mBAAmB;AAAA,IACnC;AAAA,IACA,4BAA4B,UAAwC;AAClE,aAAO,UAAU,QAAQ;AAEzB,aAAO,MAAM;AACX,eAAO,YAAY,QAAQ;AAAA,MAC7B;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
package/package.json
CHANGED
@@ -136,11 +136,26 @@
|
|
136
136
|
"@jazz-tools/source": "./src/worker/index.ts",
|
137
137
|
"types": "./dist/worker/index.d.ts",
|
138
138
|
"default": "./dist/worker/index.js"
|
139
|
+
},
|
140
|
+
"./better-auth/auth/client": {
|
141
|
+
"@jazz-tools/source": "./src/better-auth/auth/client.ts",
|
142
|
+
"types": "./dist/better-auth/auth/client.d.ts",
|
143
|
+
"default": "./dist/better-auth/auth/client.js"
|
144
|
+
},
|
145
|
+
"./better-auth/auth/react": {
|
146
|
+
"@jazz-tools/source": "./src/better-auth/auth/react.tsx",
|
147
|
+
"types": "./dist/better-auth/auth/react.d.ts",
|
148
|
+
"default": "./dist/better-auth/auth/react.js"
|
149
|
+
},
|
150
|
+
"./better-auth/auth/server": {
|
151
|
+
"@jazz-tools/source": "./src/better-auth/auth/server.ts",
|
152
|
+
"types": "./dist/better-auth/auth/server.d.ts",
|
153
|
+
"default": "./dist/better-auth/auth/server.js"
|
139
154
|
}
|
140
155
|
},
|
141
156
|
"type": "module",
|
142
157
|
"license": "MIT",
|
143
|
-
"version": "0.
|
158
|
+
"version": "0.18.1",
|
144
159
|
"dependencies": {
|
145
160
|
"@manuscripts/prosemirror-recreate-steps": "^0.1.4",
|
146
161
|
"@scure/base": "1.2.1",
|
@@ -156,9 +171,9 @@
|
|
156
171
|
"prosemirror-state": "^1.4.3",
|
157
172
|
"prosemirror-transform": "^1.9.0",
|
158
173
|
"zod": "3.25.76",
|
159
|
-
"cojson": "0.
|
160
|
-
"cojson-storage-indexeddb": "0.
|
161
|
-
"cojson-transport-ws": "0.
|
174
|
+
"cojson": "0.18.1",
|
175
|
+
"cojson-storage-indexeddb": "0.18.1",
|
176
|
+
"cojson-transport-ws": "0.18.1"
|
162
177
|
},
|
163
178
|
"devDependencies": {
|
164
179
|
"@scure/bip39": "^1.3.0",
|
@@ -183,6 +198,7 @@
|
|
183
198
|
"@bam.tech/react-native-image-resizer": "*",
|
184
199
|
"@op-engineering/op-sqlite": "*",
|
185
200
|
"@react-native-community/netinfo": "*",
|
201
|
+
"better-auth": "^1.3.0",
|
186
202
|
"expo-file-system": "*",
|
187
203
|
"expo-secure-store": "*",
|
188
204
|
"expo-sqlite": "*",
|
@@ -205,6 +221,9 @@
|
|
205
221
|
"@react-native-community/netinfo": {
|
206
222
|
"optional": true
|
207
223
|
},
|
224
|
+
"better-auth": {
|
225
|
+
"optional": true
|
226
|
+
},
|
208
227
|
"expo-file-system": {
|
209
228
|
"optional": true
|
210
229
|
},
|
@@ -0,0 +1,169 @@
|
|
1
|
+
import type { BetterAuthClientPlugin } from "better-auth";
|
2
|
+
import type {
|
3
|
+
AuthSecretStorage,
|
4
|
+
AuthSetPayload,
|
5
|
+
Account,
|
6
|
+
JazzContextType,
|
7
|
+
} from "jazz-tools";
|
8
|
+
import type { jazzPlugin } from "./server.js";
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @example
|
12
|
+
* ```ts
|
13
|
+
* const auth = betterAuth({
|
14
|
+
* plugins: [jazzPluginClient()],
|
15
|
+
* });
|
16
|
+
* ```
|
17
|
+
*/
|
18
|
+
export const jazzPluginClient = () => {
|
19
|
+
let jazzContext: JazzContextType<Account>;
|
20
|
+
let authSecretStorage: AuthSecretStorage;
|
21
|
+
let signOutUnsubscription: () => void;
|
22
|
+
|
23
|
+
const authenticateOnJazz = async (jazzAuth: AuthSetPayload) => {
|
24
|
+
const parsedJazzAuth = {
|
25
|
+
...jazzAuth,
|
26
|
+
secretSeed: jazzAuth.secretSeed
|
27
|
+
? Uint8Array.from(jazzAuth.secretSeed)
|
28
|
+
: undefined,
|
29
|
+
};
|
30
|
+
|
31
|
+
await jazzContext.authenticate(parsedJazzAuth);
|
32
|
+
await authSecretStorage.set(parsedJazzAuth);
|
33
|
+
};
|
34
|
+
|
35
|
+
return {
|
36
|
+
id: "jazz-plugin",
|
37
|
+
$InferServerPlugin: {} as ReturnType<typeof jazzPlugin>,
|
38
|
+
getActions: ($fetch, $store) => {
|
39
|
+
return {
|
40
|
+
jazz: {
|
41
|
+
setJazzContext: (context: JazzContextType<Account>) => {
|
42
|
+
jazzContext = context;
|
43
|
+
},
|
44
|
+
setAuthSecretStorage: (storage: AuthSecretStorage) => {
|
45
|
+
authSecretStorage = storage;
|
46
|
+
if (signOutUnsubscription) signOutUnsubscription();
|
47
|
+
|
48
|
+
// This is a workaround to logout from Better Auth when user logs out directly from Jazz
|
49
|
+
signOutUnsubscription = authSecretStorage.onUpdate(
|
50
|
+
(isAuthenticated) => {
|
51
|
+
if (isAuthenticated === false) {
|
52
|
+
const session = $store.atoms.session?.get();
|
53
|
+
if (!session) return;
|
54
|
+
|
55
|
+
// if the user logs out from Better Auth, the get session is immediately called
|
56
|
+
// so we must wait the next fetched session to understand if we need to call sign-out
|
57
|
+
if (session.isPending || session.isRefetching) {
|
58
|
+
// listen once for next session's data
|
59
|
+
const unsub = $store.atoms.session?.listen((session) => {
|
60
|
+
unsub?.();
|
61
|
+
// if the session is null, user has been already logged out from Better Auth
|
62
|
+
if (session.data !== null) {
|
63
|
+
$fetch("/sign-out", { method: "POST" });
|
64
|
+
}
|
65
|
+
});
|
66
|
+
}
|
67
|
+
// if the session is not pending, it means user logged out from Jazz only
|
68
|
+
// so we call the sign-out api
|
69
|
+
else {
|
70
|
+
$fetch("/sign-out", { method: "POST" });
|
71
|
+
}
|
72
|
+
}
|
73
|
+
},
|
74
|
+
);
|
75
|
+
},
|
76
|
+
},
|
77
|
+
};
|
78
|
+
},
|
79
|
+
fetchPlugins: [
|
80
|
+
{
|
81
|
+
id: "jazz-plugin",
|
82
|
+
name: "jazz-plugin",
|
83
|
+
hooks: {
|
84
|
+
async onRequest(context) {
|
85
|
+
if (
|
86
|
+
context.url.toString().includes("/sign-up") ||
|
87
|
+
context.url.toString().includes("/sign-in/social")
|
88
|
+
) {
|
89
|
+
const credentials = await authSecretStorage.get();
|
90
|
+
|
91
|
+
if (!credentials) {
|
92
|
+
throw new Error("Jazz credentials not found");
|
93
|
+
}
|
94
|
+
|
95
|
+
context.headers.set(
|
96
|
+
"x-jazz-auth",
|
97
|
+
JSON.stringify({
|
98
|
+
accountID: credentials.accountID,
|
99
|
+
secretSeed: credentials.secretSeed,
|
100
|
+
accountSecret: credentials.accountSecret,
|
101
|
+
}),
|
102
|
+
);
|
103
|
+
}
|
104
|
+
},
|
105
|
+
async onSuccess(context) {
|
106
|
+
if (context.request.url.toString().includes("/sign-up")) {
|
107
|
+
await authenticateOnJazz(context.data.jazzAuth);
|
108
|
+
return;
|
109
|
+
}
|
110
|
+
|
111
|
+
if (context.request.url.toString().includes("/sign-in/email")) {
|
112
|
+
await authenticateOnJazz(context.data.jazzAuth);
|
113
|
+
return;
|
114
|
+
}
|
115
|
+
|
116
|
+
if (context.request.url.toString().includes("/get-session")) {
|
117
|
+
if (context.data === null) {
|
118
|
+
if (authSecretStorage.isAuthenticated === true) {
|
119
|
+
console.warn(
|
120
|
+
"Jazz is authenticated, but the session is null",
|
121
|
+
);
|
122
|
+
}
|
123
|
+
return;
|
124
|
+
}
|
125
|
+
|
126
|
+
if (!context.data?.user) {
|
127
|
+
return;
|
128
|
+
}
|
129
|
+
|
130
|
+
if (authSecretStorage.isAuthenticated === false) {
|
131
|
+
console.info(
|
132
|
+
"Jazz is not authenticated, using Better Auth stored credentials",
|
133
|
+
);
|
134
|
+
await authenticateOnJazz(context.data.jazzAuth);
|
135
|
+
return;
|
136
|
+
}
|
137
|
+
|
138
|
+
const sessionAccountID = context.data.user.accountID;
|
139
|
+
|
140
|
+
const credentials = await authSecretStorage.get();
|
141
|
+
|
142
|
+
if (!credentials) {
|
143
|
+
throw new Error("Jazz credentials not found");
|
144
|
+
}
|
145
|
+
|
146
|
+
if (credentials.accountID !== sessionAccountID) {
|
147
|
+
console.info(
|
148
|
+
"Jazz credentials mismatch, using Better Auth stored credentials",
|
149
|
+
);
|
150
|
+
await authenticateOnJazz(context.data.jazzAuth);
|
151
|
+
}
|
152
|
+
return;
|
153
|
+
}
|
154
|
+
|
155
|
+
if (context.request.url.toString().includes("/sign-out")) {
|
156
|
+
await jazzContext.logOut();
|
157
|
+
return;
|
158
|
+
}
|
159
|
+
|
160
|
+
if (context.request.url.toString().includes("/delete-user")) {
|
161
|
+
await jazzContext.logOut();
|
162
|
+
return;
|
163
|
+
}
|
164
|
+
},
|
165
|
+
},
|
166
|
+
},
|
167
|
+
],
|
168
|
+
} satisfies BetterAuthClientPlugin;
|
169
|
+
};
|
@@ -0,0 +1,105 @@
|
|
1
|
+
"use client";
|
2
|
+
|
3
|
+
import type { ClientOptions } from "better-auth";
|
4
|
+
import { createAuthClient } from "better-auth/client";
|
5
|
+
import type {
|
6
|
+
Account,
|
7
|
+
AccountClass,
|
8
|
+
AnyAccountSchema,
|
9
|
+
CoValueFromRaw,
|
10
|
+
} from "jazz-tools";
|
11
|
+
import {
|
12
|
+
type JazzProviderProps,
|
13
|
+
JazzReactProvider,
|
14
|
+
useAuthSecretStorage,
|
15
|
+
useJazzContext,
|
16
|
+
} from "jazz-tools/react";
|
17
|
+
import { useEffect } from "react";
|
18
|
+
import { type PropsWithChildren, createContext } from "react";
|
19
|
+
import { jazzPluginClient } from "./client.js";
|
20
|
+
|
21
|
+
type AuthClient = ReturnType<
|
22
|
+
typeof createAuthClient<{
|
23
|
+
plugins: [ReturnType<typeof jazzPluginClient>];
|
24
|
+
}>
|
25
|
+
>;
|
26
|
+
|
27
|
+
export const AuthContext = createContext<AuthClient | null>(null);
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @param props.children - The children to render.
|
31
|
+
* @param props.betterAuthClient - The BetterAuth client with the Jazz plugin.
|
32
|
+
*
|
33
|
+
* @example
|
34
|
+
* ```ts
|
35
|
+
* const betterAuthClient = createAuthClient({
|
36
|
+
* plugins: [
|
37
|
+
* jazzPluginClient(),
|
38
|
+
* ],
|
39
|
+
* });
|
40
|
+
*
|
41
|
+
* <AuthProvider betterAuthClient={betterAuthClient}>
|
42
|
+
* <App />
|
43
|
+
* </AuthProvider>
|
44
|
+
* ```
|
45
|
+
*/
|
46
|
+
export function AuthProvider({
|
47
|
+
children,
|
48
|
+
betterAuthClient,
|
49
|
+
}: PropsWithChildren<{
|
50
|
+
betterAuthClient: AuthClient;
|
51
|
+
}>) {
|
52
|
+
const context = useJazzContext();
|
53
|
+
const authSecretStorage = useAuthSecretStorage();
|
54
|
+
|
55
|
+
if (betterAuthClient.jazz === undefined) {
|
56
|
+
throw new Error(
|
57
|
+
"Better Auth client has been initialized without the jazzPluginClient",
|
58
|
+
);
|
59
|
+
}
|
60
|
+
|
61
|
+
useEffect(() => {
|
62
|
+
betterAuthClient.jazz.setJazzContext(context);
|
63
|
+
betterAuthClient.jazz.setAuthSecretStorage(authSecretStorage);
|
64
|
+
|
65
|
+
// We need to subscribe to the session to let the plugin keep sync Jazz's and BetterAuth's session
|
66
|
+
return betterAuthClient.useSession.subscribe(() => {});
|
67
|
+
}, [betterAuthClient, context, authSecretStorage]);
|
68
|
+
|
69
|
+
return children;
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* @param props - The props for the JazzReactProvider.
|
74
|
+
* @param props.betterAuth - The options for the BetterAuth client.
|
75
|
+
* @returns The JazzReactProvider with the BetterAuth plugin.
|
76
|
+
*
|
77
|
+
* @example
|
78
|
+
* ```ts
|
79
|
+
* <JazzReactProviderWithBetterAuth
|
80
|
+
* betterAuth={{
|
81
|
+
* baseURL: "http://localhost:3000",
|
82
|
+
* }}
|
83
|
+
* sync={{
|
84
|
+
* peer: "ws://localhost:4200",
|
85
|
+
* }}
|
86
|
+
* >
|
87
|
+
* <App />
|
88
|
+
* </JazzReactProviderWithBetterAuth>
|
89
|
+
* ```
|
90
|
+
*/
|
91
|
+
export const JazzReactProviderWithBetterAuth = <
|
92
|
+
S extends
|
93
|
+
| (AccountClass<Account> & CoValueFromRaw<Account>)
|
94
|
+
| AnyAccountSchema,
|
95
|
+
>(
|
96
|
+
props: { betterAuthClient: AuthClient } & JazzProviderProps<S>,
|
97
|
+
) => {
|
98
|
+
return (
|
99
|
+
<JazzReactProvider {...props}>
|
100
|
+
<AuthProvider betterAuthClient={props.betterAuthClient}>
|
101
|
+
{props.children}
|
102
|
+
</AuthProvider>
|
103
|
+
</JazzReactProvider>
|
104
|
+
);
|
105
|
+
};
|
@@ -0,0 +1,250 @@
|
|
1
|
+
import { AuthContext, MiddlewareContext, MiddlewareOptions } from "better-auth";
|
2
|
+
import { APIError } from "better-auth/api";
|
3
|
+
import { symmetricDecrypt, symmetricEncrypt } from "better-auth/crypto";
|
4
|
+
import { BetterAuthPlugin, createAuthMiddleware } from "better-auth/plugins";
|
5
|
+
import type { Account, AuthCredentials, ID } from "jazz-tools";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @returns The BetterAuth server plugin.
|
9
|
+
*
|
10
|
+
* @example
|
11
|
+
* ```ts
|
12
|
+
* const auth = betterAuth({
|
13
|
+
* plugins: [jazzPlugin()],
|
14
|
+
* // ... other BetterAuth options
|
15
|
+
* });
|
16
|
+
* ```
|
17
|
+
*/
|
18
|
+
export const jazzPlugin = (): BetterAuthPlugin => {
|
19
|
+
return {
|
20
|
+
id: "jazz-plugin",
|
21
|
+
schema: {
|
22
|
+
user: {
|
23
|
+
fields: {
|
24
|
+
accountID: {
|
25
|
+
type: "string",
|
26
|
+
required: false,
|
27
|
+
input: false,
|
28
|
+
},
|
29
|
+
encryptedCredentials: {
|
30
|
+
type: "string",
|
31
|
+
required: false,
|
32
|
+
input: false,
|
33
|
+
returned: false,
|
34
|
+
},
|
35
|
+
},
|
36
|
+
},
|
37
|
+
},
|
38
|
+
|
39
|
+
init() {
|
40
|
+
return {
|
41
|
+
options: {
|
42
|
+
databaseHooks: {
|
43
|
+
user: {
|
44
|
+
create: {
|
45
|
+
before: async (user, context) => {
|
46
|
+
// If the user is created without a jazzAuth, it will throw an error.
|
47
|
+
if (!contextContainsJazzAuth(context)) {
|
48
|
+
throw new APIError(422, {
|
49
|
+
message: "JazzAuth is required",
|
50
|
+
});
|
51
|
+
}
|
52
|
+
// Decorate the user with the jazz's credentials.
|
53
|
+
return {
|
54
|
+
data: {
|
55
|
+
accountID: context?.jazzAuth?.accountID,
|
56
|
+
encryptedCredentials:
|
57
|
+
context?.jazzAuth?.encryptedCredentials,
|
58
|
+
},
|
59
|
+
};
|
60
|
+
},
|
61
|
+
},
|
62
|
+
},
|
63
|
+
verification: {
|
64
|
+
create: {
|
65
|
+
before: async (verification, context) => {
|
66
|
+
// If a jazzAuth is provided, save it for later usage.
|
67
|
+
if (contextContainsJazzAuth(context)) {
|
68
|
+
const parsed = JSON.parse(verification.value);
|
69
|
+
const newValue = JSON.stringify({
|
70
|
+
...parsed,
|
71
|
+
jazzAuth: context.jazzAuth,
|
72
|
+
});
|
73
|
+
|
74
|
+
return {
|
75
|
+
data: {
|
76
|
+
value: newValue,
|
77
|
+
},
|
78
|
+
};
|
79
|
+
}
|
80
|
+
},
|
81
|
+
},
|
82
|
+
},
|
83
|
+
},
|
84
|
+
},
|
85
|
+
};
|
86
|
+
},
|
87
|
+
|
88
|
+
hooks: {
|
89
|
+
before: [
|
90
|
+
/**
|
91
|
+
* If the client sends a x-jazz-auth header,
|
92
|
+
* we encrypt the credentials and inject them into the context.
|
93
|
+
*/
|
94
|
+
{
|
95
|
+
matcher: (context) => {
|
96
|
+
return !!context.headers?.get("x-jazz-auth");
|
97
|
+
},
|
98
|
+
handler: createAuthMiddleware(async (ctx) => {
|
99
|
+
const jazzAuth = JSON.parse(ctx.headers?.get("x-jazz-auth")!);
|
100
|
+
|
101
|
+
const credentials: AuthCredentials = {
|
102
|
+
accountID: jazzAuth.accountID as ID<Account>,
|
103
|
+
secretSeed: jazzAuth.secretSeed,
|
104
|
+
accountSecret: jazzAuth.accountSecret as any,
|
105
|
+
// If the provider remains 'anonymous', Jazz will not consider us authenticated later.
|
106
|
+
provider: "better-auth",
|
107
|
+
};
|
108
|
+
|
109
|
+
const encryptedCredentials = await symmetricEncrypt({
|
110
|
+
key: ctx.context.secret,
|
111
|
+
data: JSON.stringify(credentials),
|
112
|
+
});
|
113
|
+
|
114
|
+
return {
|
115
|
+
context: {
|
116
|
+
...ctx,
|
117
|
+
jazzAuth: {
|
118
|
+
accountID: jazzAuth.accountID,
|
119
|
+
encryptedCredentials: encryptedCredentials,
|
120
|
+
},
|
121
|
+
},
|
122
|
+
};
|
123
|
+
}),
|
124
|
+
},
|
125
|
+
|
126
|
+
/**
|
127
|
+
* /callback is the endpoint that BetterAuth uses to authenticate the user coming from a social provider.
|
128
|
+
* 1. Catch the state
|
129
|
+
* 2. Find the verification value
|
130
|
+
* 3. If the verification value contains a jazzAuth, inject into the context to have it in case of registration.
|
131
|
+
*/
|
132
|
+
{
|
133
|
+
matcher: (context) => {
|
134
|
+
return context.path.startsWith("/callback");
|
135
|
+
},
|
136
|
+
handler: createAuthMiddleware(async (ctx) => {
|
137
|
+
const state = ctx.query?.state || ctx.body?.state;
|
138
|
+
|
139
|
+
const data = await ctx.context.adapter.findOne<{ value: string }>({
|
140
|
+
model: ctx.context.tables.verification!.modelName,
|
141
|
+
where: [
|
142
|
+
{
|
143
|
+
field: "identifier",
|
144
|
+
operator: "eq",
|
145
|
+
value: state,
|
146
|
+
},
|
147
|
+
],
|
148
|
+
select: ["value"],
|
149
|
+
});
|
150
|
+
|
151
|
+
// if not found, the social plugin will throw later anyway
|
152
|
+
if (!data) {
|
153
|
+
throw new APIError(404, {
|
154
|
+
message: "Verification not found",
|
155
|
+
});
|
156
|
+
}
|
157
|
+
|
158
|
+
const parsed = JSON.parse(data.value);
|
159
|
+
|
160
|
+
if (parsed && "jazzAuth" in parsed) {
|
161
|
+
ctx.context.jazzAuth = parsed.jazzAuth;
|
162
|
+
} else {
|
163
|
+
throw new APIError(404, {
|
164
|
+
message: "JazzAuth not found in verification value",
|
165
|
+
});
|
166
|
+
}
|
167
|
+
}),
|
168
|
+
},
|
169
|
+
],
|
170
|
+
after: [
|
171
|
+
/**
|
172
|
+
* This middleware is used to extract the jazzAuth from the user and return it in the response.
|
173
|
+
* It is used in the following endpoints that return the user:
|
174
|
+
* - /sign-up/email
|
175
|
+
* - /sign-in/email
|
176
|
+
* - /get-session
|
177
|
+
*/
|
178
|
+
{
|
179
|
+
matcher: (context) => {
|
180
|
+
return (
|
181
|
+
context.path.startsWith("/sign-up") ||
|
182
|
+
context.path.startsWith("/sign-in") ||
|
183
|
+
context.path.startsWith("/get-session")
|
184
|
+
);
|
185
|
+
},
|
186
|
+
handler: createAuthMiddleware({}, async (ctx) => {
|
187
|
+
const returned = ctx.context.returned as any;
|
188
|
+
if (!returned?.user?.id) {
|
189
|
+
return;
|
190
|
+
}
|
191
|
+
const jazzAuth = await extractJazzAuth(returned.user.id, ctx);
|
192
|
+
|
193
|
+
return ctx.json({
|
194
|
+
...returned,
|
195
|
+
jazzAuth: jazzAuth,
|
196
|
+
});
|
197
|
+
}),
|
198
|
+
},
|
199
|
+
],
|
200
|
+
},
|
201
|
+
};
|
202
|
+
};
|
203
|
+
|
204
|
+
function contextContainsJazzAuth(ctx: unknown): ctx is {
|
205
|
+
jazzAuth: {
|
206
|
+
accountID: string;
|
207
|
+
encryptedCredentials: string;
|
208
|
+
};
|
209
|
+
} {
|
210
|
+
return !!ctx && typeof ctx === "object" && "jazzAuth" in ctx;
|
211
|
+
}
|
212
|
+
|
213
|
+
async function extractJazzAuth(
|
214
|
+
userId: string,
|
215
|
+
ctx: MiddlewareContext<
|
216
|
+
MiddlewareOptions,
|
217
|
+
AuthContext & {
|
218
|
+
returned?: unknown;
|
219
|
+
responseHeaders?: Headers;
|
220
|
+
}
|
221
|
+
>,
|
222
|
+
) {
|
223
|
+
const user = await ctx.context.adapter.findOne<{
|
224
|
+
accountID: string;
|
225
|
+
encryptedCredentials: string;
|
226
|
+
}>({
|
227
|
+
model: ctx.context.tables.user!.modelName,
|
228
|
+
where: [
|
229
|
+
{
|
230
|
+
field: "id",
|
231
|
+
operator: "eq",
|
232
|
+
value: userId,
|
233
|
+
},
|
234
|
+
],
|
235
|
+
select: ["accountID", "encryptedCredentials"],
|
236
|
+
});
|
237
|
+
|
238
|
+
if (!user) {
|
239
|
+
return;
|
240
|
+
}
|
241
|
+
|
242
|
+
const jazzAuth = JSON.parse(
|
243
|
+
await symmetricDecrypt({
|
244
|
+
key: ctx.context.secret,
|
245
|
+
data: user.encryptedCredentials,
|
246
|
+
}),
|
247
|
+
);
|
248
|
+
|
249
|
+
return jazzAuth;
|
250
|
+
}
|