@merkaly/nuxt 0.5.0 → 0.6.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
@@ -27,7 +27,7 @@ interface MerkalyModuleOptions {
27
27
  token: string;
28
28
  };
29
29
  }
30
- declare const merkalyModule: _nuxt_schema.NuxtModule<MerkalyModuleOptions, MerkalyModuleOptions, false>;
30
+ declare const _default: _nuxt_schema.NuxtModule<MerkalyModuleOptions, MerkalyModuleOptions, false>;
31
31
 
32
- export { merkalyModule as default };
32
+ export { _default as default };
33
33
  export type { MerkalyModuleOptions };
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.14.0"
6
6
  },
7
- "version": "0.5.0",
7
+ "version": "0.6.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { defineNuxtModule, useLogger, createResolver, addPlugin, addRouteMiddleware, addImportsDir, addComponentsDir, addTypeTemplate } from '@nuxt/kit';
1
+ import { defineNuxtModule, useLogger, createResolver, addPlugin, addServerHandler, addRouteMiddleware, addImportsDir, addComponentsDir, addTypeTemplate } from '@nuxt/kit';
2
2
  import { defu } from 'defu';
3
3
  import { createJiti } from 'jiti';
4
4
  import { existsSync } from 'node:fs';
@@ -73,7 +73,7 @@ function configureSentry(nuxt, options) {
73
73
  org: "merkaly",
74
74
  project: options.sentry.project
75
75
  });
76
- nuxt.options.sourcemap = { client: "hidden" };
76
+ nuxt.options.sourcemap = { client: "hidden", server: true };
77
77
  }
78
78
  async function loadBootstrapConfig(nuxt) {
79
79
  const rootDirResolver = createResolver(nuxt.options.rootDir);
@@ -95,15 +95,26 @@ function configureBootstrapVueNext(nuxt, components) {
95
95
  }
96
96
  );
97
97
  }
98
+ function configureAppHead(nuxt) {
99
+ nuxt.options.app?.head?.script?.push({
100
+ crossorigin: "anonymous",
101
+ src: "https://kit.fontawesome.com/55a4b2f4e1.js"
102
+ });
103
+ }
98
104
  function registerRuntimeFeatures(nuxt, options, resolver) {
99
105
  addPlugin({ src: resolver.resolve("./runtime/plugins/api.global") });
100
106
  addPlugin({ src: resolver.resolve("./runtime/plugins/auth0.client") });
101
107
  addPlugin({ src: resolver.resolve("./runtime/plugins/sentry.global") });
108
+ addServerHandler({
109
+ handler: resolver.resolve("./runtime/server/middleware/proxy"),
110
+ middleware: true
111
+ });
102
112
  addRouteMiddleware({
103
113
  global: options.auth0.requiresAuth,
104
114
  name: "auth",
105
115
  path: resolver.resolve("./runtime/middleware/auth")
106
116
  });
117
+ addImportsDir(resolver.resolve("./runtime/adapters"));
107
118
  addImportsDir(resolver.resolve("./runtime/composables"));
108
119
  addImportsDir(resolver.resolve("./runtime/utils"));
109
120
  addComponentsDir({
@@ -123,7 +134,7 @@ function configureVite(nuxt) {
123
134
  }
124
135
  );
125
136
  }
126
- const merkalyModule = defineNuxtModule({
137
+ const module = defineNuxtModule({
127
138
  defaults: defaultOptions,
128
139
  meta: {
129
140
  name: "@merkaly/nuxt",
@@ -148,9 +159,10 @@ const merkalyModule = defineNuxtModule({
148
159
  logger.info("Loading bootstrap.config.ts");
149
160
  }
150
161
  configureBootstrapVueNext(nuxt, bootstrapComponentsConfig);
162
+ configureAppHead(nuxt);
151
163
  registerRuntimeFeatures(nuxt, options, resolver);
152
164
  configureVite(nuxt);
153
165
  }
154
166
  });
155
167
 
156
- export { merkalyModule as default };
168
+ export { module as default };
@@ -0,0 +1,9 @@
1
+ interface AuthSessionData {
2
+ expiresAt: string | Date;
3
+ issuedAt: string | Date;
4
+ orgId?: string;
5
+ role: string;
6
+ userId: string;
7
+ }
8
+ export declare const createAuthSession: (args?: ((args: object) => import("#imports").AdapterArgs<AuthSessionData, Record<string, unknown>, object>) | undefined) => import("#imports").UseApiReturn<AuthSessionData, Record<string, unknown>, object>;
9
+ export {};
@@ -0,0 +1,14 @@
1
+ import { useAuth } from "#imports";
2
+ import { withAdapter } from "../utils/withAdapter.js";
3
+ export const createAuthSession = withAdapter(() => {
4
+ const { token } = useAuth();
5
+ return {
6
+ default: () => ({}),
7
+ global: true,
8
+ headers: {
9
+ authorization: token.value ? `Bearer ${token.value}` : ""
10
+ },
11
+ method: "POST",
12
+ uri: "/session"
13
+ };
14
+ });
@@ -0,0 +1 @@
1
+ export declare const deleteAuthSession: (args?: ((args: object) => import("../utils/withAdapter.js").AdapterArgs<undefined, Record<string, unknown>, object>) | undefined) => import("../composables/useApi.js").UseApiReturn<undefined, Record<string, unknown>, object>;
@@ -0,0 +1,6 @@
1
+ import { withAdapter } from "../utils/withAdapter.js";
2
+ export const deleteAuthSession = withAdapter(() => ({
3
+ global: true,
4
+ method: "DELETE",
5
+ uri: "/session"
6
+ }));
@@ -0,0 +1,9 @@
1
+ interface AuthSessionData {
2
+ expiresAt: string | Date;
3
+ issuedAt: string | Date;
4
+ orgId?: string;
5
+ role: string;
6
+ userId: string;
7
+ }
8
+ export declare const readAuthSession: (args?: ((args: object) => import("../utils/withAdapter.js").AdapterArgs<AuthSessionData, Record<string, unknown>, object>) | undefined) => import("../composables/useApi.js").UseApiReturn<AuthSessionData, Record<string, unknown>, object>;
9
+ export {};
@@ -0,0 +1,8 @@
1
+ import { withAdapter } from "../utils/withAdapter.js";
2
+ export const readAuthSession = withAdapter(() => ({
3
+ default: () => ({}),
4
+ global: true,
5
+ immediate: false,
6
+ method: "GET",
7
+ uri: "/session"
8
+ }));
@@ -1,8 +1,8 @@
1
- declare var __VLS_8: {}, __VLS_10: {};
1
+ declare var __VLS_7: {}, __VLS_9: {};
2
2
  type __VLS_Slots = {} & {
3
- loading?: (props: typeof __VLS_8) => any;
3
+ loading?: (props: typeof __VLS_7) => any;
4
4
  } & {
5
- default?: (props: typeof __VLS_10) => any;
5
+ default?: (props: typeof __VLS_9) => any;
6
6
  };
7
7
  declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
8
8
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -15,13 +15,15 @@ hook("page:finish", () => regenerate());
15
15
  </script>
16
16
 
17
17
  <template>
18
- <BApp>
19
- <!-- Mostramos spinner mientras auth se carga -->
20
- <slot v-if="isLoading" name="loading" />
18
+ <main>
19
+ <BApp>
20
+ <!-- Mostramos spinner mientras auth se carga -->
21
+ <slot v-if="isLoading" name="loading" />
21
22
 
22
- <!-- Renderizamos páginas solo cuando isLoading = false -->
23
- <slot v-else>
24
- <NuxtPage />
25
- </slot>
26
- </BApp>
23
+ <!-- Renderizamos páginas solo cuando isLoading = false -->
24
+ <slot v-else>
25
+ <NuxtPage />
26
+ </slot>
27
+ </BApp>
28
+ </main>
27
29
  </template>
@@ -1,8 +1,8 @@
1
- declare var __VLS_8: {}, __VLS_10: {};
1
+ declare var __VLS_7: {}, __VLS_9: {};
2
2
  type __VLS_Slots = {} & {
3
- loading?: (props: typeof __VLS_8) => any;
3
+ loading?: (props: typeof __VLS_7) => any;
4
4
  } & {
5
- default?: (props: typeof __VLS_10) => any;
5
+ default?: (props: typeof __VLS_9) => any;
6
6
  };
7
7
  declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
8
8
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -77,9 +77,9 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
77
77
  decimal: string;
78
78
  min: number;
79
79
  max: number;
80
- prefix: string;
81
80
  placeholder: string;
82
81
  precision: number;
82
+ prefix: string;
83
83
  suffix: string;
84
84
  thousands: string;
85
85
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -77,9 +77,9 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
77
77
  decimal: string;
78
78
  min: number;
79
79
  max: number;
80
- prefix: string;
81
80
  placeholder: string;
82
81
  precision: number;
82
+ prefix: string;
83
83
  suffix: string;
84
84
  thousands: string;
85
85
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -37,9 +37,9 @@ export interface ParamsOptions {
37
37
  body?: FetchOptions['body'];
38
38
  controller?: AbortController;
39
39
  default?: () => unknown;
40
+ global?: boolean;
40
41
  headers?: FetchOptions['headers'];
41
42
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
42
- prefix?: string;
43
43
  query?: FetchOptions['query'];
44
44
  timeout?: FetchOptions['timeout'];
45
45
  }
@@ -1,15 +1,15 @@
1
- import { defineNuxtPlugin, useRuntimeConfig } from "#app";
1
+ import { defineNuxtPlugin } from "#app";
2
2
  import { useAuth } from "#imports";
3
+ const GLOBAL_API_HEADER = "x-merkaly-global";
3
4
  export default defineNuxtPlugin(({ provide }) => provide("api", async (url, options = {}) => {
4
- const { public: $config } = useRuntimeConfig();
5
5
  const { tenant, token } = useAuth();
6
6
  await $fetch(url, {
7
- // Determine the base URL
8
- baseURL: new URL(options.prefix || $config.merkaly.api.prefix || "/", $config.merkaly.api.url).href,
7
+ baseURL: "/api",
9
8
  body: options?.body,
10
9
  headers: {
11
10
  authorization: token.value ? `Bearer ${token.value}` : "",
12
11
  identity: tenant.value,
12
+ [GLOBAL_API_HEADER]: options.global ? "true" : "",
13
13
  ...options?.headers
14
14
  },
15
15
  method: options?.method,
@@ -40,17 +40,17 @@ export default defineNuxtPlugin(async ({ callHook, hook }) => {
40
40
  redirect_uri: redirectUri
41
41
  }
42
42
  });
43
- auth0.linkWithConnection = (connection) => {
44
- return linkingClient.loginWithPopup({ authorizationParams: { connection } }).then(() => linkingClient.getIdTokenClaims()).then((claims) => {
45
- if (!claims?.sub) {
46
- throw new Error("Failed to get ID token for linking");
47
- }
48
- const [provider, ...userIdParts] = claims.sub.split("|");
49
- const userId = userIdParts.join("|");
50
- const body = { provider, userId };
51
- const { $api } = useNuxtApp();
52
- return $api("/identities", { method: "POST", prefix: "/", body });
53
- });
43
+ auth0.linkWithConnection = async (connection) => {
44
+ await linkingClient.loginWithPopup({ authorizationParams: { connection } });
45
+ const claims = await linkingClient.getIdTokenClaims();
46
+ if (!claims?.sub) {
47
+ throw new Error("Failed to get ID token for linking");
48
+ }
49
+ const [provider, ...userIdParts] = claims.sub.split("|");
50
+ const userId = userIdParts.join("|");
51
+ const body = { provider, userId };
52
+ const { $api } = useNuxtApp();
53
+ return await $api("/identities", { body, global: true, method: "POST" });
54
54
  };
55
55
  const isAuthCallback = window.location.pathname === callbackPath;
56
56
  if (!isAuthCallback) {
@@ -2,13 +2,10 @@ import { defineNuxtPlugin } from "#app";
2
2
  import { setUser } from "@sentry/nuxt";
3
3
  export default defineNuxtPlugin(async ({ hook }) => {
4
4
  hook("merkaly:auth", (user) => {
5
- if (!user) {
6
- return setUser(null);
7
- }
8
- return setUser({
5
+ return setUser(user ? {
9
6
  id: user.sub,
10
7
  email: user.email,
11
8
  username: user.name
12
- });
9
+ } : null);
13
10
  });
14
11
  });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any> | undefined>;
2
+ export default _default;
@@ -0,0 +1,34 @@
1
+ import { defineEventHandler, getRequestURL, proxyRequest } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
+ const GLOBAL_API_HEADER = "x-merkaly-global";
4
+ const API_PREFIX_PATTERN = /^\/api\/?/;
5
+ const API_ROUTE_PATTERN = /^\/api(?:\/|$)/;
6
+ const EDGE_SLASH_PATTERN = /^\/|\/$/g;
7
+ function normalizeSegment(value) {
8
+ return value.replace(EDGE_SLASH_PATTERN, "");
9
+ }
10
+ function resolveProxyPath(prefix, pathname, search) {
11
+ const normalizedPathname = pathname.replace(API_PREFIX_PATTERN, "");
12
+ return `/${[prefix, normalizedPathname].map(normalizeSegment).filter(Boolean).join("/")}${search}`;
13
+ }
14
+ function isGlobalRequest(value) {
15
+ if (Array.isArray(value)) {
16
+ return value.includes("true");
17
+ }
18
+ return value === "true";
19
+ }
20
+ export default defineEventHandler((event) => {
21
+ if (!API_ROUTE_PATTERN.test(event.path)) {
22
+ return;
23
+ }
24
+ const { public: $config } = useRuntimeConfig();
25
+ const targetOrigin = new URL($config.merkaly.api.url);
26
+ const url = getRequestURL(event);
27
+ const prefix = isGlobalRequest(event.node.req.headers[GLOBAL_API_HEADER]) ? "" : $config.merkaly.api.prefix;
28
+ const path = resolveProxyPath(prefix, url.pathname, url.search);
29
+ event.node.req.headers["x-forwarded-host"] = url.host;
30
+ if (import.meta.dev && targetOrigin.hostname.endsWith(".test")) {
31
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
32
+ }
33
+ return proxyRequest(event, new URL(path, targetOrigin).toString());
34
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merkaly/nuxt",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/merkaly-io/nuxt.git"