@webtwizz/cloud 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @webtwizz/cloud
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 038e061: Visitors only see WebTwizz names: session cookies are `__Secure-webtwizz-auth.*`, the sign-in route drops the sign-in service's own response headers, sign-in log lines say `[webtwizz-auth]`, and uploads go through the site's files address like every other file link. Visitors signed in on 0.1.0 sign in again once.
8
+
3
9
  ## 0.1.0
4
10
 
5
11
  - Sign-ins (`createAuth`, `createAuthClient`), plain words for every sign-in error (`authMessage`), a pooler-safe database client (`createDb`) and file uploads and links (`createFiles`).
package/README.md CHANGED
@@ -48,6 +48,8 @@ npm run build
48
48
 
49
49
  Sites pin an exact version, so a release never changes a live site until WebTwizz upgrades it.
50
50
 
51
+ The WebTwizz AI builds from its own copy of AI_GUIDE.md. After a release, run `npm run cloud:sync <version>` in the ai-service so new sites get that version and its guide.
52
+
51
53
  ## License
52
54
 
53
55
  MIT
@@ -0,0 +1,376 @@
1
+ // node_modules/@neondatabase/auth/dist/better-auth-helpers-DlzEQzcv.mjs
2
+ import { AuthApiError, AuthError, isAuthApiError, isAuthError } from "@supabase/auth-js";
3
+ var SESSION_CACHE_TTL_MS = 6e4;
4
+ var CLOCK_SKEW_BUFFER_MS = 1e4;
5
+ var NEON_AUTH_SESSION_VERIFIER_PARAM_NAME = "neon_auth_session_verifier";
6
+ var NEON_AUTH_POPUP_PARAM_NAME = "neon_popup";
7
+ var NEON_AUTH_POPUP_CALLBACK_PARAM_NAME = "neon_popup_callback";
8
+ var NEON_AUTH_POPUP_CALLBACK_ROUTE = "/auth/callback";
9
+ var OAUTH_POPUP_MESSAGE_TYPE = "neon-auth:oauth-complete";
10
+ var AuthErrorCode = {
11
+ BadJwt: "bad_jwt",
12
+ InvalidCredentials: "invalid_credentials",
13
+ SessionExpired: "session_expired",
14
+ SessionNotFound: "session_not_found",
15
+ InvalidGrant: "invalid_grant",
16
+ UserNotFound: "user_not_found",
17
+ UserAlreadyExists: "user_already_exists",
18
+ EmailExists: "email_exists",
19
+ PhoneExists: "phone_exists",
20
+ EmailNotConfirmed: "email_not_confirmed",
21
+ PhoneNotConfirmed: "phone_not_confirmed",
22
+ ValidationFailed: "validation_failed",
23
+ BadJson: "bad_json",
24
+ WeakPassword: "weak_password",
25
+ EmailAddressInvalid: "email_address_invalid",
26
+ FeatureNotSupported: "feature_not_supported",
27
+ NotImplemented: "not_implemented",
28
+ OAuthProviderNotSupported: "oauth_provider_not_supported",
29
+ PhoneProviderDisabled: "phone_provider_disabled",
30
+ MagicLinkNotSupported: "magic_link_not_supported",
31
+ SsoProviderDisabled: "sso_provider_disabled",
32
+ AnonymousProviderDisabled: "anonymous_provider_disabled",
33
+ Web3ProviderDisabled: "web3_provider_disabled",
34
+ BadOAuthCallback: "bad_oauth_callback",
35
+ OAuthCallbackFailed: "oauth_callback_failed",
36
+ OverRequestRateLimit: "over_request_rate_limit",
37
+ OverEmailSendRateLimit: "over_email_send_rate_limit",
38
+ OverSmsSendRateLimit: "over_sms_send_rate_limit",
39
+ UnexpectedFailure: "unexpected_failure",
40
+ InternalError: "internal_error",
41
+ IdentityNotFound: "identity_not_found",
42
+ UnknownError: "unknown_error"
43
+ };
44
+ var ERROR_DEFINITIONS = {
45
+ [AuthErrorCode.BadJwt]: {
46
+ code: AuthErrorCode.BadJwt,
47
+ status: 401,
48
+ message: "Invalid or expired session token",
49
+ description: "The JWT token is malformed, expired, or has an invalid signature"
50
+ },
51
+ [AuthErrorCode.InvalidCredentials]: {
52
+ code: AuthErrorCode.InvalidCredentials,
53
+ status: 401,
54
+ message: "Invalid email or password",
55
+ description: "The provided credentials do not match any user account"
56
+ },
57
+ [AuthErrorCode.SessionExpired]: {
58
+ code: AuthErrorCode.SessionExpired,
59
+ status: 401,
60
+ message: "Session has expired",
61
+ description: "The user session has exceeded its timeout period"
62
+ },
63
+ [AuthErrorCode.SessionNotFound]: {
64
+ code: AuthErrorCode.SessionNotFound,
65
+ status: 401,
66
+ message: "No active session found",
67
+ description: "The user does not have an active session or the session was invalidated"
68
+ },
69
+ [AuthErrorCode.InvalidGrant]: {
70
+ code: AuthErrorCode.InvalidGrant,
71
+ status: 401,
72
+ message: "Invalid authorization grant",
73
+ description: "OAuth/OIDC grant validation failed"
74
+ },
75
+ [AuthErrorCode.UserNotFound]: {
76
+ code: AuthErrorCode.UserNotFound,
77
+ status: 404,
78
+ message: "User not found",
79
+ description: "No user exists with the provided identifier"
80
+ },
81
+ [AuthErrorCode.UserAlreadyExists]: {
82
+ code: AuthErrorCode.UserAlreadyExists,
83
+ status: 409,
84
+ message: "User already exists",
85
+ description: "A user with this email or phone number is already registered"
86
+ },
87
+ [AuthErrorCode.EmailExists]: {
88
+ code: AuthErrorCode.EmailExists,
89
+ status: 409,
90
+ message: "Email address already registered",
91
+ description: "This email address is already associated with an account"
92
+ },
93
+ [AuthErrorCode.PhoneExists]: {
94
+ code: AuthErrorCode.PhoneExists,
95
+ status: 409,
96
+ message: "Phone number already registered",
97
+ description: "This phone number is already associated with an account"
98
+ },
99
+ [AuthErrorCode.EmailNotConfirmed]: {
100
+ code: AuthErrorCode.EmailNotConfirmed,
101
+ status: 422,
102
+ message: "Email verification required",
103
+ description: "The user must verify their email before signing in"
104
+ },
105
+ [AuthErrorCode.PhoneNotConfirmed]: {
106
+ code: AuthErrorCode.PhoneNotConfirmed,
107
+ status: 422,
108
+ message: "Phone verification required",
109
+ description: "The user must verify their phone number before signing in"
110
+ },
111
+ [AuthErrorCode.ValidationFailed]: {
112
+ code: AuthErrorCode.ValidationFailed,
113
+ status: 400,
114
+ message: "Invalid request parameters",
115
+ description: "One or more request parameters are invalid or missing"
116
+ },
117
+ [AuthErrorCode.BadJson]: {
118
+ code: AuthErrorCode.BadJson,
119
+ status: 400,
120
+ message: "Invalid JSON in request body",
121
+ description: "The request body contains malformed JSON"
122
+ },
123
+ [AuthErrorCode.WeakPassword]: {
124
+ code: AuthErrorCode.WeakPassword,
125
+ status: 400,
126
+ message: "Password does not meet security requirements",
127
+ description: "The password is too weak or does not meet complexity requirements"
128
+ },
129
+ [AuthErrorCode.EmailAddressInvalid]: {
130
+ code: AuthErrorCode.EmailAddressInvalid,
131
+ status: 400,
132
+ message: "Invalid email address format",
133
+ description: "The provided email address is not in a valid format"
134
+ },
135
+ [AuthErrorCode.FeatureNotSupported]: {
136
+ code: AuthErrorCode.FeatureNotSupported,
137
+ status: 403,
138
+ message: "Feature not available",
139
+ description: "This feature is not supported in the current configuration"
140
+ },
141
+ [AuthErrorCode.NotImplemented]: {
142
+ code: AuthErrorCode.NotImplemented,
143
+ status: 501,
144
+ message: "Feature not implemented",
145
+ description: "This feature has not been implemented yet"
146
+ },
147
+ [AuthErrorCode.OAuthProviderNotSupported]: {
148
+ code: AuthErrorCode.OAuthProviderNotSupported,
149
+ status: 403,
150
+ message: "OAuth provider not supported",
151
+ description: "The requested OAuth provider is not enabled"
152
+ },
153
+ [AuthErrorCode.PhoneProviderDisabled]: {
154
+ code: AuthErrorCode.PhoneProviderDisabled,
155
+ status: 403,
156
+ message: "Phone authentication not available",
157
+ description: "Phone number authentication is not enabled"
158
+ },
159
+ [AuthErrorCode.MagicLinkNotSupported]: {
160
+ code: AuthErrorCode.MagicLinkNotSupported,
161
+ status: 403,
162
+ message: "Magic link authentication not available",
163
+ description: "Magic link authentication is not supported"
164
+ },
165
+ [AuthErrorCode.SsoProviderDisabled]: {
166
+ code: AuthErrorCode.SsoProviderDisabled,
167
+ status: 403,
168
+ message: "SSO not supported",
169
+ description: "Enterprise SSO authentication is not available"
170
+ },
171
+ [AuthErrorCode.AnonymousProviderDisabled]: {
172
+ code: AuthErrorCode.AnonymousProviderDisabled,
173
+ status: 403,
174
+ message: "Anonymous authentication not available",
175
+ description: "Anonymous sign-in is not enabled"
176
+ },
177
+ [AuthErrorCode.Web3ProviderDisabled]: {
178
+ code: AuthErrorCode.Web3ProviderDisabled,
179
+ status: 403,
180
+ message: "Web3 authentication not supported",
181
+ description: "Web3/blockchain authentication is not available"
182
+ },
183
+ [AuthErrorCode.BadOAuthCallback]: {
184
+ code: AuthErrorCode.BadOAuthCallback,
185
+ status: 400,
186
+ message: "Invalid OAuth callback",
187
+ description: "The OAuth callback request is missing required parameters"
188
+ },
189
+ [AuthErrorCode.OAuthCallbackFailed]: {
190
+ code: AuthErrorCode.OAuthCallbackFailed,
191
+ status: 500,
192
+ message: "OAuth authentication failed",
193
+ description: "The OAuth callback completed but no session was created"
194
+ },
195
+ [AuthErrorCode.OverRequestRateLimit]: {
196
+ code: AuthErrorCode.OverRequestRateLimit,
197
+ status: 429,
198
+ message: "Too many requests",
199
+ description: "Rate limit exceeded. Please try again later"
200
+ },
201
+ [AuthErrorCode.OverEmailSendRateLimit]: {
202
+ code: AuthErrorCode.OverEmailSendRateLimit,
203
+ status: 429,
204
+ message: "Too many email requests",
205
+ description: "Too many emails sent. Please wait before trying again"
206
+ },
207
+ [AuthErrorCode.OverSmsSendRateLimit]: {
208
+ code: AuthErrorCode.OverSmsSendRateLimit,
209
+ status: 429,
210
+ message: "Too many SMS requests",
211
+ description: "Too many SMS messages sent. Please wait before trying again"
212
+ },
213
+ [AuthErrorCode.UnexpectedFailure]: {
214
+ code: AuthErrorCode.UnexpectedFailure,
215
+ status: 500,
216
+ message: "An unexpected error occurred",
217
+ description: "The server encountered an unexpected condition"
218
+ },
219
+ [AuthErrorCode.InternalError]: {
220
+ code: AuthErrorCode.InternalError,
221
+ status: 500,
222
+ message: "Internal server error",
223
+ description: "An internal error occurred while processing the request"
224
+ },
225
+ [AuthErrorCode.IdentityNotFound]: {
226
+ code: AuthErrorCode.IdentityNotFound,
227
+ status: 404,
228
+ message: "Identity not found",
229
+ description: "The requested user identity does not exist"
230
+ },
231
+ [AuthErrorCode.UnknownError]: {
232
+ code: AuthErrorCode.UnknownError,
233
+ status: 500,
234
+ message: "An unknown error occurred",
235
+ description: "The error could not be categorized"
236
+ }
237
+ };
238
+ function getErrorDefinition(code) {
239
+ return ERROR_DEFINITIONS[code];
240
+ }
241
+ var BETTER_AUTH_ERROR_MAP = {
242
+ "INVALID_EMAIL_OR_PASSWORD": AuthErrorCode.InvalidCredentials,
243
+ "INVALID_PASSWORD": AuthErrorCode.InvalidCredentials,
244
+ "INVALID_EMAIL": AuthErrorCode.EmailAddressInvalid,
245
+ "USER_NOT_FOUND": AuthErrorCode.UserNotFound,
246
+ "INVALID_TOKEN": AuthErrorCode.BadJwt,
247
+ "SESSION_EXPIRED": AuthErrorCode.SessionExpired,
248
+ "FAILED_TO_GET_SESSION": AuthErrorCode.SessionNotFound,
249
+ "USER_ALREADY_EXISTS": AuthErrorCode.UserAlreadyExists,
250
+ "EMAIL_NOT_VERIFIED": AuthErrorCode.EmailNotConfirmed,
251
+ "USER_EMAIL_NOT_FOUND": AuthErrorCode.UserNotFound,
252
+ "PASSWORD_TOO_SHORT": AuthErrorCode.WeakPassword,
253
+ "PASSWORD_TOO_LONG": AuthErrorCode.WeakPassword,
254
+ "USER_ALREADY_HAS_PASSWORD": AuthErrorCode.ValidationFailed,
255
+ "CREDENTIAL_ACCOUNT_NOT_FOUND": AuthErrorCode.IdentityNotFound,
256
+ "FAILED_TO_UNLINK_LAST_ACCOUNT": AuthErrorCode.ValidationFailed,
257
+ "ACCOUNT_NOT_FOUND": AuthErrorCode.IdentityNotFound,
258
+ "SOCIAL_ACCOUNT_ALREADY_LINKED": AuthErrorCode.ValidationFailed,
259
+ "PROVIDER_NOT_FOUND": AuthErrorCode.OAuthProviderNotSupported,
260
+ "ID_TOKEN_NOT_SUPPORTED": AuthErrorCode.FeatureNotSupported,
261
+ "FAILED_TO_CREATE_USER": AuthErrorCode.InternalError,
262
+ "FAILED_TO_CREATE_SESSION": AuthErrorCode.InternalError,
263
+ "FAILED_TO_UPDATE_USER": AuthErrorCode.InternalError,
264
+ "EMAIL_CAN_NOT_BE_UPDATED": AuthErrorCode.FeatureNotSupported
265
+ };
266
+ var STATUS_CODE_ERROR_MAP = {
267
+ 400: AuthErrorCode.ValidationFailed,
268
+ 401: AuthErrorCode.BadJwt,
269
+ 403: AuthErrorCode.FeatureNotSupported,
270
+ 404: AuthErrorCode.UserNotFound,
271
+ 409: AuthErrorCode.UserAlreadyExists,
272
+ 422: AuthErrorCode.ValidationFailed,
273
+ 429: AuthErrorCode.OverRequestRateLimit,
274
+ 500: AuthErrorCode.UnexpectedFailure,
275
+ 501: AuthErrorCode.NotImplemented,
276
+ 503: AuthErrorCode.FeatureNotSupported
277
+ };
278
+ function normalizeBetterAuthError(error) {
279
+ if (error !== null && error !== void 0 && typeof error === "object" && "status" in error && "statusText" in error) {
280
+ const betterError = error;
281
+ const status = betterError.status;
282
+ if ("code" in betterError && betterError.code && typeof betterError.code === "string") {
283
+ const mappedCode = BETTER_AUTH_ERROR_MAP[betterError.code];
284
+ if (mappedCode) {
285
+ const def$2 = getErrorDefinition(mappedCode);
286
+ return createNormalizedError(def$2.message, def$2.status, def$2.code, status);
287
+ }
288
+ }
289
+ const def$1 = getErrorDefinition(mapStatusCodeToErrorCode(status, betterError.message || betterError.statusText));
290
+ return createNormalizedError(betterError.message || def$1.message, status, def$1.code, status);
291
+ }
292
+ if (error instanceof Error) {
293
+ const def$1 = getErrorDefinition(mapMessageToErrorCode(error.message));
294
+ return createNormalizedError(error.message || def$1.message, def$1.status, def$1.code, def$1.status);
295
+ }
296
+ const def = getErrorDefinition(AuthErrorCode.UnknownError);
297
+ return new AuthError(def.message, def.status, def.code);
298
+ }
299
+ function mapStatusCodeToErrorCode(status, message) {
300
+ const lowerMessage = message?.toLowerCase() || "";
301
+ switch (status) {
302
+ case 401:
303
+ if (lowerMessage.includes("token") || lowerMessage.includes("jwt")) return AuthErrorCode.BadJwt;
304
+ if (lowerMessage.includes("session")) return AuthErrorCode.SessionNotFound;
305
+ if (lowerMessage.includes("expired")) return AuthErrorCode.SessionExpired;
306
+ return AuthErrorCode.InvalidCredentials;
307
+ case 404:
308
+ if (lowerMessage.includes("identity") || lowerMessage.includes("account")) return AuthErrorCode.IdentityNotFound;
309
+ if (lowerMessage.includes("session")) return AuthErrorCode.SessionNotFound;
310
+ return AuthErrorCode.UserNotFound;
311
+ case 409:
312
+ if (lowerMessage.includes("email")) return AuthErrorCode.EmailExists;
313
+ if (lowerMessage.includes("phone")) return AuthErrorCode.PhoneExists;
314
+ return AuthErrorCode.UserAlreadyExists;
315
+ case 422:
316
+ if (lowerMessage.includes("email") && lowerMessage.includes("confirm")) return AuthErrorCode.EmailNotConfirmed;
317
+ if (lowerMessage.includes("phone") && lowerMessage.includes("confirm")) return AuthErrorCode.PhoneNotConfirmed;
318
+ return AuthErrorCode.ValidationFailed;
319
+ case 429:
320
+ if (lowerMessage.includes("email")) return AuthErrorCode.OverEmailSendRateLimit;
321
+ if (lowerMessage.includes("sms") || lowerMessage.includes("phone")) return AuthErrorCode.OverSmsSendRateLimit;
322
+ return AuthErrorCode.OverRequestRateLimit;
323
+ case 400:
324
+ if (lowerMessage.includes("password") && lowerMessage.includes("weak")) return AuthErrorCode.WeakPassword;
325
+ if (lowerMessage.includes("email") && lowerMessage.includes("invalid")) return AuthErrorCode.EmailAddressInvalid;
326
+ if (lowerMessage.includes("json")) return AuthErrorCode.BadJson;
327
+ if (lowerMessage.includes("oauth") || lowerMessage.includes("callback")) return AuthErrorCode.BadOAuthCallback;
328
+ return AuthErrorCode.ValidationFailed;
329
+ case 403:
330
+ if (lowerMessage.includes("provider") || lowerMessage.includes("oauth")) return AuthErrorCode.OAuthProviderNotSupported;
331
+ if (lowerMessage.includes("phone")) return AuthErrorCode.PhoneProviderDisabled;
332
+ if (lowerMessage.includes("sso")) return AuthErrorCode.SsoProviderDisabled;
333
+ return AuthErrorCode.FeatureNotSupported;
334
+ case 501:
335
+ return AuthErrorCode.NotImplemented;
336
+ case 503:
337
+ return AuthErrorCode.FeatureNotSupported;
338
+ default:
339
+ if (lowerMessage.includes("oauth")) return AuthErrorCode.OAuthCallbackFailed;
340
+ return AuthErrorCode.UnexpectedFailure;
341
+ }
342
+ }
343
+ function mapMessageToErrorCode(message) {
344
+ const lower = message.toLowerCase();
345
+ if (lower.includes("invalid login") || lower.includes("incorrect") || lower.includes("wrong password")) return AuthErrorCode.InvalidCredentials;
346
+ if (lower.includes("token") && (lower.includes("invalid") || lower.includes("expired"))) return AuthErrorCode.BadJwt;
347
+ if (lower.includes("session") && lower.includes("expired")) return AuthErrorCode.SessionExpired;
348
+ if (lower.includes("session") && lower.includes("not found")) return AuthErrorCode.SessionNotFound;
349
+ if (lower.includes("already exists") || lower.includes("already registered")) return AuthErrorCode.UserAlreadyExists;
350
+ if (lower.includes("not found") && lower.includes("user")) return AuthErrorCode.UserNotFound;
351
+ if (lower.includes("not found") && lower.includes("identity")) return AuthErrorCode.IdentityNotFound;
352
+ if (lower.includes("email") && lower.includes("not confirmed")) return AuthErrorCode.EmailNotConfirmed;
353
+ if (lower.includes("phone") && lower.includes("not confirmed")) return AuthErrorCode.PhoneNotConfirmed;
354
+ if (lower.includes("weak password") || lower.includes("password") && lower.includes("requirements")) return AuthErrorCode.WeakPassword;
355
+ if (lower.includes("email") && lower.includes("invalid")) return AuthErrorCode.EmailAddressInvalid;
356
+ if (lower.includes("rate limit") || lower.includes("too many requests")) return AuthErrorCode.OverRequestRateLimit;
357
+ if (lower.includes("oauth") && lower.includes("failed")) return AuthErrorCode.OAuthCallbackFailed;
358
+ if (lower.includes("provider") && lower.includes("not supported")) return AuthErrorCode.OAuthProviderNotSupported;
359
+ return AuthErrorCode.UnexpectedFailure;
360
+ }
361
+ function createNormalizedError(message, targetStatus, code, _originalStatus) {
362
+ const status = targetStatus;
363
+ if (status !== 500 && status !== 501 && status !== 503) return new AuthApiError(message, status, code);
364
+ return new AuthError(message, status, code);
365
+ }
366
+
367
+ export {
368
+ SESSION_CACHE_TTL_MS,
369
+ CLOCK_SKEW_BUFFER_MS,
370
+ NEON_AUTH_SESSION_VERIFIER_PARAM_NAME,
371
+ NEON_AUTH_POPUP_PARAM_NAME,
372
+ NEON_AUTH_POPUP_CALLBACK_PARAM_NAME,
373
+ NEON_AUTH_POPUP_CALLBACK_ROUTE,
374
+ OAUTH_POPUP_MESSAGE_TYPE,
375
+ normalizeBetterAuthError
376
+ };