@kuckit/application 1.0.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.
- package/dist/index.d.ts +78 -0
- package/dist/index.js +77 -0
- package/package.json +46 -0
- package/src/index.ts +3 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { UserRepository } from "@kuckit/domain/ports/user-repository";
|
|
2
|
+
import { User } from "@kuckit/domain/entities/user";
|
|
3
|
+
import { EventPublisher } from "@kuckit/domain/ports/event-publisher";
|
|
4
|
+
import { Clock } from "@kuckit/domain/ports/clock";
|
|
5
|
+
import { CacheStore, DomainEvent, EventBus, EventHandler, EventMap, EventMeta, EventName, RateLimiterStore, TypedDomainEvent } from "@kuckit/domain";
|
|
6
|
+
|
|
7
|
+
//#region src/usecases/get-user-profile.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* Dependencies required by the use case
|
|
10
|
+
*/
|
|
11
|
+
interface GetUserProfileDeps {
|
|
12
|
+
readonly userRepository: UserRepository;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Input for the use case
|
|
16
|
+
*/
|
|
17
|
+
interface GetUserProfileInput {
|
|
18
|
+
readonly userId: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Use case: Get user profile
|
|
22
|
+
* Pure business logic with no infrastructure dependencies
|
|
23
|
+
*
|
|
24
|
+
* No events for read operations - this is a query use case that doesn't
|
|
25
|
+
* modify state, so no domain events are published.
|
|
26
|
+
*/
|
|
27
|
+
declare const makeGetUserProfile: (deps: GetUserProfileDeps) => (input: GetUserProfileInput) => Promise<User>;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/usecases/update-user-profile.d.ts
|
|
30
|
+
/**
|
|
31
|
+
* Dependencies required by the use case
|
|
32
|
+
*/
|
|
33
|
+
interface UpdateUserProfileDeps {
|
|
34
|
+
readonly userRepository: UserRepository;
|
|
35
|
+
readonly eventPublisher: EventPublisher;
|
|
36
|
+
readonly clock: Clock;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Input for the use case
|
|
40
|
+
*/
|
|
41
|
+
interface UpdateUserProfileInput {
|
|
42
|
+
readonly userId: string;
|
|
43
|
+
readonly updates: {
|
|
44
|
+
readonly name?: string;
|
|
45
|
+
readonly email?: string;
|
|
46
|
+
readonly emailVerified?: boolean;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Use case: Update user profile
|
|
51
|
+
* Publishes 'user.updated' event after successful update
|
|
52
|
+
*/
|
|
53
|
+
declare const makeUpdateUserProfile: (deps: UpdateUserProfileDeps) => (input: UpdateUserProfileInput) => Promise<User>;
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/usecases/create-user.d.ts
|
|
56
|
+
/**
|
|
57
|
+
* Dependencies required by the use case
|
|
58
|
+
*/
|
|
59
|
+
interface CreateUserDeps {
|
|
60
|
+
readonly userRepository: UserRepository;
|
|
61
|
+
readonly eventPublisher: EventPublisher;
|
|
62
|
+
readonly clock: Clock;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Input for the use case
|
|
66
|
+
*/
|
|
67
|
+
interface CreateUserInput {
|
|
68
|
+
readonly name: string;
|
|
69
|
+
readonly email: string;
|
|
70
|
+
readonly emailVerified: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Use case: Create user
|
|
74
|
+
* Publishes 'user.created' event after successful creation
|
|
75
|
+
*/
|
|
76
|
+
declare const makeCreateUser: (deps: CreateUserDeps) => (input: CreateUserInput) => Promise<User>;
|
|
77
|
+
//#endregion
|
|
78
|
+
export { type CacheStore, CreateUserDeps, CreateUserInput, type DomainEvent, type EventBus, type EventHandler, type EventMap, type EventMeta, type EventName, GetUserProfileDeps, GetUserProfileInput, type RateLimiterStore, type TypedDomainEvent, UpdateUserProfileDeps, UpdateUserProfileInput, makeCreateUser, makeGetUserProfile, makeUpdateUserProfile };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
|
|
3
|
+
//#region src/usecases/get-user-profile.ts
|
|
4
|
+
/**
|
|
5
|
+
* Use case: Get user profile
|
|
6
|
+
* Pure business logic with no infrastructure dependencies
|
|
7
|
+
*
|
|
8
|
+
* No events for read operations - this is a query use case that doesn't
|
|
9
|
+
* modify state, so no domain events are published.
|
|
10
|
+
*/
|
|
11
|
+
const makeGetUserProfile = (deps) => {
|
|
12
|
+
return async (input) => {
|
|
13
|
+
const user = await deps.userRepository.findById(input.userId);
|
|
14
|
+
if (!user) throw new Error("USER_NOT_FOUND");
|
|
15
|
+
return user;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/usecases/update-user-profile.ts
|
|
21
|
+
/**
|
|
22
|
+
* Use case: Update user profile
|
|
23
|
+
* Publishes 'user.updated' event after successful update
|
|
24
|
+
*/
|
|
25
|
+
const makeUpdateUserProfile = (deps) => {
|
|
26
|
+
return async (input) => {
|
|
27
|
+
const existingUser = await deps.userRepository.findById(input.userId);
|
|
28
|
+
if (!existingUser) throw new Error("USER_NOT_FOUND");
|
|
29
|
+
const updatedUser = {
|
|
30
|
+
...existingUser,
|
|
31
|
+
name: input.updates.name ?? existingUser.name,
|
|
32
|
+
email: input.updates.email ?? existingUser.email,
|
|
33
|
+
emailVerified: input.updates.emailVerified ?? existingUser.emailVerified,
|
|
34
|
+
updatedAt: deps.clock.now()
|
|
35
|
+
};
|
|
36
|
+
await deps.userRepository.save(updatedUser);
|
|
37
|
+
await deps.eventPublisher.publish("user.updated", {
|
|
38
|
+
userId: updatedUser.id,
|
|
39
|
+
changes: input.updates,
|
|
40
|
+
updatedAt: updatedUser.updatedAt
|
|
41
|
+
}, updatedUser.id);
|
|
42
|
+
return updatedUser;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/usecases/create-user.ts
|
|
48
|
+
/**
|
|
49
|
+
* Use case: Create user
|
|
50
|
+
* Publishes 'user.created' event after successful creation
|
|
51
|
+
*/
|
|
52
|
+
const makeCreateUser = (deps) => {
|
|
53
|
+
return async (input) => {
|
|
54
|
+
if (await deps.userRepository.findByEmail(input.email)) throw new Error("USER_ALREADY_EXISTS");
|
|
55
|
+
const now = deps.clock.now();
|
|
56
|
+
const newUser = {
|
|
57
|
+
id: randomUUID(),
|
|
58
|
+
name: input.name,
|
|
59
|
+
email: input.email,
|
|
60
|
+
emailVerified: input.emailVerified,
|
|
61
|
+
permissions: ["modules:read"],
|
|
62
|
+
createdAt: now,
|
|
63
|
+
updatedAt: now
|
|
64
|
+
};
|
|
65
|
+
await deps.userRepository.save(newUser);
|
|
66
|
+
await deps.eventPublisher.publish("user.created", {
|
|
67
|
+
userId: newUser.id,
|
|
68
|
+
email: newUser.email,
|
|
69
|
+
name: newUser.name,
|
|
70
|
+
createdAt: newUser.createdAt
|
|
71
|
+
}, newUser.id);
|
|
72
|
+
return newUser;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
export { makeCreateUser, makeGetUserProfile, makeUpdateUserProfile };
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kuckit/application",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"types": "src/index.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./src/index.ts",
|
|
13
|
+
"default": "./src/index.ts"
|
|
14
|
+
},
|
|
15
|
+
"./*": {
|
|
16
|
+
"types": "./src/*.ts",
|
|
17
|
+
"default": "./src/*.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"main": "dist/index.js",
|
|
22
|
+
"types": "dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./*": {
|
|
29
|
+
"types": "./dist/*.d.ts",
|
|
30
|
+
"default": "./dist/*.js"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsdown"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@kuckit/domain": "workspace:*"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"tsdown": "catalog:"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"typescript": "^5"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/index.ts
ADDED