@markwharton/pwa-core 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) 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 +212 -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 +334 -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__/server/auth/apiKey.test.d.ts +1 -0
  16. package/dist/__tests__/server/auth/apiKey.test.js +80 -0
  17. package/dist/__tests__/server/auth/token.test.d.ts +1 -0
  18. package/dist/__tests__/server/auth/token.test.js +212 -0
  19. package/dist/__tests__/server/http/responses.test.d.ts +1 -0
  20. package/dist/__tests__/server/http/responses.test.js +112 -0
  21. package/dist/__tests__/server/storage/client.test.d.ts +1 -0
  22. package/dist/__tests__/server/storage/client.test.js +173 -0
  23. package/dist/__tests__/server/storage/keys.test.d.ts +1 -0
  24. package/dist/__tests__/server/storage/keys.test.js +47 -0
  25. package/dist/__tests__/shared/auth/types.test.d.ts +1 -0
  26. package/dist/__tests__/shared/auth/types.test.js +77 -0
  27. package/dist/__tests__/shared/http/status.test.d.ts +1 -0
  28. package/dist/__tests__/shared/http/status.test.js +27 -0
  29. package/dist/__tests__/storage/client.test.d.ts +1 -0
  30. package/dist/__tests__/storage/client.test.js +173 -0
  31. package/dist/__tests__/storage/keys.test.d.ts +1 -0
  32. package/dist/__tests__/storage/keys.test.js +47 -0
  33. package/dist/__tests__/types.test.d.ts +1 -0
  34. package/dist/__tests__/types.test.js +56 -0
  35. package/dist/auth/apiKey.d.ts +24 -7
  36. package/dist/auth/apiKey.js +24 -7
  37. package/dist/auth/token.d.ts +37 -10
  38. package/dist/auth/token.js +37 -10
  39. package/dist/auth/types.d.ts +21 -3
  40. package/dist/auth/types.js +21 -3
  41. package/dist/client/api.d.ts +70 -9
  42. package/dist/client/api.js +70 -9
  43. package/dist/client/apiError.d.ts +22 -5
  44. package/dist/client/apiError.js +22 -5
  45. package/dist/http/responses.d.ts +57 -8
  46. package/dist/http/responses.js +57 -8
  47. package/dist/index.d.ts +2 -4
  48. package/dist/index.js +6 -5
  49. package/dist/server/auth/apiKey.d.ts +44 -0
  50. package/dist/server/auth/apiKey.js +59 -0
  51. package/dist/server/auth/index.d.ts +2 -0
  52. package/dist/server/auth/index.js +15 -0
  53. package/dist/server/auth/token.d.ts +56 -0
  54. package/dist/server/auth/token.js +104 -0
  55. package/dist/server/http/index.d.ts +1 -0
  56. package/dist/server/http/index.js +12 -0
  57. package/dist/server/http/responses.d.ts +82 -0
  58. package/dist/server/http/responses.js +132 -0
  59. package/dist/server/index.d.ts +3 -0
  60. package/dist/server/index.js +33 -0
  61. package/dist/server/storage/client.d.ts +48 -0
  62. package/dist/server/storage/client.js +107 -0
  63. package/dist/server/storage/index.d.ts +2 -0
  64. package/dist/server/storage/index.js +11 -0
  65. package/dist/server/storage/keys.d.ts +8 -0
  66. package/dist/server/storage/keys.js +14 -0
  67. package/dist/shared/auth/index.d.ts +2 -0
  68. package/dist/shared/auth/index.js +7 -0
  69. package/dist/shared/auth/types.d.ts +63 -0
  70. package/dist/shared/auth/types.js +41 -0
  71. package/dist/shared/http/index.d.ts +3 -0
  72. package/dist/shared/http/index.js +5 -0
  73. package/dist/shared/http/status.d.ts +17 -0
  74. package/dist/shared/http/status.js +19 -0
  75. package/dist/shared/http/types.d.ts +10 -0
  76. package/dist/shared/http/types.js +5 -0
  77. package/dist/shared/index.d.ts +5 -0
  78. package/dist/shared/index.js +10 -0
  79. package/dist/storage/client.d.ts +29 -6
  80. package/dist/storage/client.js +29 -6
  81. package/dist/types.d.ts +16 -3
  82. package/dist/types.js +16 -3
  83. package/package.json +9 -13
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateApiKey = exports.validateApiKey = exports.hashApiKey = exports.extractApiKey = exports.generateLongLivedToken = exports.generateToken = exports.validateToken = exports.extractToken = exports.getJwtSecret = exports.initAuth = void 0;
4
+ var token_1 = require("./token");
5
+ Object.defineProperty(exports, "initAuth", { enumerable: true, get: function () { return token_1.initAuth; } });
6
+ Object.defineProperty(exports, "getJwtSecret", { enumerable: true, get: function () { return token_1.getJwtSecret; } });
7
+ Object.defineProperty(exports, "extractToken", { enumerable: true, get: function () { return token_1.extractToken; } });
8
+ Object.defineProperty(exports, "validateToken", { enumerable: true, get: function () { return token_1.validateToken; } });
9
+ Object.defineProperty(exports, "generateToken", { enumerable: true, get: function () { return token_1.generateToken; } });
10
+ Object.defineProperty(exports, "generateLongLivedToken", { enumerable: true, get: function () { return token_1.generateLongLivedToken; } });
11
+ var apiKey_1 = require("./apiKey");
12
+ Object.defineProperty(exports, "extractApiKey", { enumerable: true, get: function () { return apiKey_1.extractApiKey; } });
13
+ Object.defineProperty(exports, "hashApiKey", { enumerable: true, get: function () { return apiKey_1.hashApiKey; } });
14
+ Object.defineProperty(exports, "validateApiKey", { enumerable: true, get: function () { return apiKey_1.validateApiKey; } });
15
+ Object.defineProperty(exports, "generateApiKey", { enumerable: true, get: function () { return apiKey_1.generateApiKey; } });
@@ -0,0 +1,56 @@
1
+ import { Result } from '../../types';
2
+ /**
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);
9
+ */
10
+ export declare function initAuth(secret: string | undefined, minLength?: number): void;
11
+ /**
12
+ * Gets the configured JWT secret.
13
+ * @returns The JWT secret string
14
+ * @throws Error if initAuth() has not been called
15
+ */
16
+ export declare function getJwtSecret(): string;
17
+ /**
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'));
23
+ */
24
+ export declare function extractToken(authHeader: string | null): string | null;
25
+ /**
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
+ * }
35
+ */
36
+ export declare function validateToken<T extends object>(token: string): Result<T>;
37
+ /**
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');
45
+ */
46
+ export declare function generateToken<T extends object>(payload: T, expiresIn?: string): string;
47
+ /**
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' });
55
+ */
56
+ export declare function generateLongLivedToken<T extends object>(payload: T, expiresInDays?: number): string;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initAuth = initAuth;
7
+ exports.getJwtSecret = getJwtSecret;
8
+ exports.extractToken = extractToken;
9
+ exports.validateToken = validateToken;
10
+ exports.generateToken = generateToken;
11
+ exports.generateLongLivedToken = generateLongLivedToken;
12
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
13
+ const types_1 = require("../../types");
14
+ /**
15
+ * JWT token utilities - works with any payload structure
16
+ * Use BaseJwtPayload or extend it for type safety
17
+ */
18
+ let jwtSecret = null;
19
+ /**
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);
26
+ */
27
+ function initAuth(secret, minLength = 32) {
28
+ if (!secret || secret.length < minLength) {
29
+ throw new Error(`JWT_SECRET must be at least ${minLength} characters`);
30
+ }
31
+ jwtSecret = secret;
32
+ }
33
+ /**
34
+ * Gets the configured JWT secret.
35
+ * @returns The JWT secret string
36
+ * @throws Error if initAuth() has not been called
37
+ */
38
+ function getJwtSecret() {
39
+ if (!jwtSecret) {
40
+ throw new Error('Auth not initialized. Call initAuth() first.');
41
+ }
42
+ return jwtSecret;
43
+ }
44
+ /**
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'));
50
+ */
51
+ function extractToken(authHeader) {
52
+ if (!authHeader?.startsWith('Bearer ')) {
53
+ return null;
54
+ }
55
+ return authHeader.slice(7);
56
+ }
57
+ /**
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
+ * }
67
+ */
68
+ function validateToken(token) {
69
+ try {
70
+ const payload = jsonwebtoken_1.default.verify(token, getJwtSecret());
71
+ if (typeof payload === 'object' && payload !== null) {
72
+ return (0, types_1.ok)(payload);
73
+ }
74
+ return (0, types_1.err)('Invalid token payload');
75
+ }
76
+ catch (error) {
77
+ const message = error instanceof Error ? error.message : 'Token validation failed';
78
+ return (0, types_1.err)(message);
79
+ }
80
+ }
81
+ /**
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');
89
+ */
90
+ function generateToken(payload, expiresIn = '7d') {
91
+ return jsonwebtoken_1.default.sign(payload, getJwtSecret(), { expiresIn });
92
+ }
93
+ /**
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' });
101
+ */
102
+ function generateLongLivedToken(payload, expiresInDays = 3650) {
103
+ return jsonwebtoken_1.default.sign(payload, getJwtSecret(), { expiresIn: `${expiresInDays}d` });
104
+ }
@@ -0,0 +1 @@
1
+ export { badRequestResponse, unauthorizedResponse, forbiddenResponse, notFoundResponse, conflictResponse, handleFunctionError, isNotFoundError, isConflictError } from './responses';
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isConflictError = exports.isNotFoundError = exports.handleFunctionError = exports.conflictResponse = exports.notFoundResponse = exports.forbiddenResponse = exports.unauthorizedResponse = exports.badRequestResponse = void 0;
4
+ var responses_1 = require("./responses");
5
+ Object.defineProperty(exports, "badRequestResponse", { enumerable: true, get: function () { return responses_1.badRequestResponse; } });
6
+ Object.defineProperty(exports, "unauthorizedResponse", { enumerable: true, get: function () { return responses_1.unauthorizedResponse; } });
7
+ Object.defineProperty(exports, "forbiddenResponse", { enumerable: true, get: function () { return responses_1.forbiddenResponse; } });
8
+ Object.defineProperty(exports, "notFoundResponse", { enumerable: true, get: function () { return responses_1.notFoundResponse; } });
9
+ Object.defineProperty(exports, "conflictResponse", { enumerable: true, get: function () { return responses_1.conflictResponse; } });
10
+ Object.defineProperty(exports, "handleFunctionError", { enumerable: true, get: function () { return responses_1.handleFunctionError; } });
11
+ Object.defineProperty(exports, "isNotFoundError", { enumerable: true, get: function () { return responses_1.isNotFoundError; } });
12
+ Object.defineProperty(exports, "isConflictError", { enumerable: true, get: function () { return responses_1.isConflictError; } });
@@ -0,0 +1,82 @@
1
+ import { HttpResponseInit, InvocationContext } from '@azure/functions';
2
+ /**
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');
8
+ */
9
+ export declare function badRequestResponse(message: string): HttpResponseInit;
10
+ /**
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();
16
+ */
17
+ export declare function unauthorizedResponse(message?: string): HttpResponseInit;
18
+ /**
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');
24
+ */
25
+ export declare function forbiddenResponse(message?: string): HttpResponseInit;
26
+ /**
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' }
33
+ */
34
+ export declare function notFoundResponse(resource: string): HttpResponseInit;
35
+ /**
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');
41
+ */
42
+ export declare function conflictResponse(message: string): HttpResponseInit;
43
+ /**
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
+ * }
55
+ */
56
+ export declare function handleFunctionError(error: unknown, context: InvocationContext): HttpResponseInit;
57
+ /**
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
+ * }
68
+ */
69
+ export declare function isNotFoundError(error: unknown): boolean;
70
+ /**
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
+ * }
81
+ */
82
+ export declare function isConflictError(error: unknown): boolean;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.badRequestResponse = badRequestResponse;
4
+ exports.unauthorizedResponse = unauthorizedResponse;
5
+ exports.forbiddenResponse = forbiddenResponse;
6
+ exports.notFoundResponse = notFoundResponse;
7
+ exports.conflictResponse = conflictResponse;
8
+ exports.handleFunctionError = handleFunctionError;
9
+ exports.isNotFoundError = isNotFoundError;
10
+ exports.isConflictError = isConflictError;
11
+ const status_1 = require("../../shared/http/status");
12
+ /**
13
+ * Creates a 400 Bad Request response.
14
+ * @param message - The error message to return
15
+ * @returns Azure Functions HttpResponseInit object
16
+ * @example
17
+ * if (!body.email) return badRequestResponse('Email is required');
18
+ */
19
+ function badRequestResponse(message) {
20
+ return {
21
+ status: status_1.HTTP_STATUS.BAD_REQUEST,
22
+ jsonBody: { error: message }
23
+ };
24
+ }
25
+ /**
26
+ * Creates a 401 Unauthorized response.
27
+ * @param message - The error message (default: 'Unauthorized')
28
+ * @returns Azure Functions HttpResponseInit object
29
+ * @example
30
+ * if (!token) return unauthorizedResponse();
31
+ */
32
+ function unauthorizedResponse(message = 'Unauthorized') {
33
+ return {
34
+ status: status_1.HTTP_STATUS.UNAUTHORIZED,
35
+ jsonBody: { error: message }
36
+ };
37
+ }
38
+ /**
39
+ * Creates a 403 Forbidden response.
40
+ * @param message - The error message (default: 'Forbidden')
41
+ * @returns Azure Functions HttpResponseInit object
42
+ * @example
43
+ * if (!isAdmin(payload)) return forbiddenResponse('Admin access required');
44
+ */
45
+ function forbiddenResponse(message = 'Forbidden') {
46
+ return {
47
+ status: status_1.HTTP_STATUS.FORBIDDEN,
48
+ jsonBody: { error: message }
49
+ };
50
+ }
51
+ /**
52
+ * Creates a 404 Not Found response.
53
+ * @param resource - The name of the resource that wasn't found
54
+ * @returns Azure Functions HttpResponseInit object
55
+ * @example
56
+ * if (!user) return notFoundResponse('User');
57
+ * // Returns: { error: 'User not found' }
58
+ */
59
+ function notFoundResponse(resource) {
60
+ return {
61
+ status: status_1.HTTP_STATUS.NOT_FOUND,
62
+ jsonBody: { error: `${resource} not found` }
63
+ };
64
+ }
65
+ /**
66
+ * Creates a 409 Conflict response.
67
+ * @param message - The conflict error message
68
+ * @returns Azure Functions HttpResponseInit object
69
+ * @example
70
+ * if (existingUser) return conflictResponse('Email already registered');
71
+ */
72
+ function conflictResponse(message) {
73
+ return {
74
+ status: status_1.HTTP_STATUS.CONFLICT,
75
+ jsonBody: { error: message }
76
+ };
77
+ }
78
+ /**
79
+ * Handles unexpected errors safely by logging details and returning a generic message.
80
+ * Use in catch blocks to avoid exposing internal error details to clients.
81
+ * @param error - The caught error
82
+ * @param context - Azure Functions InvocationContext for logging
83
+ * @returns Azure Functions HttpResponseInit with 500 status
84
+ * @example
85
+ * try {
86
+ * await riskyOperation();
87
+ * } catch (error) {
88
+ * return handleFunctionError(error, context);
89
+ * }
90
+ */
91
+ function handleFunctionError(error, context) {
92
+ const message = error instanceof Error ? error.message : 'Unknown error';
93
+ context.error(`Function error: ${message}`);
94
+ return {
95
+ status: status_1.HTTP_STATUS.INTERNAL_ERROR,
96
+ jsonBody: { error: 'Internal server error' }
97
+ };
98
+ }
99
+ /**
100
+ * Checks if an error is an Azure Table Storage "not found" error.
101
+ * @param error - The caught error
102
+ * @returns True if error has statusCode 404
103
+ * @example
104
+ * try {
105
+ * await tableClient.getEntity(pk, rk);
106
+ * } catch (error) {
107
+ * if (isNotFoundError(error)) return notFoundResponse('Entity');
108
+ * throw error;
109
+ * }
110
+ */
111
+ function isNotFoundError(error) {
112
+ return (error instanceof Error &&
113
+ 'statusCode' in error &&
114
+ error.statusCode === 404);
115
+ }
116
+ /**
117
+ * Checks if an error is an Azure Table Storage "conflict" error.
118
+ * @param error - The caught error
119
+ * @returns True if error has statusCode 409
120
+ * @example
121
+ * try {
122
+ * await tableClient.createEntity(entity);
123
+ * } catch (error) {
124
+ * if (isConflictError(error)) return conflictResponse('Entity already exists');
125
+ * throw error;
126
+ * }
127
+ */
128
+ function isConflictError(error) {
129
+ return (error instanceof Error &&
130
+ 'statusCode' in error &&
131
+ error.statusCode === 409);
132
+ }
@@ -0,0 +1,3 @@
1
+ export { initAuth, getJwtSecret, extractToken, validateToken, generateToken, generateLongLivedToken, extractApiKey, hashApiKey, validateApiKey, generateApiKey } from './auth';
2
+ export { badRequestResponse, unauthorizedResponse, forbiddenResponse, notFoundResponse, conflictResponse, handleFunctionError, isNotFoundError, isConflictError } from './http';
3
+ export { initStorage, initStorageFromEnv, useManagedIdentity, getTableClient, clearTableClientCache, generateRowKey } from './storage';
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateRowKey = exports.clearTableClientCache = exports.getTableClient = exports.useManagedIdentity = exports.initStorageFromEnv = exports.initStorage = exports.isConflictError = exports.isNotFoundError = exports.handleFunctionError = exports.conflictResponse = exports.notFoundResponse = exports.forbiddenResponse = exports.unauthorizedResponse = exports.badRequestResponse = exports.generateApiKey = exports.validateApiKey = exports.hashApiKey = exports.extractApiKey = exports.generateLongLivedToken = exports.generateToken = exports.validateToken = exports.extractToken = exports.getJwtSecret = exports.initAuth = void 0;
4
+ // Auth
5
+ var auth_1 = require("./auth");
6
+ Object.defineProperty(exports, "initAuth", { enumerable: true, get: function () { return auth_1.initAuth; } });
7
+ Object.defineProperty(exports, "getJwtSecret", { enumerable: true, get: function () { return auth_1.getJwtSecret; } });
8
+ Object.defineProperty(exports, "extractToken", { enumerable: true, get: function () { return auth_1.extractToken; } });
9
+ Object.defineProperty(exports, "validateToken", { enumerable: true, get: function () { return auth_1.validateToken; } });
10
+ Object.defineProperty(exports, "generateToken", { enumerable: true, get: function () { return auth_1.generateToken; } });
11
+ Object.defineProperty(exports, "generateLongLivedToken", { enumerable: true, get: function () { return auth_1.generateLongLivedToken; } });
12
+ Object.defineProperty(exports, "extractApiKey", { enumerable: true, get: function () { return auth_1.extractApiKey; } });
13
+ Object.defineProperty(exports, "hashApiKey", { enumerable: true, get: function () { return auth_1.hashApiKey; } });
14
+ Object.defineProperty(exports, "validateApiKey", { enumerable: true, get: function () { return auth_1.validateApiKey; } });
15
+ Object.defineProperty(exports, "generateApiKey", { enumerable: true, get: function () { return auth_1.generateApiKey; } });
16
+ // HTTP
17
+ var http_1 = require("./http");
18
+ Object.defineProperty(exports, "badRequestResponse", { enumerable: true, get: function () { return http_1.badRequestResponse; } });
19
+ Object.defineProperty(exports, "unauthorizedResponse", { enumerable: true, get: function () { return http_1.unauthorizedResponse; } });
20
+ Object.defineProperty(exports, "forbiddenResponse", { enumerable: true, get: function () { return http_1.forbiddenResponse; } });
21
+ Object.defineProperty(exports, "notFoundResponse", { enumerable: true, get: function () { return http_1.notFoundResponse; } });
22
+ Object.defineProperty(exports, "conflictResponse", { enumerable: true, get: function () { return http_1.conflictResponse; } });
23
+ Object.defineProperty(exports, "handleFunctionError", { enumerable: true, get: function () { return http_1.handleFunctionError; } });
24
+ Object.defineProperty(exports, "isNotFoundError", { enumerable: true, get: function () { return http_1.isNotFoundError; } });
25
+ Object.defineProperty(exports, "isConflictError", { enumerable: true, get: function () { return http_1.isConflictError; } });
26
+ // Storage
27
+ var storage_1 = require("./storage");
28
+ Object.defineProperty(exports, "initStorage", { enumerable: true, get: function () { return storage_1.initStorage; } });
29
+ Object.defineProperty(exports, "initStorageFromEnv", { enumerable: true, get: function () { return storage_1.initStorageFromEnv; } });
30
+ Object.defineProperty(exports, "useManagedIdentity", { enumerable: true, get: function () { return storage_1.useManagedIdentity; } });
31
+ Object.defineProperty(exports, "getTableClient", { enumerable: true, get: function () { return storage_1.getTableClient; } });
32
+ Object.defineProperty(exports, "clearTableClientCache", { enumerable: true, get: function () { return storage_1.clearTableClientCache; } });
33
+ Object.defineProperty(exports, "generateRowKey", { enumerable: true, get: function () { return storage_1.generateRowKey; } });
@@ -0,0 +1,48 @@
1
+ import { TableClient } from '@azure/data-tables';
2
+ /**
3
+ * Initializes Azure Table Storage configuration. Call once at application startup.
4
+ * @param config - Storage configuration options
5
+ * @param config.accountName - Azure Storage account name (for managed identity)
6
+ * @param config.connectionString - Connection string (for local development)
7
+ * @example
8
+ * // Production (Azure with managed identity)
9
+ * initStorage({ accountName: 'mystorageaccount' });
10
+ *
11
+ * // Local development (Azurite)
12
+ * initStorage({ connectionString: 'UseDevelopmentStorage=true' });
13
+ */
14
+ export declare function initStorage(config: {
15
+ accountName?: string;
16
+ connectionString?: string;
17
+ }): void;
18
+ /**
19
+ * Initializes storage from environment variables.
20
+ * Reads STORAGE_ACCOUNT_NAME and AzureWebJobsStorage.
21
+ * @example
22
+ * initStorageFromEnv(); // Uses process.env automatically
23
+ */
24
+ export declare function initStorageFromEnv(): void;
25
+ /**
26
+ * Checks if using Azure managed identity vs local connection string.
27
+ * @returns True if using managed identity (production), false for connection string (local)
28
+ */
29
+ export declare function useManagedIdentity(): boolean;
30
+ /**
31
+ * Gets a TableClient for the specified table, creating the table if needed.
32
+ * Clients are cached for reuse across requests.
33
+ * @param tableName - The Azure Table Storage table name
34
+ * @returns A configured TableClient instance
35
+ * @throws Error if storage is not configured
36
+ * @example
37
+ * const client = await getTableClient('users');
38
+ * await client.createEntity({ partitionKey: 'pk', rowKey: 'rk', name: 'John' });
39
+ */
40
+ export declare function getTableClient(tableName: string): Promise<TableClient>;
41
+ /**
42
+ * Clears the TableClient cache. Primarily useful for testing.
43
+ * @example
44
+ * afterEach(() => {
45
+ * clearTableClientCache();
46
+ * });
47
+ */
48
+ export declare function clearTableClientCache(): void;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initStorage = initStorage;
4
+ exports.initStorageFromEnv = initStorageFromEnv;
5
+ exports.useManagedIdentity = useManagedIdentity;
6
+ exports.getTableClient = getTableClient;
7
+ exports.clearTableClientCache = clearTableClientCache;
8
+ const data_tables_1 = require("@azure/data-tables");
9
+ const identity_1 = require("@azure/identity");
10
+ /**
11
+ * Azure Table Storage client factory with managed identity support
12
+ */
13
+ // Cache table clients to avoid repeated connections
14
+ const tableClients = new Map();
15
+ // Configuration
16
+ let storageAccountName;
17
+ let connectionString;
18
+ /**
19
+ * Initializes Azure Table Storage configuration. Call once at application startup.
20
+ * @param config - Storage configuration options
21
+ * @param config.accountName - Azure Storage account name (for managed identity)
22
+ * @param config.connectionString - Connection string (for local development)
23
+ * @example
24
+ * // Production (Azure with managed identity)
25
+ * initStorage({ accountName: 'mystorageaccount' });
26
+ *
27
+ * // Local development (Azurite)
28
+ * initStorage({ connectionString: 'UseDevelopmentStorage=true' });
29
+ */
30
+ function initStorage(config) {
31
+ storageAccountName = config.accountName;
32
+ connectionString = config.connectionString;
33
+ }
34
+ /**
35
+ * Initializes storage from environment variables.
36
+ * Reads STORAGE_ACCOUNT_NAME and AzureWebJobsStorage.
37
+ * @example
38
+ * initStorageFromEnv(); // Uses process.env automatically
39
+ */
40
+ function initStorageFromEnv() {
41
+ initStorage({
42
+ accountName: process.env.STORAGE_ACCOUNT_NAME,
43
+ connectionString: process.env.AzureWebJobsStorage
44
+ });
45
+ }
46
+ /**
47
+ * Checks if using Azure managed identity vs local connection string.
48
+ * @returns True if using managed identity (production), false for connection string (local)
49
+ */
50
+ function useManagedIdentity() {
51
+ return !!storageAccountName && !connectionString?.includes('UseDevelopmentStorage');
52
+ }
53
+ /**
54
+ * Gets a TableClient for the specified table, creating the table if needed.
55
+ * Clients are cached for reuse across requests.
56
+ * @param tableName - The Azure Table Storage table name
57
+ * @returns A configured TableClient instance
58
+ * @throws Error if storage is not configured
59
+ * @example
60
+ * const client = await getTableClient('users');
61
+ * await client.createEntity({ partitionKey: 'pk', rowKey: 'rk', name: 'John' });
62
+ */
63
+ async function getTableClient(tableName) {
64
+ // Return cached client if available
65
+ const cached = tableClients.get(tableName);
66
+ if (cached) {
67
+ return cached;
68
+ }
69
+ let client;
70
+ if (useManagedIdentity()) {
71
+ // Azure: Use managed identity
72
+ const credential = new identity_1.DefaultAzureCredential();
73
+ const endpoint = `https://${storageAccountName}.table.core.windows.net`;
74
+ client = new data_tables_1.TableClient(endpoint, tableName, credential);
75
+ }
76
+ else if (connectionString) {
77
+ // Local/Azurite: Use connection string
78
+ client = data_tables_1.TableClient.fromConnectionString(connectionString, tableName);
79
+ }
80
+ else {
81
+ throw new Error('Storage not configured. Set STORAGE_ACCOUNT_NAME or AzureWebJobsStorage.');
82
+ }
83
+ // Create table if it doesn't exist
84
+ try {
85
+ await client.createTable();
86
+ }
87
+ catch (error) {
88
+ // Ignore "table already exists" errors (409 Conflict)
89
+ const tableError = error;
90
+ if (tableError.statusCode !== 409) {
91
+ throw error;
92
+ }
93
+ }
94
+ // Cache and return
95
+ tableClients.set(tableName, client);
96
+ return client;
97
+ }
98
+ /**
99
+ * Clears the TableClient cache. Primarily useful for testing.
100
+ * @example
101
+ * afterEach(() => {
102
+ * clearTableClientCache();
103
+ * });
104
+ */
105
+ function clearTableClientCache() {
106
+ tableClients.clear();
107
+ }
@@ -0,0 +1,2 @@
1
+ export { initStorage, initStorageFromEnv, useManagedIdentity, getTableClient, clearTableClientCache } from './client';
2
+ export { generateRowKey } from './keys';
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateRowKey = exports.clearTableClientCache = exports.getTableClient = exports.useManagedIdentity = exports.initStorageFromEnv = exports.initStorage = void 0;
4
+ var client_1 = require("./client");
5
+ Object.defineProperty(exports, "initStorage", { enumerable: true, get: function () { return client_1.initStorage; } });
6
+ Object.defineProperty(exports, "initStorageFromEnv", { enumerable: true, get: function () { return client_1.initStorageFromEnv; } });
7
+ Object.defineProperty(exports, "useManagedIdentity", { enumerable: true, get: function () { return client_1.useManagedIdentity; } });
8
+ Object.defineProperty(exports, "getTableClient", { enumerable: true, get: function () { return client_1.getTableClient; } });
9
+ Object.defineProperty(exports, "clearTableClientCache", { enumerable: true, get: function () { return client_1.clearTableClientCache; } });
10
+ var keys_1 = require("./keys");
11
+ Object.defineProperty(exports, "generateRowKey", { enumerable: true, get: function () { return keys_1.generateRowKey; } });
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generate a unique row key from an identifier string
3
+ * Uses SHA-256 hash for consistent, URL-safe keys
4
+ *
5
+ * @param identifier - The string to hash (e.g., subscription endpoint, user ID)
6
+ * @returns A 32-character hex string suitable for Azure Table Storage row keys
7
+ */
8
+ export declare function generateRowKey(identifier: string): string;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateRowKey = generateRowKey;
4
+ const crypto_1 = require("crypto");
5
+ /**
6
+ * Generate a unique row key from an identifier string
7
+ * Uses SHA-256 hash for consistent, URL-safe keys
8
+ *
9
+ * @param identifier - The string to hash (e.g., subscription endpoint, user ID)
10
+ * @returns A 32-character hex string suitable for Azure Table Storage row keys
11
+ */
12
+ function generateRowKey(identifier) {
13
+ return (0, crypto_1.createHash)('sha256').update(identifier).digest('hex').substring(0, 32);
14
+ }
@@ -0,0 +1,2 @@
1
+ export type { BaseJwtPayload, UserTokenPayload, UsernameTokenPayload, RoleTokenPayload } from './types';
2
+ export { hasUsername, hasRole, isAdmin } from './types';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isAdmin = exports.hasRole = exports.hasUsername = void 0;
4
+ var types_1 = require("./types");
5
+ Object.defineProperty(exports, "hasUsername", { enumerable: true, get: function () { return types_1.hasUsername; } });
6
+ Object.defineProperty(exports, "hasRole", { enumerable: true, get: function () { return types_1.hasRole; } });
7
+ Object.defineProperty(exports, "isAdmin", { enumerable: true, get: function () { return types_1.isAdmin; } });