@devcoffee/nuxt-core 1.2.5 → 1.3.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,22 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.3.0
4
+
5
+ [compare changes](https://github.com/coolkg1412/devcoffee-nuxt-core/compare/v1.2.5...v1.3.0)
6
+
7
+ ### 🚀 Enhancements
8
+
9
+ - Enhance locale and timezone handling with session support in formatters plugin ([c36f621](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/c36f621))
10
+
11
+ ### 🩹 Fixes
12
+
13
+ - Harden useAuthContext composable and logging infrastructure ([2a89ebf](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/2a89ebf))
14
+ - Correct sessionCookieId reference in validateSession call in authts.ts tests ([2c8b343](https://github.com/coolkg1412/devcoffee-nuxt-core/commit/2c8b343))
15
+
16
+ ### ❤️ Contributors
17
+
18
+ - Hieu Nguyen <hieu.nguyen@devcoffee.tech>
19
+
3
20
  ## v1.2.5
4
21
 
5
22
  [compare changes](https://github.com/coolkg1412/devcoffee-nuxt-core/compare/v1.2.4...v1.2.5)
package/dist/module.d.mts CHANGED
@@ -264,6 +264,9 @@ type LoggingModuleOptions = {
264
264
  server: LoggingOptions
265
265
  ssr: LoggingOptions
266
266
  client: LoggingOptions
267
+ loggers?: {
268
+ [key: string]: Omit<LoggingOptions, 'tag'>
269
+ }
267
270
  }
268
271
 
269
272
  type ModuleOptions = {
@@ -276,7 +279,7 @@ type ModuleOptions = {
276
279
  }
277
280
 
278
281
  type ModulePublicRuntimeConfig = Pick<ModuleOptions, 'defaultLocale' | 'defaultTimeZone' | 'defaultLanguage'> & {
279
- logging: ModuleOptions['logging']['client']
282
+ logging: ModuleOptions['logging']['client'] & { loggers: ModuleOptions['logging']['loggers'] }
280
283
 
281
284
  authts: Pick<
282
285
  AuthtsModuleOptions['auth'],
package/dist/module.d.ts CHANGED
@@ -264,6 +264,9 @@ type LoggingModuleOptions = {
264
264
  server: LoggingOptions
265
265
  ssr: LoggingOptions
266
266
  client: LoggingOptions
267
+ loggers?: {
268
+ [key: string]: Omit<LoggingOptions, 'tag'>
269
+ }
267
270
  }
268
271
 
269
272
  type ModuleOptions = {
@@ -276,7 +279,7 @@ type ModuleOptions = {
276
279
  }
277
280
 
278
281
  type ModulePublicRuntimeConfig = Pick<ModuleOptions, 'defaultLocale' | 'defaultTimeZone' | 'defaultLanguage'> & {
279
- logging: ModuleOptions['logging']['client']
282
+ logging: ModuleOptions['logging']['client'] & { loggers: ModuleOptions['logging']['loggers'] }
280
283
 
281
284
  authts: Pick<
282
285
  AuthtsModuleOptions['auth'],
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-core",
3
- "version": "1.2.5",
3
+ "version": "1.3.0",
4
4
  "configKey": "nuxtCore",
5
5
  "compatibility": {
6
6
  "nuxt": "^4.0.0"
package/dist/module.mjs CHANGED
@@ -2,7 +2,7 @@ import { addCustomTab } from '@nuxt/devtools-kit';
2
2
  import { defineNuxtModule, useLogger, createResolver, addTemplate, addServerImports, addServerImportsDir, addServerPlugin, addImportsDir, addPlugin, addRouteMiddleware, addServerHandler } from '@nuxt/kit';
3
3
  import { deepMerge, pick } from '../dist/runtime/utils.js';
4
4
 
5
- const version = "1.2.5";
5
+ const version = "1.3.0";
6
6
 
7
7
  const defaultLocale = "vi-VN";
8
8
  const defaultLanguage = "vi";
@@ -95,7 +95,7 @@ function normalizePublicRuntimeConfig(inputOpts) {
95
95
  const { redirectUri } = inputOpts.authts.openid;
96
96
  const { redirectUrl: redirectCookie, sessionId: sessionCookie } = inputOpts.authts.sessions.names;
97
97
  return {
98
- logging: { ...inputOpts.logging.client },
98
+ logging: { ...inputOpts.logging.client, loggers: inputOpts.logging.loggers },
99
99
  authts: {
100
100
  enabled,
101
101
  loginUri,
@@ -1,3 +1,6 @@
1
+ import type { AuthorizedUser } from '@devcoffee/nuxt-core';
2
+ import { type NuxtSessionContext } from '#app';
3
+ import { type ComputedRef, type Ref } from '#imports';
1
4
  /**
2
5
  * 🧩 Provides reactive authentication state and actions for user login and authorization.
3
6
  *
@@ -16,10 +19,10 @@
16
19
  * @since 1.0.0
17
20
  */
18
21
  export declare function useAuthContext(initiator?: string): {
19
- user: any;
20
- session: any;
21
- processing: any;
22
- isAuthenticated: any;
22
+ user: ComputedRef<AuthorizedUser>;
23
+ session: ComputedRef<NuxtSessionContext>;
24
+ processing: Ref<boolean>;
25
+ isAuthenticated: ComputedRef<boolean>;
23
26
  login: (redirectTo?: string) => Promise<void>;
24
27
  authorize: (parameters: URLSearchParams) => Promise<void>;
25
28
  logout: () => Promise<void>;
@@ -14,7 +14,7 @@ export function useAuthContext(initiator) {
14
14
  const { callHook, runWithContext } = useNuxtApp();
15
15
  const { getValue } = useSessionContext();
16
16
  const fetchRequest = useRequestFetch();
17
- const logger = useLogger({ level: 2, tag: "authContext" });
17
+ const logger = useLogger({ tag: "auth.context" });
18
18
  const processing = ref(false);
19
19
  const session = computed(() => getValue(initiator, "useAuthContext.session"));
20
20
  const isAuthenticated = computed(() => {
@@ -52,7 +52,7 @@ function getRedirectCookie(name) {
52
52
  export default defineNuxtRouteMiddleware(async (to) => {
53
53
  const nuxtApp = useNuxtApp();
54
54
  await nuxtApp.$sessionReady;
55
- const logger = useLogger({ tag: "authts.middleware", level: 3 });
55
+ const logger = useLogger({ tag: "authts.middleware" });
56
56
  const {
57
57
  loginUri,
58
58
  defaultLoginRedirectUri,
@@ -1,11 +1,20 @@
1
- import { defineNuxtPlugin, useRuntimeConfig } from "#app";
2
- import { ref, useLogger } from "#imports";
1
+ import { defineNuxtPlugin, useRequestEvent, useRuntimeConfig, useState } from "#app";
2
+ import { useLogger } from "#imports";
3
3
  export default defineNuxtPlugin((_nuxtApp) => {
4
- const logger = useLogger({ tag: "formatters", level: 3 });
4
+ const logger = useLogger({ tag: "formatters" });
5
5
  const { defaultLocale, defaultLanguage, defaultTimeZone } = useRuntimeConfig().public.nuxtCore;
6
- const currentLocale = ref(defaultLocale);
7
- const currentLanguage = ref(defaultLanguage);
8
- const currentTimeZone = ref(defaultTimeZone);
6
+ const currentLocale = useState("devcoffee.formatters.locale", () => defaultLocale);
7
+ const currentLanguage = useState("devcoffee.formatters.language", () => defaultLanguage);
8
+ const currentTimeZone = useState("devcoffee.formatters.timeZone", () => defaultTimeZone);
9
+ if (import.meta.server) {
10
+ const event = useRequestEvent();
11
+ const session = event?.context?.session ?? null;
12
+ if (session?.user) {
13
+ if (session.user.locale) currentLocale.value = session.user.locale;
14
+ if (session.user.language) currentLanguage.value = session.user.language;
15
+ if (session.user.timezone) currentTimeZone.value = session.user.timezone;
16
+ }
17
+ }
9
18
  _nuxtApp.hooks.addHooks({
10
19
  "dfLocale:changed": (value) => {
11
20
  const { locale = defaultLocale, timeZone = defaultTimeZone, language = defaultLanguage } = value;
@@ -1,7 +1,7 @@
1
1
  import { defineNuxtPlugin, useRuntimeConfig, useState } from "#app";
2
2
  import { useAuthContext, useLogger, watch } from "#imports";
3
3
  export default defineNuxtPlugin(async (_nuxtApp) => {
4
- const logger = useLogger({ tag: "plugin.locale", level: 3 });
4
+ const logger = useLogger({ tag: "plugin.locale" });
5
5
  const { defaultLocale, defaultLanguage, defaultTimeZone } = useRuntimeConfig().public.nuxtCore;
6
6
  const localeState = useState("devecoffee.locale", () => ({
7
7
  locale: defaultLocale,
@@ -13,13 +13,16 @@ function initLogger() {
13
13
  }
14
14
  export default defineNuxtPlugin(async (_nuxtApp) => {
15
15
  const logger = reactive(initLogger());
16
+ const loggers = useRuntimeConfig().public.nuxtCore.logging.loggers;
16
17
  function getLogger(opts) {
17
- const { tag, level } = opts || {};
18
+ opts = opts || {};
18
19
  let _logger = logger;
19
- if (level != void 0) {
20
- _logger = _logger.create({ level });
20
+ const _opts = opts.tag && loggers && loggers[opts.tag] ? loggers[opts.tag] : { level: logger.level };
21
+ if (opts.level) {
22
+ _opts.level = opts.level;
21
23
  }
22
- return tag != void 0 ? _logger.withTag(tag) : _logger;
24
+ _logger = _logger.create(_opts);
25
+ return opts.tag != void 0 ? _logger.withTag(opts.tag) : _logger;
23
26
  }
24
27
  return { provide: { logging: { getLogger } } };
25
28
  });
@@ -3,5 +3,5 @@ import type { H3Event } from 'h3';
3
3
  export default function useServerLogger(options?: Partial<{
4
4
  event?: H3Event;
5
5
  tag?: string;
6
- level: LogLevel;
6
+ level?: LogLevel;
7
7
  }>): ConsolaInstance;
@@ -2,14 +2,23 @@ import { consola } from "consola";
2
2
  import { useRuntimeConfig } from "nitropack/runtime";
3
3
  let globalServerLogger;
4
4
  export default function useServerLogger(options) {
5
- const { tag, ...opts } = useRuntimeConfig(options?.event).nuxtCore.logging.server;
5
+ options = options || {};
6
+ const { server, loggers = {} } = useRuntimeConfig(options?.event).nuxtCore.logging;
7
+ const { tag: rootTag, ...opts } = server;
6
8
  if (!globalServerLogger) {
7
- globalServerLogger = consola.create(opts).withTag(tag);
9
+ globalServerLogger = consola.create(opts).withTag(rootTag);
8
10
  }
9
11
  let _logger = globalServerLogger;
10
- const { level } = opts || {};
11
- if (level != void 0) {
12
- _logger = _logger.create({ level });
12
+ if (!options.tag && options.level != opts.level) {
13
+ return _logger;
13
14
  }
14
- return tag != void 0 ? _logger.withTag(tag) : _logger;
15
+ let _opt = { level: opts.level };
16
+ if (options.tag && options.tag in loggers) {
17
+ _opt = loggers[options.tag];
18
+ }
19
+ if (options.level) {
20
+ _opt.level = options.level;
21
+ }
22
+ _logger = _logger.create(_opt);
23
+ return options.tag != void 0 ? _logger.withTag(options.tag) : _logger;
15
24
  }
@@ -66,7 +66,7 @@ export async function getSession(sessionId, opts) {
66
66
  const decrypted = decryptTokenSet(session.auth.tokenSet, opts.secret);
67
67
  session.auth.tokenSet = decrypted ?? void 0;
68
68
  } else {
69
- const logger = useServerLogger({ tag: "authts-helper", level: 3 });
69
+ const logger = useServerLogger({ tag: "authts-helper" });
70
70
  logger.warn(
71
71
  "[getSession] tokenSet is encrypted but sessions.secret is not configured \u2014 tokenSet will be inaccessible"
72
72
  );
@@ -172,7 +172,7 @@ export async function deleteSession(sessionId, opts) {
172
172
  }
173
173
  }
174
174
  export async function discoveryOpendId(wellKnownUrl, opts) {
175
- const logger = useServerLogger({ tag: "authts-helper", level: 3 });
175
+ const logger = useServerLogger({ tag: "authts-helper" });
176
176
  const {
177
177
  cache: { prefix: cachedPrefix, expires },
178
178
  clientId,
@@ -304,7 +304,7 @@ export function constructTokenSet(input) {
304
304
  };
305
305
  }
306
306
  export async function refreshTokenIfNeeded(session, opts) {
307
- const logger = useServerLogger({ tag: "authts-helper", level: 3 });
307
+ const logger = useServerLogger({ tag: "authts-helper" });
308
308
  let updateSession2 = {
309
309
  auth: { status: "unauthenticated", tokenSet: void 0 },
310
310
  user: getAnonymousUser()
@@ -1,7 +1,7 @@
1
1
  import useServerLogger from "#devcoffee-core/server/composables/useServerLogger";
2
2
  import { useStorage } from "nitropack/runtime";
3
- const logger = useServerLogger({ tag: "authts-mutex", level: 3 });
4
3
  export async function tryAcquireLock(storage, lockKey, ttlSeconds, useAtomic) {
4
+ const logger = useServerLogger({ tag: "authts-mutex" });
5
5
  if (useAtomic) {
6
6
  try {
7
7
  const baseStorage = useStorage();
@@ -10,6 +10,7 @@ import {
10
10
  useRuntimeConfig
11
11
  } from "#devcoffee-core/server/adapters/http";
12
12
  import { deepMerge, omit } from "#devcoffee-core/server/adapters/utils";
13
+ import useServerLogger from "#devcoffee-core/server/composables/useServerLogger";
13
14
  import { useNitroApp, useStorage } from "nitropack/runtime";
14
15
  import {
15
16
  authorizationCodeGrant,
@@ -71,6 +72,7 @@ export default function NuxtAuthtsHandler(options) {
71
72
  const requestUrl = getRequestURL(event);
72
73
  const queryParams = getQuery(event);
73
74
  const authAction = getAuthAction(requestUrl);
75
+ const logger = useServerLogger({ event, tag: "auth.handler" });
74
76
  let session = event.context.session;
75
77
  if (!session) {
76
78
  throw createError({
@@ -97,6 +99,7 @@ export default function NuxtAuthtsHandler(options) {
97
99
  const userInfoCacheKey = `${openid.cache.prefix}:userinfo:${session.id}`;
98
100
  let cachedUser = await cacheStorage2.getItem(userInfoCacheKey);
99
101
  if (!cachedUser) {
102
+ logger.debug("Re-fetch user info");
100
103
  cachedUser = await nuxtAuthOptions.userInfo(session.user, { tokenSet: session.auth.tokenSet });
101
104
  await cacheStorage2.setItem(userInfoCacheKey, cachedUser, { ttl: openid.autoFetchUserTtl });
102
105
  }
@@ -22,8 +22,8 @@ function resolveOptions(opts) {
22
22
  return deepMerge({ ...defaultOpts }, resolvedOpts || {});
23
23
  }
24
24
  export default function NuxtForwardRequestHandler(opts) {
25
- const { logLevel, targetBaseUrl, proxyPrefix, onBeforeRequest } = resolveOptions(opts);
26
- const logger = useServerLogger({ tag: "forward-request", level: logLevel });
25
+ const { targetBaseUrl, proxyPrefix, onBeforeRequest } = resolveOptions(opts);
26
+ const logger = useServerLogger({ tag: "forward-request" });
27
27
  if (!targetBaseUrl) {
28
28
  logger.error("no targetBaseUrl");
29
29
  throw createError({
@@ -1,4 +1,5 @@
1
1
  import { defineNitroPlugin, getCookie, setCookie, useRuntimeConfig } from "#devcoffee-core/server/adapters/http";
2
+ import useServerLogger from "#devcoffee-core/server/composables/useServerLogger";
2
3
  import { signSessionId } from "#devcoffee-core/server/core/crypto";
3
4
  import { refreshTokenIfNeeded, updateSession, validateSession } from "#devcoffee-core/server/core/helpers";
4
5
  import { useNitroApp, useStorage } from "nitropack/runtime";
@@ -23,7 +24,9 @@ export default defineNitroPlugin((nitroApp) => {
23
24
  names: { sessionId: cookieName }
24
25
  }
25
26
  } = useRuntimeConfig(event).nuxtCore.authts;
26
- let session = await validateSession(getCookie(event, cookieName), {
27
+ const sessionCookieId = getCookie(event, cookieName);
28
+ const logger = useServerLogger({ event, tag: "plugin.auth" });
29
+ let session = await validateSession(sessionCookieId, {
27
30
  storageName,
28
31
  storagePrefix,
29
32
  expiresIn,
@@ -47,6 +50,7 @@ export default defineNitroPlugin((nitroApp) => {
47
50
  const userInfoCacheKey = `${cache.prefix}:userinfo:${session.id}`;
48
51
  let cachedUser = await cacheStorage.getItem(userInfoCacheKey);
49
52
  if (!cachedUser) {
53
+ logger.debug("refetch user info sessionid=%s", sessionCookieId);
50
54
  const userInfoFn = useNitroApp()._sessionUserInfo;
51
55
  if (userInfoFn && session.auth.tokenSet) {
52
56
  cachedUser = await userInfoFn(session.user, { tokenSet: session.auth.tokenSet });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devcoffee/nuxt-core",
3
- "version": "1.2.5",
3
+ "version": "1.3.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },