jazz-tools 0.18.0 → 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.
Files changed (46) hide show
  1. package/.turbo/turbo-build.log +54 -40
  2. package/CHANGELOG.md +10 -0
  3. package/dist/better-auth/auth/client.d.ts +29 -0
  4. package/dist/better-auth/auth/client.d.ts.map +1 -0
  5. package/dist/better-auth/auth/client.js +127 -0
  6. package/dist/better-auth/auth/client.js.map +1 -0
  7. package/dist/better-auth/auth/react.d.ts +2170 -0
  8. package/dist/better-auth/auth/react.d.ts.map +1 -0
  9. package/dist/better-auth/auth/react.js +40 -0
  10. package/dist/better-auth/auth/react.js.map +1 -0
  11. package/dist/better-auth/auth/server.d.ts +14 -0
  12. package/dist/better-auth/auth/server.d.ts.map +1 -0
  13. package/dist/better-auth/auth/server.js +198 -0
  14. package/dist/better-auth/auth/server.js.map +1 -0
  15. package/dist/better-auth/auth/tests/client.test.d.ts +2 -0
  16. package/dist/better-auth/auth/tests/client.test.d.ts.map +1 -0
  17. package/dist/better-auth/auth/tests/server.test.d.ts +2 -0
  18. package/dist/better-auth/auth/tests/server.test.d.ts.map +1 -0
  19. package/dist/{chunk-HJ3GTGY7.js → chunk-IERUTUXB.js} +18 -1
  20. package/dist/chunk-IERUTUXB.js.map +1 -0
  21. package/dist/index.js +1 -1
  22. package/dist/react-core/index.js +17 -0
  23. package/dist/react-core/index.js.map +1 -1
  24. package/dist/testing.js +1 -1
  25. package/dist/tools/coValues/account.d.ts +1 -0
  26. package/dist/tools/coValues/account.d.ts.map +1 -1
  27. package/dist/tools/coValues/coMap.d.ts +10 -0
  28. package/dist/tools/coValues/coMap.d.ts.map +1 -1
  29. package/dist/tools/implementation/zodSchema/zodCo.d.ts +1 -1
  30. package/dist/tools/testing.d.ts.map +1 -1
  31. package/package.json +23 -4
  32. package/src/better-auth/auth/client.ts +169 -0
  33. package/src/better-auth/auth/react.tsx +105 -0
  34. package/src/better-auth/auth/server.ts +250 -0
  35. package/src/better-auth/auth/tests/client.test.ts +249 -0
  36. package/src/better-auth/auth/tests/server.test.ts +226 -0
  37. package/src/tools/coValues/account.ts +5 -0
  38. package/src/tools/coValues/coMap.ts +14 -0
  39. package/src/tools/implementation/zodSchema/zodCo.ts +1 -1
  40. package/src/tools/tests/ContextManager.test.ts +2 -2
  41. package/src/tools/tests/account.test.ts +51 -0
  42. package/src/tools/tests/coMap.test.ts +99 -0
  43. package/src/tools/tests/patterns/notifications.test.ts +1 -1
  44. package/src/tools/tests/testing.test.ts +2 -2
  45. package/tsup.config.ts +9 -0
  46. package/dist/chunk-HJ3GTGY7.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/better-auth/auth/react.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ "use client";
2
+
3
+ // src/better-auth/auth/react.tsx
4
+ import {
5
+ JazzReactProvider,
6
+ useAuthSecretStorage,
7
+ useJazzContext
8
+ } from "jazz-tools/react";
9
+ import { useEffect } from "react";
10
+ import { createContext } from "react";
11
+ import { jsx } from "react/jsx-runtime";
12
+ var AuthContext = createContext(null);
13
+ function AuthProvider({
14
+ children,
15
+ betterAuthClient
16
+ }) {
17
+ const context = useJazzContext();
18
+ const authSecretStorage = useAuthSecretStorage();
19
+ if (betterAuthClient.jazz === void 0) {
20
+ throw new Error(
21
+ "Better Auth client has been initialized without the jazzPluginClient"
22
+ );
23
+ }
24
+ useEffect(() => {
25
+ betterAuthClient.jazz.setJazzContext(context);
26
+ betterAuthClient.jazz.setAuthSecretStorage(authSecretStorage);
27
+ return betterAuthClient.useSession.subscribe(() => {
28
+ });
29
+ }, [betterAuthClient, context, authSecretStorage]);
30
+ return children;
31
+ }
32
+ var JazzReactProviderWithBetterAuth = (props) => {
33
+ return /* @__PURE__ */ jsx(JazzReactProvider, { ...props, children: /* @__PURE__ */ jsx(AuthProvider, { betterAuthClient: props.betterAuthClient, children: props.children }) });
34
+ };
35
+ export {
36
+ AuthContext,
37
+ AuthProvider,
38
+ JazzReactProviderWithBetterAuth
39
+ };
40
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/better-auth/auth/react.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ClientOptions } from \"better-auth\";\nimport { createAuthClient } from \"better-auth/client\";\nimport type {\n Account,\n AccountClass,\n AnyAccountSchema,\n CoValueFromRaw,\n} from \"jazz-tools\";\nimport {\n type JazzProviderProps,\n JazzReactProvider,\n useAuthSecretStorage,\n useJazzContext,\n} from \"jazz-tools/react\";\nimport { useEffect } from \"react\";\nimport { type PropsWithChildren, createContext } from \"react\";\nimport { jazzPluginClient } from \"./client.js\";\n\ntype AuthClient = ReturnType<\n typeof createAuthClient<{\n plugins: [ReturnType<typeof jazzPluginClient>];\n }>\n>;\n\nexport const AuthContext = createContext<AuthClient | null>(null);\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\n/**\n * @param props - The props for the JazzReactProvider.\n * @param props.betterAuth - The options for the BetterAuth client.\n * @returns The JazzReactProvider with the BetterAuth plugin.\n *\n * @example\n * ```ts\n * <JazzReactProviderWithBetterAuth\n * betterAuth={{\n * baseURL: \"http://localhost:3000\",\n * }}\n * sync={{\n * peer: \"ws://localhost:4200\",\n * }}\n * >\n * <App />\n * </JazzReactProviderWithBetterAuth>\n * ```\n */\nexport const JazzReactProviderWithBetterAuth = <\n S extends\n | (AccountClass<Account> & CoValueFromRaw<Account>)\n | AnyAccountSchema,\n>(\n props: { betterAuthClient: AuthClient } & JazzProviderProps<S>,\n) => {\n return (\n <JazzReactProvider {...props}>\n <AuthProvider betterAuthClient={props.betterAuthClient}>\n {props.children}\n </AuthProvider>\n </JazzReactProvider>\n );\n};\n"],"mappings":";;;AAUA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAiC,qBAAqB;AAkFhD;AAzEC,IAAM,cAAc,cAAiC,IAAI;AAmBzD,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;AAqBO,IAAM,kCAAkC,CAK7C,UACG;AACH,SACE,oBAAC,qBAAmB,GAAG,OACrB,8BAAC,gBAAa,kBAAkB,MAAM,kBACnC,gBAAM,UACT,GACF;AAEJ;","names":[]}
@@ -0,0 +1,14 @@
1
+ import { BetterAuthPlugin } from "better-auth/plugins";
2
+ /**
3
+ * @returns The BetterAuth server plugin.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * const auth = betterAuth({
8
+ * plugins: [jazzPlugin()],
9
+ * // ... other BetterAuth options
10
+ * });
11
+ * ```
12
+ */
13
+ export declare const jazzPlugin: () => BetterAuthPlugin;
14
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +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;AAG7E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,QAAO,gBAwL7B,CAAC"}
@@ -0,0 +1,198 @@
1
+ // src/better-auth/auth/server.ts
2
+ import { APIError } from "better-auth/api";
3
+ import { symmetricDecrypt, symmetricEncrypt } from "better-auth/crypto";
4
+ import { createAuthMiddleware } from "better-auth/plugins";
5
+ var jazzPlugin = () => {
6
+ return {
7
+ id: "jazz-plugin",
8
+ schema: {
9
+ user: {
10
+ fields: {
11
+ accountID: {
12
+ type: "string",
13
+ required: false,
14
+ input: false
15
+ },
16
+ encryptedCredentials: {
17
+ type: "string",
18
+ required: false,
19
+ input: false,
20
+ returned: false
21
+ }
22
+ }
23
+ }
24
+ },
25
+ init() {
26
+ return {
27
+ options: {
28
+ databaseHooks: {
29
+ user: {
30
+ create: {
31
+ before: async (user, context) => {
32
+ if (!contextContainsJazzAuth(context)) {
33
+ throw new APIError(422, {
34
+ message: "JazzAuth is required"
35
+ });
36
+ }
37
+ return {
38
+ data: {
39
+ accountID: context?.jazzAuth?.accountID,
40
+ encryptedCredentials: context?.jazzAuth?.encryptedCredentials
41
+ }
42
+ };
43
+ }
44
+ }
45
+ },
46
+ verification: {
47
+ create: {
48
+ before: async (verification, context) => {
49
+ if (contextContainsJazzAuth(context)) {
50
+ const parsed = JSON.parse(verification.value);
51
+ const newValue = JSON.stringify({
52
+ ...parsed,
53
+ jazzAuth: context.jazzAuth
54
+ });
55
+ return {
56
+ data: {
57
+ value: newValue
58
+ }
59
+ };
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ };
67
+ },
68
+ hooks: {
69
+ before: [
70
+ /**
71
+ * If the client sends a x-jazz-auth header,
72
+ * we encrypt the credentials and inject them into the context.
73
+ */
74
+ {
75
+ matcher: (context) => {
76
+ return !!context.headers?.get("x-jazz-auth");
77
+ },
78
+ handler: createAuthMiddleware(async (ctx) => {
79
+ const jazzAuth = JSON.parse(ctx.headers?.get("x-jazz-auth"));
80
+ const credentials = {
81
+ accountID: jazzAuth.accountID,
82
+ secretSeed: jazzAuth.secretSeed,
83
+ accountSecret: jazzAuth.accountSecret,
84
+ // If the provider remains 'anonymous', Jazz will not consider us authenticated later.
85
+ provider: "better-auth"
86
+ };
87
+ const encryptedCredentials = await symmetricEncrypt({
88
+ key: ctx.context.secret,
89
+ data: JSON.stringify(credentials)
90
+ });
91
+ return {
92
+ context: {
93
+ ...ctx,
94
+ jazzAuth: {
95
+ accountID: jazzAuth.accountID,
96
+ encryptedCredentials
97
+ }
98
+ }
99
+ };
100
+ })
101
+ },
102
+ /**
103
+ * /callback is the endpoint that BetterAuth uses to authenticate the user coming from a social provider.
104
+ * 1. Catch the state
105
+ * 2. Find the verification value
106
+ * 3. If the verification value contains a jazzAuth, inject into the context to have it in case of registration.
107
+ */
108
+ {
109
+ matcher: (context) => {
110
+ return context.path.startsWith("/callback");
111
+ },
112
+ handler: createAuthMiddleware(async (ctx) => {
113
+ const state = ctx.query?.state || ctx.body?.state;
114
+ const data = await ctx.context.adapter.findOne({
115
+ model: ctx.context.tables.verification.modelName,
116
+ where: [
117
+ {
118
+ field: "identifier",
119
+ operator: "eq",
120
+ value: state
121
+ }
122
+ ],
123
+ select: ["value"]
124
+ });
125
+ if (!data) {
126
+ throw new APIError(404, {
127
+ message: "Verification not found"
128
+ });
129
+ }
130
+ const parsed = JSON.parse(data.value);
131
+ if (parsed && "jazzAuth" in parsed) {
132
+ ctx.context.jazzAuth = parsed.jazzAuth;
133
+ } else {
134
+ throw new APIError(404, {
135
+ message: "JazzAuth not found in verification value"
136
+ });
137
+ }
138
+ })
139
+ }
140
+ ],
141
+ after: [
142
+ /**
143
+ * This middleware is used to extract the jazzAuth from the user and return it in the response.
144
+ * It is used in the following endpoints that return the user:
145
+ * - /sign-up/email
146
+ * - /sign-in/email
147
+ * - /get-session
148
+ */
149
+ {
150
+ matcher: (context) => {
151
+ return context.path.startsWith("/sign-up") || context.path.startsWith("/sign-in") || context.path.startsWith("/get-session");
152
+ },
153
+ handler: createAuthMiddleware({}, async (ctx) => {
154
+ const returned = ctx.context.returned;
155
+ if (!returned?.user?.id) {
156
+ return;
157
+ }
158
+ const jazzAuth = await extractJazzAuth(returned.user.id, ctx);
159
+ return ctx.json({
160
+ ...returned,
161
+ jazzAuth
162
+ });
163
+ })
164
+ }
165
+ ]
166
+ }
167
+ };
168
+ };
169
+ function contextContainsJazzAuth(ctx) {
170
+ return !!ctx && typeof ctx === "object" && "jazzAuth" in ctx;
171
+ }
172
+ async function extractJazzAuth(userId, ctx) {
173
+ const user = await ctx.context.adapter.findOne({
174
+ model: ctx.context.tables.user.modelName,
175
+ where: [
176
+ {
177
+ field: "id",
178
+ operator: "eq",
179
+ value: userId
180
+ }
181
+ ],
182
+ select: ["accountID", "encryptedCredentials"]
183
+ });
184
+ if (!user) {
185
+ return;
186
+ }
187
+ const jazzAuth = JSON.parse(
188
+ await symmetricDecrypt({
189
+ key: ctx.context.secret,
190
+ data: user.encryptedCredentials
191
+ })
192
+ );
193
+ return jazzAuth;
194
+ }
195
+ export {
196
+ jazzPlugin
197
+ };
198
+ //# sourceMappingURL=server.js.map
@@ -0,0 +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/**\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 = (): BetterAuthPlugin => {\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\",\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 context.path.startsWith(\"/callback\");\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 ctx.context.jazzAuth = parsed.jazzAuth;\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 };\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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../../../src/better-auth/auth/tests/client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=server.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../../../../src/better-auth/auth/tests/server.test.ts"],"names":[],"mappings":""}
@@ -476,6 +476,19 @@ var CoMapJazzApi = class extends CoValueJazzApi {
476
476
  get owner() {
477
477
  return getCoValueOwner(this.coMap);
478
478
  }
479
+ /**
480
+ * Check if a key is defined in the CoMap.
481
+ *
482
+ * This check does not load the referenced value or validate permissions.
483
+ *
484
+ * @param key The key to check
485
+ * @returns True if the key is defined, false otherwise
486
+ * @category Content
487
+ */
488
+ has(key) {
489
+ const entry = this.raw.getRaw(key);
490
+ return entry?.change !== void 0 && entry.change.op !== "del";
491
+ }
479
492
  /**
480
493
  * Set a value on the CoMap
481
494
  *
@@ -2299,6 +2312,10 @@ var AccountJazzApi = class extends CoValueJazzApi {
2299
2312
  this.raw.set(key, refId, "trusting");
2300
2313
  }
2301
2314
  }
2315
+ has(key) {
2316
+ const entry = this.raw.getRaw(key);
2317
+ return entry?.change !== void 0 && entry.change.op !== "del";
2318
+ }
2302
2319
  /**
2303
2320
  * Get the descriptor for a given key
2304
2321
  * @internal
@@ -5714,4 +5731,4 @@ export {
5714
5731
  JazzContextManager
5715
5732
  };
5716
5733
  /* istanbul ignore file -- @preserve */
5717
- //# sourceMappingURL=chunk-HJ3GTGY7.js.map
5734
+ //# sourceMappingURL=chunk-IERUTUXB.js.map