@ghentcdh/authentication-vue 0.0.2-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/README.md +119 -0
- package/eslint.config.cjs +21 -0
- package/package.json +23 -0
- package/project.json +13 -0
- package/src/authentication.store.ts +46 -0
- package/src/index.ts +3 -0
- package/src/keycloak.adapter.ts +55 -0
- package/src/request.store.ts +126 -0
- package/src/vue-shims.d.ts +7 -0
- package/tsconfig.json +23 -0
- package/tsconfig.lib.json +31 -0
- package/tsconfig.spec.json +28 -0
- package/vite.config.ts +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Authentication
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Use the GhentCDH keycloak libraries for authentication
|
|
6
|
+
|
|
7
|
+
## Install the libraries
|
|
8
|
+
|
|
9
|
+
```ssh
|
|
10
|
+
pnpm add @ghentcdh/auth/frontend @ghentcdh/auth/backend
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Frontend vuejs
|
|
14
|
+
|
|
15
|
+
Add following environment variables to the `.env` file.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
- VITE_KEYCLOAK_HOST=$KEYCLOAK_HOST
|
|
19
|
+
- VITE_KEYCLOAK_REALM=$KEYCLOAK_REALM
|
|
20
|
+
- VITE_KEYCLOAK_CLIENT_ID=$KEYCLOAK_CLIENT_ID
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Check if a user is logged in
|
|
24
|
+
|
|
25
|
+
```vue
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import {useAuthenticationStore} from "@ghentcdh/authentication/frontend";
|
|
29
|
+
|
|
30
|
+
const authenticationStore = useAuthenticationStore();
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<pre>user: {{ authenticationStore.user() }}</pre>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Perform backend requests with the token
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
|
|
43
|
+
<script setup lang="ts">
|
|
44
|
+
import {useHttpStore} from "@ghentcdh/authentication/frontend";
|
|
45
|
+
|
|
46
|
+
const httpStore = useHttpStore();
|
|
47
|
+
|
|
48
|
+
httpStore.post('/api/auth/login', {}).then(response => {
|
|
49
|
+
alert('login ok')
|
|
50
|
+
});
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> TODO list
|
|
57
|
+
> - [ ] Add roles guard to see if routes or parts of the application can be accessed by that user
|
|
58
|
+
> - [ ] Test if it's possible to have public routes
|
|
59
|
+
> - [ ] Add a
|
|
60
|
+
> - [ ] Add logout functionality
|
|
61
|
+
|
|
62
|
+
## Backend nestjs
|
|
63
|
+
|
|
64
|
+
Add following environment variables to the `.env` file.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
- KEYCLOAK_HOST=$KEYCLOAK_HOST
|
|
68
|
+
- KEYCLOAK_REALM=$KEYCLOAK_REALM
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Secure requests
|
|
72
|
+
|
|
73
|
+
Add the module to your module.ts imports
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
|
|
77
|
+
import {AuthenticationApiModule} from "@ghentcdh/authentication/api";
|
|
78
|
+
|
|
79
|
+
@Module({
|
|
80
|
+
imports: [AuthenticationApiModule],
|
|
81
|
+
})
|
|
82
|
+
export class MyModule {
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use the `@GhentCdhGuard` decorator to secure your routes
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import {GhentCdhGuard} from "@ghentcdh/authentication/api";
|
|
91
|
+
|
|
92
|
+
@Controller()
|
|
93
|
+
export class MyController {
|
|
94
|
+
@UseGuards(GhentCdhGuard)
|
|
95
|
+
@Post('/secure')
|
|
96
|
+
async securePath(@User() user: any, @Request() req: any) {
|
|
97
|
+
return user;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The `@User()` decorator will give you the user object from the keycloak token.
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
> TODO list
|
|
106
|
+
> - [ ] Add roles decorator and implement logic `@GhentCdhRoles(['admin'])`
|
|
107
|
+
|
|
108
|
+
## Development environment
|
|
109
|
+
|
|
110
|
+
Make sure the following is added to your hosts file, if you are running a local keycloak instance. Internally the docker
|
|
111
|
+
containers cannot connect to the localhost:8080 port, so a hook is needed in terms of host rewrite.
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
echo "127.0.0.1 authentication\n" | sudo tee -a /etc/hosts
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Setup docker
|
|
118
|
+
|
|
119
|
+
> TODO describe me
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const vue = require('eslint-plugin-vue');
|
|
2
|
+
const baseConfig = require('../../../eslint.config.js');
|
|
3
|
+
|
|
4
|
+
module.exports = [
|
|
5
|
+
...baseConfig,
|
|
6
|
+
...vue.configs['flat/recommended'],
|
|
7
|
+
{
|
|
8
|
+
files: ['**/*.vue'],
|
|
9
|
+
languageOptions: {
|
|
10
|
+
parserOptions: {
|
|
11
|
+
parser: require('@typescript-eslint/parser'),
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue'],
|
|
17
|
+
rules: {
|
|
18
|
+
'vue/multi-word-component-names': 'off',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ghentcdh/authentication-vue",
|
|
3
|
+
"version": "0.0.2-0",
|
|
4
|
+
"main": "./index.js",
|
|
5
|
+
"types": "./index.d.ts",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"vue": "^3.5.13",
|
|
8
|
+
"pinia": "^3.0.1",
|
|
9
|
+
"keycloak-js": "^26.1.2"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./index.mjs",
|
|
14
|
+
"require": "./index.js",
|
|
15
|
+
"types": "./index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/GhentCDH/ghentcdh-monorepo.git",
|
|
21
|
+
"directory": "libs/authentication/vue"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "authentication-vue",
|
|
3
|
+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "libs/authentication/vue/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"tags": [
|
|
7
|
+
"publish",
|
|
8
|
+
"scope:api",
|
|
9
|
+
"scope:feature"
|
|
10
|
+
],
|
|
11
|
+
"// targets": "to see all targets run: nx show project authentication-vue --web",
|
|
12
|
+
"targets": {}
|
|
13
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { defineStore } from 'pinia';
|
|
2
|
+
import { ref, shallowRef, watch } from 'vue';
|
|
3
|
+
|
|
4
|
+
import { KeycloakAdapter } from './keycloak.adapter';
|
|
5
|
+
|
|
6
|
+
const AUTH_STORE_NAME = 'GHENT_CDH_AUTH_STORE';
|
|
7
|
+
|
|
8
|
+
export const useAuthenticationStore = defineStore(AUTH_STORE_NAME, () => {
|
|
9
|
+
const isAuthenticated = shallowRef(false);
|
|
10
|
+
|
|
11
|
+
const keycloackAdapter = ref<KeycloakAdapter>();
|
|
12
|
+
|
|
13
|
+
// create a promise initeDone
|
|
14
|
+
const initDone = ref(false);
|
|
15
|
+
|
|
16
|
+
KeycloakAdapter.init().then((adapter) => {
|
|
17
|
+
isAuthenticated.value = adapter.isAuthenticated;
|
|
18
|
+
keycloackAdapter.value = adapter;
|
|
19
|
+
initDone.value = true;
|
|
20
|
+
return adapter;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const logout = () => {
|
|
24
|
+
console.warn('logout');
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
token: () => keycloackAdapter.value?.token,
|
|
29
|
+
user: () => keycloackAdapter.value?.userInfo,
|
|
30
|
+
isAuthenticated: () => keycloackAdapter.value?.isAuthenticated,
|
|
31
|
+
logout,
|
|
32
|
+
updateToken: async () => {
|
|
33
|
+
if (!initDone.value) {
|
|
34
|
+
await new Promise<void>((resolve) => {
|
|
35
|
+
const unwatch = watch(initDone, (newValue) => {
|
|
36
|
+
if (newValue) {
|
|
37
|
+
unwatch();
|
|
38
|
+
resolve();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return keycloackAdapter.value?.updateToken();
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import Keycloak from 'keycloak-js';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export class KeycloakAdapter extends Keycloak {
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
private constructor() {
|
|
8
|
+
const {VITE_KEYCLOAK_REALM, VITE_KEYCLOAK_HOST, VITE_KEYCLOAK_CLIENT_ID} = import.meta.env;
|
|
9
|
+
|
|
10
|
+
super({
|
|
11
|
+
url: VITE_KEYCLOAK_HOST,
|
|
12
|
+
realm: VITE_KEYCLOAK_REALM,
|
|
13
|
+
clientId: VITE_KEYCLOAK_CLIENT_ID
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private async initialize() {
|
|
19
|
+
try {
|
|
20
|
+
const authenticated = await this.init(
|
|
21
|
+
{
|
|
22
|
+
onLoad: 'login-required'
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
if (authenticated) {
|
|
26
|
+
console.log('User is authenticated');
|
|
27
|
+
}
|
|
28
|
+
console.log('User is not authenticated');
|
|
29
|
+
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('Failed to initialize adapter:', error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
static async init(): Promise<KeycloakAdapter> {
|
|
37
|
+
const instance = new KeycloakAdapter();
|
|
38
|
+
|
|
39
|
+
await instance.initialize();
|
|
40
|
+
return instance;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
get userInfo() {
|
|
45
|
+
return this.idTokenParsed
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
updateToken() {
|
|
49
|
+
return this.updateToken(30)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get isAuthenticated() {
|
|
53
|
+
return this.authenticated ?? false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { defineStore } from 'pinia';
|
|
2
|
+
|
|
3
|
+
import { useAuthenticationStore } from './authentication.store';
|
|
4
|
+
|
|
5
|
+
const AUTH_STORE_NAME = 'GHENT_CDH_HTTP_REQUEST';
|
|
6
|
+
|
|
7
|
+
// TODO add white list of request
|
|
8
|
+
type RequestOptions = {
|
|
9
|
+
skipAuth?: boolean;
|
|
10
|
+
queryParams?: Record<string, any>;
|
|
11
|
+
contentType?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type Error = {
|
|
15
|
+
status: number;
|
|
16
|
+
content: any;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const useHttpStore = defineStore(AUTH_STORE_NAME, () => {
|
|
20
|
+
const authStore = useAuthenticationStore();
|
|
21
|
+
|
|
22
|
+
const makeRequest = async (
|
|
23
|
+
url: string,
|
|
24
|
+
requestInit: RequestInit,
|
|
25
|
+
options: RequestOptions = { contentType: 'application/json' },
|
|
26
|
+
) => {
|
|
27
|
+
const headers: Record<string, string> = {
|
|
28
|
+
accept: 'application/json',
|
|
29
|
+
...(requestInit.headers ?? {}),
|
|
30
|
+
} as Record<string, string>;
|
|
31
|
+
|
|
32
|
+
if (options.contentType) {
|
|
33
|
+
headers['Content-Type'] = options.contentType;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!options?.skipAuth) {
|
|
37
|
+
await authStore.updateToken();
|
|
38
|
+
headers['Authorization'] = `Bearer ${authStore.token()}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const _url = new URL(url, window.location.href);
|
|
42
|
+
|
|
43
|
+
if (options?.queryParams) {
|
|
44
|
+
for (const [key, value] of Object.entries(options.queryParams)) {
|
|
45
|
+
_url.searchParams.set(key, value);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const response = await fetch(_url.toString(), {
|
|
50
|
+
...requestInit,
|
|
51
|
+
headers,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
if (!options?.skipAuth) {
|
|
56
|
+
// TODO if response return 400 then redirect to login page
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return Promise.reject({
|
|
60
|
+
content: response.body,
|
|
61
|
+
status: response.status,
|
|
62
|
+
} as any);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return response.json();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
get: <T>(url: string, options?: RequestOptions): Promise<T> =>
|
|
70
|
+
makeRequest(url, { method: 'GET' }, options),
|
|
71
|
+
postFile: <T>(
|
|
72
|
+
url: string,
|
|
73
|
+
file: File,
|
|
74
|
+
data: any = {},
|
|
75
|
+
options?: RequestOptions,
|
|
76
|
+
): Promise<T> => {
|
|
77
|
+
const formData = new FormData();
|
|
78
|
+
|
|
79
|
+
for (const name in data) {
|
|
80
|
+
formData.append(name, data[name]);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
formData.append('file', file);
|
|
84
|
+
|
|
85
|
+
return makeRequest(
|
|
86
|
+
url,
|
|
87
|
+
{
|
|
88
|
+
method: 'POST',
|
|
89
|
+
body: formData,
|
|
90
|
+
},
|
|
91
|
+
{ ...options, contentType: undefined },
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
post: <T>(url: string, data: any, options?: RequestOptions): Promise<T> =>
|
|
95
|
+
makeRequest(
|
|
96
|
+
url,
|
|
97
|
+
{
|
|
98
|
+
method: 'POST',
|
|
99
|
+
body: JSON.stringify(data),
|
|
100
|
+
},
|
|
101
|
+
options,
|
|
102
|
+
),
|
|
103
|
+
patch: <T>(url: string, data: any, options?: RequestOptions): Promise<T> =>
|
|
104
|
+
makeRequest(
|
|
105
|
+
url,
|
|
106
|
+
{
|
|
107
|
+
method: 'PATCH',
|
|
108
|
+
body: JSON.stringify(data),
|
|
109
|
+
},
|
|
110
|
+
options,
|
|
111
|
+
),
|
|
112
|
+
delete: <T>(
|
|
113
|
+
url: string,
|
|
114
|
+
data?: any,
|
|
115
|
+
options?: RequestOptions,
|
|
116
|
+
): Promise<T> =>
|
|
117
|
+
makeRequest(
|
|
118
|
+
url,
|
|
119
|
+
{
|
|
120
|
+
method: 'DELETE',
|
|
121
|
+
body: JSON.stringify(data),
|
|
122
|
+
},
|
|
123
|
+
options,
|
|
124
|
+
),
|
|
125
|
+
};
|
|
126
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"esModuleInterop": false,
|
|
5
|
+
"allowSyntheticDefaultImports": true,
|
|
6
|
+
"strict": true,
|
|
7
|
+
"jsx": "preserve",
|
|
8
|
+
"jsxImportSource": "vue",
|
|
9
|
+
"moduleResolution": "node",
|
|
10
|
+
"resolveJsonModule": true
|
|
11
|
+
},
|
|
12
|
+
"files": [],
|
|
13
|
+
"include": [],
|
|
14
|
+
"references": [
|
|
15
|
+
{
|
|
16
|
+
"path": "./tsconfig.lib.json"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "./tsconfig.spec.json"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"extends": "../../../tsconfig.base.json"
|
|
23
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../dist/out-tsc",
|
|
5
|
+
"types": ["vite/client"]
|
|
6
|
+
},
|
|
7
|
+
"exclude": [
|
|
8
|
+
"src/**/__tests__/*",
|
|
9
|
+
"src/**/*.spec.vue",
|
|
10
|
+
"src/**/*.test.vue",
|
|
11
|
+
"vite.config.ts",
|
|
12
|
+
"vite.config.mts",
|
|
13
|
+
"vitest.config.ts",
|
|
14
|
+
"vitest.config.mts",
|
|
15
|
+
"src/**/*.test.ts",
|
|
16
|
+
"src/**/*.spec.ts",
|
|
17
|
+
"src/**/*.test.tsx",
|
|
18
|
+
"src/**/*.spec.tsx",
|
|
19
|
+
"src/**/*.test.js",
|
|
20
|
+
"src/**/*.spec.js",
|
|
21
|
+
"src/**/*.test.jsx",
|
|
22
|
+
"src/**/*.spec.jsx"
|
|
23
|
+
],
|
|
24
|
+
"include": [
|
|
25
|
+
"src/**/*.js",
|
|
26
|
+
"src/**/*.jsx",
|
|
27
|
+
"src/**/*.ts",
|
|
28
|
+
"src/**/*.tsx",
|
|
29
|
+
"src/**/*.vue"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../dist/out-tsc",
|
|
5
|
+
"types": [
|
|
6
|
+
"vitest/globals",
|
|
7
|
+
"vitest/importMeta",
|
|
8
|
+
"vite/client",
|
|
9
|
+
"node",
|
|
10
|
+
"vitest"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"vite.config.ts",
|
|
15
|
+
"vite.config.mts",
|
|
16
|
+
"vitest.config.ts",
|
|
17
|
+
"vitest.config.mts",
|
|
18
|
+
"src/**/*.test.ts",
|
|
19
|
+
"src/**/*.spec.ts",
|
|
20
|
+
"src/**/*.test.tsx",
|
|
21
|
+
"src/**/*.spec.tsx",
|
|
22
|
+
"src/**/*.test.js",
|
|
23
|
+
"src/**/*.spec.js",
|
|
24
|
+
"src/**/*.test.jsx",
|
|
25
|
+
"src/**/*.spec.jsx",
|
|
26
|
+
"src/**/*.d.ts"
|
|
27
|
+
]
|
|
28
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/// <reference types='vitest' />
|
|
2
|
+
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|
3
|
+
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|
4
|
+
import vue from '@vitejs/plugin-vue';
|
|
5
|
+
import { defineConfig } from 'vite';
|
|
6
|
+
import dts from 'vite-plugin-dts';
|
|
7
|
+
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export default defineConfig({
|
|
12
|
+
root: __dirname,
|
|
13
|
+
cacheDir: '../../../node_modules/.vite/libs/authentication/vue',
|
|
14
|
+
plugins: [
|
|
15
|
+
vue(),
|
|
16
|
+
nxViteTsPaths(),
|
|
17
|
+
nxCopyAssetsPlugin(['*.md']),
|
|
18
|
+
dts({
|
|
19
|
+
entryRoot: 'src',
|
|
20
|
+
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
|
21
|
+
}),
|
|
22
|
+
],
|
|
23
|
+
// Uncomment this if you are using workers.
|
|
24
|
+
// worker: {
|
|
25
|
+
// plugins: [ nxViteTsPaths() ],
|
|
26
|
+
// },
|
|
27
|
+
// Configuration for building your library.
|
|
28
|
+
// See: https://vitejs.dev/guide/build.html#library-mode
|
|
29
|
+
build: {
|
|
30
|
+
outDir: '../../../dist/libs/authentication/vue',
|
|
31
|
+
emptyOutDir: true,
|
|
32
|
+
reportCompressedSize: true,
|
|
33
|
+
commonjsOptions: {
|
|
34
|
+
transformMixedEsModules: true,
|
|
35
|
+
},
|
|
36
|
+
lib: {
|
|
37
|
+
// Could also be a dictionary or array of multiple entry points.
|
|
38
|
+
entry: 'src/index.ts',
|
|
39
|
+
name: 'authentication-vue',
|
|
40
|
+
fileName: 'index',
|
|
41
|
+
// Change this to the formats you want to support.
|
|
42
|
+
// Don't forget to update your package.json as well.
|
|
43
|
+
formats: ['es'],
|
|
44
|
+
},
|
|
45
|
+
rollupOptions: {
|
|
46
|
+
// External packages that should not be bundled into your library.
|
|
47
|
+
external: [],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
test: {
|
|
51
|
+
watch: false,
|
|
52
|
+
globals: true,
|
|
53
|
+
environment: 'jsdom',
|
|
54
|
+
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
55
|
+
reporters: ['default'],
|
|
56
|
+
coverage: {
|
|
57
|
+
reportsDirectory: '../../../coverage/libs/authentication/vue',
|
|
58
|
+
provider: 'v8',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
});
|