@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.
Files changed (109) hide show
  1. package/README.md +144 -8
  2. package/dist/core/core.d.ts +72 -0
  3. package/dist/core/core.d.ts.map +1 -0
  4. package/dist/core/core.js +105 -0
  5. package/dist/core/core.js.map +1 -0
  6. package/dist/core/proxy.d.ts +79 -0
  7. package/dist/core/proxy.d.ts.map +1 -0
  8. package/dist/core/proxy.js +99 -0
  9. package/dist/core/proxy.js.map +1 -0
  10. package/dist/index.d.ts +15 -28
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +23 -55
  13. package/dist/index.js.map +1 -1
  14. package/dist/transport/client.d.ts +250 -0
  15. package/dist/transport/client.d.ts.map +1 -0
  16. package/dist/transport/client.js +940 -0
  17. package/dist/transport/client.js.map +1 -0
  18. package/dist/transport/constants.d.ts +9 -0
  19. package/dist/transport/constants.d.ts.map +1 -0
  20. package/dist/transport/constants.js +9 -0
  21. package/dist/transport/constants.js.map +1 -0
  22. package/dist/transport/error-codes.d.ts +41 -0
  23. package/dist/transport/error-codes.d.ts.map +1 -0
  24. package/dist/transport/error-codes.js +38 -0
  25. package/dist/transport/error-codes.js.map +1 -0
  26. package/dist/transport/errors.d.ts +55 -0
  27. package/dist/transport/errors.d.ts.map +1 -0
  28. package/dist/transport/errors.js +55 -0
  29. package/dist/transport/errors.js.map +1 -0
  30. package/dist/transport/helpers.d.ts +135 -0
  31. package/dist/transport/helpers.d.ts.map +1 -0
  32. package/dist/transport/helpers.js +185 -0
  33. package/dist/transport/helpers.js.map +1 -0
  34. package/dist/transport/index.d.ts +22 -0
  35. package/dist/transport/index.d.ts.map +1 -0
  36. package/dist/transport/index.js +32 -0
  37. package/dist/transport/index.js.map +1 -0
  38. package/dist/transport/messages.d.ts +104 -0
  39. package/dist/transport/messages.d.ts.map +1 -0
  40. package/dist/transport/messages.js +24 -0
  41. package/dist/transport/messages.js.map +1 -0
  42. package/dist/transport/provider/create-provider.d.ts +38 -0
  43. package/dist/transport/provider/create-provider.d.ts.map +1 -0
  44. package/dist/transport/provider/create-provider.js +119 -0
  45. package/dist/transport/provider/create-provider.js.map +1 -0
  46. package/dist/transport/provider/parser/body.d.ts +7 -0
  47. package/dist/transport/provider/parser/body.d.ts.map +1 -0
  48. package/dist/transport/provider/parser/body.js +17 -0
  49. package/dist/transport/provider/parser/body.js.map +1 -0
  50. package/dist/transport/provider/parser/cookie.d.ts +8 -0
  51. package/dist/transport/provider/parser/cookie.d.ts.map +1 -0
  52. package/dist/transport/provider/parser/cookie.js +17 -0
  53. package/dist/transport/provider/parser/cookie.js.map +1 -0
  54. package/dist/transport/provider/parser/normalize.d.ts +6 -0
  55. package/dist/transport/provider/parser/normalize.d.ts.map +1 -0
  56. package/dist/transport/provider/parser/normalize.js +21 -0
  57. package/dist/transport/provider/parser/normalize.js.map +1 -0
  58. package/dist/transport/provider/presets.d.ts +31 -0
  59. package/dist/transport/provider/presets.d.ts.map +1 -0
  60. package/dist/transport/provider/presets.js +35 -0
  61. package/dist/transport/provider/presets.js.map +1 -0
  62. package/dist/transport/provider/register-presets.d.ts +10 -0
  63. package/dist/transport/provider/register-presets.d.ts.map +1 -0
  64. package/dist/transport/provider/register-presets.js +32 -0
  65. package/dist/transport/provider/register-presets.js.map +1 -0
  66. package/dist/transport/provider/storage/indexeddb.d.ts +26 -0
  67. package/dist/transport/provider/storage/indexeddb.d.ts.map +1 -0
  68. package/dist/transport/provider/storage/indexeddb.js +72 -0
  69. package/dist/transport/provider/storage/indexeddb.js.map +1 -0
  70. package/dist/transport/provider/strategy/body.d.ts +28 -0
  71. package/dist/transport/provider/strategy/body.d.ts.map +1 -0
  72. package/dist/transport/provider/strategy/body.js +73 -0
  73. package/dist/transport/provider/strategy/body.js.map +1 -0
  74. package/dist/transport/provider/strategy/cookie.d.ts +29 -0
  75. package/dist/transport/provider/strategy/cookie.d.ts.map +1 -0
  76. package/dist/transport/provider/strategy/cookie.js +70 -0
  77. package/dist/transport/provider/strategy/cookie.js.map +1 -0
  78. package/dist/transport/result.d.ts +28 -0
  79. package/dist/transport/result.d.ts.map +1 -0
  80. package/dist/transport/result.js +87 -0
  81. package/dist/transport/result.js.map +1 -0
  82. package/dist/transport/types.d.ts +488 -0
  83. package/dist/transport/types.d.ts.map +1 -0
  84. package/dist/transport/types.js +3 -0
  85. package/dist/transport/types.js.map +1 -0
  86. package/dist/transport/utils/binary.d.ts +20 -0
  87. package/dist/transport/utils/binary.d.ts.map +1 -0
  88. package/dist/transport/utils/binary.js +51 -0
  89. package/dist/transport/utils/binary.js.map +1 -0
  90. package/dist/transport/utils/formdata.d.ts +26 -0
  91. package/dist/transport/utils/formdata.d.ts.map +1 -0
  92. package/dist/transport/utils/formdata.js +77 -0
  93. package/dist/transport/utils/formdata.js.map +1 -0
  94. package/dist/transport/utils/registry.d.ts +26 -0
  95. package/dist/transport/utils/registry.d.ts.map +1 -0
  96. package/dist/transport/utils/registry.js +51 -0
  97. package/dist/transport/utils/registry.js.map +1 -0
  98. package/dist/transport/worker-post.d.ts +44 -0
  99. package/dist/transport/worker-post.d.ts.map +1 -0
  100. package/dist/transport/worker-post.js +104 -0
  101. package/dist/transport/worker-post.js.map +1 -0
  102. package/dist/transport/worker.d.ts +10 -0
  103. package/dist/transport/worker.d.ts.map +1 -0
  104. package/dist/transport/worker.js +421 -0
  105. package/dist/transport/worker.js.map +1 -0
  106. package/dist/types.test-d.js +3 -9
  107. package/dist/types.test-d.js.map +1 -1
  108. package/eslint-isolation.mjs +82 -0
  109. 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":"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"}
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"types.test-d.js","sourceRoot":"","sources":["../src/types.test-d.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAKvD,uDAAuD;AACvD,KAAK,MAAM,CAAC,EAAE,EAAE,CAAA;AAEhB,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,CAAA;AAEF,oCAAoC;AACpC,KAAK,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAA;AAEtD,sDAAsD;AACtD,+DAA+D;AAC/D,KAAK,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;AAE7D,+CAA+C;AAC/C,iDAAiD;AACjD,KAAK,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAA;AAEpD,kCAAkC;AAClC,oDAAoD;AACpD,KAAK,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA"}
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.0",
4
- "description": "Contract-driven typed frontend client for Auth Craft. Methods are generated from @auth-craft/api-contract over the @auth-craft/transport (Web-Worker token isolation), so routes and client cannot drift.",
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
- "files": ["dist", "README.md"],
15
- "scripts": {
16
- "build": "tsc",
17
- "dev": "tsc --watch",
18
- "clean": "rm -rf dist",
19
- "typecheck": "tsc --noEmit",
20
- "test": "vitest run"
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
+ }