@markwharton/pwa-core 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/__tests__/auth/apiKey.test.d.ts +1 -0
  2. package/dist/__tests__/auth/apiKey.test.js +80 -0
  3. package/dist/__tests__/auth/token.test.d.ts +1 -0
  4. package/dist/__tests__/auth/token.test.js +189 -0
  5. package/dist/__tests__/auth/types.test.d.ts +1 -0
  6. package/dist/__tests__/auth/types.test.js +77 -0
  7. package/dist/__tests__/client/api.test.d.ts +1 -0
  8. package/dist/__tests__/client/api.test.js +269 -0
  9. package/dist/__tests__/client/apiError.test.d.ts +1 -0
  10. package/dist/__tests__/client/apiError.test.js +58 -0
  11. package/dist/__tests__/http/responses.test.d.ts +1 -0
  12. package/dist/__tests__/http/responses.test.js +112 -0
  13. package/dist/__tests__/http/status.test.d.ts +1 -0
  14. package/dist/__tests__/http/status.test.js +27 -0
  15. package/dist/__tests__/storage/client.test.d.ts +1 -0
  16. package/dist/__tests__/storage/client.test.js +173 -0
  17. package/dist/__tests__/storage/keys.test.d.ts +1 -0
  18. package/dist/__tests__/storage/keys.test.js +47 -0
  19. package/dist/__tests__/types.test.d.ts +1 -0
  20. package/dist/__tests__/types.test.js +56 -0
  21. package/dist/auth/apiKey.d.ts +24 -7
  22. package/dist/auth/apiKey.js +24 -7
  23. package/dist/auth/token.d.ts +37 -10
  24. package/dist/auth/token.js +37 -10
  25. package/dist/auth/types.d.ts +21 -3
  26. package/dist/auth/types.js +21 -3
  27. package/dist/client/api.d.ts +70 -9
  28. package/dist/client/api.js +70 -9
  29. package/dist/client/apiError.d.ts +22 -5
  30. package/dist/client/apiError.js +22 -5
  31. package/dist/http/responses.d.ts +57 -8
  32. package/dist/http/responses.js +57 -8
  33. package/dist/storage/client.d.ts +29 -6
  34. package/dist/storage/client.js +29 -6
  35. package/dist/types.d.ts +16 -3
  36. package/dist/types.js +16 -3
  37. package/package.json +1 -1
@@ -1,29 +1,56 @@
1
1
  import { Result } from '../types';
2
2
  /**
3
- * Initialize JWT secret - call once at startup
4
- * Fails fast if secret is missing or too short
3
+ * Initializes the JWT authentication system. Call once at application startup.
4
+ * @param secret - The JWT secret key (from environment variable)
5
+ * @param minLength - Minimum required secret length (default: 32)
6
+ * @throws Error if secret is missing or too short
7
+ * @example
8
+ * initAuth(process.env.JWT_SECRET);
5
9
  */
6
10
  export declare function initAuth(secret: string | undefined, minLength?: number): void;
7
11
  /**
8
- * Get the JWT secret (throws if not initialized)
12
+ * Gets the configured JWT secret.
13
+ * @returns The JWT secret string
14
+ * @throws Error if initAuth() has not been called
9
15
  */
10
16
  export declare function getJwtSecret(): string;
11
17
  /**
12
- * Extract Bearer token from Authorization header
18
+ * Extracts the Bearer token from an Authorization header.
19
+ * @param authHeader - The Authorization header value
20
+ * @returns The token string, or null if not a valid Bearer token
21
+ * @example
22
+ * const token = extractToken(request.headers.get('Authorization'));
13
23
  */
14
24
  export declare function extractToken(authHeader: string | null): string | null;
15
25
  /**
16
- * Validate and decode a JWT token
17
- * Generic type allows project-specific payload shapes
18
- *
19
- * @returns Result with decoded payload or error message
26
+ * Validates and decodes a JWT token.
27
+ * @typeParam T - The expected payload type (extends object)
28
+ * @param token - The JWT token string to validate
29
+ * @returns Result with decoded payload on success, or error message on failure
30
+ * @example
31
+ * const result = validateToken<UserPayload>(token);
32
+ * if (result.ok) {
33
+ * console.log(result.data.username);
34
+ * }
20
35
  */
21
36
  export declare function validateToken<T extends object>(token: string): Result<T>;
22
37
  /**
23
- * Generate a JWT token with custom payload
38
+ * Generates a signed JWT token with the given payload.
39
+ * @typeParam T - The payload type (extends object)
40
+ * @param payload - The data to encode in the token
41
+ * @param expiresIn - Token expiration time (default: '7d')
42
+ * @returns The signed JWT token string
43
+ * @example
44
+ * const token = generateToken({ userId: '123', role: 'admin' }, '1h');
24
45
  */
25
46
  export declare function generateToken<T extends object>(payload: T, expiresIn?: string): string;
26
47
  /**
27
- * Generate a long-lived token (e.g., for machine/API access)
48
+ * Generates a long-lived JWT token for machine/API access.
49
+ * @typeParam T - The payload type (extends object)
50
+ * @param payload - The data to encode in the token
51
+ * @param expiresInDays - Token expiration in days (default: 3650 ≈ 10 years)
52
+ * @returns The signed JWT token string
53
+ * @example
54
+ * const apiToken = generateLongLivedToken({ machineId: 'server-1' });
28
55
  */
29
56
  export declare function generateLongLivedToken<T extends object>(payload: T, expiresInDays?: number): string;
@@ -17,8 +17,12 @@ const types_1 = require("../types");
17
17
  */
18
18
  let jwtSecret = null;
19
19
  /**
20
- * Initialize JWT secret - call once at startup
21
- * Fails fast if secret is missing or too short
20
+ * Initializes the JWT authentication system. Call once at application startup.
21
+ * @param secret - The JWT secret key (from environment variable)
22
+ * @param minLength - Minimum required secret length (default: 32)
23
+ * @throws Error if secret is missing or too short
24
+ * @example
25
+ * initAuth(process.env.JWT_SECRET);
22
26
  */
23
27
  function initAuth(secret, minLength = 32) {
24
28
  if (!secret || secret.length < minLength) {
@@ -27,7 +31,9 @@ function initAuth(secret, minLength = 32) {
27
31
  jwtSecret = secret;
28
32
  }
29
33
  /**
30
- * Get the JWT secret (throws if not initialized)
34
+ * Gets the configured JWT secret.
35
+ * @returns The JWT secret string
36
+ * @throws Error if initAuth() has not been called
31
37
  */
32
38
  function getJwtSecret() {
33
39
  if (!jwtSecret) {
@@ -36,7 +42,11 @@ function getJwtSecret() {
36
42
  return jwtSecret;
37
43
  }
38
44
  /**
39
- * Extract Bearer token from Authorization header
45
+ * Extracts the Bearer token from an Authorization header.
46
+ * @param authHeader - The Authorization header value
47
+ * @returns The token string, or null if not a valid Bearer token
48
+ * @example
49
+ * const token = extractToken(request.headers.get('Authorization'));
40
50
  */
41
51
  function extractToken(authHeader) {
42
52
  if (!authHeader?.startsWith('Bearer ')) {
@@ -45,10 +55,15 @@ function extractToken(authHeader) {
45
55
  return authHeader.slice(7);
46
56
  }
47
57
  /**
48
- * Validate and decode a JWT token
49
- * Generic type allows project-specific payload shapes
50
- *
51
- * @returns Result with decoded payload or error message
58
+ * Validates and decodes a JWT token.
59
+ * @typeParam T - The expected payload type (extends object)
60
+ * @param token - The JWT token string to validate
61
+ * @returns Result with decoded payload on success, or error message on failure
62
+ * @example
63
+ * const result = validateToken<UserPayload>(token);
64
+ * if (result.ok) {
65
+ * console.log(result.data.username);
66
+ * }
52
67
  */
53
68
  function validateToken(token) {
54
69
  try {
@@ -64,13 +79,25 @@ function validateToken(token) {
64
79
  }
65
80
  }
66
81
  /**
67
- * Generate a JWT token with custom payload
82
+ * Generates a signed JWT token with the given payload.
83
+ * @typeParam T - The payload type (extends object)
84
+ * @param payload - The data to encode in the token
85
+ * @param expiresIn - Token expiration time (default: '7d')
86
+ * @returns The signed JWT token string
87
+ * @example
88
+ * const token = generateToken({ userId: '123', role: 'admin' }, '1h');
68
89
  */
69
90
  function generateToken(payload, expiresIn = '7d') {
70
91
  return jsonwebtoken_1.default.sign(payload, getJwtSecret(), { expiresIn });
71
92
  }
72
93
  /**
73
- * Generate a long-lived token (e.g., for machine/API access)
94
+ * Generates a long-lived JWT token for machine/API access.
95
+ * @typeParam T - The payload type (extends object)
96
+ * @param payload - The data to encode in the token
97
+ * @param expiresInDays - Token expiration in days (default: 3650 ≈ 10 years)
98
+ * @returns The signed JWT token string
99
+ * @example
100
+ * const apiToken = generateLongLivedToken({ machineId: 'server-1' });
74
101
  */
75
102
  function generateLongLivedToken(payload, expiresInDays = 3650) {
76
103
  return jsonwebtoken_1.default.sign(payload, getJwtSecret(), { expiresIn: `${expiresInDays}d` });
@@ -32,14 +32,32 @@ export interface RoleTokenPayload extends BaseJwtPayload {
32
32
  viewerTokenId?: string;
33
33
  }
34
34
  /**
35
- * Type guard to check if payload has a username
35
+ * Type guard to check if a JWT payload contains a username field.
36
+ * @param payload - The JWT payload to check
37
+ * @returns True if payload has a string username field
38
+ * @example
39
+ * if (hasUsername(payload)) {
40
+ * console.log(payload.username); // TypeScript knows username exists
41
+ * }
36
42
  */
37
43
  export declare function hasUsername(payload: BaseJwtPayload): payload is UsernameTokenPayload;
38
44
  /**
39
- * Type guard to check if payload has a role
45
+ * Type guard to check if a JWT payload contains a role field.
46
+ * @param payload - The JWT payload to check
47
+ * @returns True if payload has a role field
48
+ * @example
49
+ * if (hasRole(payload)) {
50
+ * console.log(payload.role); // 'admin' | 'viewer'
51
+ * }
40
52
  */
41
53
  export declare function hasRole(payload: BaseJwtPayload): payload is RoleTokenPayload;
42
54
  /**
43
- * Type guard to check if payload is admin
55
+ * Checks if a JWT payload represents an admin user.
56
+ * @param payload - The JWT payload to check
57
+ * @returns True if payload has role='admin'
58
+ * @example
59
+ * if (!isAdmin(payload)) {
60
+ * return httpForbidden('Admin access required');
61
+ * }
44
62
  */
45
63
  export declare function isAdmin(payload: BaseJwtPayload): boolean;
@@ -4,19 +4,37 @@ exports.hasUsername = hasUsername;
4
4
  exports.hasRole = hasRole;
5
5
  exports.isAdmin = isAdmin;
6
6
  /**
7
- * Type guard to check if payload has a username
7
+ * Type guard to check if a JWT payload contains a username field.
8
+ * @param payload - The JWT payload to check
9
+ * @returns True if payload has a string username field
10
+ * @example
11
+ * if (hasUsername(payload)) {
12
+ * console.log(payload.username); // TypeScript knows username exists
13
+ * }
8
14
  */
9
15
  function hasUsername(payload) {
10
16
  return 'username' in payload && typeof payload.username === 'string';
11
17
  }
12
18
  /**
13
- * Type guard to check if payload has a role
19
+ * Type guard to check if a JWT payload contains a role field.
20
+ * @param payload - The JWT payload to check
21
+ * @returns True if payload has a role field
22
+ * @example
23
+ * if (hasRole(payload)) {
24
+ * console.log(payload.role); // 'admin' | 'viewer'
25
+ * }
14
26
  */
15
27
  function hasRole(payload) {
16
28
  return 'role' in payload;
17
29
  }
18
30
  /**
19
- * Type guard to check if payload is admin
31
+ * Checks if a JWT payload represents an admin user.
32
+ * @param payload - The JWT payload to check
33
+ * @returns True if payload has role='admin'
34
+ * @example
35
+ * if (!isAdmin(payload)) {
36
+ * return httpForbidden('Admin access required');
37
+ * }
20
38
  */
21
39
  function isAdmin(payload) {
22
40
  return hasRole(payload) && payload.role === 'admin';
@@ -1,37 +1,98 @@
1
1
  import { ApiResponse } from './types';
2
2
  /**
3
- * Initialize the API client
3
+ * Initializes the API client with token retrieval and optional 401 handler.
4
+ * Call once at application startup.
5
+ * @param config - Client configuration
6
+ * @param config.getToken - Function that returns the current auth token (or null)
7
+ * @param config.onUnauthorized - Optional callback for 401 responses (e.g., redirect to login)
8
+ * @example
9
+ * initApiClient({
10
+ * getToken: () => localStorage.getItem('token'),
11
+ * onUnauthorized: () => window.location.href = '/login'
12
+ * });
4
13
  */
5
14
  export declare function initApiClient(config: {
6
15
  getToken: () => string | null;
7
16
  onUnauthorized?: () => void;
8
17
  }): void;
9
18
  /**
10
- * Make an authenticated API call
19
+ * Makes an authenticated API call. Throws ApiError on non-2xx responses.
20
+ * @typeParam T - The expected response data type
21
+ * @param url - The API endpoint URL
22
+ * @param options - Optional fetch options (method, body, headers)
23
+ * @returns The parsed JSON response
24
+ * @throws ApiError on non-2xx HTTP status
25
+ * @example
26
+ * const user = await apiCall<User>('/api/users/123');
11
27
  */
12
28
  export declare function apiCall<T>(url: string, options?: RequestInit): Promise<T>;
13
29
  /**
14
- * GET request helper
30
+ * Makes an authenticated GET request.
31
+ * @typeParam T - The expected response data type
32
+ * @param url - The API endpoint URL
33
+ * @returns The parsed JSON response
34
+ * @throws ApiError on non-2xx HTTP status
35
+ * @example
36
+ * const users = await apiGet<User[]>('/api/users');
15
37
  */
16
38
  export declare function apiGet<T>(url: string): Promise<T>;
17
39
  /**
18
- * POST request helper
40
+ * Makes an authenticated POST request.
41
+ * @typeParam T - The expected response data type
42
+ * @param url - The API endpoint URL
43
+ * @param body - Optional request body (will be JSON stringified)
44
+ * @returns The parsed JSON response
45
+ * @throws ApiError on non-2xx HTTP status
46
+ * @example
47
+ * const user = await apiPost<User>('/api/users', { name: 'John' });
19
48
  */
20
49
  export declare function apiPost<T>(url: string, body?: unknown): Promise<T>;
21
50
  /**
22
- * PUT request helper
51
+ * Makes an authenticated PUT request.
52
+ * @typeParam T - The expected response data type
53
+ * @param url - The API endpoint URL
54
+ * @param body - Optional request body (will be JSON stringified)
55
+ * @returns The parsed JSON response
56
+ * @throws ApiError on non-2xx HTTP status
57
+ * @example
58
+ * const user = await apiPut<User>('/api/users/123', { name: 'Jane' });
23
59
  */
24
60
  export declare function apiPut<T>(url: string, body?: unknown): Promise<T>;
25
61
  /**
26
- * PATCH request helper
62
+ * Makes an authenticated PATCH request.
63
+ * @typeParam T - The expected response data type
64
+ * @param url - The API endpoint URL
65
+ * @param body - Optional request body (will be JSON stringified)
66
+ * @returns The parsed JSON response
67
+ * @throws ApiError on non-2xx HTTP status
68
+ * @example
69
+ * const user = await apiPatch<User>('/api/users/123', { status: 'active' });
27
70
  */
28
71
  export declare function apiPatch<T>(url: string, body?: unknown): Promise<T>;
29
72
  /**
30
- * DELETE request helper
73
+ * Makes an authenticated DELETE request.
74
+ * @typeParam T - The expected response data type
75
+ * @param url - The API endpoint URL
76
+ * @returns The parsed JSON response
77
+ * @throws ApiError on non-2xx HTTP status
78
+ * @example
79
+ * await apiDelete('/api/users/123');
31
80
  */
32
81
  export declare function apiDelete<T>(url: string): Promise<T>;
33
82
  /**
34
- * Alternative: Response wrapper style (like financial-tracker's authJsonFetch)
35
- * Preserves actual HTTP status code on success
83
+ * Makes an authenticated API call with Result-style error handling.
84
+ * Unlike apiCall, this never throws - errors are returned in the response.
85
+ * Preserves actual HTTP status code on success (not always 200).
86
+ * @typeParam T - The expected response data type
87
+ * @param url - The API endpoint URL
88
+ * @param options - Optional fetch options (method, body, headers)
89
+ * @returns ApiResponse with ok, status, data (on success), or error (on failure)
90
+ * @example
91
+ * const response = await apiCallSafe<User>('/api/users/123');
92
+ * if (response.ok) {
93
+ * console.log(response.data);
94
+ * } else {
95
+ * console.error(response.error);
96
+ * }
36
97
  */
37
98
  export declare function apiCallSafe<T>(url: string, options?: RequestInit): Promise<ApiResponse<T>>;
@@ -17,14 +17,30 @@ let getToken = null;
17
17
  // Callback for 401 responses (e.g., redirect to login)
18
18
  let onUnauthorized = null;
19
19
  /**
20
- * Initialize the API client
20
+ * Initializes the API client with token retrieval and optional 401 handler.
21
+ * Call once at application startup.
22
+ * @param config - Client configuration
23
+ * @param config.getToken - Function that returns the current auth token (or null)
24
+ * @param config.onUnauthorized - Optional callback for 401 responses (e.g., redirect to login)
25
+ * @example
26
+ * initApiClient({
27
+ * getToken: () => localStorage.getItem('token'),
28
+ * onUnauthorized: () => window.location.href = '/login'
29
+ * });
21
30
  */
22
31
  function initApiClient(config) {
23
32
  getToken = config.getToken;
24
33
  onUnauthorized = config.onUnauthorized ?? null;
25
34
  }
26
35
  /**
27
- * Make an authenticated API call
36
+ * Makes an authenticated API call. Throws ApiError on non-2xx responses.
37
+ * @typeParam T - The expected response data type
38
+ * @param url - The API endpoint URL
39
+ * @param options - Optional fetch options (method, body, headers)
40
+ * @returns The parsed JSON response
41
+ * @throws ApiError on non-2xx HTTP status
42
+ * @example
43
+ * const user = await apiCall<User>('/api/users/123');
28
44
  */
29
45
  async function apiCall(url, options = {}) {
30
46
  const token = getToken?.();
@@ -61,13 +77,26 @@ async function apiCall(url, options = {}) {
61
77
  return JSON.parse(text);
62
78
  }
63
79
  /**
64
- * GET request helper
80
+ * Makes an authenticated GET request.
81
+ * @typeParam T - The expected response data type
82
+ * @param url - The API endpoint URL
83
+ * @returns The parsed JSON response
84
+ * @throws ApiError on non-2xx HTTP status
85
+ * @example
86
+ * const users = await apiGet<User[]>('/api/users');
65
87
  */
66
88
  async function apiGet(url) {
67
89
  return apiCall(url, { method: 'GET' });
68
90
  }
69
91
  /**
70
- * POST request helper
92
+ * Makes an authenticated POST request.
93
+ * @typeParam T - The expected response data type
94
+ * @param url - The API endpoint URL
95
+ * @param body - Optional request body (will be JSON stringified)
96
+ * @returns The parsed JSON response
97
+ * @throws ApiError on non-2xx HTTP status
98
+ * @example
99
+ * const user = await apiPost<User>('/api/users', { name: 'John' });
71
100
  */
72
101
  async function apiPost(url, body) {
73
102
  return apiCall(url, {
@@ -76,7 +105,14 @@ async function apiPost(url, body) {
76
105
  });
77
106
  }
78
107
  /**
79
- * PUT request helper
108
+ * Makes an authenticated PUT request.
109
+ * @typeParam T - The expected response data type
110
+ * @param url - The API endpoint URL
111
+ * @param body - Optional request body (will be JSON stringified)
112
+ * @returns The parsed JSON response
113
+ * @throws ApiError on non-2xx HTTP status
114
+ * @example
115
+ * const user = await apiPut<User>('/api/users/123', { name: 'Jane' });
80
116
  */
81
117
  async function apiPut(url, body) {
82
118
  return apiCall(url, {
@@ -85,7 +121,14 @@ async function apiPut(url, body) {
85
121
  });
86
122
  }
87
123
  /**
88
- * PATCH request helper
124
+ * Makes an authenticated PATCH request.
125
+ * @typeParam T - The expected response data type
126
+ * @param url - The API endpoint URL
127
+ * @param body - Optional request body (will be JSON stringified)
128
+ * @returns The parsed JSON response
129
+ * @throws ApiError on non-2xx HTTP status
130
+ * @example
131
+ * const user = await apiPatch<User>('/api/users/123', { status: 'active' });
89
132
  */
90
133
  async function apiPatch(url, body) {
91
134
  return apiCall(url, {
@@ -94,14 +137,32 @@ async function apiPatch(url, body) {
94
137
  });
95
138
  }
96
139
  /**
97
- * DELETE request helper
140
+ * Makes an authenticated DELETE request.
141
+ * @typeParam T - The expected response data type
142
+ * @param url - The API endpoint URL
143
+ * @returns The parsed JSON response
144
+ * @throws ApiError on non-2xx HTTP status
145
+ * @example
146
+ * await apiDelete('/api/users/123');
98
147
  */
99
148
  async function apiDelete(url) {
100
149
  return apiCall(url, { method: 'DELETE' });
101
150
  }
102
151
  /**
103
- * Alternative: Response wrapper style (like financial-tracker's authJsonFetch)
104
- * Preserves actual HTTP status code on success
152
+ * Makes an authenticated API call with Result-style error handling.
153
+ * Unlike apiCall, this never throws - errors are returned in the response.
154
+ * Preserves actual HTTP status code on success (not always 200).
155
+ * @typeParam T - The expected response data type
156
+ * @param url - The API endpoint URL
157
+ * @param options - Optional fetch options (method, body, headers)
158
+ * @returns ApiResponse with ok, status, data (on success), or error (on failure)
159
+ * @example
160
+ * const response = await apiCallSafe<User>('/api/users/123');
161
+ * if (response.ok) {
162
+ * console.log(response.data);
163
+ * } else {
164
+ * console.error(response.error);
165
+ * }
105
166
  */
106
167
  async function apiCallSafe(url, options = {}) {
107
168
  const token = getToken?.();
@@ -1,21 +1,38 @@
1
1
  /**
2
- * Custom error class for API errors
3
- * Preserves status code and error message from server
2
+ * Custom error class for API errors.
3
+ * Preserves HTTP status code and error message from the server.
4
+ * @example
5
+ * try {
6
+ * await apiGet('/users/123');
7
+ * } catch (error) {
8
+ * if (error instanceof ApiError && error.isNotFound()) {
9
+ * console.log('User not found');
10
+ * }
11
+ * }
4
12
  */
5
13
  export declare class ApiError extends Error {
6
14
  status: number;
7
15
  details?: string | undefined;
16
+ /**
17
+ * Creates a new ApiError instance.
18
+ * @param status - The HTTP status code
19
+ * @param message - The error message
20
+ * @param details - Optional additional error details
21
+ */
8
22
  constructor(status: number, message: string, details?: string | undefined);
9
23
  /**
10
- * Check if this is an authentication error
24
+ * Checks if this is a 401 Unauthorized error.
25
+ * @returns True if status is 401
11
26
  */
12
27
  isUnauthorized(): boolean;
13
28
  /**
14
- * Check if this is a not found error
29
+ * Checks if this is a 404 Not Found error.
30
+ * @returns True if status is 404
15
31
  */
16
32
  isNotFound(): boolean;
17
33
  /**
18
- * Check if this is a validation error
34
+ * Checks if this is a 400 Bad Request error.
35
+ * @returns True if status is 400
19
36
  */
20
37
  isBadRequest(): boolean;
21
38
  }
@@ -2,10 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ApiError = void 0;
4
4
  /**
5
- * Custom error class for API errors
6
- * Preserves status code and error message from server
5
+ * Custom error class for API errors.
6
+ * Preserves HTTP status code and error message from the server.
7
+ * @example
8
+ * try {
9
+ * await apiGet('/users/123');
10
+ * } catch (error) {
11
+ * if (error instanceof ApiError && error.isNotFound()) {
12
+ * console.log('User not found');
13
+ * }
14
+ * }
7
15
  */
8
16
  class ApiError extends Error {
17
+ /**
18
+ * Creates a new ApiError instance.
19
+ * @param status - The HTTP status code
20
+ * @param message - The error message
21
+ * @param details - Optional additional error details
22
+ */
9
23
  constructor(status, message, details) {
10
24
  super(message);
11
25
  this.status = status;
@@ -13,19 +27,22 @@ class ApiError extends Error {
13
27
  this.name = 'ApiError';
14
28
  }
15
29
  /**
16
- * Check if this is an authentication error
30
+ * Checks if this is a 401 Unauthorized error.
31
+ * @returns True if status is 401
17
32
  */
18
33
  isUnauthorized() {
19
34
  return this.status === 401;
20
35
  }
21
36
  /**
22
- * Check if this is a not found error
37
+ * Checks if this is a 404 Not Found error.
38
+ * @returns True if status is 404
23
39
  */
24
40
  isNotFound() {
25
41
  return this.status === 404;
26
42
  }
27
43
  /**
28
- * Check if this is a validation error
44
+ * Checks if this is a 400 Bad Request error.
45
+ * @returns True if status is 400
29
46
  */
30
47
  isBadRequest() {
31
48
  return this.status === 400;
@@ -1,33 +1,82 @@
1
1
  import { HttpResponseInit, InvocationContext } from '@azure/functions';
2
2
  /**
3
- * Create a 400 Bad Request response
3
+ * Creates a 400 Bad Request response.
4
+ * @param message - The error message to return
5
+ * @returns Azure Functions HttpResponseInit object
6
+ * @example
7
+ * if (!body.email) return badRequestResponse('Email is required');
4
8
  */
5
9
  export declare function badRequestResponse(message: string): HttpResponseInit;
6
10
  /**
7
- * Create a 401 Unauthorized response
11
+ * Creates a 401 Unauthorized response.
12
+ * @param message - The error message (default: 'Unauthorized')
13
+ * @returns Azure Functions HttpResponseInit object
14
+ * @example
15
+ * if (!token) return unauthorizedResponse();
8
16
  */
9
17
  export declare function unauthorizedResponse(message?: string): HttpResponseInit;
10
18
  /**
11
- * Create a 403 Forbidden response
19
+ * Creates a 403 Forbidden response.
20
+ * @param message - The error message (default: 'Forbidden')
21
+ * @returns Azure Functions HttpResponseInit object
22
+ * @example
23
+ * if (!isAdmin(payload)) return forbiddenResponse('Admin access required');
12
24
  */
13
25
  export declare function forbiddenResponse(message?: string): HttpResponseInit;
14
26
  /**
15
- * Create a 404 Not Found response
27
+ * Creates a 404 Not Found response.
28
+ * @param resource - The name of the resource that wasn't found
29
+ * @returns Azure Functions HttpResponseInit object
30
+ * @example
31
+ * if (!user) return notFoundResponse('User');
32
+ * // Returns: { error: 'User not found' }
16
33
  */
17
34
  export declare function notFoundResponse(resource: string): HttpResponseInit;
18
35
  /**
19
- * Create a 409 Conflict response
36
+ * Creates a 409 Conflict response.
37
+ * @param message - The conflict error message
38
+ * @returns Azure Functions HttpResponseInit object
39
+ * @example
40
+ * if (existingUser) return conflictResponse('Email already registered');
20
41
  */
21
42
  export declare function conflictResponse(message: string): HttpResponseInit;
22
43
  /**
23
- * Handle unexpected errors safely (logs details, returns generic message)
44
+ * Handles unexpected errors safely by logging details and returning a generic message.
45
+ * Use in catch blocks to avoid exposing internal error details to clients.
46
+ * @param error - The caught error
47
+ * @param context - Azure Functions InvocationContext for logging
48
+ * @returns Azure Functions HttpResponseInit with 500 status
49
+ * @example
50
+ * try {
51
+ * await riskyOperation();
52
+ * } catch (error) {
53
+ * return handleFunctionError(error, context);
54
+ * }
24
55
  */
25
56
  export declare function handleFunctionError(error: unknown, context: InvocationContext): HttpResponseInit;
26
57
  /**
27
- * Check if an Azure Table Storage error is "not found"
58
+ * Checks if an error is an Azure Table Storage "not found" error.
59
+ * @param error - The caught error
60
+ * @returns True if error has statusCode 404
61
+ * @example
62
+ * try {
63
+ * await tableClient.getEntity(pk, rk);
64
+ * } catch (error) {
65
+ * if (isNotFoundError(error)) return notFoundResponse('Entity');
66
+ * throw error;
67
+ * }
28
68
  */
29
69
  export declare function isNotFoundError(error: unknown): boolean;
30
70
  /**
31
- * Check if an Azure Table Storage error is "conflict"
71
+ * Checks if an error is an Azure Table Storage "conflict" error.
72
+ * @param error - The caught error
73
+ * @returns True if error has statusCode 409
74
+ * @example
75
+ * try {
76
+ * await tableClient.createEntity(entity);
77
+ * } catch (error) {
78
+ * if (isConflictError(error)) return conflictResponse('Entity already exists');
79
+ * throw error;
80
+ * }
32
81
  */
33
82
  export declare function isConflictError(error: unknown): boolean;