better-auth 1.6.17 → 1.6.19

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.
@@ -1,92 +1,172 @@
1
1
  import { db_exports } from "../../db/index.mjs";
2
2
  import { getEndpoints } from "../../api/index.mjs";
3
3
  import * as z from "zod";
4
- import { toPascalCase } from "@better-auth/core/utils/string";
5
4
  //#region src/plugins/open-api/generator.ts
6
- const allowedType = new Set([
5
+ const OPEN_API_SCHEMA_TYPES = new Set([
7
6
  "string",
8
7
  "number",
9
8
  "boolean",
10
9
  "array",
11
10
  "object"
12
11
  ]);
13
- function getTypeFromZodType(zodType) {
14
- if (zodType instanceof z.ZodDefault) return getTypeFromZodType(zodType.unwrap());
12
+ function getOpenApiTypeFromZodType(zodType) {
13
+ if (zodType instanceof z.ZodDefault || zodType instanceof z.ZodPrefault) return getOpenApiTypeFromZodType(unwrapZodSchema(zodType));
15
14
  const type = zodType.type;
16
- return allowedType.has(type) ? type : "string";
15
+ return OPEN_API_SCHEMA_TYPES.has(type) ? type : "string";
17
16
  }
18
17
  function getFieldSchema(field) {
19
18
  const schema = {
20
19
  type: field.type === "date" ? "string" : field.type,
21
20
  ...field.type === "date" && { format: "date-time" }
22
21
  };
23
- if (field.defaultValue !== void 0) schema.default = typeof field.defaultValue === "function" ? "Generated at runtime" : field.defaultValue;
22
+ if (field.defaultValue !== void 0) {
23
+ if (typeof field.defaultValue !== "function") schema.default = field.defaultValue;
24
+ }
24
25
  if (field.input === false) schema.readOnly = true;
25
26
  return schema;
26
27
  }
28
+ function asZodSchema(schema) {
29
+ return schema;
30
+ }
31
+ function unwrapZodSchema(zodType) {
32
+ return asZodSchema(zodType.unwrap());
33
+ }
34
+ function getZodDef(zodType) {
35
+ return zodType._def;
36
+ }
37
+ function getZodDescription(zodType) {
38
+ return zodType.description;
39
+ }
40
+ function withDescription(schema, zodType) {
41
+ const description = getZodDescription(zodType);
42
+ return description ? {
43
+ ...schema,
44
+ description
45
+ } : schema;
46
+ }
47
+ function addNullType(schema) {
48
+ if (schema.type) {
49
+ const type = Array.isArray(schema.type) ? schema.type : [schema.type];
50
+ const nullableType = Array.from(new Set([...type, "null"]));
51
+ return {
52
+ ...schema,
53
+ type: nullableType
54
+ };
55
+ }
56
+ return { anyOf: [schema, { type: "null" }] };
57
+ }
58
+ function getZodStringSchemaConstraints(zodType) {
59
+ const minLength = zodType.minLength;
60
+ const maxLength = zodType.maxLength;
61
+ return {
62
+ ...typeof minLength === "number" ? { minLength } : {},
63
+ ...typeof maxLength === "number" ? { maxLength } : {}
64
+ };
65
+ }
66
+ function getZodPipeSchema(zodType) {
67
+ const def = getZodDef(zodType);
68
+ return def.in instanceof z.ZodTransform && def.out instanceof z.ZodType ? def.out : def.in;
69
+ }
27
70
  function getParameters(options) {
28
71
  const parameters = [];
29
- if (options.metadata?.openapi?.parameters) {
30
- parameters.push(...options.metadata.openapi.parameters);
31
- return parameters;
32
- }
33
- if (options.query instanceof z.ZodObject) Object.entries(options.query.shape).forEach(([key, value]) => {
34
- if (value instanceof z.ZodType) parameters.push({
35
- name: key,
36
- in: "query",
37
- schema: {
38
- ...processZodType(value),
39
- ..."minLength" in value && value.minLength ? { minLength: value.minLength } : {}
40
- }
41
- });
72
+ if (options.metadata?.openapi?.parameters) parameters.push(...options.metadata.openapi.parameters);
73
+ if (!options.metadata?.openapi?.parameters && options.query instanceof z.ZodObject) Object.entries(options.query.shape).forEach(([key, value]) => {
74
+ if (value instanceof z.ZodType) {
75
+ const parameterSchema = toOpenApiSchema(value);
76
+ parameters.push({
77
+ name: key,
78
+ in: "query",
79
+ schema: parameterSchema
80
+ });
81
+ }
42
82
  });
43
83
  return parameters;
44
84
  }
85
+ function getPathParameters(path, parameters) {
86
+ const existingParameters = new Set(parameters.map((parameter) => `${parameter.in}:${parameter.name}`));
87
+ return path.split("/").filter((part) => part.startsWith(":")).map((part) => part.slice(1)).filter((name) => !existingParameters.has(`path:${name}`)).map((name) => ({
88
+ name,
89
+ in: "path",
90
+ required: true,
91
+ schema: { type: "string" }
92
+ }));
93
+ }
94
+ function getRequestBodySchemaInfo(zodType) {
95
+ return {
96
+ required: !schemaAcceptsUndefined(zodType),
97
+ schema: zodType
98
+ };
99
+ }
100
+ function schemaAcceptsUndefined(zodType) {
101
+ if (zodType instanceof z.ZodOptional || zodType instanceof z.ZodDefault || zodType instanceof z.ZodPrefault || zodType instanceof z.ZodCatch || zodType instanceof z.ZodUndefined || zodType instanceof z.ZodVoid) return true;
102
+ if (zodType instanceof z.ZodNonOptional) return false;
103
+ if (zodType instanceof z.ZodNullable || zodType instanceof z.ZodReadonly) return schemaAcceptsUndefined(unwrapZodSchema(zodType));
104
+ if (zodType instanceof z.ZodPipe) return schemaAcceptsUndefined(getZodPipeSchema(zodType));
105
+ if (zodType instanceof z.ZodUnion) return getZodDef(zodType).options.some((option) => schemaAcceptsUndefined(option));
106
+ if (zodType instanceof z.ZodIntersection) {
107
+ const def = getZodDef(zodType);
108
+ return schemaAcceptsUndefined(def.left) && schemaAcceptsUndefined(def.right);
109
+ }
110
+ return false;
111
+ }
112
+ function isUndefinedOnlySchema(zodType) {
113
+ return zodType instanceof z.ZodUndefined || zodType instanceof z.ZodVoid;
114
+ }
115
+ function isMergeableObjectSchema(schema) {
116
+ const type = schema?.type;
117
+ return !!schema && (type === "object" || Array.isArray(type) && type.includes("object")) && schema.$ref === void 0 && schema.allOf === void 0 && schema.anyOf === void 0;
118
+ }
119
+ function schemaAllowsNull(schema) {
120
+ const type = schema?.type;
121
+ return Array.isArray(type) && type.includes("null");
122
+ }
123
+ function areSchemasEqual(left, right) {
124
+ return JSON.stringify(left) === JSON.stringify(right);
125
+ }
126
+ function areSchemaMembersCompatible(left, right) {
127
+ if (left === void 0 || right === void 0) return true;
128
+ if (typeof left === "boolean" || typeof right === "boolean") return left === right;
129
+ return areSchemasEqual(left, right);
130
+ }
131
+ function mergeObjectSchemas(left, right, description) {
132
+ const properties = { ...left.properties || {} };
133
+ for (const [key, value] of Object.entries(right.properties || {})) {
134
+ if (properties[key] !== void 0 && !areSchemasEqual(properties[key], value)) return;
135
+ properties[key] = value;
136
+ }
137
+ const required = Array.from(new Set([...left.required || [], ...right.required || []]));
138
+ const leftAdditionalProperties = left.additionalProperties;
139
+ const rightAdditionalProperties = right.additionalProperties;
140
+ if (!areSchemaMembersCompatible(leftAdditionalProperties, rightAdditionalProperties)) return;
141
+ const leftPropertyNames = left.propertyNames;
142
+ const rightPropertyNames = right.propertyNames;
143
+ if (!areSchemaMembersCompatible(leftPropertyNames, rightPropertyNames)) return;
144
+ const additionalProperties = leftAdditionalProperties ?? rightAdditionalProperties;
145
+ const propertyNames = leftPropertyNames ?? rightPropertyNames;
146
+ return {
147
+ type: schemaAllowsNull(left) && schemaAllowsNull(right) ? ["object", "null"] : "object",
148
+ ...Object.keys(properties).length > 0 ? { properties } : {},
149
+ ...required.length > 0 ? { required } : {},
150
+ ...additionalProperties !== void 0 ? { additionalProperties } : {},
151
+ ...propertyNames !== void 0 ? { propertyNames } : {},
152
+ ...description ?? left.description ?? right.description ? { description: description ?? left.description ?? right.description } : {}
153
+ };
154
+ }
45
155
  function getRequestBody(options) {
46
156
  if (options.metadata?.openapi?.requestBody) return options.metadata.openapi.requestBody;
47
157
  if (!options.body) return void 0;
48
- if (options.body instanceof z.ZodObject || options.body instanceof z.ZodOptional) {
49
- const shape = options.body.shape;
50
- if (!shape) return void 0;
51
- const properties = {};
52
- const required = [];
53
- Object.entries(shape).forEach(([key, value]) => {
54
- if (value instanceof z.ZodType) {
55
- properties[key] = processZodType(value);
56
- if (!(value instanceof z.ZodOptional)) required.push(key);
57
- }
58
- });
59
- return {
60
- required: options.body instanceof z.ZodOptional ? false : options.body ? true : false,
61
- content: { "application/json": { schema: {
62
- type: "object",
63
- properties,
64
- required
65
- } } }
66
- };
67
- }
158
+ const requestBodySchemaInfo = getRequestBodySchemaInfo(options.body);
159
+ const schema = toOpenApiSchema(requestBodySchemaInfo.schema);
160
+ return {
161
+ required: requestBodySchemaInfo.required,
162
+ content: { "application/json": { schema } }
163
+ };
68
164
  }
69
- function processZodType(zodType) {
70
- if (zodType instanceof z.ZodOptional) {
71
- const innerSchema = processZodType(zodType.unwrap());
72
- if (innerSchema.type) {
73
- const type = Array.isArray(innerSchema.type) ? innerSchema.type : [innerSchema.type];
74
- return {
75
- ...innerSchema,
76
- type: Array.from(new Set([...type, "null"]))
77
- };
78
- }
79
- return { anyOf: [innerSchema, { type: "null" }] };
80
- }
81
- if (zodType instanceof z.ZodDefault) {
82
- const innerSchema = processZodType(zodType.unwrap());
83
- const defaultValueDef = zodType._def.defaultValue;
84
- const defaultValue = typeof defaultValueDef === "function" ? defaultValueDef() : defaultValueDef;
85
- return {
86
- ...innerSchema,
87
- default: defaultValue
88
- };
89
- }
165
+ function toOpenApiSchema(zodType) {
166
+ if (zodType instanceof z.ZodOptional) return toOpenApiSchema(unwrapZodSchema(zodType));
167
+ if (zodType instanceof z.ZodNullable) return addNullType(toOpenApiSchema(unwrapZodSchema(zodType)));
168
+ if (zodType instanceof z.ZodDefault || zodType instanceof z.ZodPrefault || zodType instanceof z.ZodNonOptional) return toOpenApiSchema(unwrapZodSchema(zodType));
169
+ if (zodType instanceof z.ZodAny) return withDescription({}, zodType);
90
170
  if (zodType instanceof z.ZodObject) {
91
171
  const shape = zodType.shape;
92
172
  if (shape) {
@@ -94,22 +174,64 @@ function processZodType(zodType) {
94
174
  const required = [];
95
175
  Object.entries(shape).forEach(([key, value]) => {
96
176
  if (value instanceof z.ZodType) {
97
- properties[key] = processZodType(value);
98
- if (!(value instanceof z.ZodOptional)) required.push(key);
177
+ properties[key] = toOpenApiSchema(value);
178
+ if (!schemaAcceptsUndefined(value)) required.push(key);
99
179
  }
100
180
  });
101
- return {
181
+ return withDescription({
102
182
  type: "object",
103
183
  properties,
104
- ...required.length > 0 ? { required } : {},
105
- description: zodType.description
106
- };
184
+ ...required.length > 0 ? { required } : {}
185
+ }, zodType);
107
186
  }
108
187
  }
109
- return {
110
- type: getTypeFromZodType(zodType),
111
- description: zodType.description
112
- };
188
+ if (zodType instanceof z.ZodRecord) {
189
+ const def = getZodDef(zodType);
190
+ return withDescription({
191
+ type: "object",
192
+ propertyNames: toOpenApiSchema(def.keyType),
193
+ additionalProperties: toOpenApiSchema(def.valueType)
194
+ }, zodType);
195
+ }
196
+ if (zodType instanceof z.ZodIntersection) {
197
+ const def = getZodDef(zodType);
198
+ const leftSchema = toOpenApiSchema(def.left);
199
+ const rightSchema = toOpenApiSchema(def.right);
200
+ if (isMergeableObjectSchema(leftSchema) && isMergeableObjectSchema(rightSchema)) {
201
+ const mergedSchema = mergeObjectSchemas(leftSchema, rightSchema, getZodDescription(zodType));
202
+ if (mergedSchema) return mergedSchema;
203
+ }
204
+ return withDescription({ allOf: [leftSchema, rightSchema] }, zodType);
205
+ }
206
+ if (zodType instanceof z.ZodUnion) {
207
+ const def = getZodDef(zodType);
208
+ const schemas = def.options.filter((option) => !isUndefinedOnlySchema(option)).map((option) => toOpenApiSchema(option));
209
+ if (schemas.length === 0) return withDescription({}, zodType);
210
+ if (schemas.length === 1) {
211
+ const schema = schemas[0];
212
+ if (!schema) return withDescription({}, zodType);
213
+ return withDescription(schema, zodType);
214
+ }
215
+ return withDescription(def.inclusive === false ? { oneOf: schemas } : { anyOf: schemas }, zodType);
216
+ }
217
+ if (zodType instanceof z.ZodArray) return withDescription({
218
+ type: "array",
219
+ items: toOpenApiSchema(getZodDef(zodType).element)
220
+ }, zodType);
221
+ if (zodType instanceof z.ZodLiteral) return withDescription({ enum: Array.from(zodType.values) }, zodType);
222
+ if (zodType instanceof z.ZodEnum) return withDescription({
223
+ type: "string",
224
+ enum: zodType.options
225
+ }, zodType);
226
+ if (zodType instanceof z.ZodPipe) return withDescription(toOpenApiSchema(getZodPipeSchema(zodType)), zodType);
227
+ if (zodType instanceof z.ZodCatch || zodType instanceof z.ZodReadonly) return withDescription(toOpenApiSchema(getZodDef(zodType).innerType), zodType);
228
+ if (zodType instanceof z.ZodNull) return withDescription({ type: "null" }, zodType);
229
+ if (zodType instanceof z.ZodUndefined) return withDescription({}, zodType);
230
+ if (zodType instanceof z.ZodVoid) return withDescription({}, zodType);
231
+ return withDescription({
232
+ type: getOpenApiTypeFromZodType(zodType),
233
+ ...zodType instanceof z.ZodString ? getZodStringSchemaConstraints(zodType) : {}
234
+ }, zodType);
113
235
  }
114
236
  function getResponse(responses) {
115
237
  return {
@@ -163,6 +285,29 @@ function getResponse(responses) {
163
285
  function toOpenApiPath(path) {
164
286
  return path.split("/").map((part) => part.startsWith(":") ? `{${part.slice(1)}}` : part).join("/");
165
287
  }
288
+ function getOperationId(operationId, method, usedOperationIds) {
289
+ if (!operationId) return;
290
+ if (!usedOperationIds.has(operationId)) {
291
+ usedOperationIds.add(operationId);
292
+ return operationId;
293
+ }
294
+ const normalizedMethod = method.toUpperCase();
295
+ const methodSuffix = normalizedMethod.charAt(0) + normalizedMethod.slice(1).toLowerCase();
296
+ let candidate = `${operationId}${methodSuffix}`;
297
+ let duplicateIndex = 2;
298
+ while (usedOperationIds.has(candidate)) {
299
+ candidate = `${operationId}${methodSuffix}${duplicateIndex}`;
300
+ duplicateIndex += 1;
301
+ }
302
+ usedOperationIds.add(candidate);
303
+ return candidate;
304
+ }
305
+ function cloneOpenAPIValue(value) {
306
+ if (Array.isArray(value)) return value.map((item) => cloneOpenAPIValue(item));
307
+ if (value instanceof Date) return new Date(value);
308
+ if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, cloneOpenAPIValue(entry)]));
309
+ return value;
310
+ }
166
311
  async function generator(ctx, options) {
167
312
  const baseEndpoints = getEndpoints(ctx, {
168
313
  ...options,
@@ -200,31 +345,24 @@ async function generator(ctx, options) {
200
345
  return acc;
201
346
  }, {}) } };
202
347
  const paths = {};
203
- const seenOperationIds = /* @__PURE__ */ new Set();
204
- const uniqueOperationId = (operationId, method) => {
205
- if (!operationId) return void 0;
206
- const base = seenOperationIds.has(operationId) ? `${operationId}${toPascalCase(method)}` : operationId;
207
- let result = base;
208
- let n = 2;
209
- while (seenOperationIds.has(result)) result = `${base}${n++}`;
210
- seenOperationIds.add(result);
211
- return result;
212
- };
348
+ const usedOperationIds = /* @__PURE__ */ new Set();
213
349
  Object.entries(baseEndpoints.api).forEach(([_, value]) => {
214
350
  if (!value.path || ctx.options.disabledPaths?.includes(value.path)) return;
215
351
  const options = value.options;
216
352
  if (options.metadata?.SERVER_ONLY) return;
217
353
  const path = toOpenApiPath(value.path);
354
+ const operationParameters = getParameters(options);
355
+ const parameters = [...operationParameters, ...getPathParameters(value.path, operationParameters)];
218
356
  const methods = Array.isArray(options.method) ? options.method : [options.method];
219
357
  for (const method of methods.filter((m) => m === "GET" || m === "DELETE")) paths[path] = {
220
358
  ...paths[path],
221
359
  [method.toLowerCase()]: {
222
360
  tags: ["Default", ...options.metadata?.openapi?.tags || []],
223
361
  description: options.metadata?.openapi?.description,
224
- operationId: uniqueOperationId(options.metadata?.openapi?.operationId, method),
362
+ operationId: getOperationId(options.metadata?.openapi?.operationId, method, usedOperationIds),
225
363
  security: [{ bearerAuth: [] }],
226
- parameters: getParameters(options),
227
- responses: getResponse(options.metadata?.openapi?.responses)
364
+ parameters: cloneOpenAPIValue(parameters),
365
+ responses: cloneOpenAPIValue(getResponse(options.metadata?.openapi?.responses))
228
366
  }
229
367
  };
230
368
  for (const method of methods.filter((m) => m === "POST" || m === "PATCH" || m === "PUT")) {
@@ -234,14 +372,14 @@ async function generator(ctx, options) {
234
372
  [method.toLowerCase()]: {
235
373
  tags: ["Default", ...options.metadata?.openapi?.tags || []],
236
374
  description: options.metadata?.openapi?.description,
237
- operationId: uniqueOperationId(options.metadata?.openapi?.operationId, method),
375
+ operationId: getOperationId(options.metadata?.openapi?.operationId, method, usedOperationIds),
238
376
  security: [{ bearerAuth: [] }],
239
- parameters: getParameters(options),
240
- ...body ? { requestBody: body } : { requestBody: { content: { "application/json": { schema: {
377
+ parameters: cloneOpenAPIValue(parameters),
378
+ ...body ? { requestBody: cloneOpenAPIValue(body) } : { requestBody: { content: { "application/json": { schema: {
241
379
  type: "object",
242
380
  properties: {}
243
381
  } } } } },
244
- responses: getResponse(options.metadata?.openapi?.responses)
382
+ responses: cloneOpenAPIValue(getResponse(options.metadata?.openapi?.responses))
245
383
  }
246
384
  };
247
385
  }
@@ -261,16 +399,18 @@ async function generator(ctx, options) {
261
399
  const options = value.options;
262
400
  if (options.metadata?.SERVER_ONLY) return;
263
401
  const path = toOpenApiPath(value.path);
402
+ const operationParameters = getParameters(options);
403
+ const parameters = [...operationParameters, ...getPathParameters(value.path, operationParameters)];
264
404
  const methods = Array.isArray(options.method) ? options.method : [options.method];
265
405
  for (const method of methods.filter((m) => m === "GET" || m === "DELETE")) paths[path] = {
266
406
  ...paths[path],
267
407
  [method.toLowerCase()]: {
268
408
  tags: options.metadata?.openapi?.tags || [plugin.id.charAt(0).toUpperCase() + plugin.id.slice(1)],
269
409
  description: options.metadata?.openapi?.description,
270
- operationId: uniqueOperationId(options.metadata?.openapi?.operationId, method),
410
+ operationId: getOperationId(options.metadata?.openapi?.operationId, method, usedOperationIds),
271
411
  security: [{ bearerAuth: [] }],
272
- parameters: getParameters(options),
273
- responses: getResponse(options.metadata?.openapi?.responses)
412
+ parameters: cloneOpenAPIValue(parameters),
413
+ responses: cloneOpenAPIValue(getResponse(options.metadata?.openapi?.responses))
274
414
  }
275
415
  };
276
416
  for (const method of methods.filter((m) => m === "POST" || m === "PATCH" || m === "PUT")) paths[path] = {
@@ -278,11 +418,11 @@ async function generator(ctx, options) {
278
418
  [method.toLowerCase()]: {
279
419
  tags: options.metadata?.openapi?.tags || [plugin.id.charAt(0).toUpperCase() + plugin.id.slice(1)],
280
420
  description: options.metadata?.openapi?.description,
281
- operationId: uniqueOperationId(options.metadata?.openapi?.operationId, method),
421
+ operationId: getOperationId(options.metadata?.openapi?.operationId, method, usedOperationIds),
282
422
  security: [{ bearerAuth: [] }],
283
- parameters: getParameters(options),
284
- requestBody: getRequestBody(options),
285
- responses: getResponse(options.metadata?.openapi?.responses)
423
+ parameters: cloneOpenAPIValue(parameters),
424
+ requestBody: cloneOpenAPIValue(getRequestBody(options)),
425
+ responses: cloneOpenAPIValue(getResponse(options.metadata?.openapi?.responses))
286
426
  }
287
427
  };
288
428
  });
@@ -1,4 +1,4 @@
1
- import { FieldSchema, OpenAPIModelSchema, Path, generator } from "./generator.mjs";
1
+ import { FieldSchema, OpenAPIModelSchema, OpenAPIParameter, OpenAPISchema, Path, generator } from "./generator.mjs";
2
2
  import { LiteralString } from "@better-auth/core";
3
3
  import * as better_call0 from "better-call";
4
4
 
@@ -94,4 +94,4 @@ declare const openAPI: <O extends OpenAPIOptions>(options?: O | undefined) => {
94
94
  options: NoInfer<O>;
95
95
  };
96
96
  //#endregion
97
- export { type FieldSchema, type OpenAPIModelSchema, OpenAPIOptions, type Path, generator, openAPI };
97
+ export { type FieldSchema, type OpenAPIModelSchema, OpenAPIOptions, OpenAPIParameter, OpenAPISchema, type Path, generator, openAPI };
@@ -678,10 +678,11 @@ const getOrgAdapter = (context, options) => {
678
678
  field: "status",
679
679
  value: data.fromStatus
680
680
  });
681
- return await adapter.update({
681
+ return await adapter.incrementOne({
682
682
  model: "invitation",
683
683
  where,
684
- update: { status: data.status }
684
+ increment: {},
685
+ set: { status: data.status }
685
686
  });
686
687
  }
687
688
  };
@@ -564,7 +564,7 @@ const updateOrgRole = (options) => {
564
564
  ...updateData,
565
565
  ...updateData.permission ? { permission: JSON.stringify(updateData.permission) } : {}
566
566
  };
567
- await ctx.context.adapter.update({
567
+ await ctx.context.adapter.updateMany({
568
568
  model: "organizationRole",
569
569
  where: [{
570
570
  field: "organizationId",
@@ -177,16 +177,17 @@ const backupCode2fa = (opts) => {
177
177
  }, ctx.context.secretConfig, opts);
178
178
  if (!validate.status || !validate.updated) throw APIError.from("UNAUTHORIZED", TWO_FACTOR_ERROR_CODES.INVALID_BACKUP_CODE);
179
179
  const updatedBackupCodes = await encodeBackupCodes(validate.updated, ctx.context.secretConfig, opts);
180
- if (!await ctx.context.adapter.update({
180
+ if (!await ctx.context.adapter.incrementOne({
181
181
  model: twoFactorTable,
182
- update: { backupCodes: updatedBackupCodes },
183
182
  where: [{
184
183
  field: "id",
185
184
  value: twoFactor.id
186
185
  }, {
187
186
  field: "backupCodes",
188
187
  value: twoFactor.backupCodes
189
- }]
188
+ }],
189
+ increment: {},
190
+ set: { backupCodes: updatedBackupCodes }
190
191
  })) throw APIError.fromStatus("CONFLICT", { message: "Failed to verify backup code. Please try again." });
191
192
  if (!ctx.body.disableSession) return valid(ctx);
192
193
  return ctx.json({
package/dist/state.mjs CHANGED
@@ -17,6 +17,7 @@ const stateDataSchema = z.looseObject({
17
17
  }).optional(),
18
18
  requestSignUp: z.boolean().optional()
19
19
  });
20
+ const INTERNAL_STATE_KEYS = new Set(Object.keys(stateDataSchema.shape));
20
21
  var StateError = class extends BetterAuthError {
21
22
  code;
22
23
  details;
@@ -130,4 +131,4 @@ async function parseGenericState(c, state, settings) {
130
131
  return parsedData;
131
132
  }
132
133
  //#endregion
133
- export { StateError, generateGenericState, parseGenericState };
134
+ export { INTERNAL_STATE_KEYS, StateError, generateGenericState, parseGenericState };