@hostlink/nuxt-light 0.0.16 → 0.0.18

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.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "light",
3
3
  "configKey": "light",
4
- "version": "0.0.16"
4
+ "version": "0.0.18"
5
5
  }
@@ -1,8 +1,8 @@
1
1
  <script setup>
2
2
  import { useI18n } from 'vue-i18n';
3
- import { useLight, q, getCurrentUser } from '../light';
4
- import { ref, computed, reactive } from 'vue';
5
-
3
+ import { useLight, q, getCurrentUser, m } from '../light';
4
+ import { ref, computed, reactive, provide, watch } from 'vue';
5
+ import packageJson from '../../package.json'
6
6
 
7
7
  const light = useLight();
8
8
  const props = defineProps({
@@ -12,6 +12,8 @@ const props = defineProps({
12
12
  });
13
13
 
14
14
  let app = await q("app", ["menus"]);
15
+ let my = await q("my", ["styles"]);
16
+ const menus = ref(app.menus)
15
17
 
16
18
  const i18n = useI18n();
17
19
  i18n.locale = 'zh-hk';
@@ -47,10 +49,10 @@ const layoutView = computed(() => {
47
49
  })
48
50
 
49
51
  const style = reactive({
50
- headerColor: 'bg-primary',
52
+ color: my.styles?.color || 'bg-primary',
51
53
  theme: 'semi-dark',
52
54
  miniState: false,
53
- dense: false
55
+ dense: my.styles?.dense
54
56
  });
55
57
 
56
58
 
@@ -98,12 +100,34 @@ const errors = computed(() => {
98
100
  return light.getErrors();
99
101
  })
100
102
 
103
+ const reloadMenu = async () => {
104
+ //menus.value = app.menus;
105
+ let app = await q("app", ["menus"]);
106
+ menus.value = app.menus
107
+ }
108
+
109
+ provide('reloadMenu', reloadMenu)
110
+
111
+ watch(() => style.dense, async (value) => {
112
+ await m("updateMyStyle", {
113
+ name: "dense",
114
+ value: value
115
+ });
116
+ })
117
+
118
+ watch(() => style.color, async (value) => {
119
+ await m("updateMyStyle", {
120
+ name: "color",
121
+ value: value
122
+ });
123
+ })
124
+
101
125
  </script>
102
126
 
103
127
 
104
128
  <template>
105
129
  <q-layout :view="layoutView">
106
- <q-header bordered class="text-white" :class="style.headerColor">
130
+ <q-header bordered class="text-white" :class="style.color">
107
131
  <q-toolbar>
108
132
  <q-btn dense flat round icon="menu" class="q-mr-sm" @click="toggleLeftDrawer" />
109
133
 
@@ -138,20 +162,27 @@ const errors = computed(() => {
138
162
 
139
163
 
140
164
  <q-btn flat round dense icon="sym_o_person" class="q-mr-sm">
141
- <q-menu max-width="200px">
165
+ <q-menu max-width="250px">
142
166
  <q-list>
143
167
  <q-item v-close-popup to="/User/profile">
144
168
  <q-item-section avatar>
145
169
  <q-icon name="sym_o_person" />
146
170
  </q-item-section>
147
- <q-item-section>Profile</q-item-section>
171
+ <q-item-section>{{ $t('Profile') }}</q-item-section>
172
+ </q-item>
173
+
174
+ <q-item v-close-popup to="/User/setting">
175
+ <q-item-section avatar>
176
+ <q-icon name="sym_o_settings" />
177
+ </q-item-section>
178
+ <q-item-section>{{ $t('Setting') }}</q-item-section>
148
179
  </q-item>
149
180
 
150
181
  <q-item v-close-popup v-if="showViewAs" to="/System/view_as">
151
182
  <q-item-section avatar>
152
183
  <q-icon name="sym_o_visibility" />
153
184
  </q-item-section>
154
- <q-item-section>View as</q-item-section>
185
+ <q-item-section>{{ $t('View as') }}</q-item-section>
155
186
  </q-item>
156
187
 
157
188
  <q-separator />
@@ -160,7 +191,7 @@ const errors = computed(() => {
160
191
  <q-item-section avatar>
161
192
  <q-icon name="logout" />
162
193
  </q-item-section>
163
- <q-item-section>Logout</q-item-section>
194
+ <q-item-section>{{ $t('Logout') }}</q-item-section>
164
195
  </q-item>
165
196
  </q-list>
166
197
  </q-menu>
@@ -175,14 +206,14 @@ const errors = computed(() => {
175
206
  @mouseover="isMouseOnDrawer = true">
176
207
  <!-- drawer content -->
177
208
  <q-scroll-area class="fit">
178
- <l-menu v-for="menu in app.menus" :value="menu" v-if="isAdmin" :dense="style.dense" />
209
+ <l-menu v-for="menu in menus" :value="menu" v-if="isAdmin" :dense="style.dense" />
179
210
  </q-scroll-area>
180
211
  </q-drawer>
181
212
 
182
213
  <q-drawer overlay v-model="rightDrawerOpen" side="right" bordered>
183
214
  <!-- drawer content -->
184
215
  <q-scroll-area class="fit">
185
- <l-customizer v-model:headerColor="style.headerColor" v-model:theme="style.theme"
216
+ <l-customizer v-model:headerColor="style.color" v-model:theme="style.theme"
186
217
  v-model:miniState="style.miniState" v-model:dense="style.dense"
187
218
  v-model:menuOverlayHeader="style.menuOverlayHeader" />
188
219
  </q-scroll-area>
@@ -190,15 +221,13 @@ const errors = computed(() => {
190
221
 
191
222
  <q-page-container class="bg-grey-2" style="color:#1f1f1f">
192
223
  <!-- Error message -->
193
-
194
-
195
224
  <q-card v-for="error in errors" flat class="q-ma-md" bordered style="border-color: var(--q-negative)">
196
225
  <q-card-section>
197
226
  <q-btn dense flat round icon="close" class="q-mr-sm" @click="light.removeError(error)"></q-btn>{{
198
227
  error }}
199
228
  </q-card-section>
200
229
  </q-card>
201
- <slot />
230
+ <slot :reload="reloadMenu" />
202
231
  </q-page-container>
203
232
 
204
233
 
@@ -10,6 +10,8 @@ if (props.permission) {
10
10
  if (my.granted) {
11
11
  granted.value = true;
12
12
  }
13
+ } else {
14
+ granted.value = true;
13
15
  }
14
16
 
15
17
  </script>
@@ -11,6 +11,10 @@ const form = ref(null);
11
11
  const props = defineProps({
12
12
  modelValue: {
13
13
  type: Object
14
+ },
15
+ bordered: {
16
+ type: Boolean,
17
+ default: true
14
18
  }
15
19
  });
16
20
 
@@ -63,7 +67,7 @@ const onSubmit = (e) => {
63
67
  </script>
64
68
  <template>
65
69
  <q-form ref="form" @submit="onSubmit">
66
- <l-card>
70
+ <l-card :bordered="bordered">
67
71
  <q-card-section>
68
72
  <slot></slot>
69
73
  </q-card-section>
@@ -14,4 +14,5 @@ import removeObject from "./removeObject";
14
14
  import t from "./t";
15
15
  import updateObject from "./updateObject";
16
16
  import viewAs from "./viewAs";
17
- export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs };
17
+ declare const notify: (message: string, color?: string) => void;
18
+ export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs, notify };
@@ -1,3 +1,4 @@
1
+ import { Notify } from "quasar";
1
2
  import addObject from "./addObject.mjs";
2
3
  import f from "./f.mjs";
3
4
  import getApiUrl from "./getApiUrl.mjs";
@@ -14,4 +15,11 @@ import removeObject from "./removeObject.mjs";
14
15
  import t from "./t.mjs";
15
16
  import updateObject from "./updateObject.mjs";
16
17
  import viewAs from "./viewAs.mjs";
17
- export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs };
18
+ const notify = function(message, color = "green") {
19
+ Notify.create({
20
+ message,
21
+ color,
22
+ position: "top"
23
+ });
24
+ };
25
+ export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs, notify };
@@ -4,4 +4,4 @@ interface Light {
4
4
  removeError: (error: String) => void;
5
5
  }
6
6
  export declare function useLight(): Light;
7
- export { addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs } from "./lib";
7
+ export { notify, addObject, f, getApiUrl, getCurrentUser, getObject, id, list, listData, login, m, mutation, q, removeObject, t, updateObject, viewAs } from "./lib";
@@ -16,6 +16,7 @@ export function useLight() {
16
16
  };
17
17
  }
18
18
  export {
19
+ notify,
19
20
  addObject,
20
21
  f,
21
22
  getApiUrl,
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { reactive, ref, computed } from 'vue';
2
+ import { reactive, ref, computed, inject } from 'vue';
3
3
  import { m, q } from "../../../light";
4
4
  import { useQuasar } from 'quasar';
5
5
 
@@ -82,11 +82,12 @@ const onRemove = (node) => {
82
82
  }
83
83
  }
84
84
 
85
- const splitterModel = ref(50)
85
+ const splitterModel = ref(38)
86
86
 
87
87
  const selectedNode = computed(() => {
88
88
  return tree1.value.getNodeByKey(selected.value);
89
89
  });
90
+ const reloadMenu = inject('reloadMenu')
90
91
 
91
92
  const onSave = () => {
92
93
 
@@ -107,8 +108,10 @@ const onSave = () => {
107
108
  position: 'top',
108
109
  timeout: 1000,
109
110
  });
110
- }
111
111
 
112
+ //
113
+ }
114
+ reloadMenu()
112
115
  });
113
116
  }
114
117
 
@@ -6,7 +6,8 @@ const my = await q("my", ["username", "first_name", "last_name", "email", "phone
6
6
  <template>
7
7
  <l-page title="User profile">
8
8
  <template #header>
9
- <q-btn rounded icon="sym_o_key" to="update-password" outline color="primary" label="Update password"></q-btn>
9
+ <l-btn icon="sym_o_key" to="update-password" label="Update password" />
10
+ <l-btn icon="sym_o_key" to="two-factor-auth" label="Two factor auth" />
10
11
  </template>
11
12
  <l-card>
12
13
  <l-list>
@@ -0,0 +1,60 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { m } from "../../light"
4
+ import { useQuasar } from "quasar";
5
+ const quasar = useQuasar()
6
+ const my2FA = await m("my2FA", [])
7
+ const obj = reactive({});
8
+ const save = async () => {
9
+
10
+ try {
11
+ await m("updateMy2FA", {
12
+ code: obj.code,
13
+ secret: my2FA.secret
14
+ });
15
+
16
+ } catch (e) {
17
+ quasar.notify({
18
+ message: e.message,
19
+ type: "negative",
20
+ position: "top"
21
+ })
22
+
23
+ return
24
+ }
25
+ }
26
+
27
+ </script>
28
+ <template>
29
+ <l-page>
30
+
31
+ <l-card>
32
+ <l-form @save="save">
33
+
34
+ <div>
35
+
36
+ <p>
37
+ Now download the app and scan the qrcode. Input the code to the
38
+ following input and submit
39
+ </p>
40
+ <p>
41
+ For Android user, install
42
+ <el-link type="primary" target="_blank"
43
+ href="https://play.google.com/store/apps/details?id=com.azure.authenticator">Authenticator</el-link>
44
+ </p>
45
+
46
+ <p>
47
+ For iOS user, install
48
+ <el-link type="primary" target="_blank"
49
+ href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458">Authenticator</el-link>
50
+ </p>
51
+ </div>
52
+ <q-img :src="my2FA.image" width="250px" />
53
+ <l-input v-model="obj.code" label="Code"
54
+ hint="Please scan the QR code with your authenticator app, and enter the code" required />
55
+ </l-form>
56
+
57
+ </l-card>
58
+
59
+ </l-page>
60
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+ const app = q("app"["hasBioAuth"]);
5
+ </script>
6
+ <template>
7
+ <l-card :bordered="false">
8
+
9
+
10
+ <q-card-section v-if="!app.hasBioAuth">
11
+ Biometric authentication is not installed, please install web-auth/webauthn-lib on the server.
12
+ </q-card-section>
13
+ </l-card>
14
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+
5
+ const obj = reactive(await q("my", ["username", "email", "first_name", "last_name"]))
6
+ const save = async () => {
7
+ try {
8
+ await m("updateMy", {
9
+ data: {
10
+ email: obj.email,
11
+ first_name: obj.first_name,
12
+ last_name: obj.last_name
13
+
14
+ }
15
+ });
16
+ notify("Your profile has been updated")
17
+
18
+ } catch (e) {
19
+ notify(e.message, "red")
20
+ }
21
+
22
+
23
+
24
+ }
25
+ </script>
26
+ <template>
27
+ <l-form @save="save" :bordered="false">
28
+ <l-input label="Username" v-model="obj.username" readonly></l-input>
29
+ <l-input label="Email" v-model="obj.email" required></l-input>
30
+ <l-input label="First Name" v-model="obj.first_name" required></l-input>
31
+ <l-input label="Last Name" v-model="obj.last_name"></l-input>
32
+
33
+ </l-form>
34
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+ const obj = reactive(await q("my", ["phone", "addr1", "addr2", "addr3"]))
5
+ const save = async () => {
6
+ try {
7
+ await m("updateMy", {
8
+ data: obj
9
+ });
10
+ notify("Your information has been updated")
11
+
12
+ } catch (e) {
13
+ notify(e.message, "red")
14
+ }
15
+ }
16
+ </script>
17
+ <template>
18
+ <l-form @save="save" :bordered="false">
19
+ <l-input label="Phone" v-model="obj.phone"></l-input>
20
+ <l-input label="Address1" v-model="obj.addr1"></l-input>
21
+ <l-input label="Address2" v-model="obj.addr2"></l-input>
22
+ <l-input label="Address3" v-model="obj.addr3"></l-input>
23
+
24
+ </l-form>
25
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup>
2
+ import { reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+
5
+ const obj = reactive({
6
+ old_password: "",
7
+ new_password: "",
8
+ confirm_password: ""
9
+ })
10
+
11
+ const onSave = async () => {
12
+ if (await m("updatePassword", {
13
+ old_password: obj.old_password,
14
+ new_password: obj.new_password,
15
+ })) {
16
+ notify("Your password has been updated")
17
+ } else {
18
+ notify("Old password is incorrect", "red")
19
+ }
20
+ }
21
+
22
+ </script>
23
+ <template>
24
+ <l-form @save="onSave" :bordered="false">
25
+ <l-input label="Old password" v-model="obj.old_password" type="password"
26
+ :rules="[v => !!v || 'Old password is required']" />
27
+ <l-input label="New password" v-model="obj.new_password" type="password"
28
+ :rules="[v => !!v || 'New password is required']" />
29
+ <l-input label="Confirm password" v-model="obj.confirm_password" type="password" :rules="[
30
+ v => !!v || 'Confirm password is required',
31
+ v => v == obj.new_password || 'Confirm password does not match'
32
+ ]" />
33
+ </l-form>
34
+ </template>
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <div>Style</div>
3
+ </template>
@@ -0,0 +1,60 @@
1
+ <script setup>
2
+ import { ref, reactive } from "vue"
3
+ import { q, m, notify } from "../../../light"
4
+
5
+ const my = await q("my", ["twoFactorEnabled"])
6
+ const my2FA = await m("my2FA", [])
7
+ const obj = reactive({});
8
+ const save = async () => {
9
+
10
+ try {
11
+ await m("updateMy2FA", {
12
+ code: obj.code,
13
+ secret: my2FA.secret
14
+ });
15
+ notify("Your 2FA has been updated")
16
+
17
+ } catch (e) {
18
+ notify(e.message, "red")
19
+ }
20
+ }
21
+
22
+ const show = ref(true);
23
+
24
+ if (my.twoFactorEnabled) {
25
+ show.value = false;
26
+ }
27
+
28
+
29
+ </script>
30
+ <template>
31
+ <l-form @save="save" :bordered="false" v-if="show">
32
+ <div>
33
+ <p>
34
+ Now download the app and scan the qrcode. Input the code to the
35
+ following input and submit
36
+ </p>
37
+ <p>
38
+ For Android user, install
39
+ <el-link type="primary" target="_blank"
40
+ href="https://play.google.com/store/apps/details?id=com.azure.authenticator">Authenticator</el-link>
41
+ </p>
42
+
43
+ <p>
44
+ For iOS user, install
45
+ <el-link type="primary" target="_blank"
46
+ href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458">Authenticator</el-link>
47
+ </p>
48
+ </div>
49
+ <q-img :src="my2FA.image" width="250px" />
50
+ <l-input v-model="obj.code" label="Code"
51
+ hint="Please scan the QR code with your authenticator app, and enter the code" required />
52
+ </l-form>
53
+ <div v-else>
54
+ <q-card-section>
55
+ Your 2FA is enabled
56
+ <l-btn @click="show = true" label="Reset Your 2FA" icon="sym_o_refresh" />
57
+ </q-card-section>
58
+
59
+ </div>
60
+ </template>
@@ -0,0 +1,33 @@
1
+ <script setup>
2
+ import { ref } from "vue"
3
+ const tab = ref("general")
4
+ </script>
5
+
6
+ <template>
7
+ <l-page>
8
+ <l-card>
9
+ <q-splitter unit="px" :model-value="120">
10
+ <template #before>
11
+ <q-tabs v-model="tab" vertical >
12
+ <q-route-tab name="general" icon="sym_o_info" :label="$t('General')" to="/User/setting" exact
13
+ replace />
14
+ <q-route-tab name="information" icon="sym_o_info" :label="$t('Information')"
15
+ to="/User/setting/information" exact replace />
16
+ <q-route-tab name="password" icon="sym_o_password" :label="$t('Password')"
17
+ to="/User/setting/password" exact replace />
18
+ <q-route-tab name="style" icon="sym_o_style" :label="$t('Style')" to="/User/setting/style" exact
19
+ replace />
20
+ <q-route-tab name="2fa" icon="sym_o_key" :label="$t('2FA')" to="/User/setting/two-factor-auth" exact replace />
21
+ <q-route-tab name="bio" icon="sym_o_fingerprint" :label="$t('Bio')" to="/User/setting/bio-auth"
22
+ exact replace />
23
+ </q-tabs>
24
+ </template>
25
+
26
+ <template #after>
27
+ <router-view>
28
+ </router-view>
29
+ </template>
30
+ </q-splitter>
31
+ </l-card>
32
+ </l-page>
33
+ </template>
@@ -1,8 +1,20 @@
1
+ <script setup>
2
+ import { inject } from "vue";
3
+
4
+
5
+ const reloadMenu = inject('reloadMenu')
6
+
7
+ const onClick = (parent) => {
8
+ reloadMenu()
9
+
10
+ }
11
+ </script>
1
12
  <template>
2
13
  <q-page padding>
3
14
  <l-card>
4
15
  <q-card-section>
5
- Hello
16
+ Helloas
17
+ <q-btn label="click" @click="onClick($parent)"></q-btn>
6
18
  </q-card-section>
7
19
  </l-card>
8
20
  </q-page>
@@ -1,7 +1,19 @@
1
- declare const _default: {
1
+ declare const _default: ({
2
2
  name: string;
3
3
  path: string;
4
4
  component: typeof index;
5
- }[];
5
+ children?: undefined;
6
+ } | {
7
+ path: string;
8
+ component: typeof User_setting;
9
+ children: {
10
+ name: string;
11
+ path: string;
12
+ component: typeof User_setting_index;
13
+ }[];
14
+ name?: undefined;
15
+ })[];
6
16
  export default _default;
7
17
  declare function index(): Promise<any>;
18
+ declare function User_setting(): Promise<any>;
19
+ declare function User_setting_index(): Promise<any>;
@@ -91,6 +91,46 @@ function User_profile() {
91
91
  /* webpackChunkName: "User-profile" */ './pages/User/profile.vue'
92
92
  )
93
93
  }
94
+ function User_setting() {
95
+ return import(
96
+ /* webpackChunkName: "User-setting" */ './pages/User/setting.vue'
97
+ )
98
+ }
99
+ function User_setting_index() {
100
+ return import(
101
+ /* webpackChunkName: "User-setting-index" */ './pages/User/setting/index.vue'
102
+ )
103
+ }
104
+ function User_setting_2fa() {
105
+ return import(
106
+ /* webpackChunkName: "User-setting-2fa" */ './pages/User/setting/2fa.vue'
107
+ )
108
+ }
109
+ function User_setting_bio_auth() {
110
+ return import(
111
+ /* webpackChunkName: "User-setting-bio-auth" */ './pages/User/setting/bio-auth.vue'
112
+ )
113
+ }
114
+ function User_setting_information() {
115
+ return import(
116
+ /* webpackChunkName: "User-setting-information" */ './pages/User/setting/information.vue'
117
+ )
118
+ }
119
+ function User_setting_password() {
120
+ return import(
121
+ /* webpackChunkName: "User-setting-password" */ './pages/User/setting/password.vue'
122
+ )
123
+ }
124
+ function User_setting_style() {
125
+ return import(
126
+ /* webpackChunkName: "User-setting-style" */ './pages/User/setting/style.vue'
127
+ )
128
+ }
129
+ function User_setting_two_factor_auth() {
130
+ return import(
131
+ /* webpackChunkName: "User-setting-two-factor-auth" */ './pages/User/setting/two-factor-auth.vue'
132
+ )
133
+ }
94
134
  function User_update_password() {
95
135
  return import(
96
136
  /* webpackChunkName: "User-update-password" */ './pages/User/update-password.vue'
@@ -233,6 +273,47 @@ export default [
233
273
  path: '/User/profile',
234
274
  component: User_profile,
235
275
  },
276
+ {
277
+ path: '/User/setting',
278
+ component: User_setting,
279
+ children: [
280
+ {
281
+ name: 'User-setting',
282
+ path: '',
283
+ component: User_setting_index,
284
+ },
285
+ {
286
+ name: 'User-setting-2fa',
287
+ path: '2fa',
288
+ component: User_setting_2fa,
289
+ },
290
+ {
291
+ name: 'User-setting-bio-auth',
292
+ path: 'bio-auth',
293
+ component: User_setting_bio_auth,
294
+ },
295
+ {
296
+ name: 'User-setting-information',
297
+ path: 'information',
298
+ component: User_setting_information,
299
+ },
300
+ {
301
+ name: 'User-setting-password',
302
+ path: 'password',
303
+ component: User_setting_password,
304
+ },
305
+ {
306
+ name: 'User-setting-style',
307
+ path: 'style',
308
+ component: User_setting_style,
309
+ },
310
+ {
311
+ name: 'User-setting-two-factor-auth',
312
+ path: 'two-factor-auth',
313
+ component: User_setting_two_factor_auth,
314
+ },
315
+ ],
316
+ },
236
317
  {
237
318
  name: 'User-update-password',
238
319
  path: '/User/update-password',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": "@hostlink/nuxt-light",
6
6
  "license": "MIT",