@multitenantkit/domain 0.1.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.
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/organization-memberships/index.d.ts +3 -0
- package/dist/organization-memberships/index.d.ts.map +1 -0
- package/dist/organization-memberships/index.js +3 -0
- package/dist/organization-memberships/index.js.map +1 -0
- package/dist/organization-memberships/use-cases/accept-organization-invitation/AcceptOrganizationInvitation.d.ts +26 -0
- package/dist/organization-memberships/use-cases/accept-organization-invitation/AcceptOrganizationInvitation.d.ts.map +1 -0
- package/dist/organization-memberships/use-cases/accept-organization-invitation/AcceptOrganizationInvitation.js +85 -0
- package/dist/organization-memberships/use-cases/accept-organization-invitation/AcceptOrganizationInvitation.js.map +1 -0
- package/dist/organization-memberships/use-cases/add-organization-member/AddOrganizationMember.d.ts +19 -0
- package/dist/organization-memberships/use-cases/add-organization-member/AddOrganizationMember.d.ts.map +1 -0
- package/dist/organization-memberships/use-cases/add-organization-member/AddOrganizationMember.js +126 -0
- package/dist/organization-memberships/use-cases/add-organization-member/AddOrganizationMember.js.map +1 -0
- package/dist/organization-memberships/use-cases/index.d.ts +6 -0
- package/dist/organization-memberships/use-cases/index.d.ts.map +1 -0
- package/dist/organization-memberships/use-cases/index.js +8 -0
- package/dist/organization-memberships/use-cases/index.js.map +1 -0
- package/dist/organization-memberships/use-cases/leave-organization/LeaveOrganization.d.ts +15 -0
- package/dist/organization-memberships/use-cases/leave-organization/LeaveOrganization.d.ts.map +1 -0
- package/dist/organization-memberships/use-cases/leave-organization/LeaveOrganization.js +64 -0
- package/dist/organization-memberships/use-cases/leave-organization/LeaveOrganization.js.map +1 -0
- package/dist/organization-memberships/use-cases/remove-organization-member/RemoveOrganizationMember.d.ts +16 -0
- package/dist/organization-memberships/use-cases/remove-organization-member/RemoveOrganizationMember.d.ts.map +1 -0
- package/dist/organization-memberships/use-cases/remove-organization-member/RemoveOrganizationMember.js +87 -0
- package/dist/organization-memberships/use-cases/remove-organization-member/RemoveOrganizationMember.js.map +1 -0
- package/dist/organization-memberships/use-cases/update-organization-member-role/UpdateOrganizationMemberRole.d.ts +16 -0
- package/dist/organization-memberships/use-cases/update-organization-member-role/UpdateOrganizationMemberRole.d.ts.map +1 -0
- package/dist/organization-memberships/use-cases/update-organization-member-role/UpdateOrganizationMemberRole.js +85 -0
- package/dist/organization-memberships/use-cases/update-organization-member-role/UpdateOrganizationMemberRole.js.map +1 -0
- package/dist/organizations/index.d.ts +2 -0
- package/dist/organizations/index.d.ts.map +1 -0
- package/dist/organizations/index.js +3 -0
- package/dist/organizations/index.js.map +1 -0
- package/dist/organizations/use-cases/archive-organization/ArchiveOrganization.d.ts +38 -0
- package/dist/organizations/use-cases/archive-organization/ArchiveOrganization.d.ts.map +1 -0
- package/dist/organizations/use-cases/archive-organization/ArchiveOrganization.js +117 -0
- package/dist/organizations/use-cases/archive-organization/ArchiveOrganization.js.map +1 -0
- package/dist/organizations/use-cases/create-organization/CreateOrganization.d.ts +19 -0
- package/dist/organizations/use-cases/create-organization/CreateOrganization.d.ts.map +1 -0
- package/dist/organizations/use-cases/create-organization/CreateOrganization.js +96 -0
- package/dist/organizations/use-cases/create-organization/CreateOrganization.js.map +1 -0
- package/dist/organizations/use-cases/delete-organization/DeleteOrganization.d.ts +34 -0
- package/dist/organizations/use-cases/delete-organization/DeleteOrganization.d.ts.map +1 -0
- package/dist/organizations/use-cases/delete-organization/DeleteOrganization.js +103 -0
- package/dist/organizations/use-cases/delete-organization/DeleteOrganization.js.map +1 -0
- package/dist/organizations/use-cases/get-organization/GetOrganization.d.ts +18 -0
- package/dist/organizations/use-cases/get-organization/GetOrganization.d.ts.map +1 -0
- package/dist/organizations/use-cases/get-organization/GetOrganization.js +51 -0
- package/dist/organizations/use-cases/get-organization/GetOrganization.js.map +1 -0
- package/dist/organizations/use-cases/index.d.ts +9 -0
- package/dist/organizations/use-cases/index.d.ts.map +1 -0
- package/dist/organizations/use-cases/index.js +11 -0
- package/dist/organizations/use-cases/index.js.map +1 -0
- package/dist/organizations/use-cases/list-organization-members/ListOrganizationMembers.d.ts +46 -0
- package/dist/organizations/use-cases/list-organization-members/ListOrganizationMembers.d.ts.map +1 -0
- package/dist/organizations/use-cases/list-organization-members/ListOrganizationMembers.js +130 -0
- package/dist/organizations/use-cases/list-organization-members/ListOrganizationMembers.js.map +1 -0
- package/dist/organizations/use-cases/restore-organization/RestoreOrganization.d.ts +30 -0
- package/dist/organizations/use-cases/restore-organization/RestoreOrganization.d.ts.map +1 -0
- package/dist/organizations/use-cases/restore-organization/RestoreOrganization.js +98 -0
- package/dist/organizations/use-cases/restore-organization/RestoreOrganization.js.map +1 -0
- package/dist/organizations/use-cases/transfer-organization-ownership/TransferOrganizationOwnership.d.ts +30 -0
- package/dist/organizations/use-cases/transfer-organization-ownership/TransferOrganizationOwnership.d.ts.map +1 -0
- package/dist/organizations/use-cases/transfer-organization-ownership/TransferOrganizationOwnership.js +139 -0
- package/dist/organizations/use-cases/transfer-organization-ownership/TransferOrganizationOwnership.js.map +1 -0
- package/dist/organizations/use-cases/update-organization/UpdateOrganization.d.ts +22 -0
- package/dist/organizations/use-cases/update-organization/UpdateOrganization.d.ts.map +1 -0
- package/dist/organizations/use-cases/update-organization/UpdateOrganization.js +100 -0
- package/dist/organizations/use-cases/update-organization/UpdateOrganization.js.map +1 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/result/Result.d.ts +30 -0
- package/dist/shared/result/Result.d.ts.map +1 -0
- package/dist/shared/result/Result.js +69 -0
- package/dist/shared/result/Result.js.map +1 -0
- package/dist/shared/result/index.d.ts +4 -0
- package/dist/shared/result/index.d.ts.map +1 -0
- package/dist/shared/result/index.js +2 -0
- package/dist/shared/result/index.js.map +1 -0
- package/dist/shared/use-case/BaseUseCase.d.ts +164 -0
- package/dist/shared/use-case/BaseUseCase.d.ts.map +1 -0
- package/dist/shared/use-case/BaseUseCase.js +366 -0
- package/dist/shared/use-case/BaseUseCase.js.map +1 -0
- package/dist/shared/use-case/UseCaseHelpers.d.ts +43 -0
- package/dist/shared/use-case/UseCaseHelpers.d.ts.map +1 -0
- package/dist/shared/use-case/UseCaseHelpers.js +56 -0
- package/dist/shared/use-case/UseCaseHelpers.js.map +1 -0
- package/dist/shared/use-case/index.d.ts +3 -0
- package/dist/shared/use-case/index.d.ts.map +1 -0
- package/dist/shared/use-case/index.js +4 -0
- package/dist/shared/use-case/index.js.map +1 -0
- package/dist/users/index.d.ts +2 -0
- package/dist/users/index.d.ts.map +1 -0
- package/dist/users/index.js +3 -0
- package/dist/users/index.js.map +1 -0
- package/dist/users/use-cases/create-user/CreateUser.d.ts +21 -0
- package/dist/users/use-cases/create-user/CreateUser.d.ts.map +1 -0
- package/dist/users/use-cases/create-user/CreateUser.js +81 -0
- package/dist/users/use-cases/create-user/CreateUser.js.map +1 -0
- package/dist/users/use-cases/delete-user/DeleteUser.d.ts +35 -0
- package/dist/users/use-cases/delete-user/DeleteUser.d.ts.map +1 -0
- package/dist/users/use-cases/delete-user/DeleteUser.js +120 -0
- package/dist/users/use-cases/delete-user/DeleteUser.js.map +1 -0
- package/dist/users/use-cases/get-user/GetUser.d.ts +18 -0
- package/dist/users/use-cases/get-user/GetUser.d.ts.map +1 -0
- package/dist/users/use-cases/get-user/GetUser.js +29 -0
- package/dist/users/use-cases/get-user/GetUser.js.map +1 -0
- package/dist/users/use-cases/index.d.ts +6 -0
- package/dist/users/use-cases/index.d.ts.map +1 -0
- package/dist/users/use-cases/index.js +8 -0
- package/dist/users/use-cases/index.js.map +1 -0
- package/dist/users/use-cases/list-user-organizations/ListUserOrganizations.d.ts +20 -0
- package/dist/users/use-cases/list-user-organizations/ListUserOrganizations.d.ts.map +1 -0
- package/dist/users/use-cases/list-user-organizations/ListUserOrganizations.js +68 -0
- package/dist/users/use-cases/list-user-organizations/ListUserOrganizations.js.map +1 -0
- package/dist/users/use-cases/update-user/UpdateUser.d.ts +19 -0
- package/dist/users/use-cases/update-user/UpdateUser.d.ts.map +1 -0
- package/dist/users/use-cases/update-user/UpdateUser.js +73 -0
- package/dist/users/use-cases/update-user/UpdateUser.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Adapters } from '@multitenantkit/domain-contracts';
|
|
2
|
+
import type { IUpdateOrganization, UpdateOrganizationInput, UpdateOrganizationOutput } from '@multitenantkit/domain-contracts/organizations';
|
|
3
|
+
import type { OperationContext, ToolkitOptions } from '@multitenantkit/domain-contracts/shared';
|
|
4
|
+
import { type ConflictError, type NotFoundError, UnauthorizedError, ValidationError } from '@multitenantkit/domain-contracts/shared/errors/index';
|
|
5
|
+
import { Result } from '../../../shared/result';
|
|
6
|
+
import { BaseUseCase } from '../../../shared/use-case';
|
|
7
|
+
/**
|
|
8
|
+
* UpdateOrganization use case
|
|
9
|
+
* Handles the business logic for updating a organization (any fields including custom)
|
|
10
|
+
* Note: Despite the name, this use case now handles updates to any organization property
|
|
11
|
+
*
|
|
12
|
+
* Generic support for custom fields:
|
|
13
|
+
* @template TOrganizationCustomFields - Custom fields added to Organization
|
|
14
|
+
* @template TUserCustomFields - User custom fields (for toolkit options compatibility)
|
|
15
|
+
* @template TOrganizationMembershipCustomFields - Membership custom fields (for toolkit options compatibility)
|
|
16
|
+
*/
|
|
17
|
+
export declare class UpdateOrganization<TOrganizationCustomFields = {}, TUserCustomFields = {}, TOrganizationMembershipCustomFields = {}> extends BaseUseCase<UpdateOrganizationInput & TOrganizationCustomFields, UpdateOrganizationOutput, ValidationError | NotFoundError | ConflictError | UnauthorizedError, TUserCustomFields, TOrganizationCustomFields, TOrganizationMembershipCustomFields> implements IUpdateOrganization {
|
|
18
|
+
private readonly customSchema?;
|
|
19
|
+
constructor(adapters: Adapters<TUserCustomFields, TOrganizationCustomFields, TOrganizationMembershipCustomFields>, toolkitOptions?: ToolkitOptions<TUserCustomFields, TOrganizationCustomFields, TOrganizationMembershipCustomFields>);
|
|
20
|
+
protected executeBusinessLogic(input: UpdateOrganizationInput & TOrganizationCustomFields, context: OperationContext): Promise<Result<UpdateOrganizationOutput, ValidationError | NotFoundError | ConflictError | UnauthorizedError>>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=UpdateOrganization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateOrganization.d.ts","sourceRoot":"","sources":["../../../../src/organizations/use-cases/update-organization/UpdateOrganization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EACR,mBAAmB,EAEnB,uBAAuB,EACvB,wBAAwB,EAC3B,MAAM,gDAAgD,CAAC;AAMxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EACH,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,iBAAiB,EACjB,eAAe,EAClB,MAAM,sDAAsD,CAAC;AAE9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAkB,MAAM,0BAA0B,CAAC;AAEvE;;;;;;;;;GASG;AACH,qBAAa,kBAAkB,CAEvB,yBAAyB,GAAG,EAAE,EAE9B,iBAAiB,GAAG,EAAE,EAEtB,mCAAmC,GAAG,EAAE,CAE5C,SAAQ,WAAW,CACf,uBAAuB,GAAG,yBAAyB,EACnD,wBAAwB,EACxB,eAAe,GAAG,aAAa,GAAG,aAAa,GAAG,iBAAiB,EACnE,iBAAiB,EACjB,yBAAyB,EACzB,mCAAmC,CAEvC,YAAW,mBAAmB;IAE9B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAmB;gBAG7C,QAAQ,EAAE,QAAQ,CACd,iBAAiB,EACjB,yBAAyB,EACzB,mCAAmC,CACtC,EACD,cAAc,CAAC,EAAE,cAAc,CAC3B,iBAAiB,EACjB,yBAAyB,EACzB,mCAAmC,CACtC;cA8CW,oBAAoB,CAChC,KAAK,EAAE,uBAAuB,GAAG,yBAAyB,EAC1D,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CACN,MAAM,CACF,wBAAwB,EACxB,eAAe,GAAG,aAAa,GAAG,aAAa,GAAG,iBAAiB,CACtE,CACJ;CAmGJ"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { OrganizationSchema, UpdateOrganizationInputSchema, UpdateOrganizationOutputSchema } from '@multitenantkit/domain-contracts/organizations';
|
|
2
|
+
import { UnauthorizedError, ValidationError } from '@multitenantkit/domain-contracts/shared/errors/index';
|
|
3
|
+
import { Result } from '../../../shared/result';
|
|
4
|
+
import { BaseUseCase, UseCaseHelpers } from '../../../shared/use-case';
|
|
5
|
+
/**
|
|
6
|
+
* UpdateOrganization use case
|
|
7
|
+
* Handles the business logic for updating a organization (any fields including custom)
|
|
8
|
+
* Note: Despite the name, this use case now handles updates to any organization property
|
|
9
|
+
*
|
|
10
|
+
* Generic support for custom fields:
|
|
11
|
+
* @template TOrganizationCustomFields - Custom fields added to Organization
|
|
12
|
+
* @template TUserCustomFields - User custom fields (for toolkit options compatibility)
|
|
13
|
+
* @template TOrganizationMembershipCustomFields - Membership custom fields (for toolkit options compatibility)
|
|
14
|
+
*/
|
|
15
|
+
export class UpdateOrganization extends BaseUseCase {
|
|
16
|
+
customSchema;
|
|
17
|
+
constructor(adapters, toolkitOptions) {
|
|
18
|
+
// Extract custom schema from toolkit options
|
|
19
|
+
const customSchema = toolkitOptions?.organizations?.customFields?.customSchema;
|
|
20
|
+
// Build input schema with optional custom fields
|
|
21
|
+
const inputSchema = (customSchema
|
|
22
|
+
? UpdateOrganizationInputSchema.and(customSchema.partial())
|
|
23
|
+
: UpdateOrganizationInputSchema).refine((data) => Object.keys(data).some((k) => k !== 'organizationId' && k !== 'userId' && data[k] !== undefined), {
|
|
24
|
+
message: 'At least one field must be provided for update',
|
|
25
|
+
path: ['root']
|
|
26
|
+
});
|
|
27
|
+
// Extend output schema with custom fields if provided
|
|
28
|
+
const outputSchema = customSchema
|
|
29
|
+
? UpdateOrganizationOutputSchema.merge(customSchema)
|
|
30
|
+
: UpdateOrganizationOutputSchema;
|
|
31
|
+
super('organization-updateOrganization', adapters, toolkitOptions, inputSchema, outputSchema, 'Failed to update organization');
|
|
32
|
+
// Store custom schema for use in validation
|
|
33
|
+
this.customSchema = customSchema;
|
|
34
|
+
}
|
|
35
|
+
async executeBusinessLogic(input, context) {
|
|
36
|
+
// 1. Find existing organization
|
|
37
|
+
const organizationResult = await UseCaseHelpers.findByIdOrFail(this.adapters.persistence.organizationRepository, input.organizationId, 'Organization');
|
|
38
|
+
if (organizationResult.isFailure) {
|
|
39
|
+
return organizationResult;
|
|
40
|
+
}
|
|
41
|
+
const getUserResult = await this.getUserFromExternalId(input.principalExternalId);
|
|
42
|
+
if (getUserResult.isFailure) {
|
|
43
|
+
return Result.fail(getUserResult.getError());
|
|
44
|
+
}
|
|
45
|
+
const existingUser = getUserResult.getValue();
|
|
46
|
+
const existingOrganizationDB = organizationResult.getValue();
|
|
47
|
+
const existingOrganization = existingOrganizationDB;
|
|
48
|
+
// 1.5. Verify organization is not deleted
|
|
49
|
+
if (existingOrganization.deletedAt) {
|
|
50
|
+
return Result.fail(new ValidationError('Cannot update a deleted organization', 'organizationId'));
|
|
51
|
+
}
|
|
52
|
+
// 2. Verify permissions - organization owner or admin can update organization
|
|
53
|
+
const isOwner = existingOrganization.ownerUserId === existingUser.id;
|
|
54
|
+
let isAdmin = false;
|
|
55
|
+
if (!isOwner) {
|
|
56
|
+
// Check if user is an admin organization member
|
|
57
|
+
const membershipDB = await this.adapters.persistence.organizationMembershipRepository.findByUserIdAndOrganizationId(existingUser.id, input.organizationId);
|
|
58
|
+
isAdmin =
|
|
59
|
+
!!membershipDB &&
|
|
60
|
+
!!membershipDB.joinedAt &&
|
|
61
|
+
!membershipDB.leftAt &&
|
|
62
|
+
!membershipDB.deletedAt &&
|
|
63
|
+
membershipDB.roleCode === 'admin';
|
|
64
|
+
}
|
|
65
|
+
if (!isOwner && !isAdmin) {
|
|
66
|
+
return Result.fail(new UnauthorizedError('Only organization owner or admin members can update organization'));
|
|
67
|
+
}
|
|
68
|
+
// 3. Build updated organization data
|
|
69
|
+
const now = this.adapters.system.clock.now();
|
|
70
|
+
// Filter out undefined values from input to preserve existing values
|
|
71
|
+
// Exclude organizationId and userId as they are not organization properties
|
|
72
|
+
const { _organizationId, _userId, ...updateFields } = input;
|
|
73
|
+
const definedInputFields = Object.fromEntries(Object.entries(updateFields).filter(([_, value]) => value !== undefined));
|
|
74
|
+
// Merge existing organization with defined input fields
|
|
75
|
+
const updatedOrganizationData = {
|
|
76
|
+
...existingOrganization,
|
|
77
|
+
...definedInputFields,
|
|
78
|
+
updatedAt: now
|
|
79
|
+
};
|
|
80
|
+
// Validate the merged data with custom schema if provided
|
|
81
|
+
const validationSchema = this.customSchema
|
|
82
|
+
? OrganizationSchema.strip().and(this.customSchema.strip())
|
|
83
|
+
: OrganizationSchema.strip();
|
|
84
|
+
const organizationValidationResult = validationSchema.safeParse(updatedOrganizationData);
|
|
85
|
+
if (!organizationValidationResult.success) {
|
|
86
|
+
const firstError = organizationValidationResult.error.errors[0];
|
|
87
|
+
return Result.fail(new ValidationError(firstError.message, firstError.path.join('.')));
|
|
88
|
+
}
|
|
89
|
+
// Use validated and potentially transformed data from Zod
|
|
90
|
+
const updatedOrganization = organizationValidationResult.data;
|
|
91
|
+
// 4. Persist the updated organization using Unit of Work (transaction) with audit context
|
|
92
|
+
const auditContext = UseCaseHelpers.enrichAuditContext(context, 'UPDATE_ORGANIZATION', input.organizationId);
|
|
93
|
+
await this.adapters.persistence.uow.transaction(async (repos) => {
|
|
94
|
+
await repos.organizations.update(updatedOrganization, auditContext);
|
|
95
|
+
});
|
|
96
|
+
// 5. Return success response; BaseUseCase will parse output
|
|
97
|
+
return Result.ok(updatedOrganization);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=UpdateOrganization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateOrganization.js","sourceRoot":"","sources":["../../../../src/organizations/use-cases/update-organization/UpdateOrganization.ts"],"names":[],"mappings":"AAOA,OAAO,EACH,kBAAkB,EAClB,6BAA6B,EAC7B,8BAA8B,EACjC,MAAM,gDAAgD,CAAC;AAExD,OAAO,EAGH,iBAAiB,EACjB,eAAe,EAClB,MAAM,sDAAsD,CAAC;AAE9D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;;;;;;;;GASG;AACH,MAAM,OAAO,kBAQT,SAAQ,WAOP;IAGgB,YAAY,CAAoB;IAEjD,YACI,QAIC,EACD,cAIC;QAED,6CAA6C;QAC7C,MAAM,YAAY,GAAG,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,YAEnD,CAAC;QAEhB,iDAAiD;QACjD,MAAM,WAAW,GACb,CAAC,YAAY;YACT,CAAC,CAAC,6BAA6B,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAC3D,CAAC,CAAC,6BAA6B,CAGtC,CAAC,MAAM,CACJ,CAAC,IAAS,EAAE,EAAE,CACV,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAClB,CAAC,CAAC,EAAE,EAAE,CACF,CAAC,KAAK,gBAAgB,IAAI,CAAC,KAAK,QAAQ,IAAK,IAAY,CAAC,CAAC,CAAC,KAAK,SAAS,CACjF,EACL;YACI,OAAO,EAAE,gDAAgD;YACzD,IAAI,EAAE,CAAC,MAAM,CAAC;SACjB,CACJ,CAAC;QAEF,sDAAsD;QACtD,MAAM,YAAY,GAAG,YAAY;YAC7B,CAAC,CAAE,8BAA8B,CAAC,KAAK,CACjC,YAAY,CACoC;YACtD,CAAC,CAAE,8BAAiF,CAAC;QAEzF,KAAK,CACD,iCAAiC,EACjC,QAAQ,EACR,cAAc,EACd,WAAW,EACX,YAAY,EACZ,+BAA+B,CAClC,CAAC;QAEF,4CAA4C;QAC5C,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAES,KAAK,CAAC,oBAAoB,CAChC,KAA0D,EAC1D,OAAyB;QAOzB,gCAAgC;QAChC,MAAM,kBAAkB,GAAG,MAAM,cAAc,CAAC,cAAc,CAC1D,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,sBAAsB,EAChD,KAAK,CAAC,cAAc,EACpB,cAAc,CACjB,CAAC;QACF,IAAI,kBAAkB,CAAC,SAAS,EAAE,CAAC;YAC/B,OAAO,kBAAgF,CAAC;QAC5F,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAClF,IAAI,aAAa,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,YAAY,GAAG,aAAa,CAAC,QAAQ,EAAE,CAAC;QAC9C,MAAM,sBAAsB,GAAG,kBAAkB,CAAC,QAAQ,EAAE,CAAC;QAC7D,MAAM,oBAAoB,GACtB,sBAA6B,CAAC;QAElC,0CAA0C;QAC1C,IAAI,oBAAoB,CAAC,SAAS,EAAE,CAAC;YACjC,OAAO,MAAM,CAAC,IAAI,CACd,IAAI,eAAe,CAAC,sCAAsC,EAAE,gBAAgB,CAAC,CAChF,CAAC;QACN,CAAC;QAED,8EAA8E;QAC9E,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,KAAK,YAAY,CAAC,EAAE,CAAC;QAErE,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,gDAAgD;YAChD,MAAM,YAAY,GACd,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,gCAAgC,CAAC,6BAA6B,CAC1F,YAAY,CAAC,EAAE,EACf,KAAK,CAAC,cAAc,CACvB,CAAC;YACN,OAAO;gBACH,CAAC,CAAC,YAAY;oBACd,CAAC,CAAC,YAAY,CAAC,QAAQ;oBACvB,CAAC,YAAY,CAAC,MAAM;oBACpB,CAAC,YAAY,CAAC,SAAS;oBACvB,YAAY,CAAC,QAAQ,KAAK,OAAO,CAAC;QAC1C,CAAC;QAED,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC,IAAI,CACd,IAAI,iBAAiB,CACjB,kEAAkE,CACrE,CACJ,CAAC;QACN,CAAC;QAED,qCAAqC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAE7C,qEAAqE;QACrE,4EAA4E;QAC5E,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,KAAY,CAAC;QACnE,MAAM,kBAAkB,GAAG,MAAM,CAAC,WAAW,CACzC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CACrC,CAAC;QAExC,wDAAwD;QACxD,MAAM,uBAAuB,GAA6C;YACtE,GAAG,oBAAoB;YACvB,GAAG,kBAAkB;YACrB,SAAS,EAAE,GAAG;SACjB,CAAC;QAEF,0DAA0D;QAC1D,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY;YACtC,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YAC3D,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAEjC,MAAM,4BAA4B,GAAG,gBAAgB,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QACzF,IAAI,CAAC,4BAA4B,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,UAAU,GAAG,4BAA4B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAChE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3F,CAAC;QAED,0DAA0D;QAC1D,MAAM,mBAAmB,GAAG,4BAA4B,CAAC,IAC5B,CAAC;QAE9B,0FAA0F;QAC1F,MAAM,YAAY,GAAG,cAAc,CAAC,kBAAkB,CAClD,OAAO,EACP,qBAAqB,EACrB,KAAK,CAAC,cAAc,CACvB,CAAC;QAEF,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC5D,MAAM,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,4DAA4D;QAC5D,OAAO,MAAM,CAAC,EAAE,CAAC,mBAA0D,CAAC,CAAC;IACjF,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shared/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result pattern for handling errors in a functional way
|
|
3
|
+
* Based on Railway Oriented Programming
|
|
4
|
+
*/
|
|
5
|
+
export declare abstract class Result<T, E> {
|
|
6
|
+
readonly isSuccess: boolean;
|
|
7
|
+
readonly isFailure: boolean;
|
|
8
|
+
constructor(isSuccess: boolean);
|
|
9
|
+
static ok<U>(value: U): Ok<U, never>;
|
|
10
|
+
static fail<F>(error: F): Fail<never, F>;
|
|
11
|
+
abstract getValue(): T;
|
|
12
|
+
abstract getError(): E;
|
|
13
|
+
map<U>(fn: (value: T) => U): Result<U, E>;
|
|
14
|
+
mapError<F>(fn: (error: E) => F): Result<T, F>;
|
|
15
|
+
flatMap<U>(fn: (value: T) => Result<U, E>): Result<U, E>;
|
|
16
|
+
match<U>(onSuccess: (value: T) => U, onFailure: (error: E) => U): U;
|
|
17
|
+
}
|
|
18
|
+
export declare class Ok<T, E> extends Result<T, E> {
|
|
19
|
+
private readonly _value;
|
|
20
|
+
constructor(value: T);
|
|
21
|
+
getValue(): T;
|
|
22
|
+
getError(): E;
|
|
23
|
+
}
|
|
24
|
+
export declare class Fail<T, E> extends Result<T, E> {
|
|
25
|
+
private readonly _error;
|
|
26
|
+
constructor(error: E);
|
|
27
|
+
getValue(): T;
|
|
28
|
+
getError(): E;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=Result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Result.d.ts","sourceRoot":"","sources":["../../../src/shared/result/Result.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8BAAsB,MAAM,CAAC,CAAC,EAAE,CAAC;IAC7B,SAAgB,SAAS,EAAE,OAAO,CAAC;IACnC,SAAgB,SAAS,EAAE,OAAO,CAAC;gBAEvB,SAAS,EAAE,OAAO;WAKhB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC;WAI7B,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;aAI/B,QAAQ,IAAI,CAAC;aACb,QAAQ,IAAI,CAAC;IAEtB,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAOzC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAO9C,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAOxD,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;CAM7E;AAED,qBAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAI;gBAEf,KAAK,EAAE,CAAC;IAKb,QAAQ,IAAI,CAAC;IAIb,QAAQ,IAAI,CAAC;CAGvB;AAED,qBAAa,IAAI,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAI;gBAEf,KAAK,EAAE,CAAC;IAKb,QAAQ,IAAI,CAAC;IAIb,QAAQ,IAAI,CAAC;CAGvB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result pattern for handling errors in a functional way
|
|
3
|
+
* Based on Railway Oriented Programming
|
|
4
|
+
*/
|
|
5
|
+
export class Result {
|
|
6
|
+
isSuccess;
|
|
7
|
+
isFailure;
|
|
8
|
+
constructor(isSuccess) {
|
|
9
|
+
this.isSuccess = isSuccess;
|
|
10
|
+
this.isFailure = !isSuccess;
|
|
11
|
+
}
|
|
12
|
+
static ok(value) {
|
|
13
|
+
return new Ok(value);
|
|
14
|
+
}
|
|
15
|
+
static fail(error) {
|
|
16
|
+
return new Fail(error);
|
|
17
|
+
}
|
|
18
|
+
map(fn) {
|
|
19
|
+
if (this.isFailure) {
|
|
20
|
+
return Result.fail(this.getError());
|
|
21
|
+
}
|
|
22
|
+
return Result.ok(fn(this.getValue()));
|
|
23
|
+
}
|
|
24
|
+
mapError(fn) {
|
|
25
|
+
if (this.isSuccess) {
|
|
26
|
+
return Result.ok(this.getValue());
|
|
27
|
+
}
|
|
28
|
+
return Result.fail(fn(this.getError()));
|
|
29
|
+
}
|
|
30
|
+
flatMap(fn) {
|
|
31
|
+
if (this.isFailure) {
|
|
32
|
+
return Result.fail(this.getError());
|
|
33
|
+
}
|
|
34
|
+
return fn(this.getValue());
|
|
35
|
+
}
|
|
36
|
+
match(onSuccess, onFailure) {
|
|
37
|
+
if (this.isSuccess) {
|
|
38
|
+
return onSuccess(this.getValue());
|
|
39
|
+
}
|
|
40
|
+
return onFailure(this.getError());
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class Ok extends Result {
|
|
44
|
+
_value;
|
|
45
|
+
constructor(value) {
|
|
46
|
+
super(true);
|
|
47
|
+
this._value = value;
|
|
48
|
+
}
|
|
49
|
+
getValue() {
|
|
50
|
+
return this._value;
|
|
51
|
+
}
|
|
52
|
+
getError() {
|
|
53
|
+
throw new Error('Cannot get error from Ok result');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class Fail extends Result {
|
|
57
|
+
_error;
|
|
58
|
+
constructor(error) {
|
|
59
|
+
super(false);
|
|
60
|
+
this._error = error;
|
|
61
|
+
}
|
|
62
|
+
getValue() {
|
|
63
|
+
throw new Error('Cannot get value from Fail result');
|
|
64
|
+
}
|
|
65
|
+
getError() {
|
|
66
|
+
return this._error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=Result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Result.js","sourceRoot":"","sources":["../../../src/shared/result/Result.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,OAAgB,MAAM;IACR,SAAS,CAAU;IACnB,SAAS,CAAU;IAEnC,YAAY,SAAkB;QAC1B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,CAAC,SAAS,CAAC;IAChC,CAAC;IAEM,MAAM,CAAC,EAAE,CAAI,KAAQ;QACxB,OAAO,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAEM,MAAM,CAAC,IAAI,CAAI,KAAQ;QAC1B,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAKM,GAAG,CAAI,EAAmB;QAC7B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAEM,QAAQ,CAAI,EAAmB;QAClC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC5C,CAAC;IAEM,OAAO,CAAI,EAA8B;QAC5C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/B,CAAC;IAEM,KAAK,CAAI,SAA0B,EAAE,SAA0B;QAClE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtC,CAAC;CACJ;AAED,MAAM,OAAO,EAAS,SAAQ,MAAY;IACrB,MAAM,CAAI;IAE3B,YAAY,KAAQ;QAChB,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAEM,QAAQ;QACX,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAEM,QAAQ;QACX,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACvD,CAAC;CACJ;AAED,MAAM,OAAO,IAAW,SAAQ,MAAY;IACvB,MAAM,CAAI;IAE3B,YAAY,KAAQ;QAChB,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAEM,QAAQ;QACX,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACzD,CAAC;IAEM,QAAQ;QACX,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/result/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAG5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/result/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import type { Adapters, DomainError, OperationContext, ToolkitOptions, User } from '@multitenantkit/domain-contracts';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import { Result } from '../result/Result';
|
|
4
|
+
/**
|
|
5
|
+
* Base class for all use cases following a consistent execution pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Provides automatic:
|
|
8
|
+
* - Input validation with Zod schemas
|
|
9
|
+
* - Output parsing/transformation
|
|
10
|
+
* - Error handling and wrapping
|
|
11
|
+
* - Hook lifecycle management with abort support
|
|
12
|
+
* - Consistent structure across all use cases
|
|
13
|
+
*
|
|
14
|
+
* @template TInput - Input type for the use case
|
|
15
|
+
* @template TOutput - Output type returned by the use case
|
|
16
|
+
* @template TError - Domain error types that can be returned
|
|
17
|
+
* @template TCustomFields - Custom fields extension for entities
|
|
18
|
+
* @template TOrganizationCustomFields - Custom fields for organizations (toolkit options compatibility)
|
|
19
|
+
* @template TOrganizationMembershipCustomFields - Custom fields for organization memberships (toolkit options compatibility)
|
|
20
|
+
*/
|
|
21
|
+
export declare abstract class BaseUseCase<TInput, TOutput, TError extends DomainError = DomainError, TCustomFields = any, TOrganizationCustomFields = any, TOrganizationMembershipCustomFields = any> {
|
|
22
|
+
protected readonly adapters: Adapters<TCustomFields, TOrganizationCustomFields, TOrganizationMembershipCustomFields>;
|
|
23
|
+
protected readonly toolkitOptions: ToolkitOptions<TCustomFields, TOrganizationCustomFields, TOrganizationMembershipCustomFields> | undefined;
|
|
24
|
+
private readonly inputSchema;
|
|
25
|
+
private readonly outputSchema;
|
|
26
|
+
private readonly errorMessage;
|
|
27
|
+
/**
|
|
28
|
+
* Abort state tracking
|
|
29
|
+
* These track whether a hook has requested abort and the reason
|
|
30
|
+
*/
|
|
31
|
+
private abortRequested;
|
|
32
|
+
private abortReason;
|
|
33
|
+
/**
|
|
34
|
+
* Shared state object for hooks
|
|
35
|
+
* Reset at the start of each execution
|
|
36
|
+
*/
|
|
37
|
+
private sharedState;
|
|
38
|
+
/**
|
|
39
|
+
* Step results object for hooks
|
|
40
|
+
* Stores results from each pipeline step
|
|
41
|
+
*/
|
|
42
|
+
private stepResults;
|
|
43
|
+
/**
|
|
44
|
+
* Execution ID for tracking
|
|
45
|
+
* Generated at the start of each execution
|
|
46
|
+
*/
|
|
47
|
+
private executionId;
|
|
48
|
+
/**
|
|
49
|
+
* Use case name in format "entity-useCaseName"
|
|
50
|
+
* Example: "user-updateUser", "organization-createOrganization"
|
|
51
|
+
* This helps prevent name collisions between different entities
|
|
52
|
+
*/
|
|
53
|
+
protected readonly useCaseName: string;
|
|
54
|
+
constructor(useCaseName: string, adapters: Adapters<TCustomFields, TOrganizationCustomFields, TOrganizationMembershipCustomFields>, toolkitOptions: ToolkitOptions<TCustomFields, TOrganizationCustomFields, TOrganizationMembershipCustomFields> | undefined, inputSchema: z.ZodType<TInput>, outputSchema: z.ZodType<TOutput>, errorMessage: string);
|
|
55
|
+
/**
|
|
56
|
+
* Initialize execution state for a new execution
|
|
57
|
+
* Resets abort state, shared state, step results, and generates execution ID
|
|
58
|
+
*/
|
|
59
|
+
private initializeExecutionState;
|
|
60
|
+
/**
|
|
61
|
+
* Create abort function for hook context
|
|
62
|
+
* When called, sets abort state which will be checked after each hook
|
|
63
|
+
*
|
|
64
|
+
* @returns Abort function that hooks can call
|
|
65
|
+
*/
|
|
66
|
+
private createAbortFunction;
|
|
67
|
+
/**
|
|
68
|
+
* Check if abort was requested
|
|
69
|
+
* Should be called after each hook execution
|
|
70
|
+
*
|
|
71
|
+
* @returns true if abort was requested
|
|
72
|
+
*/
|
|
73
|
+
private checkAborted;
|
|
74
|
+
/**
|
|
75
|
+
* Build HookContext object for passing to hooks
|
|
76
|
+
* Provides immutable access to input/stepResults and mutable shared state
|
|
77
|
+
*
|
|
78
|
+
* @param input - Original input to the use case
|
|
79
|
+
* @param context - Operation context
|
|
80
|
+
* @returns HookContext object
|
|
81
|
+
*/
|
|
82
|
+
private buildHookContext;
|
|
83
|
+
/**
|
|
84
|
+
* Get configured hooks for this use case from ToolkitOptions
|
|
85
|
+
*
|
|
86
|
+
* @returns UseCaseHooks if configured, undefined otherwise
|
|
87
|
+
*/
|
|
88
|
+
private getHooksConfig;
|
|
89
|
+
/**
|
|
90
|
+
* Execute a hook safely with error handling and metrics logging
|
|
91
|
+
* If hook throws an error, it propagates (hooks can abort execution)
|
|
92
|
+
*
|
|
93
|
+
* @param hookFn - Hook function to execute
|
|
94
|
+
* @param ctx - HookContext to pass to the hook
|
|
95
|
+
* @param hookName - Name of the hook for logging purposes
|
|
96
|
+
*/
|
|
97
|
+
private executeHook;
|
|
98
|
+
/**
|
|
99
|
+
* Log hook execution metrics (fire-and-forget)
|
|
100
|
+
* Errors are silently caught to not affect execution flow
|
|
101
|
+
*
|
|
102
|
+
* @param hookName - Name of the hook being executed
|
|
103
|
+
* @param ctx - Hook context (will be filtered for PII)
|
|
104
|
+
*/
|
|
105
|
+
private logMetrics;
|
|
106
|
+
/**
|
|
107
|
+
* Get user from external ID (auth provider ID)
|
|
108
|
+
*
|
|
109
|
+
* This helper maps the external auth provider ID to the internal User entity.
|
|
110
|
+
* It's used by use cases that operate on the authenticated user.
|
|
111
|
+
*
|
|
112
|
+
* @param externalId - Auth provider user ID (from Principal.authProviderId)
|
|
113
|
+
* @returns User entity with internal ID
|
|
114
|
+
* @throws NotFoundError if user doesn't exist
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* // In a use case
|
|
119
|
+
* const user = await this.getUserFromExternalId(context.principal.authProviderId);
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
protected getUserFromExternalId(externalId: string): Promise<Result<User & TCustomFields, DomainError>>;
|
|
123
|
+
/**
|
|
124
|
+
* Main execution method - defines the pipeline with hook integration
|
|
125
|
+
*
|
|
126
|
+
* Pipeline stages:
|
|
127
|
+
* 1. Initialize execution state
|
|
128
|
+
* 2. onStart hook
|
|
129
|
+
* 3. Validate input with schema
|
|
130
|
+
* 4. afterValidation hook
|
|
131
|
+
* 5. Authorize (optional)
|
|
132
|
+
* 6. beforeExecution hook (renamed from afterAuthorization)
|
|
133
|
+
* 7. Execute business logic
|
|
134
|
+
* 8. afterExecution hook
|
|
135
|
+
* 9. Parse output with schema
|
|
136
|
+
* 10. onError hook (if error occurs)
|
|
137
|
+
* 11. onAbort hook (if abort requested)
|
|
138
|
+
* 12. onFinally hook (always executes)
|
|
139
|
+
*/
|
|
140
|
+
execute(input: TInput, context: OperationContext): Promise<Result<TOutput, TError>>;
|
|
141
|
+
/**
|
|
142
|
+
* Validates input using the provided Zod schema
|
|
143
|
+
*/
|
|
144
|
+
private validateInput;
|
|
145
|
+
/**
|
|
146
|
+
* Authorization hook - override for permission checks
|
|
147
|
+
* Default: no authorization
|
|
148
|
+
*/
|
|
149
|
+
protected authorize(_input: TInput, _context: OperationContext): Promise<Result<void, DomainError>>;
|
|
150
|
+
/**
|
|
151
|
+
* Main business logic - must be implemented by each use case
|
|
152
|
+
* This is where the actual domain logic lives
|
|
153
|
+
*/
|
|
154
|
+
protected abstract executeBusinessLogic(input: TInput, context: OperationContext): Promise<Result<TOutput, TError>>;
|
|
155
|
+
/**
|
|
156
|
+
* Parses output using the provided Zod schema
|
|
157
|
+
*/
|
|
158
|
+
private parseOutput;
|
|
159
|
+
/**
|
|
160
|
+
* Wraps execution in try-catch for consistent error handling
|
|
161
|
+
*/
|
|
162
|
+
private withErrorHandling;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=BaseUseCase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseUseCase.d.ts","sourceRoot":"","sources":["../../../src/shared/use-case/BaseUseCase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,QAAQ,EACR,WAAW,EAEX,gBAAgB,EAChB,cAAc,EAEd,IAAI,EACP,MAAM,kCAAkC,CAAC;AAO1C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C;;;;;;;;;;;;;;;;GAgBG;AACH,8BAAsB,WAAW,CAC7B,MAAM,EACN,OAAO,EACP,MAAM,SAAS,WAAW,GAAG,WAAW,EACxC,aAAa,GAAG,GAAG,EACnB,yBAAyB,GAAG,GAAG,EAC/B,mCAAmC,GAAG,GAAG;IAwCrC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CACjC,aAAa,EACb,yBAAyB,EACzB,mCAAmC,CACtC;IACD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAC3B,cAAc,CACV,aAAa,EACb,yBAAyB,EACzB,mCAAmC,CACtC,GACD,SAAS;IACf,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY;IApDjC;;;OAGG;IACH,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,WAAW,CAAc;IAEjC;;;OAGG;IACH,OAAO,CAAC,WAAW,CAA2B;IAE9C;;;OAGG;IACH,OAAO,CAAC,WAAW,CAIZ;IAEP;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAc;IAEjC;;;;OAIG;IACH,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAGnC,WAAW,EAAE,MAAM,EACA,QAAQ,EAAE,QAAQ,CACjC,aAAa,EACb,yBAAyB,EACzB,mCAAmC,CACtC,EACkB,cAAc,EAC3B,cAAc,CACV,aAAa,EACb,yBAAyB,EACzB,mCAAmC,CACtC,GACD,SAAS,EACE,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAC9B,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAChC,YAAY,EAAE,MAAM;IAKzC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAQhC;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IA2BtB;;;;;;;OAOG;YACW,WAAW;IA+BzB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IA6BlB;;;;;;;;;;;;;;;OAeG;cACa,qBAAqB,CACjC,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,IAAI,GAAG,aAAa,EAAE,WAAW,CAAC,CAAC;IAoBrD;;;;;;;;;;;;;;;;OAgBG;IACU,OAAO,CAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAkInC;;OAEG;YACW,aAAa;IAS3B;;;OAGG;cACa,SAAS,CACrB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,gBAAgB,GAC3B,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAIrC;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,oBAAoB,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAEnC;;OAEG;IACH,OAAO,CAAC,WAAW;IAoBnB;;OAEG;YACW,iBAAiB;CAalC"}
|