@knpkv/clockify-api-client 1.0.2 → 1.0.3
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/CHANGELOG.md +9 -0
- package/dist/ClockifyApiClient.d.ts +8 -1
- package/dist/ClockifyApiClient.d.ts.map +1 -1
- package/dist/ClockifyApiClient.js +31 -1
- package/dist/ClockifyApiClient.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ClockifyApiClient.ts +51 -2
- package/src/index.ts +3 -1
- package/test/ClockifyApiClient.test.ts +101 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @knpkv/clockify-api-client
|
|
2
2
|
|
|
3
|
+
## 1.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#260](https://github.com/knpkv/npm/pull/260) [`38848a2`](https://github.com/knpkv/npm/commit/38848a2660aa98295f96d54d232e4cec15ea95a5) Thanks [@konopkov](https://github.com/konopkov)! - Add a read-first Clockify time-entry page with deterministic totals, source facts, people roles, and explicit Jira attribution states.
|
|
8
|
+
|
|
9
|
+
- [#303](https://github.com/knpkv/npm/pull/303) [`ad10dc7`](https://github.com/knpkv/npm/commit/ad10dc767d4c512186e47eeea5237a1e4c84e798) Thanks [@konopkov](https://github.com/konopkov)! - Add governed Clockify association correction and revision-scoped Control Center approval, with hydrated
|
|
10
|
+
time-entry reads for canonical revisions and safe replacement updates.
|
|
11
|
+
|
|
3
12
|
## 1.0.2
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
@@ -18,6 +18,7 @@ import { ClockifyApiConfig } from "./ClockifyApiConfig.js";
|
|
|
18
18
|
import * as Generated from "./generated/ClockifyApi.js";
|
|
19
19
|
export type ClockifyClientError = HttpClientError.HttpClientError | SchemaError;
|
|
20
20
|
export type User = Generated.GetLoggedUser200;
|
|
21
|
+
export type WorkspaceUser = Generated.GetUsersOfWorkspace200[number];
|
|
21
22
|
export type Workspace = Generated.GetWorkspacesOfUser200[number];
|
|
22
23
|
export type Project = Generated.GetProjects200[number];
|
|
23
24
|
export type Tag = Generated.GetTags200[number];
|
|
@@ -34,11 +35,17 @@ export type AuthenticatedClockifyApi = Omit<Generated.ClockifyApi, "uploadImage"
|
|
|
34
35
|
export interface GetTimeEntriesParams {
|
|
35
36
|
readonly start?: string | undefined;
|
|
36
37
|
readonly end?: string | undefined;
|
|
38
|
+
readonly hydrated?: boolean | undefined;
|
|
37
39
|
readonly page?: number | undefined;
|
|
38
40
|
readonly pageSize?: number | undefined;
|
|
39
41
|
}
|
|
42
|
+
export interface GetTimeEntryParams {
|
|
43
|
+
readonly hydrated?: boolean | undefined;
|
|
44
|
+
}
|
|
40
45
|
export interface ClockifyApiClientShape {
|
|
41
46
|
readonly getUser: () => Effect.Effect<User, ClockifyClientError>;
|
|
47
|
+
readonly getWorkspaceUsers?: (workspaceId: string) => Effect.Effect<ReadonlyArray<WorkspaceUser>, ClockifyClientError>;
|
|
48
|
+
readonly getWorkspaceUsersPage?: (workspaceId: string, page: number, pageSize: number) => Effect.Effect<ReadonlyArray<WorkspaceUser>, ClockifyClientError>;
|
|
42
49
|
readonly getWorkspaces: () => Effect.Effect<ReadonlyArray<Workspace>, ClockifyClientError>;
|
|
43
50
|
readonly getProjects: (workspaceId: string) => Effect.Effect<ReadonlyArray<Project>, ClockifyClientError>;
|
|
44
51
|
readonly getProjectByName: (workspaceId: string, name: string) => Effect.Effect<Project | null, ClockifyClientError>;
|
|
@@ -49,7 +56,7 @@ export interface ClockifyApiClientShape {
|
|
|
49
56
|
readonly getTags: (workspaceId: string) => Effect.Effect<Generated.GetTags200, ClockifyClientError>;
|
|
50
57
|
readonly createTag: (workspaceId: string, name: string) => Effect.Effect<Generated.CreateNewTag201, ClockifyClientError>;
|
|
51
58
|
readonly findOrCreateTag: (workspaceId: string, name: string) => Effect.Effect<Generated.GetTags200[number] | Generated.CreateNewTag201, ClockifyClientError>;
|
|
52
|
-
readonly getTimeEntry: (workspaceId: string, timeEntryId: string) => Effect.Effect<Generated.GetTimeEntry200, ClockifyClientError>;
|
|
59
|
+
readonly getTimeEntry: (workspaceId: string, timeEntryId: string, params?: GetTimeEntryParams) => Effect.Effect<Generated.GetTimeEntry200, ClockifyClientError>;
|
|
53
60
|
readonly deleteTimeEntry: (workspaceId: string, timeEntryId: string) => Effect.Effect<void, ClockifyClientError>;
|
|
54
61
|
readonly updateTimeEntry: (workspaceId: string, timeEntryId: string, params: UpdateTimeEntryParams) => Effect.Effect<Generated.UpdateTimeEntry200, ClockifyClientError>;
|
|
55
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClockifyApiClient.d.ts","sourceRoot":"","sources":["../src/ClockifyApiClient.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ClockifyApiClient.d.ts","sourceRoot":"","sources":["../src/ClockifyApiClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,8 +36,33 @@ export class ClockifyApiClient extends Context.Service()("@knpkv/clockify-api-cl
|
|
|
36
36
|
const api = make(httpClient, config);
|
|
37
37
|
const getProjects = (workspaceId) => api.getProjects(workspaceId, { params: { archived: false, "page-size": 500 } });
|
|
38
38
|
const getTags = (workspaceId) => api.getTags(workspaceId, { params: { archived: false, "page-size": 200 } });
|
|
39
|
+
const getWorkspaceUsersPage = Effect.fn("ClockifyApiClient.getWorkspaceUsersPage")(function* (workspaceId, page, pageSize) {
|
|
40
|
+
return yield* api.getUsersOfWorkspace(workspaceId, {
|
|
41
|
+
params: {
|
|
42
|
+
"account-statuses": "ACTIVE,PENDING_EMAIL_VERIFICATION,DELETED,NOT_REGISTERED,LIMITED,LIMITED_DELETED",
|
|
43
|
+
"include-roles": "false",
|
|
44
|
+
memberships: "ALL",
|
|
45
|
+
page,
|
|
46
|
+
"page-size": pageSize,
|
|
47
|
+
status: "ALL"
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
const getWorkspaceUsers = Effect.fn("ClockifyApiClient.getWorkspaceUsers")(function* (workspaceId) {
|
|
52
|
+
const users = [];
|
|
53
|
+
for (let page = 1;; page++) {
|
|
54
|
+
const batch = yield* getWorkspaceUsersPage(workspaceId, page, 500);
|
|
55
|
+
for (const user of batch)
|
|
56
|
+
users.push(user);
|
|
57
|
+
if (batch.length < 500)
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
return users;
|
|
61
|
+
});
|
|
39
62
|
return ClockifyApiClient.of({
|
|
40
63
|
getUser: () => api.getLoggedUser(undefined),
|
|
64
|
+
getWorkspaceUsers,
|
|
65
|
+
getWorkspaceUsersPage,
|
|
41
66
|
getWorkspaces: () => api.getWorkspacesOfUser(undefined),
|
|
42
67
|
getProjects,
|
|
43
68
|
getProjectByName: (workspaceId, name) => api.getProjects(workspaceId, { params: { name, archived: false } }).pipe(Effect.map((projects) => projects.find((project) => project.name.toLowerCase() === name.toLowerCase()) ?? null)),
|
|
@@ -47,6 +72,7 @@ export class ClockifyApiClient extends Context.Service()("@knpkv/clockify-api-cl
|
|
|
47
72
|
params: {
|
|
48
73
|
...(params?.start !== undefined ? { start: params.start } : {}),
|
|
49
74
|
...(params?.end !== undefined ? { end: params.end } : {}),
|
|
75
|
+
...(params?.hydrated === undefined ? {} : { hydrated: params.hydrated }),
|
|
50
76
|
...(params?.page !== undefined ? { page: params.page } : {}),
|
|
51
77
|
...(params?.pageSize !== undefined ? { "page-size": params.pageSize } : {})
|
|
52
78
|
}
|
|
@@ -62,7 +88,11 @@ export class ClockifyApiClient extends Context.Service()("@knpkv/clockify-api-cl
|
|
|
62
88
|
? api.createNewTag(workspaceId, { payload: { name } })
|
|
63
89
|
: Effect.succeed(existing);
|
|
64
90
|
})),
|
|
65
|
-
getTimeEntry: (workspaceId, timeEntryId) => api.getTimeEntry(workspaceId, timeEntryId,
|
|
91
|
+
getTimeEntry: (workspaceId, timeEntryId, params) => api.getTimeEntry(workspaceId, timeEntryId, {
|
|
92
|
+
params: {
|
|
93
|
+
...(params?.hydrated === undefined ? {} : { hydrated: params.hydrated })
|
|
94
|
+
}
|
|
95
|
+
}),
|
|
66
96
|
deleteTimeEntry: (workspaceId, timeEntryId) => api.deleteTimeEntry(workspaceId, timeEntryId, undefined),
|
|
67
97
|
updateTimeEntry: (workspaceId, timeEntryId, payload) => api.updateTimeEntry(workspaceId, timeEntryId, { payload })
|
|
68
98
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClockifyApiClient.js","sourceRoot":"","sources":["../src/ClockifyApiClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAE3C,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAA;AAE7D,OAAO,KAAK,iBAAiB,MAAM,wCAAwC,CAAA;AAC3E,OAAO,KAAK,kBAAkB,MAAM,yCAAyC,CAAA;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,KAAK,SAAS,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"ClockifyApiClient.js","sourceRoot":"","sources":["../src/ClockifyApiClient.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
6
|
export { ClockifyApiClient, type ClockifyApiClientShape, type ClockifyClientError, layer, make } from "./ClockifyApiClient.js";
|
|
7
|
-
export type { AuthenticatedClockifyApi, CreateTimeEntryParams, GetTimeEntriesParams, Project, StopTimeEntryParams, Tag, TimeEntry, TimeInterval, UpdateTimeEntryParams, User, Workspace } from "./ClockifyApiClient.js";
|
|
7
|
+
export type { AuthenticatedClockifyApi, CreateTimeEntryParams, GetTimeEntriesParams, GetTimeEntryParams, Project, StopTimeEntryParams, Tag, TimeEntry, TimeInterval, UpdateTimeEntryParams, User, Workspace, WorkspaceUser } from "./ClockifyApiClient.js";
|
|
8
8
|
export { ClockifyApiConfig, type ClockifyApiConfigShape } from "./ClockifyApiConfig.js";
|
|
9
9
|
export * as ClockifyApi from "./generated/ClockifyApi.js";
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,EACL,IAAI,EACL,MAAM,wBAAwB,CAAA;AAE/B,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,OAAO,EACP,mBAAmB,EACnB,GAAG,EACH,SAAS,EACT,YAAY,EACZ,qBAAqB,EACrB,IAAI,EACJ,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,EACL,IAAI,EACL,MAAM,wBAAwB,CAAA;AAE/B,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,GAAG,EACH,SAAS,EACT,YAAY,EACZ,qBAAqB,EACrB,IAAI,EACJ,SAAS,EACT,aAAa,EACd,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAEvF,OAAO,KAAK,WAAW,MAAM,4BAA4B,CAAA"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EAGjB,KAAK,EACL,IAAI,EACL,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EAGjB,KAAK,EACL,IAAI,EACL,MAAM,wBAAwB,CAAA;AAkB/B,OAAO,EAAE,iBAAiB,EAA+B,MAAM,wBAAwB,CAAA;AAEvF,OAAO,KAAK,WAAW,MAAM,4BAA4B,CAAA"}
|
package/package.json
CHANGED
package/src/ClockifyApiClient.ts
CHANGED
|
@@ -23,6 +23,7 @@ import * as Generated from "./generated/ClockifyApi.js"
|
|
|
23
23
|
export type ClockifyClientError = HttpClientError.HttpClientError | SchemaError
|
|
24
24
|
|
|
25
25
|
export type User = Generated.GetLoggedUser200
|
|
26
|
+
export type WorkspaceUser = Generated.GetUsersOfWorkspace200[number]
|
|
26
27
|
export type Workspace = Generated.GetWorkspacesOfUser200[number]
|
|
27
28
|
export type Project = Generated.GetProjects200[number]
|
|
28
29
|
export type Tag = Generated.GetTags200[number]
|
|
@@ -39,12 +40,25 @@ export type AuthenticatedClockifyApi = Omit<Generated.ClockifyApi, "uploadImage"
|
|
|
39
40
|
export interface GetTimeEntriesParams {
|
|
40
41
|
readonly start?: string | undefined
|
|
41
42
|
readonly end?: string | undefined
|
|
43
|
+
readonly hydrated?: boolean | undefined
|
|
42
44
|
readonly page?: number | undefined
|
|
43
45
|
readonly pageSize?: number | undefined
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
export interface GetTimeEntryParams {
|
|
49
|
+
readonly hydrated?: boolean | undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
46
52
|
export interface ClockifyApiClientShape {
|
|
47
53
|
readonly getUser: () => Effect.Effect<User, ClockifyClientError>
|
|
54
|
+
readonly getWorkspaceUsers?: (
|
|
55
|
+
workspaceId: string
|
|
56
|
+
) => Effect.Effect<ReadonlyArray<WorkspaceUser>, ClockifyClientError>
|
|
57
|
+
readonly getWorkspaceUsersPage?: (
|
|
58
|
+
workspaceId: string,
|
|
59
|
+
page: number,
|
|
60
|
+
pageSize: number
|
|
61
|
+
) => Effect.Effect<ReadonlyArray<WorkspaceUser>, ClockifyClientError>
|
|
48
62
|
readonly getWorkspaces: () => Effect.Effect<ReadonlyArray<Workspace>, ClockifyClientError>
|
|
49
63
|
readonly getProjects: (workspaceId: string) => Effect.Effect<ReadonlyArray<Project>, ClockifyClientError>
|
|
50
64
|
readonly getProjectByName: (workspaceId: string, name: string) => Effect.Effect<Project | null, ClockifyClientError>
|
|
@@ -77,7 +91,8 @@ export interface ClockifyApiClientShape {
|
|
|
77
91
|
) => Effect.Effect<Generated.GetTags200[number] | Generated.CreateNewTag201, ClockifyClientError>
|
|
78
92
|
readonly getTimeEntry: (
|
|
79
93
|
workspaceId: string,
|
|
80
|
-
timeEntryId: string
|
|
94
|
+
timeEntryId: string,
|
|
95
|
+
params?: GetTimeEntryParams
|
|
81
96
|
) => Effect.Effect<Generated.GetTimeEntry200, ClockifyClientError>
|
|
82
97
|
readonly deleteTimeEntry: (workspaceId: string, timeEntryId: string) => Effect.Effect<void, ClockifyClientError>
|
|
83
98
|
readonly updateTimeEntry: (
|
|
@@ -129,8 +144,36 @@ export class ClockifyApiClient extends Context.Service<ClockifyApiClient, Clocki
|
|
|
129
144
|
const getTags = (workspaceId: string) =>
|
|
130
145
|
api.getTags(workspaceId, { params: { archived: false, "page-size": 200 } })
|
|
131
146
|
|
|
147
|
+
const getWorkspaceUsersPage = Effect.fn("ClockifyApiClient.getWorkspaceUsersPage")(function*(
|
|
148
|
+
workspaceId: string,
|
|
149
|
+
page: number,
|
|
150
|
+
pageSize: number
|
|
151
|
+
) {
|
|
152
|
+
return yield* api.getUsersOfWorkspace(workspaceId, {
|
|
153
|
+
params: {
|
|
154
|
+
"account-statuses": "ACTIVE,PENDING_EMAIL_VERIFICATION,DELETED,NOT_REGISTERED,LIMITED,LIMITED_DELETED",
|
|
155
|
+
"include-roles": "false",
|
|
156
|
+
memberships: "ALL",
|
|
157
|
+
page,
|
|
158
|
+
"page-size": pageSize,
|
|
159
|
+
status: "ALL"
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
const getWorkspaceUsers = Effect.fn("ClockifyApiClient.getWorkspaceUsers")(function*(workspaceId: string) {
|
|
164
|
+
const users: Array<WorkspaceUser> = []
|
|
165
|
+
for (let page = 1;; page++) {
|
|
166
|
+
const batch = yield* getWorkspaceUsersPage(workspaceId, page, 500)
|
|
167
|
+
for (const user of batch) users.push(user)
|
|
168
|
+
if (batch.length < 500) break
|
|
169
|
+
}
|
|
170
|
+
return users
|
|
171
|
+
})
|
|
172
|
+
|
|
132
173
|
return ClockifyApiClient.of({
|
|
133
174
|
getUser: () => api.getLoggedUser(undefined),
|
|
175
|
+
getWorkspaceUsers,
|
|
176
|
+
getWorkspaceUsersPage,
|
|
134
177
|
getWorkspaces: () => api.getWorkspacesOfUser(undefined),
|
|
135
178
|
getProjects,
|
|
136
179
|
getProjectByName: (workspaceId, name) =>
|
|
@@ -146,6 +189,7 @@ export class ClockifyApiClient extends Context.Service<ClockifyApiClient, Clocki
|
|
|
146
189
|
params: {
|
|
147
190
|
...(params?.start !== undefined ? { start: params.start } : {}),
|
|
148
191
|
...(params?.end !== undefined ? { end: params.end } : {}),
|
|
192
|
+
...(params?.hydrated === undefined ? {} : { hydrated: params.hydrated }),
|
|
149
193
|
...(params?.page !== undefined ? { page: params.page } : {}),
|
|
150
194
|
...(params?.pageSize !== undefined ? { "page-size": params.pageSize } : {})
|
|
151
195
|
}
|
|
@@ -165,7 +209,12 @@ export class ClockifyApiClient extends Context.Service<ClockifyApiClient, Clocki
|
|
|
165
209
|
: Effect.succeed(existing)
|
|
166
210
|
})
|
|
167
211
|
),
|
|
168
|
-
getTimeEntry: (workspaceId, timeEntryId) =>
|
|
212
|
+
getTimeEntry: (workspaceId, timeEntryId, params) =>
|
|
213
|
+
api.getTimeEntry(workspaceId, timeEntryId, {
|
|
214
|
+
params: {
|
|
215
|
+
...(params?.hydrated === undefined ? {} : { hydrated: params.hydrated })
|
|
216
|
+
}
|
|
217
|
+
}),
|
|
169
218
|
deleteTimeEntry: (workspaceId, timeEntryId) => api.deleteTimeEntry(workspaceId, timeEntryId, undefined),
|
|
170
219
|
updateTimeEntry: (workspaceId, timeEntryId, payload) =>
|
|
171
220
|
api.updateTimeEntry(workspaceId, timeEntryId, { payload })
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type {
|
|
|
16
16
|
AuthenticatedClockifyApi,
|
|
17
17
|
CreateTimeEntryParams,
|
|
18
18
|
GetTimeEntriesParams,
|
|
19
|
+
GetTimeEntryParams,
|
|
19
20
|
Project,
|
|
20
21
|
StopTimeEntryParams,
|
|
21
22
|
Tag,
|
|
@@ -23,7 +24,8 @@ export type {
|
|
|
23
24
|
TimeInterval,
|
|
24
25
|
UpdateTimeEntryParams,
|
|
25
26
|
User,
|
|
26
|
-
Workspace
|
|
27
|
+
Workspace,
|
|
28
|
+
WorkspaceUser
|
|
27
29
|
} from "./ClockifyApiClient.js"
|
|
28
30
|
|
|
29
31
|
export { ClockifyApiConfig, type ClockifyApiConfigShape } from "./ClockifyApiConfig.js"
|
|
@@ -80,6 +80,107 @@ describe("ClockifyApiClient", () => {
|
|
|
80
80
|
)
|
|
81
81
|
})
|
|
82
82
|
|
|
83
|
+
it.effect("requests hydrated time-entry details when required by the caller", () => {
|
|
84
|
+
const requests: Array<HttpClientRequest.HttpClientRequest> = []
|
|
85
|
+
return Effect.gen(function*() {
|
|
86
|
+
const client = yield* ClockifyApiClient
|
|
87
|
+
const entry = yield* client.getTimeEntry("workspace-1", "entry-1", { hydrated: true })
|
|
88
|
+
yield* client.getTimeEntry("workspace-1", "entry-1")
|
|
89
|
+
yield* client.getTimeEntry("workspace-1", "entry-1", { hydrated: false })
|
|
90
|
+
expect(entry.id).toBe("entry-1")
|
|
91
|
+
expect(new Map(requests[0]?.urlParams ?? []).get("hydrated")).toBe("true")
|
|
92
|
+
expect(new Map(requests[1]?.urlParams ?? []).has("hydrated")).toBe(false)
|
|
93
|
+
expect(new Map(requests[2]?.urlParams ?? []).get("hydrated")).toBe("false")
|
|
94
|
+
}).pipe(
|
|
95
|
+
Effect.provide(clientLayer({
|
|
96
|
+
status: 200,
|
|
97
|
+
body: {
|
|
98
|
+
id: "entry-1",
|
|
99
|
+
workspaceId: "workspace-1",
|
|
100
|
+
userId: "user-1",
|
|
101
|
+
description: "Review payment safeguards",
|
|
102
|
+
billable: true,
|
|
103
|
+
customFieldValues: [],
|
|
104
|
+
projectId: "project-1",
|
|
105
|
+
taskId: "task-1",
|
|
106
|
+
tagIds: ["delivery"],
|
|
107
|
+
timeInterval: {
|
|
108
|
+
start: "2026-07-11T08:00:00Z",
|
|
109
|
+
end: "2026-07-11T09:00:00Z",
|
|
110
|
+
duration: "PT1H"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}, requests))
|
|
114
|
+
)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it.effect("forwards hydration when listing canonical time-entry snapshots", () => {
|
|
118
|
+
const requests: Array<HttpClientRequest.HttpClientRequest> = []
|
|
119
|
+
return Effect.gen(function*() {
|
|
120
|
+
const client = yield* ClockifyApiClient
|
|
121
|
+
yield* client.getTimeEntries("workspace-1", "user-1", {
|
|
122
|
+
hydrated: true,
|
|
123
|
+
page: 2,
|
|
124
|
+
pageSize: 10
|
|
125
|
+
})
|
|
126
|
+
expect(new Map(requests[0]?.urlParams ?? []).get("hydrated")).toBe("true")
|
|
127
|
+
expect(new Map(requests[0]?.urlParams ?? []).get("page")).toBe("2")
|
|
128
|
+
expect(new Map(requests[0]?.urlParams ?? []).get("page-size")).toBe("10")
|
|
129
|
+
}).pipe(
|
|
130
|
+
Effect.provide(clientLayer({ status: 200, body: [] }, requests))
|
|
131
|
+
)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it.effect("pages through the complete workspace user directory", () => {
|
|
135
|
+
const requests: Array<HttpClientRequest.HttpClientRequest> = []
|
|
136
|
+
const firstPage = Array.from({ length: 500 }, (_, index) => ({
|
|
137
|
+
id: `user-${index}`,
|
|
138
|
+
name: `User ${index}`,
|
|
139
|
+
email: `user-${index}@example.test`,
|
|
140
|
+
status: "ACTIVE"
|
|
141
|
+
}))
|
|
142
|
+
const layer = ClockifyApiClient.layer.pipe(
|
|
143
|
+
Layer.provide(Layer.succeed(ClockifyApiConfig, {
|
|
144
|
+
apiKey: Redacted.make("secret"),
|
|
145
|
+
workspaceId: "workspace-1",
|
|
146
|
+
userId: "user-1",
|
|
147
|
+
baseUrl: "https://clockify.test/api"
|
|
148
|
+
})),
|
|
149
|
+
Layer.provide(Layer.succeed(
|
|
150
|
+
HttpClient.HttpClient,
|
|
151
|
+
HttpClient.make((request) =>
|
|
152
|
+
Effect.sync(() => {
|
|
153
|
+
requests.push(request)
|
|
154
|
+
const body = requests.length <= 20
|
|
155
|
+
? firstPage
|
|
156
|
+
: [{ id: "configured-user", name: "Configured User", email: "configured@example.test", status: "ACTIVE" }]
|
|
157
|
+
return HttpClientResponse.fromWeb(
|
|
158
|
+
request,
|
|
159
|
+
new Response(JSON.stringify(body), {
|
|
160
|
+
status: 200,
|
|
161
|
+
headers: { "content-type": "application/json" }
|
|
162
|
+
})
|
|
163
|
+
)
|
|
164
|
+
})
|
|
165
|
+
)
|
|
166
|
+
))
|
|
167
|
+
)
|
|
168
|
+
return Effect.gen(function*() {
|
|
169
|
+
const client = yield* ClockifyApiClient
|
|
170
|
+
if (client.getWorkspaceUsers === undefined) return assert.fail("expected workspace user discovery")
|
|
171
|
+
const users = yield* client.getWorkspaceUsers("workspace-1")
|
|
172
|
+
expect(users).toHaveLength(10_001)
|
|
173
|
+
expect(users.at(-1)?.id).toBe("configured-user")
|
|
174
|
+
expect(requests).toHaveLength(21)
|
|
175
|
+
expect(new Map(requests[0]?.urlParams ?? []).get("page")).toBe("1")
|
|
176
|
+
expect(new Map(requests[20]?.urlParams ?? []).get("page")).toBe("21")
|
|
177
|
+
expect(new Map(requests[0]?.urlParams ?? []).get("account-statuses")).toBe(
|
|
178
|
+
"ACTIVE,PENDING_EMAIL_VERIFICATION,DELETED,NOT_REGISTERED,LIMITED,LIMITED_DELETED"
|
|
179
|
+
)
|
|
180
|
+
expect(new Map(requests[0]?.urlParams ?? []).get("memberships")).toBe("ALL")
|
|
181
|
+
}).pipe(Effect.provide(layer))
|
|
182
|
+
})
|
|
183
|
+
|
|
83
184
|
it.effect("decodes a created time entry whose optional id references are null", () => {
|
|
84
185
|
const requests: Array<HttpClientRequest.HttpClientRequest> = []
|
|
85
186
|
return Effect.gen(function*() {
|