@devcoffee/nuxt-core 1.0.2 → 1.1.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.
Files changed (62) hide show
  1. package/README.md +407 -84
  2. package/dist/module.d.mts +295 -156
  3. package/dist/module.d.ts +300 -0
  4. package/dist/module.json +1 -1
  5. package/dist/module.mjs +191 -36
  6. package/dist/runtime/app/composables/useAuthContext.d.ts +26 -0
  7. package/dist/runtime/app/composables/useAuthContext.js +111 -0
  8. package/dist/runtime/app/composables/useLogger.d.ts +3 -3
  9. package/dist/runtime/app/composables/useSessionContext.d.ts +22 -0
  10. package/dist/runtime/app/composables/useSessionContext.js +5 -0
  11. package/dist/runtime/app/middleware/authts.d.ts +12 -0
  12. package/dist/runtime/app/middleware/authts.js +101 -0
  13. package/dist/runtime/app/pages/authorize.d.vue.ts +3 -0
  14. package/dist/runtime/app/pages/authorize.vue +32 -0
  15. package/dist/runtime/app/pages/authorize.vue.d.ts +3 -0
  16. package/dist/runtime/app/plugins/authts.d.ts +82 -0
  17. package/dist/runtime/app/plugins/authts.js +91 -0
  18. package/dist/runtime/app/plugins/formatters.d.ts +29 -0
  19. package/dist/runtime/app/plugins/formatters.js +101 -0
  20. package/dist/runtime/app/plugins/locale.d.ts +37 -0
  21. package/dist/runtime/app/plugins/locale.js +39 -0
  22. package/dist/runtime/app/plugins/logging.d.ts +24 -16
  23. package/dist/runtime/app/plugins/logging.js +0 -1
  24. package/dist/runtime/app/utils/hashing.d.ts +1 -0
  25. package/dist/runtime/app/utils/hashing.js +3 -0
  26. package/dist/runtime/server/adapters/http.d.ts +5 -0
  27. package/dist/runtime/server/adapters/http.js +15 -0
  28. package/dist/runtime/server/adapters/oidc.d.ts +58 -0
  29. package/dist/runtime/server/adapters/oidc.js +21 -0
  30. package/dist/runtime/server/adapters/storage.d.ts +39 -0
  31. package/dist/runtime/server/adapters/storage.js +14 -0
  32. package/dist/runtime/server/adapters/utils.d.ts +31 -0
  33. package/dist/runtime/server/adapters/utils.js +28 -0
  34. package/dist/runtime/server/composables/useServerLogger.d.ts +3 -2
  35. package/dist/runtime/server/composables/useServerLogger.js +4 -4
  36. package/dist/runtime/server/core/crypto.d.ts +70 -0
  37. package/dist/runtime/server/core/crypto.js +55 -0
  38. package/dist/runtime/server/core/helpers.d.ts +194 -0
  39. package/dist/runtime/server/core/helpers.js +355 -0
  40. package/dist/runtime/server/core/index.d.ts +1 -0
  41. package/dist/runtime/server/core/index.js +1 -0
  42. package/dist/runtime/server/core/mutex.d.ts +19 -0
  43. package/dist/runtime/server/core/mutex.js +39 -0
  44. package/dist/runtime/server/core/nuxtAuthtsHandler.d.ts +26 -0
  45. package/dist/runtime/server/core/nuxtAuthtsHandler.js +238 -0
  46. package/dist/runtime/server/core/nuxtForwardHandler.d.ts +18 -0
  47. package/dist/runtime/server/core/nuxtForwardHandler.js +60 -0
  48. package/dist/runtime/server/dev/route/session.d.ts +2 -0
  49. package/dist/runtime/server/dev/route/session.js +8 -0
  50. package/dist/runtime/server/plugins/authts.d.ts +11 -0
  51. package/dist/runtime/server/plugins/authts.js +55 -0
  52. package/dist/runtime/server/plugins/logging.js +7 -2
  53. package/dist/runtime/server/tsconfig.json +3 -3
  54. package/dist/runtime/types/global.env.d.ts +21 -7
  55. package/dist/runtime/types/nitro.d.ts +7 -2
  56. package/dist/runtime/types/nuxt.d.ts +28 -8
  57. package/dist/runtime/utils.d.ts +31 -0
  58. package/dist/runtime/utils.js +28 -0
  59. package/dist/types.d.mts +6 -4
  60. package/package.json +23 -14
  61. package/dist/runtime/plugin.d.ts +0 -2
  62. package/dist/runtime/plugin.js +0 -4
@@ -0,0 +1,18 @@
1
+ import type { SessionContext } from '@devcoffee/nuxt-core';
2
+ import type { CoreLogLevel, H3Event, ProxyOptions } from '#devcoffee-core/server/adapters/http';
3
+ import type { Configuration } from '#devcoffee-core/server/adapters/oidc';
4
+ type ForwardInit = {
5
+ forwardUrl: string;
6
+ } & ProxyOptions;
7
+ type ForwardRequestOptions = {
8
+ logLevel: CoreLogLevel;
9
+ targetBaseUrl?: string;
10
+ proxyPrefix: string;
11
+ onBeforeRequest?: (forwardInit: ForwardInit, parameters: {
12
+ event: H3Event;
13
+ session: Nullable<SessionContext>;
14
+ oidConfig: Configuration;
15
+ }) => Awaitable<ForwardInit>;
16
+ };
17
+ export default function NuxtForwardRequestHandler(opts?: DeepPartial<ForwardRequestOptions> | (() => DeepPartial<ForwardRequestOptions>)): any;
18
+ export {};
@@ -0,0 +1,60 @@
1
+ import {
2
+ createError,
3
+ eventHandler,
4
+ getRequestHeaders,
5
+ proxyRequest,
6
+ useRuntimeConfig
7
+ } from "#devcoffee-core/server/adapters/http";
8
+ import { deepMerge } from "#devcoffee-core/server/adapters/utils";
9
+ import useServerLogger from "#devcoffee-core/server/composables/useServerLogger";
10
+ import { getOpenIdConfiguration, getSession } from "./helpers.js";
11
+ const defaultOpts = {
12
+ logLevel: 2,
13
+ proxyPrefix: ""
14
+ };
15
+ function resolveOptions(opts) {
16
+ let resolvedOpts = {};
17
+ if (typeof opts === "function") {
18
+ resolvedOpts = opts();
19
+ } else {
20
+ resolvedOpts = opts || resolvedOpts;
21
+ }
22
+ return deepMerge({ ...defaultOpts }, resolvedOpts || {});
23
+ }
24
+ export default function NuxtForwardRequestHandler(opts) {
25
+ const { logLevel, targetBaseUrl, proxyPrefix, onBeforeRequest } = resolveOptions(opts);
26
+ const logger = useServerLogger({ tag: "forward-request", level: logLevel });
27
+ if (!targetBaseUrl) {
28
+ logger.error("no targetBaseUrl");
29
+ throw createError({
30
+ statusCode: 500,
31
+ fatal: true,
32
+ statusMessage: "Internal Server Error",
33
+ message: `Option targetBaseUrl is required.`
34
+ });
35
+ }
36
+ const {
37
+ openid: { wellKnownUrl, cache, clientId, clientSecret },
38
+ sessions: {
39
+ secret = "",
40
+ storage: { name: storageName, prefix: storagePrefix }
41
+ }
42
+ } = useRuntimeConfig().nuxtCore.authts;
43
+ return eventHandler(async (event) => {
44
+ const oidConfig = await getOpenIdConfiguration(wellKnownUrl, { cache, clientId, clientSecret });
45
+ const session = await getSession(event.context.sessionId, { storageName, storagePrefix, secret });
46
+ const headers = getRequestHeaders(event);
47
+ if (session?.auth?.status === "authenticated" && session.auth.tokenSet?.accessToken) {
48
+ headers.Authorization = `${session.auth.tokenSet.tokenType} ${session.auth.tokenSet?.accessToken}`;
49
+ }
50
+ const params = { event, session, oidConfig };
51
+ const defaultForwardInit = {
52
+ forwardUrl: `${targetBaseUrl}${event.path.replace(proxyPrefix, "")}`,
53
+ fetchOptions: { ignoreResponseError: true },
54
+ headers
55
+ };
56
+ logger.info(`from '${event.path}' to '${defaultForwardInit.forwardUrl}' - auth stt='${session?.auth?.status}'`);
57
+ const { forwardUrl, ...proxyOption } = await onBeforeRequest?.(defaultForwardInit, params) || defaultForwardInit;
58
+ return await proxyRequest(event, forwardUrl, proxyOption);
59
+ });
60
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { useRuntimeConfig } from "nitropack/runtime";
3
+ import { getSession } from "../../core/helpers.js";
4
+ export default defineEventHandler(async (event) => {
5
+ const { name: storageName, prefix: storagePrefix } = useRuntimeConfig(event).nuxtCore.authts.sessions.storage;
6
+ const { secret = "" } = useRuntimeConfig(event).nuxtCore.authts.sessions;
7
+ return await getSession(event.context.sessionId, { storageName, storagePrefix, secret });
8
+ });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 🔐 Nitro plugin for session validation and cookie management.
3
+ *
4
+ * This plugin automatically validates the session ID from the incoming request cookie.
5
+ * If the session is invalid or expired, it will create or refresh the session ID and
6
+ * reassign it back to the request context and cookie.
7
+ *
8
+ * @since 1.0.0
9
+ */
10
+ declare const _default: import("nitropack").NitroAppPlugin;
11
+ export default _default;
@@ -0,0 +1,55 @@
1
+ import { signSessionId } from "#devcoffee-core/server/core/crypto";
2
+ import { getSession, refreshTokenIfNeeded, updateSession, validateSession } from "#devcoffee-core/server/core/helpers";
3
+ import { getCookie, setCookie } from "h3";
4
+ import { defineNitroPlugin, useRuntimeConfig } from "nitropack/runtime";
5
+ export default defineNitroPlugin((nitroApp) => {
6
+ nitroApp.hooks.hook("request", async (event) => {
7
+ const {
8
+ enabled: authtsEnabled,
9
+ openid: { wellKnownUrl, cache, clientId, clientSecret, tokenRefreshBufferMs },
10
+ sessions: {
11
+ expiresIn,
12
+ secret = "",
13
+ storage: { name: storageName, prefix: storagePrefix },
14
+ names: { sessionId: cookieName }
15
+ }
16
+ } = useRuntimeConfig(event).nuxtCore.authts;
17
+ const session = await validateSession(getCookie(event, cookieName), {
18
+ storageName,
19
+ storagePrefix,
20
+ expiresIn,
21
+ secret
22
+ });
23
+ const { status = "unauthenticated", tokenSet } = session.auth || {};
24
+ if (authtsEnabled && status === "authenticated" && tokenSet) {
25
+ const sessionUpdate = await refreshTokenIfNeeded(session, {
26
+ wellKnownUrl,
27
+ cache,
28
+ clientId,
29
+ clientSecret,
30
+ tokenRefreshBufferMs
31
+ });
32
+ if (Object.keys(sessionUpdate).length > 0) {
33
+ await updateSession(session.id, sessionUpdate, { storageName, storagePrefix, expiresIn, secret });
34
+ }
35
+ }
36
+ event.context.sessionId = session.id;
37
+ });
38
+ nitroApp.hooks.hook("beforeResponse", async (event) => {
39
+ const {
40
+ cookieOpts,
41
+ secret = "",
42
+ storage: { name: storageName, prefix: storagePrefix },
43
+ names: { sessionId: cookieName }
44
+ } = useRuntimeConfig(event).nuxtCore.authts.sessions;
45
+ const session = await getSession(event.context.sessionId, { storageName, storagePrefix, secret });
46
+ if (session) {
47
+ const cookieValue = secret ? signSessionId(session.id, secret) : session.id;
48
+ event.context.sessionId = session.id;
49
+ setCookie(event, cookieName, cookieValue, {
50
+ ...cookieOpts,
51
+ expires: new Date(session.expiresAt)
52
+ });
53
+ }
54
+ });
55
+ });
@@ -1,7 +1,12 @@
1
+ import useServerLogger from "#devcoffee-core/server/composables/useServerLogger";
1
2
  import { defineNitroPlugin } from "nitropack/runtime";
2
- import useServerLogger from "../composables/useServerLogger.js";
3
3
  export default defineNitroPlugin((nitroApp) => {
4
+ nitroApp.hooks.hook("error", (error, { event }) => {
5
+ const logger = useServerLogger({ event });
6
+ const formattedMessages = [` Nitro ERROR: ${error}`, event && `Request: [${event.method}] '${event.path}'`];
7
+ logger.error(formattedMessages.join("\n"));
8
+ });
4
9
  nitroApp.hooks.hook("request", async (event) => {
5
- event.context.logger = useServerLogger(event);
10
+ event.context.logger = useServerLogger({ event });
6
11
  });
7
12
  });
@@ -1,3 +1,3 @@
1
- {
2
- "extends": "../../../.nuxt/tsconfig.server.json",
3
- }
1
+ {
2
+ "extends": "../../../.nuxt/tsconfig.server.json",
3
+ }
@@ -1,17 +1,25 @@
1
1
  declare global {
2
- type GenericType<T = any, K extends string = string> = Record<K, T>
3
-
2
+ type GenericType<T = any, K extends string | number | symbol = string> = Record<K, T>
3
+ type MaybeArray<T> = T | T[]
4
4
  type Nullable<T> = T | null
5
5
 
6
6
  type Concrete<Type> = {
7
7
  [Property in keyof Type]-?: Type[Property]
8
8
  }
9
9
 
10
- type DeepPartial<T> = T extends object
11
- ? {
12
- [P in keyof T]?: DeepPartial<T[P]>
13
- }
14
- : T
10
+ type DateTimeFormatToken = DateFormatToken | TimeFormatToken
11
+ type DateFormatToken = 'yyyy' | 'yy' | 'MM' | 'M' | 'dd' | 'd'
12
+ type TimeFormatToken = 'HH' | 'mm' | 'ss' | 'SSS' | 'Z'
13
+
14
+ type DeepPartial<T> = T extends (...args: any[]) => any
15
+ ? T // 🟩 Keep function types as-is
16
+ : T extends Date
17
+ ? T
18
+ : T extends Array<infer U>
19
+ ? Array<DeepPartial<U>> // 🟨 Recurse into array elements
20
+ : T extends object
21
+ ? { [K in keyof T]?: DeepPartial<T[K]> } // 🟦 Recurse into object properties
22
+ : T // 🟧 Primitives (string, number, etc.)
15
23
 
16
24
  type DeepReadonly<T> = T extends (infer R)[]
17
25
  ? ReadonlyArray<DeepReadonly<R>>
@@ -21,6 +29,10 @@ declare global {
21
29
  ? { readonly [P in keyof T]: DeepReadonly<T[P]> }
22
30
  : T
23
31
 
32
+ type DeepKeyOf<T extends GenericType> = {
33
+ [K in keyof T & string]: T[K] extends Record<string, any> ? K | `${K}.${DeepKeyOf<T[K]>}` : K
34
+ }[keyof T & string]
35
+
24
36
  type UnionKeyOf<T1, T2> = Array<Partial<keyof T1> & Partial<keyof T2>>
25
37
 
26
38
  type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }
@@ -34,6 +46,8 @@ declare global {
34
46
  type MayBeDate = Date | string | number
35
47
 
36
48
  type Awaitable<T> = T | Promise<T>
49
+
50
+ type HintedString<T extends string> = (string & {}) | T
37
51
  }
38
52
 
39
53
  export {}
@@ -1,9 +1,14 @@
1
- import type { ConsolaInstance } from 'consola'
1
+ import type { CoreLogInstance, CoreLogLevel, NuxtAuthOptions } from '@devcoffee/nuxt-core'
2
2
 
3
3
  declare module 'h3' {
4
4
  interface H3EventContext {
5
- logger: ConsolaInstance
5
+ logger: CoreLogInstance
6
+ sessionId: string
6
7
  }
7
8
  }
8
9
 
10
+ declare module 'nitropack/runtime' {
11
+ export type { CoreLogInstance, CoreLogLevel, NuxtAuthOptions }
12
+ }
13
+
9
14
  export {}
@@ -1,17 +1,37 @@
1
- import type { ConsolaInstance } from 'consola'
1
+ import type {
2
+ AuthtsMiddlewareMeta,
3
+ CoreLogInstance,
4
+ CoreLogLevel,
5
+ ModuleOptions,
6
+ ModulePublicRuntimeConfig,
7
+ NuxtSessionContext,
8
+ NuxtSessionUpdateContext,
9
+ } from '@devcoffee/nuxt-core'
2
10
 
3
- type NuxtCoreLogging = {
4
- getLogger: (opts?: { tag?: string; level?: LogLevel }) => ConsolaInstance
11
+ declare module 'nuxt/schema' {
12
+ interface RuntimeConfig {
13
+ nuxtCore: ModuleOptions
14
+ }
15
+
16
+ interface PublicRuntimeConfig {
17
+ nuxtCore: ModulePublicRuntimeConfig
18
+ }
5
19
  }
6
20
 
7
- declare module 'vue' {
8
- interface ComponentCustomProperties {
9
- $logging: NuxtCoreLogging
21
+ declare module 'vue-router' {
22
+ interface RouteMeta {
23
+ authts?: AuthtsMiddlewareMeta
10
24
  }
11
25
  }
12
26
 
13
27
  declare module '#app' {
14
- interface NuxtApp {
15
- $logging: NuxtCoreLogging
28
+ interface PageMeta {
29
+ authts?: AuthtsMiddlewareMeta
16
30
  }
17
31
  }
32
+
33
+ declare module '#app' {
34
+ export type { AuthtsMiddlewareMeta, NuxtSessionContext, NuxtSessionUpdateContext, CoreLogLevel, CoreLogInstance }
35
+ }
36
+
37
+ export {}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Recursively merges source objects into a new object based on target shape.
3
+ * Matches lodash merge semantics: arrays overwrite (no concat), undefined values skipped.
4
+ * Does NOT mutate the target argument.
5
+ *
6
+ * @param target - The base object (not mutated).
7
+ * @param sources - One or more partial source objects to merge in order.
8
+ * @returns A new merged object.
9
+ * @since 1.0.0
10
+ */
11
+ export declare function deepMerge<T extends object>(target: T, ...sources: object[]): T;
12
+ /**
13
+ * Returns a new object excluding the specified keys.
14
+ * Does NOT mutate the source object.
15
+ *
16
+ * @param obj - The source object.
17
+ * @param keys - Array of keys to exclude.
18
+ * @returns A new object without the excluded keys.
19
+ * @since 1.0.0
20
+ */
21
+ export declare function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K>;
22
+ /**
23
+ * Returns a new object containing only the specified keys.
24
+ * Does NOT mutate the source object.
25
+ *
26
+ * @param obj - The source object.
27
+ * @param keys - Array of keys to include.
28
+ * @returns A new object with only the picked keys.
29
+ * @since 1.0.0
30
+ */
31
+ export declare function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
@@ -0,0 +1,28 @@
1
+ export function deepMerge(target, ...sources) {
2
+ const result = { ...target };
3
+ for (const source of sources) {
4
+ if (!source || typeof source !== "object") continue;
5
+ for (const key of Object.keys(source)) {
6
+ const srcVal = source[key];
7
+ const tgtVal = result[key];
8
+ if (srcVal !== null && typeof srcVal === "object" && !Array.isArray(srcVal) && tgtVal !== null && typeof tgtVal === "object" && !Array.isArray(tgtVal)) {
9
+ result[key] = deepMerge(tgtVal, srcVal);
10
+ } else if (srcVal !== void 0) {
11
+ result[key] = srcVal;
12
+ }
13
+ }
14
+ }
15
+ return result;
16
+ }
17
+ export function omit(obj, keys) {
18
+ return Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k)));
19
+ }
20
+ export function pick(obj, keys) {
21
+ const result = {};
22
+ for (const key of keys) {
23
+ if (key in obj) {
24
+ result[key] = obj[key];
25
+ }
26
+ }
27
+ return result;
28
+ }
package/dist/types.d.mts CHANGED
@@ -1,7 +1,9 @@
1
- import type { NuxtModule } from '@nuxt/schema'
1
+ import type { ModulePublicRuntimeConfig } from './module.mjs'
2
2
 
3
- import type { default as Module } from './module.mjs'
4
-
5
- export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
3
+ declare module '@nuxt/schema' {
4
+ interface PublicRuntimeConfig extends ModulePublicRuntimeConfig {}
5
+ }
6
6
 
7
7
  export { default } from './module.mjs'
8
+
9
+ export { type AuthData, type AuthorizedUser, type AuthtsMiddlewareMeta, type AuthtsModuleOptions, type CoreLogInstance, type CoreLogLevel, type InputModuleOptions, type LoggingModuleOptions, type LoggingOptions, type ModuleOptions, type ModulePublicRuntimeConfig, type NuxtAuthOptions, type NuxtCoreLogging, type NuxtSessionContext, type NuxtSessionUpdateContext, type SessionContext } from './module.mjs'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devcoffee/nuxt-core",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "author": "Hieu Nguyen <hieunguyen@devcoffee.tech>",
5
5
  "description": "devcoffee core module for Nuxt",
6
6
  "license": "MIT",
@@ -26,38 +26,47 @@
26
26
  "module": "src/module.ts"
27
27
  },
28
28
  "scripts": {
29
- "dev": "npm run dev:prepare && nuxi dev playground",
29
+ "dev": "npm run dev:prepare && cross-env NODE_EXTRA_CA_CERTS=.certs/devcoffee.ca.pem nuxi dev playground",
30
30
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
31
+ "cleanup": "nuxi cleanup && nuxi cleanup playground",
31
32
  "dev:build": "nuxi build playground",
32
33
  "prepack": "nuxt-module-build build",
33
- "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
34
- "lint": "eslint .",
35
- "test": "vitest run",
36
- "test:watch": "vitest watch",
37
- "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
34
+ "release": "npm run lint && npm run test:all && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
35
+ "lint": "eslint --fix src test",
36
+ "test": "cross-env NODE_OPTIONS=--no-deprecation vitest run test/unit",
37
+ "test:e2e": "cross-env NODE_OPTIONS=--no-deprecation vitest run test/e2e",
38
+ "test:e2e:ui": "cross-env NODE_OPTIONS=--no-deprecation PLAYWRIGHT_HEADLESS=false vitest run test/e2e",
39
+ "test:all": "cross-env NODE_OPTIONS=--no-deprecation vitest run",
40
+ "test:watch": "cross-env NODE_OPTIONS=--no-deprecation vitest watch test/unit",
41
+ "test:types": "vue-tsc --noEmit src --skipLibCheck --strict"
38
42
  },
39
43
  "dependencies": {
40
44
  "@nuxt/kit": "^4.1.3",
41
45
  "consola": "^3.4.2",
42
- "lodash-es": "^4.17.21"
46
+ "cookie-es": "^1.2.2",
47
+ "openid-client": "^6.8.1"
43
48
  },
44
49
  "devDependencies": {
45
50
  "@ianvs/prettier-plugin-sort-imports": "^4.7.0",
46
51
  "@nuxt/devtools": "^2.6.5",
47
- "@nuxt/eslint": "^1.9.0",
48
- "@nuxt/eslint-config": "^1.9.0",
52
+ "@nuxt/devtools-kit": "^1.0.0",
53
+ "@nuxt/eslint": "^1.13.0",
54
+ "@nuxt/eslint-config": "^1.13.0",
49
55
  "@nuxt/module-builder": "^1.0.2",
50
56
  "@nuxt/schema": "^4.1.3",
51
57
  "@nuxt/test-utils": "^3.19.2",
52
- "@types/lodash-es": "^4.17.12",
58
+ "@playwright/test": "^1.58.2",
53
59
  "@types/node": "latest",
60
+ "@vue/test-utils": "^2.4.6",
54
61
  "changelogen": "^0.6.2",
55
62
  "cross-env": "^10.1.0",
56
63
  "eslint": "^9.37.0",
57
64
  "eslint-config-prettier": "^10.1.8",
58
- "eslint-plugin-prettier": "^5.5.4",
59
- "nuxt": "^4.1.3",
60
- "prettier": "^3.6.2",
65
+ "eslint-plugin-prettier": "^5.5.5",
66
+ "happy-dom": "^20.5.0",
67
+ "nuxt": "^4.2.2",
68
+ "playwright-core": "^1.58.2",
69
+ "prettier": "^3.8.1",
61
70
  "typescript": "~5.9.3",
62
71
  "vitest": "^3.2.4",
63
72
  "vue-tsc": "^3.1.0"
@@ -1,2 +0,0 @@
1
- declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
- export default _default;
@@ -1,4 +0,0 @@
1
- import { defineNuxtPlugin } from "#app";
2
- export default defineNuxtPlugin((_nuxtApp) => {
3
- console.log("Plugin injected by my-module!");
4
- });