@sudobility/sudojo_client 0.0.90 → 0.0.92
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/hooks/use-sudojo-users.d.ts +1 -1
- package/dist/hooks/use-sudojo-users.d.ts.map +1 -1
- package/dist/hooks/use-sudojo-users.js +3 -3
- package/dist/hooks/use-sudojo-users.js.map +1 -1
- package/dist/network/sudojo-client.d.ts +1 -1
- package/dist/network/sudojo-client.d.ts.map +1 -1
- package/dist/network/sudojo-client.js +5 -2
- package/dist/network/sudojo-client.js.map +1 -1
- package/package.json +7 -7
|
@@ -2,5 +2,5 @@ import { UseQueryOptions, UseQueryResult } from "@tanstack/react-query";
|
|
|
2
2
|
import type { NetworkClient, UserInfoResponse } from "@sudobility/types";
|
|
3
3
|
import type { BaseResponse, SubscriptionResult } from "@sudobility/sudojo_types";
|
|
4
4
|
export declare const useSudojoUser: (networkClient: NetworkClient, baseUrl: string, token: string, userId: string, options?: Omit<UseQueryOptions<BaseResponse<UserInfoResponse>>, "queryKey" | "queryFn">) => UseQueryResult<BaseResponse<UserInfoResponse>>;
|
|
5
|
-
export declare const useSudojoUserSubscription: (networkClient: NetworkClient, baseUrl: string, token: string, userId: string, options?: Omit<UseQueryOptions<BaseResponse<SubscriptionResult>>, "queryKey" | "queryFn">) => UseQueryResult<BaseResponse<SubscriptionResult>>;
|
|
5
|
+
export declare const useSudojoUserSubscription: (networkClient: NetworkClient, baseUrl: string, token: string, userId: string, testMode?: boolean, options?: Omit<UseQueryOptions<BaseResponse<SubscriptionResult>>, "queryKey" | "queryFn">) => UseQueryResult<BaseResponse<SubscriptionResult>>;
|
|
6
6
|
//# sourceMappingURL=use-sudojo-users.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-sudojo-users.d.ts","sourceRoot":"","sources":["../../src/hooks/use-sudojo-users.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAwBlC,eAAO,MAAM,aAAa,GACxB,eAAe,aAAa,EAC5B,SAAS,MAAM,EACf,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,UAAU,IAAI,CACZ,eAAe,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,EAC/C,UAAU,GAAG,SAAS,CACvB,KACA,cAAc,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAyB/C,CAAC;AAkBF,eAAO,MAAM,yBAAyB,GACpC,eAAe,aAAa,EAC5B,SAAS,MAAM,EACf,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,UAAU,IAAI,CACZ,eAAe,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,EACjD,UAAU,GAAG,SAAS,CACvB,KACA,cAAc,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAwBjD,CAAC"}
|
|
1
|
+
{"version":3,"file":"use-sudojo-users.d.ts","sourceRoot":"","sources":["../../src/hooks/use-sudojo-users.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAwBlC,eAAO,MAAM,aAAa,GACxB,eAAe,aAAa,EAC5B,SAAS,MAAM,EACf,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,UAAU,IAAI,CACZ,eAAe,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,EAC/C,UAAU,GAAG,SAAS,CACvB,KACA,cAAc,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAyB/C,CAAC;AAkBF,eAAO,MAAM,yBAAyB,GACpC,eAAe,aAAa,EAC5B,SAAS,MAAM,EACf,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,WAAW,OAAO,EAClB,UAAU,IAAI,CACZ,eAAe,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,EACjD,UAAU,GAAG,SAAS,CACvB,KACA,cAAc,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAwBjD,CAAC"}
|
|
@@ -20,11 +20,11 @@ export const useSudojoUser = (networkClient, baseUrl, token, userId, options) =>
|
|
|
20
20
|
enabled: isEnabled,
|
|
21
21
|
});
|
|
22
22
|
};
|
|
23
|
-
export const useSudojoUserSubscription = (networkClient, baseUrl, token, userId, options) => {
|
|
23
|
+
export const useSudojoUserSubscription = (networkClient, baseUrl, token, userId, testMode, options) => {
|
|
24
24
|
const client = useMemo(() => new SudojoClient(networkClient, baseUrl), [networkClient, baseUrl]);
|
|
25
25
|
const queryFn = useCallback(async () => {
|
|
26
|
-
return client.getUserSubscription(token, userId);
|
|
27
|
-
}, [client, token, userId]);
|
|
26
|
+
return client.getUserSubscription(token, userId, testMode);
|
|
27
|
+
}, [client, token, userId, testMode]);
|
|
28
28
|
const isEnabled = !!userId &&
|
|
29
29
|
!!token &&
|
|
30
30
|
(options?.enabled !== undefined ? options.enabled : true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-sudojo-users.js","sourceRoot":"","sources":["../../src/hooks/use-sudojo-users.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EACL,QAAQ,GAGT,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAqBxD,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,aAA4B,EAC5B,OAAe,EACf,KAAa,EACb,MAAc,EACd,OAGC,EAC+C,EAAE;IAClD,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,IAAI,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,EAC9C,CAAC,aAAa,EAAE,OAAO,CAAC,CACzB,CAAC;IAEF,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAE/B,EAAE;QACF,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5B,MAAM,SAAS,GACb,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,KAAK;QACP,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE5D,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QACvC,OAAO;QACP,SAAS,EAAE,WAAW,CAAC,IAAI;QAC3B,oBAAoB,EAAE,KAAK;QAC3B,GAAG,OAAO;QACV,OAAO,EAAE,SAAS;KACnB,CAAC,CAAC;AACL,CAAC,CAAC;AAkBF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,aAA4B,EAC5B,OAAe,EACf,KAAa,EACb,MAAc,EACd,OAGC,EACiD,EAAE;IACpD,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,IAAI,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,EAC9C,CAAC,aAAa,EAAE,OAAO,CAAC,CACzB,CAAC;IAEF,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAE/B,EAAE;QACF,OAAO,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"use-sudojo-users.js","sourceRoot":"","sources":["../../src/hooks/use-sudojo-users.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EACL,QAAQ,GAGT,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAqBxD,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,aAA4B,EAC5B,OAAe,EACf,KAAa,EACb,MAAc,EACd,OAGC,EAC+C,EAAE;IAClD,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,IAAI,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,EAC9C,CAAC,aAAa,EAAE,OAAO,CAAC,CACzB,CAAC;IAEF,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAE/B,EAAE;QACF,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5B,MAAM,SAAS,GACb,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,KAAK;QACP,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE5D,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QACvC,OAAO;QACP,SAAS,EAAE,WAAW,CAAC,IAAI;QAC3B,oBAAoB,EAAE,KAAK;QAC3B,GAAG,OAAO;QACV,OAAO,EAAE,SAAS;KACnB,CAAC,CAAC;AACL,CAAC,CAAC;AAkBF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,aAA4B,EAC5B,OAAe,EACf,KAAa,EACb,MAAc,EACd,QAAkB,EAClB,OAGC,EACiD,EAAE;IACpD,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,IAAI,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,EAC9C,CAAC,aAAa,EAAE,OAAO,CAAC,CACzB,CAAC;IAEF,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAE/B,EAAE;QACF,OAAO,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7D,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEtC,MAAM,SAAS,GACb,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,KAAK;QACP,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE5D,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC;QACnD,OAAO;QACP,SAAS,EAAE,WAAW,CAAC,iBAAiB;QACxC,GAAG,OAAO;QACV,OAAO,EAAE,SAAS;KACnB,CAAC,CAAC;AACL,CAAC,CAAC","sourcesContent":["/**\n * Hook for Sudojo users endpoints\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport {\n useQuery,\n UseQueryOptions,\n UseQueryResult,\n} from \"@tanstack/react-query\";\nimport type { NetworkClient, UserInfoResponse } from \"@sudobility/types\";\nimport type {\n BaseResponse,\n SubscriptionResult,\n} from \"@sudobility/sudojo_types\";\nimport { queryKeys } from \"./query-keys\";\nimport { STALE_TIMES } from \"./query-config\";\nimport { SudojoClient } from \"../network/sudojo-client\";\n\n/**\n * Hook to fetch user info including admin status.\n *\n * **Requires Firebase authentication.** The userId must match the\n * authenticated user's Firebase UID. The query is automatically disabled\n * when either token or userId is empty.\n *\n * Disables `refetchOnWindowFocus` to avoid unnecessary refetches since\n * admin status rarely changes.\n *\n * Stale time: {@link STALE_TIMES.USER} (5 minutes).\n *\n * @param networkClient - Network client for making HTTP requests\n * @param baseUrl - Base URL of the Sudojo API\n * @param token - Firebase access token (required)\n * @param userId - Firebase UID of the user to query\n * @param options - Additional TanStack Query options\n * @returns A UseQueryResult containing the UserInfoResponse\n */\nexport const useSudojoUser = (\n networkClient: NetworkClient,\n baseUrl: string,\n token: string,\n userId: string,\n options?: Omit<\n UseQueryOptions<BaseResponse<UserInfoResponse>>,\n \"queryKey\" | \"queryFn\"\n >,\n): UseQueryResult<BaseResponse<UserInfoResponse>> => {\n const client = useMemo(\n () => new SudojoClient(networkClient, baseUrl),\n [networkClient, baseUrl],\n );\n\n const queryFn = useCallback(async (): Promise<\n BaseResponse<UserInfoResponse>\n > => {\n return client.getUser(token, userId);\n }, [client, token, userId]);\n\n const isEnabled =\n !!userId &&\n !!token &&\n (options?.enabled !== undefined ? options.enabled : true);\n\n return useQuery({\n queryKey: queryKeys.sudojo.user(userId),\n queryFn,\n staleTime: STALE_TIMES.USER,\n refetchOnWindowFocus: false,\n ...options,\n enabled: isEnabled,\n });\n};\n\n/**\n * Hook to fetch user subscription status (via RevenueCat integration).\n *\n * **Requires Firebase authentication.** The query is automatically disabled\n * when either token or userId is empty. Uses a shorter stale time since\n * subscription status may change via in-app purchase flows.\n *\n * Stale time: {@link STALE_TIMES.USER_SUBSCRIPTION} (2 minutes).\n *\n * @param networkClient - Network client for making HTTP requests\n * @param baseUrl - Base URL of the Sudojo API\n * @param token - Firebase access token (required)\n * @param userId - Firebase UID of the user to query\n * @param options - Additional TanStack Query options\n * @returns A UseQueryResult containing the SubscriptionResult\n */\nexport const useSudojoUserSubscription = (\n networkClient: NetworkClient,\n baseUrl: string,\n token: string,\n userId: string,\n testMode?: boolean,\n options?: Omit<\n UseQueryOptions<BaseResponse<SubscriptionResult>>,\n \"queryKey\" | \"queryFn\"\n >,\n): UseQueryResult<BaseResponse<SubscriptionResult>> => {\n const client = useMemo(\n () => new SudojoClient(networkClient, baseUrl),\n [networkClient, baseUrl],\n );\n\n const queryFn = useCallback(async (): Promise<\n BaseResponse<SubscriptionResult>\n > => {\n return client.getUserSubscription(token, userId, testMode);\n }, [client, token, userId, testMode]);\n\n const isEnabled =\n !!userId &&\n !!token &&\n (options?.enabled !== undefined ? options.enabled : true);\n\n return useQuery({\n queryKey: queryKeys.sudojo.userSubscription(userId),\n queryFn,\n staleTime: STALE_TIMES.USER_SUBSCRIPTION,\n ...options,\n enabled: isEnabled,\n });\n};\n"]}
|
|
@@ -46,7 +46,7 @@ export declare class SudojoClient {
|
|
|
46
46
|
updateChallenge(token: string, uuid: string, data: ChallengeUpdateRequest): Promise<BaseResponse<Challenge>>;
|
|
47
47
|
deleteChallenge(token: string, uuid: string): Promise<BaseResponse<Challenge>>;
|
|
48
48
|
getUser(token: string, userId: string): Promise<BaseResponse<UserInfoResponse>>;
|
|
49
|
-
getUserSubscription(token: string, userId: string): Promise<BaseResponse<SubscriptionResult>>;
|
|
49
|
+
getUserSubscription(token: string, userId: string, testMode?: boolean): Promise<BaseResponse<SubscriptionResult>>;
|
|
50
50
|
getPracticeCounts(token: string): Promise<BaseResponse<TechniquePracticeCountItem[]>>;
|
|
51
51
|
getRandomPractice(token: string, technique: number): Promise<BaseResponse<TechniquePractice>>;
|
|
52
52
|
createPractice(token: string, data: TechniquePracticeCreateRequest): Promise<BaseResponse<TechniquePractice>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sudojo-client.d.ts","sourceRoot":"","sources":["../../src/network/sudojo-client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sudojo-client.d.ts","sourceRoot":"","sources":["../../src/network/sudojo-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -420,11 +420,14 @@ export class SudojoClient {
|
|
|
420
420
|
token,
|
|
421
421
|
});
|
|
422
422
|
}
|
|
423
|
-
async getUserSubscription(token, userId) {
|
|
423
|
+
async getUserSubscription(token, userId, testMode) {
|
|
424
424
|
if (!userId || userId.length === 0 || userId.length > 128) {
|
|
425
425
|
throw new Error(`Invalid userId: "${userId}". Expected 1-128 characters`);
|
|
426
426
|
}
|
|
427
|
-
|
|
427
|
+
const endpoint = testMode
|
|
428
|
+
? `${this.config.ENDPOINTS.USER_SUBSCRIPTIONS(userId)}?testMode=true`
|
|
429
|
+
: this.config.ENDPOINTS.USER_SUBSCRIPTIONS(userId);
|
|
430
|
+
return this.request(endpoint, {
|
|
428
431
|
token,
|
|
429
432
|
});
|
|
430
433
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sudojo-client.js","sourceRoot":"","sources":["../../src/network/sudojo-client.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NetworkClient, UserInfoResponse } from \"@sudobility/types\";\nimport {\n type BadgeDefinition,\n type BaseResponse,\n type Board,\n type BoardCountsData,\n type BoardCreateRequest,\n type BoardQueryParams,\n type BoardUpdateRequest,\n type Challenge,\n type ChallengeCreateRequest,\n type ChallengeQueryParams,\n type ChallengeUpdateRequest,\n type Daily,\n type DailyCreateRequest,\n type DailyUpdateRequest,\n type ExampleCountsData,\n type GameFinishRequest,\n type GameFinishResponse,\n type GameStartRequest,\n type GameStartResponse,\n type GamificationStats,\n type GenerateData,\n type GenerateOptions,\n type HealthCheckData,\n type HintAccessDeniedResponse,\n isValidUUID,\n type Learning,\n type LearningCreateRequest,\n type LearningQueryParams,\n type LearningUpdateRequest,\n type Level,\n type LevelCreateRequest,\n type LevelUpdateRequest,\n type Optional,\n type PointTransaction,\n type SolveData,\n type SolveOptions,\n type SubscriptionResult,\n type Technique,\n type TechniqueCreateRequest,\n type TechniqueExample,\n type TechniqueExampleCreateRequest,\n type TechniqueExampleQueryParams,\n type TechniquePractice,\n type TechniquePracticeCountItem,\n type TechniquePracticeCreateRequest,\n type TechniqueQueryParams,\n type TechniqueUpdateRequest,\n type ValidateData,\n type ValidateOptions,\n validateUUID,\n} from \"@sudobility/sudojo_types\";\nimport { HintAccessDeniedError } from \"../errors\";\n\n// Re-export option types for convenience\nexport type { SolveOptions, ValidateOptions, GenerateOptions };\n\n// =============================================================================\n// Solution Decryption\n// =============================================================================\n\nlet _solutionKey: CryptoKey | null = null;\n\n/**\n * Configure the symmetric key used to decrypt `solution` fields in API responses.\n * Call once at app startup with the hex-encoded 256-bit key.\n * If not called (or called with empty string), encrypted solutions pass through as-is.\n */\nexport async function configureSolutionKey(keyHex: string): Promise<void> {\n if (!keyHex) return;\n const hexPairs = keyHex.match(/.{2}/g);\n if (!hexPairs) return;\n const keyBytes = new Uint8Array(hexPairs.map((byte) => parseInt(byte, 16)));\n _solutionKey = await globalThis.crypto.subtle.importKey(\n \"raw\",\n keyBytes,\n \"AES-GCM\",\n false,\n [\"decrypt\"],\n );\n}\n\nasync function decryptSolution(encrypted: string): Promise<string> {\n if (!_solutionKey) return encrypted;\n\n const raw = globalThis.atob(encrypted.slice(4)); // strip \"enc:\" prefix\n const bytes = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) {\n bytes[i] = raw.charCodeAt(i);\n }\n\n const nonce = bytes.slice(0, 12);\n const ciphertextWithTag = bytes.slice(12);\n\n const decrypted = await globalThis.crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv: nonce },\n _solutionKey,\n ciphertextWithTag,\n );\n\n return new TextDecoder().decode(decrypted);\n}\n\nasync function decryptSolutionFields(data: unknown): Promise<unknown> {\n if (data === null || data === undefined) return data;\n\n if (Array.isArray(data)) {\n return Promise.all(data.map((item) => decryptSolutionFields(item)));\n }\n\n if (typeof data === \"object\") {\n const obj = data as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (\n key === \"solution\" &&\n typeof obj[key] === \"string\" &&\n (obj[key] as string).startsWith(\"enc:\")\n ) {\n result[key] = await decryptSolution(obj[key] as string);\n } else {\n result[key] = await decryptSolutionFields(obj[key]);\n }\n }\n return result;\n }\n\n return data;\n}\n\n// =============================================================================\n// URL Search Params Utility\n// =============================================================================\n\n/**\n * Creates a lightweight URL search params builder.\n *\n * This is a custom implementation instead of the standard `URLSearchParams`\n * because the solver API requires a special encoding behavior: **commas must\n * NOT be percent-encoded** in pencilmark values. The standard `URLSearchParams`\n * encodes commas as `%2C`, which the Kotlin-based solver backend does not decode.\n *\n * @returns An object with `append(key, value)` and `toString()` methods\n *\n * @example\n * ```ts\n * const params = createURLSearchParams();\n * params.append(\"pencilmarks\", \"1,2,3\");\n * params.toString(); // \"pencilmarks=1,2,3\" (commas preserved)\n * ```\n */\nconst createURLSearchParams = () => {\n const params: Record<string, string[]> = {};\n return {\n append: (key: string, value: string) => {\n if (!params[key]) {\n params[key] = [];\n }\n params[key]?.push(value);\n },\n toString: () => {\n return Object.entries(params)\n .flatMap(([key, values]) =>\n values.map(\n (value) =>\n // Don't encode commas - the solver API expects literal commas in pencilmarks\n `${encodeURIComponent(key)}=${encodeURIComponent(value).replace(/%2C/g, \",\")}`,\n ),\n )\n .join(\"&\");\n },\n };\n};\n\n// =============================================================================\n// API Configuration Factory\n// =============================================================================\n\nconst createApiConfig = (baseUrl: string) => ({\n BASE_URL: baseUrl,\n ENDPOINTS: {\n // Health\n HEALTH: \"/\",\n\n // Levels\n LEVELS: \"/api/v1/levels\",\n LEVEL: (level: number) => `/api/v1/levels/${level}`,\n\n // Techniques\n TECHNIQUES: \"/api/v1/techniques\",\n TECHNIQUE: (technique: number) => `/api/v1/techniques/${technique}`,\n\n // Learning\n LEARNING: \"/api/v1/learning\",\n LEARNING_ITEM: (uuid: string) => `/api/v1/learning/${uuid}`,\n\n // Boards\n BOARDS: \"/api/v1/boards\",\n BOARDS_RANDOM: \"/api/v1/boards/random\",\n BOARD: (uuid: string) => `/api/v1/boards/${uuid}`,\n\n // Dailies\n DAILIES: \"/api/v1/dailies\",\n DAILIES_RANDOM: \"/api/v1/dailies/random\",\n DAILIES_TODAY: \"/api/v1/dailies/today\",\n DAILIES_DATE: (date: string) => `/api/v1/dailies/date/${date}`,\n DAILY: (uuid: string) => `/api/v1/dailies/${uuid}`,\n\n // Challenges\n CHALLENGES: \"/api/v1/challenges\",\n CHALLENGES_RANDOM: \"/api/v1/challenges/random\",\n CHALLENGE: (uuid: string) => `/api/v1/challenges/${uuid}`,\n\n // Users\n USER: (userId: string) => `/api/v1/users/${userId}`,\n USER_SUBSCRIPTIONS: (userId: string) =>\n `/api/v1/users/${userId}/subscriptions`,\n\n // Solver\n SOLVER_SOLVE: \"/api/v1/solver/solve\",\n SOLVER_VALIDATE: \"/api/v1/solver/validate\",\n SOLVER_GENERATE: \"/api/v1/solver/generate\",\n\n // Practices\n PRACTICES: \"/api/v1/practices\",\n PRACTICES_COUNTS: \"/api/v1/practices/counts\",\n PRACTICE_RANDOM: (technique: number) =>\n `/api/v1/practices/technique/${technique}/random`,\n\n // Examples\n EXAMPLES: \"/api/v1/examples\",\n EXAMPLES_COUNTS: \"/api/v1/examples/counts\",\n\n // Boards counts\n BOARDS_COUNTS: \"/api/v1/boards/counts\",\n BOARDS_COUNTS_BY_TECHNIQUE: \"/api/v1/boards/counts/by-technique\",\n BOARDS_UPDATE_STATS: \"/api/v1/boards/update-stats\",\n\n // Play (game sessions)\n PLAY_START: \"/api/v1/play/start\",\n PLAY_FINISH: \"/api/v1/play/finish\",\n\n // Gamification\n GAMIFICATION_STATS: \"/api/v1/gamification/stats\",\n GAMIFICATION_BADGES: \"/api/v1/gamification/badges\",\n GAMIFICATION_HISTORY: \"/api/v1/gamification/history\",\n },\n DEFAULT_HEADERS: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n});\n\n// =============================================================================\n// Sudojo Client Class\n// =============================================================================\n\n/**\n * Type-safe client for the Sudojo REST API.\n *\n * Provides methods for all Sudojo API endpoints including levels, techniques,\n * boards, dailies, challenges, users, solver, practices, examples, and gamification.\n *\n * ## Error Handling\n *\n * All methods throw errors on failure:\n * - **Network errors**: Thrown by the underlying `NetworkClient` (e.g., connection refused, timeout)\n * - **Empty response**: Throws `Error(\"No data received from server\")` when the server returns no data\n * - **Validation errors**: Thrown before the request for invalid parameters (e.g., invalid UUID, level out of range)\n * - **HTTP 402**: `solverSolve()` throws {@link HintAccessDeniedError} when the hint level exceeds the user's tier\n * - **Other HTTP errors**: Depend on the `NetworkClient` implementation - typically thrown as generic `Error`\n *\n * ## Authentication\n *\n * Most methods accept a `token` parameter (Firebase ID token). The token is sent\n * as a `Bearer` token in the `Authorization` header. Public endpoints (health,\n * levels, boards, etc.) accept but do not require a token. User-specific endpoints\n * (subscriptions, gamification) require a valid token.\n *\n * ## Usage\n *\n * ```typescript\n * const client = new SudojoClient(networkClient, \"https://api.sudojo.com\");\n * const levels = await client.getLevels(token);\n * const daily = await client.getDailyByDate(token, \"2024-01-15\");\n * ```\n */\nexport class SudojoClient {\n private baseUrl: string;\n private headers: Record<string, string>;\n private networkClient: NetworkClient;\n private config: ReturnType<typeof createApiConfig>;\n\n /**\n * Create a SudojoClient instance.\n *\n * @param networkClient - Network client for making HTTP requests (from `@sudobility/types`)\n * @param baseUrl - Base URL for the Sudojo API (e.g., \"https://api.sudojo.com\")\n */\n constructor(networkClient: NetworkClient, baseUrl: string) {\n this.config = createApiConfig(baseUrl);\n this.baseUrl = this.config.BASE_URL;\n this.networkClient = networkClient;\n\n this.headers = {\n ...this.config.DEFAULT_HEADERS,\n };\n }\n\n // ===========================================================================\n // Private Request Method\n // ===========================================================================\n\n private async request<T>(\n endpoint: string,\n options: {\n method?: Optional<\"GET\" | \"POST\" | \"PUT\" | \"DELETE\">;\n body?: Optional<Record<string, unknown>>;\n headers?: Optional<Record<string, string>>;\n token?: Optional<string>;\n timeout?: Optional<number>;\n } = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const requestHeaders: Record<string, string> = {\n ...this.headers,\n ...options.headers,\n };\n\n // Add authorization header if token is provided\n if (options.token) {\n requestHeaders[\"Authorization\"] = `Bearer ${options.token}`;\n }\n\n const requestOptions: {\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n headers: Record<string, string>;\n body?: string;\n timeout?: number;\n } = {\n method: options.method || \"GET\",\n headers: requestHeaders,\n };\n\n // Add body for POST/PUT/DELETE requests\n if (options.body && options.method !== \"GET\") {\n requestOptions.body = JSON.stringify(options.body);\n }\n\n // Add timeout if specified\n if (options.timeout) {\n requestOptions.timeout = options.timeout;\n }\n\n const response = await this.networkClient.request<T>(url, requestOptions);\n\n if (response.data === undefined) {\n throw new Error(\"No data received from server\");\n }\n\n return (await decryptSolutionFields(response.data)) as T;\n }\n\n // ===========================================================================\n // Health Check\n // ===========================================================================\n\n async getHealth(): Promise<BaseResponse<HealthCheckData>> {\n return this.request<BaseResponse<HealthCheckData>>(\n this.config.ENDPOINTS.HEALTH,\n );\n }\n\n // ===========================================================================\n // Levels\n // ===========================================================================\n\n async getLevels(token: string): Promise<BaseResponse<Level[]>> {\n return this.request<BaseResponse<Level[]>>(this.config.ENDPOINTS.LEVELS, {\n token,\n });\n }\n\n async getLevel(token: string, level: number): Promise<BaseResponse<Level>> {\n if (level < 1 || level > 12) {\n throw new Error(`Invalid level: ${level}. Expected 1-12`);\n }\n return this.request<BaseResponse<Level>>(\n this.config.ENDPOINTS.LEVEL(level),\n { token },\n );\n }\n\n async createLevel(\n token: string,\n data: LevelCreateRequest,\n ): Promise<BaseResponse<Level>> {\n return this.request<BaseResponse<Level>>(this.config.ENDPOINTS.LEVELS, {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n });\n }\n\n async updateLevel(\n token: string,\n level: number,\n data: LevelUpdateRequest,\n ): Promise<BaseResponse<Level>> {\n if (level < 1 || level > 12) {\n throw new Error(`Invalid level: ${level}. Expected 1-12`);\n }\n return this.request<BaseResponse<Level>>(\n this.config.ENDPOINTS.LEVEL(level),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteLevel(\n token: string,\n level: number,\n ): Promise<BaseResponse<Level>> {\n if (level < 1 || level > 12) {\n throw new Error(`Invalid level: ${level}. Expected 1-12`);\n }\n return this.request<BaseResponse<Level>>(\n this.config.ENDPOINTS.LEVEL(level),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Techniques\n // ===========================================================================\n\n async getTechniques(\n token: string,\n queryParams?: TechniqueQueryParams,\n ): Promise<BaseResponse<Technique[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.TECHNIQUES}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Technique[]>>(endpoint, { token });\n }\n\n async getTechnique(\n token: string,\n technique: number,\n ): Promise<BaseResponse<Technique>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUE(technique),\n { token },\n );\n }\n\n async createTechnique(\n token: string,\n data: TechniqueCreateRequest,\n ): Promise<BaseResponse<Technique>> {\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async updateTechnique(\n token: string,\n technique: number,\n data: TechniqueUpdateRequest,\n ): Promise<BaseResponse<Technique>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUE(technique),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteTechnique(\n token: string,\n technique: number,\n ): Promise<BaseResponse<Technique>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUE(technique),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Learning\n // ===========================================================================\n\n async getLearning(\n token: string,\n queryParams?: LearningQueryParams,\n ): Promise<BaseResponse<Learning[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.technique !== undefined) {\n params.append(\"technique\", String(queryParams.technique));\n }\n if (queryParams?.language_code) {\n params.append(\"language_code\", queryParams.language_code);\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.LEARNING}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Learning[]>>(endpoint, { token });\n }\n\n async getLearningItem(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Learning>> {\n const validatedUuid = validateUUID(uuid, \"Learning UUID\");\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING_ITEM(validatedUuid),\n { token },\n );\n }\n\n async createLearning(\n token: string,\n data: LearningCreateRequest,\n ): Promise<BaseResponse<Learning>> {\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async updateLearning(\n token: string,\n uuid: string,\n data: LearningUpdateRequest,\n ): Promise<BaseResponse<Learning>> {\n const validatedUuid = validateUUID(uuid, \"Learning UUID\");\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING_ITEM(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteLearning(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Learning>> {\n const validatedUuid = validateUUID(uuid, \"Learning UUID\");\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING_ITEM(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Boards\n // ===========================================================================\n\n async getBoards(\n token: string,\n queryParams?: BoardQueryParams,\n ): Promise<BaseResponse<Board[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n if (queryParams?.limit !== undefined) {\n params.append(\"limit\", String(queryParams.limit));\n }\n if (queryParams?.offset !== undefined) {\n params.append(\"offset\", String(queryParams.offset));\n }\n if (queryParams?.techniques !== undefined) {\n params.append(\"techniques\", String(queryParams.techniques));\n }\n if (queryParams?.technique_bit !== undefined) {\n params.append(\"technique_bit\", String(queryParams.technique_bit));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.BOARDS}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Board[]>>(endpoint, { token });\n }\n\n async getRandomBoard(\n token: string,\n queryParams?: BoardQueryParams,\n ): Promise<BaseResponse<Board>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n\n if (queryParams?.symmetrical !== undefined) {\n params.append(\"symmetrical\", String(queryParams.symmetrical));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.BOARDS_RANDOM}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Board>>(endpoint, { token });\n }\n\n async getBoard(token: string, uuid: string): Promise<BaseResponse<Board>> {\n const validatedUuid = validateUUID(uuid, \"Board UUID\");\n return this.request<BaseResponse<Board>>(\n this.config.ENDPOINTS.BOARD(validatedUuid),\n { token },\n );\n }\n\n async createBoard(\n token: string,\n data: BoardCreateRequest,\n ): Promise<BaseResponse<Board>> {\n return this.request<BaseResponse<Board>>(this.config.ENDPOINTS.BOARDS, {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n });\n }\n\n async updateBoard(\n token: string,\n uuid: string,\n data: BoardUpdateRequest,\n ): Promise<BaseResponse<Board>> {\n const validatedUuid = validateUUID(uuid, \"Board UUID\");\n return this.request<BaseResponse<Board>>(\n this.config.ENDPOINTS.BOARD(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteBoard(token: string, uuid: string): Promise<BaseResponse<Board>> {\n const validatedUuid = validateUUID(uuid, \"Board UUID\");\n return this.request<BaseResponse<Board>>(\n this.config.ENDPOINTS.BOARD(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Dailies\n // ===========================================================================\n\n async getDailies(token: string): Promise<BaseResponse<Daily[]>> {\n return this.request<BaseResponse<Daily[]>>(this.config.ENDPOINTS.DAILIES, {\n token,\n });\n }\n\n async getRandomDaily(token: string): Promise<BaseResponse<Daily>> {\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILIES_RANDOM,\n { token },\n );\n }\n\n async getTodayDaily(token: string): Promise<BaseResponse<Daily>> {\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILIES_TODAY,\n { token },\n );\n }\n\n async getDailyByDate(\n token: string,\n date: string,\n ): Promise<BaseResponse<Daily>> {\n // Validate date format (YYYY-MM-DD)\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n throw new Error(\n `Invalid date format: \"${date}\". Expected YYYY-MM-DD format`,\n );\n }\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILIES_DATE(date),\n { token },\n );\n }\n\n async getDaily(token: string, uuid: string): Promise<BaseResponse<Daily>> {\n const validatedUuid = validateUUID(uuid, \"Daily UUID\");\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILY(validatedUuid),\n { token },\n );\n }\n\n async createDaily(\n token: string,\n data: DailyCreateRequest,\n ): Promise<BaseResponse<Daily>> {\n return this.request<BaseResponse<Daily>>(this.config.ENDPOINTS.DAILIES, {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n });\n }\n\n async updateDaily(\n token: string,\n uuid: string,\n data: DailyUpdateRequest,\n ): Promise<BaseResponse<Daily>> {\n const validatedUuid = validateUUID(uuid, \"Daily UUID\");\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILY(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteDaily(token: string, uuid: string): Promise<BaseResponse<Daily>> {\n const validatedUuid = validateUUID(uuid, \"Daily UUID\");\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILY(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Challenges\n // ===========================================================================\n\n async getChallenges(\n token: string,\n queryParams?: ChallengeQueryParams,\n ): Promise<BaseResponse<Challenge[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n if (queryParams?.difficulty) {\n params.append(\"difficulty\", queryParams.difficulty);\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.CHALLENGES}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Challenge[]>>(endpoint, { token });\n }\n\n async getRandomChallenge(\n token: string,\n queryParams?: ChallengeQueryParams,\n ): Promise<BaseResponse<Challenge>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n if (queryParams?.difficulty) {\n params.append(\"difficulty\", queryParams.difficulty);\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.CHALLENGES_RANDOM}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Challenge>>(endpoint, { token });\n }\n\n async getChallenge(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Challenge>> {\n const validatedUuid = validateUUID(uuid, \"Challenge UUID\");\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGE(validatedUuid),\n { token },\n );\n }\n\n async createChallenge(\n token: string,\n data: ChallengeCreateRequest,\n ): Promise<BaseResponse<Challenge>> {\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async updateChallenge(\n token: string,\n uuid: string,\n data: ChallengeUpdateRequest,\n ): Promise<BaseResponse<Challenge>> {\n const validatedUuid = validateUUID(uuid, \"Challenge UUID\");\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGE(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteChallenge(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Challenge>> {\n const validatedUuid = validateUUID(uuid, \"Challenge UUID\");\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGE(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Users\n // ===========================================================================\n\n async getUser(\n token: string,\n userId: string,\n ): Promise<BaseResponse<UserInfoResponse>> {\n if (!userId || userId.length === 0 || userId.length > 128) {\n throw new Error(`Invalid userId: \"${userId}\". Expected 1-128 characters`);\n }\n return this.request<BaseResponse<UserInfoResponse>>(\n this.config.ENDPOINTS.USER(userId),\n {\n token,\n },\n );\n }\n\n async getUserSubscription(\n token: string,\n userId: string,\n ): Promise<BaseResponse<SubscriptionResult>> {\n if (!userId || userId.length === 0 || userId.length > 128) {\n throw new Error(`Invalid userId: \"${userId}\". Expected 1-128 characters`);\n }\n return this.request<BaseResponse<SubscriptionResult>>(\n this.config.ENDPOINTS.USER_SUBSCRIPTIONS(userId),\n {\n token,\n },\n );\n }\n\n // ===========================================================================\n // Practices\n // ===========================================================================\n\n /**\n * Get practice counts for all techniques\n */\n async getPracticeCounts(\n token: string,\n ): Promise<BaseResponse<TechniquePracticeCountItem[]>> {\n return this.request<BaseResponse<TechniquePracticeCountItem[]>>(\n this.config.ENDPOINTS.PRACTICES_COUNTS,\n { token },\n );\n }\n\n /**\n * Get a random practice for a specific technique\n */\n async getRandomPractice(\n token: string,\n technique: number,\n ): Promise<BaseResponse<TechniquePractice>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<TechniquePractice>>(\n this.config.ENDPOINTS.PRACTICE_RANDOM(technique),\n { token },\n );\n }\n\n /**\n * Create a new practice (admin only)\n */\n async createPractice(\n token: string,\n data: TechniquePracticeCreateRequest,\n ): Promise<BaseResponse<TechniquePractice>> {\n return this.request<BaseResponse<TechniquePractice>>(\n this.config.ENDPOINTS.PRACTICES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n /**\n * Delete all practices (admin only, requires confirm=true)\n */\n async deleteAllPractices(\n token: string,\n ): Promise<BaseResponse<{ deleted: number; message: string }>> {\n return this.request<BaseResponse<{ deleted: number; message: string }>>(\n `${this.config.ENDPOINTS.PRACTICES}?confirm=true`,\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Examples\n // ===========================================================================\n\n /**\n * Get example counts for all techniques\n */\n async getExampleCounts(\n token: string,\n ): Promise<BaseResponse<ExampleCountsData>> {\n return this.request<BaseResponse<ExampleCountsData>>(\n this.config.ENDPOINTS.EXAMPLES_COUNTS,\n { token },\n );\n }\n\n /**\n * Get examples, optionally filtered by technique\n */\n async getExamples(\n token: string,\n queryParams?: TechniqueExampleQueryParams,\n ): Promise<BaseResponse<TechniqueExample[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.technique !== undefined) {\n params.append(\"technique\", String(queryParams.technique));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.EXAMPLES}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<TechniqueExample[]>>(endpoint, { token });\n }\n\n /**\n * Create a new example (admin only)\n */\n async createExample(\n token: string,\n data: TechniqueExampleCreateRequest,\n ): Promise<BaseResponse<TechniqueExample>> {\n return this.request<BaseResponse<TechniqueExample>>(\n this.config.ENDPOINTS.EXAMPLES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n // ===========================================================================\n // Board Counts\n // ===========================================================================\n\n /**\n * Get board counts (total and without techniques)\n */\n async getBoardCounts(token: string): Promise<BaseResponse<BoardCountsData>> {\n return this.request<BaseResponse<BoardCountsData>>(\n this.config.ENDPOINTS.BOARDS_COUNTS,\n { token },\n );\n }\n\n /**\n * Get board counts by technique (count of boards with each technique bit set)\n * Returns Record<number, number> where key is technique ID and value is count\n */\n async getBoardCountsByTechnique(\n token: string,\n ): Promise<BaseResponse<Record<number, number>>> {\n return this.request<BaseResponse<Record<number, number>>>(\n this.config.ENDPOINTS.BOARDS_COUNTS_BY_TECHNIQUE,\n { token },\n );\n }\n\n /**\n * Calculate and update puzzle stats (percentages) on levels and techniques.\n * Requires admin authentication.\n */\n async updatePuzzleStats(token: string): Promise<\n BaseResponse<{\n levels: Record<number, number>;\n techniques: Record<number, number>;\n }>\n > {\n return this.request<\n BaseResponse<{\n levels: Record<number, number>;\n techniques: Record<number, number>;\n }>\n >(this.config.ENDPOINTS.BOARDS_UPDATE_STATS, {\n method: \"POST\",\n token,\n });\n }\n\n // ===========================================================================\n // Solver\n // ===========================================================================\n\n /**\n * Builds an endpoint path with query parameters for solver endpoints\n */\n private buildSolverUrl(\n endpoint: string,\n params: Record<string, string | boolean | undefined>,\n ): string {\n const searchParams = createURLSearchParams();\n // Sort keys alphabetically to match Kotlin behavior\n const sortedKeys = Object.keys(params).sort();\n for (const key of sortedKeys) {\n const value = params[key];\n if (value !== undefined) {\n searchParams.append(key, String(value));\n }\n }\n const query = searchParams.toString();\n // Return endpoint + query only, baseUrl is added by request()\n return `${endpoint}${query ? `?${query}` : \"\"}`;\n }\n\n /**\n * Get hints for solving a Sudoku puzzle\n * @throws {HintAccessDeniedError} When hint level exceeds user's subscription tier\n */\n async solverSolve(\n token: string,\n options: SolveOptions,\n ): Promise<BaseResponse<SolveData>> {\n const url = this.buildSolverUrl(this.config.ENDPOINTS.SOLVER_SOLVE, {\n original: options.original,\n user: options.user,\n autopencilmarks: options.autoPencilmarks,\n pencilmarks: options.pencilmarks,\n filters: options.filters,\n techniques: options.techniques,\n });\n\n const fullUrl = `${this.baseUrl}${url}`;\n const requestHeaders: Record<string, string> = {\n ...this.headers,\n };\n\n if (token) {\n requestHeaders[\"Authorization\"] = `Bearer ${token}`;\n }\n\n // Use 120 second timeout for solve (advanced techniques can be slow)\n const response = await this.networkClient.request<\n BaseResponse<SolveData> | HintAccessDeniedResponse\n >(fullUrl, {\n method: \"GET\",\n headers: requestHeaders,\n timeout: 120000,\n });\n\n // Check for hint access denied (402)\n if (response.status === 402 && response.data) {\n const errorResponse = response.data as HintAccessDeniedResponse;\n if (errorResponse.error?.code === \"HINT_ACCESS_DENIED\") {\n throw new HintAccessDeniedError(errorResponse.error);\n }\n }\n\n // Check for other errors\n if (!response.ok || response.data === undefined) {\n throw new Error(\"Failed to get hints from solver\");\n }\n\n return (await decryptSolutionFields(\n response.data,\n )) as BaseResponse<SolveData>;\n }\n\n /**\n * Validate that a Sudoku puzzle has a unique solution.\n * Uses a longer timeout (120s) because validation involves iterative solving.\n */\n async solverValidate(\n token: string,\n options: ValidateOptions,\n ): Promise<BaseResponse<ValidateData>> {\n const url = this.buildSolverUrl(this.config.ENDPOINTS.SOLVER_VALIDATE, {\n original: options.original,\n });\n\n // Use 120 second timeout for validation (iterative solving can be slow)\n return this.request<BaseResponse<ValidateData>>(url, {\n token,\n timeout: 120000,\n });\n }\n\n /**\n * Generate a new random Sudoku puzzle\n */\n async solverGenerate(\n token: string,\n options: GenerateOptions = {},\n ): Promise<BaseResponse<GenerateData>> {\n const url = this.buildSolverUrl(this.config.ENDPOINTS.SOLVER_GENERATE, {\n symmetrical: options.symmetrical,\n });\n\n return this.request<BaseResponse<GenerateData>>(url, { token });\n }\n\n // ===========================================================================\n // Play (Game Session) Endpoints\n // ===========================================================================\n\n /**\n * Start a new game session\n */\n async playStart(\n token: string,\n data: GameStartRequest,\n ): Promise<BaseResponse<GameStartResponse>> {\n return this.request<BaseResponse<GameStartResponse>>(\n this.config.ENDPOINTS.PLAY_START,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n /**\n * Finish the current game session and get rewards\n */\n async playFinish(\n token: string,\n data: GameFinishRequest,\n ): Promise<BaseResponse<GameFinishResponse>> {\n return this.request<BaseResponse<GameFinishResponse>>(\n this.config.ENDPOINTS.PLAY_FINISH,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n // ===========================================================================\n // Gamification Endpoints\n // ===========================================================================\n\n /**\n * Get user's gamification stats (points, level, badges)\n */\n async getGamificationStats(\n token: string,\n ): Promise<BaseResponse<GamificationStats>> {\n return this.request<BaseResponse<GamificationStats>>(\n this.config.ENDPOINTS.GAMIFICATION_STATS,\n { token },\n );\n }\n\n /**\n * Get all badge definitions (public)\n */\n async getBadgeDefinitions(): Promise<BaseResponse<BadgeDefinition[]>> {\n return this.request<BaseResponse<BadgeDefinition[]>>(\n this.config.ENDPOINTS.GAMIFICATION_BADGES,\n );\n }\n\n /**\n * Get user's point transaction history\n */\n async getPointHistory(\n token: string,\n options?: { limit?: number; offset?: number },\n ): Promise<BaseResponse<PointTransaction[]>> {\n let endpoint = this.config.ENDPOINTS.GAMIFICATION_HISTORY;\n if (options?.limit || options?.offset) {\n const params = createURLSearchParams();\n if (options.limit) params.append(\"limit\", String(options.limit));\n if (options.offset) params.append(\"offset\", String(options.offset));\n endpoint = `${endpoint}?${params.toString()}`;\n }\n return this.request<BaseResponse<PointTransaction[]>>(endpoint, { token });\n }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Factory function to create a new SudojoClient instance.\n *\n * Equivalent to `new SudojoClient(networkClient, baseUrl)` but useful\n * for dependency injection and functional composition patterns.\n *\n * @param networkClient - Network client for making HTTP requests\n * @param baseUrl - Base URL for the Sudojo API\n * @returns A new SudojoClient instance\n */\nexport const createSudojoClient = (\n networkClient: NetworkClient,\n baseUrl: string,\n): SudojoClient => {\n return new SudojoClient(networkClient, baseUrl);\n};\n\n// =============================================================================\n// Utility Exports\n// =============================================================================\n\n/**\n * Re-exported UUID validation utilities from `@sudobility/sudojo_types`.\n *\n * These are used internally by the SudojoClient for parameter validation\n * and are also exported for consumer convenience. Use `isValidUUID` for\n * boolean checks and `validateUUID` when you want an error thrown on invalid input.\n *\n * - `isValidUUID(value)` - Returns true if the string is a valid UUID v4\n * - `validateUUID(value, label)` - Returns the UUID or throws an Error with the label\n */\nexport { isValidUUID, validateUUID };\n"]}
|
|
1
|
+
{"version":3,"file":"sudojo-client.js","sourceRoot":"","sources":["../../src/network/sudojo-client.ts"],"names":[],"mappings":"AACA,OAAO,EAyBL,WAAW,EAyBX,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AASlD,IAAI,YAAY,GAAqB,IAAI,CAAC;AAO1C,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAc;IACvD,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5E,YAAY,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CACrD,KAAK,EACL,QAAQ,EACR,SAAS,EACT,KAAK,EACL,CAAC,SAAS,CAAC,CACZ,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,SAAiB;IAC9C,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IAEpC,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAE1C,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CACtD,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,EAC9B,YAAY,EACZ,iBAAiB,CAClB,CAAC;IAEF,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,IAAa;IAChD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAErD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,IACE,GAAG,KAAK,UAAU;gBAClB,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ;gBAC3B,GAAG,CAAC,GAAG,CAAY,CAAC,UAAU,CAAC,MAAM,CAAC,EACvC,CAAC;gBACD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,GAAG,CAAW,CAAC,CAAC;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAuBD,MAAM,qBAAqB,GAAG,GAAG,EAAE;IACjC,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,OAAO;QACL,MAAM,EAAE,CAAC,GAAW,EAAE,KAAa,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACnB,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;iBAC1B,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,CACzB,MAAM,CAAC,GAAG,CACR,CAAC,KAAK,EAAE,EAAE,CAER,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CACjF,CACF;iBACA,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAMF,MAAM,eAAe,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,CAAC;IAC5C,QAAQ,EAAE,OAAO;IACjB,SAAS,EAAE;QAET,MAAM,EAAE,GAAG;QAGX,MAAM,EAAE,gBAAgB;QACxB,KAAK,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,kBAAkB,KAAK,EAAE;QAGnD,UAAU,EAAE,oBAAoB;QAChC,SAAS,EAAE,CAAC,SAAiB,EAAE,EAAE,CAAC,sBAAsB,SAAS,EAAE;QAGnE,QAAQ,EAAE,kBAAkB;QAC5B,aAAa,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,oBAAoB,IAAI,EAAE;QAG3D,MAAM,EAAE,gBAAgB;QACxB,aAAa,EAAE,uBAAuB;QACtC,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,kBAAkB,IAAI,EAAE;QAGjD,OAAO,EAAE,iBAAiB;QAC1B,cAAc,EAAE,wBAAwB;QACxC,aAAa,EAAE,uBAAuB;QACtC,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,wBAAwB,IAAI,EAAE;QAC9D,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,mBAAmB,IAAI,EAAE;QAGlD,UAAU,EAAE,oBAAoB;QAChC,iBAAiB,EAAE,2BAA2B;QAC9C,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,sBAAsB,IAAI,EAAE;QAGzD,IAAI,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,iBAAiB,MAAM,EAAE;QACnD,kBAAkB,EAAE,CAAC,MAAc,EAAE,EAAE,CACrC,iBAAiB,MAAM,gBAAgB;QAGzC,YAAY,EAAE,sBAAsB;QACpC,eAAe,EAAE,yBAAyB;QAC1C,eAAe,EAAE,yBAAyB;QAG1C,SAAS,EAAE,mBAAmB;QAC9B,gBAAgB,EAAE,0BAA0B;QAC5C,eAAe,EAAE,CAAC,SAAiB,EAAE,EAAE,CACrC,+BAA+B,SAAS,SAAS;QAGnD,QAAQ,EAAE,kBAAkB;QAC5B,eAAe,EAAE,yBAAyB;QAG1C,aAAa,EAAE,uBAAuB;QACtC,0BAA0B,EAAE,oCAAoC;QAChE,mBAAmB,EAAE,6BAA6B;QAGlD,UAAU,EAAE,oBAAoB;QAChC,WAAW,EAAE,qBAAqB;QAGlC,kBAAkB,EAAE,4BAA4B;QAChD,mBAAmB,EAAE,6BAA6B;QAClD,oBAAoB,EAAE,8BAA8B;KACrD;IACD,eAAe,EAAE;QACf,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,kBAAkB;KAC3B;CACF,CAAC,CAAC;AAoCH,MAAM,OAAO,YAAY;IAYvB,YAAY,aAA4B,EAAE,OAAe;QACvD,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QACpC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QAEnC,IAAI,CAAC,OAAO,GAAG;YACb,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe;SAC/B,CAAC;IACJ,CAAC;IAMO,KAAK,CAAC,OAAO,CACnB,QAAgB,EAChB,UAMI,EAAE;QAEN,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC;QAEzC,MAAM,cAAc,GAA2B;YAC7C,GAAG,IAAI,CAAC,OAAO;YACf,GAAG,OAAO,CAAC,OAAO;SACnB,CAAC;QAGF,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,cAAc,CAAC,eAAe,CAAC,GAAG,UAAU,OAAO,CAAC,KAAK,EAAE,CAAC;QAC9D,CAAC;QAED,MAAM,cAAc,GAKhB;YACF,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,OAAO,EAAE,cAAc;SACxB,CAAC;QAGF,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC7C,cAAc,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;QAGD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,cAAc,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC3C,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAI,GAAG,EAAE,cAAc,CAAC,CAAC;QAE1E,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAM,CAAC;IAC3D,CAAC;IAMD,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAC7B,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,SAAS,CAAC,KAAa;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAwB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;YACvE,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,KAAa;QACzC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,iBAAiB,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAClC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAa,EACb,IAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAsB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;YACrE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAa,EACb,KAAa,EACb,IAAwB;QAExB,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,iBAAiB,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAClC;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAa,EACb,KAAa;QAEb,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,iBAAiB,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAClC;YACE,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,aAAa,CACjB,KAAa,EACb,WAAkC;QAElC,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAElF,OAAO,IAAI,CAAC,OAAO,CAA4B,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,KAAa,EACb,SAAiB;QAEjB,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,iBAAiB,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,EAC1C,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,IAA4B;QAE5B,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,EAChC;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,SAAiB,EACjB,IAA4B;QAE5B,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,iBAAiB,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,EAC1C;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,SAAiB;QAEjB,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,iBAAiB,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,EAC1C;YACE,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,WAAW,CACf,KAAa,EACb,WAAiC;QAEjC,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,WAAW,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,WAAW,EAAE,aAAa,EAAE,CAAC;YAC/B,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEhF,OAAO,IAAI,CAAC,OAAO,CAA2B,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,IAAY;QAEZ,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,EAClD,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,IAA2B;QAE3B,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAC9B;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,IAAY,EACZ,IAA2B;QAE3B,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,EAClD;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,IAAY;QAEZ,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,EAClD;YACE,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,SAAS,CACb,KAAa,EACb,WAA8B;QAE9B,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,WAAW,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,WAAW,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,WAAW,EAAE,aAAa,KAAK,SAAS,EAAE,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAE9E,OAAO,IAAI,CAAC,OAAO,CAAwB,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,WAA8B;QAE9B,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,WAAW,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAErF,OAAO,IAAI,CAAC,OAAO,CAAsB,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,IAAY;QACxC,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,EAC1C,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAa,EACb,IAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAsB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;YACrE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAa,EACb,IAAY,EACZ,IAAwB;QAExB,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,EAC1C;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,IAAY;QAC3C,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,EAC1C;YACE,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,UAAU,CAAC,KAAa;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAwB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE;YACxE,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAAa;QAChC,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,EACpC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,EACnC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,IAAY;QAGZ,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,+BAA+B,CAC7D,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,EACxC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,IAAY;QACxC,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,EAC1C,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAa,EACb,IAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAsB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE;YACtE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAa,EACb,IAAY,EACZ,IAAwB;QAExB,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,EAC1C;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,IAAY;QAC3C,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,EAC1C;YACE,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,aAAa,CACjB,KAAa,EACb,WAAkC;QAElC,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,WAAW,EAAE,UAAU,EAAE,CAAC;YAC5B,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAElF,OAAO,IAAI,CAAC,OAAO,CAA4B,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,KAAa,EACb,WAAkC;QAElC,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,WAAW,EAAE,UAAU,EAAE,CAAC;YAC5B,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEzF,OAAO,IAAI,CAAC,OAAO,CAA0B,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,KAAa,EACb,IAAY;QAEZ,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,EAC9C,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,IAA4B;QAE5B,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,EAChC;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,IAAY,EACZ,IAA4B;QAE5B,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,EAC9C;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,IAAY;QAEZ,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,EAC9C;YACE,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,OAAO,CACX,KAAa,EACb,MAAc;QAEd,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,8BAA8B,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAClC;YACE,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,KAAa,EACb,MAAc,EACd,QAAkB;QAElB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,8BAA8B,CAAC,CAAC;QAC5E,CAAC;QACD,MAAM,QAAQ,GAAG,QAAQ;YACvB,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,gBAAgB;YACrE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,OAAO,CAAmC,QAAQ,EAAE;YAC9D,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IASD,KAAK,CAAC,iBAAiB,CACrB,KAAa;QAEb,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,EACtC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,iBAAiB,CACrB,KAAa,EACb,SAAiB;QAEjB,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,sBAAsB,SAAS,iBAAiB,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,SAAS,CAAC,EAChD,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,IAAoC;QAEpC,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,EAC/B;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,kBAAkB,CACtB,KAAa;QAEb,OAAO,IAAI,CAAC,OAAO,CACjB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,eAAe,EACjD;YACE,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IASD,KAAK,CAAC,gBAAgB,CACpB,KAAa;QAEb,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,EACrC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,WAAW,CACf,KAAa,EACb,WAAyC;QAEzC,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,WAAW,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAEhF,OAAO,IAAI,CAAC,OAAO,CAAmC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IAKD,KAAK,CAAC,aAAa,CACjB,KAAa,EACb,IAAmC;QAEnC,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAC9B;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IASD,KAAK,CAAC,cAAc,CAAC,KAAa;QAChC,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,EACnC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,yBAAyB,CAC7B,KAAa;QAEb,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,0BAA0B,EAChD,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAMD,KAAK,CAAC,iBAAiB,CAAC,KAAa;QAMnC,OAAO,IAAI,CAAC,OAAO,CAKjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,mBAAmB,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IASO,cAAc,CACpB,QAAgB,EAChB,MAAoD;QAEpD,MAAM,YAAY,GAAG,qBAAqB,EAAE,CAAC;QAE7C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC;QAEtC,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAClD,CAAC;IAMD,KAAK,CAAC,WAAW,CACf,KAAa,EACb,OAAqB;QAErB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE;YAClE,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC;QACxC,MAAM,cAAc,GAA2B;YAC7C,GAAG,IAAI,CAAC,OAAO;SAChB,CAAC;QAEF,IAAI,KAAK,EAAE,CAAC;YACV,cAAc,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;QACtD,CAAC;QAGD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAE/C,OAAO,EAAE;YACT,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,cAAc;YACvB,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAGH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAgC,CAAC;YAChE,IAAI,aAAa,CAAC,KAAK,EAAE,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBACvD,MAAM,IAAI,qBAAqB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAGD,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,CAAC,MAAM,qBAAqB,CACjC,QAAQ,CAAC,IAAI,CACd,CAA4B,CAAC;IAChC,CAAC;IAMD,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,OAAwB;QAExB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,EAAE;YACrE,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QAGH,OAAO,IAAI,CAAC,OAAO,CAA6B,GAAG,EAAE;YACnD,KAAK;YACL,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;IACL,CAAC;IAKD,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,UAA2B,EAAE;QAE7B,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,EAAE;YACrE,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,OAAO,CAA6B,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,CAAC;IASD,KAAK,CAAC,SAAS,CACb,KAAa,EACb,IAAsB;QAEtB,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,EAChC;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,UAAU,CACd,KAAa,EACb,IAAuB;QAEvB,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,EACjC;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAA0C;YAChD,KAAK;SACN,CACF,CAAC;IACJ,CAAC;IASD,KAAK,CAAC,oBAAoB,CACxB,KAAa;QAEb,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,EACxC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,mBAAmB;QACvB,OAAO,IAAI,CAAC,OAAO,CACjB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAC1C,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,eAAe,CACnB,KAAa,EACb,OAA6C;QAE7C,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,oBAAoB,CAAC;QAC1D,IAAI,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;YACvC,IAAI,OAAO,CAAC,KAAK;gBAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;YACjE,IAAI,OAAO,CAAC,MAAM;gBAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACpE,QAAQ,GAAG,GAAG,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAmC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;CACF;AAgBD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,aAA4B,EAC5B,OAAe,EACD,EAAE;IAChB,OAAO,IAAI,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC,CAAC;AAgBF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import type { NetworkClient, UserInfoResponse } from \"@sudobility/types\";\nimport {\n type BadgeDefinition,\n type BaseResponse,\n type Board,\n type BoardCountsData,\n type BoardCreateRequest,\n type BoardQueryParams,\n type BoardUpdateRequest,\n type Challenge,\n type ChallengeCreateRequest,\n type ChallengeQueryParams,\n type ChallengeUpdateRequest,\n type Daily,\n type DailyCreateRequest,\n type DailyUpdateRequest,\n type ExampleCountsData,\n type GameFinishRequest,\n type GameFinishResponse,\n type GameStartRequest,\n type GameStartResponse,\n type GamificationStats,\n type GenerateData,\n type GenerateOptions,\n type HealthCheckData,\n type HintAccessDeniedResponse,\n isValidUUID,\n type Learning,\n type LearningCreateRequest,\n type LearningQueryParams,\n type LearningUpdateRequest,\n type Level,\n type LevelCreateRequest,\n type LevelUpdateRequest,\n type Optional,\n type PointTransaction,\n type SolveData,\n type SolveOptions,\n type SubscriptionResult,\n type Technique,\n type TechniqueCreateRequest,\n type TechniqueExample,\n type TechniqueExampleCreateRequest,\n type TechniqueExampleQueryParams,\n type TechniquePractice,\n type TechniquePracticeCountItem,\n type TechniquePracticeCreateRequest,\n type TechniqueQueryParams,\n type TechniqueUpdateRequest,\n type ValidateData,\n type ValidateOptions,\n validateUUID,\n} from \"@sudobility/sudojo_types\";\nimport { HintAccessDeniedError } from \"../errors\";\n\n// Re-export option types for convenience\nexport type { SolveOptions, ValidateOptions, GenerateOptions };\n\n// =============================================================================\n// Solution Decryption\n// =============================================================================\n\nlet _solutionKey: CryptoKey | null = null;\n\n/**\n * Configure the symmetric key used to decrypt `solution` fields in API responses.\n * Call once at app startup with the hex-encoded 256-bit key.\n * If not called (or called with empty string), encrypted solutions pass through as-is.\n */\nexport async function configureSolutionKey(keyHex: string): Promise<void> {\n if (!keyHex) return;\n const hexPairs = keyHex.match(/.{2}/g);\n if (!hexPairs) return;\n const keyBytes = new Uint8Array(hexPairs.map((byte) => parseInt(byte, 16)));\n _solutionKey = await globalThis.crypto.subtle.importKey(\n \"raw\",\n keyBytes,\n \"AES-GCM\",\n false,\n [\"decrypt\"],\n );\n}\n\nasync function decryptSolution(encrypted: string): Promise<string> {\n if (!_solutionKey) return encrypted;\n\n const raw = globalThis.atob(encrypted.slice(4)); // strip \"enc:\" prefix\n const bytes = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) {\n bytes[i] = raw.charCodeAt(i);\n }\n\n const nonce = bytes.slice(0, 12);\n const ciphertextWithTag = bytes.slice(12);\n\n const decrypted = await globalThis.crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv: nonce },\n _solutionKey,\n ciphertextWithTag,\n );\n\n return new TextDecoder().decode(decrypted);\n}\n\nasync function decryptSolutionFields(data: unknown): Promise<unknown> {\n if (data === null || data === undefined) return data;\n\n if (Array.isArray(data)) {\n return Promise.all(data.map((item) => decryptSolutionFields(item)));\n }\n\n if (typeof data === \"object\") {\n const obj = data as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (\n key === \"solution\" &&\n typeof obj[key] === \"string\" &&\n (obj[key] as string).startsWith(\"enc:\")\n ) {\n result[key] = await decryptSolution(obj[key] as string);\n } else {\n result[key] = await decryptSolutionFields(obj[key]);\n }\n }\n return result;\n }\n\n return data;\n}\n\n// =============================================================================\n// URL Search Params Utility\n// =============================================================================\n\n/**\n * Creates a lightweight URL search params builder.\n *\n * This is a custom implementation instead of the standard `URLSearchParams`\n * because the solver API requires a special encoding behavior: **commas must\n * NOT be percent-encoded** in pencilmark values. The standard `URLSearchParams`\n * encodes commas as `%2C`, which the Kotlin-based solver backend does not decode.\n *\n * @returns An object with `append(key, value)` and `toString()` methods\n *\n * @example\n * ```ts\n * const params = createURLSearchParams();\n * params.append(\"pencilmarks\", \"1,2,3\");\n * params.toString(); // \"pencilmarks=1,2,3\" (commas preserved)\n * ```\n */\nconst createURLSearchParams = () => {\n const params: Record<string, string[]> = {};\n return {\n append: (key: string, value: string) => {\n if (!params[key]) {\n params[key] = [];\n }\n params[key]?.push(value);\n },\n toString: () => {\n return Object.entries(params)\n .flatMap(([key, values]) =>\n values.map(\n (value) =>\n // Don't encode commas - the solver API expects literal commas in pencilmarks\n `${encodeURIComponent(key)}=${encodeURIComponent(value).replace(/%2C/g, \",\")}`,\n ),\n )\n .join(\"&\");\n },\n };\n};\n\n// =============================================================================\n// API Configuration Factory\n// =============================================================================\n\nconst createApiConfig = (baseUrl: string) => ({\n BASE_URL: baseUrl,\n ENDPOINTS: {\n // Health\n HEALTH: \"/\",\n\n // Levels\n LEVELS: \"/api/v1/levels\",\n LEVEL: (level: number) => `/api/v1/levels/${level}`,\n\n // Techniques\n TECHNIQUES: \"/api/v1/techniques\",\n TECHNIQUE: (technique: number) => `/api/v1/techniques/${technique}`,\n\n // Learning\n LEARNING: \"/api/v1/learning\",\n LEARNING_ITEM: (uuid: string) => `/api/v1/learning/${uuid}`,\n\n // Boards\n BOARDS: \"/api/v1/boards\",\n BOARDS_RANDOM: \"/api/v1/boards/random\",\n BOARD: (uuid: string) => `/api/v1/boards/${uuid}`,\n\n // Dailies\n DAILIES: \"/api/v1/dailies\",\n DAILIES_RANDOM: \"/api/v1/dailies/random\",\n DAILIES_TODAY: \"/api/v1/dailies/today\",\n DAILIES_DATE: (date: string) => `/api/v1/dailies/date/${date}`,\n DAILY: (uuid: string) => `/api/v1/dailies/${uuid}`,\n\n // Challenges\n CHALLENGES: \"/api/v1/challenges\",\n CHALLENGES_RANDOM: \"/api/v1/challenges/random\",\n CHALLENGE: (uuid: string) => `/api/v1/challenges/${uuid}`,\n\n // Users\n USER: (userId: string) => `/api/v1/users/${userId}`,\n USER_SUBSCRIPTIONS: (userId: string) =>\n `/api/v1/users/${userId}/subscriptions`,\n\n // Solver\n SOLVER_SOLVE: \"/api/v1/solver/solve\",\n SOLVER_VALIDATE: \"/api/v1/solver/validate\",\n SOLVER_GENERATE: \"/api/v1/solver/generate\",\n\n // Practices\n PRACTICES: \"/api/v1/practices\",\n PRACTICES_COUNTS: \"/api/v1/practices/counts\",\n PRACTICE_RANDOM: (technique: number) =>\n `/api/v1/practices/technique/${technique}/random`,\n\n // Examples\n EXAMPLES: \"/api/v1/examples\",\n EXAMPLES_COUNTS: \"/api/v1/examples/counts\",\n\n // Boards counts\n BOARDS_COUNTS: \"/api/v1/boards/counts\",\n BOARDS_COUNTS_BY_TECHNIQUE: \"/api/v1/boards/counts/by-technique\",\n BOARDS_UPDATE_STATS: \"/api/v1/boards/update-stats\",\n\n // Play (game sessions)\n PLAY_START: \"/api/v1/play/start\",\n PLAY_FINISH: \"/api/v1/play/finish\",\n\n // Gamification\n GAMIFICATION_STATS: \"/api/v1/gamification/stats\",\n GAMIFICATION_BADGES: \"/api/v1/gamification/badges\",\n GAMIFICATION_HISTORY: \"/api/v1/gamification/history\",\n },\n DEFAULT_HEADERS: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n});\n\n// =============================================================================\n// Sudojo Client Class\n// =============================================================================\n\n/**\n * Type-safe client for the Sudojo REST API.\n *\n * Provides methods for all Sudojo API endpoints including levels, techniques,\n * boards, dailies, challenges, users, solver, practices, examples, and gamification.\n *\n * ## Error Handling\n *\n * All methods throw errors on failure:\n * - **Network errors**: Thrown by the underlying `NetworkClient` (e.g., connection refused, timeout)\n * - **Empty response**: Throws `Error(\"No data received from server\")` when the server returns no data\n * - **Validation errors**: Thrown before the request for invalid parameters (e.g., invalid UUID, level out of range)\n * - **HTTP 402**: `solverSolve()` throws {@link HintAccessDeniedError} when the hint level exceeds the user's tier\n * - **Other HTTP errors**: Depend on the `NetworkClient` implementation - typically thrown as generic `Error`\n *\n * ## Authentication\n *\n * Most methods accept a `token` parameter (Firebase ID token). The token is sent\n * as a `Bearer` token in the `Authorization` header. Public endpoints (health,\n * levels, boards, etc.) accept but do not require a token. User-specific endpoints\n * (subscriptions, gamification) require a valid token.\n *\n * ## Usage\n *\n * ```typescript\n * const client = new SudojoClient(networkClient, \"https://api.sudojo.com\");\n * const levels = await client.getLevels(token);\n * const daily = await client.getDailyByDate(token, \"2024-01-15\");\n * ```\n */\nexport class SudojoClient {\n private baseUrl: string;\n private headers: Record<string, string>;\n private networkClient: NetworkClient;\n private config: ReturnType<typeof createApiConfig>;\n\n /**\n * Create a SudojoClient instance.\n *\n * @param networkClient - Network client for making HTTP requests (from `@sudobility/types`)\n * @param baseUrl - Base URL for the Sudojo API (e.g., \"https://api.sudojo.com\")\n */\n constructor(networkClient: NetworkClient, baseUrl: string) {\n this.config = createApiConfig(baseUrl);\n this.baseUrl = this.config.BASE_URL;\n this.networkClient = networkClient;\n\n this.headers = {\n ...this.config.DEFAULT_HEADERS,\n };\n }\n\n // ===========================================================================\n // Private Request Method\n // ===========================================================================\n\n private async request<T>(\n endpoint: string,\n options: {\n method?: Optional<\"GET\" | \"POST\" | \"PUT\" | \"DELETE\">;\n body?: Optional<Record<string, unknown>>;\n headers?: Optional<Record<string, string>>;\n token?: Optional<string>;\n timeout?: Optional<number>;\n } = {},\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n\n const requestHeaders: Record<string, string> = {\n ...this.headers,\n ...options.headers,\n };\n\n // Add authorization header if token is provided\n if (options.token) {\n requestHeaders[\"Authorization\"] = `Bearer ${options.token}`;\n }\n\n const requestOptions: {\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\n headers: Record<string, string>;\n body?: string;\n timeout?: number;\n } = {\n method: options.method || \"GET\",\n headers: requestHeaders,\n };\n\n // Add body for POST/PUT/DELETE requests\n if (options.body && options.method !== \"GET\") {\n requestOptions.body = JSON.stringify(options.body);\n }\n\n // Add timeout if specified\n if (options.timeout) {\n requestOptions.timeout = options.timeout;\n }\n\n const response = await this.networkClient.request<T>(url, requestOptions);\n\n if (response.data === undefined) {\n throw new Error(\"No data received from server\");\n }\n\n return (await decryptSolutionFields(response.data)) as T;\n }\n\n // ===========================================================================\n // Health Check\n // ===========================================================================\n\n async getHealth(): Promise<BaseResponse<HealthCheckData>> {\n return this.request<BaseResponse<HealthCheckData>>(\n this.config.ENDPOINTS.HEALTH,\n );\n }\n\n // ===========================================================================\n // Levels\n // ===========================================================================\n\n async getLevels(token: string): Promise<BaseResponse<Level[]>> {\n return this.request<BaseResponse<Level[]>>(this.config.ENDPOINTS.LEVELS, {\n token,\n });\n }\n\n async getLevel(token: string, level: number): Promise<BaseResponse<Level>> {\n if (level < 1 || level > 12) {\n throw new Error(`Invalid level: ${level}. Expected 1-12`);\n }\n return this.request<BaseResponse<Level>>(\n this.config.ENDPOINTS.LEVEL(level),\n { token },\n );\n }\n\n async createLevel(\n token: string,\n data: LevelCreateRequest,\n ): Promise<BaseResponse<Level>> {\n return this.request<BaseResponse<Level>>(this.config.ENDPOINTS.LEVELS, {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n });\n }\n\n async updateLevel(\n token: string,\n level: number,\n data: LevelUpdateRequest,\n ): Promise<BaseResponse<Level>> {\n if (level < 1 || level > 12) {\n throw new Error(`Invalid level: ${level}. Expected 1-12`);\n }\n return this.request<BaseResponse<Level>>(\n this.config.ENDPOINTS.LEVEL(level),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteLevel(\n token: string,\n level: number,\n ): Promise<BaseResponse<Level>> {\n if (level < 1 || level > 12) {\n throw new Error(`Invalid level: ${level}. Expected 1-12`);\n }\n return this.request<BaseResponse<Level>>(\n this.config.ENDPOINTS.LEVEL(level),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Techniques\n // ===========================================================================\n\n async getTechniques(\n token: string,\n queryParams?: TechniqueQueryParams,\n ): Promise<BaseResponse<Technique[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.TECHNIQUES}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Technique[]>>(endpoint, { token });\n }\n\n async getTechnique(\n token: string,\n technique: number,\n ): Promise<BaseResponse<Technique>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUE(technique),\n { token },\n );\n }\n\n async createTechnique(\n token: string,\n data: TechniqueCreateRequest,\n ): Promise<BaseResponse<Technique>> {\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async updateTechnique(\n token: string,\n technique: number,\n data: TechniqueUpdateRequest,\n ): Promise<BaseResponse<Technique>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUE(technique),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteTechnique(\n token: string,\n technique: number,\n ): Promise<BaseResponse<Technique>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<Technique>>(\n this.config.ENDPOINTS.TECHNIQUE(technique),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Learning\n // ===========================================================================\n\n async getLearning(\n token: string,\n queryParams?: LearningQueryParams,\n ): Promise<BaseResponse<Learning[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.technique !== undefined) {\n params.append(\"technique\", String(queryParams.technique));\n }\n if (queryParams?.language_code) {\n params.append(\"language_code\", queryParams.language_code);\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.LEARNING}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Learning[]>>(endpoint, { token });\n }\n\n async getLearningItem(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Learning>> {\n const validatedUuid = validateUUID(uuid, \"Learning UUID\");\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING_ITEM(validatedUuid),\n { token },\n );\n }\n\n async createLearning(\n token: string,\n data: LearningCreateRequest,\n ): Promise<BaseResponse<Learning>> {\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async updateLearning(\n token: string,\n uuid: string,\n data: LearningUpdateRequest,\n ): Promise<BaseResponse<Learning>> {\n const validatedUuid = validateUUID(uuid, \"Learning UUID\");\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING_ITEM(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteLearning(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Learning>> {\n const validatedUuid = validateUUID(uuid, \"Learning UUID\");\n return this.request<BaseResponse<Learning>>(\n this.config.ENDPOINTS.LEARNING_ITEM(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Boards\n // ===========================================================================\n\n async getBoards(\n token: string,\n queryParams?: BoardQueryParams,\n ): Promise<BaseResponse<Board[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n if (queryParams?.limit !== undefined) {\n params.append(\"limit\", String(queryParams.limit));\n }\n if (queryParams?.offset !== undefined) {\n params.append(\"offset\", String(queryParams.offset));\n }\n if (queryParams?.techniques !== undefined) {\n params.append(\"techniques\", String(queryParams.techniques));\n }\n if (queryParams?.technique_bit !== undefined) {\n params.append(\"technique_bit\", String(queryParams.technique_bit));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.BOARDS}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Board[]>>(endpoint, { token });\n }\n\n async getRandomBoard(\n token: string,\n queryParams?: BoardQueryParams,\n ): Promise<BaseResponse<Board>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n\n if (queryParams?.symmetrical !== undefined) {\n params.append(\"symmetrical\", String(queryParams.symmetrical));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.BOARDS_RANDOM}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Board>>(endpoint, { token });\n }\n\n async getBoard(token: string, uuid: string): Promise<BaseResponse<Board>> {\n const validatedUuid = validateUUID(uuid, \"Board UUID\");\n return this.request<BaseResponse<Board>>(\n this.config.ENDPOINTS.BOARD(validatedUuid),\n { token },\n );\n }\n\n async createBoard(\n token: string,\n data: BoardCreateRequest,\n ): Promise<BaseResponse<Board>> {\n return this.request<BaseResponse<Board>>(this.config.ENDPOINTS.BOARDS, {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n });\n }\n\n async updateBoard(\n token: string,\n uuid: string,\n data: BoardUpdateRequest,\n ): Promise<BaseResponse<Board>> {\n const validatedUuid = validateUUID(uuid, \"Board UUID\");\n return this.request<BaseResponse<Board>>(\n this.config.ENDPOINTS.BOARD(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteBoard(token: string, uuid: string): Promise<BaseResponse<Board>> {\n const validatedUuid = validateUUID(uuid, \"Board UUID\");\n return this.request<BaseResponse<Board>>(\n this.config.ENDPOINTS.BOARD(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Dailies\n // ===========================================================================\n\n async getDailies(token: string): Promise<BaseResponse<Daily[]>> {\n return this.request<BaseResponse<Daily[]>>(this.config.ENDPOINTS.DAILIES, {\n token,\n });\n }\n\n async getRandomDaily(token: string): Promise<BaseResponse<Daily>> {\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILIES_RANDOM,\n { token },\n );\n }\n\n async getTodayDaily(token: string): Promise<BaseResponse<Daily>> {\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILIES_TODAY,\n { token },\n );\n }\n\n async getDailyByDate(\n token: string,\n date: string,\n ): Promise<BaseResponse<Daily>> {\n // Validate date format (YYYY-MM-DD)\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n throw new Error(\n `Invalid date format: \"${date}\". Expected YYYY-MM-DD format`,\n );\n }\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILIES_DATE(date),\n { token },\n );\n }\n\n async getDaily(token: string, uuid: string): Promise<BaseResponse<Daily>> {\n const validatedUuid = validateUUID(uuid, \"Daily UUID\");\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILY(validatedUuid),\n { token },\n );\n }\n\n async createDaily(\n token: string,\n data: DailyCreateRequest,\n ): Promise<BaseResponse<Daily>> {\n return this.request<BaseResponse<Daily>>(this.config.ENDPOINTS.DAILIES, {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n });\n }\n\n async updateDaily(\n token: string,\n uuid: string,\n data: DailyUpdateRequest,\n ): Promise<BaseResponse<Daily>> {\n const validatedUuid = validateUUID(uuid, \"Daily UUID\");\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILY(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteDaily(token: string, uuid: string): Promise<BaseResponse<Daily>> {\n const validatedUuid = validateUUID(uuid, \"Daily UUID\");\n return this.request<BaseResponse<Daily>>(\n this.config.ENDPOINTS.DAILY(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Challenges\n // ===========================================================================\n\n async getChallenges(\n token: string,\n queryParams?: ChallengeQueryParams,\n ): Promise<BaseResponse<Challenge[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n if (queryParams?.difficulty) {\n params.append(\"difficulty\", queryParams.difficulty);\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.CHALLENGES}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Challenge[]>>(endpoint, { token });\n }\n\n async getRandomChallenge(\n token: string,\n queryParams?: ChallengeQueryParams,\n ): Promise<BaseResponse<Challenge>> {\n const params = createURLSearchParams();\n\n if (queryParams?.level !== undefined) {\n params.append(\"level\", String(queryParams.level));\n }\n if (queryParams?.difficulty) {\n params.append(\"difficulty\", queryParams.difficulty);\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.CHALLENGES_RANDOM}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<Challenge>>(endpoint, { token });\n }\n\n async getChallenge(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Challenge>> {\n const validatedUuid = validateUUID(uuid, \"Challenge UUID\");\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGE(validatedUuid),\n { token },\n );\n }\n\n async createChallenge(\n token: string,\n data: ChallengeCreateRequest,\n ): Promise<BaseResponse<Challenge>> {\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async updateChallenge(\n token: string,\n uuid: string,\n data: ChallengeUpdateRequest,\n ): Promise<BaseResponse<Challenge>> {\n const validatedUuid = validateUUID(uuid, \"Challenge UUID\");\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGE(validatedUuid),\n {\n method: \"PUT\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n async deleteChallenge(\n token: string,\n uuid: string,\n ): Promise<BaseResponse<Challenge>> {\n const validatedUuid = validateUUID(uuid, \"Challenge UUID\");\n return this.request<BaseResponse<Challenge>>(\n this.config.ENDPOINTS.CHALLENGE(validatedUuid),\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Users\n // ===========================================================================\n\n async getUser(\n token: string,\n userId: string,\n ): Promise<BaseResponse<UserInfoResponse>> {\n if (!userId || userId.length === 0 || userId.length > 128) {\n throw new Error(`Invalid userId: \"${userId}\". Expected 1-128 characters`);\n }\n return this.request<BaseResponse<UserInfoResponse>>(\n this.config.ENDPOINTS.USER(userId),\n {\n token,\n },\n );\n }\n\n async getUserSubscription(\n token: string,\n userId: string,\n testMode?: boolean,\n ): Promise<BaseResponse<SubscriptionResult>> {\n if (!userId || userId.length === 0 || userId.length > 128) {\n throw new Error(`Invalid userId: \"${userId}\". Expected 1-128 characters`);\n }\n const endpoint = testMode\n ? `${this.config.ENDPOINTS.USER_SUBSCRIPTIONS(userId)}?testMode=true`\n : this.config.ENDPOINTS.USER_SUBSCRIPTIONS(userId);\n return this.request<BaseResponse<SubscriptionResult>>(endpoint, {\n token,\n });\n }\n\n // ===========================================================================\n // Practices\n // ===========================================================================\n\n /**\n * Get practice counts for all techniques\n */\n async getPracticeCounts(\n token: string,\n ): Promise<BaseResponse<TechniquePracticeCountItem[]>> {\n return this.request<BaseResponse<TechniquePracticeCountItem[]>>(\n this.config.ENDPOINTS.PRACTICES_COUNTS,\n { token },\n );\n }\n\n /**\n * Get a random practice for a specific technique\n */\n async getRandomPractice(\n token: string,\n technique: number,\n ): Promise<BaseResponse<TechniquePractice>> {\n if (technique < 1) {\n throw new Error(`Invalid technique: ${technique}. Expected >= 1`);\n }\n return this.request<BaseResponse<TechniquePractice>>(\n this.config.ENDPOINTS.PRACTICE_RANDOM(technique),\n { token },\n );\n }\n\n /**\n * Create a new practice (admin only)\n */\n async createPractice(\n token: string,\n data: TechniquePracticeCreateRequest,\n ): Promise<BaseResponse<TechniquePractice>> {\n return this.request<BaseResponse<TechniquePractice>>(\n this.config.ENDPOINTS.PRACTICES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n /**\n * Delete all practices (admin only, requires confirm=true)\n */\n async deleteAllPractices(\n token: string,\n ): Promise<BaseResponse<{ deleted: number; message: string }>> {\n return this.request<BaseResponse<{ deleted: number; message: string }>>(\n `${this.config.ENDPOINTS.PRACTICES}?confirm=true`,\n {\n method: \"DELETE\",\n token,\n },\n );\n }\n\n // ===========================================================================\n // Examples\n // ===========================================================================\n\n /**\n * Get example counts for all techniques\n */\n async getExampleCounts(\n token: string,\n ): Promise<BaseResponse<ExampleCountsData>> {\n return this.request<BaseResponse<ExampleCountsData>>(\n this.config.ENDPOINTS.EXAMPLES_COUNTS,\n { token },\n );\n }\n\n /**\n * Get examples, optionally filtered by technique\n */\n async getExamples(\n token: string,\n queryParams?: TechniqueExampleQueryParams,\n ): Promise<BaseResponse<TechniqueExample[]>> {\n const params = createURLSearchParams();\n\n if (queryParams?.technique !== undefined) {\n params.append(\"technique\", String(queryParams.technique));\n }\n\n const query = params.toString();\n const endpoint = `${this.config.ENDPOINTS.EXAMPLES}${query ? `?${query}` : \"\"}`;\n\n return this.request<BaseResponse<TechniqueExample[]>>(endpoint, { token });\n }\n\n /**\n * Create a new example (admin only)\n */\n async createExample(\n token: string,\n data: TechniqueExampleCreateRequest,\n ): Promise<BaseResponse<TechniqueExample>> {\n return this.request<BaseResponse<TechniqueExample>>(\n this.config.ENDPOINTS.EXAMPLES,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n // ===========================================================================\n // Board Counts\n // ===========================================================================\n\n /**\n * Get board counts (total and without techniques)\n */\n async getBoardCounts(token: string): Promise<BaseResponse<BoardCountsData>> {\n return this.request<BaseResponse<BoardCountsData>>(\n this.config.ENDPOINTS.BOARDS_COUNTS,\n { token },\n );\n }\n\n /**\n * Get board counts by technique (count of boards with each technique bit set)\n * Returns Record<number, number> where key is technique ID and value is count\n */\n async getBoardCountsByTechnique(\n token: string,\n ): Promise<BaseResponse<Record<number, number>>> {\n return this.request<BaseResponse<Record<number, number>>>(\n this.config.ENDPOINTS.BOARDS_COUNTS_BY_TECHNIQUE,\n { token },\n );\n }\n\n /**\n * Calculate and update puzzle stats (percentages) on levels and techniques.\n * Requires admin authentication.\n */\n async updatePuzzleStats(token: string): Promise<\n BaseResponse<{\n levels: Record<number, number>;\n techniques: Record<number, number>;\n }>\n > {\n return this.request<\n BaseResponse<{\n levels: Record<number, number>;\n techniques: Record<number, number>;\n }>\n >(this.config.ENDPOINTS.BOARDS_UPDATE_STATS, {\n method: \"POST\",\n token,\n });\n }\n\n // ===========================================================================\n // Solver\n // ===========================================================================\n\n /**\n * Builds an endpoint path with query parameters for solver endpoints\n */\n private buildSolverUrl(\n endpoint: string,\n params: Record<string, string | boolean | undefined>,\n ): string {\n const searchParams = createURLSearchParams();\n // Sort keys alphabetically to match Kotlin behavior\n const sortedKeys = Object.keys(params).sort();\n for (const key of sortedKeys) {\n const value = params[key];\n if (value !== undefined) {\n searchParams.append(key, String(value));\n }\n }\n const query = searchParams.toString();\n // Return endpoint + query only, baseUrl is added by request()\n return `${endpoint}${query ? `?${query}` : \"\"}`;\n }\n\n /**\n * Get hints for solving a Sudoku puzzle\n * @throws {HintAccessDeniedError} When hint level exceeds user's subscription tier\n */\n async solverSolve(\n token: string,\n options: SolveOptions,\n ): Promise<BaseResponse<SolveData>> {\n const url = this.buildSolverUrl(this.config.ENDPOINTS.SOLVER_SOLVE, {\n original: options.original,\n user: options.user,\n autopencilmarks: options.autoPencilmarks,\n pencilmarks: options.pencilmarks,\n filters: options.filters,\n techniques: options.techniques,\n });\n\n const fullUrl = `${this.baseUrl}${url}`;\n const requestHeaders: Record<string, string> = {\n ...this.headers,\n };\n\n if (token) {\n requestHeaders[\"Authorization\"] = `Bearer ${token}`;\n }\n\n // Use 120 second timeout for solve (advanced techniques can be slow)\n const response = await this.networkClient.request<\n BaseResponse<SolveData> | HintAccessDeniedResponse\n >(fullUrl, {\n method: \"GET\",\n headers: requestHeaders,\n timeout: 120000,\n });\n\n // Check for hint access denied (402)\n if (response.status === 402 && response.data) {\n const errorResponse = response.data as HintAccessDeniedResponse;\n if (errorResponse.error?.code === \"HINT_ACCESS_DENIED\") {\n throw new HintAccessDeniedError(errorResponse.error);\n }\n }\n\n // Check for other errors\n if (!response.ok || response.data === undefined) {\n throw new Error(\"Failed to get hints from solver\");\n }\n\n return (await decryptSolutionFields(\n response.data,\n )) as BaseResponse<SolveData>;\n }\n\n /**\n * Validate that a Sudoku puzzle has a unique solution.\n * Uses a longer timeout (120s) because validation involves iterative solving.\n */\n async solverValidate(\n token: string,\n options: ValidateOptions,\n ): Promise<BaseResponse<ValidateData>> {\n const url = this.buildSolverUrl(this.config.ENDPOINTS.SOLVER_VALIDATE, {\n original: options.original,\n });\n\n // Use 120 second timeout for validation (iterative solving can be slow)\n return this.request<BaseResponse<ValidateData>>(url, {\n token,\n timeout: 120000,\n });\n }\n\n /**\n * Generate a new random Sudoku puzzle\n */\n async solverGenerate(\n token: string,\n options: GenerateOptions = {},\n ): Promise<BaseResponse<GenerateData>> {\n const url = this.buildSolverUrl(this.config.ENDPOINTS.SOLVER_GENERATE, {\n symmetrical: options.symmetrical,\n });\n\n return this.request<BaseResponse<GenerateData>>(url, { token });\n }\n\n // ===========================================================================\n // Play (Game Session) Endpoints\n // ===========================================================================\n\n /**\n * Start a new game session\n */\n async playStart(\n token: string,\n data: GameStartRequest,\n ): Promise<BaseResponse<GameStartResponse>> {\n return this.request<BaseResponse<GameStartResponse>>(\n this.config.ENDPOINTS.PLAY_START,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n /**\n * Finish the current game session and get rewards\n */\n async playFinish(\n token: string,\n data: GameFinishRequest,\n ): Promise<BaseResponse<GameFinishResponse>> {\n return this.request<BaseResponse<GameFinishResponse>>(\n this.config.ENDPOINTS.PLAY_FINISH,\n {\n method: \"POST\",\n body: data as unknown as Record<string, unknown>,\n token,\n },\n );\n }\n\n // ===========================================================================\n // Gamification Endpoints\n // ===========================================================================\n\n /**\n * Get user's gamification stats (points, level, badges)\n */\n async getGamificationStats(\n token: string,\n ): Promise<BaseResponse<GamificationStats>> {\n return this.request<BaseResponse<GamificationStats>>(\n this.config.ENDPOINTS.GAMIFICATION_STATS,\n { token },\n );\n }\n\n /**\n * Get all badge definitions (public)\n */\n async getBadgeDefinitions(): Promise<BaseResponse<BadgeDefinition[]>> {\n return this.request<BaseResponse<BadgeDefinition[]>>(\n this.config.ENDPOINTS.GAMIFICATION_BADGES,\n );\n }\n\n /**\n * Get user's point transaction history\n */\n async getPointHistory(\n token: string,\n options?: { limit?: number; offset?: number },\n ): Promise<BaseResponse<PointTransaction[]>> {\n let endpoint = this.config.ENDPOINTS.GAMIFICATION_HISTORY;\n if (options?.limit || options?.offset) {\n const params = createURLSearchParams();\n if (options.limit) params.append(\"limit\", String(options.limit));\n if (options.offset) params.append(\"offset\", String(options.offset));\n endpoint = `${endpoint}?${params.toString()}`;\n }\n return this.request<BaseResponse<PointTransaction[]>>(endpoint, { token });\n }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Factory function to create a new SudojoClient instance.\n *\n * Equivalent to `new SudojoClient(networkClient, baseUrl)` but useful\n * for dependency injection and functional composition patterns.\n *\n * @param networkClient - Network client for making HTTP requests\n * @param baseUrl - Base URL for the Sudojo API\n * @returns A new SudojoClient instance\n */\nexport const createSudojoClient = (\n networkClient: NetworkClient,\n baseUrl: string,\n): SudojoClient => {\n return new SudojoClient(networkClient, baseUrl);\n};\n\n// =============================================================================\n// Utility Exports\n// =============================================================================\n\n/**\n * Re-exported UUID validation utilities from `@sudobility/sudojo_types`.\n *\n * These are used internally by the SudojoClient for parameter validation\n * and are also exported for consumer convenience. Use `isValidUUID` for\n * boolean checks and `validateUUID` when you want an error thrown on invalid input.\n *\n * - `isValidUUID(value)` - Returns true if the string is a valid UUID v4\n * - `validateUUID(value, label)` - Returns the UUID or throws an Error with the label\n */\nexport { isValidUUID, validateUUID };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/sudojo_client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.92",
|
|
4
4
|
"description": "TypeScript client library for Sudojo API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"author": "Sudobility Team",
|
|
37
37
|
"license": "BUSL-1.1",
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@sudobility/di": "^1.5.
|
|
40
|
-
"@sudobility/sudojo_types": "^1.2.
|
|
41
|
-
"@sudobility/types": "^1.9.
|
|
39
|
+
"@sudobility/di": "^1.5.48",
|
|
40
|
+
"@sudobility/sudojo_types": "^1.2.43",
|
|
41
|
+
"@sudobility/types": "^1.9.59",
|
|
42
42
|
"@tanstack/react-query": ">=5.0.0",
|
|
43
43
|
"react": ">=18.0.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@eslint/js": "^9.38.0",
|
|
47
|
-
"@sudobility/di": "^1.5.
|
|
48
|
-
"@sudobility/sudojo_types": "^1.2.
|
|
49
|
-
"@sudobility/types": "^1.9.
|
|
47
|
+
"@sudobility/di": "^1.5.48",
|
|
48
|
+
"@sudobility/sudojo_types": "^1.2.43",
|
|
49
|
+
"@sudobility/types": "^1.9.59",
|
|
50
50
|
"@tanstack/react-query": "^5.90.5",
|
|
51
51
|
"@testing-library/react": "^16.3.0",
|
|
52
52
|
"@types/node": "^24.9.1",
|