better-auth-firestore 1.0.0
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/LICENSE +22 -0
- package/README.md +103 -0
- package/dist/firebase-adapter.d.ts +8 -0
- package/dist/firebase-adapter.js +935 -0
- package/dist/firestore.d.ts +9 -0
- package/dist/firestore.js +16 -0
- package/dist/index-utils.d.ts +28 -0
- package/dist/index-utils.js +51 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/setup.d.ts +26 -0
- package/dist/setup.js +93 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +78 -0
- package/package.json +68 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type AppOptions } from "firebase-admin/app";
|
|
2
|
+
import { type Firestore } from "firebase-admin/firestore";
|
|
3
|
+
/**
|
|
4
|
+
* Initialize or reuse a Firestore instance safely (useful in serverless).
|
|
5
|
+
* If an app with the provided name exists, reuse it; otherwise initialize.
|
|
6
|
+
*/
|
|
7
|
+
export declare function initFirestore(options?: AppOptions & {
|
|
8
|
+
name?: string;
|
|
9
|
+
}): Firestore;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getApps, initializeApp } from "firebase-admin/app";
|
|
2
|
+
import { getFirestore, initializeFirestore, } from "firebase-admin/firestore";
|
|
3
|
+
/**
|
|
4
|
+
* Initialize or reuse a Firestore instance safely (useful in serverless).
|
|
5
|
+
* If an app with the provided name exists, reuse it; otherwise initialize.
|
|
6
|
+
*/
|
|
7
|
+
export function initFirestore(options = {}) {
|
|
8
|
+
// Reuse existing app by name if exists, otherwise initialize
|
|
9
|
+
const apps = getApps();
|
|
10
|
+
const app = options.name
|
|
11
|
+
? apps.find((a) => a.name === options.name)
|
|
12
|
+
: apps[0];
|
|
13
|
+
if (app)
|
|
14
|
+
return getFirestore(app);
|
|
15
|
+
return initializeFirestore(initializeApp(options, options.name));
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Firestore } from "firebase-admin/firestore";
|
|
2
|
+
import type { NamingStrategy } from "./types";
|
|
3
|
+
export interface FirestoreIndexField {
|
|
4
|
+
fieldPath: string;
|
|
5
|
+
order: "ASCENDING" | "DESCENDING";
|
|
6
|
+
}
|
|
7
|
+
export interface FirestoreIndex {
|
|
8
|
+
collectionGroup: string;
|
|
9
|
+
queryScope: "COLLECTION" | "COLLECTION_GROUP";
|
|
10
|
+
fields: FirestoreIndexField[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Returns all required Firestore index definitions for Better Auth adapter.
|
|
14
|
+
* Supports both default and snake_case naming strategies.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getRequiredIndexes(namingStrategy?: NamingStrategy): FirestoreIndex[];
|
|
17
|
+
/**
|
|
18
|
+
* Creates Firestore indexes programmatically using the Firestore REST API.
|
|
19
|
+
* Note: Firebase Admin SDK doesn't have direct index creation methods,
|
|
20
|
+
* so this function provides a helper to format indexes for manual creation
|
|
21
|
+
* or uses the REST API if credentials are available.
|
|
22
|
+
*
|
|
23
|
+
* @param firestore - Firestore instance
|
|
24
|
+
* @param projectId - Firebase project ID
|
|
25
|
+
* @param namingStrategy - Naming strategy to use ("default" or "snake_case")
|
|
26
|
+
* @returns Array of index definitions that can be used to create indexes
|
|
27
|
+
*/
|
|
28
|
+
export declare function createFirestoreIndexes(firestore: Firestore, projectId: string, namingStrategy?: NamingStrategy): Promise<FirestoreIndex[]>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns all required Firestore index definitions for Better Auth adapter.
|
|
3
|
+
* Supports both default and snake_case naming strategies.
|
|
4
|
+
*/
|
|
5
|
+
export function getRequiredIndexes(namingStrategy = "default") {
|
|
6
|
+
const isSnakeCase = namingStrategy === "snake_case";
|
|
7
|
+
const collectionName = isSnakeCase
|
|
8
|
+
? "verification_tokens"
|
|
9
|
+
: "verificationTokens";
|
|
10
|
+
const createdAtField = isSnakeCase ? "created_at" : "createdAt";
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
collectionGroup: collectionName,
|
|
14
|
+
queryScope: "COLLECTION",
|
|
15
|
+
fields: [
|
|
16
|
+
{
|
|
17
|
+
fieldPath: "identifier",
|
|
18
|
+
order: "ASCENDING",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
fieldPath: createdAtField,
|
|
22
|
+
order: "DESCENDING",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates Firestore indexes programmatically using the Firestore REST API.
|
|
30
|
+
* Note: Firebase Admin SDK doesn't have direct index creation methods,
|
|
31
|
+
* so this function provides a helper to format indexes for manual creation
|
|
32
|
+
* or uses the REST API if credentials are available.
|
|
33
|
+
*
|
|
34
|
+
* @param firestore - Firestore instance
|
|
35
|
+
* @param projectId - Firebase project ID
|
|
36
|
+
* @param namingStrategy - Naming strategy to use ("default" or "snake_case")
|
|
37
|
+
* @returns Array of index definitions that can be used to create indexes
|
|
38
|
+
*/
|
|
39
|
+
export async function createFirestoreIndexes(firestore, projectId, namingStrategy = "default") {
|
|
40
|
+
const indexes = getRequiredIndexes(namingStrategy);
|
|
41
|
+
// Note: The Firebase Admin SDK doesn't provide direct methods to create indexes.
|
|
42
|
+
// Indexes must be created via:
|
|
43
|
+
// 1. Firebase Console (Firestore provides URLs in error messages)
|
|
44
|
+
// 2. Firebase CLI: `firebase deploy --only firestore:indexes`
|
|
45
|
+
// 3. Firestore REST API (requires additional authentication)
|
|
46
|
+
// This function returns the index definitions for reference.
|
|
47
|
+
// Users should deploy indexes using one of the methods above.
|
|
48
|
+
console.log(`[Firestore Indexes] ${indexes.length} index definition(s) generated for project: ${projectId}`);
|
|
49
|
+
console.log(`[Firestore Indexes] Deploy indexes using: firebase deploy --only firestore:indexes`);
|
|
50
|
+
return indexes;
|
|
51
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/setup.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a Firebase Console URL for creating the required Firestore composite index.
|
|
3
|
+
* This URL will pre-fill the index creation form with the correct configuration,
|
|
4
|
+
* similar to the URLs provided in Firestore error messages.
|
|
5
|
+
*
|
|
6
|
+
* @param projectId - Your Firebase project ID
|
|
7
|
+
* @param databaseId - Your Firestore database ID (defaults to "(default)")
|
|
8
|
+
* @param collectionName - The collection name (defaults to "verification")
|
|
9
|
+
* @returns A Firebase Console URL with pre-filled index configuration
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateIndexSetupUrl(projectId: string, databaseId?: string, collectionName?: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Get the index configuration object for the verification collection.
|
|
14
|
+
* This can be used to create firestore.indexes.json file.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getIndexConfig(collectionName?: string): {
|
|
17
|
+
indexes: {
|
|
18
|
+
collectionGroup: string;
|
|
19
|
+
queryScope: string;
|
|
20
|
+
fields: {
|
|
21
|
+
fieldPath: string;
|
|
22
|
+
order: string;
|
|
23
|
+
}[];
|
|
24
|
+
}[];
|
|
25
|
+
fieldOverrides: never[];
|
|
26
|
+
};
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a Firebase Console URL for creating the required Firestore composite index.
|
|
3
|
+
* This URL will pre-fill the index creation form with the correct configuration,
|
|
4
|
+
* similar to the URLs provided in Firestore error messages.
|
|
5
|
+
*
|
|
6
|
+
* @param projectId - Your Firebase project ID
|
|
7
|
+
* @param databaseId - Your Firestore database ID (defaults to "(default)")
|
|
8
|
+
* @param collectionName - The collection name (defaults to "verification")
|
|
9
|
+
* @returns A Firebase Console URL with pre-filled index configuration
|
|
10
|
+
*/
|
|
11
|
+
export function generateIndexSetupUrl(projectId, databaseId = "(default)", collectionName = "verification") {
|
|
12
|
+
// For protobuf, use the original format (keep (default) as-is)
|
|
13
|
+
const protobufDatabaseId = databaseId;
|
|
14
|
+
// Construct the index resource path for protobuf
|
|
15
|
+
// Format: projects/{projectId}/databases/{databaseId}/collectionGroups/{collectionName}/indexes/
|
|
16
|
+
const indexPath = `projects/${projectId}/databases/${protobufDatabaseId}/collectionGroups/${collectionName}/indexes/`;
|
|
17
|
+
// Build protobuf-encoded message
|
|
18
|
+
// Based on Firebase's actual error message format:
|
|
19
|
+
// Field 1 (tag 0x0a, wire type 2): parent path (string)
|
|
20
|
+
const pathTag = Buffer.from([0x0a]); // Field 1, wire type 2
|
|
21
|
+
const pathLength = Buffer.from([indexPath.length]);
|
|
22
|
+
const pathData = Buffer.from(indexPath, "utf8");
|
|
23
|
+
// Field 2 (tag 0x10, wire type 0): query scope (1 = COLLECTION)
|
|
24
|
+
const scopeTag = Buffer.from([0x10, 0x01]); // Field 2, value 1
|
|
25
|
+
// Field 3 (tag 0x1a, wire type 2): fields array - identifier
|
|
26
|
+
const identifierField = Buffer.concat([
|
|
27
|
+
Buffer.from([0x1a, 0x0e]), // Field 3, length 14
|
|
28
|
+
Buffer.from([0x0a, 0x0a]), // Nested field 1, length 10
|
|
29
|
+
Buffer.from("identifier", "utf8"),
|
|
30
|
+
Buffer.from([0x10, 0x01]), // Nested field 2, value 1 (ASCENDING)
|
|
31
|
+
]);
|
|
32
|
+
// Field 4 (tag 0x1a, wire type 2): fields array - createdAt
|
|
33
|
+
const createdAtField = Buffer.concat([
|
|
34
|
+
Buffer.from([0x1a, 0x0d]), // Field 3, length 13
|
|
35
|
+
Buffer.from([0x0a, 0x09]), // Nested field 1, length 9
|
|
36
|
+
Buffer.from("createdAt", "utf8"),
|
|
37
|
+
Buffer.from([0x10, 0x02]), // Nested field 2, value 2 (DESCENDING)
|
|
38
|
+
]);
|
|
39
|
+
// Field 5 (tag 0x1a, wire type 2): fields array - __name__
|
|
40
|
+
const nameField = Buffer.concat([
|
|
41
|
+
Buffer.from([0x1a, 0x0c]), // Field 3, length 12
|
|
42
|
+
Buffer.from([0x0a, 0x08]), // Nested field 1, length 8
|
|
43
|
+
Buffer.from("__name__", "utf8"),
|
|
44
|
+
Buffer.from([0x10, 0x02]), // Nested field 2, value 2 (DESCENDING)
|
|
45
|
+
]);
|
|
46
|
+
// Combine all parts
|
|
47
|
+
const protobuf = Buffer.concat([
|
|
48
|
+
pathTag,
|
|
49
|
+
pathLength,
|
|
50
|
+
pathData,
|
|
51
|
+
scopeTag,
|
|
52
|
+
identifierField,
|
|
53
|
+
createdAtField,
|
|
54
|
+
nameField,
|
|
55
|
+
]);
|
|
56
|
+
const createComposite = protobuf.toString("base64");
|
|
57
|
+
// For default database, omit the database path entirely
|
|
58
|
+
if (databaseId === "(default)") {
|
|
59
|
+
return `https://console.firebase.google.com/project/${projectId}/firestore/indexes?create_composite=${createComposite}`;
|
|
60
|
+
}
|
|
61
|
+
// For custom databases, include the database path (convert (default) to -default- format)
|
|
62
|
+
const urlDatabaseId = databaseId === "(default)" ? "-default-" : databaseId;
|
|
63
|
+
return `https://console.firebase.google.com/project/${projectId}/firestore/databases/${urlDatabaseId}/indexes?create_composite=${createComposite}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the index configuration object for the verification collection.
|
|
67
|
+
* This can be used to create firestore.indexes.json file.
|
|
68
|
+
*/
|
|
69
|
+
export function getIndexConfig(collectionName = "verification") {
|
|
70
|
+
return {
|
|
71
|
+
indexes: [
|
|
72
|
+
{
|
|
73
|
+
collectionGroup: collectionName,
|
|
74
|
+
queryScope: "COLLECTION",
|
|
75
|
+
fields: [
|
|
76
|
+
{
|
|
77
|
+
fieldPath: "identifier",
|
|
78
|
+
order: "ASCENDING",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
fieldPath: "createdAt",
|
|
82
|
+
order: "DESCENDING",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
fieldPath: "__name__",
|
|
86
|
+
order: "DESCENDING",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
fieldOverrides: [],
|
|
92
|
+
};
|
|
93
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DBAdapterDebugLogOption } from "better-auth/adapters";
|
|
2
|
+
import type { AppOptions } from "firebase-admin/app";
|
|
3
|
+
import type { Firestore } from "firebase-admin/firestore";
|
|
4
|
+
export type NamingStrategy = "snake_case" | "default";
|
|
5
|
+
export interface FirestoreCollectionsOverride {
|
|
6
|
+
users?: string;
|
|
7
|
+
sessions?: string;
|
|
8
|
+
accounts?: string;
|
|
9
|
+
verificationTokens?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FirestoreAdapterConfig extends AppOptions {
|
|
12
|
+
name?: string;
|
|
13
|
+
firestore?: Firestore;
|
|
14
|
+
namingStrategy?: NamingStrategy;
|
|
15
|
+
collections?: FirestoreCollectionsOverride;
|
|
16
|
+
debugLogs?: DBAdapterDebugLogOption;
|
|
17
|
+
}
|
|
18
|
+
export interface InternalNormalizedConfig {
|
|
19
|
+
firestore: Firestore;
|
|
20
|
+
preferSnakeCase: boolean;
|
|
21
|
+
collections: Required<Required<FirestoreAdapterConfig>["collections"]>;
|
|
22
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Firestore } from "firebase-admin/firestore";
|
|
2
|
+
export type FieldMapper = {
|
|
3
|
+
toDb: (field: string) => string;
|
|
4
|
+
fromDb: (field: string) => string;
|
|
5
|
+
};
|
|
6
|
+
export declare function mapFieldsFactory(preferSnakeCase?: boolean): FieldMapper;
|
|
7
|
+
export declare function getConverter<Document extends Record<string, any>>(options: {
|
|
8
|
+
excludeId?: boolean;
|
|
9
|
+
preferSnakeCase?: boolean;
|
|
10
|
+
}): {
|
|
11
|
+
toFirestore(object: Document): Record<string, unknown>;
|
|
12
|
+
fromFirestore(snapshot: FirebaseFirestore.QueryDocumentSnapshot<Document>): Document;
|
|
13
|
+
};
|
|
14
|
+
export declare function getOneDoc<T>(querySnapshot: FirebaseFirestore.Query<T>): Promise<T | null>;
|
|
15
|
+
export declare function getDoc<T>(docRef: FirebaseFirestore.DocumentReference<T>): Promise<T | null>;
|
|
16
|
+
export declare function deleteDocs<T>(querySnapshot: FirebaseFirestore.Query<T>): Promise<void>;
|
|
17
|
+
export declare function collectionsFactory(db: Firestore, preferSnakeCase: boolean | undefined, collections: {
|
|
18
|
+
users: string;
|
|
19
|
+
sessions: string;
|
|
20
|
+
accounts: string;
|
|
21
|
+
verificationTokens: string;
|
|
22
|
+
}): {
|
|
23
|
+
users: FirebaseFirestore.CollectionReference<any, FirebaseFirestore.DocumentData>;
|
|
24
|
+
sessions: FirebaseFirestore.CollectionReference<any, FirebaseFirestore.DocumentData>;
|
|
25
|
+
accounts: FirebaseFirestore.CollectionReference<any, FirebaseFirestore.DocumentData>;
|
|
26
|
+
verification_tokens: FirebaseFirestore.CollectionReference<any, FirebaseFirestore.DocumentData>;
|
|
27
|
+
};
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Timestamp } from "firebase-admin/firestore";
|
|
2
|
+
const MAP_TO_FIRESTORE = {
|
|
3
|
+
userId: "user_id",
|
|
4
|
+
sessionToken: "session_token",
|
|
5
|
+
providerAccountId: "provider_account_id",
|
|
6
|
+
emailVerified: "email_verified",
|
|
7
|
+
};
|
|
8
|
+
const MAP_FROM_FIRESTORE = Object.fromEntries(Object.entries(MAP_TO_FIRESTORE).map(([k, v]) => [v, k]));
|
|
9
|
+
const identity = (x) => x;
|
|
10
|
+
export function mapFieldsFactory(preferSnakeCase) {
|
|
11
|
+
if (preferSnakeCase) {
|
|
12
|
+
return {
|
|
13
|
+
toDb: (field) => MAP_TO_FIRESTORE[field] ?? field,
|
|
14
|
+
fromDb: (field) => MAP_FROM_FIRESTORE[field] ?? field,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return { toDb: identity, fromDb: identity };
|
|
18
|
+
}
|
|
19
|
+
export function getConverter(options) {
|
|
20
|
+
const mapper = mapFieldsFactory(options?.preferSnakeCase);
|
|
21
|
+
return {
|
|
22
|
+
toFirestore(object) {
|
|
23
|
+
const document = {};
|
|
24
|
+
for (const key in object) {
|
|
25
|
+
if (key === "id")
|
|
26
|
+
continue;
|
|
27
|
+
const value = object[key];
|
|
28
|
+
if (value !== undefined) {
|
|
29
|
+
document[mapper.toDb(key)] = value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return document;
|
|
33
|
+
},
|
|
34
|
+
fromFirestore(snapshot) {
|
|
35
|
+
const document = snapshot.data();
|
|
36
|
+
const object = {};
|
|
37
|
+
if (!options?.excludeId)
|
|
38
|
+
object.id = snapshot.id;
|
|
39
|
+
for (const key in document) {
|
|
40
|
+
let value = document[key];
|
|
41
|
+
if (value instanceof Timestamp)
|
|
42
|
+
value = value.toDate();
|
|
43
|
+
object[mapper.fromDb(key)] = value;
|
|
44
|
+
}
|
|
45
|
+
return object;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export async function getOneDoc(querySnapshot) {
|
|
50
|
+
const querySnap = await querySnapshot.limit(1).get();
|
|
51
|
+
return querySnap.docs[0]?.data() ?? null;
|
|
52
|
+
}
|
|
53
|
+
export async function getDoc(docRef) {
|
|
54
|
+
const docSnap = await docRef.get();
|
|
55
|
+
return docSnap.data() ?? null;
|
|
56
|
+
}
|
|
57
|
+
export async function deleteDocs(querySnapshot) {
|
|
58
|
+
const querySnap = await querySnapshot.get();
|
|
59
|
+
for (const doc of querySnap.docs) {
|
|
60
|
+
await doc.ref.delete();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function collectionsFactory(db, preferSnakeCase = false, collections) {
|
|
64
|
+
return {
|
|
65
|
+
users: db
|
|
66
|
+
.collection(collections.users)
|
|
67
|
+
.withConverter(getConverter({ preferSnakeCase })),
|
|
68
|
+
sessions: db
|
|
69
|
+
.collection(collections.sessions)
|
|
70
|
+
.withConverter(getConverter({ preferSnakeCase })),
|
|
71
|
+
accounts: db
|
|
72
|
+
.collection(collections.accounts)
|
|
73
|
+
.withConverter(getConverter({ preferSnakeCase })),
|
|
74
|
+
verification_tokens: db
|
|
75
|
+
.collection(collections.verificationTokens)
|
|
76
|
+
.withConverter(getConverter({ preferSnakeCase, excludeId: true })),
|
|
77
|
+
};
|
|
78
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-auth-firestore",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Firestore adapter for Better Auth (Firebase Admin SDK)",
|
|
6
|
+
"author": "Slava Yultyyev <yultyyev@gmail.com>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.cjs",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.build.json",
|
|
26
|
+
"clean": "rimraf dist",
|
|
27
|
+
"test": "./tests/test.sh",
|
|
28
|
+
"lint": "biome check --formatter-enabled=false",
|
|
29
|
+
"lint:fix": "biome check --write",
|
|
30
|
+
"lint:fix:unsafe": "biome check --write --unsafe",
|
|
31
|
+
"prepublishOnly": "pnpm run build"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=22"
|
|
35
|
+
},
|
|
36
|
+
"packageManager": "pnpm@10.0.0",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/yultyyev/better-auth-firestore.git"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"better-auth",
|
|
46
|
+
"firebase",
|
|
47
|
+
"firestore",
|
|
48
|
+
"adapter",
|
|
49
|
+
"authentication"
|
|
50
|
+
],
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"better-auth": "*",
|
|
53
|
+
"firebase-admin": ">=13",
|
|
54
|
+
"typescript": "^5.0.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@biomejs/biome": "^2.3.2",
|
|
58
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
59
|
+
"@semantic-release/commit-analyzer": "^13.0.0",
|
|
60
|
+
"@semantic-release/github": "^11.0.1",
|
|
61
|
+
"@semantic-release/npm": "^12.0.1",
|
|
62
|
+
"@semantic-release/release-notes-generator": "^12.1.0",
|
|
63
|
+
"rimraf": "^6.0.1",
|
|
64
|
+
"semantic-release": "^24.0.0",
|
|
65
|
+
"typescript": "^5.9.3",
|
|
66
|
+
"vitest": "^4.0.5"
|
|
67
|
+
}
|
|
68
|
+
}
|