@mapomodule/core 1.0.0 → 2.0.0-beta.10

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 (96) hide show
  1. package/README.md +56 -0
  2. package/dist/index.d.mts +14 -0
  3. package/dist/index.d.ts +6 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.mjs +4 -0
  6. package/dist/module.d.mts +11 -0
  7. package/dist/module.d.ts +10 -0
  8. package/dist/module.d.ts.map +1 -0
  9. package/dist/module.json +9 -0
  10. package/dist/module.mjs +78 -0
  11. package/dist/runtime/__tests__/plugins/00.fetch.real.spec.d.ts +2 -0
  12. package/dist/runtime/__tests__/plugins/00.fetch.real.spec.d.ts.map +1 -0
  13. package/dist/runtime/__tests__/plugins/00.fetch.spec.d.ts +2 -0
  14. package/dist/runtime/__tests__/plugins/00.fetch.spec.d.ts.map +1 -0
  15. package/dist/runtime/__tests__/plugins/01.init.server.spec.d.ts +2 -0
  16. package/dist/runtime/__tests__/plugins/01.init.server.spec.d.ts.map +1 -0
  17. package/dist/runtime/__tests__/utils/fetchError.spec.d.ts +2 -0
  18. package/dist/runtime/__tests__/utils/fetchError.spec.d.ts.map +1 -0
  19. package/dist/runtime/api/crud.d.ts +23 -0
  20. package/dist/runtime/api/crud.d.ts.map +1 -0
  21. package/dist/runtime/api/crud.js +80 -0
  22. package/dist/runtime/api/multipart.d.ts +15 -0
  23. package/dist/runtime/api/multipart.d.ts.map +1 -0
  24. package/dist/runtime/api/multipart.js +31 -0
  25. package/dist/runtime/auth/useCanAccessRoute.d.ts +12 -0
  26. package/dist/runtime/auth/useCanAccessRoute.d.ts.map +1 -0
  27. package/dist/runtime/auth/useCanAccessRoute.js +28 -0
  28. package/dist/runtime/auth/useMapoAuth.d.ts +28 -0
  29. package/dist/runtime/auth/useMapoAuth.d.ts.map +1 -0
  30. package/dist/runtime/auth/useMapoAuth.js +38 -0
  31. package/dist/runtime/composables/useMapo.d.ts +48 -0
  32. package/dist/runtime/composables/useMapo.d.ts.map +1 -0
  33. package/dist/runtime/composables/useMapo.js +15 -0
  34. package/dist/runtime/middleware/auth.d.ts +10 -0
  35. package/dist/runtime/middleware/auth.d.ts.map +1 -0
  36. package/dist/runtime/middleware/auth.js +15 -0
  37. package/dist/runtime/middleware/permissions.d.ts +20 -0
  38. package/dist/runtime/middleware/permissions.d.ts.map +1 -0
  39. package/dist/runtime/middleware/permissions.js +27 -0
  40. package/dist/runtime/middleware/roles.d.ts +12 -0
  41. package/dist/runtime/middleware/roles.d.ts.map +1 -0
  42. package/dist/runtime/middleware/roles.js +13 -0
  43. package/dist/runtime/page-meta.nuxt.d.ts +23 -0
  44. package/dist/runtime/plugins/00.fetch.d.ts +21 -0
  45. package/dist/runtime/plugins/00.fetch.d.ts.map +1 -0
  46. package/dist/runtime/plugins/00.fetch.js +61 -0
  47. package/dist/runtime/plugins/01.init.server.d.ts +15 -0
  48. package/dist/runtime/plugins/01.init.server.d.ts.map +1 -0
  49. package/dist/runtime/plugins/01.init.server.js +35 -0
  50. package/dist/runtime/types.d.ts +75 -0
  51. package/dist/runtime/types.d.ts.map +1 -0
  52. package/dist/runtime/types.js +10 -0
  53. package/dist/runtime/types.nuxt.d.ts +18 -0
  54. package/dist/runtime/utils/fetchError.d.ts +29 -0
  55. package/dist/runtime/utils/fetchError.d.ts.map +1 -0
  56. package/dist/runtime/utils/fetchError.js +12 -0
  57. package/dist/runtime/utils/useMapoFetch.d.ts +30 -0
  58. package/dist/runtime/utils/useMapoFetch.d.ts.map +1 -0
  59. package/dist/runtime/utils/useMapoFetch.js +8 -0
  60. package/dist/types.d.mts +13 -0
  61. package/dist/types.d.ts +13 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/package.json +58 -15
  64. package/src/index.ts +9 -0
  65. package/src/module.ts +114 -0
  66. package/src/runtime/__tests__/plugins/00.fetch.real.spec.ts +124 -0
  67. package/src/runtime/__tests__/plugins/00.fetch.spec.ts +146 -0
  68. package/src/runtime/__tests__/plugins/01.init.server.spec.ts +94 -0
  69. package/src/runtime/__tests__/utils/fetchError.spec.ts +97 -0
  70. package/src/runtime/api/crud.ts +138 -0
  71. package/src/runtime/api/multipart.ts +78 -0
  72. package/src/runtime/auth/useCanAccessRoute.ts +48 -0
  73. package/src/runtime/auth/useMapoAuth.ts +91 -0
  74. package/src/runtime/composables/useMapo.ts +61 -0
  75. package/src/runtime/middleware/auth.ts +24 -0
  76. package/src/runtime/middleware/permissions.ts +52 -0
  77. package/src/runtime/middleware/roles.ts +23 -0
  78. package/src/runtime/page-meta.nuxt.d.ts +23 -0
  79. package/src/runtime/plugins/00.fetch.ts +92 -0
  80. package/src/runtime/plugins/01.init.server.ts +66 -0
  81. package/src/runtime/types.nuxt.d.ts +18 -0
  82. package/src/runtime/types.ts +102 -0
  83. package/src/runtime/utils/fetchError.ts +50 -0
  84. package/src/runtime/utils/useMapoFetch.ts +41 -0
  85. package/src/types.ts +13 -0
  86. package/CHANGELOG.md +0 -248
  87. package/api/crud.js +0 -141
  88. package/api/multipart.js +0 -41
  89. package/index.js +0 -134
  90. package/interceptor/auth.js +0 -26
  91. package/interceptor/index.js +0 -5
  92. package/middleware/auth.js +0 -10
  93. package/middleware/permissions.js +0 -36
  94. package/middleware/roles.js +0 -10
  95. package/module.js +0 -44
  96. package/templates/options.js +0 -1
@@ -0,0 +1,27 @@
1
+ import { defineNuxtRouteMiddleware, createError } from "nuxt/app";
2
+ import { useAuthStore } from "@mapomodule/store/runtime/stores/auth";
3
+ export default defineNuxtRouteMiddleware((to) => {
4
+ const auth = useAuthStore();
5
+ const perms = to.meta.permissions;
6
+ if (!perms) return;
7
+ if (auth.info?.is_superuser) {
8
+ if (!Array.isArray(perms)) {
9
+ auth.pagePermissions[String(to.name)] = [
10
+ "view",
11
+ "add",
12
+ "change",
13
+ "delete"
14
+ ];
15
+ }
16
+ return;
17
+ }
18
+ if (Array.isArray(perms)) {
19
+ if (!perms.every((p) => auth.rawPermissions.includes(p)))
20
+ throw createError({ statusCode: 403, message: "Forbidden" });
21
+ } else {
22
+ const actions = auth.rawPermissions.filter((p) => p.endsWith(`_${perms.model}`)).map((p) => p.replace(`_${perms.model}`, ""));
23
+ if (!actions.includes("view"))
24
+ throw createError({ statusCode: 403, message: "Forbidden" });
25
+ auth.pagePermissions[String(to.name)] = actions;
26
+ }
27
+ });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Route middleware that enforces role-based access from `to.meta.roles`.
3
+ *
4
+ * Access rules:
5
+ * - If no roles are configured on the route, access is allowed.
6
+ * - Superusers always bypass role checks.
7
+ * - For other users, at least one required role must match a user group.
8
+ * - If no match is found, navigation is blocked with HTTP 403.
9
+ */
10
+ declare const _default: import("nuxt/app").RouteMiddleware;
11
+ export default _default;
12
+ //# sourceMappingURL=roles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../../src/runtime/middleware/roles.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;;AACH,wBAUG"}
@@ -0,0 +1,13 @@
1
+ import { defineNuxtRouteMiddleware, createError } from "nuxt/app";
2
+ import { useAuthStore } from "@mapomodule/store/runtime/stores/auth";
3
+ export default defineNuxtRouteMiddleware((to) => {
4
+ const auth = useAuthStore();
5
+ const required = to.meta.roles;
6
+ if (!required?.length) return;
7
+ if (auth.info?.is_superuser) return;
8
+ const userGroups = auth.info?.groups ?? [];
9
+ const hasRole = required.some((r) => userGroups.includes(r));
10
+ if (!hasRole) {
11
+ throw createError({ statusCode: 403, message: "Forbidden" });
12
+ }
13
+ });
@@ -0,0 +1,23 @@
1
+ declare module "#app" {
2
+ interface PageMeta {
3
+ /**
4
+ * Permissions required to access this route. Checked by the 'permissions' middleware and sidebar visibility.
5
+ * - `{ model: string }` — derives `view_<model>` from a Django model name and populates `authStore.pagePermissions`
6
+ * - `string[]` — raw Django permission codenames (e.g. `['view_article', 'change_article']`)
7
+ */
8
+ permissions?: { model: string } | string[];
9
+ /** Required role/group names. Checked by the 'roles' middleware. */
10
+ roles?: string[];
11
+ }
12
+ }
13
+
14
+ declare module "vue-router" {
15
+ interface RouteMeta {
16
+ permissions?: { model: string } | string[];
17
+ roles?: string[];
18
+ /** Route middleware names applied to this route. Read by useCanAccessRoute for sidebar visibility. */
19
+ middleware?: string | string[];
20
+ }
21
+ }
22
+
23
+ export {};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Registers the global Mapo fetch client and loading state.
3
+ *
4
+ * The plugin provides:
5
+ * - `$mapoFetch`: a shared `$fetch` instance with centralized request/response hooks.
6
+ * - `$mapoFetchLoading`: a computed boolean based on a global pending-request counter.
7
+ *
8
+ * Error handling behavior:
9
+ * - `401` (except logout calls): reset auth state and, on client, redirect to login
10
+ * with the current route encoded in a `redirect` query parameter.
11
+ * - `403`: show a global "Permission denied" error snackbar.
12
+ */
13
+ declare const _default: import("nuxt/app").Plugin<{
14
+ mapoFetch: import("nitropack/types").$Fetch<unknown, import("nitropack/types").NitroFetchRequest>;
15
+ mapoFetchLoading: import("vue").ComputedRef<boolean>;
16
+ }> & import("nuxt/app").ObjectPlugin<{
17
+ mapoFetch: import("nitropack/types").$Fetch<unknown, import("nitropack/types").NitroFetchRequest>;
18
+ mapoFetchLoading: import("vue").ComputedRef<boolean>;
19
+ }>;
20
+ export default _default;
21
+ //# sourceMappingURL=00.fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"00.fetch.d.ts","sourceRoot":"","sources":["../../../src/runtime/plugins/00.fetch.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;GAWG;;;;;;;;AACH,wBAmEG"}
@@ -0,0 +1,61 @@
1
+ import { ref, computed } from "vue";
2
+ import {
3
+ defineNuxtPlugin,
4
+ navigateTo,
5
+ useRequestHeaders,
6
+ useRoute,
7
+ useRuntimeConfig
8
+ } from "nuxt/app";
9
+ import { useAuthStore } from "@mapomodule/store/runtime/stores/auth";
10
+ import { useSnackStore } from "@mapomodule/store/runtime/stores/snack";
11
+ export default defineNuxtPlugin({
12
+ name: "mapo-core:fetch",
13
+ enforce: "pre",
14
+ setup() {
15
+ const rc = useRuntimeConfig().public.mapoCore;
16
+ const logoutUrl = rc.logoutUrl;
17
+ const loginUrl = rc.loginUrl;
18
+ let redirectInFlight = false;
19
+ const handle = (status, requestUrl) => {
20
+ if (status === 401 && !requestUrl.includes(logoutUrl) && !redirectInFlight) {
21
+ redirectInFlight = true;
22
+ const auth = useAuthStore();
23
+ auth.reset();
24
+ if (import.meta.client) {
25
+ const route = useRoute();
26
+ navigateTo(
27
+ `${loginUrl}?redirect=${encodeURIComponent(route.fullPath)}`
28
+ );
29
+ }
30
+ }
31
+ if (status === 403) {
32
+ useSnackStore().show("Permission denied", "error");
33
+ }
34
+ };
35
+ const pending = ref(0);
36
+ const mapoFetchLoading = computed(() => pending.value > 0);
37
+ const forwardedCookie = import.meta.server ? useRequestHeaders(["cookie"]).cookie : void 0;
38
+ const mapoFetch = $fetch.create({
39
+ onRequest({ options }) {
40
+ pending.value++;
41
+ if (forwardedCookie) {
42
+ const headers = new Headers(
43
+ options.headers
44
+ );
45
+ if (!headers.has("cookie")) headers.set("cookie", forwardedCookie);
46
+ options.headers = headers;
47
+ }
48
+ },
49
+ onResponse({ response, request }) {
50
+ pending.value--;
51
+ handle(response.status, String(request));
52
+ },
53
+ onRequestError() {
54
+ pending.value--;
55
+ }
56
+ });
57
+ return {
58
+ provide: { mapoFetch, mapoFetchLoading }
59
+ };
60
+ }
61
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Performs server-side bootstrap of Mapo runtime stores.
3
+ *
4
+ * On each SSR request, this plugin:
5
+ * - Activates the request Pinia instance and initializes auth/sidebar stores.
6
+ * - Restores sidebar UI state from cookies.
7
+ * - If the HttpOnly session cookie is present, calls the configured `userInfoApi`
8
+ * (forwarding request cookies) to restore the authenticated user in the auth store.
9
+ *
10
+ * On session restore failure it resets auth state, and clears the session cookie only
11
+ * when the backend rejected the session (401/403) — never on a transport error.
12
+ */
13
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
14
+ export default _default;
15
+ //# sourceMappingURL=01.init.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"01.init.server.d.ts","sourceRoot":"","sources":["../../../src/runtime/plugins/01.init.server.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;GAWG;;AACH,wBAuCG"}
@@ -0,0 +1,35 @@
1
+ import {
2
+ defineNuxtPlugin,
3
+ useRuntimeConfig,
4
+ useCookie,
5
+ useRequestHeaders
6
+ } from "nuxt/app";
7
+ import { setActivePinia } from "pinia";
8
+ import { useAuthStore } from "@mapomodule/store/runtime/stores/auth";
9
+ import { useSidebarStore } from "@mapomodule/store/runtime/stores/sidebar";
10
+ import { CoreCookieEnum } from "../types.js";
11
+ export default defineNuxtPlugin({
12
+ name: "mapo-core:init",
13
+ async setup(nuxtApp) {
14
+ const runtimeConfig = useRuntimeConfig().public.mapoCore;
15
+ const userInfoApi = runtimeConfig?.userInfoApi ?? "/api/profiles/me/";
16
+ const pinia = nuxtApp.$pinia;
17
+ setActivePinia(pinia);
18
+ const authStore = useAuthStore(pinia);
19
+ const sidebarStore = useSidebarStore(pinia);
20
+ sidebarStore.hydrateFromCookies();
21
+ const sessionCookie = useCookie(CoreCookieEnum.Session);
22
+ if (!sessionCookie.value) return;
23
+ try {
24
+ const headers = useRequestHeaders(["cookie"]);
25
+ const user = await nuxtApp.$mapoFetch(userInfoApi, { method: "GET", headers });
26
+ authStore.setUser(user);
27
+ } catch (e) {
28
+ console.error(`[mapo] Cannot restore session from cookie:
29
+ ${e}`);
30
+ authStore.reset();
31
+ const status = e?.status ?? e?.response?.status;
32
+ if (status === 401 || status === 403) sessionCookie.value = null;
33
+ }
34
+ }
35
+ });
@@ -0,0 +1,75 @@
1
+ export declare enum MultipartPolicyEnum {
2
+ Auto = "auto",
3
+ Force = "force",
4
+ Disable = "disable"
5
+ }
6
+ export type MultipartPolicy = `${MultipartPolicyEnum}`;
7
+ export declare enum CoreCookieEnum {
8
+ Session = "__mapo_session"
9
+ }
10
+ export interface ListParams {
11
+ page?: number;
12
+ limit?: number;
13
+ search?: string;
14
+ ordering?: string;
15
+ [key: string]: unknown;
16
+ }
17
+ export interface PaginatedResponse<T> {
18
+ results: T[];
19
+ count: number;
20
+ next?: string | null;
21
+ previous?: string | null;
22
+ }
23
+ export type ApiResponse<T> = T;
24
+ export interface CrudConfig {
25
+ baseURL?: string;
26
+ headers?: Record<string, string>;
27
+ [key: string]: unknown;
28
+ }
29
+ export interface CrudOptions {
30
+ multipart?: MultipartPolicy;
31
+ }
32
+ /**
33
+ * What an endpoint returns from OPTIONS. Deliberately loose: backends extend it
34
+ * (Camomilla adds `lang_info`), and clients read only the keys they know.
35
+ */
36
+ export interface ResourceMetadata {
37
+ name?: string;
38
+ description?: string;
39
+ renders?: string[];
40
+ parses?: string[];
41
+ actions?: Record<string, unknown>;
42
+ [key: string]: unknown;
43
+ }
44
+ export interface CrudRepository<T> {
45
+ list(params?: ListParams, config?: CrudConfig): Promise<PaginatedResponse<T>>;
46
+ detail(id: string | number, config?: CrudConfig): Promise<T>;
47
+ create(data: Partial<T>, config?: CrudConfig, opts?: CrudOptions): Promise<T>;
48
+ update(id: string | number, data: Partial<T>, config?: CrudConfig, opts?: CrudOptions): Promise<T>;
49
+ partialUpdate(id: string | number, diff: Partial<T>, config?: CrudConfig, opts?: CrudOptions): Promise<T>;
50
+ delete(id: string | number, config?: CrudConfig): Promise<void>;
51
+ options(config?: CrudConfig): Promise<ResourceMetadata>;
52
+ updateOrCreate(data: Partial<T> & {
53
+ id?: string | number;
54
+ }, config?: CrudConfig, opts?: CrudOptions): Promise<T>;
55
+ updateOrder(startId: string | number, endId: string | number, config?: CrudConfig): Promise<void>;
56
+ }
57
+ export interface Credentials {
58
+ username: string;
59
+ password: string;
60
+ }
61
+ export interface AuthToken {
62
+ token: string;
63
+ [key: string]: unknown;
64
+ }
65
+ /**
66
+ * Shape of `runtimeConfig.public.mapoCore` as written by the module setup.
67
+ * All entries are guaranteed by the module `defaults`.
68
+ */
69
+ export interface MapoCoreRuntimeConfig {
70
+ authLoginUrl: string;
71
+ userInfoApi: string;
72
+ logoutUrl: string;
73
+ loginUrl: string;
74
+ }
75
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export var MultipartPolicyEnum = /* @__PURE__ */ ((MultipartPolicyEnum2) => {
2
+ MultipartPolicyEnum2["Auto"] = "auto";
3
+ MultipartPolicyEnum2["Force"] = "force";
4
+ MultipartPolicyEnum2["Disable"] = "disable";
5
+ return MultipartPolicyEnum2;
6
+ })(MultipartPolicyEnum || {});
7
+ export var CoreCookieEnum = /* @__PURE__ */ ((CoreCookieEnum2) => {
8
+ CoreCookieEnum2["Session"] = "__mapo_session";
9
+ return CoreCookieEnum2;
10
+ })(CoreCookieEnum || {});
@@ -0,0 +1,18 @@
1
+ import type { $Fetch } from "ofetch";
2
+
3
+ declare module "nuxt/app" {
4
+ interface NuxtApp {
5
+ $mapoFetch: $Fetch;
6
+ }
7
+ }
8
+
9
+ declare module "vue-router" {
10
+ interface RouteMeta {
11
+ permissions?: { model: string } | string[];
12
+ roles?: string[];
13
+ /** Route middleware names applied to this route. Read by useCanAccessRoute for sidebar visibility. */
14
+ middleware?: string | string[];
15
+ }
16
+ }
17
+
18
+ export {};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Helpers to read the backend payload out of a failed `$mapoFetch` call.
3
+ *
4
+ * `ofetch` throws a `FetchError` that exposes the parsed response body as
5
+ * `error.data` (and `error.response._data`) — NOT as `error.response.data`.
6
+ * Reading the wrong path silently yields `undefined`, which turns every
7
+ * backend validation message into a generic "something went wrong".
8
+ * Use these helpers instead of destructuring the error by hand.
9
+ */
10
+ /**
11
+ * Parsed response body of a failed request, or `undefined` when the request
12
+ * failed before a response was received (network error, abort…).
13
+ *
14
+ * @example
15
+ * try { await crud.create(model) }
16
+ * catch (err) {
17
+ * const data = getErrorData<{ title?: string[] }>(err)
18
+ * errors.value = data ?? {}
19
+ * }
20
+ */
21
+ export declare function getErrorData<T = Record<string, unknown>>(error: unknown): T | undefined;
22
+ /** HTTP status of a failed request, or `0` when no response was received. */
23
+ export declare function getErrorStatus(error: unknown): number;
24
+ /**
25
+ * `detail` message returned by the backend (DRF convention), when present.
26
+ * Falls back to `undefined` so callers can substitute a translated default.
27
+ */
28
+ export declare function getErrorDetail(error: unknown): string | undefined;
29
+ //# sourceMappingURL=fetchError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchError.d.ts","sourceRoot":"","sources":["../../../src/runtime/utils/fetchError.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtD,KAAK,EAAE,OAAO,GACb,CAAC,GAAG,SAAS,CAGf;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGrD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGjE"}
@@ -0,0 +1,12 @@
1
+ export function getErrorData(error) {
2
+ const e = error;
3
+ return e?.data ?? e?.response?._data;
4
+ }
5
+ export function getErrorStatus(error) {
6
+ const e = error;
7
+ return e?.status ?? e?.statusCode ?? e?.response?.status ?? 0;
8
+ }
9
+ export function getErrorDetail(error) {
10
+ const data = getErrorData(error);
11
+ return typeof data?.detail === "string" ? data.detail : void 0;
12
+ }
@@ -0,0 +1,30 @@
1
+ import type { $Fetch } from "ofetch";
2
+ import type { ComputedRef } from "vue";
3
+ export interface UseMapoFetchReturn {
4
+ /** The auth-aware `$mapoFetch` instance (same one provided by the plugin). */
5
+ fetch: $Fetch;
6
+ /**
7
+ * `true` while at least one `$mapoFetch` request is in flight — globally,
8
+ * across the entire app. Incremented by the plugin-level `onRequest` hook
9
+ * and decremented by `onResponse` / `onResponseError`, so it stays accurate
10
+ * even for raw `useNuxtApp().$mapoFetch` calls outside this composable.
11
+ */
12
+ loading: ComputedRef<boolean>;
13
+ }
14
+ /**
15
+ * Returns the global `$mapoFetch` instance together with a centralized
16
+ * `loading` indicator that tracks **all** in-flight `$mapoFetch` requests,
17
+ * not just the ones made through this composable.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const { fetch, loading } = useMapoFetch()
22
+ * await fetch('/api/articles/', { method: 'POST', body: payload })
23
+ * ```
24
+ *
25
+ * ```vue
26
+ * <UButton :loading="loading" @click="submit">Save</UButton>
27
+ * ```
28
+ */
29
+ export declare function useMapoFetch(): UseMapoFetchReturn;
30
+ //# sourceMappingURL=useMapoFetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMapoFetch.d.ts","sourceRoot":"","sources":["../../../src/runtime/utils/useMapoFetch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAEvC,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,IAAI,kBAAkB,CASjD"}
@@ -0,0 +1,8 @@
1
+ import { useNuxtApp } from "nuxt/app";
2
+ export function useMapoFetch() {
3
+ const nuxt = useNuxtApp();
4
+ return {
5
+ fetch: nuxt.$mapoFetch,
6
+ loading: nuxt.$mapoFetchLoading
7
+ };
8
+ }
@@ -0,0 +1,13 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
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>
6
+
7
+ export { type ApiResponse, type AuthToken, type CoreCookieEnum, type Credentials, type CrudConfig, type CrudOptions, type CrudRepository, type ListParams, type MultipartPolicy, type MultipartPolicyEnum, type PaginatedResponse } from '../dist/runtime/types.js'
8
+
9
+ export { type MapoApiLayer, type MapoFacade } from '../dist/runtime/composables/useMapo.js'
10
+
11
+ export { type RoutePermissions } from '../dist/runtime/auth/useCanAccessRoute.js'
12
+
13
+ export { type MapoOptions, default } from './module.mjs'
@@ -0,0 +1,13 @@
1
+ export interface MapoOptions {
2
+ authLoginUrl?: string;
3
+ userInfoApi?: string;
4
+ logoutUrl?: string;
5
+ loginUrl?: string;
6
+ }
7
+ export declare const MAPO_DEFAULTS: {
8
+ authLoginUrl: string;
9
+ userInfoApi: string;
10
+ logoutUrl: string;
11
+ loginUrl: string;
12
+ };
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa;;;;;CAKO,CAAC"}
package/package.json CHANGED
@@ -1,22 +1,65 @@
1
1
  {
2
2
  "name": "@mapomodule/core",
3
- "version": "1.0.0",
4
- "description": "This is part of Mapo nuxt module. Injects the core mapo plugin helpers.",
5
- "author": "bnznamco <gabriele.baldi.01@gmail.com>",
6
- "keywords": [
7
- "mapo",
8
- "nuxt",
9
- "Admin",
10
- "Panel"
11
- ],
3
+ "version": "2.0.0-beta.10",
4
+ "description": "Mapo core: API layer, auth, composables, middleware",
5
+ "type": "module",
12
6
  "license": "MIT",
13
- "repository": "https://github.com/lotrekagency/mapo",
14
- "main": "./module.js",
15
- "dependencies": {
16
- "@mapomodule/utils": "^1.0.0"
7
+ "author": "Lotrek Agency (https://lotrek.it)",
8
+ "homepage": "https://lotrekagency.github.io/mapo-new/",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/lotrekagency/mapo-new.git",
12
+ "directory": "packages/@mapomodule/core"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/lotrekagency/mapo-new/issues"
17
16
  },
18
17
  "publishConfig": {
19
- "access": "public"
18
+ "access": "public",
19
+ "tag": "next"
20
+ },
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/module.d.mts",
24
+ "import": "./dist/module.mjs"
25
+ },
26
+ "./types": {
27
+ "types": "./dist/index.d.mts",
28
+ "import": "./dist/index.mjs"
29
+ },
30
+ "./runtime/*": {
31
+ "types": "./src/runtime/*.ts",
32
+ "import": "./dist/runtime/*.js",
33
+ "default": "./src/runtime/*"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src"
39
+ ],
40
+ "scripts": {
41
+ "dev": "nuxt-module-build build --stub --watch",
42
+ "build": "nuxt-module-build build && tsc -p tsconfig.build-types.json",
43
+ "dev:prepare": "nuxt-module-build build --stub",
44
+ "typecheck": "tsc --noEmit",
45
+ "lint": "eslint src"
46
+ },
47
+ "dependencies": {
48
+ "@mapomodule/store": "2.0.0-beta.6",
49
+ "@mapomodule/utils": "2.0.0-beta.6"
50
+ },
51
+ "peerDependencies": {
52
+ "nuxt": ">=4.0.0",
53
+ "pinia": "^3.0.0"
20
54
  },
21
- "gitHead": "1e825711fb068d6195fe6dda607d1fb0e05109ec"
55
+ "devDependencies": {
56
+ "@nuxt/kit": "4.4.2",
57
+ "@nuxt/module-builder": "^1.0.2",
58
+ "@nuxt/schema": "4.4.2",
59
+ "nuxt": "^4.5.1",
60
+ "ofetch": "^1.5.1",
61
+ "pinia": "^3.0.4",
62
+ "vue": "^3.5.40",
63
+ "vue-router": "^5.2.0"
64
+ }
22
65
  }
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ export type * from "./module";
2
+ export { MultipartPolicyEnum, CoreCookieEnum } from "./runtime/types";
3
+ export { useCanAccessRoute } from "./runtime/auth/useCanAccessRoute";
4
+ export { useMapoFetch } from "./runtime/utils/useMapoFetch";
5
+ export {
6
+ getErrorData,
7
+ getErrorStatus,
8
+ getErrorDetail,
9
+ } from "./runtime/utils/fetchError";