@better-auth/core 1.5.5 → 1.5.6
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/dist/api/index.d.mts +0 -3
- package/dist/context/endpoint-context.d.mts +0 -1
- package/dist/context/global.mjs +1 -1
- package/dist/db/adapter/factory.d.mts +0 -2
- package/dist/db/adapter/factory.mjs +53 -20
- package/dist/db/adapter/factory.mjs.map +1 -1
- package/dist/db/adapter/get-field-attributes.d.mts +0 -3
- package/dist/db/adapter/get-id-field.d.mts +0 -3
- package/dist/db/adapter/get-id-field.mjs +2 -2
- package/dist/db/adapter/get-id-field.mjs.map +1 -1
- package/dist/db/adapter/index.d.mts +0 -2
- package/dist/db/adapter/types.d.mts +0 -2
- package/dist/db/get-tables.d.mts +0 -2
- package/dist/db/schema/account.d.mts +0 -1
- package/dist/db/schema/rate-limit.d.mts +0 -1
- package/dist/db/schema/session.d.mts +0 -1
- package/dist/db/schema/user.d.mts +0 -1
- package/dist/db/schema/verification.d.mts +0 -1
- package/dist/db/type.d.mts +0 -1
- package/dist/instrumentation/attributes.d.mts +12 -0
- package/dist/instrumentation/attributes.mjs +13 -0
- package/dist/instrumentation/attributes.mjs.map +1 -0
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.mjs +4 -0
- package/dist/instrumentation/tracer.d.mts +14 -0
- package/dist/instrumentation/tracer.mjs +37 -0
- package/dist/instrumentation/tracer.mjs.map +1 -0
- package/dist/oauth2/client-credentials-token.d.mts +0 -1
- package/dist/oauth2/create-authorization-url.d.mts +0 -3
- package/dist/oauth2/oauth-provider.d.mts +0 -2
- package/dist/oauth2/refresh-access-token.d.mts +0 -1
- package/dist/oauth2/validate-authorization-code.d.mts +0 -2
- package/dist/social-providers/apple.d.mts +0 -2
- package/dist/social-providers/apple.mjs +1 -1
- package/dist/social-providers/apple.mjs.map +1 -1
- package/dist/social-providers/atlassian.d.mts +0 -2
- package/dist/social-providers/atlassian.mjs +3 -2
- package/dist/social-providers/atlassian.mjs.map +1 -1
- package/dist/social-providers/cognito.d.mts +0 -2
- package/dist/social-providers/discord.d.mts +0 -2
- package/dist/social-providers/discord.mjs +3 -2
- package/dist/social-providers/discord.mjs.map +1 -1
- package/dist/social-providers/dropbox.d.mts +0 -2
- package/dist/social-providers/facebook.d.mts +0 -2
- package/dist/social-providers/figma.d.mts +0 -2
- package/dist/social-providers/figma.mjs +3 -2
- package/dist/social-providers/figma.mjs.map +1 -1
- package/dist/social-providers/github.d.mts +0 -2
- package/dist/social-providers/github.mjs +1 -1
- package/dist/social-providers/github.mjs.map +1 -1
- package/dist/social-providers/gitlab.d.mts +0 -2
- package/dist/social-providers/google.d.mts +0 -2
- package/dist/social-providers/huggingface.d.mts +0 -2
- package/dist/social-providers/huggingface.mjs +3 -2
- package/dist/social-providers/huggingface.mjs.map +1 -1
- package/dist/social-providers/index.d.mts +61 -3
- package/dist/social-providers/index.mjs +4 -2
- package/dist/social-providers/index.mjs.map +1 -1
- package/dist/social-providers/kakao.d.mts +0 -2
- package/dist/social-providers/kakao.mjs +3 -2
- package/dist/social-providers/kakao.mjs.map +1 -1
- package/dist/social-providers/kick.d.mts +0 -2
- package/dist/social-providers/line.d.mts +0 -2
- package/dist/social-providers/linear.d.mts +0 -2
- package/dist/social-providers/linkedin.d.mts +0 -2
- package/dist/social-providers/microsoft-entra-id.d.mts +0 -2
- package/dist/social-providers/naver.d.mts +0 -2
- package/dist/social-providers/naver.mjs +3 -2
- package/dist/social-providers/naver.mjs.map +1 -1
- package/dist/social-providers/notion.d.mts +0 -2
- package/dist/social-providers/paybin.d.mts +0 -2
- package/dist/social-providers/paypal.d.mts +0 -2
- package/dist/social-providers/polar.d.mts +0 -2
- package/dist/social-providers/polar.mjs +3 -2
- package/dist/social-providers/polar.mjs.map +1 -1
- package/dist/social-providers/railway.d.mts +0 -2
- package/dist/social-providers/reddit.d.mts +0 -2
- package/dist/social-providers/roblox.d.mts +0 -2
- package/dist/social-providers/roblox.mjs +3 -2
- package/dist/social-providers/roblox.mjs.map +1 -1
- package/dist/social-providers/salesforce.d.mts +0 -2
- package/dist/social-providers/slack.d.mts +0 -2
- package/dist/social-providers/slack.mjs +3 -2
- package/dist/social-providers/slack.mjs.map +1 -1
- package/dist/social-providers/spotify.d.mts +0 -2
- package/dist/social-providers/spotify.mjs +3 -2
- package/dist/social-providers/spotify.mjs.map +1 -1
- package/dist/social-providers/tiktok.d.mts +0 -2
- package/dist/social-providers/tiktok.mjs +3 -2
- package/dist/social-providers/tiktok.mjs.map +1 -1
- package/dist/social-providers/twitch.d.mts +0 -2
- package/dist/social-providers/twitch.mjs +3 -2
- package/dist/social-providers/twitch.mjs.map +1 -1
- package/dist/social-providers/twitter.d.mts +0 -2
- package/dist/social-providers/twitter.mjs +3 -2
- package/dist/social-providers/twitter.mjs.map +1 -1
- package/dist/social-providers/vercel.d.mts +0 -2
- package/dist/social-providers/vk.d.mts +0 -2
- package/dist/social-providers/vk.mjs +3 -2
- package/dist/social-providers/vk.mjs.map +1 -1
- package/dist/social-providers/wechat.d.mts +114 -0
- package/dist/social-providers/wechat.mjs +84 -0
- package/dist/social-providers/wechat.mjs.map +1 -0
- package/dist/social-providers/zoom.d.mts +0 -2
- package/dist/types/context.d.mts +0 -2
- package/dist/types/init-options.d.mts +0 -1
- package/dist/types/plugin.d.mts +0 -1
- package/dist/utils/db.d.mts +0 -2
- package/package.json +15 -2
- package/src/db/adapter/factory.ts +119 -47
- package/src/db/adapter/get-id-field.test.ts +222 -0
- package/src/db/adapter/get-id-field.ts +15 -4
- package/src/instrumentation/attributes.ts +22 -0
- package/src/instrumentation/index.ts +2 -0
- package/src/instrumentation/instrumentation.test.ts +139 -0
- package/src/instrumentation/tracer.ts +62 -0
- package/src/social-providers/apple.ts +1 -1
- package/src/social-providers/atlassian.ts +3 -2
- package/src/social-providers/discord.ts +3 -2
- package/src/social-providers/figma.ts +3 -2
- package/src/social-providers/github.ts +1 -1
- package/src/social-providers/huggingface.ts +3 -2
- package/src/social-providers/index.ts +3 -0
- package/src/social-providers/kakao.ts +3 -2
- package/src/social-providers/naver.ts +3 -2
- package/src/social-providers/polar.ts +3 -2
- package/src/social-providers/roblox.ts +3 -2
- package/src/social-providers/slack.ts +3 -2
- package/src/social-providers/spotify.ts +3 -2
- package/src/social-providers/tiktok.ts +3 -2
- package/src/social-providers/twitch.ts +3 -2
- package/src/social-providers/twitter.ts +3 -2
- package/src/social-providers/vk.ts +3 -2
- package/src/social-providers/wechat.ts +213 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/core",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.6",
|
|
4
4
|
"description": "The most comprehensive authentication framework for TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -87,6 +87,11 @@
|
|
|
87
87
|
"dev-source": "./src/oauth2/index.ts",
|
|
88
88
|
"types": "./dist/oauth2/index.d.mts",
|
|
89
89
|
"default": "./dist/oauth2/index.mjs"
|
|
90
|
+
},
|
|
91
|
+
"./instrumentation": {
|
|
92
|
+
"dev-source": "./src/instrumentation/index.ts",
|
|
93
|
+
"types": "./dist/instrumentation/index.d.mts",
|
|
94
|
+
"default": "./dist/instrumentation/index.mjs"
|
|
90
95
|
}
|
|
91
96
|
},
|
|
92
97
|
"typesVersions": {
|
|
@@ -126,26 +131,34 @@
|
|
|
126
131
|
],
|
|
127
132
|
"oauth2": [
|
|
128
133
|
"dist/oauth2/index.d.mts"
|
|
134
|
+
],
|
|
135
|
+
"instrumentation": [
|
|
136
|
+
"dist/instrumentation/index.d.mts"
|
|
129
137
|
]
|
|
130
138
|
}
|
|
131
139
|
},
|
|
132
140
|
"dependencies": {
|
|
141
|
+
"@opentelemetry/semantic-conventions": "^1.39.0",
|
|
133
142
|
"@standard-schema/spec": "^1.1.0",
|
|
134
143
|
"zod": "^4.3.6"
|
|
135
144
|
},
|
|
136
145
|
"devDependencies": {
|
|
137
146
|
"@better-auth/utils": "0.3.1",
|
|
138
147
|
"@better-fetch/fetch": "1.1.21",
|
|
148
|
+
"@opentelemetry/api": "^1.9.0",
|
|
149
|
+
"@opentelemetry/sdk-trace-base": "^1.30.0",
|
|
150
|
+
"@opentelemetry/sdk-trace-node": "^1.30.0",
|
|
139
151
|
"better-call": "1.3.2",
|
|
140
152
|
"@cloudflare/workers-types": "^4.20250121.0",
|
|
141
153
|
"jose": "^6.1.3",
|
|
142
|
-
"kysely": "^0.28.
|
|
154
|
+
"kysely": "^0.28.12",
|
|
143
155
|
"nanostores": "^1.1.1",
|
|
144
156
|
"tsdown": "0.21.0-beta.2"
|
|
145
157
|
},
|
|
146
158
|
"peerDependencies": {
|
|
147
159
|
"@better-auth/utils": "0.3.1",
|
|
148
160
|
"@better-fetch/fetch": "1.1.21",
|
|
161
|
+
"@opentelemetry/api": "^1.9.0",
|
|
149
162
|
"better-call": "1.3.2",
|
|
150
163
|
"@cloudflare/workers-types": ">=4",
|
|
151
164
|
"jose": "^6.1.0",
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { createLogger, getColorDepth, TTY_COLORS } from "../../env";
|
|
2
2
|
import { BetterAuthError } from "../../error";
|
|
3
|
+
import {
|
|
4
|
+
ATTR_DB_COLLECTION_NAME,
|
|
5
|
+
ATTR_DB_OPERATION_NAME,
|
|
6
|
+
withSpan,
|
|
7
|
+
} from "../../instrumentation";
|
|
3
8
|
import type { BetterAuthOptions } from "../../types";
|
|
4
9
|
import { safeJSONParse } from "../../utils/json";
|
|
5
10
|
import { getAuthTables } from "../get-tables";
|
|
@@ -765,20 +770,36 @@ export const createAdapterFactory =
|
|
|
765
770
|
});
|
|
766
771
|
try {
|
|
767
772
|
if (joinConfig.relation === "one-to-one") {
|
|
768
|
-
result = await
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
773
|
+
result = await withSpan(
|
|
774
|
+
`db findOne ${modelName}`,
|
|
775
|
+
{
|
|
776
|
+
[ATTR_DB_OPERATION_NAME]: "findOne",
|
|
777
|
+
[ATTR_DB_COLLECTION_NAME]: modelName,
|
|
778
|
+
},
|
|
779
|
+
() =>
|
|
780
|
+
adapterInstance.findOne<Record<string, any>>({
|
|
781
|
+
model: modelName,
|
|
782
|
+
where: where,
|
|
783
|
+
}),
|
|
784
|
+
);
|
|
772
785
|
} else {
|
|
773
786
|
const limit =
|
|
774
787
|
joinConfig.limit ??
|
|
775
788
|
options.advanced?.database?.defaultFindManyLimit ??
|
|
776
789
|
100;
|
|
777
|
-
result = await
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
790
|
+
result = await withSpan(
|
|
791
|
+
`db findMany ${modelName}`,
|
|
792
|
+
{
|
|
793
|
+
[ATTR_DB_OPERATION_NAME]: "findMany",
|
|
794
|
+
[ATTR_DB_COLLECTION_NAME]: modelName,
|
|
795
|
+
},
|
|
796
|
+
() =>
|
|
797
|
+
adapterInstance.findMany<Record<string, any>>({
|
|
798
|
+
model: modelName,
|
|
799
|
+
where: where,
|
|
800
|
+
limit,
|
|
801
|
+
}),
|
|
802
|
+
);
|
|
782
803
|
}
|
|
783
804
|
} catch (error) {
|
|
784
805
|
logger.error(`Failed to query fallback join for model ${modelName}:`, {
|
|
@@ -879,7 +900,14 @@ export const createAdapterFactory =
|
|
|
879
900
|
`${formatMethod("create")} ${formatAction("Parsed Input")}:`,
|
|
880
901
|
{ model, data },
|
|
881
902
|
);
|
|
882
|
-
const res = await
|
|
903
|
+
const res = await withSpan(
|
|
904
|
+
`db create ${model}`,
|
|
905
|
+
{
|
|
906
|
+
[ATTR_DB_OPERATION_NAME]: "create",
|
|
907
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
908
|
+
},
|
|
909
|
+
() => adapterInstance.create<T>({ data, model }),
|
|
910
|
+
);
|
|
883
911
|
debugLog(
|
|
884
912
|
{ method: "create" },
|
|
885
913
|
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`,
|
|
@@ -937,11 +965,19 @@ export const createAdapterFactory =
|
|
|
937
965
|
`${formatMethod("update")} ${formatAction("Parsed Input")}:`,
|
|
938
966
|
{ model, data },
|
|
939
967
|
);
|
|
940
|
-
const res = await
|
|
941
|
-
model
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
968
|
+
const res = await withSpan(
|
|
969
|
+
`db update ${model}`,
|
|
970
|
+
{
|
|
971
|
+
[ATTR_DB_OPERATION_NAME]: "update",
|
|
972
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
973
|
+
},
|
|
974
|
+
() =>
|
|
975
|
+
adapterInstance.update<T>({
|
|
976
|
+
model,
|
|
977
|
+
where,
|
|
978
|
+
update: data,
|
|
979
|
+
}),
|
|
980
|
+
);
|
|
945
981
|
debugLog(
|
|
946
982
|
{ method: "update" },
|
|
947
983
|
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`,
|
|
@@ -1000,11 +1036,19 @@ export const createAdapterFactory =
|
|
|
1000
1036
|
{ model, data },
|
|
1001
1037
|
);
|
|
1002
1038
|
|
|
1003
|
-
const updatedCount = await
|
|
1004
|
-
model
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1039
|
+
const updatedCount = await withSpan(
|
|
1040
|
+
`db updateMany ${model}`,
|
|
1041
|
+
{
|
|
1042
|
+
[ATTR_DB_OPERATION_NAME]: "updateMany",
|
|
1043
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
1044
|
+
},
|
|
1045
|
+
() =>
|
|
1046
|
+
adapterInstance.updateMany({
|
|
1047
|
+
model,
|
|
1048
|
+
where,
|
|
1049
|
+
update: data,
|
|
1050
|
+
}),
|
|
1051
|
+
);
|
|
1008
1052
|
debugLog(
|
|
1009
1053
|
{ method: "updateMany" },
|
|
1010
1054
|
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`,
|
|
@@ -1063,12 +1107,20 @@ export const createAdapterFactory =
|
|
|
1063
1107
|
{ model, where, select, join },
|
|
1064
1108
|
);
|
|
1065
1109
|
|
|
1066
|
-
const res = await
|
|
1067
|
-
model
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1110
|
+
const res = await withSpan(
|
|
1111
|
+
`db findOne ${model}`,
|
|
1112
|
+
{
|
|
1113
|
+
[ATTR_DB_OPERATION_NAME]: "findOne",
|
|
1114
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
1115
|
+
},
|
|
1116
|
+
() =>
|
|
1117
|
+
adapterInstance.findOne<T>({
|
|
1118
|
+
model,
|
|
1119
|
+
where,
|
|
1120
|
+
select,
|
|
1121
|
+
join: passJoinToAdapter ? join : undefined,
|
|
1122
|
+
}),
|
|
1123
|
+
);
|
|
1072
1124
|
debugLog(
|
|
1073
1125
|
{ method: "findOne" },
|
|
1074
1126
|
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`,
|
|
@@ -1142,15 +1194,23 @@ export const createAdapterFactory =
|
|
|
1142
1194
|
`${formatMethod("findMany")}:`,
|
|
1143
1195
|
{ model, where, limit, sortBy, offset, join },
|
|
1144
1196
|
);
|
|
1145
|
-
const res = await
|
|
1146
|
-
model
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1197
|
+
const res = await withSpan(
|
|
1198
|
+
`db findMany ${model}`,
|
|
1199
|
+
{
|
|
1200
|
+
[ATTR_DB_OPERATION_NAME]: "findMany",
|
|
1201
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
1202
|
+
},
|
|
1203
|
+
() =>
|
|
1204
|
+
adapterInstance.findMany<T>({
|
|
1205
|
+
model,
|
|
1206
|
+
where,
|
|
1207
|
+
limit: limit,
|
|
1208
|
+
select,
|
|
1209
|
+
sortBy,
|
|
1210
|
+
offset,
|
|
1211
|
+
join: passJoinToAdapter ? join : undefined,
|
|
1212
|
+
}),
|
|
1213
|
+
);
|
|
1154
1214
|
debugLog(
|
|
1155
1215
|
{ method: "findMany" },
|
|
1156
1216
|
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`,
|
|
@@ -1197,10 +1257,14 @@ export const createAdapterFactory =
|
|
|
1197
1257
|
`${formatMethod("delete")}:`,
|
|
1198
1258
|
{ model, where },
|
|
1199
1259
|
);
|
|
1200
|
-
await
|
|
1201
|
-
model
|
|
1202
|
-
|
|
1203
|
-
|
|
1260
|
+
await withSpan(
|
|
1261
|
+
`db delete ${model}`,
|
|
1262
|
+
{
|
|
1263
|
+
[ATTR_DB_OPERATION_NAME]: "delete",
|
|
1264
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
1265
|
+
},
|
|
1266
|
+
() => adapterInstance.delete({ model, where }),
|
|
1267
|
+
);
|
|
1204
1268
|
debugLog(
|
|
1205
1269
|
{ method: "delete" },
|
|
1206
1270
|
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`,
|
|
@@ -1230,10 +1294,14 @@ export const createAdapterFactory =
|
|
|
1230
1294
|
`${formatMethod("deleteMany")} ${formatAction("DeleteMany")}:`,
|
|
1231
1295
|
{ model, where },
|
|
1232
1296
|
);
|
|
1233
|
-
const res = await
|
|
1234
|
-
model
|
|
1235
|
-
|
|
1236
|
-
|
|
1297
|
+
const res = await withSpan(
|
|
1298
|
+
`db deleteMany ${model}`,
|
|
1299
|
+
{
|
|
1300
|
+
[ATTR_DB_OPERATION_NAME]: "deleteMany",
|
|
1301
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
1302
|
+
},
|
|
1303
|
+
() => adapterInstance.deleteMany({ model, where }),
|
|
1304
|
+
);
|
|
1237
1305
|
debugLog(
|
|
1238
1306
|
{ method: "deleteMany" },
|
|
1239
1307
|
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`,
|
|
@@ -1267,10 +1335,14 @@ export const createAdapterFactory =
|
|
|
1267
1335
|
where,
|
|
1268
1336
|
},
|
|
1269
1337
|
);
|
|
1270
|
-
const res = await
|
|
1271
|
-
model
|
|
1272
|
-
|
|
1273
|
-
|
|
1338
|
+
const res = await withSpan(
|
|
1339
|
+
`db count ${model}`,
|
|
1340
|
+
{
|
|
1341
|
+
[ATTR_DB_OPERATION_NAME]: "count",
|
|
1342
|
+
[ATTR_DB_COLLECTION_NAME]: model,
|
|
1343
|
+
},
|
|
1344
|
+
() => adapterInstance.count({ model, where }),
|
|
1345
|
+
);
|
|
1274
1346
|
debugLog(
|
|
1275
1347
|
{ method: "count" },
|
|
1276
1348
|
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`,
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import type { BetterAuthOptions } from "../../types";
|
|
3
|
+
import type { BetterAuthDBSchema } from "../type";
|
|
4
|
+
import { initGetIdField } from "./get-id-field";
|
|
5
|
+
|
|
6
|
+
const minimalSchema: BetterAuthDBSchema = {
|
|
7
|
+
user: {
|
|
8
|
+
modelName: "user",
|
|
9
|
+
fields: {
|
|
10
|
+
name: { type: "string" },
|
|
11
|
+
email: { type: "string" },
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const uuidRegex =
|
|
17
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
18
|
+
|
|
19
|
+
function getField(
|
|
20
|
+
options: BetterAuthOptions,
|
|
21
|
+
initExtra?: Partial<Parameters<typeof initGetIdField>[0]>,
|
|
22
|
+
fieldExtra?: { customModelName?: string; forceAllowId?: boolean },
|
|
23
|
+
) {
|
|
24
|
+
const idField = initGetIdField({
|
|
25
|
+
schema: minimalSchema,
|
|
26
|
+
options,
|
|
27
|
+
...initExtra,
|
|
28
|
+
});
|
|
29
|
+
return idField({
|
|
30
|
+
customModelName: fieldExtra?.customModelName ?? "user",
|
|
31
|
+
forceAllowId: fieldExtra?.forceAllowId,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe("defaultValue priority", () => {
|
|
36
|
+
it("should return undefined when disableIdGeneration is true", () => {
|
|
37
|
+
const field = getField(
|
|
38
|
+
{ database: {} as any },
|
|
39
|
+
{ disableIdGeneration: true },
|
|
40
|
+
);
|
|
41
|
+
expect(field.defaultValue).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should return undefined when generateId is false", () => {
|
|
45
|
+
const value = getField({
|
|
46
|
+
database: {} as any,
|
|
47
|
+
advanced: { database: { generateId: false } },
|
|
48
|
+
}).defaultValue?.();
|
|
49
|
+
expect(value).toBeUndefined();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should return undefined when generateId is 'serial'", () => {
|
|
53
|
+
const value = getField({
|
|
54
|
+
database: {} as any,
|
|
55
|
+
advanced: { database: { generateId: "serial" } },
|
|
56
|
+
}).defaultValue?.();
|
|
57
|
+
expect(value).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should use generateId function over 'uuid' and customIdGenerator", () => {
|
|
61
|
+
const value = getField(
|
|
62
|
+
{
|
|
63
|
+
database: {} as any,
|
|
64
|
+
advanced: { database: { generateId: () => "fn-id" } },
|
|
65
|
+
},
|
|
66
|
+
{ customIdGenerator: () => "adapter-id" },
|
|
67
|
+
).defaultValue?.();
|
|
68
|
+
expect(value).toBe("fn-id");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should use 'uuid' over customIdGenerator", () => {
|
|
72
|
+
const value = getField(
|
|
73
|
+
{
|
|
74
|
+
database: {} as any,
|
|
75
|
+
advanced: { database: { generateId: "uuid" } },
|
|
76
|
+
},
|
|
77
|
+
{ customIdGenerator: () => "adapter-id", supportsUUIDs: false },
|
|
78
|
+
).defaultValue?.();
|
|
79
|
+
expect(value).toMatch(uuidRegex);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should use customIdGenerator when generateId is not set", () => {
|
|
83
|
+
const value = getField(
|
|
84
|
+
{ database: {} as any },
|
|
85
|
+
{ customIdGenerator: () => "adapter-id" },
|
|
86
|
+
).defaultValue?.();
|
|
87
|
+
expect(value).toBe("adapter-id");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should fall back to default id generation", () => {
|
|
91
|
+
const value = getField({ database: {} as any }).defaultValue?.();
|
|
92
|
+
expect(typeof value).toBe("string");
|
|
93
|
+
expect(value).not.toMatch(uuidRegex);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe("type and required", () => {
|
|
98
|
+
it("should have type 'number' when generateId is 'serial'", () => {
|
|
99
|
+
const field = getField({
|
|
100
|
+
database: {} as any,
|
|
101
|
+
advanced: { database: { generateId: "serial" } },
|
|
102
|
+
});
|
|
103
|
+
expect(field.type).toBe("number");
|
|
104
|
+
expect(field.required).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("should have type 'string' by default", () => {
|
|
108
|
+
const field = getField({ database: {} as any });
|
|
109
|
+
expect(field.type).toBe("string");
|
|
110
|
+
expect(field.required).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should not generate id when useUUIDs and supportsUUIDs", () => {
|
|
114
|
+
const field = getField(
|
|
115
|
+
{
|
|
116
|
+
database: {} as any,
|
|
117
|
+
advanced: { database: { generateId: "uuid" } },
|
|
118
|
+
},
|
|
119
|
+
{ supportsUUIDs: true },
|
|
120
|
+
);
|
|
121
|
+
expect(field.required).toBe(false);
|
|
122
|
+
expect(field.defaultValue).toBeUndefined();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe("transform.input", () => {
|
|
127
|
+
it("should return undefined for falsy value", () => {
|
|
128
|
+
const field = getField({ database: {} as any });
|
|
129
|
+
expect(field.transform.input(undefined)).toBeUndefined();
|
|
130
|
+
expect(field.transform.input(null)).toBeUndefined();
|
|
131
|
+
expect(field.transform.input("")).toBeUndefined();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("should return value as-is by default", () => {
|
|
135
|
+
const field = getField({ database: {} as any });
|
|
136
|
+
expect(field.transform.input("some-id")).toBe("some-id");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe("serial", () => {
|
|
140
|
+
it("should convert string to number", () => {
|
|
141
|
+
const field = getField({
|
|
142
|
+
database: {} as any,
|
|
143
|
+
advanced: { database: { generateId: "serial" } },
|
|
144
|
+
});
|
|
145
|
+
expect(field.transform.input("42")).toBe(42);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should return undefined for non-numeric string", () => {
|
|
149
|
+
const field = getField({
|
|
150
|
+
database: {} as any,
|
|
151
|
+
advanced: { database: { generateId: "serial" } },
|
|
152
|
+
});
|
|
153
|
+
expect(field.transform.input("not-a-number")).toBeUndefined();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe("uuid", () => {
|
|
158
|
+
it("should return value as-is when shouldGenerateId and not forceAllowId", () => {
|
|
159
|
+
const field = getField(
|
|
160
|
+
{
|
|
161
|
+
database: {} as any,
|
|
162
|
+
advanced: { database: { generateId: "uuid" } },
|
|
163
|
+
},
|
|
164
|
+
{ supportsUUIDs: false },
|
|
165
|
+
);
|
|
166
|
+
const uuid = crypto.randomUUID();
|
|
167
|
+
expect(field.transform.input(uuid)).toBe(uuid);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("should return undefined when supportsUUIDs (DB handles it)", () => {
|
|
171
|
+
const field = getField(
|
|
172
|
+
{
|
|
173
|
+
database: {} as any,
|
|
174
|
+
advanced: { database: { generateId: "uuid" } },
|
|
175
|
+
},
|
|
176
|
+
{ supportsUUIDs: true },
|
|
177
|
+
);
|
|
178
|
+
expect(field.transform.input("some-value")).toBeUndefined();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("should accept valid UUID when forceAllowId is true", () => {
|
|
182
|
+
const uuid = crypto.randomUUID();
|
|
183
|
+
const field = getField(
|
|
184
|
+
{
|
|
185
|
+
database: {} as any,
|
|
186
|
+
advanced: { database: { generateId: "uuid" } },
|
|
187
|
+
},
|
|
188
|
+
{ supportsUUIDs: false },
|
|
189
|
+
{ forceAllowId: true },
|
|
190
|
+
);
|
|
191
|
+
expect(field.transform.input(uuid)).toBe(uuid);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("should generate new UUID for non-string value when DB doesn't support UUIDs", () => {
|
|
195
|
+
const field = getField(
|
|
196
|
+
{
|
|
197
|
+
database: {} as any,
|
|
198
|
+
advanced: { database: { generateId: "uuid" } },
|
|
199
|
+
},
|
|
200
|
+
{ supportsUUIDs: false },
|
|
201
|
+
{ forceAllowId: true },
|
|
202
|
+
);
|
|
203
|
+
const result = field.transform.input(123);
|
|
204
|
+
expect(result).toMatch(uuidRegex);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe("transform.output", () => {
|
|
210
|
+
it("should return undefined for falsy value", () => {
|
|
211
|
+
const field = getField({ database: {} as any });
|
|
212
|
+
expect(field.transform.output(undefined)).toBeUndefined();
|
|
213
|
+
expect(field.transform.output(null)).toBeUndefined();
|
|
214
|
+
expect(field.transform.output("")).toBeUndefined();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it("should convert value to string", () => {
|
|
218
|
+
const field = getField({ database: {} as any });
|
|
219
|
+
expect(field.transform.output(123)).toBe("123");
|
|
220
|
+
expect(field.transform.output("abc")).toBe("abc");
|
|
221
|
+
});
|
|
222
|
+
});
|
|
@@ -57,18 +57,29 @@ export const initGetIdField = ({
|
|
|
57
57
|
defaultValue() {
|
|
58
58
|
if (disableIdGeneration) return undefined;
|
|
59
59
|
const generateId = options.advanced?.database?.generateId;
|
|
60
|
-
|
|
60
|
+
|
|
61
|
+
// let the database handle id generation
|
|
62
|
+
if (generateId === false || generateId === "serial")
|
|
63
|
+
return undefined;
|
|
64
|
+
|
|
65
|
+
// user-provided function takes highest priority
|
|
61
66
|
if (typeof generateId === "function") {
|
|
62
67
|
return generateId({
|
|
63
68
|
model,
|
|
64
69
|
});
|
|
65
70
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
71
|
+
|
|
72
|
+
// user-provided "uuid" option
|
|
69
73
|
if (generateId === "uuid") {
|
|
70
74
|
return crypto.randomUUID();
|
|
71
75
|
}
|
|
76
|
+
|
|
77
|
+
// database adapter-level custom id generator
|
|
78
|
+
if (customIdGenerator) {
|
|
79
|
+
return customIdGenerator({ model });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// fallback to default id generation
|
|
72
83
|
return defaultGenerateId();
|
|
73
84
|
},
|
|
74
85
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ATTR_DB_COLLECTION_NAME,
|
|
3
|
+
ATTR_DB_OPERATION_NAME,
|
|
4
|
+
ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
5
|
+
ATTR_HTTP_ROUTE,
|
|
6
|
+
} from "@opentelemetry/semantic-conventions";
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
ATTR_DB_COLLECTION_NAME,
|
|
10
|
+
ATTR_DB_OPERATION_NAME,
|
|
11
|
+
ATTR_HTTP_RESPONSE_STATUS_CODE,
|
|
12
|
+
ATTR_HTTP_ROUTE,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Operation identifier (e.g. getSession, signUpWithEmailAndPassword). Uses endpoint operationId when set, otherwise the endpoint key. */
|
|
16
|
+
export const ATTR_OPERATION_ID = "better_auth.operation_id" as const;
|
|
17
|
+
|
|
18
|
+
/** Hook type (e.g. before, after, create.before). */
|
|
19
|
+
export const ATTR_HOOK_TYPE = "better_auth.hook.type" as const;
|
|
20
|
+
|
|
21
|
+
/** Execution context (e.g. user, plugin:id). */
|
|
22
|
+
export const ATTR_CONTEXT = "better_auth.context" as const;
|