@siran/auth-core 0.1.1 → 0.9.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.
@@ -0,0 +1,21 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
4
+ "editor.codeActionsOnSave": {
5
+ "source.fixAll": "explicit",
6
+ "source.organizeImports": "explicit",
7
+ "source.fixAll.eslint": "explicit"
8
+ },
9
+ "eslint.enable": true,
10
+ "eslint.run": "onSave",
11
+ "eslint.validate": [
12
+ "javascript",
13
+ "javascriptreact",
14
+ "typescript",
15
+ "typescriptreact"
16
+ ],
17
+ "editor.tabSize": 2,
18
+ "editor.detectIndentation": false,
19
+ "editor.insertSpaces": true,
20
+ "editor.formatOnSaveMode": "file",
21
+ }
package/CHANGELOG.md CHANGED
@@ -1,3 +1,98 @@
1
+ ## 0.9.0 (2026-01-24)
2
+
3
+ ### 🚀 Features
4
+
5
+ - Introduce AuthEngine and related components for enhanced authentication flow ([fe11cd9](https://github.com/narisraz/auth/commit/fe11cd9))
6
+
7
+ ### ❤️ Thank You
8
+
9
+ - Naris Razafimahatratra
10
+
11
+ ## 0.8.1 (2026-01-24)
12
+
13
+ ### 🩹 Fixes
14
+
15
+ - Update error handling in registerUser to include violatedPolicies ([80c2363](https://github.com/narisraz/auth/commit/80c2363))
16
+
17
+ ### ❤️ Thank You
18
+
19
+ - Naris Razafimahatratra
20
+
21
+ ## 0.8.0 (2026-01-24)
22
+
23
+ ### 🚀 Features
24
+
25
+ - Enhance AuthResult and PreRegisterPolicy for detailed error reporting ([492bf1a](https://github.com/narisraz/auth/commit/492bf1a))
26
+
27
+ ### ❤️ Thank You
28
+
29
+ - Naris Razafimahatratra
30
+
31
+ ## 0.7.0 (2026-01-24)
32
+
33
+ ### 🚀 Features
34
+
35
+ - Add isActive method to PreRegisterPolicy and update user registration logic ([2fdb3d3](https://github.com/narisraz/auth/commit/2fdb3d3))
36
+
37
+ ### ❤️ Thank You
38
+
39
+ - Naris Razafimahatratra
40
+
41
+ ## 0.6.0 (2026-01-24)
42
+
43
+ ### 🚀 Features
44
+
45
+ - Enhance user registration with pre-register policy validation ([6ae97bb](https://github.com/narisraz/auth/commit/6ae97bb))
46
+
47
+ ### ❤️ Thank You
48
+
49
+ - Naris Razafimahatratra
50
+
51
+ ## 0.5.0 (2026-01-24)
52
+
53
+ ### 🚀 Features
54
+
55
+ - Add user existence check to registration process ([cd6e3b9](https://github.com/narisraz/auth/commit/cd6e3b9))
56
+
57
+ ### 🩹 Fixes
58
+
59
+ - Restore export of authenticate-user use case in index file ([aec572f](https://github.com/narisraz/auth/commit/aec572f))
60
+ - Update user registration tests for accurate assertions ([5c0e047](https://github.com/narisraz/auth/commit/5c0e047))
61
+
62
+ ### ❤️ Thank You
63
+
64
+ - Naris Razafimahatratra
65
+
66
+ ## 0.4.0 (2026-01-23)
67
+
68
+ ### 🚀 Features
69
+
70
+ - Introduce AuthPreferencesService for flexible account verification handling ([63490c6](https://github.com/narisraz/auth/commit/63490c6))
71
+
72
+ ### ❤️ Thank You
73
+
74
+ - Naris Razafimahatratra
75
+
76
+ ## 0.3.0 (2026-01-23)
77
+
78
+ ### 🚀 Features
79
+
80
+ - Extend authentication logic to include account verification status ([e7d5ffa](https://github.com/narisraz/auth/commit/e7d5ffa))
81
+
82
+ ### ❤️ Thank You
83
+
84
+ - Naris Razafimahatratra
85
+
86
+ ## 0.2.0 (2026-01-23)
87
+
88
+ ### 🚀 Features
89
+
90
+ - Enhance user authentication to handle account status ([0188b61](https://github.com/narisraz/auth/commit/0188b61))
91
+
92
+ ### ❤️ Thank You
93
+
94
+ - Naris Razafimahatratra
95
+
1
96
  ## 0.1.1 (2026-01-23)
2
97
 
3
98
  ### 🩹 Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siran/auth-core",
3
- "version": "0.1.1",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -0,0 +1,9 @@
1
+ export type AuthPreferences = {
2
+ allowLoginWithNotVerifiedAccount: boolean;
3
+ allowDuplicatedAccount: boolean;
4
+ };
5
+
6
+ export interface AuthPreferencesServicePort {
7
+ getAuthPreferences(): Promise<AuthPreferences>;
8
+ }
9
+
@@ -6,15 +6,23 @@ export type AuthMethod =
6
6
  | { type: "magic_link"; token: string }
7
7
  | { type: "oauth"; provider: "google" | "github" | "apple" | "facebook"; code: string };
8
8
 
9
- export type AuthErrorCode = "INVALID_CREDENTIALS" | "ACCOUNT_DISABLED" | "ACCOUNT_LOCKED";
9
+ export type AuthErrorCode =
10
+ | "INVALID_CREDENTIALS"
11
+ | "ACCOUNT_DISABLED"
12
+ | "ACCOUNT_NOT_VERIFIED"
13
+ | "ACCOUNT_LOCKED"
14
+ | "PRE_REGISTER_POLICY_VIOLATED";
10
15
 
11
- export type AuthResult =
12
- | { ok: true; user: UserAccount }
13
- | { ok: false; error: AuthErrorCode };
16
+ export type AuthResultSuccess = { ok: true; user: UserAccount };
17
+ export type AuthResultFailure = { ok: false; error: AuthErrorCode; violatedPolicies: string[] };
18
+
19
+ export type AuthResult = AuthResultSuccess | AuthResultFailure;
14
20
 
15
21
  export interface AuthServicePort {
16
22
  authenticate(method: AuthMethod): Promise<AuthResult>;
23
+ register(method: AuthMethod): Promise<AuthResult>;
17
24
  logout(): Promise<void>;
25
+ userExists(method: AuthMethod): Promise<boolean>;
18
26
  }
19
27
 
20
28
 
@@ -0,0 +1,7 @@
1
+ import { AuthMethod } from "./auth-service.port.js";
2
+
3
+ export interface PreRegisterPolicy {
4
+ code: string;
5
+ check: (method: AuthMethod) => Promise<boolean>;
6
+ isActive: (method: AuthMethod) => Promise<boolean>;
7
+ }
@@ -0,0 +1,20 @@
1
+
2
+ import { AuthMethod, AuthServicePort } from "@application/ports/auth-service.port.js";
3
+ import { PreRegisterPolicy } from "@application/ports/pre-register-policy.port.js";
4
+
5
+ export class AccountAlreadyExistsPolicy implements PreRegisterPolicy {
6
+ constructor(
7
+ private readonly authService: AuthServicePort,
8
+ private readonly enabled: boolean,
9
+ ) { }
10
+
11
+ code: string = 'ACCOUNT_ALREADY_EXISTS';
12
+
13
+ async check(method: AuthMethod): Promise<boolean> {
14
+ return this.authService.userExists(method);
15
+ }
16
+
17
+ async isActive(method: AuthMethod): Promise<boolean> {
18
+ return this.enabled;
19
+ }
20
+ }
@@ -1,8 +1,21 @@
1
+ import { AuthPreferencesServicePort } from "@application/ports/auth-preference-service.port.js";
2
+ import type { AuthMethod, AuthResult } from "@application/ports/auth-service.port.js";
1
3
  import { AuthServicePort } from "@application/ports/auth-service.port.js";
2
- import type { AuthMethod } from "@application/ports/auth-service.port.js";
3
4
 
4
5
 
5
6
  export const authenticateUser =
6
- (authService: AuthServicePort) =>
7
- (method: AuthMethod) =>
8
- authService.authenticate(method);
7
+ (authService: AuthServicePort, authPreferencesService: AuthPreferencesServicePort) =>
8
+ async (method: AuthMethod): Promise<AuthResult> => {
9
+ const result = await authService.authenticate(method);
10
+ if (!result.ok) {
11
+ return { ok: false, error: result.error, violatedPolicies: [] };
12
+ }
13
+ if (result.user.status === 'disabled') {
14
+ return { ok: false, error: 'ACCOUNT_DISABLED', violatedPolicies: [] };
15
+ }
16
+ const preferences = await authPreferencesService.getAuthPreferences();
17
+ if (!result.user.isVerified && !preferences.allowLoginWithNotVerifiedAccount) {
18
+ return { ok: false, error: 'ACCOUNT_NOT_VERIFIED', violatedPolicies: [] };
19
+ }
20
+ return { ok: true, user: result.user };
21
+ }
@@ -0,0 +1,28 @@
1
+ import { AuthMethod, AuthResult, AuthServicePort } from "@application/ports/auth-service.port.js";
2
+ import { PreRegisterPolicy } from "@application/ports/pre-register-policy.port.js";
3
+
4
+ export const registerUser =
5
+ (authService: AuthServicePort, policies: PreRegisterPolicy[]) =>
6
+ async (method: AuthMethod): Promise<AuthResult> => {
7
+ const activePolicies = await Promise.all(policies
8
+ .map(async policy => ({
9
+ isActive: await policy.isActive(method),
10
+ value: policy,
11
+ }))
12
+ );
13
+ const results = await Promise.all(activePolicies
14
+ .filter(policy => policy.isActive)
15
+ .map(async policy => ({
16
+ code: policy.value.code,
17
+ ok: await policy.value.check(method),
18
+ })));
19
+ const violdatedPolicies = results.filter(result => !result.ok);
20
+ if (violdatedPolicies.length > 0) {
21
+ return {
22
+ ok: false,
23
+ error: 'PRE_REGISTER_POLICY_VIOLATED',
24
+ violatedPolicies: violdatedPolicies.map(result => result.code)
25
+ };
26
+ }
27
+ return authService.register(method);
28
+ };
@@ -0,0 +1,28 @@
1
+ import { AuthPreferencesServicePort } from "@application/ports/auth-preference-service.port.js";
2
+ import { AuthServicePort } from "@application/ports/auth-service.port.js";
3
+ import { PreRegisterPolicy } from "@application/ports/pre-register-policy.port.js";
4
+ import { AccountAlreadyExistsPolicy } from "@application/services/account-already-exists.service.js";
5
+ import { authenticateUser } from "@application/use-cases/authenticate-user.js";
6
+ import { registerUser } from "@application/use-cases/register-user.js";
7
+ import { AuthEngine } from "@root/auth-engine.js";
8
+
9
+ export class AuthEngineFactory {
10
+ static async create(
11
+ authService: AuthServicePort,
12
+ authPreferencesService: AuthPreferencesServicePort,
13
+ basePolicies: PreRegisterPolicy[],
14
+ ): Promise<AuthEngine> {
15
+ const preferences = await authPreferencesService.getAuthPreferences();
16
+
17
+ const policies = [
18
+ ...basePolicies,
19
+ new AccountAlreadyExistsPolicy(authService, !preferences.allowDuplicatedAccount),
20
+ ];
21
+
22
+ return new AuthEngine({
23
+ register: registerUser(authService, policies),
24
+ authenticate: authenticateUser(authService, authPreferencesService),
25
+ logout: () => authService.logout(),
26
+ });
27
+ }
28
+ }
@@ -0,0 +1,25 @@
1
+ import { AuthMethod, AuthResult } from "@application/ports/auth-service.port.js";
2
+
3
+ export interface AuthActions {
4
+ register(method: AuthMethod): Promise<AuthResult>;
5
+ authenticate(method: AuthMethod): Promise<AuthResult>;
6
+ logout(): Promise<void>;
7
+ }
8
+
9
+ export class AuthEngine implements AuthActions {
10
+ constructor(
11
+ private readonly useCases: AuthActions,
12
+ ) { }
13
+
14
+ async register(method: AuthMethod): Promise<AuthResult> {
15
+ return this.useCases.register(method);
16
+ }
17
+
18
+ async authenticate(method: AuthMethod): Promise<AuthResult> {
19
+ return await this.useCases.authenticate(method);
20
+ }
21
+
22
+ async logout(): Promise<void> {
23
+ return await this.useCases.logout();
24
+ }
25
+ }
@@ -1,22 +1,16 @@
1
1
  export type UserStatus = "active" | "disabled" | "lockedTemporarily";
2
2
 
3
- export type UserRole = "parent" | "staff" | "admin" | "student" | "teacher";
4
-
5
3
  /**
6
4
  * Domaine: compte utilisateur Sekoliko.
7
5
  * Indépendant de toute technologie (pas de dépendance à Supabase ou React).
8
6
  */
9
7
  export interface UserAccount {
10
8
  id: string;
11
- establishmentIds: string[];
12
9
  displayName: string;
13
- firstName?: string;
14
- lastName?: string;
15
- contactEmail: string;
16
10
  status: UserStatus;
17
- roles: UserRole[];
18
- failedLoginAttempts: number;
19
- lastFailedLoginAt: Date | null;
11
+ failedLoginAttempts?: number;
12
+ lastFailedLoginAt?: Date | null;
13
+ isVerified?: boolean;
20
14
  }
21
15
 
22
16
  export const canLogin = (user: UserAccount): boolean =>
package/src/index.ts CHANGED
@@ -2,10 +2,15 @@
2
2
  * Domain
3
3
  */
4
4
  export * from '@domain/user-account.js';
5
- export * from '@domain/session.js';
6
5
 
7
6
  /**
8
7
  * Application
9
8
  */
10
- export * from '@application/use-cases/authenticate-user.js';
11
9
  export * from '@application/ports/auth-service.port.js';
10
+ export * from '@application/ports/pre-register-policy.port.js';
11
+
12
+ /**
13
+ * Auth Engine
14
+ */
15
+ export * from '@root/auth-engine.factory.js';
16
+ export * from '@root/auth-engine.js';
@@ -0,0 +1,14 @@
1
+ import { AuthPreferences, AuthPreferencesServicePort } from "@application/ports/auth-preference-service.port.js";
2
+ import { vi } from "vitest";
3
+
4
+ interface AuthPreferencesServiceMock {
5
+ getAuthPreferences?: () => Promise<AuthPreferences>;
6
+ }
7
+
8
+ export function createAuthPreferencesServiceMock(
9
+ authPreferencesService?: AuthPreferencesServiceMock,
10
+ ): AuthPreferencesServicePort {
11
+ return {
12
+ getAuthPreferences: authPreferencesService?.getAuthPreferences ?? vi.fn().mockResolvedValue({ allowLoginWithNotVerifiedAccount: false }),
13
+ };
14
+ }
@@ -0,0 +1,21 @@
1
+ import { AuthMethod, AuthResult, AuthServicePort } from "@application/ports/auth-service.port.js";
2
+ import { UserAccount } from "@domain/user-account.js";
3
+ import { vi } from "vitest";
4
+
5
+ const activeUser: UserAccount = { id: '1', displayName: 'test@test.com', status: 'active', isVerified: true };
6
+
7
+ interface AuthServiceMock {
8
+ authenticate?: (method: AuthMethod) => Promise<AuthResult>;
9
+ register?: (method: AuthMethod) => Promise<AuthResult>;
10
+ logout?: () => Promise<void>;
11
+ userExists?: (method: AuthMethod) => Promise<boolean>;
12
+ }
13
+
14
+ export function createAuthServiceMock(authService?: AuthServiceMock): AuthServicePort {
15
+ return {
16
+ authenticate: authService?.authenticate ?? vi.fn().mockResolvedValue({ ok: true, user: activeUser }),
17
+ logout: authService?.logout ?? vi.fn().mockResolvedValue(undefined),
18
+ register: authService?.register ?? vi.fn().mockResolvedValue({ ok: true, user: activeUser }),
19
+ userExists: authService?.userExists ?? vi.fn().mockResolvedValue(false),
20
+ };
21
+ }
@@ -0,0 +1,16 @@
1
+ import { AuthMethod } from "@application/ports/auth-service.port.js";
2
+ import { PreRegisterPolicy } from "@application/ports/pre-register-policy.port.js";
3
+
4
+ export interface PreRegisterPolicyMock {
5
+ check?: (method: AuthMethod) => Promise<boolean>;
6
+ isActive?: (method: AuthMethod) => Promise<boolean>;
7
+ code?: string;
8
+ }
9
+
10
+ export function createPreRegisterPolicyMock(preRegisterPolicy?: PreRegisterPolicyMock): PreRegisterPolicy {
11
+ return {
12
+ check: preRegisterPolicy?.check ?? vi.fn().mockResolvedValue(true),
13
+ isActive: preRegisterPolicy?.isActive ?? vi.fn().mockResolvedValue(false),
14
+ code: preRegisterPolicy?.code ?? 'POLICY_ERROR',
15
+ };
16
+ }
@@ -1,25 +1,72 @@
1
1
  import { authenticateUser } from "@application/use-cases/authenticate-user.js";
2
- import { AuthServicePort } from "@application/ports/auth-service.port.js";
2
+ import { createAuthPreferencesServiceMock } from "@tests/application/ports/auth-preferences-service.port.mock.js";
3
+ import { createAuthServiceMock } from "@tests/application/ports/auth-service.port.mock.js";
4
+ import { inactiveUser, notVerifiedUser } from "@tests/domain/user-account.data.js";
3
5
  import { describe, expect, it, vi } from "vitest";
4
6
 
5
7
  describe('AuthenticateUser', () => {
6
8
  it('should authenticate a user', async () => {
7
- const authService: AuthServicePort = {
8
- authenticate: vi.fn().mockResolvedValue({ ok: true, user: { id: '1', email: 'test@test.com' } }),
9
- logout: vi.fn().mockResolvedValue(undefined),
10
- };
11
- const loginUser = authenticateUser(authService);
12
- const user = await loginUser({ type: 'password', identifier: 'test@test.com', password: 'test' });
13
- expect(user).toEqual({ ok: true, user: { id: '1', email: 'test@test.com' } });
9
+ // Given
10
+ const authService = createAuthServiceMock();
11
+ const authPreferencesService = createAuthPreferencesServiceMock();
12
+ const loginUser = authenticateUser(authService, authPreferencesService);
13
+ // When
14
+ const result = await loginUser({ type: 'password', identifier: 'test@test.com', password: 'test' });
15
+ // Then
16
+ expect(result.ok).toBe(true);
14
17
  });
15
18
 
16
19
  it('should return an error if the authentication fails', async () => {
17
- const authService: AuthServicePort = {
20
+ // Given
21
+ const authService = createAuthServiceMock({
18
22
  authenticate: vi.fn().mockResolvedValue({ ok: false, error: 'INVALID_CREDENTIALS' }),
19
- logout: vi.fn().mockResolvedValue(undefined),
20
- };
21
- const loginUser = authenticateUser(authService);
23
+ });
24
+ const authPreferencesService = createAuthPreferencesServiceMock();
25
+ // When
26
+ const loginUser = authenticateUser(authService, authPreferencesService);
27
+ const user = await loginUser({ type: 'password', identifier: 'test@test.com', password: 'test' });
28
+ // Then
29
+ expect(user).toEqual({ ok: false, error: 'INVALID_CREDENTIALS', violatedPolicies: [] });
30
+ });
31
+
32
+ it('should not be possible to authenticate with deactivated account', async () => {
33
+ // Given
34
+ const authService = createAuthServiceMock({
35
+ authenticate: vi.fn().mockResolvedValue({ ok: true, user: inactiveUser }),
36
+ });
37
+ const authPreferencesService = createAuthPreferencesServiceMock();
38
+ // When
39
+ const loginUser = authenticateUser(authService, authPreferencesService);
22
40
  const user = await loginUser({ type: 'password', identifier: 'test@test.com', password: 'test' });
23
- expect(user).toEqual({ ok: false, error: 'INVALID_CREDENTIALS' });
41
+ // Then
42
+ expect(user).toEqual({ ok: false, error: 'ACCOUNT_DISABLED', violatedPolicies: [] });
43
+ });
44
+
45
+ it('should not be possible to authenticate with not verified account', async () => {
46
+ // Given
47
+ const authService = createAuthServiceMock({
48
+ authenticate: vi.fn().mockResolvedValue({ ok: true, user: notVerifiedUser }),
49
+ });
50
+ const authPreferencesService = createAuthPreferencesServiceMock();
51
+ // When
52
+ const loginUser = authenticateUser(authService, authPreferencesService);
53
+ // Then
54
+ const result = await loginUser({ type: 'password', identifier: 'test@test.com', password: 'test' });
55
+ expect(result).toEqual({ ok: false, error: 'ACCOUNT_NOT_VERIFIED', violatedPolicies: [] });
56
+ });
57
+
58
+ it('should be possible to authenticate with not verified account if unckeched in settings', async () => {
59
+ // Given
60
+ const authService = createAuthServiceMock({
61
+ authenticate: vi.fn().mockResolvedValue({ ok: true, user: notVerifiedUser }),
62
+ });
63
+ const authPreferencesService = createAuthPreferencesServiceMock({
64
+ getAuthPreferences: vi.fn().mockResolvedValue({ allowLoginWithNotVerifiedAccount: true }),
65
+ });
66
+ // When
67
+ const loginUser = authenticateUser(authService, authPreferencesService);
68
+ // Then
69
+ const result = await loginUser({ type: 'password', identifier: 'test@test.com', password: 'test' });
70
+ expect(result.ok).toEqual(true);
24
71
  });
25
- });
72
+ });
@@ -0,0 +1,89 @@
1
+ import { AuthMethod, AuthResultFailure } from "@application/ports/auth-service.port.js";
2
+ import { registerUser } from "@application/use-cases/register-user.js";
3
+ import { createAuthServiceMock } from "@tests/application/ports/auth-service.port.mock.js";
4
+ import { createPreRegisterPolicyMock } from "@tests/application/ports/pre-register-policy.port.mock.js";
5
+ import { describe, expect, it } from "vitest";
6
+
7
+ describe('RegisterUser', () => {
8
+ it('should register a user', async () => {
9
+ // Given
10
+ const authService = createAuthServiceMock();
11
+ const policy = createPreRegisterPolicyMock();
12
+ const signUpUser = registerUser(authService, [policy]);
13
+ // When
14
+ const result = await signUpUser(
15
+ { type: 'password', identifier: 'test@test.com', password: 'test' },
16
+ );
17
+ // Then
18
+ expect(result.ok).toBe(true);
19
+ });
20
+
21
+ it('should fail to register a user if a pre-register policy is violated', async () => {
22
+ // Given
23
+ const authService = createAuthServiceMock();
24
+ const policy = createPreRegisterPolicyMock({
25
+ code: 'POLICY_ERROR',
26
+ check: vi.fn().mockResolvedValue(false),
27
+ isActive: vi.fn().mockResolvedValue(true),
28
+ });
29
+ const method: AuthMethod = { type: 'password', identifier: 'test@test.com', password: 'test' };
30
+ const signUpUser = registerUser(authService, [policy]);
31
+ // When
32
+ const result = await signUpUser(method);
33
+ // Then
34
+ expect(policy.check).toHaveBeenCalledWith(method);
35
+ expect(authService.register).not.toHaveBeenCalled();
36
+ expect(result).toEqual({
37
+ ok: false,
38
+ error: 'PRE_REGISTER_POLICY_VIOLATED',
39
+ violatedPolicies: ['POLICY_ERROR']
40
+ } as AuthResultFailure);
41
+ });
42
+
43
+ it('should fail to register a user if active pre-register policies are violated', async () => {
44
+ // Given
45
+ const authService = createAuthServiceMock();
46
+ const policy1 = createPreRegisterPolicyMock({
47
+ code: 'POLICY_1_ERROR',
48
+ check: vi.fn().mockResolvedValue(false),
49
+ isActive: vi.fn().mockResolvedValue(false),
50
+ });
51
+ const policy2 = createPreRegisterPolicyMock({
52
+ code: 'POLICY_2_ERROR',
53
+ check: vi.fn().mockResolvedValue(false),
54
+ isActive: vi.fn().mockResolvedValue(true),
55
+ });
56
+ const method: AuthMethod = { type: 'password', identifier: 'test@test.com', password: 'test' };
57
+ const signUpUser = registerUser(authService, [policy1, policy2]);
58
+ // When
59
+ const result = await signUpUser(method);
60
+ // Then
61
+ expect(policy1.isActive).toHaveBeenCalledWith(method);
62
+ expect(policy2.isActive).toHaveBeenCalledWith(method);
63
+ expect(policy1.check).not.toHaveBeenCalled();
64
+ expect(policy2.check).toHaveBeenCalledWith(method);
65
+ expect(authService.register).not.toHaveBeenCalled();
66
+ expect(result).toEqual({
67
+ ok: false,
68
+ error: 'PRE_REGISTER_POLICY_VIOLATED',
69
+ violatedPolicies: ['POLICY_2_ERROR']
70
+ } as AuthResultFailure);
71
+ });
72
+
73
+ it('should register a user if the pre-register policy is deactivated', async () => {
74
+ // Given
75
+ const authService = createAuthServiceMock();
76
+ const policy = createPreRegisterPolicyMock({
77
+ isActive: vi.fn().mockResolvedValue(false),
78
+ });
79
+ const method: AuthMethod = { type: 'password', identifier: 'test@test.com', password: 'test' };
80
+ const signUpUser = registerUser(authService, [policy]);
81
+ // When
82
+ const result = await signUpUser(method);
83
+ // Then
84
+ expect(policy.isActive).toHaveBeenCalledWith(method);
85
+ expect(policy.check).not.toHaveBeenCalled();
86
+ expect(authService.register).toHaveBeenCalledWith(method);
87
+ expect(result).toEqual({ ok: true, user: { id: '1', displayName: 'test@test.com', status: 'active', isVerified: true } });
88
+ });
89
+ });
@@ -0,0 +1,5 @@
1
+ import { UserAccount } from "@domain/user-account.js";
2
+
3
+ export const activeUser: UserAccount = { id: '1', displayName: 'test@test.com', status: 'active', isVerified: true };
4
+ export const inactiveUser: UserAccount = { id: '1', displayName: 'test@test.com', status: 'disabled', isVerified: true };
5
+ export const notVerifiedUser: UserAccount = { id: '1', displayName: 'test@test.com', status: 'active', isVerified: false };
package/tsconfig.lib.json CHANGED
@@ -7,6 +7,8 @@
7
7
  "paths": {
8
8
  "@domain/*": ["src/domain/*"],
9
9
  "@application/*": ["src/application/*"],
10
+ "@infrastructure/*": ["src/infrastructure/*"],
11
+ "@root/*": ["src/*"],
10
12
  },
11
13
  "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
12
14
  "emitDeclarationOnly": true,
@@ -4,7 +4,9 @@
4
4
  "baseUrl": ".",
5
5
  "paths": {
6
6
  "@domain/*": ["src/domain/*"],
7
- "@application/*": ["src/application/*"]
7
+ "@application/*": ["src/application/*"],
8
+ "@infrastructure/*": ["src/infrastructure/*"],
9
+ "@tests/*": ["tests/*"]
8
10
  },
9
11
  "outDir": "./out-tsc/vitest",
10
12
  "types": [
@@ -30,6 +32,16 @@
30
32
  "tests/**/*.test.jsx",
31
33
  "tests/**/*.spec.jsx",
32
34
  "tests/**/*.d.ts",
35
+ "tests/**/*.mock.ts",
36
+ "tests/**/*.mock.tsx",
37
+ "tests/**/*.mock.js",
38
+ "tests/**/*.mock.jsx",
39
+ "tests/**/*.mock.d.ts",
40
+ "tests/**/*.mock.json",
41
+ "tests/**/*.mock.yaml",
42
+ "tests/**/*.mock.yml",
43
+ "tests/**/*.mock.xml",
44
+ "tests/**/*.data.ts",
33
45
  ],
34
46
  "references": [
35
47
  {
package/vite.config.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  /// <reference types='vitest' />
2
+ import * as path from 'path';
2
3
  import { defineConfig } from 'vite';
3
4
  import dts from 'vite-plugin-dts';
4
- import * as path from 'path';
5
5
  import tsconfigPaths from 'vite-tsconfig-paths';
6
6
 
7
7
  export default defineConfig(() => ({
@@ -18,6 +18,9 @@ export default defineConfig(() => ({
18
18
  alias: {
19
19
  '@domain': path.resolve(__dirname, 'src/domain'),
20
20
  '@application': path.resolve(__dirname, 'src/application'),
21
+ '@infrastructure': path.resolve(__dirname, 'src/infrastructure'),
22
+ '@root': path.resolve(__dirname, 'src'),
23
+ '@tests': path.resolve(__dirname, 'tests'),
21
24
  },
22
25
  },
23
26
  // Uncomment this if you are using workers.
@@ -1,16 +0,0 @@
1
- /**
2
- * Domaine: session utilisateur Sekoliko.
3
- * Ne contient pas de détails d’implémentation (cookies, tokens, etc.).
4
- */
5
- export interface Session {
6
- id: string;
7
- userId: string;
8
- createdAt: Date;
9
- lastActivityAt: Date;
10
- expiresAt: Date;
11
- }
12
-
13
- export const isSessionActive = (session: Session, now: Date = new Date()): boolean =>
14
- now < session.expiresAt;
15
-
16
-