@markwharton/pwa-core 1.0.0 → 1.1.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.
- package/dist/auth/apiKey.d.ts +4 -1
- package/dist/auth/apiKey.js +7 -1
- package/dist/auth/token.d.ts +4 -1
- package/dist/auth/token.js +8 -4
- package/dist/client/api.d.ts +2 -9
- package/dist/client/api.js +34 -8
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.js +2 -2
- package/dist/client/types.d.ts +12 -0
- package/dist/client/types.js +5 -0
- package/dist/http/index.d.ts +2 -1
- package/dist/http/responses.d.ts +0 -7
- package/dist/http/types.d.ts +10 -0
- package/dist/http/types.js +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +2 -2
- package/dist/types.d.ts +35 -0
- package/dist/types.js +28 -0
- package/package.json +1 -1
- /package/dist/client/{ApiError.d.ts → apiError.d.ts} +0 -0
- /package/dist/client/{ApiError.js → apiError.js} +0 -0
- /package/dist/storage/{helpers.d.ts → keys.d.ts} +0 -0
- /package/dist/storage/{helpers.js → keys.js} +0 -0
package/dist/auth/apiKey.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Result } from '../types';
|
|
1
2
|
/**
|
|
2
3
|
* API Key utilities for machine-to-machine authentication
|
|
3
4
|
*/
|
|
@@ -16,8 +17,10 @@ export declare function extractApiKey(request: {
|
|
|
16
17
|
export declare function hashApiKey(apiKey: string): string;
|
|
17
18
|
/**
|
|
18
19
|
* Validate API key against stored hash
|
|
20
|
+
*
|
|
21
|
+
* @returns Result indicating success or failure with error message
|
|
19
22
|
*/
|
|
20
|
-
export declare function validateApiKey(apiKey: string, storedHash: string):
|
|
23
|
+
export declare function validateApiKey(apiKey: string, storedHash: string): Result<void>;
|
|
21
24
|
/**
|
|
22
25
|
* Generate a new API key (random 32-byte hex string)
|
|
23
26
|
*/
|
package/dist/auth/apiKey.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.hashApiKey = hashApiKey;
|
|
|
5
5
|
exports.validateApiKey = validateApiKey;
|
|
6
6
|
exports.generateApiKey = generateApiKey;
|
|
7
7
|
const crypto_1 = require("crypto");
|
|
8
|
+
const types_1 = require("../types");
|
|
8
9
|
/**
|
|
9
10
|
* API Key utilities for machine-to-machine authentication
|
|
10
11
|
*/
|
|
@@ -23,10 +24,15 @@ function hashApiKey(apiKey) {
|
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
26
|
* Validate API key against stored hash
|
|
27
|
+
*
|
|
28
|
+
* @returns Result indicating success or failure with error message
|
|
26
29
|
*/
|
|
27
30
|
function validateApiKey(apiKey, storedHash) {
|
|
28
31
|
const keyHash = hashApiKey(apiKey);
|
|
29
|
-
|
|
32
|
+
if (keyHash === storedHash) {
|
|
33
|
+
return (0, types_1.okVoid)();
|
|
34
|
+
}
|
|
35
|
+
return (0, types_1.err)('Invalid API key');
|
|
30
36
|
}
|
|
31
37
|
/**
|
|
32
38
|
* Generate a new API key (random 32-byte hex string)
|
package/dist/auth/token.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Result } from '../types';
|
|
1
2
|
/**
|
|
2
3
|
* Initialize JWT secret - call once at startup
|
|
3
4
|
* Fails fast if secret is missing or too short
|
|
@@ -14,8 +15,10 @@ export declare function extractToken(authHeader: string | null): string | null;
|
|
|
14
15
|
/**
|
|
15
16
|
* Validate and decode a JWT token
|
|
16
17
|
* Generic type allows project-specific payload shapes
|
|
18
|
+
*
|
|
19
|
+
* @returns Result with decoded payload or error message
|
|
17
20
|
*/
|
|
18
|
-
export declare function validateToken<T extends object>(token: string): T
|
|
21
|
+
export declare function validateToken<T extends object>(token: string): Result<T>;
|
|
19
22
|
/**
|
|
20
23
|
* Generate a JWT token with custom payload
|
|
21
24
|
*/
|
package/dist/auth/token.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.validateToken = validateToken;
|
|
|
10
10
|
exports.generateToken = generateToken;
|
|
11
11
|
exports.generateLongLivedToken = generateLongLivedToken;
|
|
12
12
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
13
|
+
const types_1 = require("../types");
|
|
13
14
|
/**
|
|
14
15
|
* JWT token utilities - works with any payload structure
|
|
15
16
|
* Use BaseJwtPayload or extend it for type safety
|
|
@@ -46,17 +47,20 @@ function extractToken(authHeader) {
|
|
|
46
47
|
/**
|
|
47
48
|
* Validate and decode a JWT token
|
|
48
49
|
* Generic type allows project-specific payload shapes
|
|
50
|
+
*
|
|
51
|
+
* @returns Result with decoded payload or error message
|
|
49
52
|
*/
|
|
50
53
|
function validateToken(token) {
|
|
51
54
|
try {
|
|
52
55
|
const payload = jsonwebtoken_1.default.verify(token, getJwtSecret());
|
|
53
56
|
if (typeof payload === 'object' && payload !== null) {
|
|
54
|
-
return payload;
|
|
57
|
+
return (0, types_1.ok)(payload);
|
|
55
58
|
}
|
|
56
|
-
return
|
|
59
|
+
return (0, types_1.err)('Invalid token payload');
|
|
57
60
|
}
|
|
58
|
-
catch {
|
|
59
|
-
|
|
61
|
+
catch (error) {
|
|
62
|
+
const message = error instanceof Error ? error.message : 'Token validation failed';
|
|
63
|
+
return (0, types_1.err)(message);
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
/**
|
package/dist/client/api.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ApiResponse } from './types';
|
|
1
2
|
/**
|
|
2
3
|
* Initialize the API client
|
|
3
4
|
*/
|
|
@@ -5,15 +6,6 @@ export declare function initApiClient(config: {
|
|
|
5
6
|
getToken: () => string | null;
|
|
6
7
|
onUnauthorized?: () => void;
|
|
7
8
|
}): void;
|
|
8
|
-
/**
|
|
9
|
-
* API response wrapper
|
|
10
|
-
*/
|
|
11
|
-
export interface ApiResponse<T> {
|
|
12
|
-
ok: boolean;
|
|
13
|
-
status: number;
|
|
14
|
-
data?: T;
|
|
15
|
-
error?: string;
|
|
16
|
-
}
|
|
17
9
|
/**
|
|
18
10
|
* Make an authenticated API call
|
|
19
11
|
*/
|
|
@@ -40,5 +32,6 @@ export declare function apiPatch<T>(url: string, body?: unknown): Promise<T>;
|
|
|
40
32
|
export declare function apiDelete<T>(url: string): Promise<T>;
|
|
41
33
|
/**
|
|
42
34
|
* Alternative: Response wrapper style (like financial-tracker's authJsonFetch)
|
|
35
|
+
* Preserves actual HTTP status code on success
|
|
43
36
|
*/
|
|
44
37
|
export declare function apiCallSafe<T>(url: string, options?: RequestInit): Promise<ApiResponse<T>>;
|
package/dist/client/api.js
CHANGED
|
@@ -8,7 +8,7 @@ exports.apiPut = apiPut;
|
|
|
8
8
|
exports.apiPatch = apiPatch;
|
|
9
9
|
exports.apiDelete = apiDelete;
|
|
10
10
|
exports.apiCallSafe = apiCallSafe;
|
|
11
|
-
const
|
|
11
|
+
const apiError_1 = require("./apiError");
|
|
12
12
|
/**
|
|
13
13
|
* Client-side API utilities for authenticated requests
|
|
14
14
|
*/
|
|
@@ -51,7 +51,7 @@ async function apiCall(url, options = {}) {
|
|
|
51
51
|
catch {
|
|
52
52
|
// Ignore JSON parse errors
|
|
53
53
|
}
|
|
54
|
-
throw new
|
|
54
|
+
throw new apiError_1.ApiError(response.status, errorMessage);
|
|
55
55
|
}
|
|
56
56
|
// Handle empty responses
|
|
57
57
|
const text = await response.text();
|
|
@@ -101,16 +101,42 @@ async function apiDelete(url) {
|
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Alternative: Response wrapper style (like financial-tracker's authJsonFetch)
|
|
104
|
+
* Preserves actual HTTP status code on success
|
|
104
105
|
*/
|
|
105
106
|
async function apiCallSafe(url, options = {}) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
const token = getToken?.();
|
|
108
|
+
const headers = {
|
|
109
|
+
'Content-Type': 'application/json',
|
|
110
|
+
...options.headers
|
|
111
|
+
};
|
|
112
|
+
if (token) {
|
|
113
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
109
114
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
try {
|
|
116
|
+
const response = await fetch(url, {
|
|
117
|
+
...options,
|
|
118
|
+
headers
|
|
119
|
+
});
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
if (response.status === 401 && onUnauthorized) {
|
|
122
|
+
onUnauthorized();
|
|
123
|
+
}
|
|
124
|
+
let errorMessage = 'Request failed';
|
|
125
|
+
try {
|
|
126
|
+
const errorData = (await response.json());
|
|
127
|
+
errorMessage = errorData.error || errorMessage;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Ignore JSON parse errors
|
|
131
|
+
}
|
|
132
|
+
return { ok: false, status: response.status, error: errorMessage };
|
|
113
133
|
}
|
|
134
|
+
// Handle empty responses
|
|
135
|
+
const text = await response.text();
|
|
136
|
+
const data = text ? JSON.parse(text) : undefined;
|
|
137
|
+
return { ok: true, status: response.status, data };
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
114
140
|
return { ok: false, status: 0, error: 'Network error' };
|
|
115
141
|
}
|
|
116
142
|
}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { ApiError } from './
|
|
2
|
-
export {
|
|
1
|
+
export { ApiError } from './apiError';
|
|
2
|
+
export { type ApiResponse } from './types';
|
|
3
|
+
export { initApiClient, apiCall, apiGet, apiPost, apiPut, apiPatch, apiDelete, apiCallSafe } from './api';
|
package/dist/client/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.apiCallSafe = exports.apiDelete = exports.apiPatch = exports.apiPut = exports.apiPost = exports.apiGet = exports.apiCall = exports.initApiClient = exports.ApiError = void 0;
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return
|
|
4
|
+
var apiError_1 = require("./apiError");
|
|
5
|
+
Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return apiError_1.ApiError; } });
|
|
6
6
|
var api_1 = require("./api");
|
|
7
7
|
Object.defineProperty(exports, "initApiClient", { enumerable: true, get: function () { return api_1.initApiClient; } });
|
|
8
8
|
Object.defineProperty(exports, "apiCall", { enumerable: true, get: function () { return api_1.apiCall; } });
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { HTTP_STATUS, type HttpStatus } from './status';
|
|
2
|
-
export { type ErrorResponse
|
|
2
|
+
export { type ErrorResponse } from './types';
|
|
3
|
+
export { badRequestResponse, unauthorizedResponse, forbiddenResponse, notFoundResponse, conflictResponse, handleFunctionError, isNotFoundError, isConflictError } from './responses';
|
package/dist/http/responses.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
// Main entry point - re-export everything
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
18
19
|
__exportStar(require("./auth"), exports);
|
|
19
20
|
__exportStar(require("./http"), exports);
|
|
20
21
|
__exportStar(require("./storage"), exports);
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { initStorage, initStorageFromEnv, useManagedIdentity, getTableClient, clearTableClientCache } from './client';
|
|
2
|
-
export { generateRowKey } from './
|
|
2
|
+
export { generateRowKey } from './keys';
|
package/dist/storage/index.js
CHANGED
|
@@ -7,5 +7,5 @@ Object.defineProperty(exports, "initStorageFromEnv", { enumerable: true, get: fu
|
|
|
7
7
|
Object.defineProperty(exports, "useManagedIdentity", { enumerable: true, get: function () { return client_1.useManagedIdentity; } });
|
|
8
8
|
Object.defineProperty(exports, "getTableClient", { enumerable: true, get: function () { return client_1.getTableClient; } });
|
|
9
9
|
Object.defineProperty(exports, "clearTableClientCache", { enumerable: true, get: function () { return client_1.clearTableClientCache; } });
|
|
10
|
-
var
|
|
11
|
-
Object.defineProperty(exports, "generateRowKey", { enumerable: true, get: function () { return
|
|
10
|
+
var keys_1 = require("./keys");
|
|
11
|
+
Object.defineProperty(exports, "generateRowKey", { enumerable: true, get: function () { return keys_1.generateRowKey; } });
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for pwa-core
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Standard result type for operations that can fail.
|
|
6
|
+
* Used consistently across all modules (auth, push, client).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Success
|
|
10
|
+
* { ok: true, data: user }
|
|
11
|
+
*
|
|
12
|
+
* // Failure
|
|
13
|
+
* { ok: false, error: 'Token expired' }
|
|
14
|
+
*
|
|
15
|
+
* // With status code (HTTP/push operations)
|
|
16
|
+
* { ok: false, error: 'Subscription expired', statusCode: 410 }
|
|
17
|
+
*/
|
|
18
|
+
export interface Result<T> {
|
|
19
|
+
ok: boolean;
|
|
20
|
+
data?: T;
|
|
21
|
+
error?: string;
|
|
22
|
+
statusCode?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Helper to create a success result
|
|
26
|
+
*/
|
|
27
|
+
export declare function ok<T>(data: T): Result<T>;
|
|
28
|
+
/**
|
|
29
|
+
* Helper to create a success result with no data
|
|
30
|
+
*/
|
|
31
|
+
export declare function okVoid(): Result<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Helper to create a failure result
|
|
34
|
+
*/
|
|
35
|
+
export declare function err<T>(error: string, statusCode?: number): Result<T>;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared types for pwa-core
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ok = ok;
|
|
7
|
+
exports.okVoid = okVoid;
|
|
8
|
+
exports.err = err;
|
|
9
|
+
/**
|
|
10
|
+
* Helper to create a success result
|
|
11
|
+
*/
|
|
12
|
+
function ok(data) {
|
|
13
|
+
return { ok: true, data };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Helper to create a success result with no data
|
|
17
|
+
*/
|
|
18
|
+
function okVoid() {
|
|
19
|
+
return { ok: true };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Helper to create a failure result
|
|
23
|
+
*/
|
|
24
|
+
function err(error, statusCode) {
|
|
25
|
+
return statusCode !== undefined
|
|
26
|
+
? { ok: false, error, statusCode }
|
|
27
|
+
: { ok: false, error };
|
|
28
|
+
}
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|