@auth-craft/client 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -8
- package/dist/core/core.d.ts +72 -0
- package/dist/core/core.d.ts.map +1 -0
- package/dist/core/core.js +105 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/proxy.d.ts +79 -0
- package/dist/core/proxy.d.ts.map +1 -0
- package/dist/core/proxy.js +99 -0
- package/dist/core/proxy.js.map +1 -0
- package/dist/index.d.ts +15 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -55
- package/dist/index.js.map +1 -1
- package/dist/transport/client.d.ts +250 -0
- package/dist/transport/client.d.ts.map +1 -0
- package/dist/transport/client.js +940 -0
- package/dist/transport/client.js.map +1 -0
- package/dist/transport/constants.d.ts +9 -0
- package/dist/transport/constants.d.ts.map +1 -0
- package/dist/transport/constants.js +9 -0
- package/dist/transport/constants.js.map +1 -0
- package/dist/transport/error-codes.d.ts +41 -0
- package/dist/transport/error-codes.d.ts.map +1 -0
- package/dist/transport/error-codes.js +38 -0
- package/dist/transport/error-codes.js.map +1 -0
- package/dist/transport/errors.d.ts +55 -0
- package/dist/transport/errors.d.ts.map +1 -0
- package/dist/transport/errors.js +55 -0
- package/dist/transport/errors.js.map +1 -0
- package/dist/transport/helpers.d.ts +135 -0
- package/dist/transport/helpers.d.ts.map +1 -0
- package/dist/transport/helpers.js +185 -0
- package/dist/transport/helpers.js.map +1 -0
- package/dist/transport/index.d.ts +22 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +32 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/messages.d.ts +104 -0
- package/dist/transport/messages.d.ts.map +1 -0
- package/dist/transport/messages.js +24 -0
- package/dist/transport/messages.js.map +1 -0
- package/dist/transport/provider/create-provider.d.ts +38 -0
- package/dist/transport/provider/create-provider.d.ts.map +1 -0
- package/dist/transport/provider/create-provider.js +119 -0
- package/dist/transport/provider/create-provider.js.map +1 -0
- package/dist/transport/provider/parser/body.d.ts +7 -0
- package/dist/transport/provider/parser/body.d.ts.map +1 -0
- package/dist/transport/provider/parser/body.js +17 -0
- package/dist/transport/provider/parser/body.js.map +1 -0
- package/dist/transport/provider/parser/cookie.d.ts +8 -0
- package/dist/transport/provider/parser/cookie.d.ts.map +1 -0
- package/dist/transport/provider/parser/cookie.js +17 -0
- package/dist/transport/provider/parser/cookie.js.map +1 -0
- package/dist/transport/provider/parser/normalize.d.ts +6 -0
- package/dist/transport/provider/parser/normalize.d.ts.map +1 -0
- package/dist/transport/provider/parser/normalize.js +21 -0
- package/dist/transport/provider/parser/normalize.js.map +1 -0
- package/dist/transport/provider/presets.d.ts +31 -0
- package/dist/transport/provider/presets.d.ts.map +1 -0
- package/dist/transport/provider/presets.js +35 -0
- package/dist/transport/provider/presets.js.map +1 -0
- package/dist/transport/provider/register-presets.d.ts +10 -0
- package/dist/transport/provider/register-presets.d.ts.map +1 -0
- package/dist/transport/provider/register-presets.js +32 -0
- package/dist/transport/provider/register-presets.js.map +1 -0
- package/dist/transport/provider/storage/indexeddb.d.ts +26 -0
- package/dist/transport/provider/storage/indexeddb.d.ts.map +1 -0
- package/dist/transport/provider/storage/indexeddb.js +72 -0
- package/dist/transport/provider/storage/indexeddb.js.map +1 -0
- package/dist/transport/provider/strategy/body.d.ts +28 -0
- package/dist/transport/provider/strategy/body.d.ts.map +1 -0
- package/dist/transport/provider/strategy/body.js +73 -0
- package/dist/transport/provider/strategy/body.js.map +1 -0
- package/dist/transport/provider/strategy/cookie.d.ts +29 -0
- package/dist/transport/provider/strategy/cookie.d.ts.map +1 -0
- package/dist/transport/provider/strategy/cookie.js +70 -0
- package/dist/transport/provider/strategy/cookie.js.map +1 -0
- package/dist/transport/result.d.ts +28 -0
- package/dist/transport/result.d.ts.map +1 -0
- package/dist/transport/result.js +87 -0
- package/dist/transport/result.js.map +1 -0
- package/dist/transport/types.d.ts +488 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +3 -0
- package/dist/transport/types.js.map +1 -0
- package/dist/transport/utils/binary.d.ts +20 -0
- package/dist/transport/utils/binary.d.ts.map +1 -0
- package/dist/transport/utils/binary.js +51 -0
- package/dist/transport/utils/binary.js.map +1 -0
- package/dist/transport/utils/formdata.d.ts +26 -0
- package/dist/transport/utils/formdata.d.ts.map +1 -0
- package/dist/transport/utils/formdata.js +77 -0
- package/dist/transport/utils/formdata.js.map +1 -0
- package/dist/transport/utils/registry.d.ts +26 -0
- package/dist/transport/utils/registry.d.ts.map +1 -0
- package/dist/transport/utils/registry.js +51 -0
- package/dist/transport/utils/registry.js.map +1 -0
- package/dist/transport/worker-post.d.ts +44 -0
- package/dist/transport/worker-post.d.ts.map +1 -0
- package/dist/transport/worker-post.js +104 -0
- package/dist/transport/worker-post.js.map +1 -0
- package/dist/transport/worker.d.ts +10 -0
- package/dist/transport/worker.d.ts.map +1 -0
- package/dist/transport/worker.js +421 -0
- package/dist/transport/worker.js.map +1 -0
- package/dist/types.test-d.js +3 -9
- package/dist/types.test-d.js.map +1 -1
- package/eslint-isolation.mjs +82 -0
- package/package.json +30 -16
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/// <reference lib="webworker" />
|
|
2
|
+
import { err, ok } from 'ts-micro-result';
|
|
3
|
+
import { DEFAULT_REFRESH_EARLY_MS } from './constants';
|
|
4
|
+
import { AuthErrors, DomainErrors, GeneralErrors, InitErrors, RequestErrors } from './errors';
|
|
5
|
+
import { MSG } from './messages';
|
|
6
|
+
import { buildProviderFromPreset } from './provider/register-presets';
|
|
7
|
+
import { clearProviders, getProvider, hasProvider, listProviders, registerProvider, unregisterProvider, } from './utils/registry';
|
|
8
|
+
import { sendAuthCallResult, sendAuthStateChanged, sendError, sendFetchError, sendFetchResult, sendPong, sendReady, sendSetupError, sendTokenRefreshed, } from './worker-post';
|
|
9
|
+
// Re-export provider utilities for custom workers
|
|
10
|
+
export { createProvider } from './provider/create-provider';
|
|
11
|
+
export { bodyParser } from './provider/parser/body';
|
|
12
|
+
export { cookieParser } from './provider/parser/cookie';
|
|
13
|
+
export { createIndexedDBStorage } from './provider/storage/indexeddb';
|
|
14
|
+
export { createBodyStrategy } from './provider/strategy/body';
|
|
15
|
+
export { createCookieStrategy } from './provider/strategy/cookie';
|
|
16
|
+
// Re-export registry functions for custom workers
|
|
17
|
+
// This ensures custom workers use the SAME registry instance as the worker IIFE
|
|
18
|
+
export { clearProviders, hasProvider, listProviders, registerProvider, unregisterProvider };
|
|
19
|
+
import { arrayBufferToBase64, isBinaryContentType } from './utils/binary';
|
|
20
|
+
/**
|
|
21
|
+
* IIFE Closure to protect sensitive tokens from external access
|
|
22
|
+
* Inspired by api-worker.js security pattern
|
|
23
|
+
*/
|
|
24
|
+
import { deserializeFormData, isSerializedFormData } from './utils/formdata';
|
|
25
|
+
(() => {
|
|
26
|
+
let config = null;
|
|
27
|
+
let provider = null;
|
|
28
|
+
let accessToken = null;
|
|
29
|
+
let refreshToken = null;
|
|
30
|
+
let expiresAt = null;
|
|
31
|
+
let currentUser;
|
|
32
|
+
const pendingControllers = new Map();
|
|
33
|
+
let refreshPromise = null;
|
|
34
|
+
let authPromise = null;
|
|
35
|
+
/**
|
|
36
|
+
* Mutex wrapper for auth operations (login, logout, custom auth methods)
|
|
37
|
+
* Prevents race conditions when multiple concurrent auth calls are made.
|
|
38
|
+
*
|
|
39
|
+
* Edge case: If authPromise rejects, we catch and ignore it so the next
|
|
40
|
+
* operation can proceed. Without this, a failed login would block
|
|
41
|
+
* subsequent login attempts.
|
|
42
|
+
*/
|
|
43
|
+
async function withAuthMutex(operation) {
|
|
44
|
+
// Wait for any pending auth operation (ignore previous errors)
|
|
45
|
+
if (authPromise) {
|
|
46
|
+
try {
|
|
47
|
+
await authPromise;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Ignore previous auth error - allow new operation to proceed
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const promise = operation();
|
|
54
|
+
authPromise = promise;
|
|
55
|
+
try {
|
|
56
|
+
return await promise;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
authPromise = null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Ensure we have a valid access token (not expired).
|
|
64
|
+
* If token is missing or expired, refresh it.
|
|
65
|
+
* Prevents concurrent refresh attempts.
|
|
66
|
+
*
|
|
67
|
+
* @returns Result<string> - access token on success, error on failure
|
|
68
|
+
*/
|
|
69
|
+
async function ensureValidToken() {
|
|
70
|
+
// Provider must be initialized via SETUP first
|
|
71
|
+
if (!provider) {
|
|
72
|
+
return err(InitErrors.NotInitialized());
|
|
73
|
+
}
|
|
74
|
+
// Determine refresh reason before checking if refresh is needed
|
|
75
|
+
const refreshEarlyMs = config?.refreshEarlyMs ?? DEFAULT_REFRESH_EARLY_MS;
|
|
76
|
+
const now = Date.now();
|
|
77
|
+
const timeLeft = expiresAt ? expiresAt - now : 0;
|
|
78
|
+
const isExpired = !accessToken || !expiresAt || timeLeft <= 0;
|
|
79
|
+
const isProactive = !isExpired && timeLeft <= refreshEarlyMs;
|
|
80
|
+
if (accessToken && expiresAt && timeLeft > refreshEarlyMs) {
|
|
81
|
+
return ok(accessToken);
|
|
82
|
+
}
|
|
83
|
+
if (refreshPromise) {
|
|
84
|
+
const result = await refreshPromise;
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
refreshPromise = (async () => {
|
|
88
|
+
try {
|
|
89
|
+
// Provider already checked above, TypeScript needs assertion
|
|
90
|
+
if (!provider) {
|
|
91
|
+
return err(InitErrors.NotInitialized());
|
|
92
|
+
}
|
|
93
|
+
const valueRes = await provider.refreshToken(refreshToken);
|
|
94
|
+
if (!valueRes.ok) {
|
|
95
|
+
setTokenState({ token: null, expiresAt: null, user: undefined, refreshToken: undefined });
|
|
96
|
+
return err(valueRes.errors);
|
|
97
|
+
}
|
|
98
|
+
const tokenInfo = valueRes.data;
|
|
99
|
+
if (!tokenInfo) {
|
|
100
|
+
return err(AuthErrors.TokenRefreshFailed({ message: 'Provider returned null token info' }));
|
|
101
|
+
}
|
|
102
|
+
setTokenState(tokenInfo);
|
|
103
|
+
// Validate that we got a valid access token after refresh
|
|
104
|
+
if (!accessToken) {
|
|
105
|
+
return err(AuthErrors.TokenRefreshFailed({ message: 'Access token is null after refresh' }));
|
|
106
|
+
}
|
|
107
|
+
// Emit TOKEN_REFRESHED event for debug hooks
|
|
108
|
+
sendTokenRefreshed(isProactive ? 'proactive' : 'expired');
|
|
109
|
+
return ok(accessToken);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
refreshPromise = null;
|
|
113
|
+
}
|
|
114
|
+
})();
|
|
115
|
+
return refreshPromise;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Validate domain against allowed domains
|
|
119
|
+
*/
|
|
120
|
+
function validateDomain(url) {
|
|
121
|
+
if (!config?.allowedDomains?.length) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const urlObj = new URL(url);
|
|
126
|
+
const hostname = urlObj.hostname;
|
|
127
|
+
const port = urlObj.port;
|
|
128
|
+
for (const entry of config.allowedDomains) {
|
|
129
|
+
const idx = entry.lastIndexOf(':');
|
|
130
|
+
const hasPort = idx > -1 && entry.indexOf(':') === idx;
|
|
131
|
+
const pattern = hasPort ? entry.slice(0, idx) : entry;
|
|
132
|
+
const entryPort = hasPort ? entry.slice(idx + 1) : '';
|
|
133
|
+
const isWildcard = pattern.startsWith('*.');
|
|
134
|
+
const base = isWildcard ? pattern.slice(2) : pattern;
|
|
135
|
+
const hostnameMatch = isWildcard ? hostname === base || hostname.endsWith(`.${base}`) : hostname === base;
|
|
136
|
+
if (!hostnameMatch)
|
|
137
|
+
continue;
|
|
138
|
+
if (hasPort) {
|
|
139
|
+
if (port === entryPort)
|
|
140
|
+
return true;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Make API request with proactive token management
|
|
153
|
+
*/
|
|
154
|
+
async function makeApiRequest(url, options = {}) {
|
|
155
|
+
if (!config) {
|
|
156
|
+
return err(InitErrors.NotInitialized());
|
|
157
|
+
}
|
|
158
|
+
if (!validateDomain(url)) {
|
|
159
|
+
return err(DomainErrors.NotAllowed({ url }));
|
|
160
|
+
}
|
|
161
|
+
const requiresAuth = options.requiresAuth !== false;
|
|
162
|
+
const includeHeaders = options.includeHeaders === true;
|
|
163
|
+
// Extract FetchGuard-specific options and keep only standard RequestInit
|
|
164
|
+
const { requiresAuth: _, includeHeaders: __, ...fetchOptions } = options;
|
|
165
|
+
// Deserialize FormData if present (inspired by api-worker.js:484-518)
|
|
166
|
+
if (fetchOptions.body && isSerializedFormData(fetchOptions.body)) {
|
|
167
|
+
fetchOptions.body = deserializeFormData(fetchOptions.body);
|
|
168
|
+
}
|
|
169
|
+
const headers = {
|
|
170
|
+
...(config.defaultHeaders || {}),
|
|
171
|
+
...(fetchOptions.headers || {}),
|
|
172
|
+
};
|
|
173
|
+
// Don't set Content-Type for FormData - browser will set it with boundary
|
|
174
|
+
if (!headers['Content-Type'] && !headers['content-type'] && fetchOptions.body) {
|
|
175
|
+
if (typeof fetchOptions.body === 'object' &&
|
|
176
|
+
!(fetchOptions.body instanceof FormData) &&
|
|
177
|
+
!(fetchOptions.body instanceof URLSearchParams)) {
|
|
178
|
+
headers['Content-Type'] = 'application/json';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (requiresAuth) {
|
|
182
|
+
const tokenRes = await ensureValidToken();
|
|
183
|
+
if (!tokenRes.ok) {
|
|
184
|
+
// Propagate error - cast to correct return type
|
|
185
|
+
return err(tokenRes.errors);
|
|
186
|
+
}
|
|
187
|
+
const token = tokenRes.data;
|
|
188
|
+
if (token) {
|
|
189
|
+
headers.Authorization = `Bearer ${token}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
let response;
|
|
193
|
+
try {
|
|
194
|
+
response = await fetch(url, { ...fetchOptions, headers, credentials: 'include' });
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
const aborted = e instanceof Error && e.name === 'AbortError';
|
|
198
|
+
return aborted ? err(RequestErrors.Cancelled()) : err(RequestErrors.NetworkError({ message: String(e) }));
|
|
199
|
+
}
|
|
200
|
+
// Extract content-type (always needed for binary detection)
|
|
201
|
+
const contentType = response.headers.get('content-type') || 'application/octet-stream';
|
|
202
|
+
// Determine if response is binary
|
|
203
|
+
const isBinary = isBinaryContentType(contentType);
|
|
204
|
+
// Get body as text or base64
|
|
205
|
+
let body;
|
|
206
|
+
try {
|
|
207
|
+
if (isBinary) {
|
|
208
|
+
const buffer = await response.arrayBuffer();
|
|
209
|
+
body = arrayBufferToBase64(buffer);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
body = await response.text();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (e) {
|
|
216
|
+
// Reading/parsing response body failed
|
|
217
|
+
return err(RequestErrors.ResponseParseFailed({ message: String(e) }));
|
|
218
|
+
}
|
|
219
|
+
// Extract headers if requested
|
|
220
|
+
const responseHeaders = {};
|
|
221
|
+
if (includeHeaders) {
|
|
222
|
+
response.headers.forEach((value, key) => {
|
|
223
|
+
responseHeaders[key] = value;
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const responseData = { body, status: response.status, contentType, headers: responseHeaders };
|
|
227
|
+
return ok(responseData);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Update token state from TokenInfo and auto emit AUTH_STATE_CHANGED
|
|
231
|
+
*
|
|
232
|
+
* Smart update logic for ALL fields:
|
|
233
|
+
* - Only update field if key exists in tokenInfo
|
|
234
|
+
* - If key exists with value: update to that value (including null)
|
|
235
|
+
* - If key doesn't exist: preserve existing value
|
|
236
|
+
*
|
|
237
|
+
* This allows flexible custom auth methods:
|
|
238
|
+
* - Standard login/refresh: returns { token, user, expiresAt }
|
|
239
|
+
* - Update user info: may only return { user: {...} } (no token change)
|
|
240
|
+
* - Verify OTP: may return {} (just validation, no state change)
|
|
241
|
+
* - Logout: returns { token: null, user: null, ... } to clear all
|
|
242
|
+
*/
|
|
243
|
+
function setTokenState(tokenInfo, emitEvent = true) {
|
|
244
|
+
// Apply smart preservation to ALL fields
|
|
245
|
+
if ('token' in tokenInfo) {
|
|
246
|
+
accessToken = tokenInfo.token ?? null;
|
|
247
|
+
}
|
|
248
|
+
if ('expiresAt' in tokenInfo) {
|
|
249
|
+
expiresAt = tokenInfo.expiresAt ?? null;
|
|
250
|
+
}
|
|
251
|
+
if ('user' in tokenInfo) {
|
|
252
|
+
currentUser = tokenInfo.user;
|
|
253
|
+
}
|
|
254
|
+
if ('refreshToken' in tokenInfo) {
|
|
255
|
+
refreshToken = tokenInfo.refreshToken ?? null;
|
|
256
|
+
}
|
|
257
|
+
if (emitEvent) {
|
|
258
|
+
postAuthChanged();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Emit AUTH_STATE_CHANGED event based on current state
|
|
263
|
+
* authenticated = true if we have valid non-expired token
|
|
264
|
+
*/
|
|
265
|
+
function postAuthChanged() {
|
|
266
|
+
const now = Date.now();
|
|
267
|
+
const authenticated = accessToken !== null && accessToken !== '' && (expiresAt === null || expiresAt > now);
|
|
268
|
+
sendAuthStateChanged({
|
|
269
|
+
authenticated,
|
|
270
|
+
expiresAt,
|
|
271
|
+
user: currentUser,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Main message handler
|
|
276
|
+
* Each case has its own try-catch for better error isolation
|
|
277
|
+
*/
|
|
278
|
+
self.onmessage = async (event) => {
|
|
279
|
+
const data = event.data;
|
|
280
|
+
switch (data.type) {
|
|
281
|
+
case MSG.SETUP: {
|
|
282
|
+
try {
|
|
283
|
+
const payload = data.payload;
|
|
284
|
+
config = payload.config;
|
|
285
|
+
const providerConfig = payload.providerConfig;
|
|
286
|
+
// Build provider from config
|
|
287
|
+
if (typeof providerConfig === 'string') {
|
|
288
|
+
// Registry lookup
|
|
289
|
+
provider = getProvider(providerConfig);
|
|
290
|
+
}
|
|
291
|
+
else if (providerConfig && typeof providerConfig === 'object' && 'type' in providerConfig) {
|
|
292
|
+
// ProviderPresetConfig object - pass defaultHeaders for auth requests
|
|
293
|
+
provider = buildProviderFromPreset(providerConfig, config.defaultHeaders);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
sendSetupError('Invalid provider config');
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
// Validate provider was successfully created
|
|
300
|
+
if (!provider) {
|
|
301
|
+
sendSetupError('Provider initialization failed - provider is null');
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
sendReady();
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
308
|
+
console.error('[FetchGuard Worker] Setup failed:', errorMessage);
|
|
309
|
+
sendSetupError(errorMessage);
|
|
310
|
+
}
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
case MSG.FETCH: {
|
|
314
|
+
const { id } = data;
|
|
315
|
+
try {
|
|
316
|
+
const { url, options } = data.payload;
|
|
317
|
+
const controller = new AbortController();
|
|
318
|
+
pendingControllers.set(id, controller);
|
|
319
|
+
const merged = { ...(options || {}), signal: controller.signal };
|
|
320
|
+
const result = await makeApiRequest(url, merged);
|
|
321
|
+
if (result.ok) {
|
|
322
|
+
sendFetchResult(id, result.data);
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
// Network/timeout/cancel error
|
|
326
|
+
const error = result.errors[0];
|
|
327
|
+
const message = error?.message || 'Unknown error';
|
|
328
|
+
sendFetchError(id, message, undefined);
|
|
329
|
+
}
|
|
330
|
+
pendingControllers.delete(id);
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
pendingControllers.delete(id);
|
|
334
|
+
sendFetchError(id, error instanceof Error ? error.message : String(error), undefined);
|
|
335
|
+
}
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
case MSG.AUTH_CALL: {
|
|
339
|
+
const { id, payload } = data;
|
|
340
|
+
// Use mutex to prevent concurrent auth operations (login, logout, etc.)
|
|
341
|
+
await withAuthMutex(async () => {
|
|
342
|
+
try {
|
|
343
|
+
const { method, args, emitEvent } = payload;
|
|
344
|
+
const shouldEmitEvent = emitEvent ?? true; // Default: emit event
|
|
345
|
+
if (!provider) {
|
|
346
|
+
sendError(id, err(InitErrors.NotInitialized()));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (typeof provider[method] !== 'function') {
|
|
350
|
+
sendError(id, err(GeneralErrors.Unexpected({ message: `Method '${method}' not found on provider` })));
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
// Inject current access token for exchangeToken method
|
|
354
|
+
let methodArgs = args;
|
|
355
|
+
if (method === 'exchangeToken') {
|
|
356
|
+
methodArgs = [accessToken, ...args];
|
|
357
|
+
}
|
|
358
|
+
// Dynamic dispatch: the index signature uses `never[]` params (so
|
|
359
|
+
// specific methods stay assignable without `any`); narrow to a
|
|
360
|
+
// callable here to spread runtime args.
|
|
361
|
+
const fn = provider[method];
|
|
362
|
+
const result = await fn(...methodArgs);
|
|
363
|
+
if (!result.ok) {
|
|
364
|
+
sendError(id, result);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const tokenInfo = result.data;
|
|
368
|
+
if (!tokenInfo) {
|
|
369
|
+
sendError(id, err(GeneralErrors.Unexpected({ message: 'Provider returned null token info' })));
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
// Update token state and optionally emit event
|
|
373
|
+
setTokenState(tokenInfo, shouldEmitEvent);
|
|
374
|
+
// Always send AuthResult back
|
|
375
|
+
const now = Date.now();
|
|
376
|
+
const authenticated = accessToken !== null && accessToken !== '' && (expiresAt === null || expiresAt > now);
|
|
377
|
+
sendAuthCallResult(id, {
|
|
378
|
+
authenticated,
|
|
379
|
+
expiresAt,
|
|
380
|
+
user: currentUser,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
sendError(id, err(GeneralErrors.Unexpected({ message: error instanceof Error ? error.message : String(error) })));
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
case MSG.CANCEL: {
|
|
390
|
+
try {
|
|
391
|
+
const { id } = data;
|
|
392
|
+
const controller = pendingControllers.get(id);
|
|
393
|
+
if (controller) {
|
|
394
|
+
controller.abort();
|
|
395
|
+
pendingControllers.delete(id);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
catch (_error) {
|
|
399
|
+
// Silently ignore cancel errors
|
|
400
|
+
}
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
case MSG.PING: {
|
|
404
|
+
const { id } = data;
|
|
405
|
+
try {
|
|
406
|
+
const ts = data.payload?.timestamp ?? Date.now();
|
|
407
|
+
sendPong(id, ts);
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
sendError(id, err(GeneralErrors.Unexpected({ message: error instanceof Error ? error.message : String(error) })));
|
|
411
|
+
}
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
default: {
|
|
415
|
+
const unknownData = data;
|
|
416
|
+
sendError(unknownData.id ?? `evt_${Date.now()}`, err(GeneralErrors.UnknownMessage({ message: `Unknown message type: ${String(unknownData.type)}` })));
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
})(); // End IIFE - Immediately Invoked Function Expression
|
|
421
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/transport/worker.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9F,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAStE,OAAO,EACL,cAAc,EACd,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB,kDAAkD;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAElE,kDAAkD;AAClD,gFAAgF;AAChF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;AAE5F,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1E;;;GAGG;AACH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,CAAC,GAAG,EAAE;IACJ,IAAI,MAAM,GAAwB,IAAI,CAAC;IACvC,IAAI,QAAQ,GAAyB,IAAI,CAAC;IAC1C,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,IAAI,WAAgC,CAAC;IACrC,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC9D,IAAI,cAAc,GAAmC,IAAI,CAAC;IAC1D,IAAI,WAAW,GAA4B,IAAI,CAAC;IAEhD;;;;;;;OAOG;IACH,KAAK,UAAU,aAAa,CAAI,SAA2B;QACzD,+DAA+D;QAC/D,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC;gBACP,8DAA8D;YAChE,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;QAC5B,WAAW,GAAG,OAAO,CAAC;QAEtB,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,WAAW,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,UAAU,gBAAgB;QAC7B,+CAA+C;QAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,GAAG,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;QAC1C,CAAC;QAED,gEAAgE;QAChE,MAAM,cAAc,GAAG,MAAM,EAAE,cAAc,IAAI,wBAAwB,CAAC;QAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,CAAC,WAAW,IAAI,CAAC,SAAS,IAAI,QAAQ,IAAI,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,CAAC,SAAS,IAAI,QAAQ,IAAI,cAAc,CAAC;QAE7D,IAAI,WAAW,IAAI,SAAS,IAAI,QAAQ,GAAG,cAAc,EAAE,CAAC;YAC1D,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YACpC,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,cAAc,GAAG,CAAC,KAAK,IAA6B,EAAE;YACpD,IAAI,CAAC;gBACH,6DAA6D;gBAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,OAAO,GAAG,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;gBAC1C,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;gBAE3D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,aAAa,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC;oBAC1F,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC9B,CAAC;gBAED,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC;gBAChC,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,GAAG,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAC,CAAC;gBAC9F,CAAC;gBAED,aAAa,CAAC,SAAS,CAAC,CAAC;gBAEzB,0DAA0D;gBAC1D,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO,GAAG,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC,CAAC;gBAC/F,CAAC;gBAED,6CAA6C;gBAC7C,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAE1D,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC;YACzB,CAAC;oBAAS,CAAC;gBACT,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QAEL,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,SAAS,cAAc,CAAC,GAAW;QACjC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;YACjC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YAEzB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;gBACnC,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC;gBACvD,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBACtD,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;gBAErD,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC;gBAE1G,IAAI,CAAC,aAAa;oBAAE,SAAS;gBAE7B,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,IAAI,KAAK,SAAS;wBAAE,OAAO,IAAI,CAAC;oBACpC,SAAS;gBACX,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,UAAiC,EAAE;QAC5E,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,GAAG,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,KAAK,KAAK,CAAC;QACpD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,KAAK,IAAI,CAAC;QACvD,yEAAyE;QACzE,MAAM,EAAE,YAAY,EAAE,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;QAEzE,sEAAsE;QACtE,IAAI,YAAY,CAAC,IAAI,IAAI,oBAAoB,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACjE,YAAY,CAAC,IAAI,GAAG,mBAAmB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,OAAO,GAA2B;YACtC,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;YAChC,GAAG,CAAE,YAAY,CAAC,OAAkC,IAAI,EAAE,CAAC;SAC5D,CAAC;QAEF,0EAA0E;QAC1E,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC;YAC9E,IACE,OAAO,YAAY,CAAC,IAAI,KAAK,QAAQ;gBACrC,CAAC,CAAC,YAAY,CAAC,IAAI,YAAY,QAAQ,CAAC;gBACxC,CAAC,CAAC,YAAY,CAAC,IAAI,YAAY,eAAe,CAAC,EAC/C,CAAC;gBACD,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,EAAE,CAAC;YAC1C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,gDAAgD;gBAChD,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC;YAC5B,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACpF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC;YAC9D,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5G,CAAC;QAED,4DAA4D;QAC5D,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,0BAA0B,CAAC;QAEvF,kCAAkC;QAClC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAElD,6BAA6B;QAC7B,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC5C,IAAI,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,uCAAuC;YACvC,OAAO,GAAG,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC;QAED,+BAA+B;QAC/B,MAAM,eAAe,GAA2B,EAAE,CAAC;QACnD,IAAI,cAAc,EAAE,CAAC;YACnB,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBACtC,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC/B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,YAAY,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;QAC9F,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,SAAS,aAAa,CACpB,SAA6G,EAC7G,YAAqB,IAAI;QAEzB,yCAAyC;QACzC,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;YACzB,WAAW,GAAG,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC;QACxC,CAAC;QAED,IAAI,WAAW,IAAI,SAAS,EAAE,CAAC;YAC7B,SAAS,GAAG,SAAS,CAAC,SAAS,IAAI,IAAI,CAAC;QAC1C,CAAC;QAED,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YACxB,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,cAAc,IAAI,SAAS,EAAE,CAAC;YAChC,YAAY,GAAG,SAAS,CAAC,YAAY,IAAI,IAAI,CAAC;QAChD,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,eAAe,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,SAAS,eAAe;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,aAAa,GAAG,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,SAAS,GAAG,GAAG,CAAC,CAAC;QAC5G,oBAAoB,CAAC;YACnB,aAAa;YACb,SAAS;YACT,IAAI,EAAE,WAAW;SAClB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,SAAS,GAAG,KAAK,EAAE,KAAwC,EAAE,EAAE;QAClE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;gBACf,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;oBAC7B,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;oBAExB,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;oBAE9C,6BAA6B;oBAC7B,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;wBACvC,kBAAkB;wBAClB,QAAQ,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;oBACzC,CAAC;yBAAM,IAAI,cAAc,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,MAAM,IAAI,cAAc,EAAE,CAAC;wBAC5F,sEAAsE;wBACtE,QAAQ,GAAG,uBAAuB,CAAC,cAAsC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;oBACpG,CAAC;yBAAM,CAAC;wBACN,cAAc,CAAC,yBAAyB,CAAC,CAAC;wBAC1C,MAAM;oBACR,CAAC;oBAED,6CAA6C;oBAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACd,cAAc,CAAC,mDAAmD,CAAC,CAAC;wBACpE,MAAM;oBACR,CAAC;oBAED,SAAS,EAAE,CAAC;gBACd,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAC5E,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,YAAY,CAAC,CAAC;oBACjE,cAAc,CAAC,YAAY,CAAC,CAAC;gBAC/B,CAAC;gBACD,MAAM;YACR,CAAC;YAED,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;gBACf,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;gBACpB,IAAI,CAAC;oBACH,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;oBACtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;oBACzC,kBAAkB,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;oBACvC,MAAM,MAAM,GAAgB,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;oBAC9E,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;oBAEjD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;wBACd,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;oBACnC,CAAC;yBAAM,CAAC;wBACN,+BAA+B;wBAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;wBAC/B,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,eAAe,CAAC;wBAClD,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;oBACzC,CAAC;oBAED,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAChC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAC9B,cAAc,CAAC,EAAE,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;gBACxF,CAAC;gBACD,MAAM;YACR,CAAC;YAED,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;gBACnB,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;gBAC7B,wEAAwE;gBACxE,MAAM,aAAa,CAAC,KAAK,IAAI,EAAE;oBAC7B,IAAI,CAAC;wBACH,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;wBAC5C,MAAM,eAAe,GAAG,SAAS,IAAI,IAAI,CAAC,CAAC,sBAAsB;wBAEjE,IAAI,CAAC,QAAQ,EAAE,CAAC;4BACd,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;4BAChD,OAAO;wBACT,CAAC;wBAED,IAAI,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC;4BAC3C,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,WAAW,MAAM,yBAAyB,EAAE,CAAC,CAAC,CAAC,CAAC;4BACtG,OAAO;wBACT,CAAC;wBAED,uDAAuD;wBACvD,IAAI,UAAU,GAAG,IAAI,CAAC;wBACtB,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;4BAC/B,UAAU,GAAG,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,CAAC;wBACtC,CAAC;wBAED,kEAAkE;wBAClE,+DAA+D;wBAC/D,wCAAwC;wBACxC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAoD,CAAC;wBAC/E,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;wBACvC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;4BACf,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;4BACtB,OAAO;wBACT,CAAC;wBAED,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;wBAC9B,IAAI,CAAC,SAAS,EAAE,CAAC;4BACf,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAC,CAAC,CAAC;4BAC/F,OAAO;wBACT,CAAC;wBAED,+CAA+C;wBAC/C,aAAa,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;wBAE1C,8BAA8B;wBAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;wBACvB,MAAM,aAAa,GAAG,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,SAAS,GAAG,GAAG,CAAC,CAAC;wBAE5G,kBAAkB,CAAC,EAAE,EAAE;4BACrB,aAAa;4BACb,SAAS;4BACT,IAAI,EAAE,WAAW;yBAClB,CAAC,CAAC;oBACL,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,SAAS,CACP,EAAE,EACF,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CACnG,CAAC;oBACJ,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;YAED,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChB,IAAI,CAAC;oBACH,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;oBACpB,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBAC9C,IAAI,UAAU,EAAE,CAAC;wBACf,UAAU,CAAC,KAAK,EAAE,CAAC;wBACnB,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAChC,CAAC;gBACH,CAAC;gBAAC,OAAO,MAAM,EAAE,CAAC;oBAChB,gCAAgC;gBAClC,CAAC;gBACD,MAAM;YACR,CAAC;YAED,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gBACd,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;gBACpB,IAAI,CAAC;oBACH,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;oBACjD,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBACnB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,SAAS,CACP,EAAE,EACF,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CACnG,CAAC;gBACJ,CAAC;gBACD,MAAM;YACR,CAAC;YAED,OAAO,CAAC,CAAC,CAAC;gBACR,MAAM,WAAW,GAAG,IAAuC,CAAC;gBAC5D,SAAS,CACP,WAAW,CAAC,EAAE,IAAI,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,EACrC,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,yBAAyB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CACpG,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC,CAAC,qDAAqD"}
|
package/dist/types.test-d.js
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
* Type-level POC: the generated client methods are typed FROM the contract.
|
|
3
|
-
* Correct calls compile; wrong calls must fail (verified by @ts-expect-error).
|
|
4
|
-
* This is the mechanical guarantee — a contract change re-types these call sites.
|
|
5
|
-
*
|
|
6
|
-
* This file is type-checked (tsc --noEmit), not executed.
|
|
7
|
-
*/
|
|
8
|
-
import { authContract } from '@auth-craft/api-contract';
|
|
1
|
+
void _unreachable;
|
|
9
2
|
// ✓ me: no body, no params → callable with no argument
|
|
10
3
|
void client.me();
|
|
11
4
|
// ✓ authenticate: body inferred from the contract schema
|
|
12
5
|
void client.authenticate({
|
|
13
|
-
body: { identityType: 'email', identityValue: 'a@b.com', credentialType: 'password', credentialValue: 'x' }
|
|
6
|
+
body: { identityType: 'email', identityValue: 'a@b.com', credentialType: 'password', credentialValue: 'x' },
|
|
14
7
|
});
|
|
15
8
|
// ✓ selectTenant: body { tenantId }
|
|
16
9
|
void client.selectTenant({ body: { tenantId: 't1' } });
|
|
@@ -23,4 +16,5 @@ void client.selectTenant({ body: { tenant: 't1' } });
|
|
|
23
16
|
// ✗ me takes no body → MUST error
|
|
24
17
|
// @ts-expect-error me accepts no argument with body
|
|
25
18
|
void client.me({ body: { x: 1 } });
|
|
19
|
+
export {};
|
|
26
20
|
//# sourceMappingURL=types.test-d.js.map
|
package/dist/types.test-d.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.test-d.js","sourceRoot":"","sources":["../src/types.test-d.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.test-d.js","sourceRoot":"","sources":["../src/types.test-d.ts"],"names":[],"mappings":"AA4CA,KAAM,YAA6B,CAAC;AAIpC,uDAAuD;AACvD,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;AAEjB,yDAAyD;AACzD,KAAK,MAAM,CAAC,YAAY,CAAC;IACvB,IAAI,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,EAAE;CAC5G,CAAC,CAAC;AAEH,oCAAoC;AACpC,KAAK,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AAEvD,sDAAsD;AACtD,+DAA+D;AAC/D,KAAK,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;AAE9D,+CAA+C;AAC/C,iDAAiD;AACjD,KAAK,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AAErD,kCAAkC;AAClC,oDAAoD;AACpD,KAAK,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Craft scope-isolation ESLint guard (shipped with @auth-craft/client-core).
|
|
3
|
+
*
|
|
4
|
+
* Any project that consumes the client gets this for free:
|
|
5
|
+
* import { authCraftIsolation } from '@auth-craft/client-core/eslint'
|
|
6
|
+
*
|
|
7
|
+
* Goal: keep each web app's bundle (and its dev call surface) free of contract
|
|
8
|
+
* groups it doesn't own. The per-scope subpath split in @auth-craft/api-contract
|
|
9
|
+
* only pays off if apps import the narrow group entry — these rules make the
|
|
10
|
+
* wrong import a lint error instead of a silently-bloated bundle.
|
|
11
|
+
*
|
|
12
|
+
* Two invariants, enforced for every app:
|
|
13
|
+
* 1. Use @auth-craft/client-core + per-group contract subpaths. The
|
|
14
|
+
* batteries-included class @auth-craft/client references ALL groups, so the
|
|
15
|
+
* bundler can't tree-shake any of them away.
|
|
16
|
+
* 2. Importing the api-contract ROOT re-exports every group → same bloat.
|
|
17
|
+
*
|
|
18
|
+
* Plus a per-app allow-list: an app may only import the groups in its scope.
|
|
19
|
+
*
|
|
20
|
+
* Usage in an app's flat config (eslint.config.mjs):
|
|
21
|
+
*
|
|
22
|
+
* import tseslint from 'typescript-eslint'
|
|
23
|
+
* import { authCraftIsolation } from '@auth-craft/client-core/eslint'
|
|
24
|
+
*
|
|
25
|
+
* export default tseslint.config(
|
|
26
|
+
* // ...existing config...
|
|
27
|
+
* authCraftIsolation({ allow: ['auth', 'password', 'verification', 'mfa', 'oauth', 'session', 'users'] })
|
|
28
|
+
* )
|
|
29
|
+
*
|
|
30
|
+
* Omit a group (e.g. 'tenant') and importing it becomes an error.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/** All contract groups exposed as @auth-craft/api-contract/<group> subpaths. */
|
|
34
|
+
export const ALL_GROUPS = [
|
|
35
|
+
'auth', 'password', 'verification', 'session',
|
|
36
|
+
'mfa', 'oauth', 'users', 'tenant'
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build a flat-config block that restricts Auth Craft imports to an app's scope.
|
|
41
|
+
*
|
|
42
|
+
* @param {{ allow: string[], files?: string[] }} opts
|
|
43
|
+
* allow — contract groups this app is permitted to import (subset of ALL_GROUPS).
|
|
44
|
+
* files — glob(s) to apply to (default: src TS/TSX).
|
|
45
|
+
* @returns an ESLint flat-config object.
|
|
46
|
+
*/
|
|
47
|
+
export function authCraftIsolation({ allow, files = ['src/**/*.{ts,tsx}'] }) {
|
|
48
|
+
const unknown = allow.filter((g) => !ALL_GROUPS.includes(g))
|
|
49
|
+
if (unknown.length > 0) {
|
|
50
|
+
throw new Error(`authCraftIsolation: unknown group(s): ${unknown.join(', ')}. Valid: ${ALL_GROUPS.join(', ')}`)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const forbiddenGroups = ALL_GROUPS.filter((g) => !allow.includes(g))
|
|
54
|
+
|
|
55
|
+
const patterns = [
|
|
56
|
+
{
|
|
57
|
+
group: ['@auth-craft/client'],
|
|
58
|
+
message:
|
|
59
|
+
'Import @auth-craft/client-core + the per-group contract subpaths instead. ' +
|
|
60
|
+
'@auth-craft/client bundles every scope (auth+tenant+system) and cannot be tree-shaken.'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
group: ['@auth-craft/api-contract'],
|
|
64
|
+
message:
|
|
65
|
+
'Import a focused group, e.g. @auth-craft/api-contract/auth, not the root ' +
|
|
66
|
+
'(the root re-exports every group and defeats per-scope isolation).'
|
|
67
|
+
},
|
|
68
|
+
...forbiddenGroups.map((g) => ({
|
|
69
|
+
group: [`@auth-craft/api-contract/${g}`],
|
|
70
|
+
message:
|
|
71
|
+
`This app's scope does not include the '${g}' contract group. ` +
|
|
72
|
+
`Importing it pulls out-of-scope routes into the bundle. Allowed: ${allow.join(', ')}.`
|
|
73
|
+
}))
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
files,
|
|
78
|
+
rules: {
|
|
79
|
+
'no-restricted-imports': ['error', { patterns }]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auth-craft/client",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Contract-driven typed frontend client for Auth Craft. Methods are generated from @auth-craft/api-contract
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Contract-driven typed frontend client for Auth Craft. Methods are generated from @auth-craft/api-contract; tokens are isolated in a Web Worker. Import the root for all groups, or @auth-craft/client/core for a scope-agnostic core you wire per scope.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -9,25 +9,39 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
12
|
+
},
|
|
13
|
+
"./core": {
|
|
14
|
+
"types": "./dist/core/core.d.ts",
|
|
15
|
+
"import": "./dist/core/core.js"
|
|
16
|
+
},
|
|
17
|
+
"./worker": {
|
|
18
|
+
"import": "./dist/transport/worker.js"
|
|
19
|
+
},
|
|
20
|
+
"./eslint": "./eslint-isolation.mjs"
|
|
21
21
|
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"eslint-isolation.mjs",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
22
27
|
"dependencies": {
|
|
23
|
-
"@auth-craft/api-contract": "workspace:*",
|
|
24
|
-
"@auth-craft/transport": "workspace:*",
|
|
25
28
|
"ts-micro-result": "^3.3.0",
|
|
26
|
-
"valibot": "^1.4.1"
|
|
29
|
+
"valibot": "^1.4.1",
|
|
30
|
+
"@auth-craft/api-contract": "^0.1.0"
|
|
27
31
|
},
|
|
28
32
|
"devDependencies": {
|
|
29
33
|
"typescript": "^6.0.3",
|
|
30
34
|
"vitest": "^4.1.8"
|
|
31
35
|
},
|
|
32
|
-
"license": "MIT"
|
|
33
|
-
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"dev": "tsc --watch",
|
|
43
|
+
"clean": "rm -rf dist",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run --passWithNoTests"
|
|
46
|
+
}
|
|
47
|
+
}
|