@venturialstd/organization 0.0.1

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.
Files changed (50) hide show
  1. package/README.md +678 -0
  2. package/dist/constants/organization.constant.d.ts +12 -0
  3. package/dist/constants/organization.constant.d.ts.map +1 -0
  4. package/dist/constants/organization.constant.js +17 -0
  5. package/dist/constants/organization.constant.js.map +1 -0
  6. package/dist/constants/organization.settings.constant.d.ts +11 -0
  7. package/dist/constants/organization.settings.constant.d.ts.map +1 -0
  8. package/dist/constants/organization.settings.constant.js +14 -0
  9. package/dist/constants/organization.settings.constant.js.map +1 -0
  10. package/dist/decorators/organization.decorator.d.ts +4 -0
  11. package/dist/decorators/organization.decorator.d.ts.map +1 -0
  12. package/dist/decorators/organization.decorator.js +22 -0
  13. package/dist/decorators/organization.decorator.js.map +1 -0
  14. package/dist/decorators/roles.decorator.d.ts +3 -0
  15. package/dist/decorators/roles.decorator.d.ts.map +1 -0
  16. package/dist/decorators/roles.decorator.js +7 -0
  17. package/dist/decorators/roles.decorator.js.map +1 -0
  18. package/dist/entities/organization-user.entity.d.ts +16 -0
  19. package/dist/entities/organization-user.entity.d.ts.map +1 -0
  20. package/dist/entities/organization-user.entity.js +120 -0
  21. package/dist/entities/organization-user.entity.js.map +1 -0
  22. package/dist/entities/organization.entity.d.ts +13 -0
  23. package/dist/entities/organization.entity.d.ts.map +1 -0
  24. package/dist/entities/organization.entity.js +94 -0
  25. package/dist/entities/organization.entity.js.map +1 -0
  26. package/dist/guards/organization.guard.d.ts +16 -0
  27. package/dist/guards/organization.guard.d.ts.map +1 -0
  28. package/dist/guards/organization.guard.js +90 -0
  29. package/dist/guards/organization.guard.js.map +1 -0
  30. package/dist/index.d.ts +12 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +28 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/organization.module.d.ts +3 -0
  35. package/dist/organization.module.d.ts.map +1 -0
  36. package/dist/organization.module.js +28 -0
  37. package/dist/organization.module.js.map +1 -0
  38. package/dist/services/organization-user.service.d.ts +30 -0
  39. package/dist/services/organization-user.service.d.ts.map +1 -0
  40. package/dist/services/organization-user.service.js +246 -0
  41. package/dist/services/organization-user.service.js.map +1 -0
  42. package/dist/services/organization.service.d.ts +18 -0
  43. package/dist/services/organization.service.d.ts.map +1 -0
  44. package/dist/services/organization.service.js +117 -0
  45. package/dist/services/organization.service.js.map +1 -0
  46. package/dist/settings/organization.settings.d.ts +3 -0
  47. package/dist/settings/organization.settings.d.ts.map +1 -0
  48. package/dist/settings/organization.settings.js +79 -0
  49. package/dist/settings/organization.settings.js.map +1 -0
  50. package/package.json +42 -0
package/README.md ADDED
@@ -0,0 +1,678 @@
1
+ # @venturialstd/organization
2
+
3
+ Organization Management Module for Venturial - A NestJS module for managing organizations and organization members with role-based access control.
4
+
5
+ ## ๐Ÿ“‹ Table of Contents
6
+
7
+ - [Features](#features)
8
+ - [Installation](#installation)
9
+ - [Module Structure](#module-structure)
10
+ - [Quick Start](#quick-start)
11
+ - [Configuration](#configuration)
12
+ - [Entities](#entities)
13
+ - [API Reference](#api-reference)
14
+ - [Enums & Constants](#enums--constants)
15
+ - [Guards & Decorators](#guards--decorators)
16
+ - [Test Server](#test-server)
17
+ - [NPM Scripts](#npm-scripts)
18
+ - [Usage Examples](#usage-examples)
19
+
20
+ ---
21
+
22
+ ## โœจ Features
23
+
24
+ - ๐Ÿข **Organization Management**: Complete CRUD operations
25
+ - ๐Ÿ‘ฅ **Member Management**: Add, invite, remove organization members
26
+ - ๐Ÿ” **Role-Based Access**: Owner, Admin, Member, Viewer roles
27
+ - โš™๏ธ **Settings System**: Configurable organization settings
28
+ - ๐Ÿ›ก๏ธ **Guards & Decorators**: Request-level access control
29
+ - ๐Ÿ”„ **TypeORM Integration**: Full database support with migrations
30
+ - ๐Ÿ“ฆ **Fully Typed**: Complete TypeScript support
31
+ - ๐Ÿงช **Test Infrastructure**: Standalone test server on port 3002
32
+
33
+ ---
34
+
35
+ ## ๐Ÿ“ฆ Installation
36
+
37
+ ```bash
38
+ npm install @venturialstd/organization
39
+ ```
40
+
41
+ ### Peer Dependencies
42
+
43
+ ```json
44
+ {
45
+ "@nestjs/common": "^11.0.11",
46
+ "@nestjs/core": "^11.0.5",
47
+ "@nestjs/typeorm": "^10.0.0",
48
+ "@venturialstd/core": "^1.0.16",
49
+ "class-transformer": "^0.5.1",
50
+ "class-validator": "^0.14.1",
51
+ "typeorm": "^0.3.20"
52
+ }
53
+ ```
54
+
55
+ ---
56
+
57
+ ## ๐Ÿ“ Module Structure
58
+
59
+ ```
60
+ src/organization/
61
+ โ”œโ”€โ”€ package.json # Module configuration
62
+ โ”œโ”€โ”€ tsconfig.json # TypeScript configuration
63
+ โ”œโ”€โ”€ README.md # This file
64
+ โ”œโ”€โ”€ .npmignore # NPM publish exclusions
65
+ โ”œโ”€โ”€ src/ # Source code
66
+ โ”‚ โ”œโ”€โ”€ constants/
67
+ โ”‚ โ”‚ โ”œโ”€โ”€ organization.constant.ts # Enums (roles, status)
68
+ โ”‚ โ”‚ โ””โ”€โ”€ organization.settings.constant.ts # Settings keys
69
+ โ”‚ โ”œโ”€โ”€ decorators/
70
+ โ”‚ โ”‚ โ”œโ”€โ”€ organization.decorator.ts # @OrganizationId(), @UserId(), etc.
71
+ โ”‚ โ”‚ โ””โ”€โ”€ roles.decorator.ts # @Roles() decorator
72
+ โ”‚ โ”œโ”€โ”€ entities/
73
+ โ”‚ โ”‚ โ”œโ”€โ”€ organization.entity.ts # Organization entity
74
+ โ”‚ โ”‚ โ””โ”€โ”€ organization-user.entity.ts # OrganizationUser entity
75
+ โ”‚ โ”œโ”€โ”€ guards/
76
+ โ”‚ โ”‚ โ””โ”€โ”€ organization.guard.ts # OrganizationGuard, OrganizationRoleGuard
77
+ โ”‚ โ”œโ”€โ”€ services/
78
+ โ”‚ โ”‚ โ”œโ”€โ”€ organization.service.ts # Organization CRUD service
79
+ โ”‚ โ”‚ โ””โ”€โ”€ organization-user.service.ts # User-Organization service
80
+ โ”‚ โ”œโ”€โ”€ settings/
81
+ โ”‚ โ”‚ โ””โ”€โ”€ organization.settings.ts # Module settings definition
82
+ โ”‚ โ”œโ”€โ”€ organization.module.ts # NestJS module
83
+ โ”‚ โ””โ”€โ”€ index.ts # Public exports
84
+ โ””โ”€โ”€ test/ # Test infrastructure
85
+ โ”œโ”€โ”€ controllers/
86
+ โ”‚ โ”œโ”€โ”€ organization-test.controller.ts
87
+ โ”‚ โ””โ”€โ”€ organization-user-test.controller.ts
88
+ โ”œโ”€โ”€ migrations/ # Database migrations
89
+ โ”œโ”€โ”€ .env.example # Environment template
90
+ โ”œโ”€โ”€ data-source.ts # TypeORM DataSource
91
+ โ”œโ”€โ”€ test-app.module.ts # Test app module
92
+ โ””โ”€โ”€ main.ts # Test server bootstrap
93
+ ```
94
+
95
+ ---
96
+
97
+ ## ๐Ÿš€ Quick Start
98
+
99
+ ### 1. Import the Module
100
+
101
+ ```typescript
102
+ import { Module } from '@nestjs/common';
103
+ import { OrganizationModule } from '@venturialstd/organization';
104
+
105
+ @Module({
106
+ imports: [OrganizationModule],
107
+ })
108
+ export class AppModule {}
109
+ ```
110
+
111
+ ### 2. Use the Services
112
+
113
+ ```typescript
114
+ import { Injectable } from '@nestjs/common';
115
+ import { OrganizationService, OrganizationUserService } from '@venturialstd/organization';
116
+
117
+ @Injectable()
118
+ export class YourService {
119
+ constructor(
120
+ private readonly organizationService: OrganizationService,
121
+ private readonly organizationUserService: OrganizationUserService,
122
+ ) {}
123
+
124
+ async createOrganization() {
125
+ const organization = await this.organizationService.createOrganization(
126
+ 'My Organization',
127
+ 'my-org',
128
+ 'example.com',
129
+ 'Organization description',
130
+ 'user-id-123'
131
+ );
132
+
133
+ return organization;
134
+ }
135
+
136
+ async addMember() {
137
+ return this.organizationUserService.addUserToOrganization(
138
+ 'org-id',
139
+ 'user-id',
140
+ ORGANIZATION_USER_ROLE.MEMBER
141
+ );
142
+ }
143
+ }
144
+ ```
145
+
146
+ ---
147
+
148
+ ## โš™๏ธ Configuration
149
+
150
+ ### Development Setup
151
+
152
+ ```bash
153
+ # Navigate to module directory
154
+ cd src/organization
155
+
156
+ # Install dependencies
157
+ npm install --legacy-peer-deps
158
+
159
+ # Set up environment
160
+ cp test/.env.example test/.env
161
+ # Edit test/.env with your database credentials
162
+
163
+ # Generate migration
164
+ npm run migration:generate --name=InitialSchema
165
+
166
+ # Run migrations
167
+ npm run migration:run
168
+
169
+ # Start test server
170
+ npm run test:dev
171
+ ```
172
+
173
+ ### Environment Variables (test/.env)
174
+
175
+ ```bash
176
+ APP_PORT=3002
177
+ DB_HOST=localhost
178
+ DB_PORT=5433
179
+ DB_NAME=organization_test
180
+ DB_USER=root
181
+ DB_PASS=example
182
+ ```
183
+
184
+ ---
185
+
186
+ ## ๐Ÿ—„๏ธ Entities
187
+
188
+ ### Organization
189
+
190
+ ```typescript
191
+ @Entity('organization')
192
+ export class Organization {
193
+ id: string; // UUID primary key
194
+ name: string; // Unique organization name
195
+ slug: string; // Unique URL-friendly slug
196
+ domain?: string; // Optional custom domain
197
+ description?: string; // Organization description
198
+ isActive: boolean; // Active/inactive status
199
+ settings: Record<string, unknown>; // JSONB settings
200
+ ownerId?: string; // Owner user ID
201
+ createdAt: Date; // Creation timestamp
202
+ updatedAt: Date; // Update timestamp
203
+ }
204
+ ```
205
+
206
+ **Key Features:**
207
+ - Unique `name` and `slug` constraints
208
+ - JSONB `settings` for flexible configuration
209
+ - Soft activation with `isActive` flag
210
+ - Owner tracking via `ownerId`
211
+
212
+ ### OrganizationUser
213
+
214
+ ```typescript
215
+ @Entity('organization_user')
216
+ export class OrganizationUser {
217
+ id: string; // UUID primary key
218
+ organizationId: string; // Organization reference (indexed)
219
+ userId: string; // User reference (indexed)
220
+ role: ORGANIZATION_USER_ROLE; // User role in organization
221
+ status: ORGANIZATION_USER_STATUS; // Member status
222
+ isPrimary: boolean; // Primary owner flag
223
+ invitedBy?: string; // Inviter user ID
224
+ invitedAt?: Date; // Invitation timestamp
225
+ joinedAt?: Date; // Join timestamp
226
+ permissions: Record<string, unknown>; // JSONB custom permissions
227
+ createdAt: Date; // Creation timestamp
228
+ updatedAt: Date; // Update timestamp
229
+ }
230
+ ```
231
+
232
+ **Key Features:**
233
+ - Unique index on `(organizationId, userId)`
234
+ - Separate indexes on `organizationId` and `userId`
235
+ - Invitation system support
236
+ - Primary owner designation
237
+ - Custom permissions via JSONB
238
+
239
+ ---
240
+
241
+ ## ๐Ÿ“– API Reference
242
+
243
+ ### OrganizationService
244
+
245
+ #### Create Organization
246
+ ```typescript
247
+ createOrganization(
248
+ name: string,
249
+ slug: string,
250
+ domain?: string,
251
+ description?: string,
252
+ ownerId?: string
253
+ ): Promise<Organization>
254
+ ```
255
+
256
+ #### Find Methods
257
+ ```typescript
258
+ getOrganizationBySlug(slug: string): Promise<Organization>
259
+ getOrganizationByDomain(domain: string): Promise<Organization>
260
+ getActiveOrganizations(): Promise<Organization[]>
261
+ getOrganizationsByOwner(ownerId: string): Promise<Organization[]>
262
+ ```
263
+
264
+ #### Update Methods
265
+ ```typescript
266
+ updateOrganizationSettings(
267
+ organizationId: string,
268
+ settings: Record<string, unknown>
269
+ ): Promise<Organization>
270
+
271
+ setOrganizationStatus(
272
+ organizationId: string,
273
+ isActive: boolean
274
+ ): Promise<Organization>
275
+ ```
276
+
277
+ ### OrganizationUserService
278
+
279
+ #### Member Management
280
+ ```typescript
281
+ addUserToOrganization(
282
+ organizationId: string,
283
+ userId: string,
284
+ role?: ORGANIZATION_USER_ROLE,
285
+ invitedBy?: string
286
+ ): Promise<OrganizationUser>
287
+
288
+ inviteUserToOrganization(
289
+ organizationId: string,
290
+ userId: string,
291
+ role: ORGANIZATION_USER_ROLE,
292
+ invitedBy: string
293
+ ): Promise<OrganizationUser>
294
+
295
+ acceptInvitation(
296
+ organizationId: string,
297
+ userId: string
298
+ ): Promise<OrganizationUser>
299
+
300
+ removeUserFromOrganization(
301
+ organizationId: string,
302
+ userId: string
303
+ ): Promise<void>
304
+ ```
305
+
306
+ #### Role Management
307
+ ```typescript
308
+ updateUserRole(
309
+ organizationId: string,
310
+ userId: string,
311
+ newRole: ORGANIZATION_USER_ROLE
312
+ ): Promise<OrganizationUser>
313
+
314
+ setPrimaryOwner(
315
+ organizationId: string,
316
+ userId: string
317
+ ): Promise<OrganizationUser>
318
+
319
+ transferOwnership(
320
+ organizationId: string,
321
+ fromUserId: string,
322
+ toUserId: string
323
+ ): Promise<void>
324
+ ```
325
+
326
+ #### Query Methods
327
+ ```typescript
328
+ getUserOrganizations(userId: string): Promise<OrganizationUser[]>
329
+ getOrganizationUsers(organizationId: string): Promise<OrganizationUser[]>
330
+ getActiveOrganizationUsers(organizationId: string): Promise<OrganizationUser[]>
331
+ getUserInvitations(userId: string): Promise<OrganizationUser[]>
332
+ hasAccess(organizationId: string, userId: string): Promise<boolean>
333
+ getUserRole(organizationId: string, userId: string): Promise<ORGANIZATION_USER_ROLE | null>
334
+ ```
335
+
336
+ #### Status Management
337
+ ```typescript
338
+ suspendUser(organizationId: string, userId: string): Promise<OrganizationUser>
339
+ reactivateUser(organizationId: string, userId: string): Promise<OrganizationUser>
340
+ ```
341
+
342
+ ---
343
+
344
+ ## ๐ŸŽญ Enums & Constants
345
+
346
+ ### ORGANIZATION_USER_ROLE
347
+
348
+ ```typescript
349
+ enum ORGANIZATION_USER_ROLE {
350
+ OWNER = 'owner', // Full control over organization
351
+ ADMIN = 'admin', // Administrative access
352
+ MEMBER = 'member', // Standard member access
353
+ VIEWER = 'viewer' // Read-only access
354
+ }
355
+ ```
356
+
357
+ ### ORGANIZATION_USER_STATUS
358
+
359
+ ```typescript
360
+ enum ORGANIZATION_USER_STATUS {
361
+ ACTIVE = 'active', // Active member
362
+ INVITED = 'invited', // Pending invitation
363
+ SUSPENDED = 'suspended' // Suspended member
364
+ }
365
+ ```
366
+
367
+ ### Settings Keys
368
+
369
+ ```typescript
370
+ ORGANIZATION_SETTING_KEYS = {
371
+ GENERAL_MAX_ORGANIZATIONS: 'organization.general.max_organizations',
372
+ GENERAL_MAX_MEMBERS: 'organization.general.max_members',
373
+ FEATURES_CUSTOM_DOMAIN: 'organization.features.custom_domain',
374
+ FEATURES_API_ACCESS: 'organization.features.api_access',
375
+ FEATURES_SSO: 'organization.features.sso',
376
+ LIMITS_STORAGE: 'organization.limits.storage_gb',
377
+ LIMITS_BANDWIDTH: 'organization.limits.bandwidth_gb',
378
+ LIMITS_PROJECTS: 'organization.limits.projects',
379
+ }
380
+ ```
381
+
382
+ ---
383
+
384
+ ## ๐Ÿ›ก๏ธ Guards & Decorators
385
+
386
+ ### Decorators
387
+
388
+ #### @OrganizationId()
389
+ Extract organization ID from request:
390
+ ```typescript
391
+ @Get()
392
+ async getData(@OrganizationId() organizationId: string) {
393
+ return this.service.getData(organizationId);
394
+ }
395
+ ```
396
+
397
+ #### @UserId()
398
+ Extract user ID from request:
399
+ ```typescript
400
+ @Get()
401
+ async getData(@UserId() userId: string) {
402
+ return this.service.getUserData(userId);
403
+ }
404
+ ```
405
+
406
+ #### @OrganizationContext()
407
+ Extract full context:
408
+ ```typescript
409
+ @Get()
410
+ async getData(@OrganizationContext() context) {
411
+ // context = { organizationId, userId, role, user }
412
+ return this.service.getData(context);
413
+ }
414
+ ```
415
+
416
+ #### @Roles()
417
+ Specify required roles:
418
+ ```typescript
419
+ @Roles(ORGANIZATION_USER_ROLE.OWNER, ORGANIZATION_USER_ROLE.ADMIN)
420
+ @UseGuards(OrganizationGuard, OrganizationRoleGuard)
421
+ @Delete(':id')
422
+ async delete() { ... }
423
+ ```
424
+
425
+ ### Guards
426
+
427
+ #### OrganizationGuard
428
+ Ensures user has access to the organization:
429
+ ```typescript
430
+ @UseGuards(OrganizationGuard)
431
+ @Get()
432
+ async getData(@OrganizationId() organizationId: string) {
433
+ return this.service.getData(organizationId);
434
+ }
435
+ ```
436
+
437
+ #### OrganizationRoleGuard
438
+ Enforces role-based access control:
439
+ ```typescript
440
+ @Roles(ORGANIZATION_USER_ROLE.OWNER, ORGANIZATION_USER_ROLE.ADMIN)
441
+ @UseGuards(OrganizationGuard, OrganizationRoleGuard)
442
+ @Delete(':id')
443
+ async delete() { ... }
444
+ ```
445
+
446
+ ---
447
+
448
+ ## ๐Ÿงช Test Server
449
+
450
+ Start the test server on port **3002**:
451
+
452
+ ```bash
453
+ npm run test:dev
454
+ ```
455
+
456
+ ### Available Endpoints
457
+
458
+ #### Organization Management
459
+ ```
460
+ POST /organizations - Create organization
461
+ GET /organizations - Get all organizations
462
+ GET /organizations/active - Get active organizations
463
+ GET /organizations/owner/:ownerId - Get by owner
464
+ GET /organizations/slug/:slug - Get by slug
465
+ GET /organizations/domain/:domain - Get by domain
466
+ GET /organizations/:id - Get by ID
467
+ PUT /organizations/:id/settings - Update settings
468
+ PUT /organizations/:id/status - Update status
469
+ DELETE /organizations/:id - Delete organization
470
+ ```
471
+
472
+ #### User-Organization Management
473
+ ```
474
+ POST /organization-users/add - Add user
475
+ POST /organization-users/invite - Invite user
476
+ POST /organization-users/accept-invitation - Accept invite
477
+ GET /organization-users/organization/:organizationId - Get members
478
+ GET /organization-users/organization/:organizationId/active - Get active members
479
+ GET /organization-users/user/:userId - Get user's organizations
480
+ GET /organization-users/user/:userId/invitations - Get invitations
481
+ GET /organization-users/check-access/:orgId/:userId - Check access
482
+ GET /organization-users/role/:orgId/:userId - Get user role
483
+ PUT /organization-users/role - Update role
484
+ PUT /organization-users/primary-owner - Set primary owner
485
+ POST /organization-users/transfer-ownership - Transfer ownership
486
+ PUT /organization-users/suspend - Suspend user
487
+ PUT /organization-users/reactivate - Reactivate user
488
+ DELETE /organization-users/remove - Remove user
489
+ ```
490
+
491
+ ---
492
+
493
+ ## ๐Ÿ“ NPM Scripts
494
+
495
+ ```bash
496
+ # Build
497
+ npm run build # Build TypeScript to dist/
498
+ npm run prepublishOnly # Auto-build before publish
499
+
500
+ # Publishing
501
+ npm run release:patch # Build, bump version, publish
502
+
503
+ # Development
504
+ npm run test:dev # Start test server
505
+ npm run test:watch # Watch mode for development
506
+
507
+ # Migrations
508
+ npm run migration:generate --name=Name # Generate migration
509
+ npm run migration:run # Run pending migrations
510
+ npm run migration:revert # Revert last migration
511
+ ```
512
+
513
+ ---
514
+
515
+ ## ๐Ÿ’ก Usage Examples
516
+
517
+ ### Basic Organization Creation
518
+
519
+ ```typescript
520
+ import { OrganizationService } from '@venturialstd/organization';
521
+
522
+ @Injectable()
523
+ export class MyService {
524
+ constructor(private orgService: OrganizationService) {}
525
+
526
+ async createOrg() {
527
+ return this.orgService.createOrganization(
528
+ 'Acme Corp',
529
+ 'acme-corp',
530
+ 'acme.com',
531
+ 'A leading company',
532
+ 'owner-user-id-123'
533
+ );
534
+ }
535
+ }
536
+ ```
537
+
538
+ ### Adding Members with Roles
539
+
540
+ ```typescript
541
+ import {
542
+ OrganizationUserService,
543
+ ORGANIZATION_USER_ROLE
544
+ } from '@venturialstd/organization';
545
+
546
+ @Injectable()
547
+ export class MemberService {
548
+ constructor(private orgUserService: OrganizationUserService) {}
549
+
550
+ async addAdmin(orgId: string, userId: string) {
551
+ return this.orgUserService.addUserToOrganization(
552
+ orgId,
553
+ userId,
554
+ ORGANIZATION_USER_ROLE.ADMIN,
555
+ 'inviter-user-id'
556
+ );
557
+ }
558
+ }
559
+ ```
560
+
561
+ ### Protected Endpoints
562
+
563
+ ```typescript
564
+ import {
565
+ Controller,
566
+ Get,
567
+ UseGuards
568
+ } from '@nestjs/common';
569
+ import {
570
+ OrganizationGuard,
571
+ OrganizationRoleGuard,
572
+ OrganizationId,
573
+ Roles,
574
+ ORGANIZATION_USER_ROLE
575
+ } from '@venturialstd/organization';
576
+
577
+ @Controller('projects')
578
+ @UseGuards(OrganizationGuard)
579
+ export class ProjectController {
580
+
581
+ // Any member can view
582
+ @Get()
583
+ async list(@OrganizationId() orgId: string) {
584
+ return this.service.getProjects(orgId);
585
+ }
586
+
587
+ // Only owners and admins can delete
588
+ @Delete(':id')
589
+ @UseGuards(OrganizationRoleGuard)
590
+ @Roles(ORGANIZATION_USER_ROLE.OWNER, ORGANIZATION_USER_ROLE.ADMIN)
591
+ async delete(@OrganizationId() orgId: string, @Param('id') id: string) {
592
+ return this.service.deleteProject(orgId, id);
593
+ }
594
+ }
595
+ ```
596
+
597
+ ### Invitation Flow
598
+
599
+ ```typescript
600
+ @Injectable()
601
+ export class InvitationService {
602
+ constructor(private orgUserService: OrganizationUserService) {}
603
+
604
+ // Step 1: Send invitation
605
+ async inviteMember(orgId: string, email: string, inviterId: string) {
606
+ const userId = await this.userService.findByEmail(email);
607
+
608
+ return this.orgUserService.inviteUserToOrganization(
609
+ orgId,
610
+ userId,
611
+ ORGANIZATION_USER_ROLE.MEMBER,
612
+ inviterId
613
+ );
614
+ }
615
+
616
+ // Step 2: Get user's pending invitations
617
+ async getPendingInvites(userId: string) {
618
+ return this.orgUserService.getUserInvitations(userId);
619
+ }
620
+
621
+ // Step 3: Accept invitation
622
+ async acceptInvite(orgId: string, userId: string) {
623
+ return this.orgUserService.acceptInvitation(orgId, userId);
624
+ }
625
+ }
626
+ ```
627
+
628
+ ### Ownership Transfer
629
+
630
+ ```typescript
631
+ @Injectable()
632
+ export class OwnershipService {
633
+ constructor(private orgUserService: OrganizationUserService) {}
634
+
635
+ async transferOwnership(
636
+ orgId: string,
637
+ currentOwnerId: string,
638
+ newOwnerId: string
639
+ ) {
640
+ // Verify current owner
641
+ const isPrimaryOwner = await this.orgUserService
642
+ .getUserRole(orgId, currentOwnerId);
643
+
644
+ if (isPrimaryOwner !== ORGANIZATION_USER_ROLE.OWNER) {
645
+ throw new ForbiddenException('Only owner can transfer');
646
+ }
647
+
648
+ // Transfer
649
+ await this.orgUserService.transferOwnership(
650
+ orgId,
651
+ currentOwnerId,
652
+ newOwnerId
653
+ );
654
+ }
655
+ }
656
+ ```
657
+
658
+ ---
659
+
660
+ ## ๐Ÿ“„ License
661
+
662
+ MIT
663
+
664
+ ---
665
+
666
+ ## ๐Ÿค Contributing
667
+
668
+ Contributions are welcome! Please feel free to submit a Pull Request.
669
+
670
+ ---
671
+
672
+ ## ๐Ÿ“ง Support
673
+
674
+ For issues and questions, please create an issue in the repository.
675
+
676
+ ---
677
+
678
+ **Built with โค๏ธ using NestJS and TypeORM**
@@ -0,0 +1,12 @@
1
+ export declare enum ORGANIZATION_USER_ROLE {
2
+ OWNER = "owner",
3
+ ADMIN = "admin",
4
+ MEMBER = "member",
5
+ VIEWER = "viewer"
6
+ }
7
+ export declare enum ORGANIZATION_USER_STATUS {
8
+ ACTIVE = "active",
9
+ INVITED = "invited",
10
+ SUSPENDED = "suspended"
11
+ }
12
+ //# sourceMappingURL=organization.constant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization.constant.d.ts","sourceRoot":"","sources":["../../src/constants/organization.constant.ts"],"names":[],"mappings":"AAAA,oBAAY,sBAAsB;IAChC,KAAK,UAAU;IACf,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,oBAAY,wBAAwB;IAClC,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,SAAS,cAAc;CACxB"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ORGANIZATION_USER_STATUS = exports.ORGANIZATION_USER_ROLE = void 0;
4
+ var ORGANIZATION_USER_ROLE;
5
+ (function (ORGANIZATION_USER_ROLE) {
6
+ ORGANIZATION_USER_ROLE["OWNER"] = "owner";
7
+ ORGANIZATION_USER_ROLE["ADMIN"] = "admin";
8
+ ORGANIZATION_USER_ROLE["MEMBER"] = "member";
9
+ ORGANIZATION_USER_ROLE["VIEWER"] = "viewer";
10
+ })(ORGANIZATION_USER_ROLE || (exports.ORGANIZATION_USER_ROLE = ORGANIZATION_USER_ROLE = {}));
11
+ var ORGANIZATION_USER_STATUS;
12
+ (function (ORGANIZATION_USER_STATUS) {
13
+ ORGANIZATION_USER_STATUS["ACTIVE"] = "active";
14
+ ORGANIZATION_USER_STATUS["INVITED"] = "invited";
15
+ ORGANIZATION_USER_STATUS["SUSPENDED"] = "suspended";
16
+ })(ORGANIZATION_USER_STATUS || (exports.ORGANIZATION_USER_STATUS = ORGANIZATION_USER_STATUS = {}));
17
+ //# sourceMappingURL=organization.constant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization.constant.js","sourceRoot":"","sources":["../../src/constants/organization.constant.ts"],"names":[],"mappings":";;;AAAA,IAAY,sBAKX;AALD,WAAY,sBAAsB;IAChC,yCAAe,CAAA;IACf,yCAAe,CAAA;IACf,2CAAiB,CAAA;IACjB,2CAAiB,CAAA;AACnB,CAAC,EALW,sBAAsB,sCAAtB,sBAAsB,QAKjC;AAED,IAAY,wBAIX;AAJD,WAAY,wBAAwB;IAClC,6CAAiB,CAAA;IACjB,+CAAmB,CAAA;IACnB,mDAAuB,CAAA;AACzB,CAAC,EAJW,wBAAwB,wCAAxB,wBAAwB,QAInC"}