@lenne.tech/nuxt-extensions 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.d.mts CHANGED
@@ -3,7 +3,7 @@ import { LtExtensionsModuleOptions } from '../dist/runtime/types/index.js';
3
3
  export * from '../dist/runtime/types/index.js';
4
4
 
5
5
  declare const name = "@lenne.tech/nuxt-extensions";
6
- declare const version = "1.17.0";
6
+ declare const version = "1.18.0";
7
7
  declare const configKey = "ltExtensions";
8
8
  declare const DEFAULT_LT_AUTH_STATE_COOKIE = "lt-auth-state";
9
9
  declare const DEFAULT_LT_JWT_TOKEN_COOKIE = "lt-jwt-token";
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "configKey": "ltExtensions",
3
3
  "name": "@lenne.tech/nuxt-extensions",
4
- "version": "1.17.0",
4
+ "version": "1.18.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -2,7 +2,7 @@ import { defineNuxtModule, createResolver, tryResolveModule, addImports, addComp
2
2
  import { pathToFileURL } from 'node:url';
3
3
 
4
4
  const name = "@lenne.tech/nuxt-extensions";
5
- const version = "1.17.0";
5
+ const version = "1.18.0";
6
6
  const configKey = "ltExtensions";
7
7
  const DEFAULT_LT_AUTH_STATE_COOKIE = "lt-auth-state";
8
8
  const DEFAULT_LT_JWT_TOKEN_COOKIE = "lt-jwt-token";
@@ -61,7 +61,8 @@ export function useLtAuth() {
61
61
  const features = useState("lt-auth-features", () => ({}));
62
62
  const featuresFetched = useState("lt-auth-features-fetched", () => false);
63
63
  function setUser(userData, mode = "cookie") {
64
- const newState = { user: userData, authMode: mode };
64
+ const normalised = userData ? { ...userData, image: userData.image ?? void 0 } : null;
65
+ const newState = { user: normalised, authMode: mode };
65
66
  if (import.meta.client || userData) {
66
67
  authState.value = newState;
67
68
  }
@@ -612,91 +612,6 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
612
612
  * @see https://www.better-auth.com/docs/plugins/passkey
613
613
  */
614
614
  passkey: any;
615
- social: <FetchOptions extends import("better-auth").ClientFetchOption<Partial<{
616
- provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
617
- callbackURL?: string | undefined;
618
- newUserCallbackURL?: string | undefined;
619
- errorCallbackURL?: string | undefined;
620
- disableRedirect?: boolean | undefined;
621
- idToken?: {
622
- token: string;
623
- nonce?: string | undefined;
624
- accessToken?: string | undefined;
625
- refreshToken?: string | undefined;
626
- expiresAt?: number | undefined;
627
- user?: {
628
- name?: {
629
- firstName?: string | undefined;
630
- lastName?: string | undefined;
631
- } | undefined;
632
- email?: string | undefined;
633
- } | undefined;
634
- } | undefined;
635
- scopes?: string[] | undefined;
636
- requestSignUp?: boolean | undefined;
637
- loginHint?: string | undefined;
638
- additionalParams?: Record<string, string> | undefined;
639
- additionalData?: Record<string, any> | undefined;
640
- }> & Record<string, any>, Partial<Record<string, any>> & Record<string, any>, Record<string, string | undefined> | undefined>>(data_0: import("better-auth").Prettify<Omit<{
641
- provider: (string & {}) | "linear" | "huggingface" | "github" | "apple" | "atlassian" | "cognito" | "discord" | "facebook" | "figma" | "microsoft" | "google" | "slack" | "spotify" | "twitch" | "twitter" | "dropbox" | "kick" | "linkedin" | "gitlab" | "tiktok" | "reddit" | "roblox" | "salesforce" | "vk" | "zoom" | "notion" | "kakao" | "naver" | "line" | "paybin" | "paypal" | "polar" | "railway" | "vercel" | "wechat";
642
- callbackURL?: string | undefined;
643
- newUserCallbackURL?: string | undefined;
644
- errorCallbackURL?: string | undefined;
645
- disableRedirect?: boolean | undefined;
646
- idToken?: {
647
- token: string;
648
- nonce?: string | undefined;
649
- accessToken?: string | undefined;
650
- refreshToken?: string | undefined;
651
- expiresAt?: number | undefined;
652
- user?: {
653
- name?: {
654
- firstName?: string | undefined;
655
- lastName?: string | undefined;
656
- } | undefined;
657
- email?: string | undefined;
658
- } | undefined;
659
- } | undefined;
660
- scopes?: string[] | undefined;
661
- requestSignUp?: boolean | undefined;
662
- loginHint?: string | undefined;
663
- additionalParams?: Record<string, string> | undefined;
664
- additionalData?: Record<string, any> | undefined;
665
- } & {
666
- fetchOptions?: FetchOptions | undefined;
667
- }, "provider"> & {
668
- provider: string | (string & {});
669
- fetchOptions?: FetchOptions | undefined;
670
- }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
671
- redirect: boolean;
672
- url: string;
673
- } | (Omit<{
674
- redirect: boolean;
675
- token: string;
676
- url: undefined;
677
- user: {
678
- id: string;
679
- createdAt: Date;
680
- updatedAt: Date;
681
- email: string;
682
- emailVerified: boolean;
683
- name: string;
684
- image?: string | null | undefined | undefined;
685
- };
686
- }, "user"> & {
687
- user: import("better-auth").StripEmptyObjects<{
688
- id: string;
689
- createdAt: Date;
690
- updatedAt: Date;
691
- email: string;
692
- emailVerified: boolean;
693
- name: string;
694
- image?: string | null | undefined;
695
- }>;
696
- }), {
697
- code?: string | undefined;
698
- message?: string | undefined;
699
- }, FetchOptions["throw"] extends true ? true : false>>;
700
615
  };
701
616
  signOut: <FetchOptions extends import("better-auth").ClientFetchOption<Partial<{
702
617
  callbackURL?: string | undefined;
@@ -821,6 +736,33 @@ export declare function createLtAuthClient(config?: LtAuthClientConfig): {
821
736
  };
822
737
  }>;
823
738
  };
824
- twoFactor: any;
739
+ twoFactor: {
740
+ /**
741
+ * Disable 2FA (password is hashed before sending)
742
+ */
743
+ disable: <T extends {
744
+ password: string;
745
+ }>(params: T, options?: any) => Promise<any>;
746
+ /**
747
+ * Enable 2FA (password is hashed before sending)
748
+ */
749
+ enable: <T extends {
750
+ password: string;
751
+ }>(params: T, options?: any) => Promise<any>;
752
+ /**
753
+ * Generate backup codes (password is hashed before sending)
754
+ */
755
+ generateBackupCodes: <T extends {
756
+ password: string;
757
+ }>(params: T, options?: any) => Promise<any>;
758
+ /**
759
+ * Verify TOTP code (pass through to base client)
760
+ */
761
+ verifyTotp: any;
762
+ /**
763
+ * Verify backup code (pass through to base client)
764
+ */
765
+ verifyBackupCode: any;
766
+ };
825
767
  };
826
768
  export type LtAuthClient = ReturnType<typeof createLtAuthClient>;
@@ -169,9 +169,14 @@ export function createLtAuthClient(config = {}) {
169
169
  }
170
170
  return baseClient.resetPassword({ ...params, newPassword: hashedPassword }, options);
171
171
  },
172
- // Override signIn to hash password (keep passkey method from plugin)
172
+ // Override signIn to hash password (keep passkey method from plugin).
173
+ //
174
+ // No `...baseClient.signIn` here, for the reason given at the top of this object: the
175
+ // sub-objects are proxies too. `Object.keys(baseClient.signIn)` is `[]`, so the spread
176
+ // copied nothing while the type declared everything — `signIn.social` type-checked and
177
+ // was `undefined` when called. 1.17.0 removed the top-level spread and left these three,
178
+ // which is how the same defect survived its own fix.
173
179
  signIn: {
174
- ...baseClient.signIn,
175
180
  /**
176
181
  * Sign in with email and password (password is hashed before sending)
177
182
  */
@@ -187,9 +192,8 @@ export function createLtAuthClient(config = {}) {
187
192
  },
188
193
  // Explicitly pass through signOut (not captured by spread operator)
189
194
  signOut: baseClient.signOut,
190
- // Override signUp to hash password
195
+ // Override signUp to hash password. No spread — see `signIn` above.
191
196
  signUp: {
192
- ...baseClient.signUp,
193
197
  /**
194
198
  * Sign up with email and password (password is hashed before sending)
195
199
  */
@@ -199,8 +203,12 @@ export function createLtAuthClient(config = {}) {
199
203
  }
200
204
  },
201
205
  // Override twoFactor to hash passwords (provided by twoFactorClient plugin)
206
+ // No spread — see `signIn` above. This is the sub-object where it mattered most:
207
+ // `getTotpUri`, `sendOtp` and `verifyOtp` were declared by the type and `undefined` at
208
+ // runtime, and `getTotpUri` is what a project reaches for to render the TOTP QR code.
209
+ // They are not added here because none has a caller yet; each listed method is a promise
210
+ // this package then keeps across versions. Ask, and it gets a line.
202
211
  twoFactor: {
203
- ...baseClient.twoFactor,
204
212
  /**
205
213
  * Disable 2FA (password is hashed before sending)
206
214
  */
@@ -10,6 +10,10 @@ export interface LtUser {
10
10
  email: string;
11
11
  emailVerified?: boolean;
12
12
  id: string;
13
+ /**
14
+ * Stored as `string | undefined`, never `null` — see {@link LtUserInput}, which is what
15
+ * `setUser` accepts. Reading code therefore has one empty case to handle, not two.
16
+ */
13
17
  image?: string;
14
18
  name?: string;
15
19
  /** Single-role shape (Better-Auth admin plugin). See also {@link LtUser.roles}. */
@@ -30,6 +34,24 @@ export interface LtUser {
30
34
  roles?: string[];
31
35
  twoFactorEnabled?: boolean;
32
36
  }
37
+ /**
38
+ * What {@link UseLtAuthReturn.setUser} accepts: an {@link LtUser} whose `image` may also be
39
+ * `null`.
40
+ *
41
+ * Better Auth's session user declares `image?: string | null | undefined`
42
+ * (`@better-auth/core`), so handing `getSession().data.user` straight to `setUser` did not
43
+ * type-check — the two sides mean the same thing by "no picture" and write it differently.
44
+ * Every consumer combining them wrote the same normalising line, and this package's own call
45
+ * sites hid it behind `as LtUser`, which is why it went unnoticed until 1.17.0 exposed
46
+ * `getSession()` and gave that path a real type.
47
+ *
48
+ * `setUser` normalises `null` to `undefined` on the way in, so the stored user and every
49
+ * reader keep the single empty case. Widening `LtUser.image` itself would have done the
50
+ * opposite: pushed a second empty value onto everyone who only READS it.
51
+ */
52
+ export type LtUserInput = Omit<LtUser, 'image'> & {
53
+ image?: null | string;
54
+ };
33
55
  /**
34
56
  * Authentication mode for Cookie/JWT dual-mode authentication
35
57
  * - 'cookie': Primary mode using HttpOnly session cookies (more secure)
@@ -251,7 +273,14 @@ export interface UseLtAuthReturn {
251
273
  newPassword: string;
252
274
  token: string;
253
275
  }>(params: NoStrayCredential<T, 'newPassword'>, options?: unknown) => Promise<unknown>;
254
- setUser: (userData: LtUser | null, mode?: LtAuthMode) => void;
276
+ /**
277
+ * Store the authenticated user.
278
+ *
279
+ * Accepts {@link LtUserInput}, so `getSession().data.user` can be handed over unchanged —
280
+ * Better Auth writes "no picture" as `image: null`, which this normalises to `undefined`
281
+ * before storing. Readers of {@link LtUser} keep a single empty case.
282
+ */
283
+ setUser: (userData: LtUserInput | null, mode?: LtAuthMode) => void;
255
284
  signIn: {
256
285
  email: <T extends {
257
286
  email: string;
@@ -1,4 +1,4 @@
1
- export type { LtAuthClientConfig, LtAuthMode, LtAuthResponse, LtAuthState, LtPasskeyAuthResult, LtPasskeyRegisterResult, LtUser, UseLtAuthReturn } from './auth.js';
1
+ export type { LtAuthClientConfig, LtAuthMode, LtAuthResponse, LtAuthState, LtPasskeyAuthResult, LtPasskeyRegisterResult, LtUser, LtUserInput, UseLtAuthReturn } from './auth.js';
2
2
  export type { LtFileInfo, LtUploadItem, LtUploadOptions, LtUploadProgress, LtUploadStatus, UseLtFileReturn, UseLtTusUploadReturn } from './upload.js';
3
3
  export type { LtAiModuleOptions, LtAuthCookieNamesOptions, LtAuthModuleOptions, LtErrorTranslationModuleOptions, LtExtensionsModuleOptions, LtExtensionsPublicRuntimeConfig, LtFormLabelAssociationOptions, LtI18nModuleOptions, LtPreHydrationInputOptions, LtSystemSetupModuleOptions, LtTusModuleOptions, } from './module.js';
4
4
  export type { LtErrorTranslationResponse, LtParsedError, UseLtErrorTranslationReturn } from './error.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nuxt-extensions",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "Reusable Nuxt 4 composables, components, and Better-Auth integration for lenne.tech projects",
5
5
  "repository": {
6
6
  "type": "git",