@wopr-network/platform-core 1.0.2 → 1.0.3

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.
@@ -11,6 +11,7 @@ import { betterAuth } from "better-auth";
11
11
  import type { Pool } from "pg";
12
12
  import type { PlatformDb } from "../db/index.js";
13
13
  import { PgEmailVerifier } from "../email/verification.js";
14
+ import { type IUserCreator } from "./user-creator.js";
14
15
  /** OAuth provider credentials. */
15
16
  export interface OAuthProvider {
16
17
  clientId: string;
@@ -63,6 +64,7 @@ export interface BetterAuthConfig {
63
64
  /** Called after a new user signs up (e.g., create personal tenant). */
64
65
  onUserCreated?: (userId: string, userName: string, email: string) => Promise<void>;
65
66
  }
67
+ export declare function getUserCreator(): Promise<IUserCreator>;
66
68
  /** The type of a better-auth instance. */
67
69
  export type Auth = ReturnType<typeof betterAuth>;
68
70
  /** Initialize Better Auth with the given config. Must be called before getAuth(). */
@@ -24,15 +24,20 @@ const DEFAULT_RATE_LIMIT_RULES = {
24
24
  let _config = null;
25
25
  let _userCreator = null;
26
26
  let _userCreatorPromise = null;
27
- async function getUserCreator() {
27
+ export async function getUserCreator() {
28
28
  if (_userCreator)
29
29
  return _userCreator;
30
30
  if (!_userCreatorPromise) {
31
31
  if (!_config)
32
32
  throw new Error("BetterAuth not initialized — call initBetterAuth() first");
33
- _userCreatorPromise = createUserCreator(new RoleStore(_config.db)).then((creator) => {
33
+ _userCreatorPromise = createUserCreator(new RoleStore(_config.db))
34
+ .then((creator) => {
34
35
  _userCreator = creator;
35
36
  return creator;
37
+ })
38
+ .catch((err) => {
39
+ _userCreatorPromise = null;
40
+ throw err;
36
41
  });
37
42
  }
38
43
  return _userCreatorPromise;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,35 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ const mockCreateUserCreator = vi.fn();
3
+ vi.mock("./user-creator.js", () => ({
4
+ createUserCreator: (...args) => mockCreateUserCreator(...args),
5
+ }));
6
+ vi.mock("../admin/role-store.js", () => ({
7
+ RoleStore: vi.fn(),
8
+ }));
9
+ const { getUserCreator, initBetterAuth, resetUserCreator } = await import("./better-auth.js");
10
+ const fakeConfig = { pool: {}, db: {} };
11
+ describe("getUserCreator", () => {
12
+ afterEach(() => {
13
+ resetUserCreator();
14
+ mockCreateUserCreator.mockReset();
15
+ });
16
+ it("caches the resolved creator on success", async () => {
17
+ initBetterAuth(fakeConfig);
18
+ const fakeCreator = { createUser: vi.fn() };
19
+ mockCreateUserCreator.mockResolvedValueOnce(fakeCreator);
20
+ const first = await getUserCreator();
21
+ const second = await getUserCreator();
22
+ expect(first).toBe(second);
23
+ expect(mockCreateUserCreator).toHaveBeenCalledOnce();
24
+ });
25
+ it("clears cached promise on rejection so next call retries", async () => {
26
+ initBetterAuth(fakeConfig);
27
+ const fakeCreator = { createUser: vi.fn() };
28
+ mockCreateUserCreator.mockRejectedValueOnce(new Error("DB unavailable"));
29
+ mockCreateUserCreator.mockResolvedValueOnce(fakeCreator);
30
+ await expect(getUserCreator()).rejects.toThrow("DB unavailable");
31
+ const creator = await getUserCreator();
32
+ expect(creator).toBe(fakeCreator);
33
+ expect(mockCreateUserCreator).toHaveBeenCalledTimes(2);
34
+ });
35
+ });
@@ -187,7 +187,7 @@ export declare function validateTenantAccess(userId: string, requestedTenantId:
187
187
  export type { IApiKeyRepository } from "./api-key-repository.js";
188
188
  export { DrizzleApiKeyRepository } from "./api-key-repository.js";
189
189
  export type { Auth, AuthRateLimitRule, BetterAuthConfig, OAuthProvider, } from "./better-auth.js";
190
- export { getAuth, getEmailVerifier, initBetterAuth, resetAuth, resetUserCreator, runAuthMigrations, setAuth, } from "./better-auth.js";
190
+ export { getAuth, getEmailVerifier, getUserCreator, initBetterAuth, resetAuth, resetUserCreator, runAuthMigrations, setAuth, } from "./better-auth.js";
191
191
  export type { ILoginHistoryRepository, LoginHistoryEntry } from "./login-history-repository.js";
192
192
  export { BetterAuthLoginHistoryRepository } from "./login-history-repository.js";
193
193
  export type { SessionAuthEnv } from "./middleware.js";
@@ -422,7 +422,7 @@ export async function validateTenantAccess(userId, requestedTenantId, orgMemberR
422
422
  }
423
423
  export { DrizzleApiKeyRepository } from "./api-key-repository.js";
424
424
  // Test utilities — do not call in production code
425
- export { getAuth, getEmailVerifier, initBetterAuth, resetAuth, resetUserCreator, runAuthMigrations, setAuth, } from "./better-auth.js";
425
+ export { getAuth, getEmailVerifier, getUserCreator, initBetterAuth, resetAuth, resetUserCreator, runAuthMigrations, setAuth, } from "./better-auth.js";
426
426
  export { BetterAuthLoginHistoryRepository } from "./login-history-repository.js";
427
427
  export { dualAuth, sessionAuth } from "./middleware.js";
428
428
  export { createUserCreator } from "./user-creator.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wopr-network/platform-core",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,47 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+
3
+ const mockCreateUserCreator = vi.fn();
4
+ vi.mock("./user-creator.js", () => ({
5
+ createUserCreator: (...args: unknown[]) => mockCreateUserCreator(...args),
6
+ }));
7
+
8
+ vi.mock("../admin/role-store.js", () => ({
9
+ RoleStore: vi.fn(),
10
+ }));
11
+
12
+ const { getUserCreator, initBetterAuth, resetUserCreator } = await import("./better-auth.js");
13
+
14
+ const fakeConfig = { pool: {}, db: {} } as Parameters<typeof initBetterAuth>[0];
15
+
16
+ describe("getUserCreator", () => {
17
+ afterEach(() => {
18
+ resetUserCreator();
19
+ mockCreateUserCreator.mockReset();
20
+ });
21
+
22
+ it("caches the resolved creator on success", async () => {
23
+ initBetterAuth(fakeConfig);
24
+ const fakeCreator = { createUser: vi.fn() };
25
+ mockCreateUserCreator.mockResolvedValueOnce(fakeCreator);
26
+
27
+ const first = await getUserCreator();
28
+ const second = await getUserCreator();
29
+
30
+ expect(first).toBe(second);
31
+ expect(mockCreateUserCreator).toHaveBeenCalledOnce();
32
+ });
33
+
34
+ it("clears cached promise on rejection so next call retries", async () => {
35
+ initBetterAuth(fakeConfig);
36
+ const fakeCreator = { createUser: vi.fn() };
37
+
38
+ mockCreateUserCreator.mockRejectedValueOnce(new Error("DB unavailable"));
39
+ mockCreateUserCreator.mockResolvedValueOnce(fakeCreator);
40
+
41
+ await expect(getUserCreator()).rejects.toThrow("DB unavailable");
42
+
43
+ const creator = await getUserCreator();
44
+ expect(creator).toBe(fakeCreator);
45
+ expect(mockCreateUserCreator).toHaveBeenCalledTimes(2);
46
+ });
47
+ });
@@ -94,14 +94,19 @@ let _config: BetterAuthConfig | null = null;
94
94
  let _userCreator: IUserCreator | null = null;
95
95
  let _userCreatorPromise: Promise<IUserCreator> | null = null;
96
96
 
97
- async function getUserCreator(): Promise<IUserCreator> {
97
+ export async function getUserCreator(): Promise<IUserCreator> {
98
98
  if (_userCreator) return _userCreator;
99
99
  if (!_userCreatorPromise) {
100
100
  if (!_config) throw new Error("BetterAuth not initialized — call initBetterAuth() first");
101
- _userCreatorPromise = createUserCreator(new RoleStore(_config.db)).then((creator) => {
102
- _userCreator = creator;
103
- return creator;
104
- });
101
+ _userCreatorPromise = createUserCreator(new RoleStore(_config.db))
102
+ .then((creator) => {
103
+ _userCreator = creator;
104
+ return creator;
105
+ })
106
+ .catch((err) => {
107
+ _userCreatorPromise = null;
108
+ throw err;
109
+ });
105
110
  }
106
111
  return _userCreatorPromise;
107
112
  }
package/src/auth/index.ts CHANGED
@@ -535,6 +535,7 @@ export type {
535
535
  export {
536
536
  getAuth,
537
537
  getEmailVerifier,
538
+ getUserCreator,
538
539
  initBetterAuth,
539
540
  resetAuth,
540
541
  resetUserCreator,
package/vitest.config.ts CHANGED
@@ -3,6 +3,7 @@ import { defineConfig } from "vitest/config";
3
3
  export default defineConfig({
4
4
  test: {
5
5
  testTimeout: 30000,
6
+ hookTimeout: 30000,
6
7
  include: ["src/**/*.test.ts"],
7
8
  coverage: {
8
9
  provider: "v8",