@merkaly/nuxt 0.1.4 → 0.1.7
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 +26 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +68 -13
- package/dist/runtime/components/app.d.vue.ts +15 -0
- package/dist/runtime/components/app.vue +23 -0
- package/dist/runtime/components/app.vue.d.ts +15 -0
- package/dist/runtime/components/auth.d.vue.ts +9 -0
- package/dist/runtime/components/auth.vue +44 -0
- package/dist/runtime/components/auth.vue.d.ts +9 -0
- package/dist/runtime/components/format/FormatIcon.d.vue.ts +97 -0
- package/dist/runtime/components/format/FormatIcon.vue +40 -0
- package/dist/runtime/components/format/FormatIcon.vue.d.ts +97 -0
- package/dist/runtime/components/format/FormatMoney.d.vue.ts +70 -0
- package/dist/runtime/components/format/FormatMoney.vue +39 -0
- package/dist/runtime/components/format/FormatMoney.vue.d.ts +70 -0
- package/dist/runtime/components/input/InputMoney.d.vue.ts +88 -0
- package/dist/runtime/components/input/InputMoney.vue +35 -0
- package/dist/runtime/components/input/InputMoney.vue.d.ts +88 -0
- package/dist/runtime/composables/useApi.d.ts +18 -0
- package/dist/runtime/composables/useApi.js +42 -0
- package/dist/runtime/composables/useAuth.d.ts +8 -0
- package/dist/runtime/composables/useAuth.js +15 -0
- package/dist/runtime/middleware/auth.d.ts +2 -0
- package/dist/runtime/middleware/auth.js +20 -0
- package/dist/runtime/plugins/api.global.d.ts +47 -0
- package/dist/runtime/plugins/api.global.js +54 -0
- package/dist/runtime/plugins/auth0.client.d.ts +6 -0
- package/dist/runtime/plugins/auth0.client.js +34 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/types/nuxt.d.ts +16 -0
- package/dist/runtime/utils/withAdapter.d.ts +22 -0
- package/dist/runtime/utils/withAdapter.js +9 -0
- package/dist/types.d.mts +6 -10
- package/package.json +18 -13
- package/dist/module.d.cts +0 -2
package/dist/module.d.mts
CHANGED
|
@@ -1,2 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { ClientAuthorizationParams } from '@auth0/auth0-spa-js';
|
|
3
|
+
|
|
4
|
+
interface MerkalyModuleOptions {
|
|
5
|
+
auth0: {
|
|
6
|
+
audience: string;
|
|
7
|
+
callbackUrl: string;
|
|
8
|
+
client: string;
|
|
9
|
+
domain: string;
|
|
10
|
+
logoutUrl?: string;
|
|
11
|
+
params?: Omit<ClientAuthorizationParams, 'redirect_uri'>;
|
|
12
|
+
requiresAuth: boolean;
|
|
13
|
+
};
|
|
14
|
+
plausible?: {
|
|
15
|
+
domain: string;
|
|
16
|
+
localhost: string;
|
|
17
|
+
};
|
|
18
|
+
api: {
|
|
19
|
+
url: string;
|
|
20
|
+
prefix?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
declare const _default: _nuxt_schema.NuxtModule<MerkalyModuleOptions, MerkalyModuleOptions, false>;
|
|
24
|
+
|
|
25
|
+
export { _default as default };
|
|
26
|
+
export type { MerkalyModuleOptions };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,18 +1,73 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineNuxtModule, createResolver, addPlugin, addRouteMiddleware, addImportsDir, addComponentsDir } from '@nuxt/kit';
|
|
2
|
+
import { defu } from 'defu';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
2
4
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const module = defineNuxtModule({
|
|
6
|
+
defaults: {
|
|
7
|
+
auth0: {
|
|
8
|
+
audience: "",
|
|
9
|
+
callbackUrl: "/auth",
|
|
10
|
+
client: "",
|
|
11
|
+
domain: "",
|
|
12
|
+
logoutUrl: "/",
|
|
13
|
+
params: {},
|
|
14
|
+
requiresAuth: false
|
|
15
|
+
},
|
|
16
|
+
plausible: {
|
|
17
|
+
domain: "",
|
|
18
|
+
localhost: ""
|
|
19
|
+
},
|
|
20
|
+
api: {
|
|
21
|
+
url: "/",
|
|
22
|
+
prefix: "/"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
meta: { name: "@merkaly/nuxt", configKey: "merkaly", compatibility: { nuxt: ">=3.0.0" } },
|
|
26
|
+
moduleDependencies: {
|
|
27
|
+
"@bootstrap-vue-next/nuxt": {},
|
|
28
|
+
"@nuxt/eslint": {},
|
|
29
|
+
"@nuxt/fonts": {},
|
|
30
|
+
"@nuxt/image": {},
|
|
31
|
+
"@nuxtjs/plausible": {},
|
|
32
|
+
"@vueuse/nuxt": {}
|
|
7
33
|
},
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
34
|
+
async setup(options, nuxt) {
|
|
35
|
+
const moduleResolver = createResolver(import.meta.url);
|
|
36
|
+
const rootResolver = createResolver(nuxt.options.rootDir);
|
|
37
|
+
nuxt.options.runtimeConfig.public.merkaly = defu(options, nuxt.options.runtimeConfig.public.merkaly || {});
|
|
38
|
+
nuxt.options.plausible = defu({
|
|
39
|
+
apiHost: "https://analytics.merkaly.io",
|
|
40
|
+
domain: options.plausible?.domain,
|
|
41
|
+
enableAutoOutboundTracking: true,
|
|
42
|
+
enableAutoPageviews: true,
|
|
43
|
+
enabled: process.env.NODE_ENV === "production",
|
|
44
|
+
// ✅ Solo en producción
|
|
45
|
+
ignoredHostnames: ["localhost"].concat(options.plausible?.localhost || "").filter(Boolean)
|
|
46
|
+
}, nuxt.options.plausible || {});
|
|
47
|
+
const bootstrapConfigPath = rootResolver.resolve("bootstrap.config.ts");
|
|
48
|
+
let BootstrapConfig;
|
|
49
|
+
if (existsSync(bootstrapConfigPath)) {
|
|
50
|
+
BootstrapConfig = await import(bootstrapConfigPath) || {};
|
|
11
51
|
}
|
|
52
|
+
if (!BootstrapConfig) {
|
|
53
|
+
BootstrapConfig = {};
|
|
54
|
+
}
|
|
55
|
+
nuxt.options["bootstrapVueNext"] = defu(nuxt.options["bootstrapVueNext"] || {}, { plugin: { components: BootstrapConfig } });
|
|
56
|
+
addPlugin({ src: moduleResolver.resolve("./runtime/plugins/api.global") });
|
|
57
|
+
addPlugin({ src: moduleResolver.resolve("./runtime/plugins/auth0.client"), mode: "client" });
|
|
58
|
+
addRouteMiddleware({
|
|
59
|
+
global: options.auth0.requiresAuth,
|
|
60
|
+
name: "auth",
|
|
61
|
+
path: moduleResolver.resolve("./runtime/middleware/auth")
|
|
62
|
+
});
|
|
63
|
+
addImportsDir(moduleResolver.resolve("./runtime/composables"));
|
|
64
|
+
addImportsDir(moduleResolver.resolve("./runtime/utils"));
|
|
65
|
+
addComponentsDir({
|
|
66
|
+
path: moduleResolver.resolve("./runtime/components"),
|
|
67
|
+
prefix: "MK"
|
|
68
|
+
});
|
|
69
|
+
nuxt.options["vite"] = defu(nuxt.options["vite"] || {}, { plugins: [require("vite-svg-loader")()] });
|
|
12
70
|
}
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
/** @type {import("/Users/kronhyx/www/merkaly/src/nuxt/src/module.js")} */
|
|
16
|
-
const _module = await jiti.import("/Users/kronhyx/www/merkaly/src/nuxt/src/module.ts");
|
|
71
|
+
});
|
|
17
72
|
|
|
18
|
-
export
|
|
73
|
+
export { module as default };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare var __VLS_11: {}, __VLS_13: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
loading?: (props: typeof __VLS_11) => any;
|
|
4
|
+
} & {
|
|
5
|
+
default?: (props: typeof __VLS_13) => any;
|
|
6
|
+
};
|
|
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
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
11
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
12
|
+
new (): {
|
|
13
|
+
$slots: S;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useRoute } from "#app";
|
|
3
|
+
import { useAuth, watchOnce } from "#imports";
|
|
4
|
+
import AuthMiddleware from "../middleware/auth";
|
|
5
|
+
const $route = useRoute();
|
|
6
|
+
const { isLoading } = useAuth();
|
|
7
|
+
watchOnce(isLoading, () => AuthMiddleware($route, $route));
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<main>
|
|
12
|
+
<NuxtRouteAnnouncer />
|
|
13
|
+
<BOrchestrator />
|
|
14
|
+
|
|
15
|
+
<!-- Mostramos spinner mientras auth se carga -->
|
|
16
|
+
<slot v-if="isLoading" name="loading" />
|
|
17
|
+
|
|
18
|
+
<!-- Renderizamos páginas solo cuando isLoading = false -->
|
|
19
|
+
<slot v-else>
|
|
20
|
+
<NuxtPage />
|
|
21
|
+
</slot>
|
|
22
|
+
</main>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare var __VLS_11: {}, __VLS_13: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
loading?: (props: typeof __VLS_11) => any;
|
|
4
|
+
} & {
|
|
5
|
+
default?: (props: typeof __VLS_13) => any;
|
|
6
|
+
};
|
|
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
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
11
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
12
|
+
new (): {
|
|
13
|
+
$slots: S;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
2
|
+
error: (reason: string) => any;
|
|
3
|
+
success: () => any;
|
|
4
|
+
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
5
|
+
onError?: ((reason: string) => any) | undefined;
|
|
6
|
+
onSuccess?: (() => any) | undefined;
|
|
7
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useNuxtApp, showError } from "#app";
|
|
3
|
+
import { callOnce } from "#imports";
|
|
4
|
+
const { $auth0 } = useNuxtApp();
|
|
5
|
+
const emit = defineEmits(["success", "error"]);
|
|
6
|
+
const params = new URLSearchParams(window.location.search);
|
|
7
|
+
const code = params.get("code");
|
|
8
|
+
const error = params.get("error");
|
|
9
|
+
const invitation = params.get("invitation");
|
|
10
|
+
const organization = params.get("organization");
|
|
11
|
+
function handleInvite() {
|
|
12
|
+
return $auth0.loginWithRedirect({ authorizationParams: { organization, invitation } });
|
|
13
|
+
}
|
|
14
|
+
function handleError() {
|
|
15
|
+
const errorDescription = params.get("error_description") ?? "Auth error";
|
|
16
|
+
emit("error", errorDescription);
|
|
17
|
+
return showError({
|
|
18
|
+
statusCode: 400,
|
|
19
|
+
statusMessage: errorDescription
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function handleCode() {
|
|
23
|
+
return void $auth0.handleRedirectCallback().then(() => emit("success"));
|
|
24
|
+
}
|
|
25
|
+
callOnce(async () => {
|
|
26
|
+
if (invitation && organization) {
|
|
27
|
+
return handleInvite();
|
|
28
|
+
}
|
|
29
|
+
if (error) {
|
|
30
|
+
return handleError();
|
|
31
|
+
}
|
|
32
|
+
if (code) {
|
|
33
|
+
return handleCode();
|
|
34
|
+
}
|
|
35
|
+
return $auth0.loginWithRedirect();
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div class="d-flex gap-3 justify-content-center align-items-center h-100">
|
|
41
|
+
<BSpinner variant="primary" />
|
|
42
|
+
<span v-text="'Loading...'" />
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
2
|
+
error: (reason: string) => any;
|
|
3
|
+
success: () => any;
|
|
4
|
+
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
5
|
+
onError?: ((reason: string) => any) | undefined;
|
|
6
|
+
onSuccess?: (() => any) | undefined;
|
|
7
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { ColorVariant } from 'bootstrap-vue-next';
|
|
2
|
+
import type { PropType } from '#imports';
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
mode: {
|
|
5
|
+
type: StringConstructor;
|
|
6
|
+
default: string;
|
|
7
|
+
};
|
|
8
|
+
name: {
|
|
9
|
+
type: StringConstructor;
|
|
10
|
+
required: true;
|
|
11
|
+
};
|
|
12
|
+
opacity: {
|
|
13
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
14
|
+
default: () => string;
|
|
15
|
+
};
|
|
16
|
+
provider: {
|
|
17
|
+
type: StringConstructor;
|
|
18
|
+
default: string;
|
|
19
|
+
};
|
|
20
|
+
reversed: {
|
|
21
|
+
type: BooleanConstructor;
|
|
22
|
+
default: boolean;
|
|
23
|
+
};
|
|
24
|
+
size: {
|
|
25
|
+
type: StringConstructor;
|
|
26
|
+
default: () => string;
|
|
27
|
+
};
|
|
28
|
+
spin: {
|
|
29
|
+
type: BooleanConstructor;
|
|
30
|
+
default: boolean;
|
|
31
|
+
};
|
|
32
|
+
tag: {
|
|
33
|
+
type: StringConstructor;
|
|
34
|
+
default: () => string;
|
|
35
|
+
};
|
|
36
|
+
text: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
default: () => string;
|
|
39
|
+
};
|
|
40
|
+
variant: {
|
|
41
|
+
type: PropType<ColorVariant | string>;
|
|
42
|
+
default: () => string;
|
|
43
|
+
};
|
|
44
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
45
|
+
mode: {
|
|
46
|
+
type: StringConstructor;
|
|
47
|
+
default: string;
|
|
48
|
+
};
|
|
49
|
+
name: {
|
|
50
|
+
type: StringConstructor;
|
|
51
|
+
required: true;
|
|
52
|
+
};
|
|
53
|
+
opacity: {
|
|
54
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
55
|
+
default: () => string;
|
|
56
|
+
};
|
|
57
|
+
provider: {
|
|
58
|
+
type: StringConstructor;
|
|
59
|
+
default: string;
|
|
60
|
+
};
|
|
61
|
+
reversed: {
|
|
62
|
+
type: BooleanConstructor;
|
|
63
|
+
default: boolean;
|
|
64
|
+
};
|
|
65
|
+
size: {
|
|
66
|
+
type: StringConstructor;
|
|
67
|
+
default: () => string;
|
|
68
|
+
};
|
|
69
|
+
spin: {
|
|
70
|
+
type: BooleanConstructor;
|
|
71
|
+
default: boolean;
|
|
72
|
+
};
|
|
73
|
+
tag: {
|
|
74
|
+
type: StringConstructor;
|
|
75
|
+
default: () => string;
|
|
76
|
+
};
|
|
77
|
+
text: {
|
|
78
|
+
type: StringConstructor;
|
|
79
|
+
default: () => string;
|
|
80
|
+
};
|
|
81
|
+
variant: {
|
|
82
|
+
type: PropType<ColorVariant | string>;
|
|
83
|
+
default: () => string;
|
|
84
|
+
};
|
|
85
|
+
}>> & Readonly<{}>, {
|
|
86
|
+
text: string;
|
|
87
|
+
mode: string;
|
|
88
|
+
size: string;
|
|
89
|
+
tag: string;
|
|
90
|
+
variant: string;
|
|
91
|
+
opacity: string | number;
|
|
92
|
+
provider: string;
|
|
93
|
+
reversed: boolean;
|
|
94
|
+
spin: boolean;
|
|
95
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
96
|
+
declare const _default: typeof __VLS_export;
|
|
97
|
+
export default _default;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from "#imports";
|
|
3
|
+
const props = defineProps({
|
|
4
|
+
mode: { type: String, default: "duotone" },
|
|
5
|
+
name: { type: String, required: true },
|
|
6
|
+
opacity: { type: [String, Number], default: () => "" },
|
|
7
|
+
provider: { type: String, default: "fa" },
|
|
8
|
+
reversed: { type: Boolean, default: false },
|
|
9
|
+
size: { type: String, default: () => "" },
|
|
10
|
+
spin: { type: Boolean, default: false },
|
|
11
|
+
tag: { type: String, default: () => "i" },
|
|
12
|
+
text: { type: String, default: () => "" },
|
|
13
|
+
variant: { type: String, default: () => "" }
|
|
14
|
+
});
|
|
15
|
+
const iconName = computed(() => `${props.provider}-${props.name}`);
|
|
16
|
+
const iconMode = computed(() => `${props.provider}-${props.mode}`);
|
|
17
|
+
const animateSpin = computed(() => props.spin ? `${props.provider}-spin` : void 0);
|
|
18
|
+
const iconOpacity = computed(() => props.opacity ? `opacity-${props.opacity}` : void 0);
|
|
19
|
+
const fontSize = computed(() => props.size ? `fs-${props.size}` : void 0);
|
|
20
|
+
const fontColor = computed(() => props.variant ? `text-${props.variant}` : void 0);
|
|
21
|
+
const classList = computed(() => [
|
|
22
|
+
iconName.value,
|
|
23
|
+
iconMode.value,
|
|
24
|
+
animateSpin.value,
|
|
25
|
+
iconOpacity.value,
|
|
26
|
+
fontSize.value,
|
|
27
|
+
fontColor.value
|
|
28
|
+
].filter(Boolean));
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<template v-if="props.text">
|
|
33
|
+
<span :class="{ 'flex-row-reverse': props.reversed }" class="d-flex align-items-center">
|
|
34
|
+
<component :is="props.tag" :class="classList" />
|
|
35
|
+
<span class="ps-1" v-text="props.text" />
|
|
36
|
+
</span>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<component :is="props.tag" v-else :class="classList" />
|
|
40
|
+
</template>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { ColorVariant } from 'bootstrap-vue-next';
|
|
2
|
+
import type { PropType } from '#imports';
|
|
3
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
4
|
+
mode: {
|
|
5
|
+
type: StringConstructor;
|
|
6
|
+
default: string;
|
|
7
|
+
};
|
|
8
|
+
name: {
|
|
9
|
+
type: StringConstructor;
|
|
10
|
+
required: true;
|
|
11
|
+
};
|
|
12
|
+
opacity: {
|
|
13
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
14
|
+
default: () => string;
|
|
15
|
+
};
|
|
16
|
+
provider: {
|
|
17
|
+
type: StringConstructor;
|
|
18
|
+
default: string;
|
|
19
|
+
};
|
|
20
|
+
reversed: {
|
|
21
|
+
type: BooleanConstructor;
|
|
22
|
+
default: boolean;
|
|
23
|
+
};
|
|
24
|
+
size: {
|
|
25
|
+
type: StringConstructor;
|
|
26
|
+
default: () => string;
|
|
27
|
+
};
|
|
28
|
+
spin: {
|
|
29
|
+
type: BooleanConstructor;
|
|
30
|
+
default: boolean;
|
|
31
|
+
};
|
|
32
|
+
tag: {
|
|
33
|
+
type: StringConstructor;
|
|
34
|
+
default: () => string;
|
|
35
|
+
};
|
|
36
|
+
text: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
default: () => string;
|
|
39
|
+
};
|
|
40
|
+
variant: {
|
|
41
|
+
type: PropType<ColorVariant | string>;
|
|
42
|
+
default: () => string;
|
|
43
|
+
};
|
|
44
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
45
|
+
mode: {
|
|
46
|
+
type: StringConstructor;
|
|
47
|
+
default: string;
|
|
48
|
+
};
|
|
49
|
+
name: {
|
|
50
|
+
type: StringConstructor;
|
|
51
|
+
required: true;
|
|
52
|
+
};
|
|
53
|
+
opacity: {
|
|
54
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
55
|
+
default: () => string;
|
|
56
|
+
};
|
|
57
|
+
provider: {
|
|
58
|
+
type: StringConstructor;
|
|
59
|
+
default: string;
|
|
60
|
+
};
|
|
61
|
+
reversed: {
|
|
62
|
+
type: BooleanConstructor;
|
|
63
|
+
default: boolean;
|
|
64
|
+
};
|
|
65
|
+
size: {
|
|
66
|
+
type: StringConstructor;
|
|
67
|
+
default: () => string;
|
|
68
|
+
};
|
|
69
|
+
spin: {
|
|
70
|
+
type: BooleanConstructor;
|
|
71
|
+
default: boolean;
|
|
72
|
+
};
|
|
73
|
+
tag: {
|
|
74
|
+
type: StringConstructor;
|
|
75
|
+
default: () => string;
|
|
76
|
+
};
|
|
77
|
+
text: {
|
|
78
|
+
type: StringConstructor;
|
|
79
|
+
default: () => string;
|
|
80
|
+
};
|
|
81
|
+
variant: {
|
|
82
|
+
type: PropType<ColorVariant | string>;
|
|
83
|
+
default: () => string;
|
|
84
|
+
};
|
|
85
|
+
}>> & Readonly<{}>, {
|
|
86
|
+
text: string;
|
|
87
|
+
mode: string;
|
|
88
|
+
size: string;
|
|
89
|
+
tag: string;
|
|
90
|
+
variant: string;
|
|
91
|
+
opacity: string | number;
|
|
92
|
+
provider: string;
|
|
93
|
+
reversed: boolean;
|
|
94
|
+
spin: boolean;
|
|
95
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
96
|
+
declare const _default: typeof __VLS_export;
|
|
97
|
+
export default _default;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { PropType } from '#imports';
|
|
2
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
3
|
+
base: {
|
|
4
|
+
type: NumberConstructor;
|
|
5
|
+
default: number;
|
|
6
|
+
};
|
|
7
|
+
currency: {
|
|
8
|
+
type: StringConstructor;
|
|
9
|
+
default: () => string;
|
|
10
|
+
};
|
|
11
|
+
hideDecimal: {
|
|
12
|
+
type: BooleanConstructor;
|
|
13
|
+
default: () => boolean;
|
|
14
|
+
};
|
|
15
|
+
locale: {
|
|
16
|
+
type: StringConstructor;
|
|
17
|
+
default: () => string;
|
|
18
|
+
};
|
|
19
|
+
mode: {
|
|
20
|
+
type: PropType<Intl.NumberFormatOptionsStyle>;
|
|
21
|
+
default: string;
|
|
22
|
+
};
|
|
23
|
+
tag: {
|
|
24
|
+
type: StringConstructor;
|
|
25
|
+
default: string;
|
|
26
|
+
};
|
|
27
|
+
value: {
|
|
28
|
+
type: NumberConstructor;
|
|
29
|
+
default: number;
|
|
30
|
+
};
|
|
31
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
32
|
+
base: {
|
|
33
|
+
type: NumberConstructor;
|
|
34
|
+
default: number;
|
|
35
|
+
};
|
|
36
|
+
currency: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
default: () => string;
|
|
39
|
+
};
|
|
40
|
+
hideDecimal: {
|
|
41
|
+
type: BooleanConstructor;
|
|
42
|
+
default: () => boolean;
|
|
43
|
+
};
|
|
44
|
+
locale: {
|
|
45
|
+
type: StringConstructor;
|
|
46
|
+
default: () => string;
|
|
47
|
+
};
|
|
48
|
+
mode: {
|
|
49
|
+
type: PropType<Intl.NumberFormatOptionsStyle>;
|
|
50
|
+
default: string;
|
|
51
|
+
};
|
|
52
|
+
tag: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
default: string;
|
|
55
|
+
};
|
|
56
|
+
value: {
|
|
57
|
+
type: NumberConstructor;
|
|
58
|
+
default: number;
|
|
59
|
+
};
|
|
60
|
+
}>> & Readonly<{}>, {
|
|
61
|
+
value: number;
|
|
62
|
+
mode: keyof Intl.NumberFormatOptionsStyleRegistry;
|
|
63
|
+
base: number;
|
|
64
|
+
tag: string;
|
|
65
|
+
currency: string;
|
|
66
|
+
hideDecimal: boolean;
|
|
67
|
+
locale: string;
|
|
68
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
69
|
+
declare const _default: typeof __VLS_export;
|
|
70
|
+
export default _default;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from "#imports";
|
|
3
|
+
const props = defineProps({
|
|
4
|
+
base: { type: Number, default: 100 },
|
|
5
|
+
currency: { type: String, default: () => "USD" },
|
|
6
|
+
hideDecimal: { type: Boolean, default: () => false },
|
|
7
|
+
locale: { type: String, default: () => "en-US" },
|
|
8
|
+
mode: { type: String, default: "currency" },
|
|
9
|
+
tag: { type: String, default: "span" },
|
|
10
|
+
value: { type: Number, default: 0 }
|
|
11
|
+
});
|
|
12
|
+
const price = computed(() => {
|
|
13
|
+
const price2 = props.value / props.base;
|
|
14
|
+
const money = price2.toLocaleString(props.locale, {
|
|
15
|
+
style: props.mode,
|
|
16
|
+
currency: props.currency
|
|
17
|
+
});
|
|
18
|
+
return {
|
|
19
|
+
currency: money[0],
|
|
20
|
+
value: money.slice(1, -3),
|
|
21
|
+
digits: money.slice(-3)
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<component :is="tag" class="format-money">
|
|
28
|
+
<span class="currency" v-text="price.currency" />
|
|
29
|
+
<span class="value" v-text="price.value" />
|
|
30
|
+
<sup v-if="!props.hideDecimal" class="digits" v-text="price.digits" />
|
|
31
|
+
</component>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<style scoped>
|
|
35
|
+
.format-money {
|
|
36
|
+
font-variant-numeric: tabular-nums;
|
|
37
|
+
font-feature-settings: "tnum";
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { PropType } from '#imports';
|
|
2
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
3
|
+
base: {
|
|
4
|
+
type: NumberConstructor;
|
|
5
|
+
default: number;
|
|
6
|
+
};
|
|
7
|
+
currency: {
|
|
8
|
+
type: StringConstructor;
|
|
9
|
+
default: () => string;
|
|
10
|
+
};
|
|
11
|
+
hideDecimal: {
|
|
12
|
+
type: BooleanConstructor;
|
|
13
|
+
default: () => boolean;
|
|
14
|
+
};
|
|
15
|
+
locale: {
|
|
16
|
+
type: StringConstructor;
|
|
17
|
+
default: () => string;
|
|
18
|
+
};
|
|
19
|
+
mode: {
|
|
20
|
+
type: PropType<Intl.NumberFormatOptionsStyle>;
|
|
21
|
+
default: string;
|
|
22
|
+
};
|
|
23
|
+
tag: {
|
|
24
|
+
type: StringConstructor;
|
|
25
|
+
default: string;
|
|
26
|
+
};
|
|
27
|
+
value: {
|
|
28
|
+
type: NumberConstructor;
|
|
29
|
+
default: number;
|
|
30
|
+
};
|
|
31
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
32
|
+
base: {
|
|
33
|
+
type: NumberConstructor;
|
|
34
|
+
default: number;
|
|
35
|
+
};
|
|
36
|
+
currency: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
default: () => string;
|
|
39
|
+
};
|
|
40
|
+
hideDecimal: {
|
|
41
|
+
type: BooleanConstructor;
|
|
42
|
+
default: () => boolean;
|
|
43
|
+
};
|
|
44
|
+
locale: {
|
|
45
|
+
type: StringConstructor;
|
|
46
|
+
default: () => string;
|
|
47
|
+
};
|
|
48
|
+
mode: {
|
|
49
|
+
type: PropType<Intl.NumberFormatOptionsStyle>;
|
|
50
|
+
default: string;
|
|
51
|
+
};
|
|
52
|
+
tag: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
default: string;
|
|
55
|
+
};
|
|
56
|
+
value: {
|
|
57
|
+
type: NumberConstructor;
|
|
58
|
+
default: number;
|
|
59
|
+
};
|
|
60
|
+
}>> & Readonly<{}>, {
|
|
61
|
+
value: number;
|
|
62
|
+
mode: keyof Intl.NumberFormatOptionsStyleRegistry;
|
|
63
|
+
base: number;
|
|
64
|
+
tag: string;
|
|
65
|
+
currency: string;
|
|
66
|
+
hideDecimal: boolean;
|
|
67
|
+
locale: string;
|
|
68
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
69
|
+
declare const _default: typeof __VLS_export;
|
|
70
|
+
export default _default;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
+
decimal: {
|
|
3
|
+
type: StringConstructor;
|
|
4
|
+
default: () => string;
|
|
5
|
+
};
|
|
6
|
+
thousands: {
|
|
7
|
+
type: StringConstructor;
|
|
8
|
+
default: () => string;
|
|
9
|
+
};
|
|
10
|
+
precision: {
|
|
11
|
+
type: NumberConstructor;
|
|
12
|
+
default: () => number;
|
|
13
|
+
};
|
|
14
|
+
prefix: {
|
|
15
|
+
type: StringConstructor;
|
|
16
|
+
default: () => string;
|
|
17
|
+
};
|
|
18
|
+
suffix: {
|
|
19
|
+
type: StringConstructor;
|
|
20
|
+
default: () => string;
|
|
21
|
+
};
|
|
22
|
+
min: {
|
|
23
|
+
type: NumberConstructor;
|
|
24
|
+
default: undefined;
|
|
25
|
+
};
|
|
26
|
+
max: {
|
|
27
|
+
type: NumberConstructor;
|
|
28
|
+
default: undefined;
|
|
29
|
+
};
|
|
30
|
+
placeholder: {
|
|
31
|
+
type: StringConstructor;
|
|
32
|
+
default: () => string;
|
|
33
|
+
};
|
|
34
|
+
modelValue: {
|
|
35
|
+
type: import("vue").PropType<string | number>;
|
|
36
|
+
};
|
|
37
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
38
|
+
"update:modelValue": (value: string | number) => any;
|
|
39
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
40
|
+
decimal: {
|
|
41
|
+
type: StringConstructor;
|
|
42
|
+
default: () => string;
|
|
43
|
+
};
|
|
44
|
+
thousands: {
|
|
45
|
+
type: StringConstructor;
|
|
46
|
+
default: () => string;
|
|
47
|
+
};
|
|
48
|
+
precision: {
|
|
49
|
+
type: NumberConstructor;
|
|
50
|
+
default: () => number;
|
|
51
|
+
};
|
|
52
|
+
prefix: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
default: () => string;
|
|
55
|
+
};
|
|
56
|
+
suffix: {
|
|
57
|
+
type: StringConstructor;
|
|
58
|
+
default: () => string;
|
|
59
|
+
};
|
|
60
|
+
min: {
|
|
61
|
+
type: NumberConstructor;
|
|
62
|
+
default: undefined;
|
|
63
|
+
};
|
|
64
|
+
max: {
|
|
65
|
+
type: NumberConstructor;
|
|
66
|
+
default: undefined;
|
|
67
|
+
};
|
|
68
|
+
placeholder: {
|
|
69
|
+
type: StringConstructor;
|
|
70
|
+
default: () => string;
|
|
71
|
+
};
|
|
72
|
+
modelValue: {
|
|
73
|
+
type: import("vue").PropType<string | number>;
|
|
74
|
+
};
|
|
75
|
+
}>> & Readonly<{
|
|
76
|
+
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
|
|
77
|
+
}>, {
|
|
78
|
+
prefix: string;
|
|
79
|
+
decimal: string;
|
|
80
|
+
thousands: string;
|
|
81
|
+
precision: number;
|
|
82
|
+
suffix: string;
|
|
83
|
+
min: number;
|
|
84
|
+
max: number;
|
|
85
|
+
placeholder: string;
|
|
86
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
87
|
+
declare const _default: typeof __VLS_export;
|
|
88
|
+
export default _default;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from "#imports";
|
|
3
|
+
import { Money3Component } from "v-money3";
|
|
4
|
+
const model = defineModel({ type: [String, Number], ...{
|
|
5
|
+
default: () => 0,
|
|
6
|
+
get: (v) => v / 100,
|
|
7
|
+
set: (v) => v * 100,
|
|
8
|
+
type: [String, Number]
|
|
9
|
+
} });
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
decimal: { type: String, default: () => "." },
|
|
12
|
+
thousands: { type: String, default: () => "," },
|
|
13
|
+
precision: { type: Number, default: () => 2 },
|
|
14
|
+
prefix: { type: String, default: () => "" },
|
|
15
|
+
suffix: { type: String, default: () => "" },
|
|
16
|
+
min: { type: Number, default: void 0 },
|
|
17
|
+
max: { type: Number, default: void 0 },
|
|
18
|
+
placeholder: { type: String, default: () => "0.00" }
|
|
19
|
+
});
|
|
20
|
+
const config = computed(() => ({
|
|
21
|
+
class: "form-control",
|
|
22
|
+
decimal: props.decimal,
|
|
23
|
+
max: props.max,
|
|
24
|
+
min: props.min,
|
|
25
|
+
placeholder: props.placeholder,
|
|
26
|
+
precision: props.precision,
|
|
27
|
+
prefix: props.prefix ? `${props.prefix} ` : "",
|
|
28
|
+
suffix: props.suffix,
|
|
29
|
+
thousands: props.thousands
|
|
30
|
+
}));
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<Money3Component v-model="model" v-bind="config" />
|
|
35
|
+
</template>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
+
decimal: {
|
|
3
|
+
type: StringConstructor;
|
|
4
|
+
default: () => string;
|
|
5
|
+
};
|
|
6
|
+
thousands: {
|
|
7
|
+
type: StringConstructor;
|
|
8
|
+
default: () => string;
|
|
9
|
+
};
|
|
10
|
+
precision: {
|
|
11
|
+
type: NumberConstructor;
|
|
12
|
+
default: () => number;
|
|
13
|
+
};
|
|
14
|
+
prefix: {
|
|
15
|
+
type: StringConstructor;
|
|
16
|
+
default: () => string;
|
|
17
|
+
};
|
|
18
|
+
suffix: {
|
|
19
|
+
type: StringConstructor;
|
|
20
|
+
default: () => string;
|
|
21
|
+
};
|
|
22
|
+
min: {
|
|
23
|
+
type: NumberConstructor;
|
|
24
|
+
default: undefined;
|
|
25
|
+
};
|
|
26
|
+
max: {
|
|
27
|
+
type: NumberConstructor;
|
|
28
|
+
default: undefined;
|
|
29
|
+
};
|
|
30
|
+
placeholder: {
|
|
31
|
+
type: StringConstructor;
|
|
32
|
+
default: () => string;
|
|
33
|
+
};
|
|
34
|
+
modelValue: {
|
|
35
|
+
type: import("vue").PropType<string | number>;
|
|
36
|
+
};
|
|
37
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
38
|
+
"update:modelValue": (value: string | number) => any;
|
|
39
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
40
|
+
decimal: {
|
|
41
|
+
type: StringConstructor;
|
|
42
|
+
default: () => string;
|
|
43
|
+
};
|
|
44
|
+
thousands: {
|
|
45
|
+
type: StringConstructor;
|
|
46
|
+
default: () => string;
|
|
47
|
+
};
|
|
48
|
+
precision: {
|
|
49
|
+
type: NumberConstructor;
|
|
50
|
+
default: () => number;
|
|
51
|
+
};
|
|
52
|
+
prefix: {
|
|
53
|
+
type: StringConstructor;
|
|
54
|
+
default: () => string;
|
|
55
|
+
};
|
|
56
|
+
suffix: {
|
|
57
|
+
type: StringConstructor;
|
|
58
|
+
default: () => string;
|
|
59
|
+
};
|
|
60
|
+
min: {
|
|
61
|
+
type: NumberConstructor;
|
|
62
|
+
default: undefined;
|
|
63
|
+
};
|
|
64
|
+
max: {
|
|
65
|
+
type: NumberConstructor;
|
|
66
|
+
default: undefined;
|
|
67
|
+
};
|
|
68
|
+
placeholder: {
|
|
69
|
+
type: StringConstructor;
|
|
70
|
+
default: () => string;
|
|
71
|
+
};
|
|
72
|
+
modelValue: {
|
|
73
|
+
type: import("vue").PropType<string | number>;
|
|
74
|
+
};
|
|
75
|
+
}>> & Readonly<{
|
|
76
|
+
"onUpdate:modelValue"?: ((value: string | number) => any) | undefined;
|
|
77
|
+
}>, {
|
|
78
|
+
prefix: string;
|
|
79
|
+
decimal: string;
|
|
80
|
+
thousands: string;
|
|
81
|
+
precision: number;
|
|
82
|
+
suffix: string;
|
|
83
|
+
min: number;
|
|
84
|
+
max: number;
|
|
85
|
+
placeholder: string;
|
|
86
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
87
|
+
declare const _default: typeof __VLS_export;
|
|
88
|
+
export default _default;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ApiOptions } from '../plugins/api.global.js';
|
|
2
|
+
export interface ComposableOptions extends ApiOptions {
|
|
3
|
+
immediate?: boolean;
|
|
4
|
+
uri: string;
|
|
5
|
+
}
|
|
6
|
+
export type CallbackArgs<T extends object> = (args: T) => ComposableOptions;
|
|
7
|
+
declare function useApi<D extends object>(callback: CallbackArgs<D>): {
|
|
8
|
+
abort: {
|
|
9
|
+
(reason?: any): void;
|
|
10
|
+
(reason?: any): void;
|
|
11
|
+
};
|
|
12
|
+
data: import("vue").Ref<unknown, unknown>;
|
|
13
|
+
error: import("vue").Ref<Error | undefined, Error | undefined>;
|
|
14
|
+
execute: (args?: Partial<D>) => any;
|
|
15
|
+
loading: import("vue").Ref<boolean, boolean>;
|
|
16
|
+
meta: import("vue").Ref<{}, {}>;
|
|
17
|
+
};
|
|
18
|
+
export { useApi };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ref, reactive, useNuxtApp } from "#imports";
|
|
2
|
+
function useApi(callback) {
|
|
3
|
+
const { $api } = useNuxtApp();
|
|
4
|
+
const controller = new AbortController();
|
|
5
|
+
const params = reactive({});
|
|
6
|
+
const getOptions = (currentParams) => {
|
|
7
|
+
const options = callback(currentParams);
|
|
8
|
+
options.method ||= "GET";
|
|
9
|
+
options.immediate ??= options.method === "GET";
|
|
10
|
+
return options;
|
|
11
|
+
};
|
|
12
|
+
const initialOptions = getOptions(params);
|
|
13
|
+
const loading = ref(false);
|
|
14
|
+
const data = ref(initialOptions.default?.());
|
|
15
|
+
const meta = ref({});
|
|
16
|
+
const error = ref();
|
|
17
|
+
const execute = (args = {}) => {
|
|
18
|
+
Object.assign(params, args);
|
|
19
|
+
const currentOptions = getOptions(params);
|
|
20
|
+
return $api(currentOptions.uri, {
|
|
21
|
+
...currentOptions,
|
|
22
|
+
controller,
|
|
23
|
+
data,
|
|
24
|
+
default: currentOptions.default,
|
|
25
|
+
error,
|
|
26
|
+
loading,
|
|
27
|
+
meta
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
if (initialOptions.immediate) {
|
|
31
|
+
void execute();
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
abort: controller.abort,
|
|
35
|
+
data,
|
|
36
|
+
error,
|
|
37
|
+
execute,
|
|
38
|
+
loading,
|
|
39
|
+
meta
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export { useApi };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { User } from '@auth0/auth0-spa-js';
|
|
2
|
+
export declare const useAuth: () => {
|
|
3
|
+
isAuthenticated: import("vue").ComputedRef<boolean>;
|
|
4
|
+
isLoading: import("vue").Ref<boolean, boolean>;
|
|
5
|
+
tenant: import("vue").ComputedRef<any>;
|
|
6
|
+
token: import("vue").Ref<string | null, string | null>;
|
|
7
|
+
user: import("vue").Ref<User | null, User | null>;
|
|
8
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useState, computed } from "#imports";
|
|
2
|
+
export const useAuth = () => {
|
|
3
|
+
const user = useState("auth:user", () => null);
|
|
4
|
+
const token = useState("auth:token", () => null);
|
|
5
|
+
const isLoading = useState("auth:loading", () => true);
|
|
6
|
+
const tenant = computed(() => user.value?.org_id);
|
|
7
|
+
const isAuthenticated = computed(() => Boolean(user.value?.sub));
|
|
8
|
+
return {
|
|
9
|
+
isAuthenticated,
|
|
10
|
+
isLoading,
|
|
11
|
+
tenant,
|
|
12
|
+
token,
|
|
13
|
+
user
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineNuxtRouteMiddleware, navigateTo, useRuntimeConfig } from "#app";
|
|
2
|
+
import { useAuth } from "../composables/useAuth.js";
|
|
3
|
+
export default defineNuxtRouteMiddleware((to) => {
|
|
4
|
+
const { isLoading, isAuthenticated } = useAuth();
|
|
5
|
+
const { public: { merkaly } } = useRuntimeConfig();
|
|
6
|
+
if (isLoading.value) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (to.path === merkaly.auth0.callbackUrl) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const requiresAuth = typeof to.meta.requiresAuth === "boolean" ? to.meta.requiresAuth : merkaly.auth0.requiresAuth;
|
|
13
|
+
if (!requiresAuth) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (isAuthenticated.value) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
return navigateTo(merkaly.auth0.callbackUrl);
|
|
20
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Ref } from '#imports';
|
|
2
|
+
import type { FetchOptions, FetchResponse } from 'ofetch';
|
|
3
|
+
type OnBeforeSendArgs = {
|
|
4
|
+
query: FetchOptions['query'];
|
|
5
|
+
body: FetchOptions['body'];
|
|
6
|
+
headers: FetchOptions['headers'];
|
|
7
|
+
};
|
|
8
|
+
type OnResponseArgs = {
|
|
9
|
+
response: FetchResponse<unknown>;
|
|
10
|
+
request: RequestInfo;
|
|
11
|
+
};
|
|
12
|
+
type OnSuccessArgs = {
|
|
13
|
+
data: unknown;
|
|
14
|
+
meta: Record<string, unknown>;
|
|
15
|
+
headers: FetchOptions['headers'];
|
|
16
|
+
};
|
|
17
|
+
type OnCompleteArgs = {
|
|
18
|
+
response?: FetchResponse<unknown>;
|
|
19
|
+
request: RequestInfo;
|
|
20
|
+
};
|
|
21
|
+
export interface RefOptions {
|
|
22
|
+
data?: Ref<unknown>;
|
|
23
|
+
error?: Ref<unknown>;
|
|
24
|
+
loading?: Ref<boolean>;
|
|
25
|
+
meta?: Ref<Record<string, unknown>>;
|
|
26
|
+
}
|
|
27
|
+
export interface HooksOptions {
|
|
28
|
+
onBeforeSend?(args: OnBeforeSendArgs): Promise<unknown> | unknown;
|
|
29
|
+
onComplete?(args: OnCompleteArgs): Promise<unknown> | unknown;
|
|
30
|
+
onError?(reason: Error): Promise<unknown> | unknown;
|
|
31
|
+
onFatal?(reason: Error): Promise<unknown> | unknown;
|
|
32
|
+
onResponse?(args: OnResponseArgs): Promise<unknown> | unknown;
|
|
33
|
+
onSuccess?(args: OnSuccessArgs): Promise<unknown> | unknown;
|
|
34
|
+
}
|
|
35
|
+
export interface ParamsOptions {
|
|
36
|
+
body?: FetchOptions['body'];
|
|
37
|
+
controller?: AbortController;
|
|
38
|
+
default?: () => unknown;
|
|
39
|
+
headers?: FetchOptions['headers'];
|
|
40
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
41
|
+
prefix?: string;
|
|
42
|
+
query?: FetchOptions['query'];
|
|
43
|
+
timeout?: FetchOptions['timeout'];
|
|
44
|
+
}
|
|
45
|
+
export type ApiOptions = ParamsOptions & HooksOptions & RefOptions;
|
|
46
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
47
|
+
export default _default;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { defineNuxtPlugin, useRuntimeConfig } from "#app";
|
|
2
|
+
import { useAuth } from "#imports";
|
|
3
|
+
export default defineNuxtPlugin(({ provide }) => provide("api", async (url, options = {}) => {
|
|
4
|
+
const { public: $config } = useRuntimeConfig();
|
|
5
|
+
const { tenant, token } = useAuth();
|
|
6
|
+
$fetch(url, {
|
|
7
|
+
// Determine the base URL
|
|
8
|
+
baseURL: new URL(options.prefix || $config.merkaly.api.prefix || "/", $config.merkaly.api.url).href,
|
|
9
|
+
body: options?.body,
|
|
10
|
+
headers: {
|
|
11
|
+
authorization: token.value ? `Bearer ${token.value}` : "",
|
|
12
|
+
identity: tenant.value,
|
|
13
|
+
...options?.headers
|
|
14
|
+
},
|
|
15
|
+
method: options?.method,
|
|
16
|
+
onRequest: async () => {
|
|
17
|
+
if (options.data) options.data.value = options.default?.();
|
|
18
|
+
if (options.meta) options.meta.value = {};
|
|
19
|
+
if (options.error) options.error.value = void 0;
|
|
20
|
+
if (options.loading) options.loading.value = true;
|
|
21
|
+
const result = await Promise.resolve(options?.onBeforeSend?.({ body: options.body, headers: options.headers, query: options.query })).then((res) => res).catch(() => false);
|
|
22
|
+
if (result === false) {
|
|
23
|
+
options.controller?.abort?.("Request aborted by onBeforeSend");
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
onRequestError: async ({ error, response, request }) => {
|
|
27
|
+
await options.onFatal?.(error);
|
|
28
|
+
if (options.error) options.error.value = error;
|
|
29
|
+
await options?.onComplete?.({ response, request });
|
|
30
|
+
if (options.loading) options.loading.value = false;
|
|
31
|
+
},
|
|
32
|
+
onResponse: async ({ response, request }) => {
|
|
33
|
+
const { status, _data, headers } = response;
|
|
34
|
+
const { data, meta } = _data || {};
|
|
35
|
+
await options?.onResponse?.({ response, request });
|
|
36
|
+
if (status >= 400) return;
|
|
37
|
+
await options?.onSuccess?.({ data, meta, headers });
|
|
38
|
+
if (options.data) options.data.value = data;
|
|
39
|
+
if (options.meta) options.meta.value = meta;
|
|
40
|
+
await options?.onComplete?.({ response, request });
|
|
41
|
+
if (options.loading) options.loading.value = false;
|
|
42
|
+
},
|
|
43
|
+
onResponseError: async ({ response, request }) => {
|
|
44
|
+
const { _data } = response;
|
|
45
|
+
await options.onError?.(_data);
|
|
46
|
+
if (options.error) options.error.value = _data;
|
|
47
|
+
await options?.onComplete?.({ response, request });
|
|
48
|
+
if (options.loading) options.loading.value = false;
|
|
49
|
+
},
|
|
50
|
+
query: options?.query,
|
|
51
|
+
retry: false,
|
|
52
|
+
signal: options.controller?.signal
|
|
53
|
+
}).catch((reason) => reason);
|
|
54
|
+
}));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createAuth0Client } from "@auth0/auth0-spa-js";
|
|
2
|
+
import { defineNuxtPlugin, useRuntimeConfig } from "#imports";
|
|
3
|
+
import { navigateTo } from "#app";
|
|
4
|
+
import { defu } from "defu";
|
|
5
|
+
import { useAuth } from "../composables/useAuth.js";
|
|
6
|
+
export default defineNuxtPlugin(async () => {
|
|
7
|
+
const { public: $config } = useRuntimeConfig();
|
|
8
|
+
const auth0 = await createAuth0Client({
|
|
9
|
+
cacheLocation: "localstorage",
|
|
10
|
+
clientId: $config.merkaly.auth0.client,
|
|
11
|
+
domain: $config.merkaly.auth0.domain,
|
|
12
|
+
useRefreshTokens: true
|
|
13
|
+
});
|
|
14
|
+
const { isLoading, user, token } = useAuth();
|
|
15
|
+
const self0 = Object.assign(Object.create(Object.getPrototypeOf(auth0)), auth0);
|
|
16
|
+
auth0.getUser = () => self0.getUser().then((result) => user.value = result).catch((reason) => console.error("[Auth0] getUser failed", reason));
|
|
17
|
+
auth0.getTokenSilently = (options = {}) => self0.getTokenSilently(defu({ authorizationParams: { audience: $config.merkaly.auth0.audience } }, options)).then((result) => token.value = result).catch((err) => console.warn("[Auth0] getTokenSilently failed \u2013 fallback, user logged in?", err));
|
|
18
|
+
auth0.handleRedirectCallback = () => self0.handleRedirectCallback().then(({ appState }) => Promise.allSettled([auth0.getUser(), auth0.getTokenSilently()]).then(() => void navigateTo(appState?.target || "/"))).catch(() => navigateTo("/"));
|
|
19
|
+
auth0.loginWithRedirect = () => self0.loginWithRedirect({
|
|
20
|
+
authorizationParams: {
|
|
21
|
+
audience: $config.merkaly.auth0.audience,
|
|
22
|
+
redirect_uri: URL.canParse($config.merkaly.auth0.callbackUrl) ? $config.merkaly.auth0.callbackUrl : location.origin.concat($config.merkaly.auth0.callbackUrl),
|
|
23
|
+
scope: "openid profile email offline_access"
|
|
24
|
+
// necesario aquí para API
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
auth0.logout = () => self0.logout({
|
|
28
|
+
logoutParams: {
|
|
29
|
+
returnTo: URL.canParse($config.merkaly.auth0.logoutUrl) ? $config.merkaly.auth0.logoutUrl : location.origin.concat($config.merkaly.auth0.logoutUrl)
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
Promise.allSettled([auth0.getUser(), auth0.getTokenSilently()]).catch(() => void 0).finally(() => isLoading.value = false);
|
|
33
|
+
return { provide: { auth0 } };
|
|
34
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Auth0Client } from '@auth0/auth0-spa-js';
|
|
2
|
+
import type { ApiOptions } from '../plugins/api.global';
|
|
3
|
+
|
|
4
|
+
declare module '#app' {
|
|
5
|
+
interface NuxtApp {
|
|
6
|
+
$auth0: Auth0Client;
|
|
7
|
+
$api: (url: string, options?: ApiOptions) => Promise<unknown>;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module 'vue' {
|
|
12
|
+
interface ComponentCustomProperties {
|
|
13
|
+
$auth0: Auth0Client;
|
|
14
|
+
$api: (url: string, options?: ApiOptions) => Promise<unknown>;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ComposableOptions } from '../composables/useApi.js';
|
|
2
|
+
import type { HooksOptions } from '../plugins/api.global.js';
|
|
3
|
+
type ReturnParams<T extends AdapterOptions> = () => {
|
|
4
|
+
params?: T['params'];
|
|
5
|
+
} & HooksOptions;
|
|
6
|
+
export interface AdapterOptions {
|
|
7
|
+
data: unknown;
|
|
8
|
+
meta: Record<string, object>;
|
|
9
|
+
params: object;
|
|
10
|
+
}
|
|
11
|
+
export declare const withAdapter: <T extends AdapterOptions>(callback: (params: T["params"]) => ComposableOptions) => (args?: ReturnParams<T>) => {
|
|
12
|
+
abort: {
|
|
13
|
+
(reason?: any): void;
|
|
14
|
+
(reason?: any): void;
|
|
15
|
+
};
|
|
16
|
+
data: import("vue").Ref<unknown, unknown>;
|
|
17
|
+
error: import("vue").Ref<Error | undefined, Error | undefined>;
|
|
18
|
+
execute: (args?: Partial<T["params"]>) => any;
|
|
19
|
+
loading: import("vue").Ref<boolean, boolean>;
|
|
20
|
+
meta: import("vue").Ref<{}, {}>;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useApi } from "../composables/useApi.js";
|
|
2
|
+
import { defu } from "defu";
|
|
3
|
+
export const withAdapter = (callback) => (args) => useApi((executionParams) => {
|
|
4
|
+
const initialConfig = args?.() || {};
|
|
5
|
+
const { params: initialParams = {}, ...hooks } = initialConfig;
|
|
6
|
+
const mergedParams = defu(executionParams, initialParams);
|
|
7
|
+
const adapterResult = callback(mergedParams);
|
|
8
|
+
return defu(hooks, adapterResult);
|
|
9
|
+
});
|
package/dist/types.d.mts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { NuxtModule } from '@nuxt/schema'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
interface RuntimeNuxtHooks extends ModuleRuntimeHooks {}
|
|
5
|
-
}
|
|
3
|
+
import type { default as Module } from './module.mjs'
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
interface NuxtHooks extends ModuleHooks {}
|
|
9
|
-
interface RuntimeConfig extends ModuleRuntimeConfig {}
|
|
10
|
-
interface PublicRuntimeConfig extends ModulePublicRuntimeConfig {}
|
|
11
|
-
}
|
|
5
|
+
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
12
6
|
|
|
13
|
-
export
|
|
7
|
+
export { default } from './module.mjs'
|
|
8
|
+
|
|
9
|
+
export { type MerkalyModuleOptions } from './module.mjs'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@merkaly/nuxt",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/merkaly-io/nuxt.git"
|
|
@@ -27,6 +27,20 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "nuxt-module-build build",
|
|
32
|
+
"build:dev": "pnpm build --stub",
|
|
33
|
+
"dev": "pnpm dev:prepare && cd playground",
|
|
34
|
+
"dev:build": "nuxi build playground",
|
|
35
|
+
"dev:prepare": "pnpm build && pnpm -C playground install && nuxi prepare playground",
|
|
36
|
+
"lint": "eslint .",
|
|
37
|
+
"prepack": "pnpm dev:prepare",
|
|
38
|
+
"prepare": "nuxt-module-build prepare",
|
|
39
|
+
"release": "pnpm lint && pnpm test && pnpm build && changelogen --release && npm publish --access public && git push --follow-tags",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
42
|
+
"test:watch": "vitest watch"
|
|
43
|
+
},
|
|
30
44
|
"dependencies": {
|
|
31
45
|
"@auth0/auth0-spa-js": "^2.11.0",
|
|
32
46
|
"@bootstrap-vue-next/nuxt": "^0.42.0",
|
|
@@ -45,6 +59,7 @@
|
|
|
45
59
|
"@vueuse/nuxt": "^14.1.0",
|
|
46
60
|
"bootstrap": "^5.3.8",
|
|
47
61
|
"bootstrap-vue-next": "^0.42.0",
|
|
62
|
+
"defu": "^6.1.4",
|
|
48
63
|
"eslint": "^9.39.1",
|
|
49
64
|
"nuxt": "^4.2.0",
|
|
50
65
|
"sass": "^1.97.0",
|
|
@@ -59,6 +74,7 @@
|
|
|
59
74
|
"@nuxt/module-builder": "^1.0.2",
|
|
60
75
|
"@nuxt/schema": "^4.2.0",
|
|
61
76
|
"@nuxt/test-utils": "^3.23.0",
|
|
77
|
+
"baseline-browser-mapping": "^2.9.14",
|
|
62
78
|
"changelogen": "^0.6.2",
|
|
63
79
|
"eslint-plugin-storybook": "^10.1.11",
|
|
64
80
|
"vitest": "^4.0.6",
|
|
@@ -66,16 +82,5 @@
|
|
|
66
82
|
},
|
|
67
83
|
"engines": {
|
|
68
84
|
"node": ">=20.0.0"
|
|
69
|
-
},
|
|
70
|
-
"scripts": {
|
|
71
|
-
"build": "nuxt-module-build build --stub",
|
|
72
|
-
"dev": "pnpm dev:prepare && cd playground && pnpm storybook",
|
|
73
|
-
"dev:build": "nuxi build playground",
|
|
74
|
-
"dev:prepare": "pnpm build && nuxi prepare playground",
|
|
75
|
-
"lint": "eslint .",
|
|
76
|
-
"release": "pnpm lint && pnpm test && pnpm build && changelogen --release && npm publish --access public && git push --follow-tags",
|
|
77
|
-
"test": "vitest run",
|
|
78
|
-
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
79
|
-
"test:watch": "vitest watch"
|
|
80
85
|
}
|
|
81
|
-
}
|
|
86
|
+
}
|
package/dist/module.d.cts
DELETED