@alexisapp/leave-core 0.0.1-beta.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/README.md +260 -0
- package/dist/chunk-P5WZALLT.mjs +1633 -0
- package/dist/chunk-R7NHFDIU.mjs +53 -0
- package/dist/chunk-TUQKZ7GW.mjs +207 -0
- package/dist/chunk-VS74AXZ6.mjs +70 -0
- package/dist/components/index.d.ts +11 -0
- package/dist/components/index.mjs +23 -0
- package/dist/domain/index.d.ts +2 -0
- package/dist/domain/index.mjs +0 -0
- package/dist/en-GB-TSTNTOGN.mjs +81 -0
- package/dist/forms/index.d.ts +2 -0
- package/dist/forms/index.mjs +0 -0
- package/dist/graphql-BI4OTV8N.d.ts +1814 -0
- package/dist/hooks/index.d.ts +50 -0
- package/dist/hooks/index.mjs +106 -0
- package/dist/i18n/index.d.ts +18 -0
- package/dist/i18n/index.mjs +16 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.mjs +109 -0
- package/dist/leaveStatusUtils-C26heVdh.d.ts +11 -0
- package/dist/mutations/index.d.ts +2 -0
- package/dist/mutations/index.mjs +0 -0
- package/dist/queries/index.d.ts +489 -0
- package/dist/queries/index.mjs +15 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/index.mjs +0 -0
- package/dist/utils/index.d.ts +40 -0
- package/dist/utils/index.mjs +53 -0
- package/package.json +94 -0
- package/src/client/createKyInstance.ts +34 -0
- package/src/client/execute.ts +153 -0
- package/src/client/index.ts +4 -0
- package/src/client/initializeClient.ts +48 -0
- package/src/client/resetClient.ts +10 -0
- package/src/client/types.ts +12 -0
- package/src/components/AsyncBoundary.tsx +29 -0
- package/src/components/index.ts +1 -0
- package/src/domain/index.ts +2 -0
- package/src/errors/AuthError.ts +12 -0
- package/src/errors/DomainError.ts +15 -0
- package/src/errors/GraphQLError.ts +16 -0
- package/src/errors/LeaveError.ts +13 -0
- package/src/errors/NetworkError.ts +12 -0
- package/src/errors/classifyError.ts +46 -0
- package/src/errors/errorMessages.ts +69 -0
- package/src/errors/index.ts +13 -0
- package/src/forms/index.ts +2 -0
- package/src/graphql/codegen-gateway.ts +26 -0
- package/src/graphql/codegen-hr-core.ts +31 -0
- package/src/graphql/generated-gateway/fragment-masking.ts +84 -0
- package/src/graphql/generated-gateway/gql.ts +140 -0
- package/src/graphql/generated-gateway/graphql.ts +10828 -0
- package/src/graphql/generated-gateway/index.ts +2 -0
- package/src/graphql/generated-hr-core/fragment-masking.ts +84 -0
- package/src/graphql/generated-hr-core/gql.ts +185 -0
- package/src/graphql/generated-hr-core/graphql.ts +19385 -0
- package/src/graphql/generated-hr-core/index.ts +2 -0
- package/src/graphql/index.ts +278 -0
- package/src/graphql/operations/gateway/leave-change/mutations.graphql +74 -0
- package/src/graphql/operations/gateway/leave-change/queries.graphql +51 -0
- package/src/graphql/operations/gateway/leave-policy-employee-reference/mutations.graphql +26 -0
- package/src/graphql/operations/gateway/leave-self-certified/mutations.graphql +45 -0
- package/src/graphql/operations/gateway/leave-self-certified/queries.graphql +80 -0
- package/src/graphql/operations/gateway/leave-type-code/mutations.graphql +25 -0
- package/src/graphql/operations/gateway/self-certified-policy/mutations.graphql +29 -0
- package/src/graphql/operations/gateway/self-certified-policy/queries.graphql +34 -0
- package/src/graphql/operations/gateway/time-bank/mutations.graphql +23 -0
- package/src/graphql/operations/gateway/time-bank/queries.graphql +5 -0
- package/src/graphql/operations/gateway/time-off-settings/mutations.graphql +19 -0
- package/src/graphql/operations/gateway/time-off-settings/queries.graphql +15 -0
- package/src/graphql/operations/gateway/user/queries.graphql +11 -0
- package/src/graphql/operations/hr-core/balance/mutations.graphql +34 -0
- package/src/graphql/operations/hr-core/balance/queries.graphql +21 -0
- package/src/graphql/operations/hr-core/employee/queries.graphql +27 -0
- package/src/graphql/operations/hr-core/employment/queries.graphql +40 -0
- package/src/graphql/operations/hr-core/file/mutations.graphql +15 -0
- package/src/graphql/operations/hr-core/group/queries.graphql +13 -0
- package/src/graphql/operations/hr-core/leave/mutations.graphql +68 -0
- package/src/graphql/operations/hr-core/leave/queries.graphql +150 -0
- package/src/graphql/operations/hr-core/leave-type/queries.graphql +33 -0
- package/src/graphql/operations/hr-core/member/queries.graphql +58 -0
- package/src/graphql/operations/hr-core/office/queries.graphql +26 -0
- package/src/graphql/operations/hr-core/policy/mutations.graphql +43 -0
- package/src/graphql/operations/hr-core/policy/queries.graphql +46 -0
- package/src/graphql/operations/hr-core/scope/mutations.graphql +19 -0
- package/src/graphql/operations/hr-core/team/queries.graphql +14 -0
- package/src/graphql/operations/hr-core/user/queries.graphql +37 -0
- package/src/graphql/operations/hr-core/work-calendar/queries.graphql +60 -0
- package/src/graphql/operations/hr-core/work-week/queries.graphql +139 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useBalance.ts +58 -0
- package/src/hooks/useCurrentEmployeeId.ts +15 -0
- package/src/hooks/useLeaveList.ts +91 -0
- package/src/i18n/index.ts +2 -0
- package/src/i18n/instance.ts +52 -0
- package/src/i18n/locale.ts +23 -0
- package/src/i18n/translations/en-GB.json +67 -0
- package/src/index.ts +19 -0
- package/src/mutations/index.ts +2 -0
- package/src/queries/employeeQueryFactory.ts +97 -0
- package/src/queries/index.ts +5 -0
- package/src/queries/leaveQueryFactory.ts +171 -0
- package/src/queries/policyQueryFactory.ts +87 -0
- package/src/queries/settingsQueryFactory.ts +31 -0
- package/src/queries/userQueryFactory.ts +13 -0
- package/src/stores/index.ts +2 -0
- package/src/utils/__tests__/formatDateRangeUtils.test.ts +61 -0
- package/src/utils/__tests__/leaveStatusUtils.test.ts +27 -0
- package/src/utils/__tests__/splitLeaveSectionsUtils.test.ts +71 -0
- package/src/utils/formatDateRangeUtils.ts +71 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/leaveStatusUtils.ts +39 -0
- package/src/utils/splitLeaveSectionsUtils.ts +46 -0
- package/src/utils/typeSafeUtils.ts +4 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { D as DisplayStatus } from '../leaveStatusUtils-C26heVdh.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the current user's employeeId from the Gateway `me` query.
|
|
5
|
+
*/
|
|
6
|
+
declare function useCurrentEmployeeId(): string;
|
|
7
|
+
|
|
8
|
+
interface LeaveListItem {
|
|
9
|
+
id: string;
|
|
10
|
+
typeName: string;
|
|
11
|
+
displayStatus: DisplayStatus;
|
|
12
|
+
localStartDate: string;
|
|
13
|
+
localEndDate: string | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Fetches and merges all leave data sources into a unified list
|
|
17
|
+
* split into upcoming and history sections.
|
|
18
|
+
*
|
|
19
|
+
* Resolves the current employee internally — no args needed.
|
|
20
|
+
*
|
|
21
|
+
* Data sources:
|
|
22
|
+
* 1. Standard leaves (HR Core) — has type.name directly
|
|
23
|
+
* 2. Self-certified leaves (Gateway) — needs typeId→typeName join
|
|
24
|
+
* 3. Leave changes (Gateway) — for status overrides (pending change/revoke)
|
|
25
|
+
* 4. Employee leave types (HR Core) — provides typeId→typeName mapping
|
|
26
|
+
*/
|
|
27
|
+
declare function useLeaveList(): {
|
|
28
|
+
upcoming: LeaveListItem[];
|
|
29
|
+
history: LeaveListItem[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
interface BalanceData {
|
|
33
|
+
remaining: number;
|
|
34
|
+
spent: number;
|
|
35
|
+
saved: number | null;
|
|
36
|
+
unpaid: number | null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Fetches the current employee's vacation balance and policy,
|
|
40
|
+
* returning normalized tile values.
|
|
41
|
+
*
|
|
42
|
+
* Returns `null` when no balance data exists.
|
|
43
|
+
*
|
|
44
|
+
* Norwegian policies (`includeUnusedDaysInNewBalance`) use
|
|
45
|
+
* `balanceAmountPlusUnpaidLeft` for remaining and omit saved/unpaid
|
|
46
|
+
* (returned as `null`).
|
|
47
|
+
*/
|
|
48
|
+
declare function useBalance(): BalanceData | null;
|
|
49
|
+
|
|
50
|
+
export { type BalanceData, type LeaveListItem, useBalance, useCurrentEmployeeId, useLeaveList };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLocalToday,
|
|
3
|
+
isDefined,
|
|
4
|
+
resolveDisplayStatus,
|
|
5
|
+
splitLeaveSections
|
|
6
|
+
} from "../chunk-R7NHFDIU.mjs";
|
|
7
|
+
import {
|
|
8
|
+
leaveQueries,
|
|
9
|
+
policyQueries,
|
|
10
|
+
userQueries
|
|
11
|
+
} from "../chunk-P5WZALLT.mjs";
|
|
12
|
+
import "../chunk-TUQKZ7GW.mjs";
|
|
13
|
+
|
|
14
|
+
// src/hooks/useCurrentEmployeeId.ts
|
|
15
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
16
|
+
function useCurrentEmployeeId() {
|
|
17
|
+
const { data } = useSuspenseQuery(userQueries.me());
|
|
18
|
+
const employeeId = data.me.membership?.employeeId;
|
|
19
|
+
if (!employeeId) {
|
|
20
|
+
throw new Error("Current user has no employeeId");
|
|
21
|
+
}
|
|
22
|
+
return employeeId;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/hooks/useLeaveList.ts
|
|
26
|
+
import { useSuspenseQuery as useSuspenseQuery2 } from "@tanstack/react-query";
|
|
27
|
+
import { useMemo } from "react";
|
|
28
|
+
function useLeaveList() {
|
|
29
|
+
const employeeId = useCurrentEmployeeId();
|
|
30
|
+
const { data: standardData } = useSuspenseQuery2(leaveQueries.listVisible());
|
|
31
|
+
const { data: selfCertifiedData } = useSuspenseQuery2(leaveQueries.selfCertifiedListVisible());
|
|
32
|
+
const { data: changesData } = useSuspenseQuery2(
|
|
33
|
+
leaveQueries.approvalQueue({ filters: { status: { eq: "PENDING" } } })
|
|
34
|
+
);
|
|
35
|
+
const { data: leaveTypesData } = useSuspenseQuery2(policyQueries.employeeLeaveTypes(employeeId));
|
|
36
|
+
return useMemo(() => {
|
|
37
|
+
const typeMap = /* @__PURE__ */ new Map();
|
|
38
|
+
for (const lt of leaveTypesData.employeeLeaveTypeList) {
|
|
39
|
+
if (lt?.id) {
|
|
40
|
+
typeMap.set(lt.id, lt.name);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const changeMap = /* @__PURE__ */ new Map();
|
|
44
|
+
for (const change of changesData.leaveChangeList.data) {
|
|
45
|
+
const changeType = change.type;
|
|
46
|
+
if (changeType === "UPDATE" || changeType === "REVOKE") {
|
|
47
|
+
for (const leaveId of change.leaveIds) {
|
|
48
|
+
changeMap.set(leaveId, changeType);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const standardItems = standardData.leaveListVisible.filter(isDefined).map((item) => ({
|
|
53
|
+
id: item.id ?? "",
|
|
54
|
+
typeName: item.type.name,
|
|
55
|
+
displayStatus: resolveDisplayStatus(item.id ?? "", item.status, changeMap),
|
|
56
|
+
localStartDate: item.localStartDate,
|
|
57
|
+
localEndDate: item.localEndDate
|
|
58
|
+
}));
|
|
59
|
+
const selfCertifiedItems = selfCertifiedData.leaveSelfCertifiedListVisible.data.filter((item) => item.status !== "MIGRATED").map((item) => ({
|
|
60
|
+
id: item.id,
|
|
61
|
+
typeName: typeMap.get(item.typeId) ?? item.typeId,
|
|
62
|
+
displayStatus: resolveDisplayStatus(item.id, item.status, changeMap),
|
|
63
|
+
localStartDate: item.localStartDate,
|
|
64
|
+
localEndDate: item.localEndDate ?? null
|
|
65
|
+
}));
|
|
66
|
+
const allItems = [...standardItems, ...selfCertifiedItems];
|
|
67
|
+
const today = getLocalToday();
|
|
68
|
+
return splitLeaveSections(allItems, today);
|
|
69
|
+
}, [standardData, selfCertifiedData, changesData, leaveTypesData]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/hooks/useBalance.ts
|
|
73
|
+
import { useSuspenseQuery as useSuspenseQuery3 } from "@tanstack/react-query";
|
|
74
|
+
function useBalance() {
|
|
75
|
+
const employeeId = useCurrentEmployeeId();
|
|
76
|
+
const { data: balanceData } = useSuspenseQuery3(
|
|
77
|
+
leaveQueries.balanceList({
|
|
78
|
+
filters: { employeeId: { eq: employeeId } }
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
const rows = (balanceData.employeeVacationBalanceList?.rows ?? []).filter(isDefined);
|
|
82
|
+
const balance = rows[0];
|
|
83
|
+
const leavePolicyId = balance?.leavePolicyId ?? "";
|
|
84
|
+
const { data: policyData } = useSuspenseQuery3(policyQueries.detail(leavePolicyId));
|
|
85
|
+
if (!balance) return null;
|
|
86
|
+
const isNorwegian = policyData.leavePolicy?.allowance?.includeUnusedDaysInNewBalance === true;
|
|
87
|
+
if (isNorwegian) {
|
|
88
|
+
return {
|
|
89
|
+
remaining: balance.balanceAmountPlusUnpaidLeft ?? 0,
|
|
90
|
+
spent: balance.spentAmount ?? 0,
|
|
91
|
+
saved: null,
|
|
92
|
+
unpaid: null
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
remaining: balance.balanceAmount ?? 0,
|
|
97
|
+
spent: balance.spentAmount ?? 0,
|
|
98
|
+
saved: balance.savedDaysLeft ?? 0,
|
|
99
|
+
unpaid: balance.balanceAmountUnpaidLeft ?? 0
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export {
|
|
103
|
+
useBalance,
|
|
104
|
+
useCurrentEmployeeId,
|
|
105
|
+
useLeaveList
|
|
106
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { i18n } from 'i18next';
|
|
2
|
+
|
|
3
|
+
declare function initLeaveI18n(locale?: string): Promise<i18n>;
|
|
4
|
+
declare function getLeaveI18n(): i18n;
|
|
5
|
+
declare function resetLeaveI18n(): void;
|
|
6
|
+
|
|
7
|
+
declare const Locale: {
|
|
8
|
+
readonly EN: "en-GB";
|
|
9
|
+
readonly SV: "sv-SE";
|
|
10
|
+
readonly NB: "nb-NO";
|
|
11
|
+
readonly DA: "da-DK";
|
|
12
|
+
readonly FI: "fi-FI";
|
|
13
|
+
};
|
|
14
|
+
type Locale = (typeof Locale)[keyof typeof Locale];
|
|
15
|
+
declare const supportedLocales: readonly Locale[];
|
|
16
|
+
declare function resolveLocale(input: string): Locale;
|
|
17
|
+
|
|
18
|
+
export { Locale, getLeaveI18n, initLeaveI18n, resetLeaveI18n, resolveLocale, supportedLocales };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Locale,
|
|
3
|
+
getLeaveI18n,
|
|
4
|
+
initLeaveI18n,
|
|
5
|
+
resetLeaveI18n,
|
|
6
|
+
resolveLocale,
|
|
7
|
+
supportedLocales
|
|
8
|
+
} from "../chunk-VS74AXZ6.mjs";
|
|
9
|
+
export {
|
|
10
|
+
Locale,
|
|
11
|
+
getLeaveI18n,
|
|
12
|
+
initLeaveI18n,
|
|
13
|
+
resetLeaveI18n,
|
|
14
|
+
resolveLocale,
|
|
15
|
+
supportedLocales
|
|
16
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { ag as TypedDocumentString, ah as TypedDocumentString$1 } from './graphql-BI4OTV8N.js';
|
|
2
|
+
export { Locale, getLeaveI18n, initLeaveI18n, resetLeaveI18n, resolveLocale, supportedLocales } from './i18n/index.js';
|
|
3
|
+
import { HTTPError } from 'ky';
|
|
4
|
+
import '@graphql-typed-document-node/core';
|
|
5
|
+
import 'i18next';
|
|
6
|
+
|
|
7
|
+
interface ClientConfig {
|
|
8
|
+
/** Base proxy URL. Core appends /v2/graphql (gateway) and /graphql (hrCore) internally. */
|
|
9
|
+
endpoint: string;
|
|
10
|
+
/** Override base URL for gateway only (local dev with split services). Falls back to `endpoint`. */
|
|
11
|
+
gatewayEndpoint?: string | undefined;
|
|
12
|
+
/** Mobile only — returns Auth0 JWT. Web BFF handles auth transparently. */
|
|
13
|
+
getToken?: (() => Promise<string | null>) | undefined;
|
|
14
|
+
/** Mobile only — called on 401/403 before throwing. Shell handles 401 redirect on web. */
|
|
15
|
+
onAuthError?: (() => void) | undefined;
|
|
16
|
+
/** Hardcoded Alexis token for dev. Platform reads from env, core never touches process.env. */
|
|
17
|
+
devToken?: string | undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates a fresh ky instance. Throws if called twice without resetClient().
|
|
22
|
+
* Called in useEffect with resetClient() in cleanup.
|
|
23
|
+
*/
|
|
24
|
+
declare function initializeClient(config: ClientConfig): void;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resets module-scoped singleton. Used in:
|
|
28
|
+
* - useEffect cleanup on unmount (prevents stale closure on MF remount)
|
|
29
|
+
* - afterEach() in tests (prevents cross-test state pollution)
|
|
30
|
+
*/
|
|
31
|
+
declare function resetClient(): void;
|
|
32
|
+
|
|
33
|
+
interface ExecuteProps<TQuery, TVariables> {
|
|
34
|
+
query: TQuery;
|
|
35
|
+
variables: TVariables extends Record<string, never> ? unknown : TVariables | undefined;
|
|
36
|
+
signal?: AbortSignal | undefined;
|
|
37
|
+
}
|
|
38
|
+
type ExecuteGatewayProps<TResult, TVariables> = ExecuteProps<TypedDocumentString<TResult, TVariables>, TVariables>;
|
|
39
|
+
type ExecuteHrCoreProps<TResult, TVariables> = ExecuteProps<TypedDocumentString$1<TResult, TVariables>, TVariables>;
|
|
40
|
+
/**
|
|
41
|
+
* Typed GraphQL executors. Classifies all errors at this boundary (§12).
|
|
42
|
+
* Auth errors (401/403): zero retry, immediate onAuthError() callback (§4).
|
|
43
|
+
*
|
|
44
|
+
* - execute.gateway() — new leave service (default for most operations)
|
|
45
|
+
* - execute.hrCore() — legacy HR Core (employee/policy lookups)
|
|
46
|
+
*/
|
|
47
|
+
declare const execute: {
|
|
48
|
+
readonly gateway: <TResult, TVariables>({ query, variables, signal, }: ExecuteGatewayProps<TResult, TVariables>) => Promise<TResult>;
|
|
49
|
+
readonly hrCore: <TResult, TVariables>({ query, variables, signal, }: ExecuteHrCoreProps<TResult, TVariables>) => Promise<TResult>;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Base error class for all leave management errors.
|
|
54
|
+
* All domain-specific errors extend this class.
|
|
55
|
+
*/
|
|
56
|
+
declare class LeaveError extends Error {
|
|
57
|
+
readonly code: string;
|
|
58
|
+
constructor(code: string, message: string);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Authentication/authorization error — 401 or 403.
|
|
63
|
+
* Never retried. Immediately escalated via onAuthError() callback.
|
|
64
|
+
*/
|
|
65
|
+
declare class AuthError extends LeaveError {
|
|
66
|
+
readonly statusCode: 401 | 403;
|
|
67
|
+
constructor(statusCode: 401 | 403);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Server returned errors[] in the GraphQL response body.
|
|
72
|
+
*/
|
|
73
|
+
declare class GraphQLError extends LeaveError {
|
|
74
|
+
readonly errors: Array<{
|
|
75
|
+
message: string;
|
|
76
|
+
extensions?: Record<string, unknown>;
|
|
77
|
+
}>;
|
|
78
|
+
constructor(errors: Array<{
|
|
79
|
+
message: string;
|
|
80
|
+
extensions?: Record<string, unknown>;
|
|
81
|
+
}>);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Fetch failed, timeout, or no connectivity.
|
|
86
|
+
* Also used for non-auth HTTP errors that reach classifyError after ky retries are exhausted.
|
|
87
|
+
*/
|
|
88
|
+
declare class NetworkError extends LeaveError {
|
|
89
|
+
readonly cause: unknown;
|
|
90
|
+
constructor(cause: unknown);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Business rule violation returned by the server
|
|
95
|
+
* (e.g., insufficient leave balance, blackout period).
|
|
96
|
+
*/
|
|
97
|
+
declare class DomainError extends LeaveError {
|
|
98
|
+
readonly domainCode: string;
|
|
99
|
+
constructor(domainCode: string, message: string);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Classifies an unknown error into a LeaveError subclass.
|
|
104
|
+
* Idempotent — if the error is already a LeaveError, passes through unchanged.
|
|
105
|
+
*
|
|
106
|
+
* Classification order:
|
|
107
|
+
* 1. LeaveError passthrough (idempotent)
|
|
108
|
+
* 2. AbortError → ABORT_ERROR (no-op in UI — no toast, no error boundary)
|
|
109
|
+
* 3. ky HTTPError 401/403 → AuthError
|
|
110
|
+
* 4. ky HTTPError other → NetworkError (retries already exhausted by ky)
|
|
111
|
+
* 5. TypeError → NetworkError (fetch throws TypeError on DNS failure, CORS, network-down)
|
|
112
|
+
* 6. Fallback → UNKNOWN_ERROR
|
|
113
|
+
*/
|
|
114
|
+
declare function classifyError(error: unknown): LeaveError;
|
|
115
|
+
|
|
116
|
+
declare enum ErrorCode {
|
|
117
|
+
UNEXPECTED_ERROR = "UNEXPECTED_ERROR",
|
|
118
|
+
CONNECTION_FAILURE = "CONNECTION_FAILURE",
|
|
119
|
+
BAD_REQUEST = "BAD_REQUEST",
|
|
120
|
+
NOT_FOUND = "NOT_FOUND",
|
|
121
|
+
SYSTEM_FAILURE = "SYSTEM_FAILURE",
|
|
122
|
+
UNAUTHORIZED = "UNAUTHORIZED",
|
|
123
|
+
FORBIDDEN = "FORBIDDEN"
|
|
124
|
+
}
|
|
125
|
+
declare function getErrorCode(error: unknown): ErrorCode;
|
|
126
|
+
declare function isHttpError(error: unknown): error is HTTPError;
|
|
127
|
+
declare function isRetryable(error: unknown): boolean;
|
|
128
|
+
declare function getErrorMessage(error: unknown): {
|
|
129
|
+
title: string;
|
|
130
|
+
description: string;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export { AuthError, type ClientConfig, DomainError, ErrorCode, GraphQLError, LeaveError, NetworkError, classifyError, execute, getErrorCode, getErrorMessage, initializeClient, isHttpError, isRetryable, resetClient };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthError,
|
|
3
|
+
GraphQLError,
|
|
4
|
+
LeaveError,
|
|
5
|
+
NetworkError,
|
|
6
|
+
classifyError,
|
|
7
|
+
execute,
|
|
8
|
+
initializeClient,
|
|
9
|
+
resetClient
|
|
10
|
+
} from "./chunk-TUQKZ7GW.mjs";
|
|
11
|
+
import {
|
|
12
|
+
Locale,
|
|
13
|
+
getLeaveI18n,
|
|
14
|
+
initLeaveI18n,
|
|
15
|
+
resetLeaveI18n,
|
|
16
|
+
resolveLocale,
|
|
17
|
+
supportedLocales
|
|
18
|
+
} from "./chunk-VS74AXZ6.mjs";
|
|
19
|
+
|
|
20
|
+
// src/errors/DomainError.ts
|
|
21
|
+
var DomainError = class extends LeaveError {
|
|
22
|
+
constructor(domainCode, message) {
|
|
23
|
+
super("DOMAIN_ERROR", message);
|
|
24
|
+
this.domainCode = domainCode;
|
|
25
|
+
this.name = "DomainError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/errors/errorMessages.ts
|
|
30
|
+
import { HTTPError } from "ky";
|
|
31
|
+
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
|
|
32
|
+
ErrorCode2["UNEXPECTED_ERROR"] = "UNEXPECTED_ERROR";
|
|
33
|
+
ErrorCode2["CONNECTION_FAILURE"] = "CONNECTION_FAILURE";
|
|
34
|
+
ErrorCode2["BAD_REQUEST"] = "BAD_REQUEST";
|
|
35
|
+
ErrorCode2["NOT_FOUND"] = "NOT_FOUND";
|
|
36
|
+
ErrorCode2["SYSTEM_FAILURE"] = "SYSTEM_FAILURE";
|
|
37
|
+
ErrorCode2["UNAUTHORIZED"] = "UNAUTHORIZED";
|
|
38
|
+
ErrorCode2["FORBIDDEN"] = "FORBIDDEN";
|
|
39
|
+
return ErrorCode2;
|
|
40
|
+
})(ErrorCode || {});
|
|
41
|
+
var httpStatusToErrorCode = {
|
|
42
|
+
400: "BAD_REQUEST" /* BAD_REQUEST */,
|
|
43
|
+
401: "UNAUTHORIZED" /* UNAUTHORIZED */,
|
|
44
|
+
403: "FORBIDDEN" /* FORBIDDEN */,
|
|
45
|
+
404: "NOT_FOUND" /* NOT_FOUND */
|
|
46
|
+
};
|
|
47
|
+
function getErrorCode(error) {
|
|
48
|
+
if (error instanceof AuthError) {
|
|
49
|
+
return error.statusCode === 401 ? "UNAUTHORIZED" /* UNAUTHORIZED */ : "FORBIDDEN" /* FORBIDDEN */;
|
|
50
|
+
}
|
|
51
|
+
if (error instanceof NetworkError) {
|
|
52
|
+
return "CONNECTION_FAILURE" /* CONNECTION_FAILURE */;
|
|
53
|
+
}
|
|
54
|
+
if (error instanceof GraphQLError) {
|
|
55
|
+
return "SYSTEM_FAILURE" /* SYSTEM_FAILURE */;
|
|
56
|
+
}
|
|
57
|
+
if (error instanceof Error && "response" in error) {
|
|
58
|
+
const status = error.response?.status;
|
|
59
|
+
if (status != null) {
|
|
60
|
+
const mapped = httpStatusToErrorCode[status];
|
|
61
|
+
if (mapped != null) return mapped;
|
|
62
|
+
if (status >= 500) return "SYSTEM_FAILURE" /* SYSTEM_FAILURE */;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return "UNEXPECTED_ERROR" /* UNEXPECTED_ERROR */;
|
|
66
|
+
}
|
|
67
|
+
function isHttpError(error) {
|
|
68
|
+
return error instanceof HTTPError;
|
|
69
|
+
}
|
|
70
|
+
function isRetryable(error) {
|
|
71
|
+
if (error instanceof NetworkError) return true;
|
|
72
|
+
if (error instanceof GraphQLError) return true;
|
|
73
|
+
if (error instanceof AuthError) return false;
|
|
74
|
+
if (error instanceof DomainError) return false;
|
|
75
|
+
if (error instanceof HTTPError) {
|
|
76
|
+
return error.response.status >= 500;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
function getErrorMessage(error) {
|
|
81
|
+
const code = getErrorCode(error);
|
|
82
|
+
const t = getLeaveI18n().t;
|
|
83
|
+
return {
|
|
84
|
+
title: t(`errors.${code}.title`),
|
|
85
|
+
description: t(`errors.${code}.description`)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
AuthError,
|
|
90
|
+
DomainError,
|
|
91
|
+
ErrorCode,
|
|
92
|
+
GraphQLError,
|
|
93
|
+
LeaveError,
|
|
94
|
+
Locale,
|
|
95
|
+
NetworkError,
|
|
96
|
+
classifyError,
|
|
97
|
+
execute,
|
|
98
|
+
getErrorCode,
|
|
99
|
+
getErrorMessage,
|
|
100
|
+
getLeaveI18n,
|
|
101
|
+
initLeaveI18n,
|
|
102
|
+
initializeClient,
|
|
103
|
+
isHttpError,
|
|
104
|
+
isRetryable,
|
|
105
|
+
resetClient,
|
|
106
|
+
resetLeaveI18n,
|
|
107
|
+
resolveLocale,
|
|
108
|
+
supportedLocales
|
|
109
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type DisplayStatus = 'APPROVED' | 'PENDING' | 'DENIED' | 'CANCELLED' | 'PENDING_CHANGES' | 'PENDING_REVOKE';
|
|
2
|
+
type LeaveChangeType = 'UPDATE' | 'REVOKE';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the display status for a leave item, applying change overrides.
|
|
5
|
+
*
|
|
6
|
+
* If the leave has a pending change (UPDATE or REVOKE), the display status
|
|
7
|
+
* is overridden to reflect the pending change instead of the leave's own status.
|
|
8
|
+
*/
|
|
9
|
+
declare function resolveDisplayStatus(leaveId: string, leaveStatus: string, changeMap: ReadonlyMap<string, LeaveChangeType>): DisplayStatus;
|
|
10
|
+
|
|
11
|
+
export { type DisplayStatus as D, type LeaveChangeType as L, resolveDisplayStatus as r };
|
|
File without changes
|