@open-kingdom/shared-backend-data-access-users 0.0.2-14 → 0.0.2-16
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/README.md +158 -4
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,7 +1,161 @@
|
|
|
1
|
-
# data-access-users
|
|
1
|
+
# `@open-kingdom/shared-backend-data-access-users`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A NestJS module providing `UsersService` for User entity persistence via Drizzle ORM + SQLite, including bcrypt password hashing, full CRUD operations, and automatic admin user seeding on startup.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Exports
|
|
8
|
+
|
|
9
|
+
| Export | Kind | Description |
|
|
10
|
+
| ----------------------------------------- | -------------------- | -------------------------------------------------------------------------- |
|
|
11
|
+
| `OpenKingdomDataAccessBackendUsersModule` | `class` | Standard NestJS module. Provides and exports `UsersService`. |
|
|
12
|
+
| `DataAccessBackendUsersModule` | `class` | Alias for `OpenKingdomDataAccessBackendUsersModule`. |
|
|
13
|
+
| `UsersService` | `class` | Injectable service for all user persistence operations. |
|
|
14
|
+
| `users` | `BetterSQLite3Table` | Drizzle table definition for the `users` table. |
|
|
15
|
+
| `UsersTableName` | `string` | The literal string `'users'`. Used when constructing typed schema objects. |
|
|
16
|
+
| `User` | `type` | TypeScript type inferred from `users.$inferSelect`. |
|
|
17
|
+
| `NewUser` | `type` | TypeScript type inferred from `users.$inferInsert`. |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Type Definitions
|
|
22
|
+
|
|
23
|
+
### `users` Table Schema
|
|
24
|
+
|
|
25
|
+
The `users` SQLite table has the following columns:
|
|
26
|
+
|
|
27
|
+
| Column | Type | Constraints | Description |
|
|
28
|
+
| ------------ | --------- | --------------------------- | --------------------------------------------------- |
|
|
29
|
+
| `id` | `integer` | Primary key, auto-increment | Unique user identifier |
|
|
30
|
+
| `first_name` | `text` | Nullable | User's first name |
|
|
31
|
+
| `last_name` | `text` | Nullable | User's last name |
|
|
32
|
+
| `email` | `text` | Not null, unique | User's email address |
|
|
33
|
+
| `password` | `text` | Not null | bcrypt-hashed password; never returned in plaintext |
|
|
34
|
+
|
|
35
|
+
### `User` Type
|
|
36
|
+
|
|
37
|
+
The `User` type is inferred from `users.$inferSelect` and has the following shape:
|
|
38
|
+
|
|
39
|
+
| Property | Type | Description |
|
|
40
|
+
| ----------- | ---------------- | -------------------------------------- |
|
|
41
|
+
| `id` | `number` | Auto-incremented primary key |
|
|
42
|
+
| `firstName` | `string \| null` | User's first name |
|
|
43
|
+
| `lastName` | `string \| null` | User's last name |
|
|
44
|
+
| `email` | `string` | Unique email address |
|
|
45
|
+
| `password` | `string` | bcrypt hash — never exposed to clients |
|
|
46
|
+
|
|
47
|
+
### `NewUser` Type
|
|
48
|
+
|
|
49
|
+
The `NewUser` type is inferred from `users.$inferInsert`. All fields are the same as `User` except `id` is optional (omitted for auto-increment inserts) and `firstName`/`lastName` are also optional. When passed to `UsersService.create()`, the `password` field is plaintext — the service hashes it before storage.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Module Registration
|
|
54
|
+
|
|
55
|
+
`OpenKingdomDataAccessBackendUsersModule` is a standard (non-dynamic) module. It does not call `register()` or `forRoot()`. Import it directly.
|
|
56
|
+
|
|
57
|
+
This module does **not** register the database connection itself. `DatabaseSetupModule.register()` must be registered globally (in the root `AppModule`) before this module is imported.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// some-feature.module.ts
|
|
61
|
+
import { Module } from '@nestjs/common';
|
|
62
|
+
import { OpenKingdomDataAccessBackendUsersModule } from '@open-kingdom/shared-backend-data-access-users';
|
|
63
|
+
|
|
64
|
+
@Module({
|
|
65
|
+
imports: [OpenKingdomDataAccessBackendUsersModule],
|
|
66
|
+
// UsersService is now available for injection in this module's providers
|
|
67
|
+
})
|
|
68
|
+
export class SomeFeatureModule {}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
When imported inside a dynamic module (e.g., `FeatureUserManagementModule`), the import is declared in the returned `DynamicModule` object's `imports` array — the same pattern applies.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Configuration
|
|
76
|
+
|
|
77
|
+
No configuration options. The service resolves its database dependency via the global `DB_TAG` token provided by `DatabaseSetupModule`.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## UsersService API
|
|
82
|
+
|
|
83
|
+
### Constructor Injection
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { UsersService } from '@open-kingdom/shared-backend-data-access-users';
|
|
87
|
+
|
|
88
|
+
@Injectable()
|
|
89
|
+
export class MyService {
|
|
90
|
+
constructor(private usersService: UsersService) {}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Methods
|
|
95
|
+
|
|
96
|
+
| Method | Parameters | Returns | Description |
|
|
97
|
+
| ------------ | ------------------------ | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `findOne` | `email: string` | `Promise<User \| undefined>` | Finds a user by email address. Returns `undefined` if not found. |
|
|
99
|
+
| `findById` | `id: number` | `Promise<User \| undefined>` | Finds a user by primary key. Returns `undefined` if not found. |
|
|
100
|
+
| `findAll` | — | `Promise<User[]>` | Returns all users. |
|
|
101
|
+
| `create` | `data: Omit<User, 'id'>` | `Promise<User>` | Inserts a new user. Hashes the plaintext password with bcrypt (12 salt rounds) before storage. |
|
|
102
|
+
| `delete` | `id: number` | `Promise<void>` | Deletes a user by primary key. |
|
|
103
|
+
| `ensureUser` | `data: Omit<User, 'id'>` | `Promise<User \| undefined>` | Inserts a user only if no user with that email already exists. Returns the existing user if found. Password is hashed before storage (same as `create`). |
|
|
104
|
+
|
|
105
|
+
### Lifecycle: `onModuleInit`
|
|
106
|
+
|
|
107
|
+
`UsersService` implements `OnModuleInit`. On application startup it calls `ensureUser` with a default admin account (`email: 'admin@admin.com'`, `password: 'admin'`, first and last name both `'Admin'`). This seeds a default admin user if the database is empty. **Change or remove this default credential in production.**
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Drizzle Schema Reference
|
|
112
|
+
|
|
113
|
+
The `users` table definition is exported from this package and must be included in the `schema` passed to `DatabaseSetupModule.register()` so that relational queries work correctly. The `UsersTableName` constant (`'users'`) can be used as a key when building typed schema composition objects.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { users, UsersTableName } from '@open-kingdom/shared-backend-data-access-users';
|
|
117
|
+
|
|
118
|
+
DatabaseSetupModule.register({
|
|
119
|
+
schema: { [UsersTableName]: users, ...otherTables },
|
|
120
|
+
filename: 'app.db',
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The `invitations` table in `feature-user-management` references `users.id` via a foreign key, so the `users` table must be present in the schema whenever that module is used.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Injecting UsersService in a Custom Module
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { Module } from '@nestjs/common';
|
|
132
|
+
import { Injectable } from '@nestjs/common';
|
|
133
|
+
import { OpenKingdomDataAccessBackendUsersModule, UsersService, User } from '@open-kingdom/shared-backend-data-access-users';
|
|
134
|
+
|
|
135
|
+
@Injectable()
|
|
136
|
+
export class ProfileService {
|
|
137
|
+
constructor(private usersService: UsersService) {}
|
|
138
|
+
|
|
139
|
+
async getProfile(id: number): Promise<Omit<User, 'password'> | undefined> {
|
|
140
|
+
const user = await this.usersService.findById(id);
|
|
141
|
+
if (!user) return undefined;
|
|
142
|
+
const { password: _, ...rest } = user;
|
|
143
|
+
return rest;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@Module({
|
|
148
|
+
imports: [OpenKingdomDataAccessBackendUsersModule],
|
|
149
|
+
providers: [ProfileService],
|
|
150
|
+
exports: [ProfileService],
|
|
151
|
+
})
|
|
152
|
+
export class ProfileModule {}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Testing
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
nx test @open-kingdom/shared-backend-data-access-users
|
|
161
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-kingdom/shared-backend-data-access-users",
|
|
3
|
-
"version": "0.0.2-
|
|
3
|
+
"version": "0.0.2-16",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
|
+
"README.md",
|
|
20
21
|
"dist",
|
|
21
22
|
"!**/*.tsbuildinfo"
|
|
22
23
|
],
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
32
|
"tslib": "^2.3.0",
|
|
32
|
-
"@open-kingdom/shared-poly-util-constants": "0.0.2-
|
|
33
|
+
"@open-kingdom/shared-poly-util-constants": "0.0.2-16",
|
|
33
34
|
"@nestjs/common": "^11.0.0",
|
|
34
35
|
"drizzle-orm": "^0.44.5",
|
|
35
36
|
"bcrypt": "^5.1.1"
|